Skip to content

Commit

Permalink
put DNA end on end of Extension. still need to apply correct rotation
Browse files Browse the repository at this point in the history
  • Loading branch information
dave-doty committed Sep 5, 2022
1 parent ca9d233 commit 478df80
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 29 deletions.
2 changes: 2 additions & 0 deletions lib/src/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ const css_selector_domain_name_text = 'domain-name-text';
const css_selector_strand_name_text = 'strand-name-text';
const css_selector_loopout_name = 'loopout-name';
const css_selector_loopout_name_text = 'loopout-name-text';
const css_selector_extension_name = 'extension-name';
const css_selector_extension_name_text = 'extension-name-text';

const css_selector_domain_moving = 'domain-line-moving';
const css_selector_disallowed = 'disallowed';
Expand Down
5 changes: 4 additions & 1 deletion lib/src/state/extension.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:tuple/tuple.dart';
Expand Down Expand Up @@ -86,7 +88,7 @@ abstract class Extension
..label = label
..dna_sequence = dna_sequence
..is_scaffold = is_scaffold
..adjacent_domain.replace(adjacent_domain)
..adjacent_domain = adjacent_domain?.toBuilder()
..unused_fields.replace(unused_fields));
}

Expand Down Expand Up @@ -166,4 +168,5 @@ abstract class Extension
substrand_is_last: !is_5p,
is_on_extension: true,
substrand_id: id);

}
12 changes: 12 additions & 0 deletions lib/src/state/strand.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:react/react.dart';
import 'package:tuple/tuple.dart';

import 'address.dart';
import 'helix.dart';
import 'linker.dart';
import 'modification.dart';
import '../serializers.dart';
Expand Down Expand Up @@ -805,6 +806,17 @@ abstract class Strand
substrands[i] = loopouts[i];
}

// go through extensions and set adjacent domains and adjacent helices
for (int i = 0; i < substrands.length; i++) {
if (substrands[i] is Extension) {
Extension ext = substrands[i];
Domain adjacent_domain = ext.is_5p ? substrands[i + 1] as Domain : substrands[i - 1] as Domain;
ext = ext.rebuild(
(b) => b..adjacent_domain.replace(adjacent_domain));
substrands[i] = ext;
}
}

