aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-05-03 15:28:53 -0400
committerbobzel <zzzman@gmail.com>2024-05-03 15:28:53 -0400
commit93ab35c251b399f3e44ab2fa016e2af13df5a53b (patch)
tree08e6a720ef7bd652b74d05d74633b4be9070fc83 /src
parente77b55c771a2bd3ba49169185edd9ed2099de1c6 (diff)
fixed not having docs being dragged show up in schema view unless it is active.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/DocComponent.tsx1
-rw-r--r--src/client/views/collections/TabDocView.tsx13
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx148
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx5
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 };
}