@teselagen/ove 0.7.27 → 0.7.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AASliver.js +187 -0
- package/AddLaddersDialog.js +82 -0
- package/AdditionalCutsiteInfoDialog.js +599 -0
- package/AlignmentView/Mismatches.d.ts +3 -3
- package/AlignmentVisibilityTool.js +105 -0
- package/AnnotationContainerHolder.js +20 -0
- package/AnnotationPositioner.js +27 -0
- package/AutoAnnotate.js +501 -0
- package/AutoAnnotateBpMatchingDialog.js +208 -0
- package/Axis.js +151 -0
- package/AxisNumbers.js +35 -0
- package/Browser.js +106 -0
- package/Caret.js +63 -0
- package/Chromatogram.js +293 -0
- package/CircularDnaSequence.js +73 -0
- package/CircularView/Labels/index.d.ts +1 -1
- package/CircularView/index.d.ts +0 -1
- package/CircularZoomMinimap.js +16 -0
- package/ColorPicker.js +30 -0
- package/CommandHotkeyHandler.js +44 -0
- package/CreateAnnotationsPage.d.ts +4 -4
- package/CreateAnnotationsPage.js +98 -0
- package/Cutsite.js +18 -0
- package/CutsiteProperties.js +176 -0
- package/CutsiteSelectionLayers.js +47 -0
- package/Cutsites.js +271 -0
- package/DeletionLayer.js +28 -0
- package/DigestTool/Ladder.d.ts +1 -1
- package/DropHandler.css +21 -0
- package/DropHandler.js +64 -0
- package/EditCaretPosition.js +234 -0
- package/EditTrackNameDialog.js +30 -0
- package/Feature.js +83 -0
- package/FeatureProperties.js +6 -0
- package/FillWindow.js +47 -0
- package/GenbankView.js +74 -0
- package/GeneralProperties.js +117 -0
- package/GenericAnnotationProperties.js +406 -0
- package/GlobalDialog.js +73 -0
- package/GlobalDialogUtils.js +110 -0
- package/GoToDialog.js +25 -0
- package/HorizontalPanelDragHandle.js +35 -0
- package/Keyboard.js +85 -0
- package/Labels.js +327 -0
- package/Ladder.css +20 -0
- package/Ladder.js +303 -0
- package/MeltingTemp.js +85 -0
- package/Menlo.ttf +0 -0
- package/Minimap.js +515 -0
- package/Mismatches.js +134 -0
- package/Monaco.ttf +0 -0
- package/MultipleSeqsDetectedOnImportDialog.js +74 -0
- package/Orf.js +109 -0
- package/OrfProperties.js +117 -0
- package/Orfs.js +35 -0
- package/PCRTool.js +179 -0
- package/PairwiseAlignmentView.js +68 -0
- package/Part.js +34 -0
- package/PartProperties.js +9 -0
- package/PassThrough.js +3 -0
- package/PerformantSelectionLayer.js +32 -0
- package/PinchHelper.js +24 -0
- package/PointedAnnotation.js +347 -0
- package/PositionAnnotationOnCircle.js +26 -0
- package/Primer.js +41 -0
- package/PrimerProperties.js +19 -0
- package/Reflex/index.d.ts +0 -1
- package/ReflexContainer.js +802 -0
- package/ReflexElement.js +160 -0
- package/ReflexEvents.js +77 -0
- package/ReflexSplitter.js +205 -0
- package/RenameSequenceDialog.js +7 -0
- package/RotateCircularViewSlider.js +93 -0
- package/RowView/index.d.ts +0 -1
- package/SelectDialog.js +150 -0
- package/SequenceName.js +15 -0
- package/SimpleCircularOrLinearView.js +381 -0
- package/SimpleOligoPreview.js +39 -0
- package/SingleEnzymeCutsiteInfo.js +139 -0
- package/ToolBar/ToolbarItem.d.ts +1 -3
- package/ToolbarItem.js +192 -0
- package/Translation.js +198 -0
- package/TranslationProperties.js +149 -0
- package/UncontrolledSliderWithPlusMinusBtns.css +5 -0
- package/UncontrolledSliderWithPlusMinusBtns.js +134 -0
- package/VeTopRightContainer.js +12 -0
- package/ZoomCircularViewSlider.js +62 -0
- package/ZoomLinearView.js +47 -0
- package/addAlignment.js +6 -0
- package/addMetaToActionCreators.js +12 -0
- package/addWrappedAddons.js +20 -0
- package/alignmentTool.js +503 -0
- package/alignments.js +379 -0
- package/annotationLabelVisibility.js +2 -0
- package/annotationSearchSelector.js +24 -0
- package/annotationTypes.js +35 -0
- package/annotationVisibility.js +196 -0
- package/annotationsToSupport.js +104 -0
- package/arrayToObjWithIds.js +17 -0
- package/arrayUtils.js +19 -0
- package/array_move.js +10 -0
- package/calculateTickMarkPositionsForGivenRange.js +47 -0
- package/caretPosition.js +27 -0
- package/cdsFeaturesSelector.js +9 -0
- package/charWidth.js +22 -0
- package/circular.js +19 -0
- package/circularSelector.js +4 -0
- package/clickAndDragUtils.js +576 -0
- package/coerceInitialValue.js +7 -0
- package/combineReducersDontIgnoreKeys.js +12 -0
- package/commandUtils.js +20 -0
- package/constants.js +2 -0
- package/copyOptions.js +34 -0
- package/createFragmentLines.js +120 -0
- package/createMergedDefaultStateReducer.js +30 -0
- package/createMetaAction.js +12 -0
- package/createSequenceInputPopup.js +290 -0
- package/createSequenceInputPopupStyle.css +87 -0
- package/createSimpleDialog.js +89 -0
- package/createYourOwnEnzyme.js +39 -0
- package/cutsiteLabelColorSelector.js +6 -0
- package/cutsiteTool.js +88 -0
- package/cutsitesByRangeSelector.js +5 -0
- package/cutsitesSelector.js +61 -0
- package/darkmode.css +98 -0
- package/defaultConfig.js +150 -0
- package/deletionLayers.js +36 -0
- package/description.js +21 -0
- package/digestTool.js +34 -0
- package/dnaToColor.js +17 -0
- package/downloadTool.js +39 -0
- package/draggableClassnames.js +5 -0
- package/drawAnnotations.js +440 -0
- package/drawDirectedPiePiece.js +142 -0
- package/editTool.js +49 -0
- package/editorSelector.js +2 -0
- package/editorUtils.js +205 -0
- package/estimateRowHeight.js +184 -0
- package/featureLengthsToHide.js +27 -0
- package/featureTool.js +34 -0
- package/features.js +19 -0
- package/featuresSelector.js +8 -0
- package/filteredCutsitesSelector.js +136 -0
- package/filteredFeaturesSelector.js +32 -0
- package/filteredPartsSelector.js +57 -0
- package/filteredPrimersSelector.js +27 -0
- package/filteredRestrictionEnzymesSelector.js +1 -0
- package/find.png +0 -0
- package/findTool.js +79 -0
- package/findToolConstants.js +1 -0
- package/frameTranslations.js +52 -0
- package/fullscreen.png +0 -0
- package/getAdditionalEnzymesSelector.js +46 -0
- package/getAngleForPositionMidpoint.js +3 -0
- package/getAnnotationClassnames.js +12 -0
- package/getAnnotationNameAndStartStopString.js +61 -0
- package/getBpsPerRow.js +19 -0
- package/getCutsiteLabelHeights.js +56 -0
- package/getGapMap.js +12 -0
- package/getGaps.js +27 -0
- package/getInternalLabel.js +40 -0
- package/getOveHotkeyDefs.js +12 -0
- package/getPairwiseOverviewLinearViewOptions.js +38 -0
- package/getRangeAnglesSpecial.js +12 -0
- package/getStructuredBases.js +97 -0
- package/getTrackFromEvent.js +25 -0
- package/getVisibleStartEnd.js +7 -0
- package/getXStartAndWidthFromNonCircularRange.js +12 -0
- package/getXStartAndWidthOfRangeWrtRow.js +27 -0
- package/getXStartAndWidthOfRowAnnotation.js +19 -0
- package/getYOffset.js +15 -0
- package/hoveredAnnotation.js +24 -0
- package/{html2canvas.esm--JN4fLQL.js → html2canvas.esm-DiGWN1gP.js} +187 -229
- package/{html2canvas.esm-B7d7VJmQ.cjs → html2canvas.esm-J1esNpMJ.cjs} +187 -229
- package/importTool.js +27 -0
- package/index.cjs.js +48165 -47142
- package/index.es.js +47699 -46676
- package/index.js +71 -0
- package/inlineFindTool.js +38 -0
- package/isElementInViewport.js +29 -0
- package/isEnzymeFilterAndSelector.js +1 -0
- package/isTargetWithinEl.js +6 -0
- package/labelLineIntensity.js +25 -0
- package/labelSize.js +23 -0
- package/ladderDefaults.js +25 -0
- package/lastSavedId.js +20 -0
- package/lineageLines.js +11 -0
- package/linear.png +0 -0
- package/makeStore.js +34 -0
- package/massageTickSpacing.js +19 -0
- package/materiallyAvailable.js +19 -0
- package/middleware.js +112 -0
- package/minimumOrfSize.js +24 -0
- package/minimumOrfSizeSelector.js +2 -0
- package/modalActions.js +3 -0
- package/moveCaret.js +58 -0
- package/name.js +19 -0
- package/normalizeAngle.js +3 -0
- package/normalizeAngleRange.js +9 -0
- package/oligoTool.js +30 -0
- package/onlyUpdateForKeysDeep.js +31 -0
- package/orfFrameToColorMap.js +10 -0
- package/orfTool.js +136 -0
- package/orfsSelector.js +15 -0
- package/ove.css +12107 -0
- package/package.json +6 -5
- package/panelsShown.js +294 -0
- package/partLengthsToHide.js +23 -0
- package/partOverhangs.js +6 -0
- package/partTagSearch.js +69 -0
- package/partTool.js +45 -0
- package/parts.js +19 -0
- package/partsSelector.js +8 -0
- package/pie.png +0 -0
- package/polarToSpecialCartesian.js +7 -0
- package/positionCutsites.js +6 -0
- package/prepareRowData.js +64 -0
- package/primerBases.js +221 -0
- package/primerLengthsToHide.js +27 -0
- package/primers.js +19 -0
- package/primersSelector.js +8 -0
- package/print.png +0 -0
- package/printTool.js +31 -0
- package/propertiesTool.js +40 -0
- package/proteinUtils.js +3 -0
- package/pureNoFunc.js +18 -0
- package/readOnly.js +25 -0
- package/redoTool.js +30 -0
- package/reflex-styles.css +128 -0
- package/reflex-styles.css.map +9 -0
- package/relaxLabelAngles.js +157 -0
- package/relaxLabels_DEPRECATED.js +105 -0
- package/replacementLayers.js +36 -0
- package/restrictionEnzymes.js +52 -0
- package/restrictionEnzymesSelector.js +34 -0
- package/rowviewContants.js +3 -0
- package/ruler.css +89 -0
- package/save.png +0 -0
- package/saveTool.js +44 -0
- package/searchLayersSelector.js +71 -0
- package/selectedAnnotations.js +89 -0
- package/selectedAnnotationsSelector.js +1 -0
- package/selectedCutsitesSelector.js +21 -0
- package/selectedPartTags.js +21 -0
- package/selectionLayer.js +25 -0
- package/selectors/annotationSearchSelector.d.ts +1 -1
- package/sequence.js +12 -0
- package/sequenceDataHistory.js +43 -0
- package/sequenceDataSelector.js +2 -0
- package/sequenceLengthSelector.js +5 -0
- package/sequenceSelector.js +4 -0
- package/sharedActionCreators.js +0 -0
- package/shouldFlipText.js +4 -0
- package/shouldRerender.js +27 -0
- package/showFileDialog.js +25 -0
- package/showGCContent.js +23 -0
- package/show_cut_sites.png +0 -0
- package/show_features.png +0 -0
- package/show_orfs.png +0 -0
- package/show_primers.png +0 -0
- package/simpleDialog.css +13 -0
- package/specialCutsiteFilterOptions.js +22 -0
- package/src/Editor/DropHandler.js +2 -1
- package/src/Editor/index.js +0 -2
- package/src/RowItem/StackedAnnotations/getStructuredBases.js +20 -6
- package/src/ToolBar/cutsiteTool.js +1 -1
- package/src/helperComponents/PropertiesDialog/TranslationProperties.js +2 -1
- package/style.css +3 -12100
- package/tagsToBoldSelector.js +2 -0
- package/toggle_views.svg +1 -0
- package/toolBar.js +23 -0
- package/translationSearchMatchesSelector.js +14 -0
- package/translations.js +20 -0
- package/translationsRawSelector.js +8 -0
- package/translationsSelector.js +137 -0
- package/typeField.js +24 -0
- package/undoTool.js +30 -0
- package/updateEditor.d.ts +1 -3
- package/updateEditor.js +200 -0
- package/updateLabelsForInViewFeatures.js +55 -0
- package/updateLabelsForInViewFeaturesCircView.js +41 -0
- package/updateTrackHelper.js +58 -0
- package/uppercaseSequenceMapFont.js +25 -0
- package/upsertDeleteActionGenerator.js +31 -0
- package/useAAColorType.js +8 -0
- package/useAdditionalOrfStartCodons.js +24 -0
- package/useAnnotationLimits.js +42 -0
- package/useChromatogramPrefs.js +31 -0
- package/useFormValue.js +7 -0
- package/useLadders.js +6 -0
- package/useMeltingTemp.js +7 -0
- package/useTmType.js +10 -0
- package/userDefinedHandlersAndOpts.js +61 -0
- package/utils/getAnnotationNameAndStartStopString.d.ts +1 -5
- package/utils/selectionLayer.d.ts +2 -2
- package/utils.js +37 -0
- package/versionHistory.js +26 -0
- package/versionHistoryTool.js +21 -0
- package/viewSubmenu.js +479 -0
- package/visibilityTool.js +39 -0
- package/withEditorInteractions/getBpsPerRow.d.ts +1 -3
- package/withHover.js +113 -0
- package/withRestrictionEnzymes.js +15 -0
- package/index.umd.js +0 -188322
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import IntervalTree from "node-interval-tree";
|
|
3
|
+
import { sortBy, noop } from "lodash-es";
|
|
4
|
+
import { getRangeLength } from "@teselagen/range-utils";
|
|
5
|
+
import getRangeAngles from "./getRangeAnglesSpecial";
|
|
6
|
+
import getYOffset from "./getYOffset";
|
|
7
|
+
import withHover from "../helperComponents/withHover";
|
|
8
|
+
import PositionAnnotationOnCircle from "./PositionAnnotationOnCircle";
|
|
9
|
+
import getAnnotationNameAndStartStopString from "../utils/getAnnotationNameAndStartStopString";
|
|
10
|
+
import Feature from "./Feature";
|
|
11
|
+
import getAnnotationClassnames from "../utils/getAnnotationClassnames";
|
|
12
|
+
// import { normalizeAngleRange } from "./normalizeAngleRange";
|
|
13
|
+
// import { normalizeAngle } from "./normalizeAngle";
|
|
14
|
+
|
|
15
|
+
//annotations coming in can be positioned either by caretPosition or range
|
|
16
|
+
function drawAnnotations(props) {
|
|
17
|
+
const {
|
|
18
|
+
readOnly,
|
|
19
|
+
annotationType,
|
|
20
|
+
radius,
|
|
21
|
+
noHover,
|
|
22
|
+
isProtein,
|
|
23
|
+
type,
|
|
24
|
+
annotations,
|
|
25
|
+
annotationHeight,
|
|
26
|
+
noTitle,
|
|
27
|
+
spaceBetweenAnnotations,
|
|
28
|
+
sequenceLength,
|
|
29
|
+
showCicularViewInternalLabels,
|
|
30
|
+
// reverseAnnotations, //set true when drawing annotations that use the drawDirectedPiePiece function because that function returns things that need to be flipped
|
|
31
|
+
// editorName,
|
|
32
|
+
getColor,
|
|
33
|
+
useStartAngle, //use the startAngle instead of the centerAngle to position the labels
|
|
34
|
+
onClick = noop,
|
|
35
|
+
noHeight,
|
|
36
|
+
positionBy, //by default the annotation.start and annotation.end are used to position the annotation on the circle, but passing a function here gives an option to override that
|
|
37
|
+
allOnSameLevel, //by default overlapping annotations are given different yOffsets. Setting this to true prevents that and positions all annotations on the same level (no y-offsets given). Cutsites for example just get drawn all on the same level
|
|
38
|
+
onRightClicked = noop,
|
|
39
|
+
onDoubleClick = noop,
|
|
40
|
+
showLabels,
|
|
41
|
+
hideAnnotation,
|
|
42
|
+
// rotationRadians,
|
|
43
|
+
labelOptions,
|
|
44
|
+
annotationProps,
|
|
45
|
+
fontStyle
|
|
46
|
+
// isZoomedIn,
|
|
47
|
+
// visibleAngleRange
|
|
48
|
+
} = props;
|
|
49
|
+
const totalAnnotationHeight = annotationHeight + spaceBetweenAnnotations;
|
|
50
|
+
const featureITree = new IntervalTree();
|
|
51
|
+
let maxYOffset = 0;
|
|
52
|
+
const svgGroup = [];
|
|
53
|
+
const labels = {};
|
|
54
|
+
|
|
55
|
+
if (!Object.keys(annotations).length) return null;
|
|
56
|
+
sortBy(annotations, a => {
|
|
57
|
+
return -getRangeLength(a, sequenceLength);
|
|
58
|
+
})
|
|
59
|
+
.map(annotation => {
|
|
60
|
+
const { startAngle, endAngle, totalAngle, centerAngle, locationAngles } =
|
|
61
|
+
getRangeAngles(
|
|
62
|
+
positionBy ? positionBy(annotation) : annotation,
|
|
63
|
+
sequenceLength
|
|
64
|
+
);
|
|
65
|
+
const spansOrigin = startAngle > endAngle;
|
|
66
|
+
const annotationCopy = {
|
|
67
|
+
...annotation,
|
|
68
|
+
startAngle,
|
|
69
|
+
endAngle,
|
|
70
|
+
locationAngles,
|
|
71
|
+
totalAngle,
|
|
72
|
+
centerAngle,
|
|
73
|
+
yOffset: 0
|
|
74
|
+
};
|
|
75
|
+
if (!allOnSameLevel) {
|
|
76
|
+
//expand the end angle if annotation spans the origin
|
|
77
|
+
const expandedEndAngle = spansOrigin
|
|
78
|
+
? endAngle + 2 * Math.PI
|
|
79
|
+
: endAngle;
|
|
80
|
+
let yOffset1;
|
|
81
|
+
let yOffset2;
|
|
82
|
+
if (spansOrigin) {
|
|
83
|
+
annotationCopy.yOffset = getYOffset(
|
|
84
|
+
featureITree,
|
|
85
|
+
startAngle,
|
|
86
|
+
expandedEndAngle
|
|
87
|
+
);
|
|
88
|
+
} else {
|
|
89
|
+
//we need to check both locations to account for annotations that span the origin
|
|
90
|
+
yOffset1 = getYOffset(featureITree, startAngle, expandedEndAngle);
|
|
91
|
+
yOffset2 = getYOffset(
|
|
92
|
+
featureITree,
|
|
93
|
+
startAngle + Math.PI * 2,
|
|
94
|
+
expandedEndAngle + Math.PI * 2
|
|
95
|
+
);
|
|
96
|
+
annotationCopy.yOffset = Math.max(yOffset1, yOffset2);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (spansOrigin) {
|
|
100
|
+
featureITree.insert(startAngle, expandedEndAngle, {
|
|
101
|
+
...annotationCopy
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
//normal feature
|
|
105
|
+
// we need to add it twice to the interval tree to accomodate features which span the origin
|
|
106
|
+
featureITree.insert(startAngle, expandedEndAngle, {
|
|
107
|
+
...annotationCopy
|
|
108
|
+
});
|
|
109
|
+
featureITree.insert(
|
|
110
|
+
startAngle + 2 * Math.PI,
|
|
111
|
+
expandedEndAngle + 2 * Math.PI,
|
|
112
|
+
|
|
113
|
+
{ ...annotationCopy }
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (annotationCopy.yOffset > maxYOffset) {
|
|
118
|
+
maxYOffset = annotationCopy.yOffset;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return annotationCopy;
|
|
123
|
+
})
|
|
124
|
+
.forEach(function (annotation, index) {
|
|
125
|
+
annotation.yOffset = maxYOffset - annotation.yOffset;
|
|
126
|
+
function _onClick(event) {
|
|
127
|
+
onClick && onClick({ event, annotation });
|
|
128
|
+
annotation.onClick && annotation.onClick({ event, annotation });
|
|
129
|
+
}
|
|
130
|
+
function onContextMenu(event) {
|
|
131
|
+
onRightClicked({ event, annotation });
|
|
132
|
+
if (annotation.onRightClick) {
|
|
133
|
+
annotation.onRightClick({ event, annotation });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function _onDoubleClick(event) {
|
|
137
|
+
onDoubleClick && onDoubleClick({ event, annotation });
|
|
138
|
+
if (annotation.onDoubleClick) {
|
|
139
|
+
annotation.onDoubleClick({ event, annotation });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const {
|
|
144
|
+
startAngle,
|
|
145
|
+
endAngle,
|
|
146
|
+
totalAngle,
|
|
147
|
+
centerAngle,
|
|
148
|
+
locationAngles,
|
|
149
|
+
...rest
|
|
150
|
+
} = annotation;
|
|
151
|
+
|
|
152
|
+
const _annotationProps = {
|
|
153
|
+
...annotationProps,
|
|
154
|
+
...rest
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const titleText = getAnnotationNameAndStartStopString(annotation, {
|
|
158
|
+
isProtein,
|
|
159
|
+
readOnly
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const classNames = getAnnotationClassnames(annotation, {
|
|
163
|
+
viewName: "CircularView",
|
|
164
|
+
type,
|
|
165
|
+
isProtein,
|
|
166
|
+
readOnly
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const annotationRadius =
|
|
170
|
+
radius + annotation.yOffset * totalAnnotationHeight;
|
|
171
|
+
const name =
|
|
172
|
+
annotation.name ||
|
|
173
|
+
(annotation.restrictionEnzyme && annotation.restrictionEnzyme.name);
|
|
174
|
+
let ellipsizedName;
|
|
175
|
+
// let spaceBeforeName = 0;
|
|
176
|
+
let angleAdjust;
|
|
177
|
+
|
|
178
|
+
if (name && showCicularViewInternalLabels) {
|
|
179
|
+
// eslint-disable-next-line no-inner-declarations
|
|
180
|
+
function getEllipsizedName(totalAngle) {
|
|
181
|
+
let ellipsizedName;
|
|
182
|
+
const arcLength =
|
|
183
|
+
2 * Math.PI * (annotationRadius - annotationHeight) * totalAngle; //for arrowhead
|
|
184
|
+
|
|
185
|
+
const annLength = Math.max(0, Math.floor(arcLength / 55 - 3));
|
|
186
|
+
ellipsizedName = name.slice(0, annLength);
|
|
187
|
+
if (ellipsizedName && ellipsizedName !== name) {
|
|
188
|
+
if (ellipsizedName.length >= name.length - 2) {
|
|
189
|
+
ellipsizedName = name;
|
|
190
|
+
} else if (ellipsizedName.length > 3) {
|
|
191
|
+
ellipsizedName += "..";
|
|
192
|
+
} else {
|
|
193
|
+
ellipsizedName = undefined;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return ellipsizedName;
|
|
197
|
+
}
|
|
198
|
+
if (locationAngles) {
|
|
199
|
+
annotation.locationAngles = locationAngles.map(l => {
|
|
200
|
+
const en = getEllipsizedName(l.totalAngle);
|
|
201
|
+
if (en?.length > (ellipsizedName?.length || 0)) {
|
|
202
|
+
ellipsizedName = en;
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
...l,
|
|
206
|
+
ellipsizedName: en
|
|
207
|
+
};
|
|
208
|
+
});
|
|
209
|
+
} else {
|
|
210
|
+
ellipsizedName = getEllipsizedName(totalAngle);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// //tnr: WIP to try to adjust the inline label in the circular view to always show up even when zoomed in
|
|
214
|
+
// if (ellipsizedName && isZoomedIn) {
|
|
215
|
+
// const nameAngle =
|
|
216
|
+
// ((ellipsizedName.length + 3) * 55) /
|
|
217
|
+
// (2 * Math.PI * (annotationRadius - annotationHeight));
|
|
218
|
+
// const maxAngleAdjust = (totalAngle - nameAngle) / 2;
|
|
219
|
+
// const idealAngle = normalizeAngle(
|
|
220
|
+
// -normalizeAngle(rotationRadians) - normalizeAngle(centerAngle)
|
|
221
|
+
// );
|
|
222
|
+
// angleAdjust = idealAngle;
|
|
223
|
+
// if (
|
|
224
|
+
// Math.min(maxAngleAdjust, idealAngle) !== idealAngle
|
|
225
|
+
// // &&
|
|
226
|
+
// // Math.min(maxAngleAdjust, 2 * Math.PI - idealAngle) !==
|
|
227
|
+
// // 2 * Math.PI - idealAngle
|
|
228
|
+
// ) {
|
|
229
|
+
// angleAdjust = -maxAngleAdjust;
|
|
230
|
+
// if (
|
|
231
|
+
// normalizeAngle(
|
|
232
|
+
// normalizeAngle(centerAngle) + normalizeAngle(rotationRadians)
|
|
233
|
+
// ) > Math.PI
|
|
234
|
+
// ) {
|
|
235
|
+
// angleAdjust = -angleAdjust;
|
|
236
|
+
// }
|
|
237
|
+
// }
|
|
238
|
+
// // angleAdjust =idealAngle
|
|
239
|
+
// angleAdjust = (angleAdjust / Math.PI) * 180;
|
|
240
|
+
// // if (normalizeAngle(normalizeAngle(centerAngle) + normalizeAngle(rotationRadians)) > Math.PI) {
|
|
241
|
+
// // angleAdjust = -angleAdjust;
|
|
242
|
+
// // }
|
|
243
|
+
// }
|
|
244
|
+
}
|
|
245
|
+
if (showLabels && !ellipsizedName) {
|
|
246
|
+
//add labels to the exported label array (to be drawn by the label component)
|
|
247
|
+
labels[annotation.id] = {
|
|
248
|
+
annotation,
|
|
249
|
+
annotationType,
|
|
250
|
+
annotationCenterAngle: useStartAngle ? startAngle : centerAngle,
|
|
251
|
+
annotationCenterRadius: annotationRadius,
|
|
252
|
+
text: name,
|
|
253
|
+
id: annotation.id,
|
|
254
|
+
title: titleText,
|
|
255
|
+
className: `${classNames} ${annotation.labelClassName || ""}`,
|
|
256
|
+
highPriorityLabel: annotation.highPriorityLabel,
|
|
257
|
+
onClick: _onClick,
|
|
258
|
+
onDoubleClick: _onDoubleClick,
|
|
259
|
+
fontStyle: fontStyle || "normal",
|
|
260
|
+
color:
|
|
261
|
+
annotation.labelColor ||
|
|
262
|
+
(annotationType === "part" ? "#ac68cc" : "black"),
|
|
263
|
+
onContextMenu,
|
|
264
|
+
...labelOptions
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (!hideAnnotation) {
|
|
268
|
+
const annotationColor = getColor
|
|
269
|
+
? getColor(annotation)
|
|
270
|
+
: annotation.color || "#ac68cc";
|
|
271
|
+
DrawAnnotation.displayName = annotationType + "--- DrawAnnotation";
|
|
272
|
+
const CompToUse = noHover ? DrawAnnotationInner : DrawAnnotation;
|
|
273
|
+
svgGroup.push(
|
|
274
|
+
<CompToUse
|
|
275
|
+
{...{
|
|
276
|
+
...props,
|
|
277
|
+
...rest,
|
|
278
|
+
...annotation,
|
|
279
|
+
angleAdjust,
|
|
280
|
+
ellipsizedName,
|
|
281
|
+
name,
|
|
282
|
+
annotationHeight,
|
|
283
|
+
annotationRadius,
|
|
284
|
+
annotationType,
|
|
285
|
+
isProtein,
|
|
286
|
+
noTitle,
|
|
287
|
+
titleText,
|
|
288
|
+
classNames,
|
|
289
|
+
onClick: _onClick,
|
|
290
|
+
onDoubleClick: _onDoubleClick,
|
|
291
|
+
onContextMenu,
|
|
292
|
+
annotation,
|
|
293
|
+
annotationColor,
|
|
294
|
+
totalAngle,
|
|
295
|
+
centerAngle,
|
|
296
|
+
annotationProps: _annotationProps
|
|
297
|
+
}}
|
|
298
|
+
id={annotation.id}
|
|
299
|
+
key={"veAnnotation-" + annotationType + index}
|
|
300
|
+
/>
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
return {
|
|
305
|
+
component: (
|
|
306
|
+
<g
|
|
307
|
+
className={"veAnnotations-" + annotationType}
|
|
308
|
+
key={"veAnnotations-" + annotationType}
|
|
309
|
+
>
|
|
310
|
+
{svgGroup}
|
|
311
|
+
</g>
|
|
312
|
+
),
|
|
313
|
+
height: noHeight
|
|
314
|
+
? 0
|
|
315
|
+
: maxYOffset * totalAnnotationHeight + 0.5 * annotationHeight,
|
|
316
|
+
labels
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export default drawAnnotations;
|
|
321
|
+
|
|
322
|
+
function DrawAnnotationInner({
|
|
323
|
+
className,
|
|
324
|
+
startAngle,
|
|
325
|
+
endAngle,
|
|
326
|
+
onClick,
|
|
327
|
+
onDoubleClick,
|
|
328
|
+
onContextMenu,
|
|
329
|
+
titleText,
|
|
330
|
+
classNames,
|
|
331
|
+
locationAngles,
|
|
332
|
+
annotation,
|
|
333
|
+
reverseAnnotations,
|
|
334
|
+
Annotation = Feature,
|
|
335
|
+
totalAngle,
|
|
336
|
+
annotationColor,
|
|
337
|
+
isProtein,
|
|
338
|
+
annotationRadius,
|
|
339
|
+
annotationHeight,
|
|
340
|
+
onMouseLeave,
|
|
341
|
+
onMouseOver,
|
|
342
|
+
annotationType,
|
|
343
|
+
annotationProps,
|
|
344
|
+
addHeight,
|
|
345
|
+
noTitle,
|
|
346
|
+
useCenter,
|
|
347
|
+
centerAngle,
|
|
348
|
+
perAnnotationProps,
|
|
349
|
+
passAnnotation,
|
|
350
|
+
ellipsizedName,
|
|
351
|
+
angleAdjust,
|
|
352
|
+
rotationRadians
|
|
353
|
+
}) {
|
|
354
|
+
const sharedProps = {
|
|
355
|
+
style: noTitle ? undefined : { cursor: "pointer" },
|
|
356
|
+
className: `${className} ${classNames}`,
|
|
357
|
+
onContextMenu: onContextMenu,
|
|
358
|
+
onClick: onClick,
|
|
359
|
+
onDoubleClick: onDoubleClick,
|
|
360
|
+
onMouseLeave,
|
|
361
|
+
onMouseOver
|
|
362
|
+
};
|
|
363
|
+
function getInner(
|
|
364
|
+
{
|
|
365
|
+
startAngle,
|
|
366
|
+
endAngle,
|
|
367
|
+
totalAngle,
|
|
368
|
+
isNotLocation,
|
|
369
|
+
containsLocations,
|
|
370
|
+
ellipsizedName: ellipsizedNameLocation
|
|
371
|
+
},
|
|
372
|
+
i
|
|
373
|
+
) {
|
|
374
|
+
const { transform, revTransform } = PositionAnnotationOnCircle({
|
|
375
|
+
sAngle: useCenter ? centerAngle : startAngle,
|
|
376
|
+
eAngle: useCenter ? centerAngle : endAngle,
|
|
377
|
+
height: addHeight ? annotationRadius : undefined,
|
|
378
|
+
forward: reverseAnnotations ? !annotation.forward : annotation.forward
|
|
379
|
+
});
|
|
380
|
+
return (
|
|
381
|
+
<g
|
|
382
|
+
transform={transform}
|
|
383
|
+
data-title={noTitle ? null : titleText}
|
|
384
|
+
{...avoidOverlapWith}
|
|
385
|
+
key={
|
|
386
|
+
isNotLocation
|
|
387
|
+
? "notLocation"
|
|
388
|
+
: "location--" + annotation.id + "--" + i
|
|
389
|
+
}
|
|
390
|
+
{...sharedProps}
|
|
391
|
+
>
|
|
392
|
+
{noTitle ? null : (
|
|
393
|
+
<g hidden style={{ display: "none" }}>
|
|
394
|
+
{titleText}
|
|
395
|
+
</g>
|
|
396
|
+
)}
|
|
397
|
+
<Annotation
|
|
398
|
+
{...(passAnnotation && { annotation })}
|
|
399
|
+
annotationType={annotationType}
|
|
400
|
+
arrowheadType={annotation.arrowheadType}
|
|
401
|
+
totalAngle={totalAngle}
|
|
402
|
+
centerAngle={centerAngle}
|
|
403
|
+
revTransform={revTransform}
|
|
404
|
+
rotationRadians={rotationRadians}
|
|
405
|
+
ellipsizedName={
|
|
406
|
+
containsLocations ? ellipsizedNameLocation : ellipsizedName
|
|
407
|
+
}
|
|
408
|
+
locationNumber={i}
|
|
409
|
+
angleAdjust={angleAdjust}
|
|
410
|
+
color={annotationColor}
|
|
411
|
+
isProtein={isProtein}
|
|
412
|
+
containsLocations={containsLocations}
|
|
413
|
+
radius={annotationRadius}
|
|
414
|
+
annotationHeight={annotationHeight}
|
|
415
|
+
{...annotationProps}
|
|
416
|
+
{...(perAnnotationProps && perAnnotationProps(annotation))}
|
|
417
|
+
/>
|
|
418
|
+
</g>
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
return (
|
|
422
|
+
<React.Fragment>
|
|
423
|
+
{getInner({
|
|
424
|
+
startAngle,
|
|
425
|
+
endAngle,
|
|
426
|
+
totalAngle,
|
|
427
|
+
centerAngle,
|
|
428
|
+
containsLocations: !!locationAngles
|
|
429
|
+
})}
|
|
430
|
+
{locationAngles && locationAngles.map(getInner)}
|
|
431
|
+
</React.Fragment>
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const DrawAnnotation = withHover(DrawAnnotationInner);
|
|
436
|
+
|
|
437
|
+
export const avoidOverlapWith = {
|
|
438
|
+
"data-avoid": ".topLevelLabelGroup",
|
|
439
|
+
"data-avoid-backup": ".veLabel.veAnnotationHovered"
|
|
440
|
+
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import Path from "paths-js/path";
|
|
2
|
+
function polarToSpecialCartesian(radius, angleInRadians) {
|
|
3
|
+
//the 0 angle returns the 0,1 point on the unit circle instead of the 1,0 point like normal
|
|
4
|
+
return {
|
|
5
|
+
x: radius * Math.cos(angleInRadians - Math.PI / 2),
|
|
6
|
+
y: radius * Math.sin(angleInRadians - Math.PI / 2)
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
const stickOutThisMuch = 0.03;
|
|
10
|
+
|
|
11
|
+
// draws a directed piece of the pie with an arrowhead, starts at 0 angle, only draws in one direction (use transforms to move it around the )
|
|
12
|
+
export default function drawDirectedPiePiece({
|
|
13
|
+
tailThickness = 0.6,
|
|
14
|
+
// arrowheadLength = 1,
|
|
15
|
+
radius,
|
|
16
|
+
arrowheadType,
|
|
17
|
+
overlapsSelf,
|
|
18
|
+
annotationHeight,
|
|
19
|
+
totalAngle,
|
|
20
|
+
hasLabel,
|
|
21
|
+
labelNeedsFlip,
|
|
22
|
+
returnTextPath
|
|
23
|
+
}) {
|
|
24
|
+
const tailHeight = annotationHeight * tailThickness;
|
|
25
|
+
|
|
26
|
+
const arrowheadOuterRadius = radius + annotationHeight / 2;
|
|
27
|
+
const arrowheadInnerRadius = radius - annotationHeight / 2;
|
|
28
|
+
const tailOuterRadius = radius + tailHeight / 2;
|
|
29
|
+
const tailInnerRadius = radius - tailHeight / 2;
|
|
30
|
+
|
|
31
|
+
// var arrowheadAngle = totalAngle / 2
|
|
32
|
+
let arrowheadAngle = 80 / radius / (Math.PI * 2);
|
|
33
|
+
|
|
34
|
+
if (totalAngle < arrowheadAngle) {
|
|
35
|
+
//set arrowhead length to the angle in radians length
|
|
36
|
+
arrowheadAngle = totalAngle;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (arrowheadType === "NONE") arrowheadAngle = 0;
|
|
40
|
+
const arcAngle = totalAngle - arrowheadAngle;
|
|
41
|
+
|
|
42
|
+
//the main points we need to draw the arrow and in the order we draw them in:
|
|
43
|
+
const arrowheadPoint = polarToSpecialCartesian(radius, 0);
|
|
44
|
+
|
|
45
|
+
const arrowheadBottom = polarToSpecialCartesian(
|
|
46
|
+
arrowheadInnerRadius,
|
|
47
|
+
arrowheadAngle
|
|
48
|
+
);
|
|
49
|
+
const arcLeftBottom = polarToSpecialCartesian(
|
|
50
|
+
tailInnerRadius,
|
|
51
|
+
arrowheadAngle
|
|
52
|
+
);
|
|
53
|
+
const arcRightBottom = polarToSpecialCartesian(tailInnerRadius, totalAngle);
|
|
54
|
+
const arcRightTop = polarToSpecialCartesian(tailOuterRadius, totalAngle);
|
|
55
|
+
const arcRightMiddle = polarToSpecialCartesian(radius, totalAngle);
|
|
56
|
+
const arcRightMiddleOuter = polarToSpecialCartesian(
|
|
57
|
+
radius,
|
|
58
|
+
totalAngle + stickOutThisMuch
|
|
59
|
+
);
|
|
60
|
+
const arcLeftTop = polarToSpecialCartesian(tailOuterRadius, arrowheadAngle);
|
|
61
|
+
const arrowheadTop = polarToSpecialCartesian(
|
|
62
|
+
arrowheadOuterRadius,
|
|
63
|
+
arrowheadAngle
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const largeArcFlag = arcAngle > Math.PI ? 1 : 0;
|
|
67
|
+
let path = Path().moveto(arrowheadPoint.x, arrowheadPoint.y);
|
|
68
|
+
|
|
69
|
+
if (overlapsSelf) {
|
|
70
|
+
const arrowheadPointInner = polarToSpecialCartesian(
|
|
71
|
+
radius,
|
|
72
|
+
-stickOutThisMuch
|
|
73
|
+
);
|
|
74
|
+
path = path
|
|
75
|
+
.lineto(arrowheadPointInner.x, arrowheadPointInner.y)
|
|
76
|
+
.lineto(arrowheadPoint.x, arrowheadPoint.y);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
path = path
|
|
80
|
+
.lineto(arrowheadBottom.x, arrowheadBottom.y)
|
|
81
|
+
.lineto(arcLeftBottom.x, arcLeftBottom.y)
|
|
82
|
+
.arc({
|
|
83
|
+
rx: tailInnerRadius,
|
|
84
|
+
ry: tailInnerRadius,
|
|
85
|
+
xrot: 0,
|
|
86
|
+
largeArcFlag,
|
|
87
|
+
sweepFlag: 1,
|
|
88
|
+
x: arcRightBottom.x,
|
|
89
|
+
y: arcRightBottom.y
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (overlapsSelf) {
|
|
93
|
+
path = path
|
|
94
|
+
.lineto(arcRightMiddle.x, arcRightMiddle.y)
|
|
95
|
+
.lineto(arcRightMiddleOuter.x, arcRightMiddleOuter.y)
|
|
96
|
+
.lineto(arcRightMiddle.x, arcRightMiddle.y);
|
|
97
|
+
}
|
|
98
|
+
let textPath;
|
|
99
|
+
if (returnTextPath && hasLabel) {
|
|
100
|
+
if (labelNeedsFlip) {
|
|
101
|
+
const arcLeftTop = polarToSpecialCartesian(tailOuterRadius, 0);
|
|
102
|
+
textPath = Path().moveto(arcRightTop.x, arcRightTop.y).arc({
|
|
103
|
+
rx: tailOuterRadius,
|
|
104
|
+
ry: tailOuterRadius,
|
|
105
|
+
xrot: 0,
|
|
106
|
+
largeArcFlag,
|
|
107
|
+
sweepFlag: 0,
|
|
108
|
+
x: arcLeftTop.x,
|
|
109
|
+
y: arcLeftTop.y
|
|
110
|
+
});
|
|
111
|
+
} else {
|
|
112
|
+
const arcLeftBottom = polarToSpecialCartesian(tailInnerRadius, 0);
|
|
113
|
+
textPath = Path().moveto(arcLeftBottom.x, arcLeftBottom.y).arc({
|
|
114
|
+
rx: tailInnerRadius,
|
|
115
|
+
ry: tailInnerRadius,
|
|
116
|
+
xrot: 0,
|
|
117
|
+
largeArcFlag,
|
|
118
|
+
sweepFlag: 1,
|
|
119
|
+
x: arcRightBottom.x,
|
|
120
|
+
y: arcRightBottom.y
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
path = path
|
|
125
|
+
|
|
126
|
+
.lineto(arcRightTop.x, arcRightTop.y)
|
|
127
|
+
.arc({
|
|
128
|
+
rx: tailOuterRadius,
|
|
129
|
+
ry: tailOuterRadius,
|
|
130
|
+
xrot: 0,
|
|
131
|
+
largeArcFlag,
|
|
132
|
+
sweepFlag: 0,
|
|
133
|
+
x: arcLeftTop.x,
|
|
134
|
+
y: arcLeftTop.y
|
|
135
|
+
})
|
|
136
|
+
.lineto(arrowheadTop.x, arrowheadTop.y)
|
|
137
|
+
.closepath();
|
|
138
|
+
if (returnTextPath) {
|
|
139
|
+
return [path, textPath];
|
|
140
|
+
}
|
|
141
|
+
return path;
|
|
142
|
+
}
|
package/editTool.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Icon } from "@blueprintjs/core";
|
|
3
|
+
import ToolbarItem from "./ToolbarItem";
|
|
4
|
+
import { connectToEditor } from "../withEditorProps";
|
|
5
|
+
|
|
6
|
+
export default connectToEditor(editorState => {
|
|
7
|
+
return {
|
|
8
|
+
readOnly: editorState.readOnly
|
|
9
|
+
};
|
|
10
|
+
})(props => {
|
|
11
|
+
const { toolbarItemProps, readOnly, disableSetReadOnly } = props;
|
|
12
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
13
|
+
const readOnlyTooltip = ({ readOnly, disableSetReadOnly }) => {
|
|
14
|
+
if (isLoading) {
|
|
15
|
+
return "Loading...";
|
|
16
|
+
} else if (disableSetReadOnly) {
|
|
17
|
+
return "You do not have permission to edit locks on this sequence";
|
|
18
|
+
}
|
|
19
|
+
return readOnly ? "Click to enable editing" : "Click to disable editing";
|
|
20
|
+
};
|
|
21
|
+
return (
|
|
22
|
+
<ToolbarItem
|
|
23
|
+
{...{
|
|
24
|
+
disabled: isLoading || disableSetReadOnly,
|
|
25
|
+
Icon: <Icon icon={readOnly ? "lock" : "unlock"} />,
|
|
26
|
+
onIconClick: () =>
|
|
27
|
+
handleReadOnlyChange(!readOnly, { ...props, setIsLoading }),
|
|
28
|
+
tooltip: readOnlyTooltip({ readOnly, disableSetReadOnly }),
|
|
29
|
+
...toolbarItemProps
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export async function handleReadOnlyChange(
|
|
36
|
+
newVal,
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
38
|
+
{ beforeReadOnlyChange, updateReadOnlyMode, setIsLoading = () => {} }
|
|
39
|
+
) {
|
|
40
|
+
if (beforeReadOnlyChange) {
|
|
41
|
+
setIsLoading(true);
|
|
42
|
+
const shouldChange = await beforeReadOnlyChange(newVal);
|
|
43
|
+
setIsLoading(false);
|
|
44
|
+
if (shouldChange === false) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
updateReadOnlyMode(newVal);
|
|
49
|
+
}
|