diff options
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
5 files changed, 96 insertions, 65 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index a8f5e6dd2..3b3e069d8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -2,14 +2,16 @@ import { action, computed, IReactionDisposer, observable, reaction } from "mobx" import { observer } from "mobx-react"; import { Doc } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; +import { List } from "../../../../fields/List"; import { NumCast, StrCast } from "../../../../fields/Types"; import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; -import { DocumentType } from "../../../documents/DocumentTypes"; +import { LinkManager } from "../../../util/LinkManager"; import { SnappingManager } from "../../../util/SnappingManager"; import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); + export interface CollectionFreeFormLinkViewProps { A: DocumentView; B: DocumentView; @@ -40,8 +42,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo if (SnappingManager.GetIsDragging() || !A.ContentDiv || !B.ContentDiv) return; setTimeout(action(() => this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. - const acont = A.rootDoc.type === DocumentType.LINK ? A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; - const bcont = B.rootDoc.type === DocumentType.LINK ? B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; + const acont = A.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); + const bcont = B.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); const adiv = acont.length ? acont[0] : A.ContentDiv; const bdiv = bcont.length ? bcont[0] : B.ContentDiv; const a = adiv.getBoundingClientRect(); @@ -66,8 +68,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo } else { const m = targetAhyperlink.getBoundingClientRect(); const mp = A.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); - linkDoc.anchor1_x = Math.min(1, mp[0] / A.props.PanelWidth()) * 100; - linkDoc.anchor1_y = Math.min(1, mp[1] / A.props.PanelHeight()) * 100; + const mpx = mp[0] / A.props.PanelWidth(); + const mpy = mp[1] / A.props.PanelHeight(); + if (mpx >= 0 && mpx <= 1) linkDoc.anchor1_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.anchor1_y = mpy * 100; } if (!targetBhyperlink) { if (linkDoc.linkAutoMove) { @@ -77,8 +81,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo } else { const m = targetBhyperlink.getBoundingClientRect(); const mp = B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5); - linkDoc.anchor2_x = Math.min(1, mp[0] / B.props.PanelWidth()) * 100; - linkDoc.anchor2_y = Math.min(1, mp[1] / B.props.PanelHeight()) * 100; + const mpx = mp[0] / B.props.PanelWidth(); + const mpy = mp[1] / B.props.PanelHeight(); + if (mpx >= 0 && mpx <= 1) linkDoc.anchor2_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.anchor2_y = mpy * 100; } } @@ -137,8 +143,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo if (!A.ContentDiv || !B.ContentDiv || !LinkDocs.length) return undefined; const acont = A.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); const bcont = B.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); - const adiv = (acont.length ? acont[0] : A.ContentDiv); - const bdiv = (bcont.length ? bcont[0] : B.ContentDiv); + const adiv = acont.length ? acont[0] : A.ContentDiv; + const bdiv = bcont.length ? bcont[0] : B.ContentDiv; for (let apdiv = adiv; apdiv; apdiv = apdiv.parentElement as any) if ((apdiv as any).hidden) return; for (let bpdiv = bdiv; bpdiv; bpdiv = bpdiv.parentElement as any) if ((bpdiv as any).hidden) return; const a = adiv.getBoundingClientRect(); @@ -173,8 +179,14 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo render() { if (!this.renderData) return (null); const { a, b, pt1norm, pt2norm, aActive, bActive, textX, textY, pt1, pt2 } = this.renderData; + LinkManager.currentLink = this.props.LinkDocs[0]; + const linkRelationship = StrCast(LinkManager.currentLink?.linkRelationship); //get string representing relationship + const linkRelationshipList = Doc.UserDoc().linkRelationshipList as List<string>; + const linkColorList = Doc.UserDoc().linkColorList as List<string>; + //access stroke color using index of the relationship in the color list (default black) + const strokeColor = linkRelationshipList.indexOf(linkRelationship) === -1 ? "black" : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; return !a.width || !b.width || ((!this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<> - <path className="collectionfreeformlinkview-linkLine" style={{ opacity: this._opacity, strokeDasharray: "2 2" }} + <path className="collectionfreeformlinkview-linkLine" style={{ opacity: this._opacity, strokeDasharray: "2 2", stroke: strokeColor }} d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} /> {textX === undefined ? (null) : <text className="collectionfreeformlinkview-linkText" x={textX} y={textY} onPointerDown={this.pointerDown} > {StrCast(this.props.LinkDocs[0].description)} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 5e0b31754..dacbb3508 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -1,29 +1,17 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; -import { Utils } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; -import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinksView.scss"; import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView"; import React = require("react"); -import { DocumentType } from "../../../documents/DocumentTypes"; @observer export class CollectionFreeFormLinksView extends React.Component { @computed get uniqueConnections() { - const connections = DocumentManager.Instance.LinkedDocumentViews - .filter(c => c.a.props.Document.type === DocumentType.LINK || c.b.props.Document.type === DocumentType.LINK) - .reduce((drawnPairs, connection) => { - const matchingPairs = drawnPairs.filter(pair => connection.a === pair.a && connection.b === pair.b); - matchingPairs.forEach(drawnPair => drawnPair.l.add(connection.l)); - if (!matchingPairs.length) drawnPairs.push({ a: connection.a, b: connection.b, l: new Set<Doc>([connection.l]) }); - return drawnPairs; - }, [] as { a: DocumentView, b: DocumentView, l: Set<Doc> }[]); - const set = new Map<Doc, { a: DocumentView, b: DocumentView, l: Doc[] }>(); - connections.map(c => !set.has(Array.from(c.l)[0]) && set.set(Array.from(c.l)[0], { a: c.a, b: c.b, l: Array.from(c.l) })); - return Array.from(set.values()).map(c => <CollectionFreeFormLinkView key={c.l[0][Id]} A={c.a} B={c.b} LinkDocs={c.l} />); + return Array.from(new Set(DocumentManager.Instance.LinkedDocumentViews)).map(c => + <CollectionFreeFormLinkView key={c.l[Id]} A={c.a} B={c.b} LinkDocs={[c.l]} /> + ); } render() { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d09d9b9d7..be0b078ec 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,6 +1,7 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import { computedFn } from "mobx-utils"; +import { DateField } from "../../../../fields/DateField"; import { Doc, HeightSym, Opt, StrListCast, WidthSym } from "../../../../fields/Doc"; import { collectionSchema, documentSchema } from "../../../../fields/documentSchemas"; import { Id } from "../../../../fields/FieldSymbols"; @@ -17,6 +18,7 @@ import { aggregateBounds, emptyFunction, intersectRect, returnFalse, setupMoveUp import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { DocServer } from "../../../DocServer"; import { Docs, DocUtils } from "../../../documents/Documents"; +import { DocumentType } from "../../../documents/DocumentTypes"; import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager, dropActionType } from "../../../util/DragManager"; @@ -48,8 +50,7 @@ import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCurso import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); -import { DocumentType } from "../../../documents/DocumentTypes"; -import { DateField } from "../../../../fields/DateField"; +import Color = require("color"); export const panZoomSchema = createSchema({ _panX: "number", @@ -74,6 +75,8 @@ export type collectionFreeformViewProps = { scaleField?: string; noOverlay?: boolean; // used to suppress docs in the overlay (z) layer (ie, for minimap since overlay doesn't scale) engineProps?: any; + dontRenderDocuments?: boolean; // used for annotation overlays which need to distribute documents into different freeformviews with different mixBlendModes depending on whether they are trnasparent or not. + // However, this screws up interactions since only the top layer gets events. so we render the freeformview a 3rd time with all documents in order to get interaction events (eg., marquee) but we don't actually want to display the documents. }; @observer @@ -115,7 +118,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @computed get views() { return this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele); } @computed get backgroundEvents() { return this.props.layerProvider?.(this.layoutDoc) === false && SnappingManager.GetIsDragging(); } - @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && (this.props.ContainingCollectionView?.isContentActive() || this.props.isContentActive()); } + @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && this.props.isContentActive(); } @computed get fitToContentVals() { return { bounds: { ...this.contentBounds, cx: (this.contentBounds.x + this.contentBounds.r) / 2, cy: (this.contentBounds.y + this.contentBounds.b) / 2 }, @@ -168,6 +171,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P getContainerTransform = () => this.cachedGetContainerTransform.copy(); getTransformOverlay = () => this.getContainerTransform().translate(1, 1); getActiveDocuments = () => this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout); + isAnyChildContentActive = () => this.props.isAnyChildContentActive(); addLiveTextBox = (newBox: Doc) => { FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed this.addDocument(newBox); @@ -179,7 +183,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P addDocument = (newBox: Doc | Doc[]) => { let retVal = false; if (newBox instanceof Doc) { - if (retVal = this.props.addDocument?.(newBox) || false) { + if (retVal = (this.props.addDocument?.(newBox) || false)) { this.bringToFront(newBox); this.updateCluster(newBox); } @@ -205,25 +209,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P return retVal; } - updateGroupBounds = () => { - if (!this.props.Document._isGroup) return; - const clist = this.childDocs.map(cd => ({ x: NumCast(cd.x), y: NumCast(cd.y), width: cd[WidthSym](), height: cd[HeightSym]() })); - const cbounds = aggregateBounds(clist, 0, 0); - const c = [NumCast(this.layoutDoc.x) + this.layoutDoc[WidthSym]() / 2, NumCast(this.layoutDoc.y) + this.layoutDoc[HeightSym]() / 2]; - const p = [NumCast(this.layoutDoc._panX), NumCast(this.layoutDoc._panY)]; - const pbounds = { - x: (cbounds.x - p[0]) * this.zoomScaling() + c[0], y: (cbounds.y - p[1]) * this.zoomScaling() + c[1], - r: (cbounds.r - p[0]) * this.zoomScaling() + c[0], b: (cbounds.b - p[1]) * this.zoomScaling() + c[1] - }; - - this.layoutDoc._width = (pbounds.r - pbounds.x); - this.layoutDoc._height = (pbounds.b - pbounds.y); - this.layoutDoc._panX = (cbounds.r + cbounds.x) / 2; - this.layoutDoc._panY = (cbounds.b + cbounds.y) / 2; - this.layoutDoc.x = pbounds.x; - this.layoutDoc.y = pbounds.y; - } - isCurrent(doc: Doc) { const dispTime = NumCast(doc._timecodeToShow, -1); const endTime = NumCast(doc._timecodeToHide, dispTime + 1.5); @@ -265,8 +250,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P !StrListCast(d._layerTags).includes(StyleLayers.Background) && (d._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : d._raiseWhenDragged) && (d.zIndex = zsorted.length + 1 + i); // bringToFront } - this.updateGroupBounds(); - (docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(docDragData.droppedDocuments); return true; } @@ -506,7 +489,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P const points = ge.points; const B = this.getTransform().transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height); const inkDoc = Docs.Create.InkDocument(ActiveInkColor(), CurrentUserUtils.SelectedTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), points, - { title: "ink stroke", x: B.x - Number(ActiveInkWidth()) / 2, y: B.y - Number(ActiveInkWidth()) / 2, _width: B.width + Number(ActiveInkWidth()), _height: B.height + Number(ActiveInkWidth()) }); + { title: "ink stroke", x: B.x - ActiveInkWidth() / 2, y: B.y - ActiveInkWidth() / 2, _width: B.width + ActiveInkWidth(), _height: B.height + ActiveInkWidth() }); this.addDocument(inkDoc); e.stopPropagation(); break; @@ -1031,7 +1014,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P docFilters={this.childDocFilters} docRangeFilters={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} - isContentActive={this.isAnnotationOverlay ? this.props.isContentActive : returnFalse} + isContentActive={returnFalse} isDocumentActive={this.props.childDocumentsActive ? this.props.isDocumentActive : this.isContentActive} focus={this.focusDocument} addDocTab={this.addDocTab} @@ -1048,7 +1031,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P freezeDimensions={this.props.childFreezeDimensions} dropAction={StrCast(this.props.Document.childDropAction) as dropActionType} bringToFront={this.bringToFront} - dontRegisterView={this.props.dontRegisterView} + showTitle={this.props.childShowTitle} + dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView} pointerEvents={this.backgroundActive || this.props.childPointerEvents ? "all" : (this.props.viewDefDivClick || (engine === "pass" && !this.props.isSelected(true))) ? "none" : undefined} jitterRotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0} @@ -1231,6 +1215,30 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P { fireImmediately: true, name: "doLayout" }); this._marqueeRef.current?.addEventListener("dashDragAutoScroll", this.onDragAutoScroll as any); + + this._disposers.groupBounds = reaction(() => { + if (this.props.Document._isGroup && this.childDocs.length === this.childDocList?.length) { + const clist = this.childDocs.map(cd => ({ x: NumCast(cd.x), y: NumCast(cd.y), width: cd[WidthSym](), height: cd[HeightSym]() })); + return aggregateBounds(clist, NumCast(this.layoutDoc._xPadding), NumCast(this.layoutDoc._yPadding)); + } + return undefined; + }, + (cbounds) => { + if (cbounds) { + const c = [NumCast(this.layoutDoc.x) + this.layoutDoc[WidthSym]() / 2, NumCast(this.layoutDoc.y) + this.layoutDoc[HeightSym]() / 2]; + const p = [NumCast(this.layoutDoc._panX), NumCast(this.layoutDoc._panY)]; + const pbounds = { + x: (cbounds.x - p[0]) * this.zoomScaling() + c[0], y: (cbounds.y - p[1]) * this.zoomScaling() + c[1], + r: (cbounds.r - p[0]) * this.zoomScaling() + c[0], b: (cbounds.b - p[1]) * this.zoomScaling() + c[1] + }; + this.layoutDoc._width = (pbounds.r - pbounds.x); + this.layoutDoc._height = (pbounds.b - pbounds.y); + this.layoutDoc._panX = (cbounds.r + cbounds.x) / 2; + this.layoutDoc._panY = (cbounds.b + cbounds.y) / 2; + this.layoutDoc.x = pbounds.x; + this.layoutDoc.y = pbounds.y; + } + }, { fireImmediately: true }); } componentWillUnmount() { @@ -1322,8 +1330,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P !options && ContextMenu.Instance.addItem({ description: "Options...", subitems: optionItems, icon: "eye" }); const mores = ContextMenu.Instance.findByDescription("More..."); const moreItems = mores && "subitems" in mores ? mores.subitems : []; - moreItems.push({ description: "Export collection", icon: "download", event: async () => Doc.Zip(this.props.Document) }); - moreItems.push({ description: "Import exported collection", icon: "upload", event: ({ x, y }) => this.importDocument(x, y) }); + if (!Doc.UserDoc().noviceMode) { + moreItems.push({ description: "Export collection", icon: "download", event: async () => Doc.Zip(this.props.Document) }); + moreItems.push({ description: "Import exported collection", icon: "upload", event: ({ x, y }) => this.importDocument(x, y) }); + } !mores && ContextMenu.Instance.addItem({ description: "More...", subitems: moreItems, icon: "eye" }); } @@ -1395,6 +1405,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P } chooseGridSpace = (gridSpace: number): number => { + if (!this.zoomScaling()) return 50; const divisions = this.props.PanelWidth() / this.zoomScaling() / gridSpace + 3; return divisions < 60 ? gridSpace : this.chooseGridSpace(gridSpace * 10); } @@ -1452,8 +1463,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} isAnnotationOverlay={this.isAnnotationOverlay}> - <div ref={this._marqueeRef}> - {this.layoutDoc["_backgroundGrid-show"] ? this.backgroundGrid : (null)} + <div ref={this._marqueeRef} style={{ display: this.props.dontRenderDocuments ? "none" : undefined }}> + {this.layoutDoc._backgroundGridShow ? this.backgroundGrid : (null)} <CollectionFreeFormViewPannableContents isAnnotationOverlay={this.isAnnotationOverlay} transform={this.contentTransform} @@ -1479,6 +1490,14 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P return wscale < hscale ? wscale : hscale; } + private groupDropDisposer?: DragManager.DragDropDisposer; + protected createGroupEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view + this.groupDropDisposer?.(); + if (ele) { + this.groupDropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc, this.onInternalPreDrop.bind(this)); + } + } + render() { TraceMobx(); const clientRect = this._mainCont?.getBoundingClientRect(); @@ -1522,7 +1541,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P </div>} {this.props.Document._isGroup && SnappingManager.GetIsDragging() && (this.ChildDrag || this.props.layerProvider?.(this.props.Document) === false) ? - <div className="collectionFreeForm-groupDropper" ref={this.createDashEventsTarget} style={{ + <div className="collectionFreeForm-groupDropper" ref={this.createGroupEventsTarget} style={{ width: this.ChildDrag ? "10000" : "100%", height: this.ChildDrag ? "10000" : "100%", left: this.ChildDrag ? "-5000" : 0, diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index d0243850f..81f6307d1 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -41,7 +41,7 @@ interface MarqueeViewProps { trySelectCluster: (addToSel: boolean) => boolean; nudge?: (x: number, y: number, nudgeTime?: number) => boolean; ungroup?: () => void; - setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void; + setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void; } @observer export class MarqueeView extends React.Component<SubCollectionViewProps & MarqueeViewProps> @@ -211,7 +211,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque // allow marquee if right click OR alt+left click if (e.button === 2 || (e.button === 0 && e.altKey)) { // if (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))) { - this.setPreviewCursor(e.clientX, e.clientY, true); + this.setPreviewCursor(e.clientX, e.clientY, true, false); // (!e.altKey) && e.stopPropagation(); // bcz: removed so that you can alt-click on button in a collection to switch link following behaviors. e.preventDefault(); // } @@ -284,8 +284,13 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque else if (document.getSelection()) { document.getSelection()?.empty(); } } - setPreviewCursor = action((x: number, y: number, drag: boolean) => { - if (drag) { + setPreviewCursor = action((x: number, y: number, drag: boolean, hide: boolean) => { + if (hide) { + this._downX = this._lastX = x; + this._downY = this._lastY = y; + this._commandExecuted = false; + PreviewCursor.Visible = false; + } else if (drag) { this._downX = this._lastX = x; this._downY = this._lastY = y; this._commandExecuted = false; @@ -313,7 +318,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque if (!(e.nativeEvent as any).marqueeHit) { (e.nativeEvent as any).marqueeHit = true; if (!this.props.trySelectCluster(e.shiftKey)) { - this.setPreviewCursor(e.clientX, e.clientY, false); + this.setPreviewCursor(e.clientX, e.clientY, false, false); } else e.stopPropagation(); } } @@ -443,8 +448,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque syntaxHighlight = (e: KeyboardEvent | React.PointerEvent | undefined) => { const selected = this.marqueeSelect(false); if (e instanceof KeyboardEvent ? e.key === "i" : true) { - const inks = selected.filter(s => s.proto?.type === DocumentType.INK); - const setDocs = selected.filter(s => s.proto?.type === DocumentType.RTF && s.color); + const inks = selected.filter(s => s.type === DocumentType.INK); + const setDocs = selected.filter(s => s.type === DocumentType.RTF && s.color); const sets = setDocs.map((sd) => Cast(sd.data, RichTextField)?.Text as string); const colors = setDocs.map(sd => FieldValue(sd.color) as string); const wordToColor = new Map<string, string>(); diff --git a/src/client/views/collections/collectionFreeForm/index.ts b/src/client/views/collections/collectionFreeForm/index.ts new file mode 100644 index 000000000..702dc8d42 --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/index.ts @@ -0,0 +1,7 @@ +export * from "./CollectionFreeFormLayoutEngines"; +export * from "./CollectionFreeFormLinkView"; +export * from "./CollectionFreeFormLinksView"; +export * from "./CollectionFreeFormRemoteCursors"; +export * from "./CollectionFreeFormView"; +export * from "./MarqueeOptionsMenu"; +export * from "./MarqueeView";
\ No newline at end of file |
