Skip to content

Commit

Permalink
Merge pull request #377 from UC-Davis-molecular-computing/changing-cs…
Browse files Browse the repository at this point in the history
…s-classes-on-strands-and-strand-parts-outside-of-React/Redux

Changing css classes on strands and strand parts outside of react/redux
  • Loading branch information
dave-doty authored Jul 15, 2020
2 parents 4cb7998 + 52a03ca commit 9b3babb
Show file tree
Hide file tree
Showing 41 changed files with 911 additions and 653 deletions.
43 changes: 43 additions & 0 deletions lib/src/actions/actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,26 @@ abstract class ConvertCrossoverToLoopout
static Serializer<ConvertCrossoverToLoopout> get serializer => _$convertCrossoverToLoopoutSerializer;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// dumb action issued by domain since it doesn't know current edit mode;
// mode_sensitive_actions_filter_middleware figures out which one to turn it into

//NickOrInsertionOrDeletionAdd
abstract class NickOrInsertionOrDeletionAdd
with BuiltJsonSerializable
implements Action, Built<NickOrInsertionOrDeletionAdd, NickOrInsertionOrDeletionAddBuilder> {
Domain get domain;

int get offset;

/************************ begin BuiltValue boilerplate ************************/
factory NickOrInsertionOrDeletionAdd({Domain domain, int offset}) = _$NickOrInsertionOrDeletionAdd._;

NickOrInsertionOrDeletionAdd._();

static Serializer<NickOrInsertionOrDeletionAdd> get serializer => _$nickOrInsertionOrDeletionAddSerializer;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// nick/join

Expand Down Expand Up @@ -1377,6 +1397,29 @@ abstract class Ligate with BuiltJsonSerializable, UndoableAction implements Buil
static Serializer<Ligate> get serializer => _$ligateSerializer;
}

abstract class DNAEndClicked
with BuiltJsonSerializable
implements Action, Built<DNAEndClicked, DNAEndClickedBuilder> {
DNAEnd get dna_end;

PotentialCrossover get potential_crossover;

bool get is_first;

bool get is_last;

/************************ begin BuiltValue boilerplate ************************/
factory DNAEndClicked(
{DNAEnd dna_end,
PotentialCrossover potential_crossover,
bool is_first,
bool is_last}) = _$DNAEndClicked._;

DNAEndClicked._();

static Serializer<DNAEndClicked> get serializer => _$dNAEndClickedSerializer;
}

