aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx')
-rw-r--r--src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx133
1 files changed, 119 insertions, 14 deletions
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
index e48a6ada4..bc04f9a69 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
@@ -8,7 +8,7 @@ import { DocCast, ImageCast } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
import { emptyFunction } from '../../../../Utils';
import { SnappingManager } from '../../../util/SnappingManager';
-import { undoable } from '../../../util/UndoManager';
+import { UndoManager, undoable } from '../../../util/UndoManager';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { DocumentView } from '../DocumentView';
import { DataVizBox } from './DataVizBox';
@@ -18,6 +18,8 @@ import { Colors, IconButton, Size } from 'browndash-components';
import { MakeTemplate } from '../../../util/DropConverter';
import { threadId } from 'worker_threads';
import { ideahub } from 'googleapis/build/src/apis/ideahub';
+import { DragManager } from '../../../util/DragManager';
+import { DateField } from '../../../../fields/DateField';
export enum LayoutType {
Stacked = 'stacked',
@@ -58,6 +60,14 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
@observable _dragging: boolean = false;
@observable _draggingIndicator: boolean = false;
@observable _dataViz?: DataVizBox;
+ @observable _interactionLock: any;
+ @observable _snapPt: any;
+ @observable _resizeHdlId: string = '';
+ @observable _resizing: boolean = false;
+ @observable _offset: {x: number, y: number} = {x: 0, y: 0};
+ @observable _resizeUndo: UndoManager.Batch | undefined = undefined;
+ @observable _initDimensions: {width: number, height: number, x: number, y: number} = {width: 300, height: 400, x: 0, y: 0};
+ @observable _menuDimensions: {width: number, height: number} = {width: 300, height: 400};
constructor(props: any) {
super(props);
@@ -102,6 +112,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
return this._selectedTemplate !== undefined && this._layout !== undefined;
}
+ get bounds(): {t: number, b: number, l: number, r: number} {
+ const rect = this._ref?.getBoundingClientRect();
+ const bounds = {t: rect?.top ?? 0, b: rect?.bottom ?? 0, l: rect?.left ?? 0, r: rect?.right ?? 0};
+ return bounds;
+ }
+
setUpButtonClick = (e: any, func: Function) => {
setupMoveUpEvents(
this,
@@ -123,6 +139,19 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
@action
onPointerUp = (e: PointerEvent) => {
+ if (this._resizing) {
+ this._initDimensions.width = this._menuDimensions.width;
+ this._initDimensions.height = this._menuDimensions.height;
+ this._initDimensions.x = this._pageX;
+ this._initDimensions.y = this._pageY;
+ document.removeEventListener('pointermove', this.onResize);
+ SnappingManager.SetIsResizing(undefined);
+ this._resizing = false;
+ }
+ if (this._dragging) {
+ document.removeEventListener('pointermove', this.onDrag);
+ this._dragging = false;
+ }
if (e.button !== 2 && !e.ctrlKey) return;
const curX = e.clientX;
const curY = e.clientY;
@@ -164,17 +193,76 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
};
@action
- onPointerMove = (e: any) => {
- // if (this._draggingIndicator) {
- // this._indicatorX = e.pageX - (this._startPos?.x ?? 0) + this._pageX;
- // this._indicatorY = e.pageY - (this._startPos?.y ?? 0) + this._pageY;
- // } else
- if (this._dragging){
- this._pageX = e.pageX - (this._startPos?.x ?? 0);
- this._pageY = e.pageY - (this._startPos?.y ?? 0);
- }
+ onResizePointerDown = (e: React.PointerEvent): void => {
+ this._resizing = true;
+ document.addEventListener('pointermove', this.onResize);
+ SnappingManager.SetIsResizing(DocumentView.Selected().lastElement()?.Document[Id]); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
+ e.stopPropagation();
+ const id = (this._resizeHdlId = e.currentTarget.className);
+ const pad = id.includes('Left') || id.includes('Right') ? Number(getComputedStyle(e.target as any).width.replace('px', '')) / 2 : 0;
+ const bounds = e.currentTarget.getBoundingClientRect();
+ this._offset = {
+ x: id.toLowerCase().includes('left') ? bounds.right - e.clientX - pad : bounds.left - e.clientX + pad, //
+ y: id.toLowerCase().includes('top') ? bounds.bottom - e.clientY - pad : bounds.top - e.clientY + pad,
+ };
+ this._resizeUndo = UndoManager.StartBatch('drag resizing');
+ this._snapPt = { x: e.pageX, y: e.pageY };
+ };
+
+ @action
+ onResize = (e: any): boolean => {
+ const dragHdl = this._resizeHdlId.split(' ')[1];
+ const thisPt = DragManager.snapDrag(e, -this._offset.x, -this._offset.y, this._offset.x, this._offset.y);
+
+ const { scale, refPt, transl } = 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;
+ const scaleAspect = {x: scale.x, y: scale.y};
+ this.resizeView(refPt, scaleAspect, transl); // prettier-ignore
+ await new Promise<any>(res => { setTimeout(() => { res(this._interactionLock = undefined)})});
+ }); // prettier-ignore
+ return true;
}
+ @action
+ onDrag = (e: any): boolean => {
+ this._pageX = e.pageX - (this._startPos?.x ?? 0);
+ this._pageY = e.pageY - (this._startPos?.y ?? 0);
+ return true;
+ }
+
+ getResizeVals = (thisPt: { x: number; y: number }, dragHdl: string) => {
+ const [w, h] = [this._initDimensions.width, this._initDimensions.height];
+ const [moveX, moveY] = [thisPt.x - this._snapPt.x, thisPt.y - this._snapPt.y];
+ let vals: {scale: {x: number, y: number}, refPt: [number, number], transl: {x: number, y: number}};
+ switch (dragHdl) {
+ case 'topLeft': vals = { scale: { x: 1 - moveX / w, y: 1 -moveY / h }, refPt: [this.bounds.r, this.bounds.b], transl: {x: moveX, y: -moveY } }; break;
+ case 'topRight': vals = { scale: { x: 1 + moveX / w, y: 1 -moveY / h }, refPt: [this.bounds.l, this.bounds.b], transl: {x: 0, y: -moveY } }; break;
+ case 'top': vals = { scale: { x: 1, y: 1 -moveY / h }, refPt: [this.bounds.l, this.bounds.b], transl: {x: 0, y: moveY } }; break;
+ case 'left': vals = { scale: { x: 1 - moveX / w, y: 1 }, refPt: [this.bounds.r, this.bounds.t], transl: {x: moveX, y: 0 } }; break;
+ case 'bottomLeft': vals = { scale: { x: 1 - moveX / w, y: 1 + moveY / h }, refPt: [this.bounds.r, this.bounds.t], transl: {x: moveX, y: moveY } }; break;
+ case 'right': vals = { scale: { x: 1 + moveX / w, y: 1 }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break;
+ case 'bottomRight':vals = { scale: { x: 1 + moveX / w, y: 1 + moveY / h }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break;
+ case 'bottom': vals = { scale: { x: 1, y: 1 + moveY / h }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break;
+ default: vals = { scale: { x: 1, y: 1 }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break;
+ } // prettier-ignore
+ return vals;
+ };
+
+ resizeView = (refPt: number[], scale: { x: number; y: number }, translation: {x: number, y: number}) => {
+ const refCent = [refPt[0], refPt[1]] // fixed reference point for resize (ie, a point that doesn't move)
+ if (this._initDimensions.x === undefined) this._initDimensions.x = this._pageX;
+ if (this._initDimensions.y === undefined) this._initDimensions.y = this._pageY;
+ const {height, width, x, y} = this._initDimensions;
+
+ console.log(scale.x)
+
+ this._menuDimensions.width = Math.max(100, scale.x * width);
+ this._menuDimensions.height = Math.max(100, scale.y * height);
+ this._pageX = x + translation.x;
+ this._pageY = y + translation.y;
+ };
+
async getIcon(doc: Doc) {
const docView = DocumentView.getDocumentView(doc);
if (docView) {
@@ -470,6 +558,23 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
}
}
+ get resizePanes(){
+ const ref = this._ref?.getBoundingClientRect();
+ const height: number = ref?.height ?? 0;
+ const width: number = ref?.width ?? 0;
+
+ return [
+ <div className='docCreatorMenu-resizer top' onPointerDown={this.onResizePointerDown} style={{width: width, left: 0, top: -7}}/>,
+ <div className='docCreatorMenu-resizer right' onPointerDown={this.onResizePointerDown} style={{height: height, left: width - 3, top: 0}}/>,
+ <div className='docCreatorMenu-resizer bottom' onPointerDown={this.onResizePointerDown} style={{width: width, left: 0, top: height - 3}}/>,
+ <div className='docCreatorMenu-resizer left' onPointerDown={this.onResizePointerDown} style={{height: height, left: -7, top: 0}}/>,
+ <div className='docCreatorMenu-resizer topRight' onPointerDown={this.onResizePointerDown} style={{left: width, top: -7, cursor: 'nesw-resize'}}/>,
+ <div className='docCreatorMenu-resizer topLeft' onPointerDown={this.onResizePointerDown} style={{left: -7, top: -7, cursor: 'nwse-resize'}}/>,
+ <div className='docCreatorMenu-resizer bottomRight' onPointerDown={this.onResizePointerDown} style={{left: width, top: height, cursor: 'nwse-resize'}}/>,
+ <div className='docCreatorMenu-resizer bottomLeft' onPointerDown={this.onResizePointerDown} style={{left: -7, top: height, cursor: 'nesw-resize'}}/>
+ ]; //prettier-ignore
+ }
+
render() {
const topButton = (icon: string, opt: string, func: Function, tag: string) => {
return (
@@ -526,11 +631,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
display: '',
left: this._pageX,
top: this._pageY,
- width: 300,
- height: 400,
+ width: this._menuDimensions.width,
+ height: this._menuDimensions.height,
background: SnappingManager.userBackgroundColor,
color: SnappingManager.userColor,
}}>
+ {this.resizePanes}
<div
className='docCreatorMenu-menu'
onPointerDown={e =>
@@ -542,6 +648,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
this._startPos = {x: 0, y: 0};
this._startPos.x = e.pageX - (this._ref?.getBoundingClientRect().left ?? 0);
this._startPos.y = e.pageY - (this._ref?.getBoundingClientRect().top ?? 0);
+ document.addEventListener('pointermove', this.onDrag);
return true;
},
emptyFunction,
@@ -550,8 +657,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
}, 'drag menu')
)
}
- onPointerMove={e => this.onPointerMove(e)}
- onPointerUp={() => this._dragging = false}
>
<div className='docCreatorMenu-top-buttons-container'>
{topButton('table-cells', 'templates', onPreviewSelected, 'left')}