diff options
author | bobzel <zzzman@gmail.com> | 2024-05-03 15:28:53 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2024-05-03 15:28:53 -0400 |
commit | 93ab35c251b399f3e44ab2fa016e2af13df5a53b (patch) | |
tree | 08e6a720ef7bd652b74d05d74633b4be9070fc83 | |
parent | e77b55c771a2bd3ba49169185edd9ed2099de1c6 (diff) |
fixed not having docs being dragged show up in schema view unless it is active.
4 files changed, 77 insertions, 90 deletions
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 70b20aec7..f01666d62 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -53,6 +53,7 @@ export class ViewBoxInterface<P> extends ObservableReactComponent<React.PropsWit dragConfig?: (dragData: DragManager.DocumentDragData) => void; // function to setup dragData in custom way (see TreeViews which add a tree view flag) incrementalRendering?: () => void; infoUI?: () => JSX.Element | null; + contentBounds?: () => undefined | { bounds: { x: number; y: number; r: number; b: number }; cx: number; cy: number; width: number; height: number }; // bounds of contents in collection coordinate space (used by TabDocViewThumb) screenBounds?: () => Opt<{ left: number; top: number; right: number; bottom: number; transition?: string }>; ptToScreen?: (pt: { X: number; Y: number }) => { X: number; Y: number }; ptFromScreen?: (pt: { X: number; Y: number }) => { X: number; Y: number }; diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 2d8b2564d..008ef6ab4 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -93,13 +93,10 @@ export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps }; @computed get renderBounds() { - const compView = this._props.tabView()?.ComponentView as CollectionFreeFormView; - const bounds = compView?.freeformData?.(true)?.bounds; - if (!bounds) return undefined; - const xbounds = bounds.r - bounds.x; - const ybounds = bounds.b - bounds.y; - const dim = Math.max(xbounds, ybounds); - return { l: bounds.x + xbounds / 2 - dim / 2, t: bounds.y + ybounds / 2 - dim / 2, cx: bounds.x + xbounds / 2, cy: bounds.y + ybounds / 2, dim }; + const cbounds = this._props.tabView()?.ComponentView?.contentBounds?.(); + const { width, height, bounds, cx, cy } = cbounds ?? { bounds: undefined, width: 0, height: 0 }; + const dim = Math.max(width, height); + return bounds === undefined ? bounds : { l: bounds.x + width / 2 - dim / 2, t: bounds.y + height / 2 - dim / 2, cx, cy, dim }; } @computed get xPadding() { return !this.renderBounds ? 0 : Math.max(0, this._props.PanelWidth() / NumCast(this._props.document._freeform_scale, 1) - 2 * (this.renderBounds.cx - this.renderBounds.l)); @@ -127,8 +124,8 @@ export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps ); }; popup = () => { - if (!this.renderBounds) return <div />; const { renderBounds } = this; + if (!renderBounds) return <div />; const miniWidth = () => (this._props.PanelWidth() / NumCast(this._props.document._freeform_scale, 1) / renderBounds.dim) * 100; const miniHeight = () => (this._props.PanelHeight() / NumCast(this._props.document._freeform_scale, 1) / renderBounds.dim) * 100; const miniLeft = () => 50 + ((NumCast(this._props.document._freeform_panX) - renderBounds.cx) / renderBounds.dim) * 100 - miniWidth() / 2; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 64398a60a..a36c36261 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -88,13 +88,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection return parent instanceof CollectionFreeFormView ? parent : undefined; } - _oldWheel: any; - _clusters = new CollectionFreeFormClusters(this); - constructor(props: any) { - super(props); - makeObservable(this); - } - + private _clusters = new CollectionFreeFormClusters(this); + private _oldWheel: any; private _panZoomTransitionTimer: any; private _lastX: number = 0; private _lastY: number = 0; @@ -129,16 +124,20 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @observable _paintedId = 'id' + Utils.GenerateGuid().replace(/-/g, ''); @observable _keyframeEditing = false; + constructor(props: any) { + super(props); + makeObservable(this); + } + @computed get layoutEngine() { return this._props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine); } @computed get childPointerEvents() { - const engine = this._props.layoutEngine?.() || StrCast(this.Document._layoutEngine); return SnappingManager.IsResizing ? 'none' : this._props.childPointerEvents?.() ?? (this._props.viewDefDivClick || // - (engine === computePassLayout.name && !this._props.isSelected()) || + (this.layoutEngine === computePassLayout.name && !this._props.isSelected()) || this.isContentActive() === false ? 'none' : this._props.pointerEvents?.()); @@ -149,27 +148,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection if (viewsMask.length) renderableEles.push(<div className={`collectionfreeformview-mask${this._layoutElements.some(ele => (ele.inkMask ?? 0) > 0) ? '' : '-empty'}`}>{viewsMask}</div>); return renderableEles; } - @computed get fitToContentVals() { - const hgt = this.contentBounds.b - this.contentBounds.y; - const wid = this.contentBounds.r - this.contentBounds.x; - return { - bounds: { ...this.contentBounds, cx: this.contentBounds.x + wid / 2, cy: this.contentBounds.y + hgt / 2 }, - scale: - (!this.childDocs.length || !Number.isFinite(hgt) || !Number.isFinite(wid) - ? 1 // - : Math.min(this._props.PanelHeight() / hgt, this._props.PanelWidth() / wid)) / (this._props.NativeDimScaling?.() || 1), - }; - } @computed get fitContentsToBox() { return (this._props.fitContentsToBox?.() || this.Document._freeform_fitContentsToBox) && !this.isAnnotationOverlay; } - @computed get contentBounds() { - return aggregateBounds( - this._layoutElements.filter(e => e.bounds?.width && !e.bounds.z).map(e => e.bounds!), - NumCast(this.layoutDoc._xPadding, this._props.xPadding ?? 10), - NumCast(this.layoutDoc._yPadding, this._props.yPadding ?? 10) - ); - } @computed get nativeWidth() { return this._props.NativeWidth?.() || Doc.NativeWidth(this.Document, Cast(this.Document.resolvedDataDoc, Doc, null)); } @@ -177,14 +158,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection return this._props.NativeHeight?.() || Doc.NativeHeight(this.Document, Cast(this.Document.resolvedDataDoc, Doc, null)); } @computed get centeringShiftX(): number { - const scaling = this.nativeDimScaling; - return this._props.isAnnotationOverlay || this._props.originTopLeft ? 0 : this._props.PanelWidth() / 2 / scaling; // shift so pan position is at center of window for non-overlay collections + return this._props.isAnnotationOverlay || this._props.originTopLeft ? 0 : this._props.PanelWidth() / 2 / this.nativeDimScaling; // shift so pan position is at center of window for non-overlay collections } @computed get centeringShiftY(): number { const panLocAtCenter = !(this._props.isAnnotationOverlay || this._props.originTopLeft); if (!panLocAtCenter) return 0; const dv = this.DocumentView?.(); - const aspect = !(this._props.layout_fitWidth?.(this.Document) ?? dv?.layoutDoc.layout_fitWidth) && dv?.nativeWidth && dv?.nativeHeight; + const aspect = !this.fitWidth && dv?.nativeWidth && dv?.nativeHeight; const scaling = this.nativeDimScaling; // if freeform has a native aspect, then the panel height needs to be adjusted to match it const height = aspect ? (dv.nativeHeight / dv.nativeWidth) * this._props.PanelWidth() : this._props.PanelHeight(); @@ -202,14 +182,16 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @computed get backgroundColor() { return this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor); } + @computed get fitWidth() { + return this._props.layout_fitWidth?.(this.Document) ?? this.layoutDoc.layout_fitWidth; + } @computed get nativeDimScaling() { if (this._firstRender || (this._props.isAnnotationOverlay && !this._props.annotationLayerHostsContent)) return 1; - 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 || (this._props.layout_fitWidth?.(this.Document) ?? this.layoutDoc.layout_fitWidth) ? wscale : hscale; + const hscale = this._props.PanelHeight() / (this.nativeHeight || this._props.PanelHeight()); + const wscale = this._props.PanelWidth() / (this.nativeWidth || this._props.PanelWidth()); + return wscale < hscale || this.fitWidth ? wscale : hscale; } + @computed get fitContentBounds() { return !this._firstRender && this.fitContentsToBox ? this.contentBounds() : undefined; } // prettier-ignore @computed get paintFunc() { const field = this.dataDoc[this.fieldKey]; const paintFunc = StrCast(Field.toJavascriptString(Cast(field, RichTextField, null)?.Text as FieldType)).trim(); @@ -244,23 +226,40 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection }; getKeyFrameEditing = () => this._keyframeEditing; + override contentBounds = () => { + const { x, y, r, b } = aggregateBounds( + this._layoutElements.filter(e => e.bounds?.width && !e.bounds.z).map(e => e.bounds!), + NumCast(this.layoutDoc._xPadding, this._props.xPadding ?? 0), + NumCast(this.layoutDoc._yPadding, this._props.yPadding ?? 0) + ); + const [width, height] = [r - x, b - y]; + return { + width, + height, + cx: x + width / 2, + cy: y + height / 2, + bounds: { x, y, r, b }, + scale: (!this.childDocs.length || !Number.isFinite(height) || !Number.isFinite(width) + ? 1 // + : Math.min(this._props.PanelHeight() / height,this._props.PanelWidth() / width )) / (this._props.NativeDimScaling?.() || 1), + }; // prettier-ignore + }; onChildClickHandler = () => this._props.childClickScript || ScriptCast(this.Document.onChildClick); onChildDoubleClickHandler = () => this._props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); elementFunc = () => this._layoutElements; viewTransition = () => (this._panZoomTransition ? '' + this._panZoomTransition : undefined); panZoomTransition = () => (this._panZoomTransition ? `transform ${this._panZoomTransition}ms` : Cast(this.layoutDoc._viewTransition, 'string', Cast(this.Document._viewTransition, 'string', null))); fitContentOnce = () => { - const vals = this.fitToContentVals; - this.layoutDoc._freeform_panX = vals.bounds.cx; - this.layoutDoc._freeform_panY = vals.bounds.cy; - this.layoutDoc._freeform_scale = vals.scale; + const { cx, cy, scale } = this.contentBounds(); // prettier-ignore + this.layoutDoc._freeform_panX = cx; + this.layoutDoc._freeform_panY = cy; + this.layoutDoc._freeform_scale = scale; }; - freeformData = (force?: boolean) => (!this._firstRender && (this.fitContentsToBox || force) ? this.fitToContentVals : undefined); // freeform_panx, freeform_pany, freeform_scale all attempt to get values first from the layout controller, then from the layout/dataDoc (or template layout doc), and finally from the resolved template data document. // this search order, for example, allows icons of cropped images to find the panx/pany/zoom on the cropped image's data doc instead of the usual layout doc because the zoom/panX/panY define the cropped image - panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panX, 1)); - panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panY, 1)); - zoomScaling = () => this.freeformData()?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], 1); // , NumCast(DocCast(this.Document.resolvedDataDoc)?.[this.scaleFieldKey], 1)); + panX = () => this.fitContentBounds?.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panX, 1)); + panY = () => this.fitContentBounds?.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panY, 1)); + zoomScaling = () => this.fitContentBounds?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], 1); // , NumCast(DocCast(this.Document.resolvedDataDoc)?.[this.scaleFieldKey], 1)); PanZoomCenterXf = () => (this._props.isAnnotationOverlay && this.zoomScaling() === 1 ? `` : `translate(${this.centeringShiftX}px, ${this.centeringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`); ScreenToContentsXf = () => this.screenToFreeformContentsXf.copy(); getActiveDocuments = () => this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout); @@ -274,19 +273,16 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection docs.map(doc => DocumentView.getDocumentView(doc, this.DocumentView?.())).forEach(dv => dv && DocumentView.SelectView(dv, true)); }; addDocument = (newBox: Doc | Doc[]) => { - let retVal = false; - if (newBox instanceof Doc) { - retVal = this._props.addDocument?.(newBox) || false; - if (retVal) { - this.bringToFront(newBox); - this._clusters.addDocument(newBox); + const newBoxes = toList(newBox); + const retVal = newBoxes.every(doc => { + const added = this._props.addDocument?.(doc); + if (added) { + this.bringToFront(doc); + this._clusters.addDocument(doc); } - } else { - retVal = this._props.addDocument?.(newBox) || false; - // bcz: deal with clusters - } + return added; + }); if (retVal) { - const newBoxes = toList(newBox); newBoxes.forEach(box => { if (box.activeFrame !== undefined) { const vals = CollectionFreeFormDocumentView.animFields.map(field => box[field.key]); @@ -856,33 +852,25 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection if (!this.isAnnotationOverlay && clamp) { // this section wraps the pan position, horizontally and/or vertically whenever the content is panned out of the viewing bounds const docs = this.childLayoutPairs.map(pair => pair.layout).filter(doc => doc instanceof Doc && doc.type !== DocumentType.LINK); - const measuredDocs = docs - .map(doc => ({ pos: { x: NumCast(doc.x), y: NumCast(doc.y) }, size: { width: NumCast(doc._width), height: NumCast(doc._height) } })) - .filter(({ pos, size }) => pos && size) - .map(({ pos, size }) => ({ pos: pos!, size: size! })); + const measuredDocs = docs.map(doc => ({ x: NumCast(doc.x), y: NumCast(doc.y), width: NumCast(doc._width), height: NumCast(doc._height) })); if (measuredDocs.length) { - const ranges = measuredDocs.reduce( - ( - { xrange, yrange }, - { pos, size } // computes range of content - ) => ({ - xrange: { min: Math.min(xrange.min, pos.x), max: Math.max(xrange.max, pos.x + (size.width || 0)) }, - yrange: { min: Math.min(yrange.min, pos.y), max: Math.max(yrange.max, pos.y + (size.height || 0)) }, - }), - { - xrange: { min: this._props.originTopLeft ? 0 : Number.MAX_VALUE, max: -Number.MAX_VALUE }, - yrange: { min: this._props.originTopLeft ? 0 : Number.MAX_VALUE, max: -Number.MAX_VALUE }, - } - ); - const scaling = this.zoomScaling() * (this._props.NativeDimScaling?.() || 1); - const panelWidMax = (this._props.PanelWidth() / scaling) * (this._props.originTopLeft ? 2 / this.nativeDimScaling : 1); - const panelWidMin = (this._props.PanelWidth() / scaling) * (this._props.originTopLeft ? 0 : 1); - const panelHgtMax = (this._props.PanelHeight() / scaling) * (this._props.originTopLeft ? 2 / this.nativeDimScaling : 1); - const panelHgtMin = (this._props.PanelHeight() / scaling) * (this._props.originTopLeft ? 0 : 1); - if (ranges.xrange.min >= panX + panelWidMax / 2) panX = ranges.xrange.max + (this._props.originTopLeft ? 0 : panelWidMax / 2); - else if (ranges.xrange.max <= panX - panelWidMin / 2) panX = ranges.xrange.min - (this._props.originTopLeft ? panelWidMax / 2 : panelWidMin / 2); - if (ranges.yrange.min >= panY + panelHgtMax / 2) panY = ranges.yrange.max + (this._props.originTopLeft ? 0 : panelHgtMax / 2); - else if (ranges.yrange.max <= panY - panelHgtMin / 2) panY = ranges.yrange.min - (this._props.originTopLeft ? panelHgtMax / 2 : panelHgtMin / 2); + const { originTopLeft } = this._props; + // const xrangeMin = Math.min(...measuredDocs.map(doc => doc.x), originTopLeft ? 0 : Number.MAX_VALUE); + // const yrangeMin = Math.min(...measuredDocs.map(doc => doc.y), originTopLeft ? 0 : Number.MAX_VALUE); + // const xrangeMax = Math.max(...measuredDocs.map(doc => doc.x + doc.width)); + // const yrangeMax = Math.max(...measuredDocs.map(doc => doc.y + doc.height)); + const { bounds: { x: xrangeMin, y: yrangeMin, r: xrangeMax, b: yrangeMax } } = this.contentBounds(); // prettier-ignore + const nativeScaling = this._props.NativeDimScaling?.() || 1; + const scaling = this.zoomScaling() * nativeScaling; + const [widScaling, hgtScaling] = [this._props.PanelWidth() / scaling, this._props.PanelHeight() / scaling]; + const panelWidMax = widScaling * (originTopLeft ? 2 / nativeScaling : 1); + const panelHgtMax = hgtScaling * (originTopLeft ? 2 / nativeScaling : 1); + const panelWidMin = widScaling * (originTopLeft ? 0 : 1); + const panelHgtMin = hgtScaling * (originTopLeft ? 0 : 1); + if (xrangeMin >= panX + panelWidMax / 2) panX = xrangeMax + (originTopLeft ? 0 : panelWidMax / 2); + else if (xrangeMax <= panX - panelWidMin / 2) panX = xrangeMin - (originTopLeft ? panelWidMax / 2 : panelWidMin / 2); // prettier-ignore + if (yrangeMin >= panY + panelHgtMax / 2) panY = yrangeMax + (originTopLeft ? 0 : panelHgtMax / 2); + else if (yrangeMax <= panY - panelHgtMin / 2) panY = yrangeMin - (originTopLeft ? panelHgtMax / 2 : panelHgtMin / 2); // prettier-ignore } } if (!this.layoutDoc._lockedTransform || LightboxView.LightboxDoc) { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 023b72778..b684b65e5 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1014,9 +1014,10 @@ export class CollectionSchemaView extends CollectionSubView() { }; @computed get sortedDocs() { + const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; const field = StrCast(this.layoutDoc.sortField); const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort - const staticDocs = this.childDocs.filter(d => !DragManager.docsBeingDragged.includes(d)); + const staticDocs = this.childDocs.filter(d => !draggedDocs.includes(d)); const docs = !field ? staticDocs : [...staticDocs].sort((docA, docB) => { @@ -1030,7 +1031,7 @@ export class CollectionSchemaView extends CollectionSubView() { return out; }); - docs.splice(this.rowDropIndex, 0, ...DragManager.docsBeingDragged); + docs.splice(this.rowDropIndex, 0, ...draggedDocs); return { docs }; } |