diff options
author | bobzel <zzzman@gmail.com> | 2023-11-17 21:53:36 -0500 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2023-11-17 21:53:36 -0500 |
commit | 0dc39baf9630ae5aeaa41b89523ec6bf96d0b198 (patch) | |
tree | 6664d8e16c4dddfc4ed3cf88f5a65505eb4913ba /src | |
parent | 96d27379d77b77f7496a1b2c5f30824cc04370c0 (diff) |
major overhaul of resizing code. updated doc fields for enabling native with modification to be cleaner. added Vcenter option for text in menu bar. fixed doc rotation. enabled scaling of DataViz views. fixed text sidebar opening size and sidebar issues with native dims for PDF/Web
Diffstat (limited to 'src')
-rw-r--r-- | src/client/documents/Documents.ts | 43 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 4 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 312 | ||||
-rw-r--r-- | src/client/views/InkControlPtHandles.tsx | 7 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/global/globalScripts.ts | 14 | ||||
-rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/DataVizBox/DataVizBox.tsx | 10 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 13 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 6 | ||||
-rw-r--r-- | src/fields/Doc.ts | 6 |
15 files changed, 191 insertions, 237 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1ea9b1dcc..bd5fa5d78 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -186,8 +186,6 @@ export class DocumentOptions { linearBtnWidth?: NUMt = new NumInfo('unexpanded width of a linear menu button (button "width" changes when it expands)', false); _nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)', false); _nativeHeight?: NUMt = new NumInfo('native height of document contents (e.g., the pixel height of an image)', false); - _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false); - _nativeHeightUnfrozen?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); 'acl-Guest'?: STRt = new StrInfo("permissions granted to users logged in as 'guest' (either view, or private)"); // public permissions '_acl-Guest'?: string; // public permissions @@ -229,12 +227,16 @@ export class DocumentOptions { layout_hideLinkButton?: BOOLt = new BoolInfo('whether the blue link counter button should be hidden'); layout_hideDecorationTitle?: BOOLt = new BoolInfo('whether to suppress the document decortations title when selected'); layout_borderRounding?: string; + _layout_nativeDimEditable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false); + _layout_reflowVertical?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); + _layout_reflowHorizontal?: BOOLt = new BoolInfo('whether a doc with a native size can be horizonally resized, causing some form of reflow'); layout_boxShadow?: string; // box-shadow css string OR "standard" to use dash standard box shadow layout_maxAutoHeight?: NUMt = new NumInfo('maximum height for newly created (eg, from pasting) text documents', false); _layout_autoHeight?: BOOLt = new BoolInfo('whether document automatically resizes vertically to display contents'); _layout_curPage?: NUMt = new NumInfo('current page of a PDF or other? paginated document', false); _layout_currentTimecode?: NUMt = new NumInfo('the current timecode of a time-based document (e.g., current time of a video) value is in seconds', false); _layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown'); + _layout_centered?: BOOLt = new BoolInfo('whether text should be vertically centered in Doc'); _layout_fitWidth?: BOOLt = new BoolInfo('whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)'); _layout_fitContentsToBox?: BOOLt = new BoolInfo('whether a freeformview should zoom/scale to create a shrinkwrapped view of its content'); _layout_fieldKey?: STRt = new StrInfo('the field key containing the current layout definition', false); @@ -472,9 +474,9 @@ export namespace Docs { _height: 35, _xMargin: 10, _yMargin: 10, - nativeDimModifiable: true, - nativeHeightUnfrozen: true, - layout_forceReflow: true, + layout_nativeDimEditable: true, + layout_reflowVertical: true, + layout_reflowHorizontal: true, defaultDoubleClick: 'ignore', systemIcon: 'BsFileEarmarkTextFill', }, @@ -505,7 +507,7 @@ export namespace Docs { DocumentType.WEB, { layout: { view: WebBox, dataField: defaultDataKey }, - options: { _height: 300, _layout_fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, waitForDoubleClickToClick: 'always', systemIcon: 'BsGlobe' }, + options: { _height: 300, _layout_fitWidth: true, layout_nativeDimEditable: true, layout_reflowVertical: true, waitForDoubleClickToClick: 'always', systemIcon: 'BsGlobe' }, }, ], [ @@ -533,7 +535,7 @@ export namespace Docs { DocumentType.AUDIO, { layout: { view: AudioBox, dataField: defaultDataKey }, - options: { _height: 100, layout_fitWidth: true, layout_forceReflow: true, nativeDimModifiable: true, systemIcon: 'BsFillVolumeUpFill' }, + options: { _height: 100, layout_fitWidth: true, layout_reflowHorizontal: true, layout_nativeDimEditable: true, systemIcon: 'BsFillVolumeUpFill' }, }, ], [ @@ -547,14 +549,14 @@ export namespace Docs { DocumentType.PDF, { layout: { view: PDFBox, dataField: defaultDataKey }, - options: { _layout_curPage: 1, _layout_fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, systemIcon: 'BsFileEarmarkPdfFill' }, + options: { _layout_curPage: 1, _layout_fitWidth: true, layout_nativeDimEditable: true, layout_reflowVertical: true, systemIcon: 'BsFileEarmarkPdfFill' }, }, ], [ DocumentType.MAP, { layout: { view: MapBox, dataField: defaultDataKey }, - options: { map: '', _height: 600, _width: 800, nativeDimModifiable: true, systemIcon: 'BsFillPinMapFill' }, + options: { map: '', _height: 600, _width: 800, layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true, systemIcon: 'BsFillPinMapFill' }, }, ], [ @@ -613,14 +615,14 @@ export namespace Docs { DocumentType.EQUATION, { layout: { view: EquationBox, dataField: 'text' }, - options: { nativeDimModifiable: true, fontSize: '14px', layout_hideResizeHandles: true, layout_hideDecorationTitle: true, systemIcon: 'BsCalculatorFill' }, ///systemIcon: 'BsSuperscript' + BsSubscript + options: { layout_nativeDimEditable: true, fontSize: '14px', layout_hideResizeHandles: true, layout_hideDecorationTitle: true, systemIcon: 'BsCalculatorFill' }, ///systemIcon: 'BsSuperscript' + BsSubscript }, ], [ DocumentType.FUNCPLOT, { layout: { view: FunctionPlotBox, dataField: defaultDataKey }, - options: { nativeDimModifiable: true }, + options: { layout_nativeDimEditable: true }, }, ], [ @@ -672,12 +674,12 @@ export namespace Docs { layout: { view: InkingStroke, dataField: 'stroke' }, options: { systemIcon: 'BsFillPencilFill', // - nativeDimModifiable: true, - nativeHeightUnfrozen: true, + layout_nativeDimEditable: true, + layout_reflowVertical: true, + layout_reflowHorizontal: true, layout_hideDecorationTitle: true, // don't show title when selected fitWidth: false, layout_isSvg: true, - layout_forceReflow: true, }, }, ], @@ -685,7 +687,7 @@ export namespace Docs { DocumentType.SCREENSHOT, { layout: { view: ScreenshotBox, dataField: defaultDataKey }, - options: { nativeDimModifiable: true, nativeHeightUnfrozen: true, systemIcon: 'BsCameraFill' }, + options: { layout_nativeDimEditable: true, systemIcon: 'BsCameraFill' }, }, ], [ @@ -714,14 +716,14 @@ export namespace Docs { DocumentType.DATAVIZ, { layout: { view: DataVizBox, dataField: defaultDataKey }, - options: { dataViz_title: '', dataViz_line: '', dataViz_pie: '', dataViz_histogram: '', dataViz: 'table', _layout_fitWidth: true, nativeDimModifiable: true }, + options: { dataViz_title: '', dataViz_line: '', dataViz_pie: '', dataViz_histogram: '', dataViz: 'table', _layout_fitWidth: true, layout_reflowHorizontal: true, layout_reflowVertical: true, layout_nativeDimEditable: true }, }, ], [ DocumentType.LOADING, { layout: { view: LoadingBox, dataField: '' }, - options: { _layout_fitWidth: true, _fitHeight: true, nativeDimModifiable: true }, + options: { _layout_fitWidth: true, _fitHeight: true, layout_nativeDimEditable: true }, }, ], [ @@ -731,11 +733,9 @@ export namespace Docs { layout: { view: PhysicsSimulationBox, dataField: defaultDataKey, _width: 1000, _height: 800 }, options: { _height: 100, - layout_forceReflow: true, - nativeHeightUnfrozen: true, mass1: '', mass2: '', - nativeDimModifiable: true, + layout_nativeDimEditable: true, position: '', acceleration: '', pendulum: '', @@ -948,7 +948,7 @@ export namespace Docs { export function ImageDocument(url: string | ImageField, options: DocumentOptions = {}, overwriteDoc?: Doc) { const imgField = url instanceof ImageField ? url : new ImageField(url); - return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { _nativeDimModifiable: false, _nativeHeightUnfrozen: false, title: basename(imgField.url.href), ...options }, undefined, undefined, undefined, overwriteDoc); + return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(imgField.url.href), ...options }, undefined, undefined, undefined, overwriteDoc); } export function PresDocument(options: DocumentOptions = {}) { @@ -1864,6 +1864,7 @@ export namespace DocUtils { _height: 35, x: x, y: y, + _layout_centered: BoolCast(Doc.UserDoc().layout_centered), _layout_fitWidth: true, _layout_autoHeight: true, _layout_enableAltContentUI: BoolCast(Doc.UserDoc().defaultToFlashcards), diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index cd19daee5..ac506e2d6 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -655,13 +655,13 @@ export class CurrentUserUtils { { title: "Under", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", toolType:"underline",ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'} }, { title: "Bullets", toolTip: "Bullet List", btnType: ButtonType.ToggleButton, icon: "list", toolType:"bullet", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'} }, { title: "#", toolTip: "Number List", btnType: ButtonType.ToggleButton, icon: "list-ol", toolType:"decimal", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'} }, + { title: "Vcenter", toolTip: "Vertical center", btnType: ButtonType.ToggleButton, icon: "pallet", toolType:"vcent", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'} }, { title: "Align", toolTip: "Alignment", btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true, subMenu: [ { title: "Left", toolTip: "Left align (Cmd-[)", btnType: ButtonType.ToggleButton, icon: "align-left", toolType:"left", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}' }}, { title: "Center", toolTip: "Center align (Cmd-\\)",btnType: ButtonType.ToggleButton, icon: "align-center",toolType:"center",ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'} }, { title: "Right", toolTip: "Right align (Cmd-])", btnType: ButtonType.ToggleButton, icon: "align-right", toolType:"right", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'} }, - ] - }, + ]}, { title: "Dictate", toolTip: "Dictate", btnType: ButtonType.ToggleButton, icon: "microphone", toolType:"dictation", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'}}, { title: "NoLink", toolTip: "Auto Link", btnType: ButtonType.ToggleButton, icon: "link", toolType:"noAutoLink", expertMode:true, scripts: {onClick: '{ return toggleCharStyle(self.toolType, _readOnly_);}'}, funcs: {hidden: 'IsNoviceMode()'}}, // { title: "Strikethrough", tooltip: "Strikethrough", btnType: ButtonType.ToggleButton, icon: "strikethrough", scripts: {onClick:: 'toggleStrikethrough()'}}, diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 33886e791..8df5740fa 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -2,18 +2,17 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import { IconButton } from 'browndash-components'; -import { action, computed, observable, reaction } from 'mobx'; +import { action, computed, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { FaUndo } from 'react-icons/fa'; -import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Field, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, DocData } from '../../fields/DocSymbols'; import { InkField } from '../../fields/InkField'; import { RichTextField } from '../../fields/RichTextField'; import { ScriptField } from '../../fields/ScriptField'; -import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; +import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; import { GetEffectiveAcl } from '../../fields/util'; -import { aggregateBounds, emptyFunction, numberValue, returnFalse, setupMoveUpEvents, Utils } from '../../Utils'; +import { emptyFunction, numberValue, returnFalse, setupMoveUpEvents, Utils } from '../../Utils'; import { Docs } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; import { DocumentManager } from '../util/DocumentManager'; @@ -36,6 +35,7 @@ import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { ImageBox } from './nodes/ImageBox'; import React = require('react'); import _ = require('lodash'); +import { DateField } from '../../fields/DateField'; @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> { @@ -46,11 +46,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P private _linkBoxHeight = 20 + 3; // link button height + margin private _titleHeight = 20; private _resizeUndo?: UndoManager.Batch; - private _offX = 0; - private _offY = 0; // offset from click pt to inner edge of resize border - private _snapX = 0; - private _snapY = 0; // last snapped location of resize border - private _dragHeights = new Map<Doc, { start: number; lowest: number }>(); + private _offset = { x: 0, y: 0 }; // offset from click pt to inner edge of resize border + private _snapPt = { x: 0, y: 0 }; // last snapped location of resize border private _inkDragDocs: { doc: Doc; x: number; y: number; width: number; height: number }[] = []; @observable private _accumulatedTitle = ''; @@ -479,29 +476,24 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P DocumentView.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them this._resizeHdlId = e.currentTarget.className; const bounds = e.currentTarget.getBoundingClientRect(); - this._offX = this._resizeHdlId.toLowerCase().includes('left') ? bounds.right - e.clientX : bounds.left - e.clientX; - this._offY = this._resizeHdlId.toLowerCase().includes('top') ? bounds.bottom - e.clientY : bounds.top - e.clientY; + this._offset = { x: this._resizeHdlId.toLowerCase().includes('left') ? bounds.right - e.clientX : bounds.left - e.clientX, y: this._resizeHdlId.toLowerCase().includes('top') ? bounds.bottom - e.clientY : bounds.top - e.clientY }; this._resizeUndo = UndoManager.StartBatch('drag resizing'); - this._snapX = e.pageX; - this._snapY = e.pageY; - const ffviewSet = new Set<CollectionFreeFormView>(); - SelectionManager.Views().forEach(docView => { - docView.CollectionFreeFormView && ffviewSet.add(docView.CollectionFreeFormView); - this._dragHeights.set(docView.layoutDoc, { start: NumCast(docView.rootDoc._height), lowest: NumCast(docView.rootDoc._height) }); - }); - Array.from(ffviewSet).map(ffview => ffview.dragStarting(false, false)); + this._snapPt = { x: e.pageX, y: e.pageY }; + SelectionManager.Views().forEach(docView => docView.CollectionFreeFormView?.dragStarting(false, false)); }; + _lock: any; onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => { const first = SelectionManager.Views()[0]; const effectiveAcl = GetEffectiveAcl(first.rootDoc); if (!(effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment)) return false; if (!first) return false; - let thisPt = { x: e.clientX - this._offX, y: e.clientY - this._offY }; + let thisPt = { x: e.clientX - this._offset.x, y: e.clientY - this._offset.y }; var fixedAspect = Doc.NativeAspect(first.layoutDoc); + const dragHdl = this._resizeHdlId.split(' ')[0].replace('documentDecorations-', '').replace('Resizer', ''); - const resizeHdl = this._resizeHdlId.split(' ')[0]; - if (fixedAspect && (resizeHdl === 'documentDecorations-bottomRightResizer' || resizeHdl === 'documentDecorations-topLeftResizer')) { + // do snapping of drag point + if (fixedAspect && (dragHdl === 'bottomRight' || dragHdl === 'topLeft')) { // need to generalize for bl and tr drag handles const project = (p: number[], a: number[], b: number[]) => { const atob = [b[0] - a[0], b[1] - a[1]]; @@ -513,173 +505,124 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P return [a[0] + atob[0] * t, a[1] + atob[1] * t]; }; const tl = first.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); - const drag = project([e.clientX + this._offX, e.clientY + this._offY], tl, [tl[0] + fixedAspect, tl[1] + 1]); + const drag = project([e.clientX + this._offset.x, e.clientY + this._offset.y], tl, [tl[0] + fixedAspect, tl[1] + 1]); thisPt = DragManager.snapDragAspect(drag, fixedAspect); } else { - thisPt = DragManager.snapDrag(e, -this._offX, -this._offY, this._offX, this._offY); + thisPt = DragManager.snapDrag(e, -this._offset.x, -this._offset.y, this._offset.x, this._offset.y); } - move[0] = thisPt.x - this._snapX; - move[1] = thisPt.y - this._snapY; - this._snapX = thisPt.x; - this._snapY = thisPt.y; - let dragBottom = false, - dragRight = false, - dragBotRight = false, - dragTop = false; - let dXin = 0, - dYin = 0, - dWin = 0, - dHin = 0; - switch (this._resizeHdlId.split(' ')[0]) { - case '': - break; - case 'documentDecorations-topLeftResizer': - dXin = -1; - dYin = -1; - dWin = -move[0]; - dHin = -move[1]; - break; - case 'documentDecorations-topRightResizer': - dWin = move[0]; - dYin = -1; - dHin = -move[1]; - break; - case 'documentDecorations-topResizer': - dYin = -1; - dHin = -move[1]; - dragTop = true; - break; - case 'documentDecorations-bottomLeftResizer': - dXin = -1; - dWin = -move[0]; - dHin = move[1]; - break; - case 'documentDecorations-bottomRightResizer': - dWin = move[0]; - dHin = move[1]; - dragBotRight = true; - break; - case 'documentDecorations-bottomResizer': - dHin = move[1]; - dragBottom = true; - break; - case 'documentDecorations-leftResizer': - dXin = -1; - dWin = -move[0]; - break; - case 'documentDecorations-rightResizer': - dWin = move[0]; - dragRight = true; - break; - } + const { scale, refPt } = this.getResizeVals(thisPt, dragHdl); + // resize selected docs + !this._lock && runInAction(async () => { + this._lock = true; + this._snapPt = thisPt; + e.ctrlKey && (SelectionManager.Views().forEach(docView => !Doc.NativeHeight(docView.props.Document) && docView.toggleNativeDimensions())); + const fixedAspect = SelectionManager.Docs().some(this.hasFixedAspect); + SelectionManager.Views().forEach(docView => + this.resizeView(docView, refPt, scale.x === 1 && fixedAspect ? scale.y : scale.x, + scale.x !== 1 && fixedAspect ? scale.x : scale.y, { dragHdl, ctrlKey:e.ctrlKey })); // prettier-ignore + await new Promise<any>(res => setTimeout(() => res(this._lock = undefined))); + }); // prettier-ignore - const isGroup = first.rootDoc._isGroup ? first.rootDoc : undefined; - const scaleViews = isGroup ? DocListCast(isGroup.data).map(doc => DocumentManager.Instance.getFirstDocumentView(doc)!) : SelectionManager.Views(); - const aggBounds = aggregateBounds(scaleViews.map(view => view.rootDoc) as any, 0, 0); - const refWidth = aggBounds.r - aggBounds.x; - const refHeight = aggBounds.b - aggBounds.y; - const scaleRefPt = first.props - .ScreenToLocalTransform() - .inverse() - .transformPoint( - NumCast(isGroup?._xPadding) + (dXin ? refWidth : 0), // - NumCast(isGroup?._yPadding) + (dYin ? refHeight : 0) - ); - scaleViews.forEach( - action((docView: DocumentView) => { - if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions(); - if (dXin !== 0 || dYin !== 0 || dWin !== 0 || dHin !== 0) { - const doc = docView.rootDoc; - const refCent = docView.props.ScreenToLocalTransform().transformPoint(scaleRefPt[0], scaleRefPt[1]); - - if (doc.nativeHeightUnfrozen && !NumCast(doc.nativeHeight) && doc._nativeWidth !== undefined) { - doc._nativeHeight = (NumCast(doc._height) / NumCast(doc._width, 1)) * docView.nativeWidth; - } - const nwidth = docView.nativeWidth; - const nheight = docView.nativeHeight; - const docwidth = NumCast(doc._width); - let docheight = (hgt => (!hgt || isNaN(hgt) ? 20 : hgt))(NumCast(doc._height) || (nheight / nwidth) * docwidth); - let dW = docwidth * (dWin / refWidth); - let dH = docheight * (dHin / refHeight); - const scale = docView.props.ScreenToLocalTransform().Scale; - const modifyNativeDim = (e.ctrlKey && doc.nativeDimModifiable) || (doc.layout_forceReflow && !dragBottom && !dragTop) || (doc.nativeHeightUnfrozen && (dragBottom || dragTop || e.ctrlKey)); - if (nwidth && nheight) { - if (nwidth / nheight !== docwidth / docheight && !dragBottom && !dragTop) { - docheight = (nheight / nwidth) * docwidth; - } - if (modifyNativeDim && !dragBottom && !dragTop) { - // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction - if (Math.abs(dW) > Math.abs(dH)) dH = (dW * nheight) / nwidth; - else dW = (dH * nwidth) / nheight; - } - } - let actualdW = Math.max(docwidth + dW * scale, 20); - let actualdH = Math.max(docheight + dH * scale, 20); - let dX = !dWin ? 0 : (scale * refCent[0] * -dWin) / refWidth; - let dY = !dHin ? 0 : (scale * refCent[1] * -dHin) / refHeight; - const preserveNativeDim = !doc._nativeHeightUnfrozen && !doc._nativeDimModifiable; - const fixedAspect = nwidth && nheight && (!doc._layout_fitWidth || preserveNativeDim || e.ctrlKey || doc.nativeHeightUnfrozen || doc.nativeDimModifiable); - if (fixedAspect) { - if ((Math.abs(dW) > Math.abs(dH) && ((!dragBottom && !dragTop) || !modifyNativeDim)) || dragRight) { - if (dragRight && modifyNativeDim) { - if (Doc.NativeWidth(doc)) { - doc._nativeWidth = (actualdW / (docwidth || 1)) * Doc.NativeWidth(doc); - } - } else { - if (!doc._layout_fitWidth || preserveNativeDim) { - actualdH = (nheight / nwidth) * actualdW; - dYin && (dY = -dW * scale * (nheight / nwidth)); - doc._height = actualdH; - } else if (!modifyNativeDim || dragBotRight) { - doc._height = actualdH; - } - } - doc._width = actualdW; - } else { - if ((dragBottom || dragTop) && (modifyNativeDim || (docView.layoutDoc.nativeHeightUnfrozen && docView.layoutDoc._layout_fitWidth))) { - // frozen web pages, PDFs, and some RTFS have frozen nativewidth/height. But they are marked to allow their nativeHeight - // to be explicitly modified with fitWidth and vertical resizing. (ie, with fitWidth they can't grow horizontally to match - // a vertical resize so it makes more sense to change their nativeheight even if the ctrl key isn't used) - doc._nativeHeight = (actualdH / (docheight || 1)) * Doc.NativeHeight(doc); - doc._layout_autoHeight = false; - } else { - if (!doc._layout_fitWidth || preserveNativeDim) { - actualdW = (nwidth / nheight) * actualdH; - dXin && (dX = -dH * scale * (nwidth / nheight)); - doc._width = actualdW; - } else if (!modifyNativeDim || dragBotRight) { - doc._width = actualdW; - } - } - if (!modifyNativeDim) { - actualdH = (nheight / nwidth) * NumCast(doc._width); //, actualdH); - } - doc._height = actualdH; - } - } else { - const rotCtr = [docwidth / 2, docheight / 2]; - const tlRotated = Utils.rotPt(-rotCtr[0], -rotCtr[1], (NumCast(doc._rotation) / 180) * Math.PI); - - const maxHeight = doc.nativeHeightUnfrozen || !nheight ? 0 : Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '_scrollHeight']))) * docView.NativeDimScaling(); - dH && (doc._height = actualdH > maxHeight && maxHeight ? maxHeight : actualdH); - dW && (doc._width = actualdW); - dH && (doc._layout_autoHeight = false); - - const rotCtr2 = [NumCast(doc._width) / 2, NumCast(doc._height) / 2]; - const tlRotated2 = Utils.rotPt(-rotCtr2[0], -rotCtr2[1], (NumCast(doc._rotation) / 180) * Math.PI); - doc.x = NumCast(doc.x) + tlRotated.x + rotCtr[0] - (tlRotated2.x + rotCtr2[0]); // doc shifts by amount topleft moves because rotation is about center of doc - doc.y = NumCast(doc.y) + tlRotated.y + rotCtr[1] - (tlRotated2.y + rotCtr2[1]); - } - doc.x = NumCast(doc.x) + dX; - doc.y = NumCast(doc.y) + dY; - doc._layout_modificationDate = new DateField(); + return false; + }; + + // + // determines how much to resize, and determines the resize reference point + // + getResizeVals = (thisPt: { x: number; y: number }, dragHdl: string) => { + const [w, h] = [this.Bounds.r - this.Bounds.x, this.Bounds.b - this.Bounds.y]; + const [moveX, moveY] = [thisPt.x - this._snapPt.x, thisPt.y - this._snapPt.y]; + switch (dragHdl) { + case 'topLeft': return { scale: { x: 1 - moveX / w, y: 1 -moveY / h }, refPt: [this.Bounds.r, this.Bounds.b] }; + case 'topRight': return { scale: { x: 1 + moveX / w, y: 1 -moveY / h }, refPt: [this.Bounds.x, this.Bounds.b] }; + case 'top': return { scale: { x: 1, y: 1 -moveY / h }, refPt: [this.Bounds.x, this.Bounds.b] }; + case 'left': return { scale: { x: 1 - moveX / w, y: 1 }, refPt: [this.Bounds.r, this.Bounds.y] }; + case 'bottomLeft': return { scale: { x: 1 - moveX / w, y: 1 + moveY / h }, refPt: [this.Bounds.r, this.Bounds.y] }; + case 'right': return { scale: { x: 1 + moveX / w, y: 1 }, refPt: [this.Bounds.x, this.Bounds.y] }; + case 'bottomRight':return { scale: { x: 1 + moveX / w, y: 1 + moveY / h }, refPt: [this.Bounds.x, this.Bounds.y] }; + case 'bottom': return { scale: { x: 1, y: 1 + moveY / h }, refPt: [this.Bounds.x, this.Bounds.y] }; + default: return { scale: { x: 1, y: 1 }, refPt: [this.Bounds.x, this.Bounds.y] }; + } // prettier-ignore + }; + + // + // determines if anything being dragged directly or via a group has a fixed aspect ratio (in which case we resize uniformly) + // + hasFixedAspect = (doc: Doc): boolean => (doc.isGroup ? DocListCast(doc.data).some(this.hasFixedAspect) : !BoolCast(doc.layout_nativeDimEditable)); + + // + // resize a single DocumentView about the specified reference point, possibly setting/updating the native dimensions of the Doc + // + resizeView = (docView: DocumentView, refPt: number[], scaleX: number, scaleY: number, opts: { dragHdl: string; ctrlKey: boolean }) => { + const doc = docView.rootDoc; + if (doc.isGroup) { + DocListCast(doc.data) + .map(member => DocumentManager.Instance.getDocumentView(member, docView)!) + .forEach(member => this.resizeView(member, refPt, scaleX, scaleY, opts)); + doc.xPadding = NumCast(doc.xPadding) * scaleX; + doc.yPadding = NumCast(doc.yPadding) * scaleY; + } else { + const doc = docView.rootDoc; + const refCent = docView.props.ScreenToLocalTransform().transformPoint(refPt[0], refPt[1]); // fixed reference point for resize (ie, a point that doesn't move) + const [nwidth, nheight] = [docView.nativeWidth, docView.nativeHeight]; + const [initWidth, initHeight] = [NumCast(doc._width, 1), NumCast(doc._height)]; + + const modifyNativeDim = + (opts.ctrlKey && doc.layout_nativeDimEditable) || // e.g., PDF or web page + (doc.layout_reflowHorizontal && opts.dragHdl !== 'bottom' && opts.dragHdl !== 'top') || // eg rtf or some web pages + (doc.layout_reflowVertical && (opts.dragHdl === 'bottom' || opts.dragHdl === 'top' || opts.ctrlKey)); // eg rtf, web, pdf + if (nwidth && nheight && !modifyNativeDim) { + // eg., dragging right resizer on PDF -- enforce native dimensions because not expliclty overridden with ctrl or bottom resize drag + scaleX === 1 ? (scaleX = scaleY) : (scaleY = scaleX); + } + + if (['right', 'left'].includes(opts.dragHdl) && modifyNativeDim && Doc.NativeWidth(doc)) { + const setData = Doc.NativeWidth(Doc.GetProto(doc)) === doc.nativeWidth; + doc.nativeWidth = scaleX * Doc.NativeWidth(doc); + if (setData) Doc.SetNativeWidth(Doc.GetProto(doc), NumCast(doc.nativeWidth)); + if (doc.layout_reflowVertical && !NumCast(doc.nativeHeight)) { + doc._nativeHeight = (initHeight / initWidth) * nwidth; // initializes the nativeHeight for a PDF } - const val = this._dragHeights.get(docView.layoutDoc); - if (val) this._dragHeights.set(docView.layoutDoc, { start: val.start, lowest: Math.min(val.lowest, NumCast(docView.layoutDoc._height)) }); - }) + } + if (['bottom', 'top'].includes(opts.dragHdl) && modifyNativeDim && Doc.NativeHeight(doc)) { + const setData = Doc.NativeHeight(Doc.GetProto(doc)) === doc.nativeHeight; + doc._nativeHeight = scaleY * Doc.NativeHeight(doc); + if (setData) Doc.SetNativeHeight(Doc.GetProto(doc), NumCast(doc._nativeHeight)); + } + + doc._width = NumCast(doc._width) * scaleX; + doc._height = NumCast(doc._height) * scaleY; + const { deltaX, deltaY } = this.realignRefPt(doc, refCent, initWidth, initHeight); + doc.x = NumCast(doc.x) + deltaX; + doc.y = NumCast(doc.y) + deltaY; + + doc._layout_modificationDate = new DateField(); + scaleY !== 1 && (doc._layout_autoHeight = undefined); + } + }; + + // This realigns the doc's resize reference point with where it was before resizing it. + // This is needed, because the transformation for doc's with a rotation is screwy: + // the top left of the doc is the 'origin', but the rotation happens about the center of the Doc. + // So resizing a rotated doc will cause it to shift -- this counteracts that shift by determine how + // the reference points shifted, and returning a translation to restore the reference point. + realignRefPt = (doc: Doc, refCent: number[], initWidth: number, initHeight: number) => { + const refCentPct = [refCent[0] / initWidth, refCent[1] / initHeight]; + const rotRefStart = Utils.rotPt( + refCent[0] - initWidth / 2, // rotate reference pointe before scaling + refCent[1] - initHeight / 2, + (NumCast(doc._rotation) / 180) * Math.PI ); - return false; + const rotRefEnd = Utils.rotPt( + refCentPct[0] * NumCast(doc._width) - NumCast(doc._width) / 2, // rotate reference point after scaling + refCentPct[1] * NumCast(doc._height) - NumCast(doc._height) / 2, + (NumCast(doc._rotation) / 180) * Math.PI + ); + return { + deltaX: rotRefStart.x + initWidth / 2 - (rotRefEnd.x + NumCast(doc._width) / 2), // + deltaY: rotRefStart.y + initHeight / 2 - (rotRefEnd.y + NumCast(doc._height) / 2), + }; }; @action @@ -691,10 +634,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P SnappingManager.clearSnapLines(); // detect layout_autoHeight gesture and apply - SelectionManager.Views() - .map(docView => ({ doc: docView.layoutDoc, hgts: this._dragHeights.get(docView.layoutDoc) })) - .filter(pair => pair.hgts && pair.hgts.lowest < pair.hgts.start && pair.hgts.lowest <= 20) - .forEach(pair => (pair.doc._layout_autoHeight = true)); + SelectionManager.Docs().forEach(doc => NumCast(doc._height) < 20 && (doc._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 || [] })) diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx index 0d7f7ebd8..e5141b7f4 100644 --- a/src/client/views/InkControlPtHandles.tsx +++ b/src/client/views/InkControlPtHandles.tsx @@ -12,6 +12,7 @@ import { UndoManager } from '../util/UndoManager'; import { Colors } from './global/globalEnums'; import { InkingStroke } from './InkingStroke'; import { InkStrokeProperties } from './InkStrokeProperties'; +import { SnappingManager } from '../util/SnappingManager'; export interface InkControlProps { inkDoc: Doc; @@ -190,6 +191,7 @@ export class InkEndPtHandles extends React.Component<InkEndProps> { @action dragRotate = (e: React.PointerEvent, pt1: () => { X: number; Y: number }, pt2: () => { X: number; Y: number }) => { + SnappingManager.SetIsDragging(true); setupMoveUpEvents( this, e, @@ -211,6 +213,7 @@ export class InkEndPtHandles extends React.Component<InkEndProps> { return false; }), action(() => { + SnappingManager.SetIsDragging(false); this.props.inkView.controlUndo?.end(); this.props.inkView.controlUndo = undefined; UndoManager.FilterBatches(['stroke', 'x', 'y', 'width', 'height']); @@ -237,8 +240,8 @@ export class InkEndPtHandles extends React.Component<InkEndProps> { ); return ( <svg> - {hdl('start', this.props.startPt(), (e: React.PointerEvent) => this.dragRotate(e, this.props.startPt, this.props.endPt))} - {hdl('end', this.props.endPt(), (e: React.PointerEvent) => this.dragRotate(e, this.props.endPt, this.props.startPt))} + {hdl('start', this.props.startPt(), e => this.dragRotate(e, this.props.startPt, this.props.endPt))} + {hdl('end', this.props.endPt(), e => this.dragRotate(e, this.props.endPt, this.props.startPt))} </svg> ); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index a6f0b9e84..5bed0f923 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -252,6 +252,7 @@ export class MainView extends React.Component { fa.faShare, fa.faTaxi, fa.faDownload, + fa.faPallet, fa.faExpandArrowsAlt, fa.faAmbulance, fa.faLayerGroup, diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 81453c0b8..c2586fb4b 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -295,7 +295,7 @@ export class CollectionMulticolumnView extends CollectionSubView() { const aspect = Doc.NativeAspect(layout, undefined, true); const width = () => this.lookupPixels(layout); const height = () => PanelHeight() - 2 * NumCast(Document._yMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0); - const docwidth = () => (layout._layout_forceReflow ? width() : Math.min(height() * aspect, width())); + const docwidth = () => (layout._layout_reflowHorizontal ? width() : Math.min(height() * aspect, width())); const docheight = () => Math.min(docwidth() / aspect, height()); const dxf = () => this.lookupIndividualTransform(layout) diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 04cfc5456..249c3551b 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -292,7 +292,7 @@ export class CollectionMultirowView extends CollectionSubView() { const height = () => this.lookupPixels(layout); const width = () => PanelWidth() - 2 * NumCast(Document._xMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0); const docheight = () => Math.min(width() / aspect, height()); - const docwidth = () => (layout._layout_forceReflow ? width() : Math.min(width(), docheight() * aspect)); + const docwidth = () => (layout._layout_reflowHorizontal ? width() : Math.min(width(), docheight() * aspect)); const dxf = () => this.lookupIndividualTransform(layout) .translate(-NumCast(Document._xMargin) - (width() - docwidth()) / 2, -NumCast(Document._yMargin) - (height() - docheight()) / 2) diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index c690b8623..3af523d73 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -181,16 +181,22 @@ ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highligh map.get(attr)?.setDoc?.(); }); -type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'underline' | 'left' | 'center' | 'right' | 'bullet' | 'decimal'; +type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'underline' | 'left' | 'center' | 'right' | 'vcent' | 'bullet' | 'decimal'; type attrfuncs = [attrname, { checkResult: () => boolean; toggle: () => any }]; ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) { const textView = RichTextMenu.Instance?.TextView; const editorView = textView?.EditorView; // prettier-ignore - const alignments:attrfuncs[] = (['left','right','center'] as ("left"|"center"|"right")[]).map((where) => - [ where, { checkResult: () =>(editorView ? (RichTextMenu.Instance.textAlign ===where): (Doc.UserDoc().textAlign ===where) ? true:false), - toggle: () => (editorView?.state ? RichTextMenu.Instance.align(editorView, editorView.dispatch, where):(Doc.UserDoc().textAlign = where))}]); + const alignments:attrfuncs[] = (['left','right','center','vcent'] as ("left"|"center"|"right"|"vcent")[]).map((where) => + [ where, { checkResult: () =>(editorView ? (where === 'vcent' ? SelectionManager.Docs().some(doc => doc.layout_centered): + (RichTextMenu.Instance.textAlign === where)): + where === 'vcent' ? BoolCast(Doc.UserDoc().layout_centered): + (Doc.UserDoc().textAlign ===where) ? true:false), + toggle: () => (editorView?.state ? (where === 'vcent' ? SelectionManager.Docs().forEach(doc => doc.layout_centered = !doc.layout_centered): + RichTextMenu.Instance.align(editorView, editorView.dispatch, where)): + where === 'vcent' ? Doc.UserDoc().layout_centered = !Doc.UserDoc().layout_centered: + (Doc.UserDoc().textAlign = where))}]); // prettier-ignore // prettier-ignore const listings:attrfuncs[] = (['bullet','decimal'] as attrname[]).map(list => [ list, { checkResult: () => (editorView ? RichTextMenu.Instance.getActiveListStyle() === list:false), diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index a05d6c904..582a5518a 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -62,7 +62,7 @@ export class CollectionFreeFormDocumentViewWrapper extends DocComponent<Collecti w_Y = () => this.Y; // prettier-ignore w_Z = () => this.Z; // prettier-ignore w_ZIndex = () => this.ZIndex ?? NumCast(this.props.Document.zIndex); // prettier-ignore - w_Rot = () => this.Rotation ?? NumCast(this.props.Document._rotation); // prettier-ignore + w_Rotation = () => this.Rotation ?? NumCast(this.props.Document._rotation); // prettier-ignore w_Opacity = () => this.Opacity; // prettier-ignore w_BackgroundColor = () => this.BackgroundColor ?? Cast(this.props.Document._backgroundColor, 'string', null); // prettier-ignore w_Color = () => this.Color ?? Cast(this.props.Document._color, 'string', null); // prettier-ignore diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 299494c83..b3f813eda 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -115,8 +115,8 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { layoutDoc: this.layoutDoc, records: this.records, axes: this.axes, - height: (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9, - width: this.props.PanelWidth() * 0.9, + height: (this.props.PanelHeight() * (this.props.NativeDimScaling?.() || 1) - 32) /* height of 'change view' button */ * 0.9, + width: this.props.PanelWidth() * (this.props.NativeDimScaling?.() || 1) * 0.9, margin: { top: 10, right: 25, bottom: 75, left: 45 }, }; if (!this.records.length) return 'no data/visualization'; @@ -133,6 +133,8 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { }; render() { + const scale = this.props.NativeDimScaling?.() || 1; + return !this.records.length ? ( // displays how to get data into the DataVizBox if its empty <div className="start-message">To create a DataViz box, either import / drag a CSV file into your canvas or copy a data table and use the command 'ctrl + p' to bring the data table to your canvas.</div> @@ -141,6 +143,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { className="dataViz" style={{ pointerEvents: this.props.isContentActive() === true ? 'all' : 'none', + width: `${100 / scale}%`, + height: `${100 / scale}%`, + transform: `scale(${scale})`, + position: 'absolute', }} onWheel={e => e.stopPropagation()} ref={r => diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d1caf0acf..e3d6c3fdf 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1495,7 +1495,7 @@ export class DocumentView extends React.Component<DocumentViewProps> { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); } @computed get panelHeight() { - if (this.effectiveNativeHeight && (!this.layout_fitWidth || !this.layoutDoc.nativeHeightUnfrozen)) { + if (this.effectiveNativeHeight && (!this.layout_fitWidth || !this.layoutDoc.layout_reflowVertical)) { return Math.min(this.props.PanelHeight(), this.effectiveNativeHeight * this.nativeScaling); } return this.props.PanelHeight(); @@ -1507,7 +1507,7 @@ export class DocumentView extends React.Component<DocumentViewProps> { return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 && - (!this.layoutDoc.nativeHeightUnfrozen || (!this.layout_fitWidth && this.effectiveNativeHeight * this.nativeScaling <= this.props.PanelHeight())) + (!this.layoutDoc.layout_reflowVertical || (!this.layout_fitWidth && this.effectiveNativeHeight * this.nativeScaling <= this.props.PanelHeight())) ? Math.max(0, (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2) : 0; } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index bde1d5fa4..185c6553a 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -347,7 +347,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps toggleSidebar = action((preview: boolean = false) => { const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']); const sideratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? PDFBox.openSidebarWidth : 0) + nativeWidth) / nativeWidth; - const pdfratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? PDFBox.openSidebarWidth + PDFBox.sidebarResizerWidth : 0) + nativeWidth) / nativeWidth; + const pdfratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? PDFBox.openSidebarWidth + PDFBox.sidebarResizerWidth : 0) + NumCast(this.layoutDoc._width)) / NumCast(this.layoutDoc._width); const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth); if (preview) { this._previewNativeWidth = nativeWidth * sideratio; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index a452b1cdd..d9ea48c3b 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -707,10 +707,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps icon: 'snowflake', }); funcs.push({ - description: (!this.layoutDoc.layout_forceReflow ? 'Force' : 'Prevent') + ' Reflow', + description: (!this.layoutDoc.layout_reflowHorizontal ? 'Force' : 'Prevent') + ' Reflow', event: () => { - const nw = !this.layoutDoc.layout_forceReflow ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this.props.NativeDimScaling?.() || 1); - this.layoutDoc.layout_forceReflow = !nw; + const nw = !this.layoutDoc.layout_reflowHorizontal ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this.props.NativeDimScaling?.() || 1); + this.layoutDoc.layout_reflowHorizontal = !nw; if (nw) { Doc.SetInPlace(this.layoutDoc, this.fieldKey + '_nativeWidth', nw, true); } @@ -872,13 +872,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps toggleSidebar = action((preview: boolean = false) => { var nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']); if (!nativeWidth) { - const defaultNativeWidth = this.rootDoc[this.fieldKey] instanceof WebField ? 850 : NumCast(this.Document._width); + const defaultNativeWidth = NumCast(this.rootDoc.nativeWidth, this.rootDoc[this.fieldKey] instanceof WebField ? 850 : NumCast(this.Document._width)); Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(this.dataDoc) || defaultNativeWidth); Doc.SetNativeHeight(this.dataDoc, Doc.NativeHeight(this.dataDoc) || (NumCast(this.Document._height) / NumCast(this.Document._width)) * defaultNativeWidth); nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']); } const sideratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? WebBox.openSidebarWidth : 0) + nativeWidth) / nativeWidth; - const pdfratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? WebBox.openSidebarWidth + WebBox.sidebarResizerWidth : 0) + nativeWidth) / nativeWidth; + const pdfratio = ((!this.layoutDoc.nativeWidth || this.layoutDoc.nativeWidth === nativeWidth ? WebBox.openSidebarWidth + WebBox.sidebarResizerWidth : 0) + NumCast(this.layoutDoc.width)) / NumCast(this.layoutDoc.width); const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth); if (preview) { this._previewNativeWidth = nativeWidth * sideratio; @@ -890,6 +890,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps if (!this.layoutDoc._layout_showSidebar && !(this.dataDoc[this.fieldKey] instanceof WebField)) { this.layoutDoc.nativeWidth = this.dataDoc[this.fieldKey + '_nativeWidth'] = undefined; } else { + !this.layoutDoc._layout_showSidebar && (this.dataDoc[this.fieldKey + '_nativeWidth'] = this.dataDoc[this.fieldKey + '_nativeHeight'] = undefined); this.layoutDoc.nativeWidth = nativeWidth * pdfratio; } } @@ -917,7 +918,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps className={'webBox-cont' + (interactive ? '-interactive' : '')} onKeyDown={e => e.stopPropagation()} style={{ - width: !this.layoutDoc.layout_forceReflow ? NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']) || `100%` : '100%', + width: !this.layoutDoc.layout_reflowHorizontal ? NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']) || `100%` : '100%', transform: `scale(${this.zoomScaling()}) translate(${-NumCast(this.layoutDoc.freeform_panX)}px, ${-NumCast(this.layoutDoc.freeform_panY)}px)`, }}> {this._hackHide ? null : this.urlContent} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 9ab3189a6..a80c1e030 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -704,14 +704,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps @action toggleSidebar = (preview: boolean = false) => { + const defaultSidebar = 250; const prevWidth = 1 - this.sidebarWidth() / Number(getComputedStyle(this._ref.current!).width.replace('px', '')); if (preview) this._showSidebar = true; else { this.layoutDoc[this.SidebarKey + '_freeform_scale_max'] = 1; - this.layoutDoc._layout_showSidebar = (this.layoutDoc._layout_sidebarWidthPercent = StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%') === '0%' ? '50%' : '0%') !== '0%'; + this.layoutDoc._layout_showSidebar = + (this.layoutDoc._layout_sidebarWidthPercent = StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%') === '0%' ? `${(defaultSidebar / (NumCast(this.layoutDoc._width) + defaultSidebar)) * 100}%` : '0%') !== '0%'; } - this.layoutDoc._width = !preview && this.SidebarShown ? NumCast(this.layoutDoc._width) * 2 : Math.max(20, NumCast(this.layoutDoc._width) * prevWidth); + this.layoutDoc._width = !preview && this.SidebarShown ? NumCast(this.layoutDoc._width) + defaultSidebar : Math.max(20, NumCast(this.layoutDoc._width) * prevWidth); }; sidebarDown = (e: React.PointerEvent) => { const batch = UndoManager.StartBatch('toggle sidebar'); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 6dece87b5..e91fcd858 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1295,17 +1295,11 @@ export namespace Doc { layoutDoc._freeform_scale = NumCast(layoutDoc._freeform_scale, 1) * contentScale; layoutDoc._nativeWidth = undefined; layoutDoc._nativeHeight = undefined; - layoutDoc._layout_forceReflow = undefined; - layoutDoc._nativeHeightUnfrozen = undefined; - layoutDoc._nativeDimModifiable = undefined; } else { layoutDoc._layout_autoHeight = false; if (!Doc.NativeWidth(layoutDoc)) { layoutDoc._nativeWidth = NumCast(layoutDoc._width, panelWidth); layoutDoc._nativeHeight = NumCast(layoutDoc._height, panelHeight); - layoutDoc._layout_forceReflow = true; - layoutDoc._nativeHeightUnfrozen = true; - layoutDoc._nativeDimModifiable = true; } } }); |