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.tsx158
1 files changed, 127 insertions, 31 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 54e050f9f..d7ff0d06a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,6 +1,7 @@
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';
@@ -473,6 +474,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const tl = docView.screenToContentsTransform().inverse().transformPoint(0, 0);
return project([e.clientX + this._offset.x, e.clientY + this._offset.y], tl, [tl[0] + fixedAspect, tl[1] + 1]);
};
+
+ // Modify the onPointerMove method to handle shift+click during resize
onPointerMove = (e: PointerEvent): boolean => {
const first = DocumentView.Selected()[0];
const effectiveAcl = GetEffectiveAcl(first.Document);
@@ -491,17 +494,135 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
!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;
- 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 })); // prettier-ignore
+
+ // 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)})});
- }); // prettier-ignore
+ });
return false;
};
+ 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)!)
+ .forEach(member => this.resizeViewForOutpainting(member, refPt, scale, opts));
+ doc.xPadding = NumCast(doc.xPadding) * scale.x;
+ 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,
+ originalHeight: doc._outpaintingOriginalHeight,
+ newWidth,
+ newHeight,
+ scaleX: scale.x,
+ scaleY: scale.y,
+ anchorHandle: opts.dragHdl
+ });
+ };
+
+ @action
+ 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();
+
+ // detect layout_autoHeight gesture and apply
+ DocumentView.Selected().forEach(view => {
+ NumCast(view.Document._height) < 20 && (view.layoutDoc._layout_autoHeight = true);
+ });
+ // need to change points for resize, or else rotation/control points will fail.
+ 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(
+ (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,
+ }))); // prettier-ignore
+ Doc.SetNativeWidth(doc, undefined);
+ Doc.SetNativeHeight(doc, undefined);
+ });
+ };
+
//
// determines how much to resize, and determines the resize reference point
//
@@ -606,31 +727,6 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
};
};
- @action
- onPointerUp = (): void => {
- SnappingManager.SetIsResizing(undefined);
- SnappingManager.clearSnapLines();
- this._resizeHdlId = '';
- this._resizeUndo?.end();
-
- // detect layout_autoHeight gesture and apply
- DocumentView.Selected().forEach(view => {
- NumCast(view.Document._height) < 20 && (view.layoutDoc._layout_autoHeight = true);
- });
- // need to change points for resize, or else rotation/control points will fail.
- 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(
- (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,
- }))); // prettier-ignore
- Doc.SetNativeWidth(doc, undefined);
- Doc.SetNativeHeight(doc, undefined);
- });
- };
-
@computed get selectionTitle(): string {
if (DocumentView.Selected().length === 1) {
const selected = DocumentView.Selected()[0];