@@ -4,7 +4,11 @@ import 'package:collection/collection.dart';
44import 'package:redux/redux.dart' ;
55import 'package:built_collection/built_collection.dart' ;
66import 'package:scadnano/src/reducers/groups_reducer.dart' ;
7+ import 'package:scadnano/src/reducers/strands_move_reducer.dart' ;
78import 'package:scadnano/src/state/group.dart' ;
9+ import 'package:scadnano/src/state/strand_creation.dart' ;
10+ import 'package:scadnano/src/state/strands_move.dart' ;
11+ import 'package:scadnano/src/state/substrand.dart' ;
812import '../reducers/util_reducer.dart' ;
913import '../state/app_state.dart' ;
1014
@@ -51,6 +55,13 @@ GlobalReducer<BuiltMap<int, Helix>, AppState> helices_global_reducer = combineGl
5155 TypedGlobalReducer <BuiltMap <int , Helix >, AppState , actions.HelixMaxOffsetSetByDomainsAllSameMax >(
5256 helix_max_offset_set_by_domains_all_same_max_reducer,
5357 ),
58+ TypedGlobalReducer <BuiltMap <int , Helix >, AppState , actions.StrandsMoveAdjustAddress >(
59+ helix_offset_change_all_with_moving_strands_reducer),
60+ TypedGlobalReducer <BuiltMap <int , Helix >, AppState , actions.StrandCreateAdjustOffset >(
61+ helix_offset_change_all_while_creating_strand_reducer),
62+ TypedGlobalReducer <BuiltMap <int , Helix >, AppState , actions.ReplaceStrands >(first_replace_strands_reducer),
63+ TypedGlobalReducer <BuiltMap <int , Helix >, AppState , actions.SelectionsClear >(
64+ reset_helices_offsets_after_selections_clear)
5465]);
5566
5667BuiltMap <int , Helix > helix_individual_reducer (
@@ -186,6 +197,136 @@ Helix _change_offset_one_helix(Helix helix, int min_offset, int max_offset) => h
186197 ..min_offset = min_offset ?? helix.min_offset
187198 ..max_offset = max_offset ?? helix.max_offset);
188199
200+ BuiltMap <int , Helix > helix_offset_change_all_with_moving_strands_reducer (
201+ BuiltMap <int , Helix > helices, AppState state, actions.StrandsMoveAdjustAddress action) {
202+ if (state.ui_state.dynamically_update_helices) {
203+ StrandsMove new_strands_move =
204+ state.ui_state.strands_move.rebuild ((b) => b..current_address.replace (action.address));
205+ Map strand_bounds_details = get_strand_bounds_details (state.design, new_strands_move);
206+ constants.strand_bounds_status status = strand_bounds_details['status' ];
207+
208+ var offsets = strand_bounds_details['offsets' ];
209+ if (status == constants.strand_bounds_status.min_offset_out_of_bounds ||
210+ status == constants.strand_bounds_status.in_bounds_with_min_offset_changes) {
211+ Helix map_func (int idx, Helix helix) => _change_offset_one_helix (helix, offsets[idx], null );
212+ helices = helices.map_values (map_func);
213+ } else if (status == constants.strand_bounds_status.max_offset_out_of_bounds ||
214+ status == constants.strand_bounds_status.in_bounds_with_max_offset_changes) {
215+ Helix map_func (int idx, Helix helix) => _change_offset_one_helix (helix, null , offsets[idx]);
216+ helices = helices.map_values (map_func);
217+ }
218+ }
219+ return helices;
220+ }
221+
222+ BuiltMap <int , Helix > helix_offset_change_all_while_creating_strand_reducer (
223+ BuiltMap <int , Helix > helices, AppState state, actions.StrandCreateAdjustOffset action) {
224+ if (state.ui_state.dynamically_update_helices) {
225+ StrandCreation strand_creation = state.ui_state.strand_creation;
226+ if (strand_creation != null ) {
227+ var helices_map = helices.toMap ();
228+ var original_helix_offsets = state.ui_state.original_helix_offsets;
229+
230+ // Increase helix size according to strand movement
231+ if (helices_map[strand_creation.helix.idx].min_offset > action.offset) {
232+ helices_map[strand_creation.helix.idx] =
233+ helices_map[strand_creation.helix.idx].rebuild ((b) => b..min_offset = action.offset);
234+ return helices_map.build ();
235+ }
236+ if (helices_map[strand_creation.helix.idx].max_offset <= action.offset) {
237+ helices_map[strand_creation.helix.idx] =
238+ helices_map[strand_creation.helix.idx].rebuild ((b) => b..max_offset = action.offset + 1 );
239+ return helices_map.build ();
240+ }
241+
242+ // Decrease helix size according to strand movement
243+ if (action.offset > helices_map[strand_creation.helix.idx].min_offset &&
244+ helices_map[strand_creation.helix.idx].min_offset <
245+ original_helix_offsets[strand_creation.helix.idx].item1) {
246+ helices_map[strand_creation.helix.idx] =
247+ helices_map[strand_creation.helix.idx].rebuild ((b) => b..min_offset = action.offset);
248+ return helices_map.build ();
249+ }
250+ if (action.offset < helices_map[strand_creation.helix.idx].max_offset + 1 &&
251+ helices_map[strand_creation.helix.idx].max_offset >
252+ original_helix_offsets[strand_creation.helix.idx].item2) {
253+ helices_map[strand_creation.helix.idx] =
254+ helices_map[strand_creation.helix.idx].rebuild ((b) => b.max_offset = action.offset + 1 );
255+ return helices_map.build ();
256+ }
257+ }
258+ }
259+ return helices;
260+ }
261+
262+ BuiltMap <int , Helix > first_replace_strands_reducer (
263+ BuiltMap <int , Helix > helices, AppState state, actions.ReplaceStrands action) {
264+ Map changed_strands = action.new_strands.toMap ();
265+ Map <int , int > min_offsets = {};
266+ Map <int , int > max_offsets = {};
267+ for (int key in changed_strands.keys) {
268+ Strand strand = changed_strands[key];
269+ List <Substrand > substrands = strand.substrands.toList ();
270+ for (var domain in substrands) {
271+ if (domain is Domain ) {
272+ int helix_idx = domain.helix;
273+ if (domain.start < helices[helix_idx].min_offset) {
274+ if (min_offsets.containsKey (helix_idx))
275+ min_offsets[helix_idx] = [min_offsets[helix_idx], domain.start].min;
276+ else
277+ min_offsets[helix_idx] = domain.start;
278+ }
279+ if (domain.end > helices[helix_idx].max_offset) {
280+ if (max_offsets.containsKey (helix_idx))
281+ max_offsets[helix_idx] = [max_offsets[helix_idx], domain.end].max;
282+ else
283+ max_offsets[helix_idx] = domain.end;
284+ }
285+ }
286+ }
287+ }
288+ var helices_map = helices.toMap ();
289+ if (min_offsets.length > 0 ) {
290+ for (int helix_idx in min_offsets.keys) {
291+ helices_map[helix_idx] = helices_map[helix_idx].rebuild ((b) => b..min_offset = min_offsets[helix_idx]);
292+ }
293+ }
294+ if (max_offsets.length > 0 ) {
295+ for (int helix_idx in max_offsets.keys) {
296+ helices_map[helix_idx] = helices_map[helix_idx].rebuild ((b) => b..max_offset = max_offsets[helix_idx]);
297+ }
298+ }
299+ return helices_map.build ();
300+ }
301+
302+ BuiltMap <int , Helix > reset_helices_offsets (BuiltMap <int , Helix > helices, AppState state) {
303+ var helices_updated = helices.toMap ();
304+ var original_helix_offsets = state.ui_state.original_helix_offsets;
305+ for (int idx in original_helix_offsets.keys) {
306+ int current_helix_min_offset = state.design.min_offset_of_strands_at (idx);
307+ if (current_helix_min_offset >= original_helix_offsets[idx].item1) {
308+ helices_updated[idx] =
309+ helices_updated[idx].rebuild ((b) => b.min_offset = original_helix_offsets[idx].item1);
310+ }
311+ int current_helix_max_offset = state.design.max_offset_of_strands_at (idx);
312+ if (current_helix_max_offset <= original_helix_offsets[idx].item2) {
313+ helices_updated[idx] =
314+ helices_updated[idx].rebuild ((b) => b.max_offset = original_helix_offsets[idx].item2);
315+ }
316+ }
317+ return helices_updated.build ();
318+ }
319+
320+ BuiltMap <int , Helix > reset_helices_offsets_after_selections_clear (
321+ BuiltMap <int , Helix > helices, AppState state, actions.SelectionsClear action) {
322+ return reset_helices_offsets (helices, state);
323+ }
324+
325+ // BuiltMap<int, Helix> reset_helices_offsets_after_creation(
326+ // BuiltMap<int, Helix> helices, AppState state, actions.StrandCreateStop action) {
327+ // return reset_helices_offsets(helices, state);
328+ // }
329+
189330BuiltMap <int , Helix > helix_offset_change_all_reducer (
190331 BuiltMap <int , Helix > helices, AppState state, actions.HelixOffsetChangeAll action) {
191332 Helix map_func (_, Helix helix) => _change_offset_one_helix (helix, action.min_offset, action.max_offset);
0 commit comments