From 93ab35c251b399f3e44ab2fa016e2af13df5a53b Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 3 May 2024 15:28:53 -0400 Subject: fixed not having docs being dragged show up in schema view unless it is active. --- src/client/views/DocComponent.tsx | 1 + src/client/views/collections/TabDocView.tsx | 13 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 148 ++++++++++----------- .../collectionSchema/CollectionSchemaView.tsx | 5 +- 4 files changed, 77 insertions(+), 90 deletions(-) (limited to 'src') 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

extends ObservableReactComponent 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 { - if (!this.renderBounds) return

; const { renderBounds } = this; + if (!renderBounds) return
; 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 (ele.inkMask ?? 0) > 0) ? '' : '-empty'}`}>{viewsMask}
); 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 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 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 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 }; } -- cgit v1.2.3-70-g09d2