abstract class JoinStrandsByCrossover
with BuiltJsonSerializable, UndoableAction
implements Built<JoinStrandsByCrossover, JoinStrandsByCrossoverBuilder> {
Expand Down
1 change: 0 additions & 1 deletion lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import 'reducers/dna_ends_move_reducer.dart';
import 'reducers/potential_crossover_reducer.dart';
import 'state/app_state.dart';
import 'state/selection_box.dart';
import 'state/undo_redo.dart';
import 'reducers/selection_reducer.dart';
import 'view/design.dart';
import 'view/view.dart';
Expand Down
24 changes: 23 additions & 1 deletion lib/src/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const String DNA_BASE_WILDCARD = '?';
const default_min_offset = 0;
const default_max_offset = 64;

//const scadnano_css_stylesheet_name_no_ext = r'scadnano-styles';
const scadnano_css_stylesheet_name_no_ext = r'scadnano-styles';
const scadnano_css_stylesheet_name = r'scadnano-styles.css';

const NUM_DIGITS_PRECISION_POSITION_DISPLAYED = 2;

Expand Down Expand Up @@ -299,3 +300,24 @@ const num ZOOM_THRESHOLD = 1;
// Backend
const export_url = 'https://dna.hamilton.ie/scadnano-backend/scadnano_to_cadnano_v2';
const import_url = 'https://dna.hamilton.ie/scadnano-backend/cadnano_v2_to_scadnano';


/////////////////////////////////////////////////////////////
// CSS selector classnames

const css_selector_strand = 'strand';
const css_selector_scaffold = 'scaffold';
const css_selector_staple = 'staple';
const css_selector_domain = 'domain-line';
const css_selector_crossover = 'crossover-curve';
const css_selector_loopout = 'loopout-curve';
const css_selector_end_5p_strand = 'five-prime-end-first-substrand';
const css_selector_end_3p_strand = 'three-prime-end-last-substrand';
const css_selector_end_5p_domain = 'five-prime-end';
const css_selector_end_3p_domain = 'three-prime-end';

const css_selector_insertion = 'insertion-curve';
const css_selector_deletion = 'deletion-cross';
const css_selector_selected = 'selected';


4 changes: 4 additions & 0 deletions lib/src/middleware/all_middleware.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:scadnano/src/middleware/export_cadnano_or_codenano_file.dart';

import 'assign_dna.dart';
import 'check_mirror_strands_legal.dart';
import 'edit_select_mode_change.dart';
import 'example_dna_design_selected.dart';
import 'export_dna_sequences.dart';
import 'dna_ends_move_start.dart';
Expand All @@ -12,6 +13,7 @@ import 'helix_hide_all.dart';
import 'helix_offsets_change.dart';
import 'insertion_deletion_pairing.dart';
import 'load_file.dart';
import 'mode_sensitive_actions_filter.dart';
import 'reselect_moved_dna_ends.dart';
import 'reselect_moved_strands.dart';
import 'save_file.dart';
Expand All @@ -25,6 +27,7 @@ import 'invalidate_png.dart';
import '../state/app_state.dart';

final all_middleware = List<Middleware<AppState>>.unmodifiable([
mode_sensitive_actions_filter_middleware,
local_storage_middleware,
export_svg_middleware,
save_file_middleware,
Expand All @@ -47,4 +50,5 @@ final all_middleware = List<Middleware<AppState>>.unmodifiable([
adjust_grid_position_middleware,
invalidate_png_middleware,
check_mirror_strands_legal_middleware,
edit_select_mode_change_middleware,
]);
135 changes: 135 additions & 0 deletions lib/src/middleware/edit_select_mode_change.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import 'dart:html';

import 'package:built_collection/src/set.dart';
import 'package:redux/redux.dart';

import 'package:scadnano/src/state/app_state.dart';
import 'package:scadnano/src/state/dna_design.dart';
import 'package:scadnano/src/state/edit_mode.dart';
import 'package:scadnano/src/state/select_mode.dart';

import '../actions/actions.dart' as actions;
import '../util.dart' as util;

const selectable_css_style_non_domain_end = {
'filter': 'url("#shadow")',
};

const selectable_css_style_domain_end = {
'filter': 'url("#shadow")',
'stroke': 'black',
'stroke-width': '0.5px',
'visibility': 'visible',
};

edit_select_mode_change_middleware(Store<AppState> store, action, NextDispatcher next) {
next(action);
if (action is actions.EditModesSet ||
action is actions.EditModeToggle ||
action is actions.SelectModesSet ||
action is actions.SelectModeToggle ||
action is actions.SetAppUIStateStorable) {
var select_modes = store.state.ui_state.select_mode_state.modes;
var edit_modes = store.state.ui_state.edit_modes;
var design = store.state.dna_design;
bool is_origami = store.state.dna_design.is_origami;
set_selectables_css_style_rules(design, edit_modes, select_modes, is_origami);
}
}

set_selectables_css_style_rules(DNADesign design, BuiltSet<EditModeChoice> edit_modes,
BuiltSet<SelectModeChoice> select_modes, bool is_origami) {
bool edit_mode_is_select = edit_modes.contains(EditModeChoice.select);
bool scaffold_parts_selectable =
edit_mode_is_select && (design.is_origami && select_modes.contains(SelectModeChoice.scaffold));
bool staple_parts_selectable =
edit_mode_is_select && (design.is_origami && select_modes.contains(SelectModeChoice.staple));
bool all_parts_selectable =
edit_mode_is_select && (!design.is_origami || (scaffold_parts_selectable && staple_parts_selectable));

for (var select_mode_choice in [SelectModeChoice.strand] + SelectModeChoice.strand_parts.toList()) {
set_strand_part_selectable_css_style_rules(select_modes,
all_parts_selectable: all_parts_selectable,
staple_parts_selectable: staple_parts_selectable,
scaffold_parts_selectable: scaffold_parts_selectable,
select_mode_choice: select_mode_choice,
is_origami: is_origami);
}
}

set_strand_part_selectable_css_style_rules(BuiltSet<SelectModeChoice> select_modes,
{bool all_parts_selectable,
bool staple_parts_selectable,
bool scaffold_parts_selectable,
SelectModeChoice select_mode_choice,
bool is_origami}) {
bool select_mode_contains_part = select_modes.contains(select_mode_choice);
var selectable_css_style_this_choice = SelectModeChoice.ends.contains(select_mode_choice)
? selectable_css_style_domain_end
: selectable_css_style_non_domain_end;

var all_strand_selector = '.${select_mode_choice.css_selector()}:hover';
var staple_only_selector =
':not(.${SelectModeChoice.scaffold.css_selector()}).${select_mode_choice.css_selector()}:hover';
var scaffold_selector =
'.${SelectModeChoice.scaffold.css_selector()}.${select_mode_choice.css_selector()}:hover';

if (!select_mode_contains_part) {
css_class_remove_style(all_strand_selector);
css_class_remove_style(staple_only_selector);
css_class_remove_style(scaffold_selector);
} else if (!is_origami || all_parts_selectable) {
css_class_set_style(all_strand_selector, selectable_css_style_this_choice);
css_class_set_style(staple_only_selector, selectable_css_style_this_choice);
css_class_set_style(scaffold_selector, selectable_css_style_this_choice);
} else if (scaffold_parts_selectable) {
css_class_remove_style(all_strand_selector);
css_class_remove_style(staple_only_selector);
css_class_set_style(scaffold_selector, selectable_css_style_this_choice);
} else if (staple_parts_selectable) {
css_class_remove_style(all_strand_selector);
css_class_set_style(staple_only_selector, selectable_css_style_this_choice);
css_class_remove_style(scaffold_selector);
} else {
css_class_remove_style(all_strand_selector);
css_class_remove_style(staple_only_selector);
css_class_remove_style(scaffold_selector);
}
}

css_class_set_style(String selector, Map<String, String> new_style_map) {
var stylesheet = util.get_scadnano_stylesheet();
var rule = style_rule_with_selector(stylesheet, selector);
if (rule == null) {
int new_index = stylesheet.insertRule(selector + ' {}');
rule = stylesheet.cssRules[new_index];
}
var style = rule.style;
for (var style_key in new_style_map.keys) {
var style_val = new_style_map[style_key];
style.setProperty(style_key, style_val);
}
}

css_class_remove_style(String selector) {
var stylesheet = util.get_scadnano_stylesheet();
int idx = style_rule_index_with_selector(stylesheet, selector);
if (idx != null) {
stylesheet.removeRule(idx);
}
}

CssStyleRule style_rule_with_selector(CssStyleSheet stylesheet, String selector) {
int idx = style_rule_index_with_selector(stylesheet, selector);
return idx == null ? null : stylesheet.cssRules[idx];
}

int style_rule_index_with_selector(CssStyleSheet stylesheet, String selector) {
for (int i = 0; i < stylesheet.cssRules.length; i++) {
CssRule rule = stylesheet.cssRules[i];
if (rule is CssStyleRule && rule.selectorText == selector) {
return i;
}
}
return null;
}
9 changes: 1 addition & 8 deletions lib/src/middleware/local_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,7 @@ save(AppState state, Storable storable) {
if (value_string != null) window.localStorage[storable_key] = value_string;
}

String side_pane_width() {
String key = _LOCAL_STORAGE_PREFIX + 'side_pane_width';
if (window.localStorage.containsKey(key)) {
return window.localStorage[key];
} else {
return null;
}
}
String side_pane_width() => window.localStorage[_LOCAL_STORAGE_PREFIX + 'side_pane_width'];

restore(Storable storable) {
try {
Expand Down
Loading

0 comments on commit 9b3babb

Please sign in to comment.