for (int i = 0; i < num_substrands; i++) {
if (substrands[i] == null) {
throw AssertionError('should not have any null entries in substrands but ${i} is null:\n'
Expand Down
8 changes: 5 additions & 3 deletions lib/src/state/strand_maker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ class StrandMaker {

if (substrands.last is Extension) {
Extension ext = substrands.last;
ext = ext.rebuild((b) => b..adjacent_domain.replace(new_domain));
int last_idx = substrands.length-1;
ext =
ext.rebuild((b) => b..adjacent_domain.replace(new_domain));
int last_idx = substrands.length - 1;
substrands[last_idx] = ext;
}
this.substrands.add(new_domain);
Expand All @@ -133,12 +134,13 @@ class StrandMaker {

StrandMaker extension_3p(int num_bases, {double display_length = 1.0, double display_angle = 45.0}) {
_verify_extension_3p_is_valid();
Domain adjacent_domain = this.substrands.last;
Extension ext = Extension(
num_bases: num_bases,
display_length: display_length,
display_angle: display_angle,
is_5p: false,
adjacent_domain: this.substrands.last,
adjacent_domain: adjacent_domain,
);
this.substrands.add(ext);
this.contains_extension = true;
Expand Down
16 changes: 12 additions & 4 deletions lib/src/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1545,11 +1545,19 @@ mouse_leave_update_mouseover() {
}
}

Point<num> compute_extension_attached_end_svg(
Extension ext, Domain adj_dom, Helix adj_helix, num adj_helix_svg_y) {
int end_offset = ext.is_5p ? adj_dom.offset_5p : adj_dom.offset_3p;
Point<num> extension_attached_end_svg =
adj_helix.svg_base_pos(end_offset, adj_dom.forward, adj_helix_svg_y);
return extension_attached_end_svg;
}

// computes the SVG coordinates of the end of an Extension that is not shared with the adjacent Domain
Point<num> compute_extension_end(Point<num> domain_end_svg, Extension ext, Domain adjacent_domain,
Geometry geometry) {
num x = domain_end_svg.x;
num y = domain_end_svg.y;
Point<num> compute_extension_free_end_svg(
Point<num> attached_end_svg, Extension ext, Domain adjacent_domain, Geometry geometry) {
num x = attached_end_svg.x;
num y = attached_end_svg.y;
var angle_radians = ext.display_angle * 2 * pi / 360.0;
// convert polar coordiantes in Extension to rectangular coordines, and convert from nm to SVG pixels
num x_delta = ext.display_length * cos(angle_radians) * geometry.nm_to_svg_pixels;
Expand Down
18 changes: 17 additions & 1 deletion lib/src/view/design_main_strand_and_domain_names.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:built_collection/built_collection.dart';
import 'package:over_react/over_react.dart';
import 'package:scadnano/src/state/address.dart';
import 'package:scadnano/src/state/context_menu.dart';
import 'package:scadnano/src/state/extension.dart';
import 'package:scadnano/src/state/modification_type.dart';

import 'transform_by_helix_group.dart';
Expand All @@ -15,6 +16,7 @@ import 'design_main_strand_paths.dart';
import 'design_main_strand_domain_name.dart';
import 'design_main_strand_strand_name.dart';
import 'design_main_strand_loopout_name.dart';
import 'design_main_strand_extension_name.dart';
import 'pure_component.dart';
import '../state/strand.dart';
import '../state/helix.dart';
Expand Down Expand Up @@ -163,8 +165,22 @@ class DesignMainStrandAndDomainNamesComponent extends UiComponent2<DesignMainStr
..className = constants.css_selector_loopout_name
..key = "loopout-name-$i")());
}
} else if (substrand is Extension) {
Extension ext = substrand;
int adj_helix_idx = ext.adjacent_domain.helix;
bool draw_loopout = should_draw_extension(adj_helix_idx, props.side_selected_helix_idxs,
props.only_display_selected_helices);
if (draw_loopout && ext.name != null) {
names.add((DesignMainStrandExtensionName()
..ext = ext
..geometry = props.geometry
..font_size = props.domain_name_font_size
..show_dna = props.show_dna
..className = constants.css_selector_extension_name
..key = "extension-name-$i")());
}
} else {
throw AssertionError('substrand must be Domain or Loopout');
throw AssertionError('substrand must be Domain, Loopout, or Extension');
}
i++;
}
Expand Down
24 changes: 14 additions & 10 deletions lib/src/view/design_main_strand_dna_end.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ class DesignMainDNAEndComponent extends UiComponent2<DesignMainDNAEndProps> with
EndMovingProps end_moving_props = ConnectedEndMoving();

DNAEnd dna_end;
Helix helix;
int offset;
Point<num> pos;
bool forward;
Expand All @@ -117,17 +116,20 @@ class DesignMainDNAEndComponent extends UiComponent2<DesignMainDNAEndProps> with
// see here: https://github.com/marcojakob/dart-dnd/issues/27
forward = props.domain.forward;
dna_end = props.is_5p ? props.domain.dnaend_5p : props.domain.dnaend_3p;
helix = app.state.design.helices[props.domain.helix];
offset = props.is_5p ? props.domain.offset_5p : props.domain.offset_3p;
pos = helix.svg_base_pos(offset, props.domain.forward, props.helix_svg_position.y);
pos = props.helix.svg_base_pos(offset, props.domain.forward, props.helix_svg_position.y);
} else {
// is on extension
forward = props.ext.adjacent_domain.forward;
dna_end = props.ext.dnaend_free;
helix = null;
offset = null;
//TODO for testing; change to other end of extension line
pos = helix.svg_base_pos(offset, props.domain.forward, props.helix_svg_position.y);

Point<num> extension_attached_end_svg = util.compute_extension_attached_end_svg(
props.ext, props.ext.adjacent_domain, props.helix, props.helix_svg_position.y);

pos = util.compute_extension_free_end_svg(
extension_attached_end_svg, props.ext, props.ext.adjacent_domain, props.geometry);

//TODO: apply rotation
}

end_props = end_props
Expand All @@ -147,7 +149,7 @@ class DesignMainDNAEndComponent extends UiComponent2<DesignMainDNAEndProps> with
// draw avatar of moving DNA end if it is moving
end_moving_props = end_moving_props
..dna_end = dna_end
..helix = helix
..helix = props.helix
..color = props.color
..forward = forward
..is_5p = props.is_5p
Expand All @@ -166,9 +168,11 @@ class DesignMainDNAEndComponent extends UiComponent2<DesignMainDNAEndProps> with
componentDidMount() {
var element;
if (props.is_5p) {
element = querySelector('#${props.domain.dnaend_5p.id}');
var id = props.domain != null ? props.domain.dnaend_5p.id : props.ext.dnaend_free.id;
element = querySelector('#${id}');
} else {
element = querySelector('#${props.domain.dnaend_3p.id}');
var id = props.domain != null ? props.domain.dnaend_3p.id : props.ext.dnaend_free.id;
element = querySelector('#${id}');
}
element.addEventListener('contextmenu', on_context_menu);
}
Expand Down
18 changes: 10 additions & 8 deletions lib/src/view/design_main_strand_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,13 @@ class DesignMainExtensionComponent extends UiComponent2<DesignMainExtensionProps
String id = props.ext.id;
var adj_dom = props.adjacent_domain;
var adj_helix = props.adjacent_helix;
var adj_helix_svg_y = props.adjacent_helix_svg_position.y;

int end_offset = ext.is_5p ? adj_dom.offset_5p : adj_dom.offset_3p;
Point<num> end_svg =
adj_helix.svg_base_pos(end_offset, adj_dom.forward, props.adjacent_helix_svg_position.y);
Point<num> extension_attached_end_svg =
util.compute_extension_attached_end_svg(ext, adj_dom, adj_helix, adj_helix_svg_y);

Point<num> start_svg = util.compute_extension_end(end_svg, ext, adj_dom, props.geometry);
Point<num> extension_free_end_svg =
util.compute_extension_free_end_svg(extension_attached_end_svg, ext, adj_dom, props.geometry);

var classname = constants.css_selector_extension;
if (props.selected) {
Expand All @@ -88,14 +89,15 @@ class DesignMainExtensionComponent extends UiComponent2<DesignMainExtensionProps
..onPointerUp = handle_click_up
..stroke = props.color.toHexColor().toCssString()
..transform = props.transform
..x1 = '${start_svg.x}'
..y1 = '${start_svg.y}'
..x2 = '${end_svg.x}'
..y2 = '${end_svg.y}'
..x1 = '${extension_free_end_svg.x}'
..y1 = '${extension_free_end_svg.y}'
..x2 = '${extension_attached_end_svg.x}'
..y2 = '${extension_attached_end_svg.y}'
..id = id
..key = id)(Dom.svgTitle()(tooltip_text(ext) + '\n' + props.strand_tooltip));
}


