diff options
author | bobzel <zzzman@gmail.com> | 2023-11-01 23:54:49 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2023-11-01 23:54:49 -0400 |
commit | 84c15417f2247fc650a9f7b2c959479519bd3ebb (patch) | |
tree | f97f9f34ed0a1e65394f7b9e3818a9075b3a64f7 /src | |
parent | 58213b0201ea0191f06f42beac9c3a17ebfc98ea (diff) |
fixes to snapping lines when dragging/resizing (lines are created for doc not being dragged, snapping lines are created for documents in groups). cleanup of pres path code.
Diffstat (limited to 'src')
-rw-r--r-- | src/Utils.ts | 2 | ||||
-rw-r--r-- | src/client/util/DragManager.ts | 22 | ||||
-rw-r--r-- | src/client/util/SnappingManager.ts | 23 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 9 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 98 | ||||
-rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 46 |
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; |