aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/DocumentDecorations.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/DocumentDecorations.tsx')
-rw-r--r--src/client/views/DocumentDecorations.tsx165
1 files changed, 82 insertions, 83 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index d7ff0d06a..7424aaf2c 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,7 +1,6 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
-import { DimensionField } from '../../fields/DimensionField';
import { IconButton } from '@dash/components';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -50,7 +49,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
static Instance: DocumentDecorations;
private _resizeHdlId = '';
private _keyinput = React.createRef<HTMLInputElement>();
- private _resizeBorderWidth = 16;
+ private _resizeBorderWidth = 8;
private _linkBoxHeight = 20 + 3; // link button height + margin
private _titleHeight = 20;
private _resizeUndo?: UndoManager.Batch;
@@ -99,11 +98,11 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const bounds = { ...this.Bounds };
const leftBounds = this._props.boundsLeft;
const topBounds = DocumentView.LightboxDoc() ? 0 : this._props.boundsTop;
- bounds.x = Math.max(leftBounds, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2;
- bounds.y = Math.max(topBounds, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight;
+ bounds.x = Math.max(leftBounds, bounds.x - this._resizeBorderWidth) + this._resizeBorderWidth;
+ bounds.y = Math.max(topBounds, bounds.y - this._resizeBorderWidth - this._titleHeight) + this._resizeBorderWidth + this._titleHeight;
const borderRadiusDraggerWidth = 15;
- bounds.r = Math.max(bounds.x, Math.max(leftBounds, Math.min(window.innerWidth, bounds.r + borderRadiusDraggerWidth + this._resizeBorderWidth / 2) - this._resizeBorderWidth / 2 - borderRadiusDraggerWidth));
- bounds.b = Math.max(bounds.y, Math.max(topBounds, Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth / 2 + this._linkBoxHeight) - this._resizeBorderWidth / 2 - this._linkBoxHeight));
+ bounds.r = Math.max(bounds.x, Math.max(leftBounds, Math.min(window.innerWidth, bounds.r + borderRadiusDraggerWidth + this._resizeBorderWidth) - this._resizeBorderWidth - borderRadiusDraggerWidth));
+ bounds.b = Math.max(bounds.y, Math.max(topBounds, Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth + this._linkBoxHeight) - this._resizeBorderWidth - this._linkBoxHeight));
return bounds;
}
@@ -128,7 +127,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
} else if (this._titleControlString.startsWith('$')) {
if (this._accumulatedTitle.startsWith('-->#')) {
DocumentView.SelectedDocs().forEach(doc => {
- doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`);
+ doc.$onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`);
});
}
const titleFieldKey = this._titleControlString.substring(1);
@@ -321,7 +320,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2);
const dist = moveEv.clientX < x && moveEv.clientY < y ? 0 : Math.sqrt((moveEv.clientX - x) * (moveEv.clientX - x) + (moveEv.clientY - y) * (moveEv.clientY - y));
DocumentView.SelectedDocs().forEach(doc => {
- const docMax = Math.min(NumCast(doc.width) / 2, NumCast(doc.height) / 2);
+ const docMax = Math.min(NumCast(doc._width) / 2, NumCast(doc._height) / 2);
const radius = Math.min(1, dist / maxDist) * docMax; // set radius based on ratio of drag distance to half diagonal distance of bounding box
doc._layout_borderRounding = `${radius}px`;
});
@@ -389,7 +388,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
DocumentView.Selected().forEach(dv => {
const accumRot = (NumCast(dv.Document._rotation) / 180) * Math.PI;
const localRotCtr = dv.screenToViewTransform().transformPoint(rcScreen.X, rcScreen.Y);
- const localRotCtrOffset = [localRotCtr[0] - NumCast(dv.Document.width) / 2, localRotCtr[1] - NumCast(dv.Document.height) / 2];
+ const localRotCtrOffset = [localRotCtr[0] - NumCast(dv.Document._width) / 2, localRotCtr[1] - NumCast(dv.Document._height) / 2];
const startRotCtr = Utils.rotPt(localRotCtrOffset[0], localRotCtrOffset[1], -accumRot);
const unrotatedDocPos = { x: NumCast(dv.Document.x) + localRotCtrOffset[0] - startRotCtr.x, y: NumCast(dv.Document.y) + localRotCtrOffset[1] - startRotCtr.y };
infos.set(dv.Document, { unrotatedDocPos, startRotCtr, accumRot });
@@ -491,51 +490,52 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const { scale, refPt } = this.getResizeVals(thisPt, dragHdl);
- !this._interactionLock && runInAction(async () => { // resize selected docs if we're not in the middle of a resize (ie, throttle input events to frame rate)
- this._interactionLock = true;
- this._snapPt = thisPt;
-
- // Special handling for shift+click (outpainting mode)
- if (e.shiftKey && DocumentView.Selected().some(dv => dv.ComponentView instanceof ImageBox)) {
- DocumentView.Selected().forEach(docView => {
- if (docView.ComponentView instanceof ImageBox) {
- // Set flag for outpainting mode
- docView.Document._outpaintingResize = true;
-
- // Adjust only the document dimensions without scaling internal content
- this.resizeViewForOutpainting(docView, refPt, scale, { dragHdl, shiftKey: e.shiftKey });
- }
- else {
- // Handle regular resize for non-image components
- e.ctrlKey && !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions();
- const hasFixedAspect = this.hasFixedAspect(docView.Document);
- const scaleAspect = {x:scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y};
- this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey: e.ctrlKey });
- }
+ !this._interactionLock &&
+ runInAction(async () => {
+ // resize selected docs if we're not in the middle of a resize (ie, throttle input events to frame rate)
+ this._interactionLock = true;
+ this._snapPt = thisPt;
+
+ // Special handling for shift+click (outpainting mode)
+ if (e.shiftKey && DocumentView.Selected().some(dv => dv.ComponentView instanceof ImageBox)) {
+ DocumentView.Selected().forEach(docView => {
+ if (docView.ComponentView instanceof ImageBox) {
+ // Set flag for outpainting mode
+ docView.Document._outpaintingResize = true;
+
+ // Adjust only the document dimensions without scaling internal content
+ this.resizeViewForOutpainting(docView, refPt, scale, { dragHdl, shiftKey: e.shiftKey });
+ } else {
+ // Handle regular resize for non-image components
+ e.ctrlKey && !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions();
+ const hasFixedAspect = this.hasFixedAspect(docView.Document);
+ const scaleAspect = { x: scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y };
+ this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey: e.ctrlKey });
+ }
+ });
+ } else {
+ // Regular resize behavior (existing code)
+ e.ctrlKey && DocumentView.Selected().forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions());
+ const hasFixedAspect = DocumentView.Selected()
+ .map(dv => dv.Document)
+ .some(this.hasFixedAspect);
+ const scaleAspect = { x: scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y };
+ DocumentView.Selected().forEach(docView => this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey: e.ctrlKey }));
+ }
+
+ await new Promise<void>(res => {
+ setTimeout(() => {
+ res((this._interactionLock = undefined));
+ });
});
- } else {
- // Regular resize behavior (existing code)
- e.ctrlKey && (DocumentView.Selected().forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions()));
- const hasFixedAspect = DocumentView.Selected().map(dv => dv.Document).some(this.hasFixedAspect);
- const scaleAspect = {x:scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y};
- DocumentView.Selected().forEach(docView =>
- this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey:e.ctrlKey }));
- }
-
- await new Promise<void>(res => { setTimeout(() => { res(this._interactionLock = undefined)})});
- });
+ });
return false;
};
- resizeViewForOutpainting = (
- docView: DocumentView,
- refPt: number[],
- scale: { x: number; y: number },
- opts: { dragHdl: string; shiftKey: boolean }
- ) => {
+ resizeViewForOutpainting = (docView: DocumentView, refPt: number[], scale: { x: number; y: number }, opts: { dragHdl: string; shiftKey: boolean }) => {
const doc = docView.Document;
-
+
if (doc.isGroup) {
DocListCast(doc.data)
.map(member => DocumentView.getDocumentView(member, docView)!)
@@ -544,35 +544,32 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
doc.yPadding = NumCast(doc.yPadding) * scale.y;
return;
}
-
+
if (!doc._outpaintingOriginalWidth || !doc._outpaintingOriginalHeight) {
doc._outpaintingOriginalWidth = NumCast(doc._width);
doc._outpaintingOriginalHeight = NumCast(doc._height);
-
- // Initialize or update the _originalDims ObjectField correctly
- doc._originalDims = new DimensionField(doc._outpaintingOriginalWidth, doc._outpaintingOriginalHeight);
}
-
+
// Calculate new boundary dimensions
const originalWidth = NumCast(doc._width);
const originalHeight = NumCast(doc._height);
const newWidth = Math.max(NumCast(doc._width_min, 25), originalWidth * scale.x);
const newHeight = Math.max(NumCast(doc._height_min, 10), originalHeight * scale.y);
-
+
// Apply new dimensions
doc._width = newWidth;
doc._height = newHeight;
-
+
const refCent = docView.screenToViewTransform().transformPoint(refPt[0], refPt[1]);
const { deltaX, deltaY } = this.realignRefPt(doc, refCent, originalWidth, originalHeight);
doc.x = NumCast(doc.x) + deltaX;
doc.y = NumCast(doc.y) + deltaY;
-
+
doc._layout_modificationDate = new DateField();
-
+
// Trigger outpainting
doc._needsOutpainting = true;
-
+
// Store metadata needed for outpainting
doc._outpaintingMetadata = JSON.stringify({
originalWidth: doc._outpaintingOriginalWidth,
@@ -581,7 +578,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
newHeight,
scaleX: scale.x,
scaleY: scale.y,
- anchorHandle: opts.dragHdl
+ anchorHandle: opts.dragHdl,
});
};
@@ -589,19 +586,19 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
onPointerUp = (): void => {
SnappingManager.SetIsResizing(undefined);
SnappingManager.clearSnapLines();
-
+
// Check if any outpainting needs to be processed
DocumentView.Selected().forEach(view => {
if (view.Document._needsOutpainting && view.ComponentView instanceof ImageBox) {
// Trigger outpainting process in the ImageBox component
(view.ComponentView as ImageBox).processOutpainting();
-
+
// Clear flags
view.Document._needsOutpainting = false;
view.Document._outpaintingResize = false;
}
});
-
+
this._resizeHdlId = '';
this._resizeUndo?.end();
@@ -613,7 +610,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
this._inkDragDocs
.map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] }))
.forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => {
- doc[DocData].data = new InkField(inkPts.map(
+ doc.$data = new InkField(inkPts.map(
(ipt) => ({// (new x — oldx) + newWidth * (oldxpoint /oldWidth)
X: NumCast(doc.x) - x + (NumCast(doc._width) * ipt.X) / width,
Y: NumCast(doc.y) - y + (NumCast(doc._height) * ipt.Y) / height,
@@ -672,7 +669,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
scale.x === 1 ? (scale.x = scale.y) : (scale.y = scale.x);
}
- if (['right', 'left'].includes(opts.dragHdl) && modifyNativeDim && Doc.NativeWidth(doc)) {
+ if (['right', 'left', 'bottomRight'].includes(opts.dragHdl) && modifyNativeDim && Doc.NativeWidth(doc)) {
const setData = Doc.NativeWidth(doc[DocData]) === doc.nativeWidth;
doc.nativeWidth = scale.x * Doc.NativeWidth(doc);
if (setData) Doc.SetNativeWidth(doc[DocData], NumCast(doc.nativeWidth));
@@ -680,7 +677,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
doc._nativeHeight = (initHeight / initWidth) * nwidth; // initializes the nativeHeight for a PDF
}
}
- if (['bottom', 'top'].includes(opts.dragHdl) && modifyNativeDim && Doc.NativeHeight(doc)) {
+ if (['bottom', 'top', 'bottomRight'].includes(opts.dragHdl) && modifyNativeDim && Doc.NativeHeight(doc)) {
const setData = Doc.NativeHeight(doc[DocData]) === doc.nativeHeight && (!doc.layout_reflowVertical || opts.ctrlKey);
doc._nativeHeight = scale.y * Doc.NativeHeight(doc);
if (setData) Doc.SetNativeHeight(doc[DocData], NumCast(doc._nativeHeight));
@@ -815,7 +812,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
// Radius constants
const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView;
const borderRadius = numberValue(Cast(seldocview.Document.layout_borderRounding, 'string', null));
- const docMax = Math.min(NumCast(seldocview.Document.width) / 2, NumCast(seldocview.Document.height) / 2);
+ const docMax = Math.min(NumCast(seldocview.Document._width) / 2, NumCast(seldocview.Document._height) / 2);
const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2);
const radiusHandle = (borderRadius / docMax) * maxDist;
const radiusHandleLocation = Math.min(radiusHandle, maxDist);
@@ -869,7 +866,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
</span>
)}
{sharingMenu}
- {!useLock ? null : (
+ {!useLock || hideTitle ? null : (
<Tooltip key="lock" title={<div className="dash-tooltip">toggle ability to interact with document</div>} placement="top">
<div className="documentDecorations-lock" style={{ color: seldocview.Document._lockedPosition ? 'red' : undefined }} onPointerDown={this.onLockDown}>
<FontAwesomeIcon size="sm" icon="lock" />
@@ -886,10 +883,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
<div
className="documentDecorations-background"
style={{
- width: bounds.r - bounds.x + this._resizeBorderWidth + 'px',
- height: bounds.b - bounds.y + this._resizeBorderWidth + 'px',
- left: bounds.x - this._resizeBorderWidth / 2,
- top: bounds.y - this._resizeBorderWidth / 2,
+ width: bounds.r - bounds.x + 2 * this._resizeBorderWidth + 'px',
+ height: bounds.b - bounds.y + 2 * this._resizeBorderWidth + 'px',
+ left: bounds.x - this._resizeBorderWidth,
+ top: bounds.y - this._resizeBorderWidth,
transformOrigin,
background: SnappingManager.ShiftKey ? undefined : 'yellow',
pointerEvents: SnappingManager.ShiftKey || SnappingManager.IsResizing ? 'none' : 'all',
@@ -903,10 +900,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
<div
className={`documentDecorations-container ${this._showNothing ? 'showNothing' : ''}`}
style={{
- transform: `translate(${bounds.x - this._resizeBorderWidth / 2}px, ${bounds.y - this._resizeBorderWidth / 2 - this._titleHeight}px) rotate(${rotation}deg)`,
+ transform: `translate(${bounds.x - this._resizeBorderWidth}px, ${bounds.y - this._resizeBorderWidth - this._titleHeight}px) rotate(${rotation}deg)`,
transformOrigin,
- width: bounds.r - bounds.x + this._resizeBorderWidth + 'px',
- height: bounds.b - bounds.y + this._resizeBorderWidth + (this._showNothing ? 0 : this._titleHeight) + 'px',
+ width: bounds.r - bounds.x + 2 * this._resizeBorderWidth + 'px',
+ height: bounds.b - bounds.y + 2 * this._resizeBorderWidth + (this._showNothing ? 0 : this._titleHeight) + 'px',
}}>
<div
className="documentDecorations-topbar"
@@ -914,8 +911,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
display: hideDeleteButton && hideTitle && hideOpenButton ? 'none' : undefined,
}}
onPointerDown={this.onContainerDown}>
- {hideDeleteButton ? null : topBtn('close', 'times', undefined, () => this.onCloseClick(true), 'Close')}
- {hideResizers || hideDeleteButton ? null : topBtn('minimize', 'window-maximize', undefined, () => this.onCloseClick(undefined), 'Minimize')}
+ <div className="documentDecorations-closeWrapper">
+ {hideDeleteButton ? null : topBtn('close', 'times', undefined, () => this.onCloseClick(true), 'Close')}
+ {hideResizers || hideDeleteButton ? null : topBtn('minimize', 'window-maximize', undefined, () => this.onCloseClick(undefined), 'Minimize')}
+ </div>
{titleArea}
{hideOpenButton ? <div /> : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as alias, shift: in new collection, opption: in editor view)')}
</div>
@@ -928,7 +927,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
<div key="c" className="documentDecorations-centerCont" />
<div key="r" className="documentDecorations-rightResizer" onPointerDown={this.onPointerDown} />
<div key="bl" className="documentDecorations-bottomLeftResizer" onPointerDown={this.onPointerDown} />
- <div key="b" className="documentDecorations-bottomResizer" onPointerDown={this.onPointerDown} />
+ {seldocview.TagPanelHeight !== 0 || seldocview.TagPanelEditing ? null : <div key="b" className="documentDecorations-bottomResizer" onPointerDown={this.onPointerDown} />}
<div key="br" className="documentDecorations-bottomRightResizer" onPointerDown={this.onPointerDown} />
</>
)}
@@ -944,12 +943,12 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
/>
)}
- {hideDocumentButtonBar || this._showNothing ? null : (
+ {seldocview.TagPanelEditing || hideDocumentButtonBar || this._showNothing ? null : (
<div
className="link-button-container"
style={{
- top: DocumentView.Selected().length > 1 ? 0 : `${seldocview.showTags ? 4 + seldocview.TagPanelHeight : 4}px`,
- transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
+ top: DocumentView.Selected().length > 1 || !seldocview.showTags ? 0 : `${seldocview.TagPanelHeight}px`,
+ transform: `translate(${-this._resizeBorderWidth + 10}px, ${(seldocview.TagPanelHeight === 0 ? 2 * this._resizeBorderWidth : this._resizeBorderWidth) + bounds.b - bounds.y + this._titleHeight}px) `,
}}>
<DocumentButtonBar views={() => DocumentView.Selected()} />
</div>
@@ -957,10 +956,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
<div
className="documentDecorations-tagsView"
style={{
- top: 30, // offset by height of documentButtonBar so that items can be clicked without overlap interference
- transform: `translate(${-this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
+ display: DocumentView.Selected().length > 1 || !seldocview.showTags ? 'none' : undefined,
+ transform: `translate(${-this._resizeBorderWidth + 10}px, ${2 * this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
}}>
- {DocumentView.Selected().length > 1 ? <TagsView Views={DocumentView.Selected()} /> : null}
+ {DocumentView.Selected().length > 1 ? <TagsView Views={DocumentView.Selected()} background={SnappingManager.userBackgroundColor ?? ''} /> : null}
</div>
</div>