handle_click_down(react.SyntheticPointerEvent event_syn) {
MouseEvent event = event_syn.nativeEvent;
if (event.button == constants.LEFT_CLICK_BUTTON) {
Expand Down
54 changes: 54 additions & 0 deletions lib/src/view/design_main_strand_extension_name.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'package:over_react/over_react.dart';

import '../state/geometry.dart';
import '../state/extension.dart';
import 'pure_component.dart';
import '../util.dart' as util;
import '../constants.dart' as constants;

part 'design_main_strand_extension_name.over_react.g.dart';

UiFactory<DesignMainStrandExtensionNameProps> DesignMainStrandExtensionName = _$DesignMainStrandExtensionName;

mixin DesignMainStrandExtensionNamePropsMixin on UiProps {
Extension ext;
Geometry geometry;

int font_size;
bool show_dna;
}

class DesignMainStrandExtensionNameProps = UiProps with DesignMainStrandExtensionNamePropsMixin;

class DesignMainStrandExtensionNameComponent extends UiComponent2<DesignMainStrandExtensionNameProps>
with PureComponent {
@override
render() {
var start_offset = '50%';
var dy = -0.1 * props.geometry.base_height_svg;
if (props.show_dna) {
dy -= props.geometry.base_height_svg;
}

num letter_spacing = 0.0;
num font_size = props.font_size;

Map<String, dynamic> style_map;
if (letter_spacing != null) {
style_map = {'letterSpacing': '${letter_spacing}em', 'fontSize': '${font_size}px'};
} else {
style_map = {'fontSize': '${font_size}px'};
}

SvgProps text_path_props = (Dom.textPath()
..className = constants.css_selector_extension_name
..xlinkHref = '#${props.ext.id}'
..startOffset = start_offset
..style = style_map);
var dom = props.ext.adjacent_domain;
var adj_dom_offset = props.ext.is_5p? dom.offset_5p: dom.offset_3p;
return (Dom.text()
..key = 'extension-text-H${props.ext.adjacent_domain.helix},${adj_dom_offset}'
..dy = '$dy')(text_path_props(props.ext.name));
}
}
1 change: 0 additions & 1 deletion lib/src/view/design_main_strand_paths.dart
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,6 @@ class DesignMainStrandPathsComponent extends UiComponent2<DesignMainStrandPathsP
ends.add((DesignMainDNAEnd()
..ext = ext
..is_on_extension = true
..is_on_extension = false
..is_5p = ext.is_5p
..transform = transform_of_helix(ext.adjacent_domain.helix)
..color = strand.color
Expand Down
2 changes: 1 addition & 1 deletion web/scadnano-styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ https://stackoverflow.com/questions/47758565/adding-fedropshadow-to-a-vertical-l
white-space: pre; /* needed to display multiple space symbols in a row */
}

.loopout-name {
.loopout-name, .extension-name {
text-anchor: middle;
pointer-events: none;
dominant-baseline: ideographic;
Expand Down

0 comments on commit 478df80

Please sign in to comment.