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.tsx66
1 files changed, 41 insertions, 25 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 1feb643df..29e088143 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -19,6 +19,7 @@ import { SelectionManager } from "../util/SelectionManager";
import { SnappingManager } from '../util/SnappingManager';
import { undoBatch, UndoManager } from "../util/UndoManager";
import { CollectionDockingView } from './collections/CollectionDockingView';
+import { CollectionFreeFormView } from './collections/collectionFreeForm';
import { DocumentButtonBar } from './DocumentButtonBar';
import './DocumentDecorations.scss';
import { KeyManager } from './GlobalKeyHandler';
@@ -27,8 +28,8 @@ import { InkStrokeProperties } from './InkStrokeProperties';
import { LightboxView } from './LightboxView';
import { DocumentView } from "./nodes/DocumentView";
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
+import { ImageBox } from './nodes/ImageBox';
import React = require("react");
-import { CollectionFreeFormView } from './collections/collectionFreeForm';
@observer
export class DocumentDecorations extends React.Component<{ PanelWidth: number, PanelHeight: number, boundsLeft: number, boundsTop: number }, { value: string }> {
@@ -48,7 +49,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
@observable private _titleControlString: string = "#title";
@observable private _edtingTitle = false;
@observable private _hidden = false;
-
+ @observable public AddToSelection = false; // if Shift is pressed, then this should be set so that clicking on the selection background is ignored so overlapped documents can be added to the selection set.
@observable public Interacting = false;
@observable public pushIcon: IconProp = "arrow-alt-circle-up";
@observable public pullIcon: IconProp = "arrow-alt-circle-down";
@@ -63,7 +64,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
@computed
get Bounds() {
const views = SelectionManager.Views();
- return views.map(dv => dv.getBounds()).reduce((bounds, rect) =>
+ return views.filter(dv => dv.props.renderDepth > 0).map(dv => dv.getBounds()).reduce((bounds, rect) =>
!rect ? bounds :
{
x: Math.min(rect.left, bounds.x),
@@ -112,7 +113,12 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
}
}
- titleEntered = (e: React.KeyboardEvent) => e.key === "Enter" && (e.target as any).blur();
+ titleEntered = (e: React.KeyboardEvent) => {
+ if (e.key === "Enter") {
+ e.stopPropagation();
+ (e.target as any).blur();
+ }
+ }
@action onTitleDown = (e: React.PointerEvent): void => {
setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), (e) => { }, action((e) => {
@@ -146,14 +152,15 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
_deleteAfterIconify = false;
_iconifyBatch: UndoManager.Batch | undefined;
- onCloseClick = (force = false) => {
+ onCloseClick = (forceDeleteOrIconify: boolean | undefined) => {
if (this.canDelete) {
const views = SelectionManager.Views().slice().filter(v => v);
- this._deleteAfterIconify = force || this._iconifyBatch ? true : false;
+ if (forceDeleteOrIconify === false && this._iconifyBatch) return;
+ this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false;
if (!this._iconifyBatch) {
this._iconifyBatch = UndoManager.StartBatch("iconifying");
} else {
- force = false; // can't force immediate close in the middle of iconifying -- have to wait until iconifying completes
+ forceDeleteOrIconify = false; // can't force immediate close in the middle of iconifying -- have to wait until iconifying completes
}
var iconifyingCount = views.length;
const finished = action((force?: boolean) => {
@@ -166,7 +173,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
this._iconifyBatch = undefined;
}
});
- if (force) finished(force);
+ if (forceDeleteOrIconify) finished(forceDeleteOrIconify);
else if (!this._deleteAfterIconify) views.forEach(dv => dv.iconify(finished));
}
}
@@ -223,14 +230,18 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
@action
onRotateDown = (e: React.PointerEvent): void => {
const rotateUndo = UndoManager.StartBatch("rotatedown");
- const centerPoint = { X: this.Bounds.c?.X ?? (this.Bounds.x + this.Bounds.r) / 2, Y: this.Bounds.c?.Y ?? (this.Bounds.y + this.Bounds.b) / 2 };
+ const selectedInk = SelectionManager.Views().filter(i => i.ComponentView instanceof InkingStroke);
+ const centerPoint = !selectedInk.length ? { X: this.Bounds.x, Y: this.Bounds.y } : { X: this.Bounds.c?.X ?? (this.Bounds.x + this.Bounds.r) / 2, Y: this.Bounds.c?.Y ?? (this.Bounds.y + this.Bounds.b) / 2 };
setupMoveUpEvents(this, e,
(e: PointerEvent, down: number[], delta: number[]) => {
const previousPoint = { X: e.clientX, Y: e.clientY };
const movedPoint = { X: e.clientX - delta[0], Y: e.clientY - delta[1] };
const angle = InkStrokeProperties.angleChange(previousPoint, movedPoint, centerPoint);
- const selectedInk = SelectionManager.Views().filter(i => i.ComponentView instanceof InkingStroke);
- angle && InkStrokeProperties.Instance.rotateInk(selectedInk, -angle, centerPoint);
+ if (selectedInk.length) {
+ angle && InkStrokeProperties.Instance.rotateInk(selectedInk, -angle, centerPoint);
+ } else {
+ SelectionManager.Views().forEach(dv => dv.rootDoc._jitterRotation = NumCast(dv.rootDoc._jitterRotation) - angle * 180 / Math.PI);
+ }
return false;
},
() => {
@@ -495,16 +506,13 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
value={this._accumulatedTitle}
onBlur={e => this.titleBlur()}
onChange={action(e => this._accumulatedTitle = e.target.value)}
- onKeyPress={this.titleEntered} /> :
+ onKeyDown={this.titleEntered} /> :
<div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
<span className={`documentDecorations-titleSpan${colorScheme}`}>{`${this.selectionTitle}`}</span>
</div>;
- let inMainMenuPanel = false;
- for (let node = seldoc.ContentDiv; node && !inMainMenuPanel; node = node?.parentNode as any) {
- if (node.className === "mainView-mainContent") inMainMenuPanel = true;
- }
- const leftBounds = inMainMenuPanel ? 0 : this.props.boundsLeft;
+
+ const leftBounds = this.props.boundsLeft;
const topBounds = LightboxView.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;
@@ -512,26 +520,30 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
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));
- const useRotation = seldoc.ComponentView instanceof InkingStroke;
+ const useRotation = seldoc.ComponentView instanceof InkingStroke || seldoc.ComponentView instanceof ImageBox;
const resizerScheme = colorScheme ? "documentDecorations-resizer" + colorScheme : "";
+ const rotation = NumCast(seldoc.rootDoc._jitterRotation);
+
return (<div className={`documentDecorations${colorScheme}`}>
<div className="documentDecorations-background" style={{
+ transform: `rotate(${rotation}deg)`,
+ transformOrigin: "top left",
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,
- pointerEvents: KeyManager.Instance.ShiftPressed || this.Interacting ? "none" : "all",
+ pointerEvents: DocumentDecorations.Instance.AddToSelection || this.Interacting ? "none" : "all",
display: SelectionManager.Views().length <= 1 ? "none" : undefined
}} onPointerDown={this.onBackgroundDown} onContextMenu={e => { e.preventDefault(); e.stopPropagation(); }} />
{bounds.r - bounds.x < 15 && bounds.b - bounds.y < 15 ? (null) : <>
<div className="documentDecorations-container" key="container" style={{
+ transform: ` translate(${bounds.x - this._resizeBorderWidth / 2}px, ${bounds.y - this._resizeBorderWidth / 2 - this._titleHeight}px) rotate(${rotation}deg)`,
+ transformOrigin: `8px 26px`,
width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
height: (bounds.b - bounds.y + this._resizeBorderWidth + this._titleHeight) + "px",
- left: bounds.x - this._resizeBorderWidth / 2,
- top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
}}>
- {!canDelete ? <div /> : topBtn("close", this.hasIcons ? "times" : "window-maximize", undefined, e => this.onCloseClick(this.hasIcons), "Close")}
+ {!canDelete ? <div /> : topBtn("close", this.hasIcons ? "times" : "window-maximize", undefined, e => this.onCloseClick(this.hasIcons ? true : undefined), "Close")}
{titleArea}
{!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")}
{hideResizers ? (null) :
@@ -553,10 +565,14 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
onContextMenu={e => e.preventDefault()}>{useRotation && "⟲"}</div>
</>
}
+ {seldoc?.Document.type === DocumentType.FONTICON ? (null) :
+ <div className="link-button-container" key="links"
+ style={{
+ transform: ` translate(${- this._resizeBorderWidth / 2 + 10}px, ${this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `,
+ }}>
+ <DocumentButtonBar views={SelectionManager.Views} />
+ </div>}
</div >
- {seldoc?.Document.type === DocumentType.FONTICON ? (null) : <div className="link-button-container" key="links" style={{ left: bounds.x - this._resizeBorderWidth / 2 + 10, top: bounds.b + this._resizeBorderWidth / 2 }}>
- <DocumentButtonBar views={SelectionManager.Views} />
- </div>}
</>}
</div >
);