aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Utils.ts2
-rw-r--r--src/client/util/DragManager.ts22
-rw-r--r--src/client/util/SnappingManager.ts23
-rw-r--r--src/client/views/DocumentDecorations.tsx9
-rw-r--r--src/client/views/MainView.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx98
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx3
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx46
8 files changed, 92 insertions, 114 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index 34419f665..330ca59f9 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -758,7 +758,7 @@ export function DashColor(color: string) {
}
export function lightOrDark(color: any) {
- if (color === 'transparent') return Colors.DARK_GRAY;
+ if (color === 'transparent' || !color) return Colors.DARK_GRAY;
if (color.startsWith?.('linear')) return Colors.BLACK;
const nonAlphaColor = color.startsWith('#') ? (color as string).substring(0, 7) : color.startsWith('rgba') ? color.replace(/,.[^,]*\)/, ')').replace('rgba', 'rgb') : color;
const col = DashColor(nonAlphaColor).rgb();
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4f30e92ce..ea13eaa5b 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -191,13 +191,6 @@ export namespace DragManager {
// drag a document and drop it (or make an embed/copy on drop)
export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions, onDropCompleted?: (e?: DragCompleteEvent) => any) {
- dragData.draggedViews.forEach(
- action(view => {
- const ffview = view.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
- ffview && (ffview.GroupChildDrag = BoolCast(ffview.Document._isGroup));
- ffview?.setupDragLines(false);
- })
- );
const addAudioTag = (dropDoc: any) => {
dropDoc && !dropDoc.author_date && (dropDoc.author_date = new DateField());
dropDoc instanceof Doc && DocUtils.MakeLinkToActiveAudio(() => dropDoc);
@@ -205,14 +198,7 @@ export namespace DragManager {
};
const finishDrag = async (e: DragCompleteEvent) => {
const docDragData = e.docDragData;
- setTimeout(() =>
- dragData.draggedViews.forEach(
- action(view => {
- const ffview = view.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
- ffview && (ffview.GroupChildDrag = false);
- })
- )
- );
+ setTimeout(() => dragData.draggedViews.forEach(view => view.props.CollectionFreeFormDocumentView?.().dragEnding()));
onDropCompleted?.(e); // glr: optional additional function to be called - in this case with presentation trails
if (docDragData && !docDragData.droppedDocuments.length) {
docDragData.dropAction = dragData.userDropAction || dragData.dropAction;
@@ -248,6 +234,7 @@ export namespace DragManager {
};
dragData.draggedDocuments.map(d => d.dragFactory); // does this help? trying to make sure the dragFactory Doc is loaded
StartDrag(eles, dragData, downX, downY, options, finishDrag);
+ dragData.draggedViews.forEach(view => view.props.CollectionFreeFormDocumentView?.().dragStarting());
return true;
}
@@ -281,9 +268,6 @@ export namespace DragManager {
StartDrag(ele, dragData, downX, downY, options, undefined, 'Drag Column');
}
- export function SetSnapLines(horizLines: number[], vertLines: number[]) {
- SnappingManager.setSnapLines(horizLines, vertLines);
- }
export function snapDragAspect(dragPt: number[], snapAspect: number) {
let closest = Utils.SNAP_THRESHOLD;
let near = dragPt;
@@ -491,11 +475,11 @@ export namespace DragManager {
};
const cleanupDrag = action((undo: boolean) => {
+ (dragData as DocumentDragData).draggedViews?.forEach(view => view.props.CollectionFreeFormDocumentView?.().dragEnding());
hideDragShowOriginalElements(false);
document.removeEventListener('pointermove', moveHandler, true);
document.removeEventListener('pointerup', upHandler, true);
SnappingManager.SetIsDragging(false);
- SnappingManager.clearSnapLines();
if (batch.end() && undo) UndoManager.Undo();
docsBeingDragged.length = 0;
});
diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts
index ed9819fc0..3cb41ab4d 100644
--- a/src/client/util/SnappingManager.ts
+++ b/src/client/util/SnappingManager.ts
@@ -1,19 +1,19 @@
import { observable, action, runInAction } from 'mobx';
-import { computedFn } from 'mobx-utils';
import { Doc } from '../../fields/Doc';
export namespace SnappingManager {
class Manager {
@observable IsDragging: boolean = false;
+ @observable IsResizing: Doc | undefined;
@observable public horizSnapLines: number[] = [];
@observable public vertSnapLines: number[] = [];
@action public clearSnapLines() {
this.vertSnapLines = [];
this.horizSnapLines = [];
}
- @action public setSnapLines(horizLines: number[], vertLines: number[]) {
- this.horizSnapLines = horizLines;
- this.vertSnapLines = vertLines;
+ @action public addSnapLines(horizLines: number[], vertLines: number[]) {
+ this.horizSnapLines.push(...horizLines);
+ this.vertSnapLines.push(...vertLines);
}
}
@@ -22,8 +22,8 @@ export namespace SnappingManager {
export function clearSnapLines() {
manager.clearSnapLines();
}
- export function setSnapLines(horizLines: number[], vertLines: number[]) {
- manager.setSnapLines(horizLines, vertLines);
+ export function addSnapLines(horizLines: number[], vertLines: number[]) {
+ manager.addSnapLines(horizLines, vertLines);
}
export function horizSnapLines() {
return manager.horizSnapLines;
@@ -35,14 +35,13 @@ export namespace SnappingManager {
export function SetIsDragging(dragging: boolean) {
runInAction(() => (manager.IsDragging = dragging));
}
+ export function SetIsResizing(doc: Doc | undefined) {
+ runInAction(() => (manager.IsResizing = doc));
+ }
export function GetIsDragging() {
return manager.IsDragging;
}
-
- export function SetShowSnapLines(show: boolean) {
- runInAction(() => (Doc.UserDoc().freeform_snapLines = show));
- }
- export function GetShowSnapLines() {
- return Doc.UserDoc().freeform_snapLines;
+ export function GetIsResizing() {
+ return manager.IsResizing;
}
}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 65f7c7a70..5a145e94a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -63,7 +63,6 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
@observable public pullColor: string = 'white';
@observable private _isRotating: boolean = false;
@observable private _isRounding: boolean = false;
- @observable private _isResizing: boolean = false;
@observable private showLayoutAcl: boolean = false;
constructor(props: any) {
@@ -475,7 +474,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
@action
onPointerDown = (e: React.PointerEvent): void => {
- this._isResizing = true;
+ SnappingManager.SetIsResizing(SelectionManager.Docs().lastElement());
setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
DocumentView.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
this._resizeHdlId = e.currentTarget.className;
@@ -491,7 +490,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
ffview && ffviewSet.add(ffview);
this._dragHeights.set(docView.layoutDoc, { start: NumCast(docView.rootDoc._height), lowest: NumCast(docView.rootDoc._height) });
});
- Array.from(ffviewSet).map(ffview => ffview.setupDragLines(false));
+ Array.from(ffviewSet).map(ffview => ffview.dragStarting(false, false));
};
onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => {
@@ -686,7 +685,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
@action
onPointerUp = (e: PointerEvent): void => {
- this._isResizing = false;
+ SnappingManager.SetIsResizing(undefined);
this._resizeHdlId = '';
DocumentView.Interacting = false;
this._resizeUndo?.end();
@@ -774,7 +773,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
var shareSymbolIcon = ReverseHierarchyMap.get(shareMode)?.image;
// hide the decorations if the parent chooses to hide it or if the document itself hides it
- const hideDecorations = this._isResizing || seldocview.props.hideDecorations || seldocview.rootDoc.layout_hideDecorations;
+ const hideDecorations = SnappingManager.GetIsResizing() || seldocview.props.hideDecorations || seldocview.rootDoc.layout_hideDecorations;
const hideResizers =
![AclAdmin, AclEdit, AclAugment].includes(GetEffectiveAcl(seldocview.rootDoc)) || hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.layout_hideResizeHandles || this._isRounding || this._isRotating;
const hideTitle = this._showNothing || hideDecorations || seldocview.props.hideDecorationTitle || seldocview.rootDoc.layout_hideDecorationTitle || this._isRounding || this._isRotating;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 0a3389fc2..da5e4f966 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -918,7 +918,8 @@ export class MainView extends React.Component {
}
@computed get snapLines() {
SnappingManager.GetIsDragging();
- const dragged = DragManager.docsBeingDragged.lastElement();
+ SnappingManager.GetIsResizing();
+ const dragged = DragManager.docsBeingDragged.lastElement() ?? SelectionManager.Docs().lastElement();
const dragPar = dragged ? DocumentManager.Instance.getDocumentView(dragged)?.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView : undefined;
return !dragPar?.rootDoc.freeform_snapLines ? null : (
<div className="mainView-snapLines">
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a8b743896..0c3033579 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -16,7 +16,7 @@ import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } fro
import { ImageField } from '../../../../fields/URLField';
import { TraceMobx } from '../../../../fields/util';
import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
-import { aggregateBounds, DashColor, emptyFunction, intersectRect, lightOrDark, returnFalse, returnNone, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils';
+import { aggregateBounds, DashColor, emptyFunction, intersectRect, lightOrDark, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils';
import { CognitiveServices } from '../../../cognitive_services/CognitiveServices';
import { Docs, DocUtils } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
@@ -118,8 +118,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@observable.shallow _layoutElements: ViewDefResult[] = []; // shallow because some layout items (eg pivot labels) are just generated 'divs' and can't be frozen as observables
@observable _panZoomTransition: number = 0; // sets the pan/zoom transform ease time- used by nudge(), focus() etc to smoothly zoom/pan. set to 0 to use document's transition time or default of 0
- @observable _hLines: number[] | undefined;
- @observable _vLines: number[] | undefined;
@observable _firstRender = false; // this turns off rendering of the collection's content so that there's instant feedback when a tab is switched of what content will be shown. could be used for performance improvement
@observable _showAnimTimeline = false;
@observable _clusterSets: Doc[][] = [];
@@ -463,9 +461,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return false;
};
- onExternalDrop = (e: React.DragEvent) => {
- return (pt => super.onExternalDrop(e, { x: pt[0], y: pt[1] }))(this.getTransform().transformPoint(e.pageX, e.pageY));
- };
+ onExternalDrop = (e: React.DragEvent) => (([x, y]) => super.onExternalDrop(e, { x, y }))(this.getTransform().transformPoint(e.pageX, e.pageY));
pickCluster(probe: number[]) {
return this.childLayoutPairs
@@ -1820,9 +1816,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const viewctrls = ContextMenu.Instance.findByDescription('UI Controls...');
const viewCtrlItems = viewctrls && 'subitems' in viewctrls ? viewctrls.subitems : [];
- !Doc.noviceMode
- ? viewCtrlItems.push({ description: (SnappingManager.GetShowSnapLines() ? 'Hide' : 'Show') + ' Snap Lines', event: () => SnappingManager.SetShowSnapLines(!SnappingManager.GetShowSnapLines()), icon: 'compress-arrows-alt' })
- : null;
!Doc.noviceMode ? viewCtrlItems.push({ description: (this.Document._freeform_useClusters ? 'Hide' : 'Show') + ' Clusters', event: () => this.updateClusters(!this.Document._freeform_useClusters), icon: 'braille' }) : null;
!viewctrls && ContextMenu.Instance.addItem({ description: 'UI Controls...', subitems: viewCtrlItems, icon: 'eye' });
@@ -1858,23 +1851,38 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
@action
- setupDragLines = (snapToDraggedDoc: boolean = false) => {
+ dragEnding = () => {
+ this.GroupChildDrag = false;
+ SnappingManager.clearSnapLines();
+ };
+ @action
+ dragStarting = (snapToDraggedDoc: boolean = false, showGroupDragTarget: boolean, visited = new Set<Doc>()) => {
+ if (visited.has(this.rootDoc)) return;
+ visited.add(this.rootDoc);
+ showGroupDragTarget && (this.GroupChildDrag = BoolCast(this.Document._isGroup));
+ if (this.rootDoc._isGroup && this.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView) {
+ this.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView.dragStarting(snapToDraggedDoc, false, visited);
+ }
const activeDocs = this.getActiveDocuments();
const size = this.getTransform().transformDirection(this.props.PanelWidth(), this.props.PanelHeight());
const selRect = { left: this.panX() - size[0] / 2, top: this.panY() - size[1] / 2, width: size[0], height: size[1] };
const docDims = (doc: Doc) => ({ left: NumCast(doc.x), top: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) });
const isDocInView = (doc: Doc, rect: { left: number; top: number; width: number; height: number }) => intersectRect(docDims(doc), rect);
- const otherBounds = { left: this.panX(), top: this.panY(), width: Math.abs(size[0]), height: Math.abs(size[1]) };
- let snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to
- !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect))); // if not, see if there are background docs to snap to
- !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z !== undefined && isDocInView(doc, otherBounds))); // if not, then why not snap to floating docs
+ const snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to
+ activeDocs.forEach(
+ doc =>
+ doc._isGroup &&
+ SnappingManager.GetIsResizing() !== doc &&
+ !DragManager.docsBeingDragged.includes(doc) &&
+ (DocumentManager.Instance.getDocumentView(doc)?.ComponentView as CollectionFreeFormView)?.dragStarting(snapToDraggedDoc, false, visited)
+ );
const horizLines: number[] = [];
const vertLines: number[] = [];
const invXf = this.getTransform().inverse();
snappableDocs
- .filter(doc => snapToDraggedDoc || !DragManager.docsBeingDragged.includes(Cast(doc.rootDocument, Doc, null) || doc))
+ .filter(doc => !doc._isGroup && (snapToDraggedDoc || (SnappingManager.GetIsResizing() !== doc && !DragManager.docsBeingDragged.includes(doc))))
.forEach(doc => {
const { left, top, width, height } = docDims(doc);
const topLeftInScreen = invXf.transformPoint(left, top);
@@ -1883,7 +1891,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
horizLines.push(topLeftInScreen[1], topLeftInScreen[1] + docSize[1] / 2, topLeftInScreen[1] + docSize[1]); // horiz center line
vertLines.push(topLeftInScreen[0], topLeftInScreen[0] + docSize[0] / 2, topLeftInScreen[0] + docSize[0]); // right line
});
- DragManager.SetSnapLines(horizLines, vertLines);
+ SnappingManager.addSnapLines(horizLines, vertLines);
};
incrementalRendering = () => this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id])).length !== 0;
@@ -1913,7 +1921,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
);
}
- showPresPaths = () => (CollectionFreeFormView.ShowPresPaths ? PresBox.Instance.getPaths(this.rootDoc) : null);
brushedView = () => this._brushedView;
gridColor = () =>
DashColor(lightOrDark(this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor)))
@@ -1921,7 +1928,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
.toString();
@computed get marqueeView() {
TraceMobx();
- return (
+ return this._firstRender ? (
+ this.placeholder
+ ) : (
<MarqueeView
{...this.props}
ref={this._marqueeViewRef}
@@ -1966,7 +1975,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
brushedView={this.brushedView}
isAnnotationOverlay={this.isAnnotationOverlay}
transform={this.contentTransform}
- presPaths={this.showPresPaths}
transition={this._panZoomTransition ? `transform ${this._panZoomTransition}ms` : Cast(this.layoutDoc._viewTransition, 'string', Cast(this.props.DocumentView?.()?.rootDoc._viewTransition, 'string', null))}
viewDefDivClick={this.props.viewDefDivClick}>
{this.children}
@@ -2028,7 +2036,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onClick={this.onClick}
onPointerDown={this.onPointerDown}
onPointerMove={this.onCursorMove}
- onDrop={this.onExternalDrop.bind(this)}
+ onDrop={this.onExternalDrop}
onDragOver={e => e.preventDefault()}
onContextMenu={this.onContextMenu}
style={{
@@ -2065,18 +2073,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
</div>
) : (
<>
- {this._firstRender ? this.placeholder : this.marqueeView}
+ {this.marqueeView}
{this.props.noOverlay ? null : <CollectionFreeFormOverlayView elements={this.elementFunc} />}
-
- <div className="snapLines" style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', pointerEvents: 'none' }}>
- <svg style={{ width: '100%', height: '100%' }}>
- {(this._hLines ?? [])
- .map(l => <line x1="0" y1={l} x2="1000" y2={l} stroke="black" />) //
- .concat((this._vLines ?? []).map(l => <line y1="0" x1={l} y2="1000" x2={l} stroke="black" />)) ?? []}
- </svg>
- </div>
-
- {this.GroupChildDrag ? <div className="collectionFreeForm-groupDropper" /> : null}
+ {!this.GroupChildDrag ? null : <div className="collectionFreeForm-groupDropper" />}
</>
)}
</div>
@@ -2104,7 +2103,6 @@ interface CollectionFreeFormViewPannableContentsProps {
children?: React.ReactNode | undefined;
transition?: string;
isAnnotationOverlay: boolean | undefined;
- presPaths: () => JSX.Element | null;
transform: () => string;
brushedView: () => { panX: number; panY: number; width: number; height: number } | undefined;
}
@@ -2112,41 +2110,21 @@ interface CollectionFreeFormViewPannableContentsProps {
@observer
class CollectionFreeFormViewPannableContents extends React.Component<CollectionFreeFormViewPannableContentsProps> {
@computed get presPaths() {
- return !this.props.presPaths() ? null : (
- <>
- <div className="presPathLabels">{PresBox.Instance?.orderedPathLabels(this.props.rootDoc)}</div>
- <svg key="svg" className="presPaths">
- <defs>
- <marker id="markerSquare" markerWidth="3" markerHeight="3" refX="1.5" refY="1.5" orient="auto" overflow="visible">
- <rect x="0" y="0" width="3" height="3" stroke="#69a6db" strokeWidth="1" fill="white" fillOpacity="0.8" />
- </marker>
- <marker id="markerSquareFilled" markerWidth="3" markerHeight="3" refX="1.5" refY="1.5" orient="auto" overflow="visible">
- <rect x="0" y="0" width="3" height="3" stroke="#69a6db" strokeWidth="1" fill="#69a6db" />
- </marker>
- <marker id="markerArrow" markerWidth="3" markerHeight="3" refX="2" refY="4" orient="auto" overflow="visible">
- <path d="M2,2 L2,6 L6,4 L2,2 Z" stroke="#69a6db" strokeLinejoin="round" strokeWidth="1" fill="white" fillOpacity="0.8" />
- </marker>
- </defs>
- {this.props.presPaths()}
- </svg>
- </>
- );
+ return CollectionFreeFormView.ShowPresPaths ? PresBox.Instance.pathLines(this.props.rootDoc) : null;
}
// rectangle highlight used when following trail/link to a region of a collection that isn't a document
- @computed get brushedView() {
- const brushedView = this.props.brushedView();
- return !brushedView ? null : (
+ showViewport = (viewport: { panX: number; panY: number; width: number; height: number } | undefined) =>
+ !viewport ? null : (
<div
className="collectionFreeFormView-brushView"
style={{
- transform: `translate(${brushedView.panX}px, ${brushedView.panY}px)`,
- width: brushedView.width,
- height: brushedView.height,
- border: `orange solid ${brushedView.width * 0.005}px`,
+ transform: `translate(${viewport.panX}px, ${viewport.panY}px)`,
+ width: viewport.width,
+ height: viewport.height,
+ border: `orange solid ${viewport.width * 0.005}px`,
}}
/>
);
- }
render() {
return (
@@ -2165,7 +2143,7 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
}}>
{this.props.children}
{this.presPaths}
- {this.brushedView}
+ {this.showViewport(this.props.brushedView())}
</div>
);
}
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 9f7ebc5d9..f9afe4d53 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -182,6 +182,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
}
};
+ dragEnding = () => this.props.CollectionFreeFormView?.dragEnding();
+ dragStarting = () => this.props.CollectionFreeFormView?.dragStarting(false, true);
+
nudge = (x: number, y: number) => {
this.props.Document.x = NumCast(this.props.Document.x) + x;
this.props.Document.y = NumCast(this.props.Document.y) + y;
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 54249a975..05810b63a 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -1384,24 +1384,38 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
});
return (
- <polyline
- points={pathPoints}
- style={{
- opacity: 1,
- stroke: '#69a6db',
- strokeWidth: 5,
- strokeDasharray: '10 5',
- boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.25)',
- }}
- fill="none"
- markerStart="url(#markerArrow)"
- markerMid="url(#markerSquare)"
- markerEnd="url(#markerSquareFilled)"
- />
+ <>
+ <div className="presPathLabels">{PresBox.Instance?.orderedPathLabels(collection)}</div>
+ <svg key="svg" className="presPaths">
+ <defs>
+ <marker id="markerSquare" markerWidth="3" markerHeight="3" refX="1.5" refY="1.5" orient="auto" overflow="visible">
+ <rect x="0" y="0" width="3" height="3" stroke="#69a6db" strokeWidth="1" fill="white" fillOpacity="0.8" />
+ </marker>
+ <marker id="markerSquareFilled" markerWidth="3" markerHeight="3" refX="1.5" refY="1.5" orient="auto" overflow="visible">
+ <rect x="0" y="0" width="3" height="3" stroke="#69a6db" strokeWidth="1" fill="#69a6db" />
+ </marker>
+ <marker id="markerArrow" markerWidth="3" markerHeight="3" refX="2" refY="4" orient="auto" overflow="visible">
+ <path d="M2,2 L2,6 L6,4 L2,2 Z" stroke="#69a6db" strokeLinejoin="round" strokeWidth="1" fill="white" fillOpacity="0.8" />
+ </marker>
+ </defs>
+ <polyline
+ points={pathPoints}
+ style={{
+ opacity: 1,
+ stroke: '#69a6db',
+ strokeWidth: 5,
+ strokeDasharray: '10 5',
+ boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.25)',
+ }}
+ fill="none"
+ markerStart="url(#markerArrow)"
+ markerMid="url(#markerSquare)"
+ markerEnd="url(#markerSquareFilled)"
+ />
+ </svg>
+ </>
);
};
- getPaths = (collection: Doc) => this.pathLines(collection); // needs to be smarter and figure out the paths to draw for this specific collection. or better yet, draw everything in an overlay layer instad of within a collection
-
// Converts seconds to ms and updates presentation_transition
public static SetTransitionTime = (number: String, setter: (timeInMS: number) => void, change?: number) => {
let timeInMS = Number(number) * 1000;