Skip to content

Commit

Permalink
addresses issue #36 but does not fix it totally; helix idxs can now b…
Browse files Browse the repository at this point in the history
…e changed one at a time, and not with a recalculation of view order until #407 is addressed
  • Loading branch information
dave-doty committed Jul 22, 2020
1 parent 38d51b0 commit 2eab946
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 27 deletions.
21 changes: 20 additions & 1 deletion lib/src/actions/actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ abstract class BatchAction

/************************ begin BuiltValue boilerplate ************************/
factory BatchAction(Iterable<UndoableAction> actions) =>
BatchAction.from((b) => b..actions.replace(BuiltList<UndoableAction>(actions)));
BatchAction.from((b) => b..actions.replace(actions));

factory BatchAction.from([void Function(BatchActionBuilder) updates]) = _$BatchAction;

Expand Down Expand Up @@ -1225,6 +1225,25 @@ abstract class HelixMajorTickPeriodicDistancesChangeAll
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Helix change min/max offsets

abstract class HelixIdxsChange
with BuiltJsonSerializable, UndoableAction
implements Built<HelixIdxsChange, HelixIdxsChangeBuilder> {
BuiltMap<int, int> get idx_replacements;

/************************ begin BuiltValue boilerplate ************************/
factory HelixIdxsChange({Map<int,int> idx_replacements}) =>
HelixIdxsChange.from((b) => b..idx_replacements.replace(idx_replacements));

factory HelixIdxsChange.from([void Function(HelixIdxsChangeBuilder) updates]) = _$HelixIdxsChange;

HelixIdxsChange._();

static Serializer<HelixIdxsChange> get serializer => _$helixIdxsChangeSerializer;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Helix change min/max offsets

abstract class HelixOffsetChange
with BuiltJsonSerializable, UndoableAction
implements HelixIndividualAction, Built<HelixOffsetChange, HelixOffsetChangeBuilder> {
Expand Down
4 changes: 2 additions & 2 deletions lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ import 'dna_sequence_constants.dart';
// global variable for whole program
App app = App();

const USE_REDUX_DEV_TOOLS = false;
//const USE_REDUX_DEV_TOOLS = true;
//const USE_REDUX_DEV_TOOLS = false;
const USE_REDUX_DEV_TOOLS = true;

const RUN_TEST_CODE_INSTEAD_OF_APP = false;
//const RUN_TEST_CODE_INSTEAD_OF_APP = true;
Expand Down
2 changes: 2 additions & 0 deletions lib/src/middleware/all_middleware.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'export_dna_sequences.dart';
import 'dna_ends_move_start.dart';
import 'helix_grid_change.dart';
import 'helix_hide_all.dart';
import 'helix_idxs_change.dart';
import 'helix_offsets_change.dart';
import 'insertion_deletion_pairing.dart';
import 'load_file.dart';
Expand Down Expand Up @@ -38,6 +39,7 @@ final all_middleware = List<Middleware<AppState>>.unmodifiable([
strand_create_middleware,
helix_remove_middleware,
helix_change_offsets_middleware,
helix_idxs_change_middleware,
helix_grid_offsets_middleware,
helix_hide_all_middleware,
helix_positions_set_based_on_crossovers_middleware,
Expand Down
24 changes: 24 additions & 0 deletions lib/src/middleware/helix_idxs_change.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'dart:html';

import 'package:redux/redux.dart';
import 'package:scadnano/src/state/design.dart';

import '../actions/actions.dart' as actions;
import '../state/app_state.dart';

/// Check whether user wants to remove helix that has strands on it.
helix_idxs_change_middleware(Store<AppState> store, dynamic action, NextDispatcher next) {
if (action is actions.HelixIdxsChange) {
Set<int> existing_idxs = store.state.design.helices.keys.toSet();
Set<int> old_idxs = action.idx_replacements.keys.toSet();
Set<int> remaining_idxs = existing_idxs.difference(old_idxs);
for (int new_idx in action.idx_replacements.values) {
if (remaining_idxs.contains(new_idx)) {
var msg = 'Index ${new_idx} is already taken.';
window.alert(msg);
return;
}
}
}
next(action);
}
4 changes: 4 additions & 0 deletions lib/src/reducers/design_reducer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,12 @@ Design design_error_message_set_reducer(Design design, actions.ErrorMessageSet a
// whole: operate on the whole DNADesign
// global: need the whole AppState
GlobalReducer<Design, AppState> design_whole_global_reducer = combineGlobalReducers([
TypedGlobalReducer<Design, AppState, actions.HelixIdxsChange>(helix_idx_change_reducer),
TypedGlobalReducer<Design, AppState, actions.HelixAdd>(helix_add_design_reducer),
TypedGlobalReducer<Design, AppState, actions.HelixRemove>(helix_remove_design_global_reducer),
TypedGlobalReducer<Design, AppState, actions.HelixRemoveAllSelected>(
helix_remove_all_selected_design_global_reducer),
]);



46 changes: 46 additions & 0 deletions lib/src/reducers/helices_reducer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,52 @@ Reducer<Helix> _helix_individual_reducers = combineReducers([
TypedReducer<Helix, actions.HelixRollSet>(helix_roll_set_reducer),
]);

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// change idx

Design helix_idx_change_reducer(Design design, AppState state, actions.HelixIdxsChange action) {
var helices = design.helices.toMap();
var strands = design.strands.toList();

// change helices
for (int old_idx in action.idx_replacements.keys) {
int new_idx = action.idx_replacements[old_idx];
var helix = helices[old_idx].rebuild((b) => b..idx = new_idx);
helices.remove(old_idx);
helices[new_idx] = helix;
}


// change helix idx refs on domains
for (int s = 0; s < strands.length; s++) {
var strand = strands[s];
var substrands = strand.substrands.toList();
bool changed_strand = false;
for (int d = 0; d < strand.substrands.length; d++) {
var substrand = strand.substrands[d];
if (substrand is Domain) {
Domain domain = substrand as Domain;
int new_idx = action.idx_replacements[domain.helix];
if (new_idx != null) {
domain = domain.rebuild((b) => b..helix = new_idx);
substrands[d] = domain;
changed_strand = true;
}
}
}
if (changed_strand) {
strands[s] = strand.rebuild((b) => b..substrands.replace(substrands));
}
}

//TODO: recalculate view order; first figure out if it was non-default by looking at Helix.view_order


helices = util.helices_assign_svg(design.geometry, state.ui_state.invert_yz, helices, design.grid);
design = design.rebuild((b) => b..helices.replace(helices)..strands.replace(strands));
return design;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// change min/max offsets

Expand Down
1 change: 1 addition & 0 deletions lib/src/serializers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ part 'serializers.g.dart';
HelixRemoveAllSelected,
HelixOffsetChange,
HelixOffsetChangeAll,
HelixIdxsChange,
HelixMajorTickDistanceChange,
HelixMajorTickDistanceChangeAll,
HelixMajorTicksChange,
Expand Down
7 changes: 0 additions & 7 deletions lib/src/state/design.dart
Original file line number Diff line number Diff line change
Expand Up @@ -617,13 +617,6 @@ abstract class Design with UnusedFields implements Built<Design, DesignBuilder>,
throw IllegalDNADesignError(
'grid is not none, but Helix $idx has position = ${helix_json[constants.position_key]}');
}
// don't want to do this while codenano has different version numbers
// if (position_x_z_should_swap && grid_is_none) {
// // prior to version 0.10.0, x and z had the opposite role
// num swap = helix_builder.position_.x;
// helix_builder.position_.x = helix_builder.position_.z;
// helix_builder.position_.z = swap;
// }
helix_builders.add(helix_builder);
idx++;
}
Expand Down
24 changes: 21 additions & 3 deletions lib/src/view/helix_context_menu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import '../util.dart' as util;

List<ContextMenuItem> context_menu_helix(Helix helix, bool helix_change_apply_to_all) {
Future<void> dialog_helix_adjust_length() async {
int helix_idx = helix.idx;

var dialog = Dialog(title: 'adjust helix length', items: [
DialogNumber(label: 'minimum', value: helix.min_offset),
DialogNumber(label: 'maximum', value: helix.max_offset),
Expand All @@ -38,10 +36,22 @@ List<ContextMenuItem> context_menu_helix(Helix helix, bool helix_change_apply_to
app.dispatch(actions.HelixOffsetChangeAll(min_offset: min_offset, max_offset: max_offset));
} else {
app.dispatch(
actions.HelixOffsetChange(helix_idx: helix_idx, min_offset: min_offset, max_offset: max_offset));
actions.HelixOffsetChange(helix_idx: helix.idx, min_offset: min_offset, max_offset: max_offset));
}
}

Future<void> dialog_helix_adjust_idx() async {
var dialog = Dialog(title: 'adjust helix index', items: [
DialogNumber(label: 'new index', value: helix.idx),
]);
List<DialogItem> results = await util.dialog(dialog);
if (results == null) return;

int new_idx = (results[0] as DialogNumber).value;

app.dispatch(actions.HelixIdxsChange(idx_replacements: {helix.idx: new_idx}));
}

Future<void> dialog_helix_adjust_roll() async {
int helix_idx = helix.idx;

Expand Down Expand Up @@ -277,6 +287,10 @@ minimum offset ${helix.min_offset} of helix ${helix.min_offset}.''');
app.disable_keyboard_shortcuts_while(dialog_helix_adjust_length);
}

helix_adjust_idx() {
app.disable_keyboard_shortcuts_while(dialog_helix_adjust_idx);
}

helix_adjust_major_tick_marks() {
app.disable_keyboard_shortcuts_while(dialog_helix_adjust_major_tick_marks);
}
Expand Down Expand Up @@ -308,6 +322,10 @@ minimum offset ${helix.min_offset} of helix ${helix.min_offset}.''');
title: 'adjust length',
on_click: helix_adjust_length,
),
ContextMenuItem(
title: 'adjust index',
on_click: helix_adjust_idx,
),
ContextMenuItem(
title: 'adjust tick marks',
on_click: helix_adjust_major_tick_marks,
Expand Down
5 changes: 0 additions & 5 deletions test/reducer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3519,7 +3519,6 @@ main() {
app_state_reducer(state, MouseoverDataUpdate(mouseover_params: [mouseoverParams].toBuiltList()));

Helix helix = two_helices_design.helices[1];
int offset = 12;
Domain domain = two_helices_design.strands[2].domains()[0];

mouseoverParams = MouseoverParams(1, 13, true);
Expand Down Expand Up @@ -3586,10 +3585,6 @@ main() {
state =
app_state_reducer(state, MouseoverDataUpdate(mouseover_params: [mouseoverParams].toBuiltList()));

Helix helix = two_helices_design.helices[1];
int offset = 12;
Domain domain = two_helices_design.strands[2].domains()[0];

state = app_state_reducer(state, MouseoverDataClear());

expect(state.ui_state.mouseover_datas, BuiltList<MouseoverData>());
Expand Down
9 changes: 0 additions & 9 deletions web/scadnano-styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,6 @@ html, body {
font-family: sans-serif;
}

/* https://stackoverflow.com/questions/15904416/placing-a-link-inside-of-a-tooltip */
.parent .tooltip {
display: none;
}

.parent:hover .tooltip {
display: block;
}

/************************************************
** BEGIN layout
************************************************/
Expand Down

0 comments on commit 2eab946

Please sign in to comment.