diff options
Diffstat (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')
| -rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 76 |
1 files changed, 56 insertions, 20 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b8576681d..1add65c10 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx"; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; import { computedFn } from "mobx-utils"; import { Doc, DocListCast, HeightSym, Opt, WidthSym, StrListCast } from "../../../../fields/Doc"; @@ -31,9 +31,9 @@ import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss" import { Timeline } from "../../animationtimeline/Timeline"; import { ContextMenu } from "../../ContextMenu"; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth } from "../../InkingStroke"; -import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; +import { CollectionFreeFormDocumentView, CollectionFreeFormDocumentViewProps } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentLinksButton } from "../../nodes/DocumentLinksButton"; -import { DocumentViewProps, DocAfterFocusFunc } from "../../nodes/DocumentView"; +import { DocumentViewProps, DocAfterFocusFunc, DocumentView } from "../../nodes/DocumentView"; import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox"; import { pageSchema } from "../../nodes/ImageBox"; import { PresBox } from "../../nodes/PresBox"; @@ -49,6 +49,7 @@ import React = require("react"); import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; import { StyleProp, StyleLayers } from "../../StyleProvider"; import { DocumentDecorations } from "../../DocumentDecorations"; +import { FieldViewProps } from "../../nodes/FieldView"; export const panZoomSchema = createSchema({ _panX: "number", @@ -115,11 +116,11 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && (this.props.ContainingCollectionView?.active() || this.props.active()); } @computed get fitToContentScaling() { return this.fitToContent ? NumCast(this.layoutDoc.fitToContentScaling, 1) : 1; } - @computed get fitToContent() { return (this.props.fitToBox || this.Document._fitToBox) && !this.isAnnotationOverlay; } - @computed get parentScaling() { return this.props.ContentScaling && this.fitToContent ? this.props.ContentScaling() : 1; } + @computed get fitToContent() { return (this.props.fitContentsToDoc || this.Document._fitToBox) && !this.isAnnotationOverlay; } + @computed get parentScaling() { return 1; } @computed get contentBounds() { return aggregateBounds(this._layoutElements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!), NumCast(this.layoutDoc._xPadding, 10), NumCast(this.layoutDoc._yPadding, 10)); } - @computed get nativeWidth() { return this.fitToContent ? 0 : returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.Document)); } - @computed get nativeHeight() { return this.fitToContent ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.Document)); } + @computed get nativeWidth() { return this.fitToContent ? 0 : Doc.NativeWidth(this.Document); } + @computed get nativeHeight() { return this.fitToContent ? 0 : Doc.NativeHeight(this.Document); } private get isAnnotationOverlay() { return this.props.isAnnotationOverlay; } private get scaleFieldKey() { return this.props.scaleField || "_viewScale"; } private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } @@ -219,8 +220,28 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P return (pt => super.onExternalDrop(e, { x: pt[0], y: pt[1] }))(this.getTransform().transformPoint(e.pageX, e.pageY)); } + 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; + } + @action internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number, yp: number) { + if (!this.ChildDrag && this.props.layerProvider?.(this.props.Document) !== false && this.props.Document._isGroup) return false; if (!super.onInternalDrop(e, de)) return false; const refDoc = docDragData.droppedDocuments[0]; const [xpo, ypo] = this.getTransformOverlay().transformPoint(de.x, de.y); @@ -251,6 +272,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P !StrListCast(d.layers).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; } @@ -279,7 +302,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P } else { const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" }); this.props.addDocument?.(source); - linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation", ""); // TODODO this is where in text links get passed + de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation", ""); // TODODO this is where in text links get passed e.stopPropagation(); return true; } @@ -321,7 +344,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.CollectionView)!); const de = new DragManager.DocumentDragData(eles); de.moveDocument = this.props.moveDocument; - const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0); + const { left, top } = clusterDocs[0].getBounds() || { left: 0, top: 0 }; de.offset = this.getTransform().transformDirection(ptsParent.clientX - left, ptsParent.clientY - top); de.dropAction = e.ctrlKey || e.altKey ? "alias" : undefined; DragManager.StartDocumentDrag(clusterDocs.map(v => v.ContentDiv!), de, ptsParent.clientX, ptsParent.clientY, { hideSource: !de.dropAction }); @@ -405,7 +428,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P } } - getClusterColor = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => { + getClusterColor = (doc: Opt<Doc>, props: Opt<DocumentViewProps | FieldViewProps>, property: string) => { let styleProp = this.props.styleProvider?.(doc, props, property); // bcz: check 'props' used to be renderDepth + 1 if (property !== StyleProp.BackgroundColor) return styleProp; const cluster = NumCast(doc?.cluster); @@ -421,7 +444,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P set && set.filter(s => !StrListCast(s.layers).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); set && set.filter(s => StrListCast(s.layers).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); } - } else if (doc && NumCast(doc.group, -1) !== -1) styleProp = "gray"; + } //else if (doc && NumCast(doc.group, -1) !== -1) styleProp = "gray"; return styleProp; } @@ -653,6 +676,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P return; } if (!e.cancelBubble) { + if (this.props.Document._isGroup) return; // groups don't pan when dragged -- instead let the event go through to allow the group itself to drag if (Doc.GetSelectedTool() === InkTool.None) { if (this.tryDragCluster(e, this._hitCluster)) { e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers @@ -986,6 +1010,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P pw && ph && (this.Document[this.scaleFieldKey] = scale * Math.min(pw / NumCast(doc._width), ph / NumCast(doc._height))); } + @observable ChildDrag: DocumentView | undefined; onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick); onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); parentActive = (outsideReaction: boolean) => this.props.active(outsideReaction) || this.props.parentActive?.(outsideReaction) || this.backgroundActive || this.layoutDoc._viewType === CollectionViewType.Pile ? true : false; @@ -997,7 +1022,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P pinToPres: this.props.pinToPres, whenActiveChanged: this.props.whenActiveChanged, parentActive: this.parentActive, - fitToBox: false, DataDoc: childData, Document: childLayout, ContainingCollectionView: this.props.CollectionView, @@ -1010,7 +1034,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P ScreenToLocalTransform: childLayout.z ? this.getTransformOverlay : this.getTransform, PanelWidth: childLayout[WidthSym], PanelHeight: childLayout[HeightSym], - ContentScaling: returnOne, docFilters: this.docFilters, docRangeFilters: this.docRangeFilters, searchFilterDocs: this.searchFilterDocs, @@ -1166,6 +1189,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P key={entry[1].pair.layout[Id] + (entry[1].replica || "")} {...this.getChildDocumentViewProps(entry[1].pair.layout, entry[1].pair.data)} replica={entry[1].replica} + CollectionFreeFormView={this} dataProvider={this.childDataProvider} sizeProvider={this.childSizeProvider} layerProvider={this.props.layerProvider} @@ -1174,7 +1198,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P (this.props.viewDefDivClick || (engine === "pass" && !this.props.isSelected(true))) ? "none" : undefined} jitterRotation={NumCast(this.props.Document._jitterRotation) || ((Doc.UserDoc().renderStyle === "comic" ? 10 : 0))} //fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this - fitToBox={BoolCast(this.props.childFreezeDimensions)} // bcz: check this freezeDimensions={BoolCast(this.props.childFreezeDimensions)} />, bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica) @@ -1204,6 +1227,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P } })); } + //this.updateGroupBounds(); this._marqueeRef.current?.addEventListener("dashDragAutoScroll", this.onDragAutoScroll as any); } @@ -1277,7 +1301,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @undoBatch @action toggleNativeDimensions = () => { - Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth?.() || 0, this.props.NativeHeight?.() || 0); + Doc.toggleNativeDimensions(this.layoutDoc, 1, this.nativeWidth, this.nativeHeight); } @undoBatch @@ -1294,6 +1318,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P appearanceItems.push({ description: "Reset View", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document[this.scaleFieldKey] = 1; }, icon: "compress-arrows-alt" }); !Doc.UserDoc().noviceMode && Doc.UserDoc().defaultTextLayout && appearanceItems.push({ description: "Reset default note style", event: () => Doc.UserDoc().defaultTextLayout = undefined, icon: "eye" }); appearanceItems.push({ description: `${this.fitToContent ? "Make Zoomable" : "Scale to Window"}`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" }); + this.props.ContainingCollectionView && + appearanceItems.push({ description: "Ungroup collection", event: this.promoteCollection, icon: "table" }); !Doc.UserDoc().noviceMode ? appearanceItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" }) : null; !appearance && ContextMenu.Instance.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" }); @@ -1308,8 +1334,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P const optionItems = options && "subitems" in options ? options.subitems : []; !this.props.isAnnotationOverlay && !Doc.UserDoc().noviceMode && optionItems.push({ description: (this._showAnimTimeline ? "Close" : "Open") + " Animation Timeline", event: action(() => this._showAnimTimeline = !this._showAnimTimeline), icon: "eye" }); - this.props.ContainingCollectionView && - optionItems.push({ description: "Move Items Out of Collection", event: this.promoteCollection, icon: "table" }); optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" }); this.props.renderDepth && optionItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" }); if (!Doc.UserDoc().noviceMode) { @@ -1382,7 +1406,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P } onPointerOver = (e: React.PointerEvent) => { - (DocumentDecorations.Instance.Interacting || SnappingManager.GetIsDragging()) && this.setupDragLines(e.ctrlKey || e.shiftKey); + (DocumentDecorations.Instance.Interacting || (this.props.layerProvider?.(this.props.Document) === false && SnappingManager.GetIsDragging())) && this.setupDragLines(e.ctrlKey || e.shiftKey); e.stopPropagation(); } @@ -1470,6 +1494,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @computed get marqueeView() { return <MarqueeView {...this.props} + ungroup={this.props.Document._isGroup ? this.promoteCollection : undefined} nudge={this.isAnnotationOverlay || this.props.renderDepth > 0 ? undefined : this.nudge} addDocTab={this.addDocTab} trySelectCluster={this.trySelectCluster} @@ -1501,8 +1526,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @computed get contentScaling() { if (this.props.isAnnotationOverlay && !this.props.forceScaling) return 0; - const nw = returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.Document)); - const nh = returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.Document)); + const nw = this.nativeWidth; + const nh = this.nativeHeight; const hscale = nh ? this.props.PanelHeight() / nh : 1; const wscale = nw ? this.props.PanelWidth() / nw : 1; return wscale < hscale ? wscale : hscale; @@ -1549,6 +1574,17 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P {this._vLines?.map(l => <line y1="0" x1={l} y2="1000" x2={l} stroke="black" />)} </svg> </div>} + + {this.props.Document._isGroup && SnappingManager.GetIsDragging() && (this.ChildDrag || this.props.layerProvider?.(this.props.Document) === false) ? + <div className="collectionFreeForm-groupDropper" ref={this.createDashEventsTarget} style={{ + width: this.ChildDrag ? "10000" : "100%", + height: this.ChildDrag ? "10000" : "100%", + left: this.ChildDrag ? "-5000" : 0, + top: this.ChildDrag ? "-5000" : 0, + position: "absolute", + background: "#0009930", + pointerEvents: "all" + }} /> : (null)} </div >; } } |
