aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionDockingView.scss31
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx1015
-rw-r--r--src/client/views/collections/CollectionDockingViewMenu.scss (renamed from src/client/views/collections/ParentDocumentSelector.scss)41
-rw-r--r--src/client/views/collections/CollectionDockingViewMenu.tsx48
-rw-r--r--src/client/views/collections/CollectionMenu.tsx22
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaHeaders.tsx12
-rw-r--r--src/client/views/collections/CollectionSchemaMovableTableHOC.tsx2
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx24
-rw-r--r--src/client/views/collections/CollectionView.tsx14
-rw-r--r--src/client/views/collections/ParentDocumentSelector.tsx128
-rw-r--r--src/client/views/collections/SchemaTable.tsx2
-rw-r--r--src/client/views/collections/TabDocView.scss20
-rw-r--r--src/client/views/collections/TabDocView.tsx379
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx23
-rw-r--r--src/client/views/collections/collectionFreeForm/FormatShapePane.scss68
-rw-r--r--src/client/views/collections/collectionFreeForm/FormatShapePane.tsx545
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx12
-rw-r--r--src/client/views/collections/collectionFreeForm/PropertiesView.scss779
-rw-r--r--src/client/views/collections/collectionFreeForm/PropertiesView.tsx1106
-rw-r--r--src/client/views/collections/collectionGrid/CollectionGridView.scss11
22 files changed, 702 insertions, 3585 deletions
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index f1a29bd13..d3be1636d 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -1,24 +1,5 @@
@import "../../views/globalCssVariables.scss";
-.miniMap {
- position: absolute;
- overflow: hidden;
- right: 10;
- bottom: 10;
- border: solid 1px;
- box-shadow: black 0.4vw 0.4vw 0.8vw;
-
- .miniOverlay {
- width: 100%;
- height: 100%;
- position: absolute;
-
- .miniThumb {
- background: #25252525;
- position: absolute;
- }
- }
-}
.lm_title {
margin-top: 3px;
@@ -72,18 +53,6 @@
display: inline;
}
-.messageCounter {
- width: 18px;
- height: 20px;
- text-align: center;
- border-radius: 20px;
- margin-left: 5px;
- transform: translate(0px, -8px);
- display: inline-block;
- background: transparent;
- border: 1px #999999 solid;
-}
-
.collectiondockingview-container {
width: 100%;
height: 100%;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 3d8ac2a23..d8e95bcdc 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,46 +1,32 @@
import 'golden-layout/src/css/goldenlayout-base.css';
import 'golden-layout/src/css/goldenlayout-dark-theme.css';
-import { clamp } from 'lodash';
-import { action, computed, IReactionDisposer, Lambda, observable, reaction, runInAction } from "mobx";
+import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
import * as ReactDOM from 'react-dom';
import * as GoldenLayout from "../../../client/goldenLayout";
-import { DateField } from '../../../fields/DateField';
-import { DataSym, Doc, DocListCast, Field, Opt } from "../../../fields/Doc";
+import { Doc, DocListCast, Opt } from "../../../fields/Doc";
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
-import { FieldId } from "../../../fields/RefField";
-import { listSpec } from '../../../fields/Schema';
import { Cast, NumCast, StrCast } from "../../../fields/Types";
-import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils, returnEmptyDoclist } from "../../../Utils";
import { DocServer } from "../../DocServer";
import { Docs } from '../../documents/Documents';
-import { DocumentManager } from '../../util/DocumentManager';
-import { DragManager, dropActionType } from "../../util/DragManager";
+import { CurrentUserUtils } from '../../util/CurrentUserUtils';
+import { DragManager } from "../../util/DragManager";
import { InteractionUtils } from '../../util/InteractionUtils';
import { Scripting } from '../../util/Scripting';
-import { SelectionManager } from '../../util/SelectionManager';
-import { SnappingManager } from '../../util/SnappingManager';
-import { Transform } from '../../util/Transform';
-import { undoBatch } from "../../util/UndoManager";
-import { DocumentView } from "../nodes/DocumentView";
-import { PresBox } from '../nodes/PresBox';
+import { undoBatch, UndoManager } from "../../util/UndoManager";
import "./CollectionDockingView.scss";
-import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
-import { SubCollectionViewProps, CollectionSubView } from "./CollectionSubView";
+import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
import { CollectionViewType } from './CollectionView';
-import { DockingViewButtonSelector } from './ParentDocumentSelector';
+import { TabDocView } from './TabDocView';
import React = require("react");
-import { CurrentUserUtils } from '../../util/CurrentUserUtils';
const _global = (window /* browser */ || global /* node */) as any;
@observer
export class CollectionDockingView extends CollectionSubView(doc => doc) {
- @observable public static Instances: CollectionDockingView[] = [];
- @computed public static get Instance() { return CollectionDockingView.Instances[0]; }
- public static makeDocumentConfig(document: Doc, width?: number, libraryPath?: Doc[]) {
+ @observable public static Instance: CollectionDockingView;
+ public static makeDocumentConfig(document: Doc, panelName?: string, width?: number) {
return {
type: 'react-component',
component: 'DocumentFrameRenderer',
@@ -48,332 +34,210 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
width: width,
props: {
documentId: document[Id],
- libraryPath: libraryPath?.map(d => d[Id])
+ panelName // name of tab that can be used to close or replace its contents
}
};
}
- @computed public get initialized() {
- return this._goldenLayout !== null;
- }
-
- @observable private _goldenLayout: any = null;
+ private _reactionDisposer?: IReactionDisposer;
private _containerRef = React.createRef<HTMLDivElement>();
- private _flush: boolean = false;
+ private _flush: UndoManager.Batch | undefined;
private _ignoreStateChange = "";
- private _isPointerDown = false;
- private _maximizedSrc: Opt<DocumentView>;
+ public tabMap: Set<any> = new Set();
+ public get initialized() { return this._goldenLayout !== null; }
+ public get HasFullScreen() { return this._goldenLayout._maximisedItem !== null; }
+ @observable private _goldenLayout: any = null;
constructor(props: SubCollectionViewProps) {
super(props);
- runInAction(() => !CollectionDockingView.Instances ? CollectionDockingView.Instances = [this] : CollectionDockingView.Instances.push(this));
+ runInAction(() => CollectionDockingView.Instance = this);
//Why is this here?
(window as any).React = React;
(window as any).ReactDOM = ReactDOM;
DragManager.StartWindowDrag = this.StartOtherDrag;
}
+
public StartOtherDrag = (e: any, dragDocs: Doc[]) => {
+ !this._flush && (this._flush = UndoManager.StartBatch("golden layout drag"));
const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) :
- {
- type: 'row',
- content: dragDocs.map((doc, i) => CollectionDockingView.makeDocumentConfig(doc))
- };
+ { type: 'row', content: dragDocs.map((doc, i) => CollectionDockingView.makeDocumentConfig(doc)) };
const dragSource = this._goldenLayout.createDragSource(document.createElement("div"), config);
- dragSource._dragListener.on("dragStop", () => dragSource.destroy());
+ //dragSource._dragListener.on("dragStop", dragSource.destroy);
dragSource._dragListener.onMouseDown(e);
}
@undoBatch
- @action
- public OpenFullScreen(docView: DocumentView, libraryPath?: Doc[]) {
- if (docView.props.Document._viewType === CollectionViewType.Docking && docView.props.Document.layoutKey === "layout") {
- return CurrentUserUtils.openDashboard(Doc.UserDoc(), docView.props.Document);
- }
- const document = Doc.MakeAlias(docView.props.Document);
- const newItemStackConfig = {
- type: 'stack',
- content: [CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath)]
- };
- const docconfig = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
- this._goldenLayout.root.contentItems[0].addChild(docconfig);
- docconfig.callDownwards('_$init');
- this._goldenLayout._$maximiseItem(docconfig);
- this._maximizedSrc = docView;
- this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
+ public CloseFullScreen = () => {
+ this._goldenLayout._maximisedItem?.toggleMaximise();
this.stateChanged();
- SelectionManager.DeselectAll();
}
- public CloseFullScreen = () => {
- const target = this._goldenLayout._maximisedItem;
- if (target !== null && this._maximizedSrc) {
- this._goldenLayout._maximisedItem.remove();
- SelectionManager.SelectDoc(this._maximizedSrc, false);
- this._maximizedSrc = undefined;
- this.stateChanged();
+ @undoBatch
+ public static CloseSplit(document: Opt<Doc>, panelName?: string): boolean {
+ const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => panelName ? tab.contentItem.config.props.panelName === panelName : tab.DashDoc === document);
+ if (tab) {
+ const j = tab.header.parent.contentItems.indexOf(tab.contentItem);
+ if (j !== -1) {
+ tab.header.parent.contentItems[j].remove();
+ return CollectionDockingView.Instance.layoutChanged();
+ }
}
- }
- public HasFullScreen = () => {
- return this._goldenLayout._maximisedItem !== null;
+ return false;
}
@undoBatch
- @action
- public static CloseRightSplit(document: Opt<Doc>): boolean {
+ public static OpenFullScreen(doc: Doc, libraryPath?: Doc[]) {
const instance = CollectionDockingView.Instance;
- const tryClose = (childItem: any) => {
- if (childItem.config?.component === "DocumentFrameRenderer") {
- const docView = DocumentManager.Instance.getDocumentViewById(childItem.config.props.documentId);
- if (docView && ((!document && docView.Document.isDisplayPanel) || (document && Doc.AreProtosEqual(docView.props.Document, document)))) {
- childItem.remove();
- instance.layoutChanged(document);
- return true;
- }
- }
- return false;
+ if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === "layout") {
+ return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
+ }
+ const newItemStackConfig = {
+ type: 'stack',
+ content: [CollectionDockingView.makeDocumentConfig(Doc.MakeAlias(doc))]
};
- const retVal = !instance?._goldenLayout.root.contentItems[0].isRow ? false :
- Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => Array.from(child.contentItems).some(tryClose));
-
- retVal && instance.stateChanged();
- return retVal;
+ const docconfig = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
+ instance._goldenLayout.root.contentItems[0].addChild(docconfig);
+ docconfig.callDownwards('_$init');
+ instance._goldenLayout._$maximiseItem(docconfig);
+ instance._goldenLayout.emit('stateChanged');
+ instance._ignoreStateChange = JSON.stringify(instance._goldenLayout.toConfig());
+ instance.stateChanged();
+ return true;
}
- @action
- layoutChanged(removed?: Doc) {
- this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
- this._goldenLayout.emit('stateChanged');
- this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
- this.stateChanged();
- }
@undoBatch
- @action
- public static ReplaceRightSplit(document: Doc, libraryPath?: Doc[], addToSplit?: boolean): boolean {
- if (!CollectionDockingView.Instance) return false;
+ public static ReplaceTab(document: Doc, panelName: string, stack: any, addToSplit?: boolean): boolean {
const instance = CollectionDockingView.Instance;
- let retVal = false;
- if (instance._goldenLayout.root.contentItems[0].isRow) {
- retVal = Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => {
- if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" &&
- DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)?.Document.isDisplayPanel) {
- const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath);
- child.addChild(newItemStackConfig, undefined);
- !addToSplit && child.contentItems[0].remove();
- instance.layoutChanged(document);
- return true;
- }
- return Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => {
- if (DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)?.Document.isDisplayPanel) {
- const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath);
- child.addChild(newItemStackConfig, undefined);
- !addToSplit && child.contentItems[j].remove();
- instance.layoutChanged(document);
- return true;
- }
- return false;
- });
- });
+ if (!instance) return false;
+ const newConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
+ if (!panelName && stack) {
+ const activeContentItemIndex = stack.contentItems.findIndex((item: any) => item.config === stack._activeContentItem.config);
+ const newContentItem = stack.layoutManager.createContentItem(newConfig, instance._goldenLayout);
+ stack.addChild(newContentItem.contentItems[0], undefined);
+ stack.contentItems[activeContentItemIndex].remove();
+ return CollectionDockingView.Instance.layoutChanged();
}
- if (retVal) {
- instance.stateChanged();
+ const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => tab.contentItem.config.props.panelName === panelName);
+ if (tab) {
+ tab.header.parent.addChild(newConfig, undefined);
+ const j = tab.header.parent.contentItems.indexOf(tab.contentItem);
+ !addToSplit && j !== -1 && tab.header.parent.contentItems[j].remove();
+ return CollectionDockingView.Instance.layoutChanged();
}
- return retVal;
+ return CollectionDockingView.AddSplit(document, panelName, stack, panelName);
}
- //
- // Creates a vertical split on the right side of the docking view, and then adds the Document to the right of that split
- //
- @undoBatch
- @action
- public static AddRightSplit(document: Doc, libraryPath?: Doc[]) {
- if (!CollectionDockingView.Instance) return false;
- if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document);
- const instance = CollectionDockingView.Instance;
- const newItemStackConfig = {
- type: 'stack',
- content: [CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath)]
- };
-
- const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
-
- if (instance._goldenLayout.root.contentItems.length === 0) {
- instance._goldenLayout.root.addChild(newContentItem);
- } else if (instance._goldenLayout.root.contentItems[0].isRow) {
- instance._goldenLayout.root.contentItems[0].addChild(newContentItem);
- } else {
- const collayout = instance._goldenLayout.root.contentItems[0];
- const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout);
- collayout.parent.replaceChild(collayout, newRow);
-
- newRow.addChild(newContentItem, undefined, true);
- newRow.addChild(collayout, 0, true);
- collayout.config.width = 50;
- newContentItem.config.width = 50;
- }
- newContentItem.callDownwards('_$init');
- instance.layoutChanged();
- return true;
+ @undoBatch
+ public static ToggleSplit(doc: Doc, location: string, stack?: any, panelName?: string) {
+ return Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex((tab) => tab.DashDoc === doc) !== -1 ?
+ CollectionDockingView.CloseSplit(doc) : CollectionDockingView.AddSplit(doc, location, stack, panelName);
}
-
//
// Creates a split on any side of the docking view based on the passed input pullSide and then adds the Document to the requested side
//
@undoBatch
- @action
- public static AddSplit(document: Doc, pullSide: string, libraryPath?: Doc[]) {
- if (!CollectionDockingView.Instance) return false;
+ public static AddSplit(document: Doc, pullSide: string, stack?: any, panelName?: string) {
const instance = CollectionDockingView.Instance;
- const newItemStackConfig = {
- type: 'stack',
- content: [CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath)]
- };
+ if (!instance) return false;
+ const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
- const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
-
- if (instance._goldenLayout.root.contentItems.length === 0) { // if no rows / columns
- instance._goldenLayout.root.addChild(newContentItem);
- } else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row
- if (pullSide === "left") {
- instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0);
- } else if (pullSide === "right") {
- instance._goldenLayout.root.contentItems[0].addChild(newContentItem);
- } else if (pullSide === "top" || pullSide === "bottom") {
- // if not going in a row layout, must add already existing content into column
- const rowlayout = instance._goldenLayout.root.contentItems[0];
- const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout);
- rowlayout.parent.replaceChild(rowlayout, newColumn);
- if (pullSide === "top") {
- newColumn.addChild(rowlayout, undefined, true);
- newColumn.addChild(newContentItem, 0, true);
- } else if (pullSide === "bottom") {
- newColumn.addChild(newContentItem, undefined, true);
- newColumn.addChild(rowlayout, 0, true);
- }
+ if (!pullSide && stack) {
+ stack.addChild(docContentConfig, undefined);
+ } else {
+ const newItemStackConfig = { type: 'stack', content: [docContentConfig] };
+ const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
+ if (instance._goldenLayout.root.contentItems.length === 0) { // if no rows / columns
+ instance._goldenLayout.root.addChild(newContentItem);
+ } else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row
+ switch (pullSide) {
+ default:
+ case "right": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break;
+ case "left": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break;
+ case "top":
+ case "bottom":
+ // if not going in a row layout, must add already existing content into column
+ const rowlayout = instance._goldenLayout.root.contentItems[0];
+ const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout);
+ rowlayout.parent.replaceChild(rowlayout, newColumn);
+ if (pullSide === "top") {
+ newColumn.addChild(rowlayout, undefined, true);
+ newColumn.addChild(newContentItem, 0, true);
+ } else if (pullSide === "bottom") {
+ newColumn.addChild(newContentItem, undefined, true);
+ newColumn.addChild(rowlayout, 0, true);
+ }
- rowlayout.config.height = 50;
- newContentItem.config.height = 50;
- }
- } else if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
- if (pullSide === "top") {
- instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0);
- } else if (pullSide === "bottom") {
- instance._goldenLayout.root.contentItems[0].addChild(newContentItem);
- } else if (pullSide === "left" || pullSide === "right") {
- // if not going in a row layout, must add already existing content into column
- const collayout = instance._goldenLayout.root.contentItems[0];
- const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout);
- collayout.parent.replaceChild(collayout, newRow);
-
- if (pullSide === "left") {
- newRow.addChild(collayout, undefined, true);
- newRow.addChild(newContentItem, 0, true);
- } else if (pullSide === "right") {
- newRow.addChild(newContentItem, undefined, true);
- newRow.addChild(collayout, 0, true);
+ rowlayout.config.height = 50;
+ newContentItem.config.height = 50;
}
+ } else if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
+ switch (pullSide) {
+ case "top": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break;
+ case "bottom": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break;
+ case "left":
+ case "right":
+ default:
+ // if not going in a row layout, must add already existing content into column
+ const collayout = instance._goldenLayout.root.contentItems[0];
+ const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout);
+ collayout.parent.replaceChild(collayout, newRow);
+
+ if (pullSide === "left") {
+ newRow.addChild(collayout, undefined, true);
+ newRow.addChild(newContentItem, 0, true);
+ } else {
+ newRow.addChild(newContentItem, undefined, true);
+ newRow.addChild(collayout, 0, true);
+ }
- collayout.config.width = 50;
- newContentItem.config.width = 50;
- }
- }
-
- newContentItem.callDownwards('_$init');
- instance.layoutChanged();
- return true;
- }
-
-
- //
- // Creates a vertical split on the right side of the docking view, and then adds the Document to that split
- //
- @undoBatch
- @action
- public static UseRightSplit(document: Doc, libraryPath?: Doc[], shiftKey?: boolean) {
- document.isDisplayPanel = true;
- if (shiftKey || !CollectionDockingView.ReplaceRightSplit(document, libraryPath, shiftKey)) {
- CollectionDockingView.AddRightSplit(document, libraryPath);
- }
- }
-
- @undoBatch
- @action
- public AddTab = (stack: any, document: Doc, libraryPath?: Doc[]) => {
- Doc.GetProto(document).lastOpened = new DateField;
- const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath);
- if (stack === undefined) {
- let stack: any = this._goldenLayout.root;
- while (!stack.isStack) {
- if (stack.contentItems.length) {
- stack = stack.contentItems[0];
- } else {
- stack.addChild({ type: 'stack', content: [docContentConfig] });
- stack = undefined;
- break;
+ collayout.config.width = 50;
+ newContentItem.config.width = 50;
}
}
- if (stack) {
- stack.addChild(docContentConfig);
- }
- } else {
- stack.addChild(docContentConfig, undefined);
+ newContentItem.callDownwards('_$init');
}
- this.layoutChanged();
- return true;
+
+ return instance.layoutChanged();
}
@undoBatch
@action
- public ReplaceTab = (stack: any, document: Doc, libraryPath?: Doc[]) => {
- Doc.GetProto(document).lastOpened = new DateField;
- const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath);
- if (stack === undefined) {
- let stack: any = this._goldenLayout.root;
- while (!stack.isStack) {
- if (stack.contentItems.length) {
- stack = stack.contentItems[0];
- } else {
- stack.addChild({ type: 'stack', content: [docContentConfig] });
- stack = undefined;
- break;
- }
- }
- if (stack) {
- stack.addChild(docContentConfig);
- }
- } else {
- stack.addChild(docContentConfig, undefined);
- }
- this.layoutChanged();
+ layoutChanged() {
+ this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
+ this._goldenLayout.emit('stateChanged');
+ this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
+ this.stateChanged();
return true;
}
- setupGoldenLayout() {
+ async setupGoldenLayout() {
const config = StrCast(this.props.Document.dockingConfig);
if (config) {
- if (!this._goldenLayout) {
- runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config)));
- }
- else {
+ const matches = config.match(/\"documentId\":\"[a-z0-9-]+\"/g);
+ const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")) ?? [];
+ await Promise.all(docids.map(id => DocServer.GetRefField(id)));
+
+ if (this._goldenLayout) {
if (config === JSON.stringify(this._goldenLayout.toConfig())) {
return;
+ } else {
+ try {
+ this._goldenLayout.unbind('tabCreated', this.tabCreated);
+ this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
+ this._goldenLayout.unbind('stackCreated', this.stackCreated);
+ } catch (e) { }
}
- try {
- this._goldenLayout.unbind('itemDropped', this.itemDropped);
- this._goldenLayout.unbind('tabCreated', this.tabCreated);
- this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
- this._goldenLayout.unbind('stackCreated', this.stackCreated);
- } catch (e) { }
- this._goldenLayout.destroy();
- runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config)));
}
- this._goldenLayout.on('itemDropped', this.itemDropped);
+ this.tabMap.clear();
+ this._goldenLayout?.destroy();
+ runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config)));
this._goldenLayout.on('tabCreated', this.tabCreated);
this._goldenLayout.on('tabDestroyed', this.tabDestroyed);
this._goldenLayout.on('stackCreated', this.stackCreated);
- this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer);
+ this._goldenLayout.registerComponent('DocumentFrameRenderer', TabDocView);
this._goldenLayout.container = this._containerRef.current;
if (this._goldenLayout.config.maximisedItemId === '__glMaximised') {
try {
@@ -385,50 +249,33 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
this._goldenLayout.init();
}
}
- reactionDisposer?: Lambda;
+
componentDidMount: () => void = () => {
if (this._containerRef.current) {
- const observer = new _global.ResizeObserver(action((entries: any) => {
- for (const entry of entries) {
- this.onResize(null as any);
- }
- }));
- observer.observe(this._containerRef.current);
- this.reactionDisposer = reaction(
- () => this.props.Document.dockingConfig,
- () => {
- if (!this._goldenLayout || this._ignoreStateChange !== JSON.stringify(this._goldenLayout.toConfig())) {
- // Because this is in a set timeout, if this component unmounts right after mounting,
- // we will leak a GoldenLayout, because we try to destroy it before we ever create it
- setTimeout(() => this.setupGoldenLayout(), 1);
- DocListCast((Doc.UserDoc().myDashboards as Doc).data).map(d => d.dashboardBrush = false);
- this.props.Document.dashboardBrush = true;
+ new _global.ResizeObserver(this.onResize).observe(this._containerRef.current);
+ this._reactionDisposer = reaction(() => StrCast(this.props.Document.dockingConfig),
+ config => {
+ if (!this._goldenLayout || this._ignoreStateChange !== config) {
+ this.setupGoldenLayout();
}
this._ignoreStateChange = "";
- }, { fireImmediately: true });
-
+ });
+ setTimeout(() => this.setupGoldenLayout(), 0);
window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
}
}
+
componentWillUnmount: () => void = () => {
try {
- this.props.Document.dashboardBrush = false;
- this._goldenLayout.unbind('itemDropped', this.itemDropped);
- this._goldenLayout.unbind('tabCreated', this.tabCreated);
this._goldenLayout.unbind('stackCreated', this.stackCreated);
this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
- } catch (e) {
-
- }
- this._goldenLayout && this._goldenLayout.destroy();
- runInAction(() => {
- CollectionDockingView.Instances.splice(CollectionDockingView.Instances.indexOf(this), 1);
- this._goldenLayout = null;
- });
+ } catch (e) { }
+ this._goldenLayout?.destroy();
window.removeEventListener('resize', this.onResize);
- this.reactionDisposer && this.reactionDisposer();
+ this._reactionDisposer?.();
}
+
@action
onResize = (event: any) => {
const cur = this._containerRef.current;
@@ -437,56 +284,35 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
}
@action
- onPointerUp = (e: React.PointerEvent): void => {
+ onPointerUp = (e: MouseEvent): void => {
+ window.removeEventListener("pointerup", this.onPointerUp);
if (this._flush) {
- this._flush = false;
setTimeout(() => {
CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig());
this.stateChanged();
+ this._flush!.end();
+ this._flush = undefined;
}, 10);
}
}
+
@action
onPointerDown = (e: React.PointerEvent): void => {
- this._isPointerDown = true;
- const onPointerUp = action(() => {
- window.removeEventListener("pointerup", onPointerUp);
- this._isPointerDown = false;
- });
- window.addEventListener("pointerup", onPointerUp);
- const className = (e.target as any).className;
- if (className === "lm_drag_handle" || className === "lm_close" || className === "lm_maximise" || className === "lm_minimise" || className === "lm_close_tab") {
- this._flush = true;
+ window.addEventListener("mouseup", this.onPointerUp);
+ if (!(e.target as HTMLElement).closest("*.lm_content") && ((e.target as HTMLElement).closest("*.lm_tab") || (e.target as HTMLElement).closest("*.lm_stack"))) {
+ this._flush = UndoManager.StartBatch("golden layout edit");
}
- if (e.nativeEvent.cancelBubble || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) || InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || (Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) {
- return;
- } else {
+ if (!e.nativeEvent.cancelBubble && !InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) &&
+ Doc.GetSelectedTool() !== InkTool.Highlighter && Doc.GetSelectedTool() !== InkTool.Pen) {
e.stopPropagation();
}
}
- updateDataField = async (json: string) => {
- const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
- const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", ""));
-
- const docs = !docids ? [] : (await Promise.all(docids.map(id => DocServer.GetRefField(id)))).filter(f => f).map(f => f as Doc);
- const sublists = DocListCast(this.props.Document[this.props.fieldKey]);
- const tabs = Cast(sublists[0], Doc, null);
- const other = Cast(sublists[1], Doc, null);
- const tabdocs = DocListCast(tabs.data);
- const otherdocs = DocListCast(other.data);
- Doc.GetProto(tabs).data = new List<Doc>(docs);
- const otherSet = new Set<Doc>();
- otherdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
- tabdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
- Doc.GetProto(other).data = new List<Doc>(Array.from(otherSet.values()));
- }
-
- public static async Copy(doc: Doc) {
+ public static Copy(doc: Doc) {
let json = StrCast(doc.dockingConfig);
const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")) || [];
- const docs = (await Promise.all(docids.map(id => DocServer.GetRefField(id)))).filter(f => f).map(f => f as Doc);
+ const docs = docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
const newtabs = docs.map(doc => {
const copy = Doc.MakeAlias(doc);
json = json.replace(doc[Id], copy[Id]);
@@ -503,511 +329,72 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
return copy;
}
- @undoBatch
+ @action
stateChanged = () => {
const json = JSON.stringify(this._goldenLayout.toConfig());
- this.props.Document.dockingConfig = json;
- this.updateDataField(json);
- }
-
- itemDropped = () => {
- CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig());
- this.stateChanged();
- }
-
- htmlToElement(html: string) {
- const template = document.createElement('template');
- html = html.trim(); // Never return a text node of whitespace as the result
- template.innerHTML = html;
- return template.content.firstChild;
- }
-
- tabCreated = async (tab: any) => {
- tab.titleElement[0].Tab = tab;
- if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") {
- if (tab.contentItem.config.fixed) {
- tab.contentItem.parent.config.fixed = true;
- }
+ const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
+ const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", ""));
+ const docs = !docids ? [] : docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
- const doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId) as Doc;
- if (doc instanceof Doc) {
- tab.titleElement[0].onclick = (e: any) => {
- if (Date.now() - tab.titleElement[0].lastClick < 1000) tab.titleElement[0].select();
- tab.titleElement[0].lastClick = Date.now();
- tab.titleElement[0].focus();
- };
- tab.titleElement[0].onchange = (e: any) => {
- tab.titleElement[0].size = e.currentTarget.value.length + 1;
- Doc.GetProto(doc).title = e.currentTarget.value, true;
- };
- tab.titleElement[0].size = StrCast(doc.title).length + 1;
- tab.titleElement[0].value = doc.title;
- tab.titleElement[0].style["max-width"] = "100px";
- const gearSpan = document.createElement("span");
- gearSpan.className = "collectionDockingView-gear";
- gearSpan.style.position = "relative";
- gearSpan.style.paddingLeft = "0px";
- gearSpan.style.paddingRight = "12px";
- const stack = tab.contentItem.parent;
- tab.element[0].onpointerdown = (e: any) => {
- const view = DocumentManager.Instance.getDocumentView(doc);
- view && SelectionManager.SelectDoc(view, false);
- };
- // shifts the focus to this tab when another tab is dragged over it
- tab.element[0].onmouseenter = (e: any) => {
- if (!this._isPointerDown || !SnappingManager.GetIsDragging()) return;
- const activeContentItem = tab.header.parent.getActiveContentItem();
- if (tab.contentItem !== activeContentItem) {
- tab.header.parent.setActiveContentItem(tab.contentItem);
- }
- tab.setActive(true);
- };
- const onDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, (e) => {
- if (!(e as any).defaultPrevented) {
- const dragData = new DragManager.DocumentDragData([doc]);
- dragData.dropAction = doc.dropAction as dropActionType;
- DragManager.StartDocumentDrag([gearSpan], dragData, e.clientX, e.clientY);
- return true;
- }
- return false;
- }, returnFalse, emptyFunction);
- };
-
- tab.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments(),
- (sel) => {
- const selected = sel.some(v => v.props.Document === doc);
- selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && tab.header.parent.setActiveContentItem(tab.contentItem);
- }
- );
- tab.buttonDisposer = reaction(() => ((view: Opt<DocumentView>) => view ? [view] : [])(DocumentManager.Instance.getDocumentView(doc)),
- (views) => {
- if (views.length) {
- ReactDOM.render(<span title="Drag as document" className="collectionDockingView-dragAsDocument" onPointerDown={onDown} >
- <DockingViewButtonSelector views={() => views} Stack={stack} />
- </span>,
- gearSpan);
- tab.buttonDisposer?.();
- }
- }, { fireImmediately: true });
-
- tab.reactComponents = [gearSpan];
- tab.element.append(gearSpan);
- tab.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => {
- tab.titleElement[0].textContent = title, { fireImmediately: true };
- tab.titleElement[0].style.padding = degree ? 0 : 2;
- tab.titleElement[0].style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`;
- });
- //TODO why can't this just be doc instead of the id?
- tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
- }
- }
- tab.closeElement.off('click') //unbind the current click handler
- .click(async function () {
- tab.selectionDisposer?.();
- tab.reactionDisposer?.();
- tab.buttonDisposer?.();
- const doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId);
- if (doc instanceof Doc) {
- const theDoc = doc;
-
- const recent = await Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc);
- if (recent) {
- Doc.AddDocToList(recent, "data", doc, undefined, true, true);
- }
- SelectionManager.DeselectAll();
- }
- CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig());
- tab.contentItem.remove();
- CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig());
- });
+ this.props.Document.dockingConfig = json;
+ const sublists = DocListCast(this.props.Document[this.props.fieldKey]);
+ const tabs = Cast(sublists[0], Doc, null);
+ const other = Cast(sublists[1], Doc, null);
+ const tabdocs = DocListCast(tabs.data);
+ const otherdocs = DocListCast(other.data);
+ Doc.GetProto(tabs).data = new List<Doc>(docs);
+ const otherSet = new Set<Doc>();
+ otherdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
+ tabdocs.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
+ Doc.GetProto(other).data = new List<Doc>(Array.from(otherSet.values()));
}
tabDestroyed = (tab: any) => {
- if (tab.reactComponents) {
- for (const ele of tab.reactComponents) {
- ReactDOM.unmountComponentAtNode(ele);
- }
- }
+ this.tabMap.delete(tab);
+ Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
+ tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele));
}
-
- stackActiveChanged = () => {
- try {
- CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig());
- this.stateChanged();
- } catch (e) { } // catch exception thrown when config has not been initialzed yet
+ tabCreated = (tab: any) => {
+ tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous abs (ie, when dragging a tab around a new tab is created for the old content)
}
stackCreated = (stack: any) => {
- stack.layoutManager.on("activeContentItemChanged", this.stackActiveChanged);
- //stack.header.controlsContainer.find('.lm_popout').hide();
stack.header.element.on('mousedown', (e: any) => {
if (e.target === stack.header.element[0] && e.button === 2) {
- const emptyPane = Cast(Doc.UserDoc().emptyPane, Doc, null);
+ const emptyPane = CurrentUserUtils.EmptyPane;
emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
- this.AddTab(stack, Docs.Create.FreeformDocument([], {
+ CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], {
_width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`
- }));
+ }), "", stack);
}
});
- // starter code for bezel to add new pane
- // stack.element.on("touchstart", (e: TouchEvent) => {
- // if (e.targetTouches.length === 2) {
- // let pt1 = e.targetTouches.item(0);
- // let pt2 = e.targetTouches.item(1);
- // let threshold = 40 * window.devicePixelRatio;
- // if (pt1 && pt2 && InteractionUtils.TwoPointEuclidist(pt1, pt2) < threshold) {
- // let edgeThreshold = 30 * window.devicePixelRatio;
- // let center = InteractionUtils.CenterPoint([pt1, pt2]);
- // let stackRect: DOMRect = stack.element.getBoundingClientRect();
- // let nearLeft = center.X - stackRect.x < edgeThreshold;
- // let nearTop = center.Y - stackRect.y < edgeThreshold;
- // let nearRight = stackRect.right - center.X < edgeThreshold;
- // let nearBottom = stackRect.bottom - center.Y < edgeThreshold;
- // let ns = [nearLeft, nearTop, nearRight, nearBottom].filter(n => n);
- // if (ns.length === 1) {
-
- // }
- // }
- // }
- // });
stack.header.controlsContainer.find('.lm_close') //get the close icon
.off('click') //unbind the current click handler
- .click(action(async () => {
+ .click(action(() => {
//if (confirm('really close this?')) {
-
stack.remove();
- stack.contentItems.forEach(async (contentItem: any) => {
- const doc = await DocServer.GetRefField(contentItem.config.props.documentId);
- if (doc instanceof Doc) {
- let recent: Doc | undefined;
- if (recent = await Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc)) {
- Doc.AddDocToList(recent, "data", doc, undefined, true, true);
- }
- const theDoc = doc;
- }
- });
- //}
+ stack.contentItems.forEach((contentItem: any) => Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", contentItem.tab.DashDoc, undefined, true, true));
}));
stack.header.controlsContainer.find('.lm_popout') //get the close icon
.off('click') //unbind the current click handler
.click(action(() => {
// stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size
-
- const emptyPane = Cast(Doc.UserDoc().emptyPane, Doc, null);
+ const emptyPane = CurrentUserUtils.EmptyPane;
emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
- this.AddTab(stack, Docs.Create.FreeformDocument([], {
+ CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], {
_width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`
- }));
-
- // const url = Utils.prepend("/doc/" + stack.contentItems[0].tab.contentItem.config.props.documentId);
- // let win = window.open(url, stack.contentItems[0].tab.title, "width=300,height=400");
+ }), "", stack);
}));
}
render() {
- if (this.props.renderDepth > 0) {
- return <div style={{ width: "100%", height: "100%" }}>Nested dashboards can't be rendered</div>;
- }
- return <div className="collectiondockingview-container" id="menuContainer"
- onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} ref={this._containerRef} />;
- }
-
-}
-
-interface DockedFrameProps {
- documentId: FieldId;
- glContainer: any;
- libraryPath: (FieldId[]);
- //collectionDockingView: CollectionDockingView
-}
-@observer
-export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
- _mainCont: HTMLDivElement | null = null;
- @observable private _libraryPath: Doc[] = [];
- @observable private _panelWidth = 0;
- @observable private _panelHeight = 0;
- @observable private _document: Opt<Doc>;
- @observable private _isActive: boolean = false;
- _tabReaction: IReactionDisposer | undefined;
-
- get _stack(): any {
- return (this.props as any).glContainer.parent.parent;
- }
- get _tab(): any {
- const tab = (this.props as any).glContainer.tab?.element[0] as HTMLElement;
- return tab?.getElementsByClassName("lm_title")?.[0];
- }
- constructor(props: any) {
- super(props);
- DocServer.GetRefField(this.props.documentId).then(action((f: Opt<Field>) => this._document = f as Doc));
- this.props.libraryPath && this.setupLibraryPath();
- }
-
- async setupLibraryPath() {
- Promise.all(this.props.libraryPath.map(async docid => {
- const d = await DocServer.GetRefField(docid);
- return d instanceof Doc ? d : undefined;
- })).then(action((list: (Doc | undefined)[]) => this._libraryPath = list.filter(d => d).map(d => d as Doc)));
- }
-
- /**
- * Adds a document to the presentation view
- **/
- @undoBatch
- @action
- public static PinDoc(doc: Doc, unpin = false) {
- if (unpin) DockedFrameRenderer.UnpinDoc(doc);
- else {
- //add this new doc to props.Document
- const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
- if (curPres) {
- const pinDoc = Doc.MakeAlias(doc);
- pinDoc.presentationTargetDoc = doc;
- pinDoc.presZoomButton = true;
- pinDoc.context = curPres;
- Doc.AddDocToList(curPres, "data", pinDoc);
- if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
- if (!DocumentManager.Instance.getDocumentView(curPres)) {
- CollectionDockingView.AddRightSplit(curPres);
- }
- DocumentManager.Instance.jumpToDocument(doc, false, undefined, Cast(doc.context, Doc, null));
- }
- }
- }
- /**
- * Adds a document to the presentation view
- **/
- @undoBatch
- @action
- public static UnpinDoc(doc: Doc) {
- //add this new doc to props.Document
- const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
- if (curPres) {
- const ind = DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc));
- ind !== -1 && Doc.RemoveDocFromList(curPres, "data", DocListCast(curPres.data)[ind]);
- }
- }
-
- componentDidMount() {
- const color = () => StrCast(this._document?._backgroundColor, this._document && CollectionDockingView.Instance?.props.backgroundColor?.(this._document, 0) || "white");
- const selected = () => SelectionManager.SelectedDocuments().some(v => Doc.AreProtosEqual(v.props.Document, this._document));
- const updateTabColor = () => this._tab && (this._tab.style.backgroundColor = selected() ? color() : "");
- const observer = new _global.ResizeObserver(action((entries: any) => {
- for (const entry of entries) {
- this._panelWidth = entry.contentRect.width;
- this._panelHeight = entry.contentRect.height;
- }
- updateTabColor();
- }));
- observer.observe(this.props.glContainer._element[0]);
- this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged);
- this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged();
- this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: color() }), updateTabColor, { fireImmediately: true });
- }
-
- componentWillUnmount() {
- this._tabReaction?.();
- this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged);
- }
-
- @action.bound
- private onActiveContentItemChanged() {
- if (this.props.glContainer.tab && this._isActive !== this.props.glContainer.tab.isActive) {
- this._isActive = this.props.glContainer.tab.isActive;
- this._isActive && setTimeout(() => {
- const dv = this._document && DocumentManager.Instance.getFirstDocumentView(this._document);
- dv && SelectionManager.SelectDoc(dv, false);
- });
- !this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
- }
- }
-
- get layoutDoc() { return this._document && Doc.Layout(this._document); }
- nativeAspect = () => this.nativeWidth() ? this.nativeWidth() / this.nativeHeight() : 0;
- panelWidth = () => this.layoutDoc?.maxWidth ? Math.min(Math.max(NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._nativeWidth)), this._panelWidth) :
- (this.nativeAspect() && this.nativeAspect() < this._panelWidth / this._panelHeight ? this._panelHeight * this.nativeAspect() : this._panelWidth)
- panelHeight = () => this.nativeAspect() && this.nativeAspect() > this._panelWidth / this._panelHeight ? this._panelWidth / this.nativeAspect() : this._panelHeight;
-
- nativeWidth = () => !this.layoutDoc!._fitWidth ? NumCast(this.layoutDoc!._nativeWidth) || this._panelWidth : 0;
- nativeHeight = () => !this.layoutDoc!._fitWidth ? NumCast(this.layoutDoc!._nativeHeight) || this._panelHeight : 0;
-
- contentScaling = () => {
- const nativeH = this.nativeHeight();
- const nativeW = this.nativeWidth();
- let scaling = 1;
- if (!this.layoutDoc?._fitWidth && (!nativeW || !nativeH)) {
- scaling = 1;
- } else if (NumCast(this.layoutDoc!._nativeWidth) && ((this.layoutDoc?._fitWidth) ||
- this._panelHeight / NumCast(this.layoutDoc!._nativeHeight) > this._panelWidth / NumCast(this.layoutDoc!._nativeWidth))) {
- scaling = this._panelWidth / NumCast(this.layoutDoc!._nativeWidth);
- } else if (nativeW && nativeH) {
- // if (this.layoutDoc!.type === DocumentType.PDF || this.layoutDoc!.type === DocumentType.WEB) {
- // if ((this.layoutDoc?._fitWidth) ||
- // this._panelHeight / NumCast(this.layoutDoc!._nativeHeight) > this._panelWidth / NumCast(this.layoutDoc!._nativeWidth)) {
- // return this._panelWidth / NumCast(this.layoutDoc!._nativeWidth);
- // } else {
- // return this._panelHeight / NumCast(this.layoutDoc!._nativeHeight);
- // }
- // }
- const wscale = this.panelWidth() / nativeW;
- scaling = wscale * nativeH > this._panelHeight ? this._panelHeight / nativeH : wscale;
- } else scaling = 1;
- return scaling;
- }
-
- ScreenToLocalTransform = () => {
- if (this._mainCont && this._mainCont.children) {
- const { translateX, translateY } = Utils.GetScreenTransform(this._mainCont.children[0].firstChild as HTMLElement);
- const scale = Utils.GetScreenTransform(this._mainCont).scale;
- return CollectionDockingView.Instance?.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.contentScaling() / scale);
- }
- return Transform.Identity();
- }
- get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
- get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this._panelWidth * 100}% ` : undefined; }
-
- addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => {
- SelectionManager.DeselectAll();
- if (doc._viewType === CollectionViewType.Docking) {
- return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
- } else if (location === "onRight") {
- return CollectionDockingView.AddRightSplit(doc, libraryPath);
- } else if (location === "close") {
- return CollectionDockingView.CloseRightSplit(doc);
- } else if (location === "replace") {
- CollectionDockingView.UseRightSplit(doc);
- return true;
- } else {// if (location === "inPlace") {
- return CollectionDockingView.Instance.AddTab(this._stack, doc, libraryPath);
- }
- }
-
- @computed get renderContentBounds() {
- const bounds = this._document ? Cast(this._document._renderContentBounds, listSpec("number"), [0, 0, this.returnMiniSize(), this.returnMiniSize()]) : [0, 0, 0, 0];
- const xbounds = bounds[2] - bounds[0];
- const ybounds = bounds[3] - bounds[1];
- const dim = Math.max(xbounds, ybounds);
- return { l: bounds[0] + xbounds / 2 - dim / 2, t: bounds[1] + ybounds / 2 - dim / 2, cx: bounds[0] + xbounds / 2, cy: bounds[1] + ybounds / 2, dim };
- }
- @computed get miniLeft() { return 50 + (NumCast(this._document?._panX) - this.renderContentBounds.cx) / this.renderContentBounds.dim * 100 - this.miniWidth / 2; }
- @computed get miniTop() { return 50 + (NumCast(this._document?._panY) - this.renderContentBounds.cy) / this.renderContentBounds.dim * 100 - this.miniHeight / 2; }
- @computed get miniWidth() { return this.panelWidth() / NumCast(this._document?._viewScale, 1) / this.renderContentBounds.dim * 100; }
- @computed get miniHeight() { return this.panelHeight() / NumCast(this._document?._viewScale, 1) / this.renderContentBounds.dim * 100; }
- childLayoutTemplate = () => Cast(this._document?.childLayoutTemplate, Doc, null);
- returnMiniSize = () => NumCast(this._document?._miniMapSize, 150);
- miniDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
- this._document!._panX = clamp(NumCast(this._document!._panX) + delta[0] / this.returnMiniSize() * this.renderContentBounds.dim, this.renderContentBounds.l, this.renderContentBounds.l + this.renderContentBounds.dim);
- this._document!._panY = clamp(NumCast(this._document!._panY) + delta[1] / this.returnMiniSize() * this.renderContentBounds.dim, this.renderContentBounds.t, this.renderContentBounds.t + this.renderContentBounds.dim);
- return false;
- }), emptyFunction, emptyFunction);
- }
- getCurrentFrame = (): number => {
- const presTargetDoc = Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex].presentationTargetDoc, Doc, null);
- return Cast(presTargetDoc._currentFrame, "number", null);
- }
-
- renderMiniMap() {
- return <div className="miniMap" style={{
- width: this.returnMiniSize(), height: this.returnMiniSize(), background: StrCast(this._document!._backgroundColor,
- StrCast(this._document!.backgroundColor, CollectionDockingView.Instance.props.backgroundColor?.(this._document!, 0))),
- }}>
- <CollectionFreeFormView
- Document={this._document!}
- LibraryPath={emptyPath}
- CollectionView={undefined}
- ContainingCollectionView={undefined}
- ContainingCollectionDoc={undefined}
- ChildLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid havin to set stuff like this.
- noOverlay={true} // don't render overlay Docs since they won't scale
- active={returnTrue}
- select={emptyFunction}
- dropAction={undefined}
- isSelected={returnFalse}
- dontRegisterView={true}
- annotationsKey={""}
- fieldKey={Doc.LayoutFieldKey(this._document!)}
- bringToFront={emptyFunction}
- rootSelected={returnTrue}
- addDocument={returnFalse}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- ContentScaling={returnOne}
- PanelWidth={this.returnMiniSize}
- PanelHeight={this.returnMiniSize}
- NativeHeight={returnZero}
- NativeWidth={returnZero}
- ScreenToLocalTransform={this.ScreenToLocalTransform}
- renderDepth={0}
- whenActiveChanged={emptyFunction}
- focus={emptyFunction}
- backgroundColor={CollectionDockingView.Instance.props.backgroundColor}
- addDocTab={this.addDocTab}
- pinToPres={DockedFrameRenderer.PinDoc}
- docFilters={CollectionDockingView.Instance.docFilters}
- searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
- fitToBox={true}
- />
- <div className="miniOverlay" onPointerDown={this.miniDown} >
- <div className="miniThumb" style={{
- width: `${this.miniWidth}% `,
- height: `${this.miniHeight}% `,
- left: `${this.miniLeft}% `,
- top: `${this.miniTop}% `,
- }}
- />
- </div>
+ return <div className="collectiondockingview-container" onPointerDown={this.onPointerDown} ref={this._containerRef}>
+ {this.props.renderDepth > 0 ? "Nested dashboards can't be rendered" : (null)}
</div>;
}
- @computed get docView() {
- TraceMobx();
- if (!this._document) return (null);
- const document = this._document;
- const resolvedDataDoc = !Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined;
- return <>
- <DocumentView key={document[Id]}
- LibraryPath={this._libraryPath}
- Document={document}
- DataDoc={resolvedDataDoc}
- bringToFront={emptyFunction}
- rootSelected={returnTrue}
- addDocument={undefined}
- removeDocument={undefined}
- ContentScaling={this.contentScaling}
- PanelWidth={this.panelWidth}
- PanelHeight={this.panelHeight}
- NativeHeight={this.nativeHeight}
- NativeWidth={this.nativeWidth}
- ScreenToLocalTransform={this.ScreenToLocalTransform}
- renderDepth={0}
- parentActive={returnTrue}
- whenActiveChanged={emptyFunction}
- focus={emptyFunction}
- backgroundColor={CollectionDockingView.Instance.props.backgroundColor}
- addDocTab={this.addDocTab}
- pinToPres={DockedFrameRenderer.PinDoc}
- docFilters={CollectionDockingView.Instance.docFilters}
- searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
- ContainingCollectionView={undefined}
- ContainingCollectionDoc={undefined} />
- {document._viewType === CollectionViewType.Freeform && !this._document?.hideMinimap ? this.renderMiniMap() : (null)}
- </>;
- }
-
- render() {
- return (!this._isActive || !this.layoutDoc) ? (null) :
- (<div className="collectionDockingView-content" ref={ref => this._mainCont = ref}
- style={{
- transform: `translate(${this.previewPanelCenteringOffset}px, 0px)`,
- height: this.layoutDoc && this.layoutDoc._fitWidth ? undefined : "100%",
- width: this.widthpercent
- }}>
- {this.docView}
- </div >);
- }
}
-Scripting.addGlobal(function openOnRight(doc: any) { CollectionDockingView.AddRightSplit(doc); },
+
+Scripting.addGlobal(function openOnRight(doc: any) { CollectionDockingView.AddSplit(doc, "right"); },
"opens up the inputted document on the right side of the screen", "(doc: any)");
-Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.UseRightSplit(doc, undefined, shiftKey); });
+Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.ReplaceTab(doc, "right", undefined, shiftKey); });
diff --git a/src/client/views/collections/ParentDocumentSelector.scss b/src/client/views/collections/CollectionDockingViewMenu.scss
index bc9cf4848..4157f0f7e 100644
--- a/src/client/views/collections/ParentDocumentSelector.scss
+++ b/src/client/views/collections/CollectionDockingViewMenu.scss
@@ -1,15 +1,14 @@
-.parentDocumentSelector-linkFlyout {
+
+.dockingViewButtonSelector {
div {
overflow: visible !important;
}
- .metadataEntry-outerDiv {
- overflow: hidden !important;
- pointer-events: all;
- }
+ display: inline-block;
+ width:100%;
+ height:100%;
}
-
-.parentDocumentSelector-flyout {
+.dockingViewButtonSelector-flyout {
position: relative;
z-index: 9999;
background-color: #eeeeee;
@@ -32,32 +31,4 @@
border-right: 0px;
border-left: 0px;
}
-}
-
-.parentDocumentSelector-button {
- pointer-events: all;
- position: relative;
- display: inline-block;
-
- svg {
- // width:20px !important;
- //height:20px;
- }
-}
-
-.parentDocumentSelector-metadata {
- pointer-events: auto;
- padding-right: 5px;
- width: 25px;
- display: inline-block;
-}
-
-.buttonSelector {
- div {
- overflow: visible !important;
- }
-
- display: inline-block;
- width:100%;
- height:100%;
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionDockingViewMenu.tsx b/src/client/views/collections/CollectionDockingViewMenu.tsx
new file mode 100644
index 000000000..1cab293a8
--- /dev/null
+++ b/src/client/views/collections/CollectionDockingViewMenu.tsx
@@ -0,0 +1,48 @@
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Tooltip } from "@material-ui/core";
+import { action, computed, observable } from "mobx";
+import { observer } from "mobx-react";
+import * as React from "react";
+import { DocumentButtonBar } from "../DocumentButtonBar";
+import { DocumentView } from "../nodes/DocumentView";
+const higflyout = require("@hig/flyout");
+export const { anchorPoints } = higflyout;
+export const Flyout = higflyout.default;
+
+@observer
+export class CollectionDockingViewMenu extends React.Component<{ views: () => DocumentView[], Stack: any }> {
+ customStylesheet(styles: any) {
+ return {
+ ...styles,
+ panel: {
+ ...styles.panel,
+ minWidth: "100px"
+ },
+ };
+ }
+ _ref = React.createRef<HTMLDivElement>();
+
+ @computed get flyout() {
+ return (
+ <div className="dockingViewButtonSelector-flyout" title=" " ref={this._ref}>
+ <DocumentButtonBar views={this.props.views} stack={this.props.Stack} />
+ </div>
+ );
+ }
+
+ @observable _tooltipOpen: boolean = false;
+ render() {
+ return <Tooltip open={this._tooltipOpen} onClose={action(() => this._tooltipOpen = false)} title={<><div className="dash-tooltip">Tap for toolbar, drag to create alias in another pane</div></>} placement="bottom">
+ <span className="dockingViewButtonSelector"
+ onPointerEnter={action(() => !this._ref.current?.getBoundingClientRect().width && (this._tooltipOpen = true))}
+ onPointerDown={action(e => {
+ this.props.views()[0]?.select(false);
+ this._tooltipOpen = false;
+ })} >
+ <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.flyout} stylesheet={this.customStylesheet}>
+ <FontAwesomeIcon icon={"arrows-alt"} size={"sm"} />
+ </Flyout>
+ </span>
+ </Tooltip >;
+ }
+}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index f5d64ba0d..eaada32b0 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -5,7 +5,7 @@ import { Tooltip } from "@material-ui/core";
import { action, computed, Lambda, observable, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
import { ColorState } from "react-color";
-import { Doc, DocListCast, Opt, Field } from "../../../fields/Doc";
+import { Doc, DocListCast, Field, Opt } from "../../../fields/Doc";
import { Document } from "../../../fields/documentSchemas";
import { Id } from "../../../fields/FieldSymbols";
import { InkTool } from "../../../fields/InkField";
@@ -29,10 +29,10 @@ import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart
import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
import { DocumentView } from "../nodes/DocumentView";
import { RichTextMenu } from "../nodes/formattedText/RichTextMenu";
+import { PresBox } from "../nodes/PresBox";
import "./CollectionMenu.scss";
import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView";
-import { DockedFrameRenderer } from "./CollectionDockingView";
-import { PresBox } from "../nodes/PresBox";
+import { TabDocView } from "./TabDocView";
@observer
export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -379,7 +379,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
return !targetDoc ? (null) : <Tooltip key="pin" title={<div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div>} placement="top">
<button className="antimodeMenu-button" style={{ backgroundColor: isPinned ? "121212" : undefined, borderRight: "1px solid gray" }}
- onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
+ onClick={e => TabDocView.PinDoc(targetDoc, isPinned)}>
<FontAwesomeIcon className="documentdecorations-icon" size="lg" icon="map-pin" />
</button>
</Tooltip>;
@@ -443,7 +443,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
<button className="antidmodeMenu-button" style={{ borderRight: "1px solid gray" }}
onClick={e => {
if (targetDoc) {
- DockedFrameRenderer.PinDoc(targetDoc, false);
+ TabDocView.PinDoc(targetDoc, false);
const activeDoc = PresBox.Instance.childDocs[PresBox.Instance.childDocs.length - 1];
const x = targetDoc._panX;
const y = targetDoc._panY;
@@ -868,18 +868,6 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
</Tooltip> : null}
{!this.props.isOverlay || this.document.type !== DocumentType.WEB || this.isText || this.props.isDoc ? (null) :
- <Tooltip key="hypothesis" title={<div className="dash-tooltip">Toggle between native iframe and annotation modes</div>} placement="bottom">
- <button className={"antimodeMenu-button"} key="hypothesis"
- style={{
- backgroundColor: this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined,
- borderRight: "1px solid gray"
- }}
- onClick={() => this.props.docView.layoutDoc.isAnnotating = !this.props.docView.layoutDoc.isAnnotating}>
- <FontAwesomeIcon icon={"edit"} size="lg" /> {/* ["fab", "hire-a-helper"]} size={"lg"} /> */}
- </button>
- </Tooltip>
- }
- {!this.props.isOverlay || this.document.type !== DocumentType.WEB || this.isText || this.props.isDoc ? (null) :
this.urlEditor
}
{!this.isText ?
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 18ca29aaa..0d3a951cf 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -370,7 +370,7 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell {
})}
/>
</div >
- <div onClick={() => this._doc && this.props.addDocTab(this._doc, "onRight")} className="collectionSchemaView-cellContents-docButton">
+ <div onClick={() => this._doc && this.props.addDocTab(this._doc, "add:right")} className="collectionSchemaView-cellContents-docButton">
<FontAwesomeIcon icon="external-link-alt" size="lg" />
</div>
</div>;
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index b2fdf376d..cecee1de3 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -260,6 +260,10 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
componentDidMount() {
document.addEventListener("pointerdown", this.detectClick);
+ const filters = Cast(this.props.Document._docFilters, listSpec("string"));
+ if (filters?.includes(this._key)) {
+ runInAction(() => this.closeResultsVisibility = "contents");
+ }
}
@action
@@ -271,14 +275,6 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
}
}
- componentWillMount() {
- document.removeEventListener("pointerdown", this.detectClick);
- const filters = Cast(this.props.Document._docFilters, listSpec("string"));
- if (filters?.includes(this._key)) {
- runInAction(() => this.closeResultsVisibility = "contents");
- }
- }
-
private tempfilter: string = "";
@undoBatch
onKeyDown = (e: React.KeyboardEvent): void => {
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index a3475b481..383a9312f 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -246,7 +246,7 @@ export class MovableRow extends React.Component<MovableRowProps> {
<div className="row-dragger">
<div className="row-option" style={{ left: 5 }} onClick={undoBatch(() => this.props.removeDoc(this.props.rowInfo.original))}><FontAwesomeIcon icon="trash" size="sm" /></div>
<div className="row-option" style={{ cursor: "grab", left: 25 }} ref={reference} onPointerDown={onItemDown}><FontAwesomeIcon icon="grip-vertical" size="sm" /></div>
- <div className="row-option" style={{ left: 40 }} onClick={() => this.props.addDocTab(this.props.rowInfo.original, "onRight")}><FontAwesomeIcon icon="external-link-alt" size="sm" /></div>
+ <div className="row-option" style={{ left: 40 }} onClick={() => this.props.addDocTab(this.props.rowInfo.original, "add:right")}><FontAwesomeIcon icon="external-link-alt" size="sm" /></div>
</div>
{children}
</ReactTableDefaults.TrComponent>
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 66bdcf130..84fd4cbe8 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -39,7 +39,7 @@ export interface TreeViewProps {
containingCollection: Doc;
prevSibling?: Doc;
renderDepth: number;
- deleteDoc: (doc: Doc | Doc[]) => boolean;
+ removeDoc: ((doc: Doc | Doc[]) => boolean) | undefined;
moveDocument: DragManager.MoveFunction;
dropAction: dropActionType;
addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean;
@@ -117,16 +117,16 @@ class TreeView extends React.Component<TreeViewProps> {
Doc.ComputeContentBounds(DocListCast(this.props.document[this.fieldKey]));
}
- @undoBatch openRight = () => this.props.addDocTab(this.doc, "onRight");
+ @undoBatch openRight = () => this.props.addDocTab(this.doc, "add:right");
@undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => {
- return this.doc !== target && this.props.deleteDoc(doc) && addDoc(doc);
+ return this.doc !== target && this.props.removeDoc?.(doc) === true && addDoc(doc);
}
@undoBatch @action remove = (doc: Doc | Doc[], key: string) => {
return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true);
}
@undoBatch @action removeDoc = (doc: Doc | Doc[]) => {
return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) =>
- flg && Doc.RemoveDocFromList(this.props.containingCollection, Doc.LayoutFieldKey(this.props.containingCollection), doc), true);
+ flg && Doc.RemoveDocFromList(this.doc, Doc.LayoutFieldKey(this.doc), doc), true);
}
constructor(props: any) {
@@ -280,8 +280,8 @@ class TreeView extends React.Component<TreeViewProps> {
const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce(
(flg, doc) => flg && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true), true);
- contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] :
- DocListCast(contents), this.props.treeView, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
+ contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] : DocListCast(contents),
+ this.props.treeView, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active,
this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen,
[...this.props.renderedIds, doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false, this.props.whenActiveChanged);
@@ -458,7 +458,7 @@ class TreeView extends React.Component<TreeViewProps> {
onDoubleClick={this.onChildDoubleClick}
dropAction={this.props.dropAction}
moveDocument={this.move}
- removeDocument={this.removeDoc}
+ removeDocument={this.props.removeDoc}
ScreenToLocalTransform={this.getTransform}
ContentScaling={returnOne}
PanelWidth={this.truncateTitleWidth}
@@ -483,7 +483,7 @@ class TreeView extends React.Component<TreeViewProps> {
style={{
fontWeight: Doc.IsSearchMatch(this.doc) !== undefined ? "bold" : undefined,
textDecoration: Doc.GetT(this.doc, "title", "string", true) ? "underline" : undefined,
- outline: BoolCast(this.doc.dashboardBrush) ? "dashed 1px #06123232" : undefined,
+ outline: this.doc === CurrentUserUtils.ActiveDashboard ? "dashed 1px #06123232" : undefined,
pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined
}} >
{view}
@@ -612,7 +612,7 @@ class TreeView extends React.Component<TreeViewProps> {
}
const indent = i === 0 ? undefined : () => {
- if (StrCast(docs[i - 1].layout).indexOf('fieldKey') !== -1) {
+ if (remove && StrCast(docs[i - 1].layout).indexOf('fieldKey') !== -1) {
const fieldKeysub = StrCast(docs[i - 1].layout).split('fieldKey')[1];
const fieldKey = fieldKeysub.split("\'")[1];
if (fieldKey && Cast(docs[i - 1][fieldKey], listSpec(Doc)) !== undefined) {
@@ -623,7 +623,7 @@ class TreeView extends React.Component<TreeViewProps> {
}
};
const outdent = !parentCollectionDoc ? undefined : () => {
- if (StrCast(parentCollectionDoc.layout).indexOf('fieldKey') !== -1) {
+ if (remove && StrCast(parentCollectionDoc.layout).indexOf('fieldKey') !== -1) {
const fieldKeysub = StrCast(parentCollectionDoc.layout).split('fieldKey')[1];
const fieldKey = fieldKeysub.split("\'")[1];
Doc.AddDocToList(parentCollectionDoc, fieldKey, child, parentPrevSibling, false);
@@ -651,7 +651,7 @@ class TreeView extends React.Component<TreeViewProps> {
onCheckedClick={onCheckedClick}
onChildClick={onChildClick}
renderDepth={renderDepth}
- deleteDoc={remove}
+ removeDoc={StrCast(containingCollection.freezeChildren).includes("remove") ? undefined : remove}
addDocument={addDocument}
backgroundColor={backgroundColor}
panelWidth={rowWidth}
@@ -738,7 +738,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
}
onContextMenu = (e: React.MouseEvent): void => {
// need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
- if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myDashboards) {
+ if (!e.isPropagationStopped() && this.doc === CurrentUserUtils.MyDashboards) {
ContextMenu.Instance.addItem({ description: "Create Dashboard", event: () => CurrentUserUtils.createNewDashboard(Doc.UserDoc()), icon: "plus" });
ContextMenu.Instance.addItem({ description: "Delete Dashboard", event: () => this.remove(this.doc), icon: "minus" });
e.stopPropagation();
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index f028b797c..81403de46 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -305,7 +305,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
this.setupViewTypes("UI Controls...", vtype => {
const newRendition = Doc.MakeAlias(this.props.Document);
newRendition._viewType = vtype;
- this.props.addDocTab(newRendition, "onRight");
+ this.props.addDocTab(newRendition, "add:right");
return newRendition;
}, false);
@@ -313,10 +313,10 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
const optionItems = options && "subitems" in options ? options.subitems : [];
!Doc.UserDoc().noviceMode ? optionItems.splice(0, 0, { description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }) : null;
if (this.props.Document.childLayout instanceof Doc) {
- optionItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" });
+ optionItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "add:right"), icon: "project-diagram" });
}
if (this.props.Document.childClickedOpenTemplateView instanceof Doc) {
- optionItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childClickedOpenTemplateView as Doc, "onRight"), icon: "project-diagram" });
+ optionItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childClickedOpenTemplateView as Doc, "add:right"), icon: "project-diagram" });
}
!Doc.UserDoc().noviceMode && optionItems.push({ description: `${this.props.Document.isInPlaceContainer ? "Unset" : "Set"} inPlace Container`, event: () => this.props.Document.isInPlaceContainer = !this.props.Document.isInPlaceContainer, icon: "project-diagram" });
@@ -331,7 +331,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
description: `Edit ${func.name} script`, icon: "edit", event: (obj: any) => {
const alias = Doc.MakeAlias(this.props.Document);
DocUtils.makeCustomViewClicked(alias, undefined, func.key);
- this.props.addDocTab(alias, "onRight");
+ this.props.addDocTab(alias, "add:right");
}
}));
DocListCast(Cast(Doc.UserDoc()["clickFuncs-child"], Doc, null).data).forEach(childClick =>
@@ -582,10 +582,10 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
ChildLayoutTemplate: this.childLayoutTemplate,
ChildLayoutString: this.childLayoutString,
};
- const boxShadow = Doc.UserDoc().renderStyle === "comic" || this.props.Document.isBackground || this.collectionViewType === CollectionViewType.Linear ? undefined :
- `${Cast(Doc.UserDoc().activeDashboard, Doc, null)?.darkScheme ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(this.props.Document.boxShadow, "0.2vw 0.2vw 0.8vw")}`;
+ const boxShadow = Doc.UserDoc().renderStyle === "comic" || this.props.Document._isBackground || this.collectionViewType === CollectionViewType.Linear ? undefined :
+ `${CurrentUserUtils.ActiveDashboard?.darkScheme ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(this.props.Document.boxShadow, "0.2vw 0.2vw 0.8vw")}`;
return (<div className={"collectionView"} onContextMenu={this.onContextMenu}
- style={{ pointerEvents: this.props.Document.isBackground ? "none" : undefined, boxShadow }}>
+ style={{ pointerEvents: this.props.Document._isBackground ? "none" : undefined, boxShadow }}>
{this.showIsTagged()}
<div className="collectionView-facetCont" style={{ display: this.props.PanelPosition === "absolute" ? "flex" : "", justifyContent: this.props.PanelPosition === "absolute" ? "center" : "", width: `calc(100% - ${this.facetWidth()}px)` }}>
{this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)}
diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx
deleted file mode 100644
index 6556e7889..000000000
--- a/src/client/views/collections/ParentDocumentSelector.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from "@material-ui/core";
-import { computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import * as React from "react";
-import { Doc } from "../../../fields/Doc";
-import { Id } from "../../../fields/FieldSymbols";
-import { NumCast } from "../../../fields/Types";
-import { SearchUtil } from "../../util/SearchUtil";
-import { DocumentButtonBar } from "../DocumentButtonBar";
-import { DocumentView } from "../nodes/DocumentView";
-import { CollectionDockingView } from "./CollectionDockingView";
-import { CollectionViewType } from "./CollectionView";
-import './ParentDocumentSelector.scss';
-const higflyout = require("@hig/flyout");
-export const { anchorPoints } = higflyout;
-export const Flyout = higflyout.default;
-
-type SelectorProps = {
- Document: Doc,
- Stack?: any,
- hideTitle?: boolean,
- addDocTab(doc: Doc, location: string): void
-};
-
-@observer
-export class SelectorContextMenu extends React.Component<SelectorProps> {
- @observable private _docs: { col: Doc, target: Doc }[] = [];
- @observable private _otherDocs: { col: Doc, target: Doc }[] = [];
- _reaction: IReactionDisposer | undefined;
-
- componentDidMount() {
- this._reaction = reaction(() => this.props.Document, () => this.fetchDocuments(), { fireImmediately: true });
- }
- componentWillUnmount() {
- this._reaction?.();
- }
- async fetchDocuments() {
- const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document);
- const containerProtoSets = await Promise.all(aliases.map(async alias => ((await SearchUtil.Search("", true, { fq: `data_l:"${alias[Id]}"` })).docs)));
- const containerProtos = containerProtoSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>());
- const containerSets = await Promise.all(Array.from(containerProtos.keys()).map(async container => SearchUtil.GetAliasesOfDocument(container)));
- const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>());
- const doclayoutSets = await Promise.all(Array.from(containers.keys()).map(async (dp) => SearchUtil.GetAliasesOfDocument(dp)));
- const doclayouts = Array.from(doclayoutSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>()).keys());
- runInAction(() => {
- this._docs = doclayouts.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).filter(doc => !Doc.IsSystem(doc)).map(doc => ({ col: doc, target: this.props.Document }));
- this._otherDocs = [];
- });
- }
-
- getOnClick({ col, target }: { col: Doc, target: Doc }) {
- return () => {
- col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
- if (col._viewType === CollectionViewType.Freeform) {
- const newPanX = NumCast(target.x) + NumCast(target._width) / 2;
- const newPanY = NumCast(target.y) + NumCast(target._height) / 2;
- col._panX = newPanX;
- col._panY = newPanY;
- }
- this.props.addDocTab(col, "inTab"); // bcz: dataDoc?
- };
- }
-
- render() {
- return <div >
- {this.props.hideTitle ? (null) : <p key="contexts">Contexts:</p>}
- {this._docs.map(doc => <p key={doc.col[Id] + doc.target[Id]}><a onClick={this.getOnClick(doc)}>{doc.col.title?.toString()}</a></p>)}
- {this._otherDocs.length ? <hr key="hr" /> : null}
- {this._otherDocs.map(doc => <p key={"p" + doc.col[Id] + doc.target[Id]}><a onClick={this.getOnClick(doc)}>{doc.col.title?.toString()}</a></p>)}
- </div>;
- }
-}
-
-@observer
-export class ParentDocSelector extends React.Component<SelectorProps> {
- render() {
- const flyout = (
- <div className="parentDocumentSelector-flyout" title=" ">
- <SelectorContextMenu {...this.props} />
- </div>
- );
- return <div title="Show Contexts" onPointerDown={e => e.stopPropagation()} className="parentDocumentSelector-linkFlyout">
- <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={flyout}>
- <span className="parentDocumentSelector-button" >
- <FontAwesomeIcon icon={"chevron-circle-up"} size={"lg"} />
- </span>
- </Flyout>
- </div>;
- }
-}
-
-@observer
-export class DockingViewButtonSelector extends React.Component<{ views: () => DocumentView[], Stack: any }> {
- customStylesheet(styles: any) {
- return {
- ...styles,
- panel: {
- ...styles.panel,
- minWidth: "100px"
- },
- };
- }
- _ref = React.createRef<HTMLDivElement>();
-
- @computed get flyout() {
- return (
- <div className="ParentDocumentSelector-flyout" title=" " ref={this._ref}>
- <DocumentButtonBar views={this.props.views} stack={this.props.Stack} />
- </div>
- );
- }
-
- render() {
- return <Tooltip title={<><div className="dash-tooltip">Tap for toolbar, drag to create alias in another pane</div></>} placement="bottom">
- <span onPointerDown={e => {
- if (getComputedStyle(this._ref.current!).width !== "100%") {
- e.stopPropagation(); e.preventDefault();
- }
- this.props.views()[0]?.select(false);
- }} className="buttonSelector">
- <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.flyout} stylesheet={this.customStylesheet}>
- <FontAwesomeIcon icon={"arrows-alt"} size={"sm"} />
- </Flyout>
- </span>
- </Tooltip>;
- }
-}
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index 2fe00a245..1fb7aa04a 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -545,7 +545,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
}
onOpenClick = () => {
- this._showDoc && this.props.addDocTab(this._showDoc, "onRight");
+ this._showDoc && this.props.addDocTab(this._showDoc, "add:right");
}
getPreviewTransform = (): Transform => {
diff --git a/src/client/views/collections/TabDocView.scss b/src/client/views/collections/TabDocView.scss
new file mode 100644
index 000000000..9a4b5cbd1
--- /dev/null
+++ b/src/client/views/collections/TabDocView.scss
@@ -0,0 +1,20 @@
+
+.miniMap {
+ position: absolute;
+ overflow: hidden;
+ right: 10;
+ bottom: 10;
+ border: solid 1px;
+ box-shadow: black 0.4vw 0.4vw 0.8vw;
+
+ .miniOverlay {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+
+ .miniThumb {
+ background: #25252525;
+ position: absolute;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
new file mode 100644
index 000000000..5acf825f1
--- /dev/null
+++ b/src/client/views/collections/TabDocView.tsx
@@ -0,0 +1,379 @@
+import 'golden-layout/src/css/goldenlayout-base.css';
+import 'golden-layout/src/css/goldenlayout-dark-theme.css';
+import { clamp } from 'lodash';
+import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
+import { observer } from "mobx-react";
+import * as ReactDOM from 'react-dom';
+import { DataSym, Doc, DocListCast, Opt } from "../../../fields/Doc";
+import { Id } from '../../../fields/FieldSymbols';
+import { FieldId } from "../../../fields/RefField";
+import { listSpec } from '../../../fields/Schema';
+import { Cast, NumCast, StrCast } from "../../../fields/Types";
+import { TraceMobx } from '../../../fields/util';
+import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils } from "../../../Utils";
+import { DocServer } from "../../DocServer";
+import { CurrentUserUtils } from '../../util/CurrentUserUtils';
+import { DocumentManager } from '../../util/DocumentManager';
+import { DragManager, dropActionType } from "../../util/DragManager";
+import { SelectionManager } from '../../util/SelectionManager';
+import { SnappingManager } from '../../util/SnappingManager';
+import { Transform } from '../../util/Transform';
+import { undoBatch } from "../../util/UndoManager";
+import { DocumentView } from "../nodes/DocumentView";
+import { PresBox } from '../nodes/PresBox';
+import { CollectionDockingView } from './CollectionDockingView';
+import "./TabDocView.scss";
+import { CollectionDockingViewMenu } from './CollectionDockingViewMenu';
+import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
+import { CollectionViewType } from './CollectionView';
+import React = require("react");
+const _global = (window /* browser */ || global /* node */) as any;
+
+interface TabDocViewProps {
+ documentId: FieldId;
+ glContainer: any;
+}
+@observer
+export class TabDocView extends React.Component<TabDocViewProps> {
+ _mainCont: HTMLDivElement | null = null;
+ _tabReaction: IReactionDisposer | undefined;
+ @observable private _panelWidth = 0;
+ @observable private _panelHeight = 0;
+ @observable private _isActive: boolean = false;
+ @observable private _document: Doc | undefined;
+ @observable private _view: DocumentView | undefined;
+
+ get stack(): any { return (this.props as any).glContainer.parent.parent; }
+ get tab() { return (this.props as any).glContainer.tab; }
+ get view() { return this._view; }
+
+ @action
+ init = (tab: any, doc: Opt<Doc>) => {
+ if (tab.DashDoc !== doc && doc && tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") {
+ tab._disposers = {} as { [name: string]: IReactionDisposer };
+ tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true);
+ tab.DashDoc = doc;
+
+ CollectionDockingView.Instance.tabMap.add(tab);
+ tab.titleElement[0].onclick = (e: any) => {
+ if (Date.now() - tab.titleElement[0].lastClick < 1000) tab.titleElement[0].select();
+ tab.titleElement[0].lastClick = Date.now();
+ tab.titleElement[0].focus();
+ };
+ tab.titleElement[0].onchange = (e: any) => {
+ tab.titleElement[0].size = e.currentTarget.value.length + 1;
+ Doc.GetProto(doc).title = e.currentTarget.value;
+ };
+ tab.titleElement[0].size = StrCast(doc.title).length + 1;
+ tab.titleElement[0].value = doc.title;
+ tab.titleElement[0].style["max-width"] = "100px";
+ const gearSpan = document.createElement("span");
+ gearSpan.className = "collectionDockingView-gear";
+ gearSpan.style.position = "relative";
+ gearSpan.style.paddingLeft = "0px";
+ gearSpan.style.paddingRight = "12px";
+ const stack = tab.contentItem.parent;
+ tab.element[0].onpointerdown = (e: any) => {
+ e.target.className !== "lm_close_tab" && this.view && SelectionManager.SelectDoc(this.view, false);
+ };
+ // shifts the focus to this tab when another tab is dragged over it
+ tab.element[0].onmouseenter = (e: MouseEvent) => {
+ if (SnappingManager.GetIsDragging() && tab.contentItem !== tab.header.parent.getActiveContentItem()) {
+ tab.header.parent.setActiveContentItem(tab.contentItem);
+ }
+ tab.setActive(true);
+ };
+ const onDown = (e: React.PointerEvent) => {
+ setupMoveUpEvents(this, e, (e) => {
+ !e.defaultPrevented && DragManager.StartDocumentDrag([gearSpan], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY);
+ return !e.defaultPrevented;
+ }, returnFalse, emptyFunction);
+ };
+
+ tab._disposers.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments().some(v => v.props.Document === doc),
+ (selected) => {
+ selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && tab.header.parent.setActiveContentItem(tab.contentItem);
+ }
+ );
+ tab._disposers.buttonDisposer = reaction(() => this.view,
+ (view) => {
+ if (view) {
+ ReactDOM.render(<span title="Drag as document" className="collectionDockingView-dragAsDocument" onPointerDown={onDown} >
+ <CollectionDockingViewMenu views={() => [view]} Stack={stack} />
+ </span>,
+ gearSpan);
+ tab._disposers.buttonDisposer?.();
+ }
+ }, { fireImmediately: true });
+
+ tab.reactComponents = [gearSpan];
+ tab.element.append(gearSpan);
+ tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => {
+ tab.titleElement[0].value = title;
+ tab.titleElement[0].style.padding = degree ? 0 : 2;
+ tab.titleElement[0].style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`;
+ }, { fireImmediately: true });
+ tab.closeElement.off('click') //unbind the current click handler
+ .click(function () {
+ Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
+ Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", doc, undefined, true, true);
+ SelectionManager.DeselectAll();
+ tab.contentItem.remove();
+ });
+ }
+ }
+ /**
+ * Adds a document to the presentation view
+ **/
+ @undoBatch
+ @action
+ public static PinDoc(doc: Doc, unpin = false) {
+ if (unpin) TabDocView.UnpinDoc(doc);
+ else {
+ //add this new doc to props.Document
+ const curPres = CurrentUserUtils.ActivePresentation;
+ if (curPres) {
+ const pinDoc = Doc.MakeAlias(doc);
+ pinDoc.presentationTargetDoc = doc;
+ pinDoc.presZoomButton = true;
+ pinDoc.context = curPres;
+ Doc.AddDocToList(curPres, "data", pinDoc);
+ if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
+ if (!DocumentManager.Instance.getDocumentView(curPres)) {
+ CollectionDockingView.AddSplit(curPres, "right");
+ }
+ DocumentManager.Instance.jumpToDocument(doc, false, undefined, Cast(doc.context, Doc, null));
+ }
+ }
+ }
+ /**
+ * Adds a document to the presentation view
+ **/
+ @undoBatch
+ @action
+ public static UnpinDoc(doc: Doc) {
+ //add this new doc to props.Document
+ const curPres = CurrentUserUtils.ActivePresentation;
+ if (curPres) {
+ const ind = DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc));
+ ind !== -1 && Doc.RemoveDocFromList(curPres, "data", DocListCast(curPres.data)[ind]);
+ }
+ }
+
+ componentDidMount() {
+ const color = () => StrCast(this._document?._backgroundColor, this._document && CollectionDockingView.Instance?.props.backgroundColor?.(this._document, 0) || "white");
+ const selected = () => SelectionManager.SelectedDocuments().some(v => v.props.Document === this._document);
+ const updateTabColor = () => this.tab?.titleElement[0] && (this.tab.titleElement[0].style.backgroundColor = selected() ? color() : "");
+ const observer = new _global.ResizeObserver(action((entries: any) => {
+ for (const entry of entries) {
+ this._panelWidth = entry.contentRect.width;
+ this._panelHeight = entry.contentRect.height;
+ }
+ updateTabColor();
+ }));
+ observer.observe(this.props.glContainer._element[0]);
+ this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged);
+ this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged();
+ this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: color() }), updateTabColor, { fireImmediately: true });
+ }
+
+ componentWillUnmount() {
+ this._tabReaction?.();
+ this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged);
+ }
+
+ @action.bound
+ private onActiveContentItemChanged() {
+ if (this.props.glContainer.tab && this._isActive !== this.props.glContainer.tab.isActive) {
+ this._isActive = this.props.glContainer.tab.isActive;
+ this._isActive && setTimeout(() => this.view && SelectionManager.SelectDoc(this.view, false), 0);
+ (CollectionDockingView.Instance as any)._goldenLayout.isInitialised && CollectionDockingView.Instance.stateChanged();
+ !this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
+ }
+ }
+
+ get layoutDoc() { return this._document && Doc.Layout(this._document); }
+ nativeAspect = () => this.nativeWidth() ? this.nativeWidth() / this.nativeHeight() : 0;
+ panelWidth = () => this.layoutDoc?.maxWidth ? Math.min(Math.max(NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._nativeWidth)), this._panelWidth) :
+ (this.nativeAspect() && this.nativeAspect() < this._panelWidth / this._panelHeight ? this._panelHeight * this.nativeAspect() : this._panelWidth)
+ panelHeight = () => this.nativeAspect() && this.nativeAspect() > this._panelWidth / this._panelHeight ? this._panelWidth / this.nativeAspect() : this._panelHeight;
+ nativeWidth = () => !this.layoutDoc?._fitWidth ? NumCast(this.layoutDoc?._nativeWidth) || this._panelWidth : 0;
+ nativeHeight = () => !this.layoutDoc?._fitWidth ? NumCast(this.layoutDoc?._nativeHeight) || this._panelHeight : 0;
+
+ contentScaling = () => {
+ const nativeH = this.nativeHeight();
+ const nativeW = this.nativeWidth();
+ let scaling = 1;
+ if (!this.layoutDoc?._fitWidth && (!nativeW || !nativeH)) {
+ scaling = 1;
+ } else if (NumCast(this.layoutDoc?._nativeWidth) && ((this.layoutDoc?._fitWidth) ||
+ this._panelHeight / NumCast(this.layoutDoc?._nativeHeight) > this._panelWidth / NumCast(this.layoutDoc?._nativeWidth))) {
+ scaling = this._panelWidth / NumCast(this.layoutDoc?._nativeWidth);
+ } else if (nativeW && nativeH) {
+ const wscale = this.panelWidth() / nativeW;
+ scaling = wscale * nativeH > this._panelHeight ? this._panelHeight / nativeH : wscale;
+ }
+ return scaling;
+ }
+
+ ScreenToLocalTransform = () => {
+ if (this._mainCont && this._mainCont.children) {
+ const { translateX, translateY } = Utils.GetScreenTransform(this._mainCont.children[0].firstChild as HTMLElement);
+ const scale = Utils.GetScreenTransform(this._mainCont).scale;
+ return CollectionDockingView.Instance?.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.contentScaling() / scale);
+ }
+ return Transform.Identity();
+ }
+ get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
+ get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this._panelWidth * 100}% ` : undefined; }
+
+ // adds a tab to the layout based on the locaiton parameter which can be:
+ // close[:{left,right,top,bottom}] - e.g., "close" will close the tab, "close:left" will close the left tab,
+ // add[:{left,right,top,bottom}] - e.g., "add" will add a tab to the current stack, "add:right" will add a tab on the right
+ // replace[:{left,right,top,bottom,<any string>}] - e.g., "replace" will replace the current stack contents,
+ // "replace:right" - will replace the stack on the right named "right" if it exists, or create a stack on the right with that name,
+ // "replace:monkeys" - will replace any tab that has the label 'monkeys', or a tab with that label will be created by default on the right
+ // inPlace - will add the document to any collection along the path from the document to the docking view that has a field isInPlaceContainer. if none is found, inPlace adds a tab to current stack
+ addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => {
+ SelectionManager.DeselectAll();
+ if (doc._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
+ const locationFields = location.split(":");
+ const locationParams = locationFields.length > 1 ? locationFields[1] : "";
+ switch (locationFields[0]) {
+ case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
+ case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
+ case "replace": return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack);
+ case "inPlace":
+ case "add":
+ default: return CollectionDockingView.ToggleSplit(doc, locationParams, this.stack);
+ }
+ }
+
+ @computed get renderContentBounds() {
+ const bounds = this._document ? Cast(this._document._renderContentBounds, listSpec("number"), [0, 0, this.returnMiniSize(), this.returnMiniSize()]) : [0, 0, 0, 0];
+ const xbounds = bounds[2] - bounds[0];
+ const ybounds = bounds[3] - bounds[1];
+ const dim = Math.max(xbounds, ybounds);
+ return { l: bounds[0] + xbounds / 2 - dim / 2, t: bounds[1] + ybounds / 2 - dim / 2, cx: bounds[0] + xbounds / 2, cy: bounds[1] + ybounds / 2, dim };
+ }
+ @computed get miniLeft() { return 50 + (NumCast(this._document?._panX) - this.renderContentBounds.cx) / this.renderContentBounds.dim * 100 - this.miniWidth / 2; }
+ @computed get miniTop() { return 50 + (NumCast(this._document?._panY) - this.renderContentBounds.cy) / this.renderContentBounds.dim * 100 - this.miniHeight / 2; }
+ @computed get miniWidth() { return this.panelWidth() / NumCast(this._document?._viewScale, 1) / this.renderContentBounds.dim * 100; }
+ @computed get miniHeight() { return this.panelHeight() / NumCast(this._document?._viewScale, 1) / this.renderContentBounds.dim * 100; }
+ childLayoutTemplate = () => Cast(this._document?.childLayoutTemplate, Doc, null);
+ returnMiniSize = () => NumCast(this._document?._miniMapSize, 150);
+ miniDown = (e: React.PointerEvent) => {
+ this._document && setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
+ this._document!._panX = clamp(NumCast(this._document!._panX) + delta[0] / this.returnMiniSize() * this.renderContentBounds.dim, this.renderContentBounds.l, this.renderContentBounds.l + this.renderContentBounds.dim);
+ this._document!._panY = clamp(NumCast(this._document!._panY) + delta[1] / this.returnMiniSize() * this.renderContentBounds.dim, this.renderContentBounds.t, this.renderContentBounds.t + this.renderContentBounds.dim);
+ return false;
+ }), emptyFunction, emptyFunction);
+ }
+ getCurrentFrame = (): number => {
+ const presTargetDoc = Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex].presentationTargetDoc, Doc, null);
+ return Cast(presTargetDoc._currentFrame, "number", null);
+ }
+
+ renderMiniMap() {
+ return <div className="miniMap" style={{
+ width: this.returnMiniSize(), height: this.returnMiniSize(), background: StrCast(this._document!._backgroundColor,
+ StrCast(this._document!.backgroundColor, CollectionDockingView.Instance.props.backgroundColor?.(this._document!, 0))),
+ }}>
+ <CollectionFreeFormView
+ Document={this._document!}
+ LibraryPath={emptyPath}
+ CollectionView={undefined}
+ ContainingCollectionView={undefined}
+ ContainingCollectionDoc={undefined}
+ ChildLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid havin to set stuff like this.
+ noOverlay={true} // don't render overlay Docs since they won't scale
+ active={returnTrue}
+ select={emptyFunction}
+ dropAction={undefined}
+ isSelected={returnFalse}
+ dontRegisterView={true}
+ annotationsKey={""}
+ fieldKey={Doc.LayoutFieldKey(this._document!)}
+ bringToFront={emptyFunction}
+ rootSelected={returnTrue}
+ addDocument={returnFalse}
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ ContentScaling={returnOne}
+ PanelWidth={this.returnMiniSize}
+ PanelHeight={this.returnMiniSize}
+ NativeHeight={returnZero}
+ NativeWidth={returnZero}
+ ScreenToLocalTransform={this.ScreenToLocalTransform}
+ renderDepth={0}
+ whenActiveChanged={emptyFunction}
+ focus={emptyFunction}
+ backgroundColor={CollectionDockingView.Instance.props.backgroundColor}
+ addDocTab={this.addDocTab}
+ pinToPres={TabDocView.PinDoc}
+ docFilters={CollectionDockingView.Instance.docFilters}
+ searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
+ fitToBox={true}
+ />
+ <div className="miniOverlay" onPointerDown={this.miniDown} >
+ <div className="miniThumb" style={{
+ width: `${this.miniWidth}% `,
+ height: `${this.miniHeight}% `,
+ left: `${this.miniLeft}% `,
+ top: `${this.miniTop}% `,
+ }}
+ />
+ </div>
+ </div>;
+ }
+ focusFunc = (doc: Doc, willZoom: boolean, scale?: number, afterFocus?: () => void) => afterFocus?.();
+ setView = action((view: DocumentView) => this._view = view);
+ @computed get docView() {
+ TraceMobx();
+ return !this._document ? (null) :
+ <><DocumentView key={this._document[Id]}
+ LibraryPath={emptyPath}
+ Document={this._document}
+ getView={this.setView}
+ DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined}
+ bringToFront={emptyFunction}
+ rootSelected={returnTrue}
+ addDocument={undefined}
+ removeDocument={undefined}
+ ContentScaling={this.contentScaling}
+ PanelWidth={this.panelWidth}
+ PanelHeight={this.panelHeight}
+ NativeHeight={this.nativeHeight}
+ NativeWidth={this.nativeWidth}
+ ScreenToLocalTransform={this.ScreenToLocalTransform}
+ renderDepth={0}
+ parentActive={returnTrue}
+ whenActiveChanged={emptyFunction}
+ focus={this.focusFunc}
+ backgroundColor={CollectionDockingView.Instance.props.backgroundColor}
+ addDocTab={this.addDocTab}
+ pinToPres={TabDocView.PinDoc}
+ docFilters={CollectionDockingView.Instance.docFilters}
+ searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
+ ContainingCollectionView={undefined}
+ ContainingCollectionDoc={undefined} />
+ {this._document._viewType === CollectionViewType.Freeform && !this._document?.hideMinimap ? this.renderMiniMap() : (null)}
+ </>;
+ }
+
+ render() {
+ return (<div className="collectionDockingView-content" ref={ref => {
+ if (this._mainCont = ref) {
+ (this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
+ this.tab && DocServer.GetRefField(this.tab.contentItem.config.props.documentId).then(action(doc => doc instanceof Doc && (this._document = doc) && this.init(this.tab, this._document)));
+ }
+ }}
+ style={{
+ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)`,
+ height: this.layoutDoc?._fitWidth ? undefined : "100%",
+ width: this.widthpercent
+ }}>
+ {this.docView}
+ </div >);
+ }
+}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index 646ae94fb..bc2cb2d20 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -10,6 +10,7 @@ import { Id, ToString } from "../../../../fields/FieldSymbols";
import { ObjectField } from "../../../../fields/ObjectField";
import { RefField } from "../../../../fields/RefField";
import { listSpec } from "../../../../fields/Schema";
+import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
export interface ViewDefBounds {
type: string;
@@ -359,7 +360,7 @@ export function computeTimelineLayout(
groupNames.push({ type: "text", text: toLabel(Math.ceil(maxTime)), x: Math.ceil(maxTime - minTime) * scaling, y: 0, height: fontHeight, fontSize, payload: undefined });
}
- const divider = { type: "div", color: Cast(Doc.UserDoc().activeDashboard, Doc, null)?.darkScheme ? "dimGray" : "black", x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined };
+ const divider = { type: "div", color: CurrentUserUtils.ActiveDashboard?.darkScheme ? "dimGray" : "black", x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined };
return normalizeResults(panelDim, fontHeight, docMap, poolData, viewDefsToJSX, groupNames, (maxTime - minTime) * scaling, [divider]);
function layoutDocsAtTime(keyDocs: Doc[], key: number) {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7ba8694ed..30a71398b 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -217,7 +217,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const nd = [NumCast(layoutDoc._nativeWidth), NumCast(layoutDoc._nativeHeight)];
layoutDoc._width = NumCast(layoutDoc._width, 300);
layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? nd[1] / nd[0] * NumCast(layoutDoc._width) : 300);
- d.isBackground === undefined && (d.zIndex = zsorted.length + 1 + i); // bringToFront
+ d._isBackground === undefined && (d.zIndex = zsorted.length + 1 + i); // bringToFront
}
(docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(docDragData.droppedDocuments);
@@ -256,7 +256,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@action
onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
- // if (this.props.Document.isBackground) return false;
+ // if (this.props.Document._isBackground) return false;
const [xp, yp] = this.getTransform().transformPoint(de.x, de.y);
if (this.isAnnotationOverlay !== true && de.complete.linkDragData) {
return this.internalLinkDrop(e, de, de.complete.linkDragData, xp, yp);
@@ -384,8 +384,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
clusterColor = colors[cluster % colors.length];
const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor);
// override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document
- set && set.filter(s => !s.isBackground).map(s => clusterColor = StrCast(s.backgroundColor));
- set && set.filter(s => s.isBackground).map(s => clusterColor = StrCast(s.backgroundColor));
+ set && set.filter(s => !s._isBackground).map(s => clusterColor = StrCast(s.backgroundColor));
+ set && set.filter(s => s._isBackground).map(s => clusterColor = StrCast(s.backgroundColor));
}
}
return clusterColor;
@@ -839,7 +839,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
bringToFront = action((doc: Doc, sendToBack?: boolean) => {
- if (sendToBack || doc.isBackground) {
+ if (sendToBack || doc._isBackground) {
doc.zIndex = 0;
} else if (doc.isInkMask) {
doc.zIndex = 5000;
@@ -904,10 +904,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const savedState = { px: this.Document._panX, py: this.Document._panY, s: this.Document[this.scaleFieldKey], pt: this.Document._viewTransition };
- // if (!willZoom && DocumentView._focusHack.length) {
- // Doc.BrushDoc(this.props.Document);
- // !doc.z && NumCast(this.layoutDoc.scale) < 1 && this.scaleAtPt(DocumentView._focusHack, 1); // [NumCast(doc.x), NumCast(doc.y)], 1);
- // } else {
if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) {
// glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
if (!doc.z) this.setPan(newPanX, newPanY, doc.presTransition || doc.presTransition === 0 ? `transform ${doc.presTransition}ms` : "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
@@ -916,7 +912,6 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this.props.focus(this.props.Document);
willZoom && this.setScaleToZoom(layoutdoc, scale);
Doc.linkFollowHighlight(doc);
- //}
afterFocus && setTimeout(() => {
if (afterFocus?.()) {
@@ -935,7 +930,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
@computed get libraryPath() { return this.props.LibraryPath ? [...this.props.LibraryPath, this.props.Document] : []; }
- @computed get backgroundActive() { return this.layoutDoc.isBackground && (this.props.ContainingCollectionView?.active() || this.props.active()); }
+ @computed get backgroundActive() { return this.layoutDoc._isBackground && (this.props.ContainingCollectionView?.active() || this.props.active()); }
onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick);
onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick);
backgroundHalo = () => BoolCast(this.Document._useClusters);
@@ -1328,7 +1323,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
};
const snappableDocs: Doc[] = []; // the set of documents in the visible viewport that we will try to snap to;
const otherBounds = { left: this.panX(), top: this.panY(), width: Math.abs(size[0]), height: Math.abs(size[1]) };
- this.getActiveDocuments().filter(doc => !doc.isBackground && doc.z === undefined).map(doc => isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to
+ this.getActiveDocuments().filter(doc => !doc._isBackground && doc.z === undefined).map(doc => isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to
!snappableDocs.length && this.getActiveDocuments().filter(doc => doc.z === undefined).map(doc => isDocInView(doc, selRect)); // if not, see if there are background docs to snap to
!snappableDocs.length && this.getActiveDocuments().filter(doc => doc.z !== undefined).map(doc => isDocInView(doc, otherBounds)); // if not, then why not snap to floating docs
@@ -1422,7 +1417,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const wscale = nw ? this.props.PanelWidth() / nw : 1;
return wscale < hscale ? wscale : hscale;
}
- @computed get backgroundEvents() { return this.layoutDoc.isBackground && SnappingManager.GetIsDragging(); }
+ @computed get backgroundEvents() { return this.layoutDoc._isBackground && SnappingManager.GetIsDragging(); }
render() {
TraceMobx();
const clientRect = this._mainCont?.getBoundingClientRect();
@@ -1637,7 +1632,7 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
style={{
transform: `translate(${cenx}px, ${ceny}px) scale(${zoom}) translate(${panx}px, ${pany}px)`,
transition: this.props.transition,
- willChange: "transform"
+ //willChange: "transform"
}}>
{this.props.children()}
{this.presPaths}
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.scss b/src/client/views/collections/collectionFreeForm/FormatShapePane.scss
deleted file mode 100644
index d49ab27fb..000000000
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.scss
+++ /dev/null
@@ -1,68 +0,0 @@
-.antimodeMenu-button {
- width: 200px;
- position: relative;
- text-align: left;
-
- .color-previewI {
- width: 100%;
- height: 40%;
- }
-
- .color-previewII {
- width: 100%;
- height: 100%;
- }
-}
-
-.antimenu-Buttonup {
- position: absolute;
- width: 20;
- height: 10;
- right: 0;
- padding: 0;
-}
-
-.formatShapePane-inputBtn {
- width: inherit;
- position: absolute;
-}
-
-.btn-group-palette {
- .sketch-picker {
- background: #323232;
- width: 160px !important;
- height: 80% !important;
-
- .flexbox-fit {
- background: #323232;
- }
- }
-}
-
-.btn-group {
- display: grid;
- grid-template-columns: auto auto auto auto;
- /* Make the buttons appear below each other */
-}
-
-.btn-group-palette {
- display: block;
- /* Make the buttons appear below each other */
-}
-
-.btn-draw {
- display: inline;
- /* Make the buttons appear below each other */
-}
-
-.btn2-group {
- display: block;
- background: #323232;
- grid-template-columns: auto;
-
- /* Make the buttons appear below each other */
- .antimodeMenu-button {
- background: #323232;
- display: block;
- }
-} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
deleted file mode 100644
index e6ec274f0..000000000
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ /dev/null
@@ -1,545 +0,0 @@
-import React = require("react");
-import { IconProp } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import { Doc, Field, Opt } from "../../../../fields/Doc";
-import { Document } from "../../../../fields/documentSchemas";
-import { InkField } from "../../../../fields/InkField";
-import { BoolCast, Cast, NumCast } from "../../../../fields/Types";
-import { DocumentType } from "../../../documents/DocumentTypes";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { AntimodeMenu, AntimodeMenuProps } from "../../AntimodeMenu";
-import "./FormatShapePane.scss";
-import { undoBatch } from "../../../util/UndoManager";
-import { ColorState, SketchPicker } from 'react-color';
-
-@observer
-export class FormatShapePane extends AntimodeMenu<AntimodeMenuProps> {
- static Instance: FormatShapePane;
-
- private _lastFill = "#D0021B";
- private _lastLine = "#D0021B";
- private _lastDash = "2";
- private _mode = ["fill-drip", "ruler-combined"];
-
- @observable private _subOpen = [false, false];
- @observable private _currMode = "fill-drip";
- @observable _lock = false;
- @observable private _fillBtn = false;
- @observable private _lineBtn = false;
- @observable _controlBtn = false;
- @observable private _controlPoints: { X: number, Y: number }[] = [];
- @observable _currPoint = -1;
-
- getField(key: string) {
- return this.selectedInk?.reduce((p, i) =>
- (p === undefined || (p && p === i.rootDoc[key])) && i.rootDoc[key] !== "0" ? Field.toString(i.rootDoc[key] as Field) : "", undefined as Opt<string>);
- }
-
- @computed get selectedInk() {
- const inks = SelectionManager.SelectedDocuments().filter(i => Document(i.rootDoc).type === DocumentType.INK);
- return inks.length ? inks : undefined;
- }
- @computed get unFilled() { return this.selectedInk?.reduce((p, i) => p && !i.rootDoc.fillColor ? true : false, true) || false; }
- @computed get unStrokd() { return this.selectedInk?.reduce((p, i) => p && !i.rootDoc.color ? true : false, true) || false; }
- @computed get solidFil() { return this.selectedInk?.reduce((p, i) => p && i.rootDoc.fillColor ? true : false, true) || false; }
- @computed get solidStk() { return this.selectedInk?.reduce((p, i) => p && i.rootDoc.color && (!i.rootDoc.strokeDash || i.rootDoc.strokeDash === "0") ? true : false, true) || false; }
- @computed get dashdStk() { return !this.unStrokd && this.getField("strokeDash") || ""; }
- @computed get colorFil() { const ccol = this.getField("fillColor") || ""; ccol && (this._lastFill = ccol); return ccol; }
- @computed get colorStk() { const ccol = this.getField("color") || ""; ccol && (this._lastLine = ccol); return ccol; }
- @computed get widthStk() { return this.getField("strokeWidth") || "1"; }
- @computed get markHead() { return this.getField("strokeStartMarker") || ""; }
- @computed get markTail() { return this.getField("strokeEndMarker") || ""; }
- @computed get shapeHgt() { return this.getField("_height"); }
- @computed get shapeWid() { return this.getField("_width"); }
- @computed get shapeXps() { return this.getField("x"); }
- @computed get shapeYps() { return this.getField("y"); }
- @computed get shapeRot() { return this.getField("rotation"); }
- set unFilled(value) { this.colorFil = value ? "" : this._lastFill; }
- set solidFil(value) { this.unFilled = !value; }
- set colorFil(value) { value && (this._lastFill = value); this.selectedInk?.forEach(i => i.rootDoc.fillColor = value ? value : undefined); }
- set colorStk(value) { value && (this._lastLine = value); this.selectedInk?.forEach(i => i.rootDoc.color = value ? value : undefined); }
- set markHead(value) { this.selectedInk?.forEach(i => i.rootDoc.strokeStartMarker = value); }
- set markTail(value) { this.selectedInk?.forEach(i => i.rootDoc.strokeEndMarker = value); }
- set unStrokd(value) { this.colorStk = value ? "" : this._lastLine; }
- set solidStk(value) { this.dashdStk = ""; this.unStrokd = !value; }
- set dashdStk(value) {
- value && (this._lastDash = value) && (this.unStrokd = false);
- this.selectedInk?.forEach(i => i.rootDoc.strokeDash = value ? this._lastDash : undefined);
- }
- set shapeXps(value) { this.selectedInk?.forEach(i => i.rootDoc.x = Number(value)); }
- set shapeYps(value) { this.selectedInk?.forEach(i => i.rootDoc.y = Number(value)); }
- set shapeRot(value) { this.selectedInk?.forEach(i => i.rootDoc.rotation = Number(value)); }
- set widthStk(value) { this.selectedInk?.forEach(i => i.rootDoc.strokeWidth = Number(value)); }
- set shapeWid(value) {
- this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => {
- const oldWidth = NumCast(i.rootDoc._width);
- i.rootDoc._width = Number(value);
- this._lock && (i.rootDoc._height = (i.rootDoc._width * NumCast(i.rootDoc._height)) / oldWidth);
- });
- }
- set shapeHgt(value) {
- this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => {
- const oldHeight = NumCast(i.rootDoc._height);
- i.rootDoc._height = Number(value);
- this._lock && (i.rootDoc._width = (i.rootDoc._height * NumCast(i.rootDoc._width)) / oldHeight);
- });
- }
-
- constructor(props: Readonly<{}>) {
- super(props);
- FormatShapePane.Instance = this;
- this._canFade = false;
- runInAction(() => this.Pinned = BoolCast(Doc.UserDoc()["menuFormatShape-pinned"]));
- }
-
- @action
- closePane = () => {
- this.fadeOut(false);
- this.Pinned = false;
- }
-
- @action
- upDownButtons = (dirs: string, field: string) => {
- switch (field) {
- case "rot": this.rotate((dirs === "up" ? .1 : -.1)); break;
- // case "rot": this.selectedInk?.forEach(i => i.rootDoc.rotation = NumCast(i.rootDoc.rotation) + (dirs === "up" ? 0.1 : -0.1)); break;
- case "Xps": this.selectedInk?.forEach(i => i.rootDoc.x = NumCast(i.rootDoc.x) + (dirs === "up" ? 10 : -10)); break;
- case "Yps": this.selectedInk?.forEach(i => i.rootDoc.y = NumCast(i.rootDoc.y) + (dirs === "up" ? 10 : -10)); break;
- case "stk": this.selectedInk?.forEach(i => i.rootDoc.strokeWidth = NumCast(i.rootDoc.strokeWidth) + (dirs === "up" ? .1 : -.1)); break;
- case "wid": this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => {
- //redraw points
- const oldWidth = NumCast(i.rootDoc._width);
- const oldHeight = NumCast(i.rootDoc._height);
- const oldX = NumCast(i.rootDoc.x);
- const oldY = NumCast(i.rootDoc.y);
- i.rootDoc._width = oldWidth + (dirs === "up" ? 10 : - 10);
- this._lock && (i.rootDoc._height = (i.rootDoc._width / oldWidth * NumCast(i.rootDoc._height)));
- const doc = Document(i.rootDoc);
- if (doc.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
- const newPoints: { X: number, Y: number }[] = [];
- ink.forEach(i => {
- // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
- const newX = ((doc.x || 0) - oldX) + (i.X * (doc._width || 0)) / oldWidth;
- const newY = ((doc.y || 0) - oldY) + (i.Y * (doc._height || 0)) / oldHeight;
- newPoints.push({ X: newX, Y: newY });
- });
- Doc.GetProto(doc).data = new InkField(newPoints);
- }
- }
- });
- break;
- case "hgt": this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => {
- const oldWidth = NumCast(i.rootDoc._width);
- const oldHeight = NumCast(i.rootDoc._height);
- const oldX = NumCast(i.rootDoc.x);
- const oldY = NumCast(i.rootDoc.y); i.rootDoc._height = oldHeight + (dirs === "up" ? 10 : - 10);
- this._lock && (i.rootDoc._width = (i.rootDoc._height / oldHeight * NumCast(i.rootDoc._width)));
- const doc = Document(i.rootDoc);
- if (doc.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
- const newPoints: { X: number, Y: number }[] = [];
- ink.forEach(i => {
- // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
- const newX = ((doc.x || 0) - oldX) + (i.X * (doc._width || 0)) / oldWidth;
- const newY = ((doc.y || 0) - oldY) + (i.Y * (doc._height || 0)) / oldHeight;
- newPoints.push({ X: newX, Y: newY });
- });
- Doc.GetProto(doc).data = new InkField(newPoints);
- }
- }
- });
- break;
- }
- }
-
- @undoBatch
- @action
- addPoints = (x: number, y: number, pts: { X: number, Y: number }[], index: number, control: { X: number, Y: number }[]) => {
- this.selectedInk?.forEach(action(inkView => {
- if (this.selectedInk?.length === 1) {
- const doc = Document(inkView.rootDoc);
- if (doc.type === DocumentType.INK) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
- const newPoints: { X: number, Y: number }[] = [];
- var counter = 0;
- for (var k = 0; k < index; k++) {
- control.forEach(pt => (pts[k].X === pt.X && pts[k].Y === pt.Y) && counter++);
- }
- //decide where to put the new coordinate
- const spNum = Math.floor(counter / 2) * 4 + 2;
-
- for (var i = 0; i < spNum; i++) {
- ink[i] && newPoints.push({ X: ink[i].X, Y: ink[i].Y });
- }
- for (var j = 0; j < 4; j++) {
- newPoints.push({ X: x, Y: y });
-
- }
- for (var i = spNum; i < ink.length; i++) {
- newPoints.push({ X: ink[i].X, Y: ink[i].Y });
- }
- this._currPoint = -1;
- Doc.GetProto(doc).data = new InkField(newPoints);
- }
- }
- }
- }));
- }
-
- @undoBatch
- @action
- deletePoints = () => {
- this.selectedInk?.forEach(action(inkView => {
- if (this.selectedInk?.length === 1 && this._currPoint !== -1) {
- const doc = Document(inkView.rootDoc);
- if (doc.type === DocumentType.INK) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink && ink.length > 4) {
- const newPoints: { X: number, Y: number }[] = [];
- const toRemove = Math.floor(((this._currPoint + 2) / 4));
- for (var i = 0; i < ink.length; i++) {
- if (Math.floor((i + 2) / 4) !== toRemove) {
- newPoints.push({ X: ink[i].X, Y: ink[i].Y });
- }
- }
- this._currPoint = -1;
- Doc.GetProto(doc).data = new InkField(newPoints);
- if (newPoints.length === 4) {
- const newerPoints: { X: number, Y: number }[] = [];
- newerPoints.push({ X: newPoints[0].X, Y: newPoints[0].Y });
- newerPoints.push({ X: newPoints[0].X, Y: newPoints[0].Y });
- newerPoints.push({ X: newPoints[3].X, Y: newPoints[3].Y });
- newerPoints.push({ X: newPoints[3].X, Y: newPoints[3].Y });
- Doc.GetProto(doc).data = new InkField(newerPoints);
-
- }
- }
- }
- }
- }));
- }
-
- @undoBatch
- @action
- rotate = (angle: number) => {
- const _centerPoints: { X: number, Y: number }[] = [];
- SelectionManager.SelectedDocuments().forEach(action(inkView => {
- const doc = Document(inkView.rootDoc);
- if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
- const xs = ink.map(p => p.X);
- const ys = ink.map(p => p.Y);
- const left = Math.min(...xs);
- const top = Math.min(...ys);
- const right = Math.max(...xs);
- const bottom = Math.max(...ys);
- _centerPoints.push({ X: left, Y: top });
- }
- }
- }));
-
- var index = 0;
- SelectionManager.SelectedDocuments().forEach(action(inkView => {
- const doc = Document(inkView.rootDoc);
- if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
- doc.rotation = Number(doc.rotation) + Number(angle);
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
-
- const newPoints: { X: number, Y: number }[] = [];
- ink.forEach(i => {
- const newX = Math.cos(angle) * (i.X - _centerPoints[index].X) - Math.sin(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].X;
- const newY = Math.sin(angle) * (i.X - _centerPoints[index].X) + Math.cos(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].Y;
- newPoints.push({ X: newX, Y: newY });
- });
- Doc.GetProto(doc).data = new InkField(newPoints);
- const xs = newPoints.map(p => p.X);
- const ys = newPoints.map(p => p.Y);
- const left = Math.min(...xs);
- const top = Math.min(...ys);
- const right = Math.max(...xs);
- const bottom = Math.max(...ys);
-
- doc._height = (bottom - top);
- doc._width = (right - left);
- }
- index++;
- }
- }));
- }
-
- @undoBatch
- @action
- control = (xDiff: number, yDiff: number, controlNum: number) => {
- this.selectedInk?.forEach(action(inkView => {
- if (this.selectedInk?.length === 1) {
- const doc = Document(inkView.rootDoc);
- if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
-
- const newPoints: { X: number, Y: number }[] = [];
- const order = controlNum % 4;
- for (var i = 0; i < ink.length; i++) {
- if (controlNum === i ||
- (order === 0 && i === controlNum + 1) ||
- (order === 0 && controlNum !== 0 && i === controlNum - 2) ||
- (order === 0 && controlNum !== 0 && i === controlNum - 1) ||
- (order === 3 && i === controlNum - 1) ||
- (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 1) ||
- (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 2)
- || ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1))
- ) {
- newPoints.push({ X: ink[i].X - (xDiff * inkView.props.ScreenToLocalTransform().Scale), Y: ink[i].Y - (yDiff * inkView.props.ScreenToLocalTransform().Scale) });
- }
- else {
- newPoints.push({ X: ink[i].X, Y: ink[i].Y });
- }
- }
- const oldx = doc.x;
- const oldy = doc.y;
- const xs = ink.map(p => p.X);
- const ys = ink.map(p => p.Y);
- const left = Math.min(...xs);
- const top = Math.min(...ys);
- Doc.GetProto(doc).data = new InkField(newPoints);
- const xs2 = newPoints.map(p => p.X);
- const ys2 = newPoints.map(p => p.Y);
- const left2 = Math.min(...xs2);
- const top2 = Math.min(...ys2);
- const right2 = Math.max(...xs2);
- const bottom2 = Math.max(...ys2);
- doc._height = (bottom2 - top2);
- doc._width = (right2 - left2);
- //if points move out of bounds
-
- doc.x = oldx - (left - left2);
- doc.y = oldy - (top - top2);
-
- }
- }
- }
- }));
- }
-
- @undoBatch
- @action
- switchStk = (color: ColorState) => {
- const val = String(color.hex);
- this.colorStk = val;
- return true;
- }
-
- @undoBatch
- @action
- switchFil = (color: ColorState) => {
- const val = String(color.hex);
- this.colorFil = val;
- return true;
- }
-
-
- colorPicker(setter: (color: string) => {}, type: string) {
- return <div className="btn-group-palette" key="colorpicker" style={{ width: 160, margin: 10 }}>
- <SketchPicker onChange={type === "stk" ? this.switchStk : this.switchFil} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
- color={type === "stk" ? this.colorStk : this.colorFil} />
- </div>;
- }
- inputBox = (key: string, value: any, setter: (val: string) => {}) => {
- return <>
- <input style={{ color: "black", width: 40, position: "absolute", right: 20 }}
- type="text" defaultValue={value}
- onChange={undoBatch(action((e) => setter(e.target.value)))}
- autoFocus />
- <button className="antiMenu-Buttonup" key="up1" onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))}>
- ˄
- </button>
- <br />
- <button className="antiMenu-Buttonup" key="down1" onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} style={{ marginTop: -8 }}>
- ˅
- </button>
- </>;
- }
-
- inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => {
- return <>
- {title1}
- <p style={{ marginTop: -20, right: 70, position: "absolute" }}>{title2}</p>
-
- <input style={{ color: "black", width: 40, position: "absolute", right: 130 }}
- type="text" defaultValue={value}
- onChange={e => setter(e.target.value)}
- autoFocus />
- <button className="antiMenu-Buttonup" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))} style={{ right: 110 }}>
- ˄
- </button>
- <button className="antiMenu-Buttonup" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} style={{ marginTop: 12, right: 110 }}>
- ˅
- </button>
- {title2 === "" ? "" : <>
- <input style={{ color: "black", width: 40, position: "absolute", right: 20 }}
- type="text" defaultValue={value2}
- onChange={e => setter2(e.target.value)}
- autoFocus />
- <button className="antiMenu-Buttonup" key="up3" onPointerDown={undoBatch(action(() => this.upDownButtons("up", key2)))}>
- ˄
- </button>
- <br />
- <button className="antiMenu-Buttonup" key="down3" onPointerDown={undoBatch(action(() => this.upDownButtons("down", key2)))} style={{ marginTop: -8 }}>
- ˅
- </button></>}
- </>;
- }
-
-
- colorButton(value: string, setter: () => {}) {
- return <>
- <button className="antimodeMenu-button" key="color" onPointerDown={undoBatch(action(e => setter()))} style={{ position: "relative", marginTop: -5 }}>
- <div className="color-previewII" style={{ backgroundColor: value ?? "121212" }} />
- {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -23, position: "fixed" }}>☒</p> : ""}
- </button>
- </>;
- }
-
- controlPointsButton() {
- return <>
- <button className="antimodeMenu-button" title="Edit points" key="bezier" onPointerDown={action(() => this._controlBtn = this._controlBtn ? false : true)} style={{ position: "relative", marginTop: 10, backgroundColor: this._controlBtn ? "black" : "" }}>
- <FontAwesomeIcon icon="bezier-curve" size="lg" />
- </button>
- <button className="antimodeMenu-button" title="Lock ratio" key="ratio" onPointerDown={action(() => this._lock = this._lock ? false : true)} style={{ position: "relative", marginTop: 10, backgroundColor: this._lock ? "black" : "" }}>
- <FontAwesomeIcon icon="lock" size="lg" />
-
- </button>
- <button className="antimodeMenu-button" key="rotate" title="Rotate 90˚" onPointerDown={action(() => this.rotate(Math.PI / 2))} style={{ position: "relative", marginTop: 10, fontSize: 15 }}>
- ⟲
- </button>
- <br /> <br />
- </>;
- }
-
- lockRatioButton() {
- return <>
- <button className="antimodeMenu-button" key="lock" onPointerDown={action(() => this._lock = this._lock ? false : true)} style={{ position: "absolute", right: 80, backgroundColor: this._lock ? "black" : "" }}>
- {/* <FontAwesomeIcon icon="bezier-curve" size="lg" /> */}
- <FontAwesomeIcon icon="lock" size="lg" />
-
- </button>
- <br /> <br />
- </>;
- }
-
- rotate90Button() {
- return <>
- <button className="antimodeMenu-button" key="rot" onPointerDown={action(() => this.rotate(Math.PI / 2))} style={{ position: "absolute", right: 80, }}>
- {/* <FontAwesomeIcon icon="bezier-curve" size="lg" /> */}
- ⟲
- </button>
- <br /> <br />
- </>;
- }
- @computed get fillButton() { return this.colorButton(this.colorFil, () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); }
- @computed get lineButton() { return this.colorButton(this.colorStk, () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); }
-
- @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color, "fil"); }
- @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color, "stk"); }
-
- @computed get stkInput() { return this.inputBox("stk", this.widthStk, (val: string) => this.widthStk = val); }
- @computed get dashInput() { return this.inputBox("dsh", this.widthStk, (val: string) => this.widthStk = val); }
-
- @computed get hgtInput() { return this.inputBoxDuo("hgt", this.shapeHgt, (val: string) => this.shapeHgt = val, "H:", "wid", this.shapeWid, (val: string) => this.shapeWid = val, "W:"); }
- @computed get widInput() { return this.inputBox("wid", this.shapeWid, (val: string) => this.shapeWid = val); }
- @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); }
-
- @computed get YpsInput() { return this.inputBox("Yps", this.shapeYps, (val: string) => this.shapeYps = val); }
-
- @computed get controlPoints() { return this.controlPointsButton(); }
- @computed get lockRatio() { return this.lockRatioButton(); }
- @computed get rotate90() { return this.rotate90Button(); }
- @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
-
-
- @computed get propertyGroupItems() {
- const fillCheck = <div key="fill" style={{ display: (this._subOpen[0] && this.selectedInk && this.selectedInk.length >= 1) ? "" : "none", width: "inherit", backgroundColor: "#323232", color: "white", }}>
- Fill:
- {this.fillButton}
- <div style={{ float: "left", width: 100 }} >
- Stroke:
- {this.lineButton}
- </div>
-
- {this._fillBtn ? this.fillPicker : ""}
- {this._lineBtn ? this.linePicker : ""}
- {this._fillBtn || this._lineBtn ? "" : <br />}
- {(this.solidStk || this.dashdStk) ? "Width" : ""}
- {(this.solidStk || this.dashdStk) ? this.stkInput : ""}
- {(this.solidStk || this.dashdStk) ? <input type="range" defaultValue={Number(this.widthStk)} min={1} max={100} onChange={undoBatch(action((e) => this.widthStk = e.target.value))} /> : (null)}
- <br />
- {(this.solidStk || this.dashdStk) ? <>
- <p style={{ position: "absolute", fontSize: 12 }}>Arrow Head</p>
- <input key="markHead" className="formatShapePane-inputBtn" type="checkbox" checked={this.markHead !== ""} onChange={undoBatch(action(() => this.markHead = this.markHead ? "" : "arrow"))} style={{ position: "absolute", right: 110, width: 20 }} />
- <p style={{ position: "absolute", fontSize: 12, right: 30 }}>Arrow End</p>
- <input key="markTail" className="formatShapePane-inputBtn" type="checkbox" checked={this.markTail !== ""} onChange={undoBatch(action(() => this.markTail = this.markTail ? "" : "arrow"))} style={{ position: "absolute", right: 0, width: 20 }} />
- <br />
- </> : ""}
- Dash:
- <input key="markHead" className="formatShapePane-inputBtn" type="checkbox" checked={this.dashdStk === "2"} onChange={undoBatch(action(() => this.dashdStk = this.dashdStk === "2" ? "0" : "2"))} style={{ position: "absolute", right: 110, width: 20 }} />
- </div>;
-
-
-
- const sizeCheck =
-
- <div key="sizeCheck" style={{ display: (this._subOpen[1] && this.selectedInk && this.selectedInk.length >= 1) ? "" : "none", width: "inherit", backgroundColor: "#323232", color: "white", }}>
- {this.controlPoints}
- {this.hgtInput}
- {this.XpsInput}
- {this.rotInput}
-
- </div>;
-
-
- const subMenus = this._currMode === "fill-drip" ? [`Appearance`, 'Transform'] : [];
- const menuItems = this._currMode === "fill-drip" ? [fillCheck, sizeCheck] : [];
- const indexOffset = 0;
-
- return <div className="antimodeMenu-sub" key="submenu" style={{ position: "absolute", width: "inherit", top: 60 }}>
- {subMenus.map((subMenu, i) =>
- <div key={subMenu} style={{ width: "inherit" }}>
- <button className="antimodeMenu-button" onPointerDown={action(() => this._subOpen[i + indexOffset] = !this._subOpen[i + indexOffset])}
- style={{ backgroundColor: "121212", position: "relative", width: "inherit" }}>
- {this._subOpen[i + indexOffset] ? "▼" : "▶︎"}
- {subMenu}
- </button>
- {menuItems[i]}
- </div>)}
- </div>;
- }
-
- @computed get closeBtn() {
- return <button className="antimodeMenu-button" key="close" onPointerDown={action(() => this.closePane())} style={{ position: "absolute", right: 0 }}>
- X
- </button>;
- }
-
- @computed get propertyGroupBtn() {
- return <div className="antimodeMenu-button-tab" key="modes">
- {this._mode.map(mode =>
- <button className="antimodeMenu-button" key={mode} onPointerDown={action(() => this._currMode = mode)}
- style={{ backgroundColor: this._currMode === mode ? "121212" : "", position: "relative", top: 30 }}>
- <FontAwesomeIcon icon={mode as IconProp} size="lg" />
- </button>)}
- </div>;
- }
-
- render() {
- return this.getElementVert([this.closeBtn,
- this.propertyGroupItems]);
- }
-} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 864c45ca2..1aa30fc02 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -76,7 +76,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
const [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY);
if (e.key === "?") {
cm.setDefaultItem("?", (str: string) => this.props.addDocTab(
- Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 200, x, y, _nativeHeight: 962, _nativeWidth: 850, isAnnotating: false, title: "bing", UseCors: true }), "onRight"));
+ Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 200, x, y, _nativeHeight: 962, _nativeWidth: 850, isAnnotating: false, title: "bing", UseCors: true }), "add:right"));
cm.displayMenu(this._downX, this._downY);
e.stopPropagation();
@@ -355,7 +355,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
this.hideMarquee();
}
- getCollection = action((selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, isBackground?: boolean) => {
+ getCollection = action((selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, _isBackground?: boolean) => {
const newCollection = creator ? creator(selected, { title: "nested stack", }) : ((doc: Doc) => {
Doc.GetProto(doc).data = new List<Doc>(selected);
Doc.GetProto(doc).title = "nested freeform";
@@ -363,8 +363,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
return doc;
})(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true));
newCollection.system = undefined;
- newCollection.isBackground = isBackground;
- newCollection.backgroundColor = this.props.isAnnotationOverlay ? "#00000015" : isBackground ? "cyan" : undefined;
+ newCollection._isBackground = _isBackground;
+ newCollection.backgroundColor = this.props.isAnnotationOverlay ? "#00000015" : _isBackground ? "cyan" : undefined;
newCollection._width = this.Bounds.width;
newCollection._height = this.Bounds.height;
newCollection.x = this.Bounds.left;
@@ -400,7 +400,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
Doc.AddDocToList(curPres, "data", pinDoc);
if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
if (!DocumentManager.Instance.getDocumentView(curPres)) {
- CollectionDockingView.AddRightSplit(curPres);
+ CollectionDockingView.AddSplit(curPres, "right");
}
if (e instanceof KeyboardEvent ? e.key === "c" : true) {
const x = this.Bounds.left + this.Bounds.width / 2;
@@ -682,7 +682,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
marqueeSelect(selectBackgrounds: boolean = true) {
const selRect = this.Bounds;
const selection: Doc[] = [];
- this.props.activeDocuments().filter(doc => !doc.isBackground && !doc.z).map(doc => {
+ this.props.activeDocuments().filter(doc => !doc._isBackground && !doc.z).map(doc => {
const layoutDoc = Doc.Layout(doc);
const x = NumCast(doc.x);
const y = NumCast(doc.y);
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
deleted file mode 100644
index 254afeb0a..000000000
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ /dev/null
@@ -1,779 +0,0 @@
-.propertiesView {
-
- background-color: rgb(205, 205, 205);
- height: 100%;
- font-family: "Noto Sans";
- cursor: auto;
-
- overflow-x: hidden;
- overflow-y: scroll;
-
- .propertiesView-title {
- background-color: rgb(159, 159, 159);
- text-align: center;
- padding-top: 12px;
- padding-bottom: 12px;
- display: flex;
- font-size: 18px;
- font-weight: bold;
- justify-content: center;
-
- .propertiesView-title-icon {
- width: 20px;
- height: 20px;
- padding-left: 38px;
- margin-top: -5px;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 10px;
-
- &:hover {
- color: grey;
- cursor: pointer;
- }
-
- }
-
- }
-
- .propertiesView-name {
- border-bottom: 1px solid black;
- padding: 8.5px;
- font-size: 12.5px;
-
- &:hover {
- cursor: text;
- }
- }
-
- .propertiesView-settings {
- border-bottom: 1px solid black;
- //padding: 8.5px;
- font-size: 12.5px;
- font-weight: bold;
-
- .propertiesView-settings-title {
- font-weight: bold;
- font-size: 12.5px;
- padding: 4px;
- display: flex;
- color: white;
- padding-left: 8px;
- background-color: rgb(51, 51, 51);
-
- &:hover {
- cursor: pointer;
- }
-
- .propertiesView-settings-title-icon {
- float: right;
- justify-items: right;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 9px;
-
- &:hover {
- cursor: pointer;
- }
- }
- }
-
- .propertiesView-settings-content {
- margin-left: 12px;
- padding-bottom: 10px;
- padding-top: 8px;
- }
-
- }
-
- .propertiesView-sharing {
- border-bottom: 1px solid black;
- //padding: 8.5px;
-
- .propertiesView-sharing-title {
- font-weight: bold;
- font-size: 12.5px;
- padding: 4px;
- display: flex;
- color: white;
- padding-left: 8px;
- background-color: rgb(51, 51, 51);
-
- &:hover {
- cursor: pointer;
- }
-
- .propertiesView-sharing-title-icon {
- float: right;
- justify-items: right;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 9px;
-
- &:hover {
- cursor: pointer;
- }
- }
- }
-
- .propertiesView-sharing-content {
- font-size: 10px;
- padding: 10px;
- margin-left: 5px;
-
- .propertiesView-acls-checkbox {
- float: right;
- height: 20px;
- margin-top: -20px;
- margin-right: -15;
-
- .propertiesView-acls-checkbox-text {
- font-size: 7px;
- margin-top: -10px;
- margin-left: 6px;
- }
- }
-
- .change-buttons {
- display: flex;
-
- button {
- width: 5;
- height: 5;
- }
-
- input {
- width: 100%;
- }
- }
- }
- }
-
- .propertiesView-appearance {
- border-bottom: 1px solid black;
- //padding: 8.5px;
-
- .propertiesView-appearance-title {
- font-weight: bold;
- font-size: 12.5px;
- padding: 4px;
- display: flex;
- color: white;
- padding-left: 8px;
- background-color: rgb(51, 51, 51);
-
- &:hover {
- cursor: pointer;
- }
-
- .propertiesView-appearance-title-icon {
- float: right;
- justify-items: right;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 9px;
-
- &:hover {
- cursor: pointer;
- }
- }
- }
-
- .propertiesView-appearance-content {
- font-size: 10px;
- padding: 10px;
- margin-left: 5px;
- }
- }
-
- .propertiesView-transform {
- border-bottom: 1px solid black;
- //padding: 8.5px;
-
- .propertiesView-transform-title {
- font-weight: bold;
- font-size: 12.5px;
- padding: 4px;
- display: flex;
- color: white;
- padding-left: 8px;
- background-color: rgb(51, 51, 51);
-
- &:hover {
- cursor: pointer;
- }
-
- .propertiesView-transform-title-icon {
- float: right;
- justify-items: right;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 9px;
-
- &:hover {
- cursor: pointer;
- }
- }
- }
-
- .propertiesView-transform-content {
- font-size: 10px;
- padding: 10px;
- margin-left: 5px;
- }
- }
-
- .notify-button {
- padding: 2px;
- width: 12px;
- height: 12px;
- background-color: black;
- border-radius: 10px;
- padding-left: 2px;
- padding-right: 2px;
- margin-top: 2px;
- margin-left: 3px;
-
- .notify-button-icon {
- width: 6px;
- height: 6.5px;
- margin-left: .5px;
- }
-
- &:hover {
- background-color: rgb(158, 158, 158);
- cursor: pointer;
- }
- }
-
- .expansion-button-icon {
- width: 11px;
- height: 11px;
- color: black;
- margin-left: 27px;
-
- &:hover {
- color: rgb(131, 131, 131);
- cursor: pointer;
- }
- }
-
- .propertiesView-sharingTable {
-
- // whatever's commented out - add it back in when adding the buttons
-
- // border: 1.5px solid black;
- border: 1px solid black;
- padding: 5px; // remove when adding buttons
- border-radius: 6px; // remove when adding buttons
- margin-right: 10px; // remove when adding buttons
- // width: 100%;
- // display: inline-table;
- background-color: #ececec;
- max-height: 130px;
- overflow-y: scroll;
- width: 92%;
-
- .propertiesView-sharingTable-item {
-
- display: flex;
- // padding: 5px;
- padding: 3px;
- align-items: center;
- border-bottom: 0.5px solid grey;
-
- &:hover .propertiesView-sharingTable-item-name {
- overflow-x: unset;
- white-space: unset;
- overflow-wrap: break-word;
- }
-
- .propertiesView-sharingTable-item-name {
- font-weight: bold;
- width: 95px;
- overflow-x: hidden;
- display: inline-block;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- .propertiesView-sharingTable-item-permission {
- display: flex;
- align-items: flex-end;
- margin-left: auto;
-
- .permissions-select {
- border: none;
- background-color: inherit;
- width: 75px;
- //text-align: justify; // for Edge
- //text-align-last: end;
-
- &:hover {
- cursor: pointer;
- }
- }
- }
-
- &:last-child {
- border-bottom: none;
- }
- }
- }
-
- .propertiesView-fields {
- border-bottom: 1px solid black;
- //padding: 8.5px;
-
- .propertiesView-fields-title {
- font-weight: bold;
- font-size: 12.5px;
- padding: 4px;
- display: flex;
- color: white;
- padding-left: 8px;
- background-color: rgb(51, 51, 51);
-
- &:hover {
- cursor: pointer;
- }
-
- .propertiesView-fields-title-icon {
- float: right;
- justify-items: right;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 9px;
-
- &:hover {
- cursor: pointer;
- }
- }
-
- }
-
- .propertiesView-fields-checkbox {
- float: right;
- height: 20px;
- margin-top: -9px;
-
- .propertiesView-fields-checkbox-text {
- font-size: 7px;
- margin-top: -10px;
- margin-left: 6px;
- }
- }
-
- .propertiesView-fields-content {
- font-size: 10px;
- margin-left: 2px;
- padding: 10px;
-
- &:hover {
- cursor: pointer;
- }
- }
- }
-
- .field {
- display: flex;
- font-size: 7px;
- background-color: #e8e8e8;
- padding-right: 3px;
- border: 0.5px solid grey;
- border-radius: 5px;
- padding-left: 3px;
- }
-
- .uneditable-field {
- display: flex;
- overflow-y: visible;
- margin-bottom: 2px;
-
- &:hover {
- cursor: auto;
- }
- }
- .propertiesView-contexts {
-
- .propertiesView-contexts-title {
- font-weight: bold;
- font-size: 12.5px;
- padding: 4px;
- display: flex;
- color: white;
- padding-left: 8px;
- background-color: rgb(51, 51, 51);
-
- &:hover {
- cursor: pointer;
- }
-
- .propertiesView-contexts-title-icon {
- float: right;
- justify-items: right;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 9px;
-
- &:hover {
- cursor: pointer;
- }
- }
- }
-
- .propertiesView-contexts-content {
- overflow: hidden;
- padding: 10px;
- }
-
- }
-
- .propertiesView-layout {
-
- .propertiesView-layout-title {
- font-weight: bold;
- font-size: 12.5px;
- padding: 4px;
- display: flex;
- color: white;
- padding-left: 8px;
- background-color: rgb(51, 51, 51);
-
- &:hover {
- cursor: pointer;
- }
-
- .propertiesView-layout-title-icon {
- float: right;
- justify-items: right;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 9px;
-
- &:hover {
- cursor: pointer;
- }
- }
- }
-
- .propertiesView-layout-content {
- overflow: hidden;
- padding: 10px;
- }
-
- }
-
- .propertiesView-presTrails {
- border-bottom: 1px solid black;
- //padding: 8.5px;
-
- .propertiesView-presTrails-title {
- font-weight: bold;
- font-size: 12.5px;
- padding: 4px;
- display: flex;
- color: white;
- padding-left: 8px;
- background-color: rgb(51, 51, 51);
-
- &:hover {
- cursor: pointer;
- }
-
- .propertiesView-presTrails-title-icon {
- float: right;
- justify-items: right;
- align-items: flex-end;
- margin-left: auto;
- margin-right: 9px;
-
- &:hover {
- cursor: pointer;
- }
- }
- }
-
- .propertiesView-presTrails-content {
- font-size: 10px;
- padding: 10px;
- margin-left: 5px;
- }
- }
-}
-
-.inking-button {
-
- display: flex;
-
- .inking-button-points {
- background-color: #333333;
- padding: 7px;
- border-radius: 7px;
- margin-right: 32px;
- width: 32;
- height: 32;
- padding-top: 9px;
- margin-left: 18px;
-
- &:hover {
- background: rgb(131, 131, 131);
- transform: scale(1.05);
- cursor: pointer;
- }
- }
-
- .inking-button-lock {
- background-color: #333333;
- padding: 7px;
- border-radius: 7px;
- margin-right: 32px;
- width: 32;
- height: 32;
- padding-top: 9px;
- padding-left: 10px;
-
- &:hover {
- background: rgb(131, 131, 131);
- transform: scale(1.05);
- cursor: pointer;
- }
- }
-
- .inking-button-rotate {
- background-color: #333333;
- padding: 7px;
- border-radius: 7px;
- width: 32;
- height: 32;
- padding-top: 9px;
- padding-left: 10px;
-
- &:hover {
- background: rgb(131, 131, 131);
- transform: scale(1.05);
- cursor: pointer;
- }
- }
-}
-
-.inputBox-duo {
- display: flex;
-}
-
-.inputBox {
-
- margin-top: 10px;
- display: flex;
- height: 19px;
- margin-right: 15px;
-
- .inputBox-title {
- font-size: 12px;
- padding-right: 5px;
- }
-
- .inputBox-input {
- font-size: 10px;
- width: 50px;
- margin-right: 1px;
- border-radius: 3px;
-
- &:hover {
- cursor: pointer;
- }
- }
-
- .inputBox-button {
-
- .inputBox-button-up {
- background-color: #333333;
- height: 9px;
- padding-left: 3px;
- padding-right: 3px;
- padding-top: 1px;
- padding-bottom: 1px;
- border-radius: 1.5px;
-
- &:hover {
- background: rgb(131, 131, 131);
- transform: scale(1.05);
- cursor: pointer;
- }
- }
-
- .inputBox-button-down {
- background-color: #333333;
- height: 9px;
- padding-left: 3px;
- padding-right: 3px;
- padding-top: 1px;
- padding-bottom: 1px;
- border-radius: 1.5px;
-
- &:hover {
- background: rgb(131, 131, 131);
- transform: scale(1.05);
- cursor: pointer;
- }
- }
-
- }
-}
-
-.color-palette {
- width: 160px;
- height: 360;
-}
-
-.strokeAndFill {
- display: flex;
- margin-top: 10px;
-
- .fill {
- margin-right: 40px;
- display: flex;
- padding-bottom: 7px;
- margin-left: 35px;
-
- .fill-title {
- font-size: 12px;
- margin-right: 2px;
- }
-
- .fill-button {
- padding-top: 2px;
- margin-top: -1px;
- }
- }
-
- .stroke {
- display: flex;
-
- .stroke-title {
- font-size: 12px;
- }
-
- .stroke-button {
- padding-top: 2px;
- margin-left: 2px;
- margin-top: -1px;
- }
- }
-}
-
-.propertiesView-presSelected {
- border-top: solid 1px darkgrey;
- width: 100%;
- padding-top: 5px;
- font-family: Roboto;
- font-weight: 500;
- display: inline-flex;
-
- .propertiesView-selectedList {
- border-left: solid 1px darkgrey;
- margin-left: 10px;
- padding-left: 5px;
-
- .selectedList-items {
- font-size: 12;
- font-weight: 300;
- margin-top: 1;
- }
- }
-}
-
-.widthAndDash {
-
- .width {
- .width-top {
- display: flex;
-
- .width-title {
- font-size: 12;
- margin-right: 20px;
- margin-left: 35px;
- text-align: center;
- }
-
- .width-input {
- margin-right: 30px;
- margin-top: -10px;
- }
- }
-
- .width-range {
- margin-right: 1px;
- margin-bottom: 6;
- }
- }
-
- .arrows {
-
- display: flex;
- margin-bottom: 3px;
- margin-left: 4px;
-
- .arrows-head {
-
- display: flex;
- margin-right: 35px;
-
- .arrows-head-title {
- font-size: 10;
- }
-
- .arrows-head-input {
- margin-left: 6px;
- margin-top: 2px;
- }
- }
-
- .arrows-tail {
- display: flex;
-
- .arrows-tail-title {
- font-size: 10;
- }
-
- .arrows-tail-input {
- margin-left: 6px;
- margin-top: 2px;
- }
- }
- }
-
- .dashed {
-
- display: flex;
- margin-left: 64px;
- margin-bottom: 6px;
-
- .dashed-title {
- font-size: 10;
- }
-
- .dashed-input {
- margin-left: 6px;
- margin-top: 2px;
- }
- }
-}
-
-.editable-title {
- border: none;
- padding: 6px;
- padding-bottom: 2px;
- background: #eeeeee;
- border-top: 1px solid;
- border-left: 1px solid;
-
- &:hover {
- border: 0.75px solid rgb(122, 28, 28);
- }
-}
-
-
-.properties-flyout {
- grid-column: 2/4;
-} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
deleted file mode 100644
index 4d9445caa..000000000
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ /dev/null
@@ -1,1106 +0,0 @@
-import React = require("react");
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Checkbox, Tooltip } from "@material-ui/core";
-import { action, computed, observable } from "mobx";
-import { observer } from "mobx-react";
-import { ColorState, SketchPicker } from "react-color";
-import { AclAddonly, AclAdmin, AclEdit, AclPrivate, AclReadonly, AclSym, DataSym, Doc, Field, HeightSym, WidthSym } from "../../../../fields/Doc";
-import { Id } from "../../../../fields/FieldSymbols";
-import { InkField } from "../../../../fields/InkField";
-import { ComputedField } from "../../../../fields/ScriptField";
-import { Cast, NumCast, StrCast } from "../../../../fields/Types";
-import { GetEffectiveAcl, SharingPermissions } from "../../../../fields/util";
-import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../../Utils";
-import { DocumentType } from "../../../documents/DocumentTypes";
-import { DocumentManager } from "../../../util/DocumentManager";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { SharingManager } from "../../../util/SharingManager";
-import { Transform } from "../../../util/Transform";
-import { undoBatch, UndoManager } from "../../../util/UndoManager";
-import { EditableView } from "../../EditableView";
-import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView";
-import { KeyValueBox } from "../../nodes/KeyValueBox";
-import { PresBox } from "../../nodes/PresBox";
-import { PropertiesButtons } from "../../PropertiesButtons";
-import { FormatShapePane } from "./FormatShapePane";
-import "./FormatShapePane.scss";
-import "./PropertiesView.scss";
-import { CollectionDockingView } from "../CollectionDockingView";
-import { ParentDocSelector, SelectorContextMenu } from "../ParentDocumentSelector";
-import { intersection } from "lodash";
-const higflyout = require("@hig/flyout");
-export const { anchorPoints } = higflyout;
-export const Flyout = higflyout.default;
-const _global = (window /* browser */ || global /* node */) as any;
-
-interface PropertiesViewProps {
- width: number;
- height: number;
- renderDepth: number;
- ScreenToLocalTransform: () => Transform;
- onDown: (event: any) => void;
-}
-
-@observer
-export class PropertiesView extends React.Component<PropertiesViewProps> {
- private _widthUndo?: UndoManager.Batch;
-
- @computed get MAX_EMBED_HEIGHT() { return 200; }
-
- @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; }
- @computed get selectedDocumentView() {
- if (SelectionManager.SelectedDocuments().length) {
- return SelectionManager.SelectedDocuments()[0];
- } else if (PresBox.Instance && PresBox.Instance._selectedArray.length) {
- return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc);
- } else { return undefined; }
- }
- @computed get isPres(): boolean {
- if (this.selectedDoc?.type === DocumentType.PRES) return true;
- return false;
- }
- @computed get dataDoc() { return this.selectedDoc?.[DataSym]; }
-
- @observable layoutFields: boolean = false;
-
- @observable openOptions: boolean = true;
- @observable openSharing: boolean = true;
- @observable openFields: boolean = true;
- @observable openLayout: boolean = true;
- @observable openContexts: boolean = true;
- @observable openAppearance: boolean = true;
- @observable openTransform: boolean = true;
- // @observable selectedUser: string = "";
- // @observable addButtonPressed: boolean = false;
- @observable layoutDocAcls: boolean = false;
-
- //Pres Trails booleans:
- @observable openPresTransitions: boolean = false;
- @observable openPresProgressivize: boolean = false;
- @observable openAddSlide: boolean = false;
- @observable openSlideOptions: boolean = false;
-
- @observable inOptions: boolean = false;
- @observable _controlBtn: boolean = false;
- @observable _lock: boolean = false;
-
- @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; }
-
- @action
- rtfWidth = () => {
- if (this.selectedDoc) {
- return Math.min(this.selectedDoc?.[WidthSym](), this.props.width - 20);
- } else {
- return 0;
- }
- }
- @action
- rtfHeight = () => {
- if (this.selectedDoc) {
- return this.rtfWidth() <= this.selectedDoc?.[WidthSym]() ? Math.min(this.selectedDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
- } else {
- return 0;
- }
- }
-
- @action
- docWidth = () => {
- if (this.selectedDoc) {
- const layoutDoc = this.selectedDoc;
- const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
- if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.width - 20));
- return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20;
- } else {
- return 0;
- }
- }
-
- @action
- docHeight = () => {
- if (this.selectedDoc && this.dataDoc) {
- const layoutDoc = this.selectedDoc;
- return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => {
- const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
- if (aspect) return this.docWidth() * aspect;
- return layoutDoc._fitWidth ? (!this.dataDoc._nativeHeight ? NumCast(this.props.height) :
- Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth,
- NumCast(this.props.height)))) :
- NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50;
- })()));
- } else {
- return 0;
- }
- }
-
- @computed get expandedField() {
- if (this.dataDoc && this.selectedDoc) {
- const ids: { [key: string]: string } = {};
- const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] :
- SelectionManager.SelectedDocuments().map(dv => this.layoutFields ? Doc.Layout(dv.layoutDoc) : dv.dataDoc);
- docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)));
- const rows: JSX.Element[] = [];
- for (const key of Object.keys(ids).slice().sort()) {
- const docvals = new Set<any>();
- docs.forEach(doc => docvals.add(doc[key]));
- const contents = Array.from(docvals.keys()).length > 1 ? "-multiple" : docs[0][key];
- if (key[0] === "#") {
- rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "2px" }} key={key}>
- <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span>
- &nbsp;
- </div>);
- } else {
- let contentElement = <EditableView key="editableView"
- contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
- height={13}
- fontSize={10}
- GetValue={() => contents !== undefined ? Field.toString(contents as Field) : "null"}
- SetValue={(value: string) => { docs.map(doc => KeyValueBox.SetField(doc, key, value, true)); return true; }}
- />;
- rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
- <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
- &nbsp;
- {contentElement}
- </div>);
- }
- }
- rows.push(<div className="field" key={"newKeyValue"} style={{ marginTop: "3px" }}>
- <EditableView
- key="editableView"
- contents={"add key:value or #tags"}
- height={13}
- fontSize={10}
- GetValue={() => ""}
- SetValue={this.setKeyValue} />
- </div>);
- return rows;
- }
- }
-
- @computed get noviceFields() {
- if (this.dataDoc) {
- const ids: { [key: string]: string } = {};
- const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.dataDoc] : SelectionManager.SelectedDocuments().map(dv => dv.dataDoc);
- docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)));
- const rows: JSX.Element[] = [];
- const noviceReqFields = ["author", "creationDate"];
- const noviceLayoutFields = ["_curPage"];
- const noviceKeys = [...Array.from(Object.keys(ids)).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("ACL") && key !== "UseCors")),
- ...noviceReqFields, ...noviceLayoutFields];
- for (const key of noviceKeys.sort()) {
- const docvals = new Set<any>();
- docs.forEach(doc => docvals.add(doc[key]));
- const contents = Array.from(docvals.keys()).length > 1 ? "-multiple" : docs[0][key];
- if (key[0] === "#") {
- rows.push(<div className="uneditable-field" key={key}>
- <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span>
- &nbsp;
- </div>);
- } else if (contents !== undefined) {
- const value = Field.toString(contents as Field);
- if (noviceReqFields.includes(key) || key.indexOf("lastModified") !== -1) {
- rows.push(<div className="uneditable-field" key={key}>
- <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ": "}</span>
- <div style={{ whiteSpace: "nowrap", overflowX: "hidden" }}>{value}</div>
- </div>);
- } else {
- const contentElement = <EditableView key="editableView"
- contents={value}
- height={13}
- fontSize={10}
- GetValue={() => contents !== undefined ? Field.toString(contents as Field) : "null"}
- SetValue={(value: string) => { docs.map(doc => KeyValueBox.SetField(doc, key, value, true)); return true; }}
- />;
-
- rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
- <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
- &nbsp;
- {contentElement}
- </div>);
- }
- }
- }
- rows.push(<div className="field" key={"newKeyValue"} style={{ marginTop: "3px" }}>
- <EditableView
- key="editableView"
- contents={"add key:value or #tags"}
- height={13}
- fontSize={10}
- GetValue={() => ""}
- SetValue={this.setKeyValue} />
- </div>);
- return rows;
- }
- }
-
- @undoBatch
- setKeyValue = (value: string) => {
- const docs = SelectionManager.SelectedDocuments().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.SelectedDocuments().map(dv => this.layoutFields ? dv.layoutDoc : dv.dataDoc);
- docs.forEach(doc => {
- if (value.indexOf(":") !== -1) {
- const newVal = value[0].toUpperCase() + value.substring(1, value.length);
- KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true);
- return true;
- } else if (value[0] === "#") {
- const newVal = value + `:'${value}'`;
- KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true);
- return true;
- }
- });
- return false;
- }
-
- @observable transform: Transform = Transform.Identity();
- getTransform = () => this.transform;
- propertiesDocViewRef = (ref: HTMLDivElement) => {
- const observer = new _global.ResizeObserver(action((entries: any) => {
- const cliRect = ref.getBoundingClientRect();
- this.transform = new Transform(-cliRect.x, -cliRect.y, 1);
- }));
- ref && observer.observe(ref);
- }
-
- @computed get contexts() {
- return !this.selectedDoc ? (null) : <SelectorContextMenu Document={this.selectedDoc} hideTitle={true} addDocTab={(doc, where) => CollectionDockingView.AddRightSplit(doc)} />;
- }
-
- previewBackground = () => "lightgrey";
- @computed get layoutPreview() {
- if (SelectionManager.SelectedDocuments().length > 1) {
- return "-- multiple selected --";
- }
- if (this.selectedDoc) {
- const layoutDoc = Doc.Layout(this.selectedDoc);
- const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docHeight;
- const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docWidth;
- return <div ref={this.propertiesDocViewRef} style={{ pointerEvents: "none", display: "inline-block", height: panelHeight() }} key={this.selectedDoc[Id]}>
- <ContentFittingDocumentView
- Document={layoutDoc}
- DataDoc={this.dataDoc}
- LibraryPath={emptyPath}
- renderDepth={this.props.renderDepth + 1}
- rootSelected={returnFalse}
- treeViewDoc={undefined}
- backgroundColor={this.previewBackground}
- fitToBox={true}
- FreezeDimensions={true}
- NativeWidth={layoutDoc.type ===
- StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : returnZero}
- NativeHeight={layoutDoc.type ===
- StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : returnZero}
- PanelWidth={panelWidth}
- PanelHeight={panelHeight}
- focus={returnFalse}
- ScreenToLocalTransform={this.getTransform}
- docFilters={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- ContainingCollectionDoc={undefined}
- ContainingCollectionView={undefined}
- addDocument={returnFalse}
- moveDocument={undefined}
- removeDocument={returnFalse}
- parentActive={() => false}
- whenActiveChanged={emptyFunction}
- addDocTab={returnFalse}
- pinToPres={emptyFunction}
- bringToFront={returnFalse}
- ContentScaling={returnOne}
- dontRegisterView={true}
- dropAction={undefined}
- />
- </div>;
- } else {
- return null;
- }
- }
-
- /**
- * Handles the changing of a user's permissions from the permissions panel.
- */
- @undoBatch
- changePermissions = (e: any, user: string) => {
- const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.selectedDoc!] : SelectionManager.SelectedDocuments().map(docView => docView.props.Document);
- SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs);
- }
-
- /**
- * @returns the options for the permissions dropdown.
- */
- getPermissionsSelect(user: string, permission: string) {
- const dropdownValues: string[] = Object.values(SharingPermissions);
- if (permission === "-multiple-") dropdownValues.unshift(permission);
- return <select className="permissions-select"
- value={permission}
- onChange={e => this.changePermissions(e, user)}>
- {dropdownValues.map(permission => {
- return (
- <option key={permission} value={permission}>
- {permission}
- </option>);
- })}
- </select>;
- }
-
- /**
- * @returns the notification icon. On clicking, it should notify someone of a document been shared with them.
- */
- @computed get notifyIcon() {
- return <Tooltip title={<div className="dash-tooltip">Notify with message</div>}>
- <div className="notify-button">
- <FontAwesomeIcon className="notify-button-icon" icon="bell" color="white" size="sm" />
- </div>
- </Tooltip>;
- }
-
- /**
- * ... next to the owner that opens the main SharingManager interface on click.
- */
- @computed get expansionIcon() {
- return <Tooltip title={<div className="dash-tooltip">{"Show more permissions"}</div>}>
- <div className="expansion-button" onPointerDown={() => {
- if (this.selectedDocumentView || this.selectedDoc) {
- SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDocumentView ? this.selectedDocumentView : undefined, this.selectedDoc);
- }
- }}>
- <FontAwesomeIcon className="expansion-button-icon" icon="ellipsis-h" color="black" size="sm" />
- </div>
- </Tooltip>;
- }
-
- /**
- * @returns a row of the permissions panel
- */
- sharingItem(name: string, admin: boolean, permission: string) {
- return <div className="propertiesView-sharingTable-item" key={name + permission}
- // style={{ backgroundColor: this.selectedUser === name ? "#bcecfc" : "" }}
- // onPointerDown={action(() => this.selectedUser = this.selectedUser === name ? "" : name)}
- >
- <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "85px" : "80px" }}> {name} </div>
- {/* {name !== "Me" ? this.notifyIcon : null} */}
- <div className="propertiesView-sharingTable-item-permission">
- {admin && permission !== "Owner" ? this.getPermissionsSelect(name, permission) : permission}
- {permission === "Owner" ? this.expansionIcon : null}
- </div>
- </div>;
- }
-
- /**
- * @returns the sharing and permissiosn panel.
- */
- @computed get sharingTable() {
- const AclMap = new Map<symbol, string>([
- [AclPrivate, SharingPermissions.None],
- [AclReadonly, SharingPermissions.View],
- [AclAddonly, SharingPermissions.Add],
- [AclEdit, SharingPermissions.Edit],
- [AclAdmin, SharingPermissions.Admin]
- ]);
-
- // all selected docs
- const docs = SelectionManager.SelectedDocuments().length < 2 ?
- [this.layoutDocAcls ? this.selectedDoc! : this.selectedDoc![DataSym]]
- : SelectionManager.SelectedDocuments().map(docView => this.layoutDocAcls ? docView.props.Document : docView.props.Document[DataSym]);
-
- const target = docs[0];
-
- // tslint:disable-next-line: no-unnecessary-callback-wrapper
- const effectiveAcls = docs.map(doc => GetEffectiveAcl(doc));
- const showAdmin = effectiveAcls.every(acl => acl === AclAdmin);
-
- // users in common between all docs
- const commonKeys = intersection(...docs.map(doc => this.layoutDocAcls ? doc?.[AclSym] && Object.keys(doc[AclSym]) : doc?.[DataSym][AclSym] && Object.keys(doc[DataSym][AclSym])));
-
- const tableEntries = [];
-
- // DocCastAsync(Doc.UserDoc().sidebarUsersDisplayed).then(sidebarUsersDisplayed => {
- if (commonKeys.length) {
- for (const key of commonKeys) {
- const name = key.substring(4).replace("_", ".");
- const uniform = docs.every(doc => this.layoutDocAcls ? doc?.[AclSym]?.[key] === docs[0]?.[AclSym]?.[key] : doc?.[DataSym]?.[AclSym]?.[key] === docs[0]?.[DataSym]?.[AclSym]?.[key]);
- if (name !== Doc.CurrentUserEmail && name !== target.author && name !== "Public"/* && sidebarUsersDisplayed![name] !== false*/) {
- tableEntries.push(this.sharingItem(name, showAdmin, uniform ? AclMap.get(this.layoutDocAcls ? target[AclSym][key] : target[DataSym][AclSym][key])! : "-multiple-"));
- }
- }
- }
-
- // if (Doc.UserDoc().sidebarUsersDisplayed) {
- // for (const [name, value] of Object.entries(sidebarUsersDisplayed!)) {
- // if (value === true && !this.selectedDoc![`ACL-${name.substring(8).replace(".", "_")}`]) tableEntries.push(this.sharingItem(name.substring(8), effectiveAcl, SharingPermissions.None));
- // }
- // }
- // })
-
- // shifts the current user, owner, public to the top of the doc.
- tableEntries.unshift(this.sharingItem("Public", showAdmin, docs.every(doc => doc["ACL-Public"] === docs[0]["ACL-Public"]) ? (AclMap.get(target[AclSym]?.["ACL-Public"]) || SharingPermissions.None) : "-multiple-"));
- tableEntries.unshift(this.sharingItem("Me", showAdmin, docs.every(doc => doc.author === Doc.CurrentUserEmail) ? "Owner" : effectiveAcls.every(acl => acl === effectiveAcls[0]) ? AclMap.get(effectiveAcls[0])! : "-multiple-"));
- if (Doc.CurrentUserEmail !== target.author && docs.every(doc => doc.author === docs[0].author)) tableEntries.unshift(this.sharingItem(StrCast(target.author), showAdmin, "Owner"));
-
- return <div className="propertiesView-sharingTable">
- {tableEntries}
- </div>;
- }
-
- @computed get fieldsCheckbox() {
- return <Checkbox
- color="primary"
- onChange={this.toggleCheckbox}
- checked={this.layoutFields}
- />;
- }
-
- @action
- toggleCheckbox = () => {
- this.layoutFields = !this.layoutFields;
- }
-
- @computed get editableTitle() {
- const titles = new Set<string>();
- SelectionManager.SelectedDocuments().forEach(dv => titles.add(StrCast(dv.rootDoc.title)));
- const title = Array.from(titles.keys()).length > 1 ? "--multiple selected--" : StrCast(this.selectedDoc?.title);
- return <div className="editable-title"><EditableView
- key="editableView"
- contents={title}
- height={25}
- fontSize={14}
- GetValue={() => title}
- SetValue={this.setTitle} /> </div>;
- }
-
- @undoBatch
- @action
- setTitle = (value: string) => {
- if (SelectionManager.SelectedDocuments().length > 1) {
- SelectionManager.SelectedDocuments().map(dv => Doc.SetInPlace(dv.rootDoc, "title", value, true));
- return true;
- } else if (this.dataDoc) {
- if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, "title", value, true);
- else KeyValueBox.SetField(this.dataDoc, "title", value, true);
- return true;
- }
- return false;
- }
-
-
- @undoBatch
- @action
- rotate = (angle: number) => {
- const _centerPoints: { X: number, Y: number }[] = [];
- if (this.selectedDoc) {
- const doc = this.selectedDoc;
- if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
- const xs = ink.map(p => p.X);
- const ys = ink.map(p => p.Y);
- const left = Math.min(...xs);
- const top = Math.min(...ys);
- const right = Math.max(...xs);
- const bottom = Math.max(...ys);
- _centerPoints.push({ X: left, Y: top });
- }
- }
-
- var index = 0;
- if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
- doc.rotation = Number(doc.rotation) + Number(angle);
- const inks = Cast(doc.data, InkField)?.inkData;
- if (inks) {
- const newPoints: { X: number, Y: number }[] = [];
- inks.forEach(ink => {
- const newX = Math.cos(angle) * (ink.X - _centerPoints[index].X) - Math.sin(angle) * (ink.Y - _centerPoints[index].Y) + _centerPoints[index].X;
- const newY = Math.sin(angle) * (ink.X - _centerPoints[index].X) + Math.cos(angle) * (ink.Y - _centerPoints[index].Y) + _centerPoints[index].Y;
- newPoints.push({ X: newX, Y: newY });
- });
- doc.data = new InkField(newPoints);
- const xs = newPoints.map(p => p.X);
- const ys = newPoints.map(p => p.Y);
- const left = Math.min(...xs);
- const top = Math.min(...ys);
- const right = Math.max(...xs);
- const bottom = Math.max(...ys);
-
- doc._height = (bottom - top);
- doc._width = (right - left);
- }
- index++;
- }
- }
- }
-
-
-
- @computed
- get controlPointsButton() {
- return <div className="inking-button">
- <Tooltip title={<div className="dash-tooltip">{"Edit points"}</div>}>
- <div className="inking-button-points" onPointerDown={action(() => FormatShapePane.Instance._controlBtn = !FormatShapePane.Instance._controlBtn)} style={{ backgroundColor: FormatShapePane.Instance._controlBtn ? "black" : "" }}>
- <FontAwesomeIcon icon="bezier-curve" color="white" size="lg" />
- </div>
- </Tooltip>
- <Tooltip title={<div className="dash-tooltip">{FormatShapePane.Instance._lock ? "Unlock ratio" : "Lock ratio"}</div>}>
- <div className="inking-button-lock" onPointerDown={action(() => FormatShapePane.Instance._lock = !FormatShapePane.Instance._lock)} >
- <FontAwesomeIcon icon={FormatShapePane.Instance._lock ? "lock" : "unlock"} color="white" size="lg" />
- </div>
- </Tooltip>
- <Tooltip title={<div className="dash-tooltip">{"Rotate 90˚"}</div>}>
- <div className="inking-button-rotate" onPointerDown={action(() => this.rotate(Math.PI / 2))}>
- <FontAwesomeIcon icon="undo" color="white" size="lg" />
- </div>
- </Tooltip>
- </div>;
- }
-
- inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => {
- return <div className="inputBox"
- style={{
- marginRight: title === "X:" ? "19px" : "",
- marginLeft: title === "∠:" ? "39px" : ""
- }}>
- <div className="inputBox-title"> {title} </div>
- <input className="inputBox-input"
- type="text" value={value}
- onChange={e => {
- setter(e.target.value);
- }}
- onKeyPress={e => {
- e.stopPropagation();
- }} />
- <div className="inputBox-button">
- <div className="inputBox-button-up" key="up2"
- onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))} >
- <FontAwesomeIcon icon="caret-up" color="white" size="sm" />
- </div>
- <div className="inputbox-Button-down" key="down2"
- onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} >
- <FontAwesomeIcon icon="caret-down" color="white" size="sm" />
- </div>
- </div>
- </div>;
- }
-
- inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => {
- return <div className="inputBox-duo">
- {this.inputBox(key, value, setter, title1)}
- {title2 === "" ? (null) : this.inputBox(key2, value2, setter2, title2)}
- </div>;
- }
-
- @action
- upDownButtons = (dirs: string, field: string) => {
- switch (field) {
- case "rot": this.rotate((dirs === "up" ? .1 : -.1)); break;
- // case "rot": this.selectedInk?.forEach(i => i.rootDoc.rotation = NumCast(i.rootDoc.rotation) + (dirs === "up" ? 0.1 : -0.1)); break;
- case "Xps": this.selectedDoc && (this.selectedDoc.x = NumCast(this.selectedDoc?.x) + (dirs === "up" ? 10 : -10)); break;
- case "Yps": this.selectedDoc && (this.selectedDoc.y = NumCast(this.selectedDoc?.y) + (dirs === "up" ? 10 : -10)); break;
- case "stk": this.selectedDoc && (this.selectedDoc.strokeWidth = NumCast(this.selectedDoc?.strokeWidth) + (dirs === "up" ? .1 : -.1)); break;
- case "wid":
- const oldWidth = NumCast(this.selectedDoc?._width);
- const oldHeight = NumCast(this.selectedDoc?._height);
- const oldX = NumCast(this.selectedDoc?.x);
- const oldY = NumCast(this.selectedDoc?.y);
- this.selectedDoc && (this.selectedDoc._width = oldWidth + (dirs === "up" ? 10 : - 10));
- FormatShapePane.Instance._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) / oldWidth * NumCast(this.selectedDoc?._height)));
- const doc = this.selectedDoc;
- if (doc?.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
- const newPoints: { X: number, Y: number }[] = [];
- for (var j = 0; j < ink.length; j++) {
- // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
- const newX = (NumCast(doc.x) - oldX) + (ink[j].X * NumCast(doc._width)) / oldWidth;
- const newY = (NumCast(doc.y) - oldY) + (ink[j].Y * NumCast(doc._height)) / oldHeight;
- newPoints.push({ X: newX, Y: newY });
- }
- doc.data = new InkField(newPoints);
- }
- }
- break;
- case "hgt":
- const oWidth = NumCast(this.selectedDoc?._width);
- const oHeight = NumCast(this.selectedDoc?._height);
- const oX = NumCast(this.selectedDoc?.x);
- const oY = NumCast(this.selectedDoc?.y);
- this.selectedDoc && (this.selectedDoc._height = oHeight + (dirs === "up" ? 10 : - 10));
- FormatShapePane.Instance._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) / oHeight * NumCast(this.selectedDoc?._width)));
- const docu = this.selectedDoc;
- if (docu?.type === DocumentType.INK && docu.x && docu.y && docu._height && docu._width) {
- const ink = Cast(docu.data, InkField)?.inkData;
- if (ink) {
- const newPoints: { X: number, Y: number }[] = [];
- for (var j = 0; j < ink.length; j++) {
- // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
- const newX = (NumCast(docu.x) - oX) + (ink[j].X * NumCast(docu._width)) / oWidth;
- const newY = (NumCast(docu.y) - oY) + (ink[j].Y * NumCast(docu._height)) / oHeight;
- newPoints.push({ X: newX, Y: newY });
- }
- docu.data = new InkField(newPoints);
- }
- }
- break;
- }
- }
-
- getField(key: string) {
- //if (this.selectedDoc) {
- return Field.toString(this.selectedDoc?.[key] as Field);
- // } else {
- // return undefined as Opt<string>;
- // }
- }
-
- @computed get shapeXps() { return this.getField("x"); }
- @computed get shapeYps() { return this.getField("y"); }
- @computed get shapeRot() { return this.getField("rotation"); }
- @computed get shapeHgt() { return this.getField("_height"); }
- @computed get shapeWid() { return this.getField("_width"); }
- set shapeXps(value) { this.selectedDoc && (this.selectedDoc.x = Number(value)); }
- set shapeYps(value) { this.selectedDoc && (this.selectedDoc.y = Number(value)); }
- set shapeRot(value) { this.selectedDoc && (this.selectedDoc.rotation = Number(value)); }
- set shapeWid(value) {
- const oldWidth = NumCast(this.selectedDoc?._width);
- this.selectedDoc && (this.selectedDoc._width = Number(value));
- FormatShapePane.Instance._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) * NumCast(this.selectedDoc?._height)) / oldWidth);
- }
- set shapeHgt(value) {
- const oldHeight = NumCast(this.selectedDoc?._height);
- this.selectedDoc && (this.selectedDoc._height = Number(value));
- FormatShapePane.Instance._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) * NumCast(this.selectedDoc?._width)) / oldHeight);
- }
-
- @computed get hgtInput() { return this.inputBoxDuo("hgt", this.shapeHgt, (val: string) => { if (!isNaN(Number(val))) { this.shapeHgt = val; } return true; }, "H:", "wid", this.shapeWid, (val: string) => { if (!isNaN(Number(val))) { this.shapeWid = val; } return true; }, "W:"); }
- @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => { if (val !== "0" && !isNaN(Number(val))) { this.shapeXps = val; } return true; }, "X:", "Yps", this.shapeYps, (val: string) => { if (val !== "0" && !isNaN(Number(val))) { this.shapeYps = val; } return true; }, "Y:"); }
- @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { if (!isNaN(Number(val))) { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; } return true; }, "∠:", "rot", this.shapeRot, (val: string) => { if (!isNaN(Number(val))) { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; } return true; }, ""); }
-
-
- @observable private _fillBtn = false;
- @observable private _lineBtn = false;
-
- private _lastFill = "#D0021B";
- private _lastLine = "#D0021B";
- private _lastDash: any = "2";
-
- @computed get colorFil() { const ccol = this.getField("fillColor") || ""; ccol && (this._lastFill = ccol); return ccol; }
- @computed get colorStk() { const ccol = this.getField("color") || ""; ccol && (this._lastLine = ccol); return ccol; }
- set colorFil(value) { value && (this._lastFill = value); this.selectedDoc && (this.selectedDoc.fillColor = value ? value : undefined); }
- set colorStk(value) { value && (this._lastLine = value); this.selectedDoc && (this.selectedDoc.color = value ? value : undefined); }
-
- colorButton(value: string, type: string, setter: () => {}) {
- // return <div className="properties-flyout" onPointerEnter={e => this.changeScrolling(false)}
- // onPointerLeave={e => this.changeScrolling(true)}>
- // <Flyout anchorPoint={anchorPoints.LEFT_TOP}
- // content={type === "fill" ? this.fillPicker : this.linePicker}>
- return <div className="color-button" key="color" onPointerDown={undoBatch(action(e => setter()))}>
- <div className="color-button-preview" style={{
- backgroundColor: value ?? "121212", width: 15, height: 15,
- display: value === "" || value === "transparent" ? "none" : ""
- }} />
- {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -14 }}>☒</p> : ""}
- </div>;
- // </Flyout>
- // </div>;
-
- }
-
- @undoBatch
- @action
- switchStk = (color: ColorState) => {
- const val = String(color.hex);
- this.colorStk = val;
- return true;
- }
- @undoBatch
- @action
- switchFil = (color: ColorState) => {
- const val = String(color.hex);
- this.colorFil = val;
- return true;
- }
-
- colorPicker(setter: (color: string) => {}, type: string) {
- return <SketchPicker onChange={type === "stk" ? this.switchStk : this.switchFil}
- presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
- '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
- '#FFFFFF', '#f1efeb', 'transparent']}
- color={type === "stk" ? this.colorStk : this.colorFil} />;
- }
-
- @computed get fillButton() { return this.colorButton(this.colorFil, "fill", () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); }
- @computed get lineButton() { return this.colorButton(this.colorStk, "line", () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); }
-
- @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color, "fil"); }
- @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color, "stk"); }
-
- @computed get strokeAndFill() {
- return <div>
- <div key="fill" className="strokeAndFill">
- <div className="fill">
- <div className="fill-title">Fill:</div>
- <div className="fill-button">{this.fillButton}</div>
- </div>
- <div className="stroke">
- <div className="stroke-title"> Stroke: </div>
- <div className="stroke-button">{this.lineButton}</div>
- </div>
- </div>
- {this._fillBtn ? this.fillPicker : ""}
- {this._lineBtn ? this.linePicker : ""}
- </div>;
- }
-
- @computed get solidStk() { return this.selectedDoc?.color && (!this.selectedDoc?.strokeDash || this.selectedDoc?.strokeDash === "0") ? true : false; }
- @computed get dashdStk() { return this.selectedDoc?.strokeDash || ""; }
- @computed get unStrokd() { return this.selectedDoc?.color ? true : false; }
- @computed get widthStk() { return this.getField("strokeWidth") || "1"; }
- @computed get markHead() { return this.getField("strokeStartMarker") || ""; }
- @computed get markTail() { return this.getField("strokeEndMarker") || ""; }
- set solidStk(value) { this.dashdStk = ""; this.unStrokd = !value; }
- set dashdStk(value) {
- value && (this._lastDash = value) && (this.unStrokd = false);
- this.selectedDoc && (this.selectedDoc.strokeDash = value ? this._lastDash : undefined);
- }
- set widthStk(value) { this.selectedDoc && (this.selectedDoc.strokeWidth = Number(value)); }
- set unStrokd(value) { this.colorStk = value ? "" : this._lastLine; }
- set markHead(value) { this.selectedDoc && (this.selectedDoc.strokeStartMarker = value); }
- set markTail(value) { this.selectedDoc && (this.selectedDoc.strokeEndMarker = value); }
-
-
- @computed get stkInput() { return this.regInput("stk", this.widthStk, (val: string) => this.widthStk = val); }
-
-
- regInput = (key: string, value: any, setter: (val: string) => {}) => {
- return <div className="inputBox">
- <input className="inputBox-input"
- type="text" value={value}
- onChange={e => setter(e.target.value)} />
- <div className="inputBox-button">
- <div className="inputBox-button-up" key="up2"
- onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))} >
- <FontAwesomeIcon icon="caret-up" color="white" size="sm" />
- </div>
- <div className="inputbox-Button-down" key="down2"
- onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} >
- <FontAwesomeIcon icon="caret-down" color="white" size="sm" />
- </div>
- </div>
- </div>;
- }
-
- @computed get widthAndDash() {
- return <div className="widthAndDash">
- <div className="width">
- <div className="width-top">
- <div className="width-title">Width:</div>
- <div className="width-input">{this.stkInput}</div>
- </div>
- <input className="width-range" type="range"
- defaultValue={Number(this.widthStk)} min={1} max={100}
- onChange={(action((e) => this.widthStk = e.target.value))}
- onMouseDown={(e) => { this._widthUndo = UndoManager.StartBatch("width undo"); }}
- onMouseUp={(e) => { this._widthUndo?.end(); this._widthUndo = undefined; }}
- />
- </div>
-
- <div className="arrows">
- <div className="arrows-head">
- <div className="arrows-head-title" >Arrow Head: </div>
- <input key="markHead" className="arrows-head-input" type="checkbox"
- checked={this.markHead !== ""}
- onChange={undoBatch(action(() => this.markHead = this.markHead ? "" : "arrow"))} />
- </div>
- <div className="arrows-tail">
- <div className="arrows-tail-title" >Arrow End: </div>
- <input key="markTail" className="arrows-tail-input" type="checkbox"
- checked={this.markTail !== ""}
- onChange={undoBatch(action(() => this.markTail = this.markTail ? "" : "arrow"))} />
- </div>
- </div>
- <div className="dashed">
- <div className="dashed-title">Dashed Line:</div>
- <input key="markHead" className="dashed-input"
- type="checkbox" checked={this.dashdStk === "2"}
- onChange={this.changeDash} />
- </div>
- </div>;
- }
-
- @undoBatch @action
- changeDash = () => {
- this.dashdStk = this.dashdStk === "2" ? "0" : "2";
- }
-
- @computed get appearanceEditor() {
- return <div className="appearance-editor">
- {this.widthAndDash}
- {this.strokeAndFill}
- </div>;
- }
-
- @computed get transformEditor() {
- return <div className="transform-editor">
- {this.controlPointsButton}
- {this.hgtInput}
- {this.XpsInput}
- {this.rotInput}
- </div>;
- }
-
- /**
- * Handles adding and removing members from the sharing panel
- */
- // handleUserChange = (selectedUser: string, add: boolean) => {
- // if (!Doc.UserDoc().sidebarUsersDisplayed) Doc.UserDoc().sidebarUsersDisplayed = new Doc;
- // DocCastAsync(Doc.UserDoc().sidebarUsersDisplayed).then(sidebarUsersDisplayed => {
- // sidebarUsersDisplayed![`display-${selectedUser}`] = add;
- // !add && runInAction(() => this.selectedUser = "");
- // });
- // }
-
- render() {
- if (!this.selectedDoc && !this.isPres) {
- return <div className="propertiesView" style={{ width: this.props.width }}>
- <div className="propertiesView-title" style={{ width: this.props.width }}>
- No Document Selected
- </div>
- </div>;
-
- } else {
- const novice = Doc.UserDoc().noviceMode;
-
- if (this.selectedDoc && !this.isPres) {
- return <div className="propertiesView" style={{
- width: this.props.width,
- //overflowY: this.scrolling ? "scroll" : "visible"
- }} >
- <div className="propertiesView-title" style={{ width: this.props.width }}>
- Properties
- {/* <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
- <FontAwesomeIcon icon="times" color="black" size="sm" />
- </div> */}
- </div>
- <div className="propertiesView-name">
- {this.editableTitle}
- </div>
- <div className="propertiesView-settings" onPointerEnter={action(() => this.inOptions = true)}
- onPointerLeave={action(() => this.inOptions = false)}>
- <div className="propertiesView-settings-title"
- onPointerDown={action(() => this.openOptions = !this.openOptions)}
- style={{ backgroundColor: this.openOptions ? "black" : "" }}>
- Options
- <div className="propertiesView-settings-title-icon">
- <FontAwesomeIcon icon={this.openOptions ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {!this.openOptions ? (null) :
- <div className="propertiesView-settings-content">
- <PropertiesButtons />
- </div>}
- </div>
- <div className="propertiesView-sharing">
- <div className="propertiesView-sharing-title"
- onPointerDown={action(() => this.openSharing = !this.openSharing)}
- style={{ backgroundColor: this.openSharing ? "black" : "" }}>
- Sharing {"&"} Permissions
- <div className="propertiesView-sharing-title-icon">
- <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {!this.openSharing ? (null) :
- <div className="propertiesView-sharing-content">
- <div className="propertiesView-acls-checkbox">
- <Checkbox
- color="primary"
- onChange={action(() => this.layoutDocAcls = !this.layoutDocAcls)}
- checked={this.layoutDocAcls}
- />;
- <div className="propertiesView-acls-checkbox-text">Layout</div>
- </div>
- {this.sharingTable}
- {/* <div className="change-buttons">
- <button
- onPointerDown={action(() => this.addButtonPressed = !this.addButtonPressed)}
- >
- <FontAwesomeIcon icon={fa.faPlus} size={"sm"} style={{ marginTop: -3, marginLeft: -3 }} />
- </button>
- <button
- id="sharingProperties-removeUser"
- onPointerDown={() => this.handleUserChange(this.selectedUser, false)}
- style={{ backgroundColor: this.selectedUser ? "#121721" : "#777777" }}
- ><FontAwesomeIcon icon={fa.faMinus} size={"sm"} style={{ marginTop: -3, marginLeft: -3 }} /></button>
- <button onClick={() => SharingManager.Instance.open(this.selectedDocumentView!)}><FontAwesomeIcon icon={fa.faCog} size={"sm"} style={{ marginTop: -3, marginLeft: -3 }} /></button>
- {this.addButtonPressed ?
- // <input type="text" onKeyDown={this.handleKeyPress} /> :
- <select onChange={e => this.handleUserChange(e.target.value, true)}>
- <option selected disabled hidden>
- Add users
- </option>
- {SharingManager.Instance.users.map(user =>
- (<option value={user.user.email}>
- {user.user.email}
- </option>)
- )}
- {GroupManager.Instance.getAllGroups().map(group =>
- (<option value={StrCast(group.groupName)}>
- {StrCast(group.groupName)}
- </option>))}
- </select> :
- null}
- </div> */}
- </div>}
- </div>
-
- {!this.isInk ? (null) :
- <div className="propertiesView-appearance">
- <div className="propertiesView-appearance-title"
- onPointerDown={action(() => this.openAppearance = !this.openAppearance)}
- style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
- Appearance
- <div className="propertiesView-appearance-title-icon">
- <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {!this.openAppearance ? (null) :
- <div className="propertiesView-appearance-content">
- {this.appearanceEditor}
- </div>}
- </div>}
-
- {this.isInk ? <div className="propertiesView-transform">
- <div className="propertiesView-transform-title"
- onPointerDown={action(() => this.openTransform = !this.openTransform)}
- style={{ backgroundColor: this.openTransform ? "black" : "" }}>
- Transform
- <div className="propertiesView-transform-title-icon">
- <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {this.openTransform ? <div className="propertiesView-transform-content">
- {this.transformEditor}
- </div> : null}
- </div> : null}
-
- <div className="propertiesView-fields">
- <div className="propertiesView-fields-title"
- onPointerDown={action(() => this.openFields = !this.openFields)}
- style={{ backgroundColor: this.openFields ? "black" : "" }}>
- Fields {"&"} Tags
- <div className="propertiesView-fields-title-icon">
- <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {!novice && this.openFields ? <div className="propertiesView-fields-checkbox">
- {this.fieldsCheckbox}
- <div className="propertiesView-fields-checkbox-text">Layout</div>
- </div> : null}
- {!this.openFields ? (null) :
- <div className="propertiesView-fields-content">
- {novice ? this.noviceFields : this.expandedField}
- </div>}
- </div>
- <div className="propertiesView-contexts">
- <div className="propertiesView-contexts-title"
- onPointerDown={action(() => this.openContexts = !this.openContexts)}
- style={{ backgroundColor: this.openContexts ? "black" : "" }}>
- Contexts
- <div className="propertiesView-contexts-title-icon">
- <FontAwesomeIcon icon={this.openContexts ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {this.openContexts ? <div className="propertiesView-contexts-content" >{this.contexts}</div> : null}
- </div>
- <div className="propertiesView-layout">
- <div className="propertiesView-layout-title"
- onPointerDown={action(() => this.openLayout = !this.openLayout)}
- style={{ backgroundColor: this.openLayout ? "black" : "" }}>
- Layout
- <div className="propertiesView-layout-title-icon">
- <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {this.openLayout ? <div className="propertiesView-layout-content" >{this.layoutPreview}</div> : null}
- </div>
- </div>;
- }
- if (this.isPres) {
- const selectedItem: boolean = PresBox.Instance?._selectedArray.length > 0;
- return <div className="propertiesView" style={{ width: this.props.width }}>
- <div className="propertiesView-title" style={{ width: this.props.width }}>
- Presentation
- </div>
- <div className="propertiesView-name">
- {this.editableTitle}
- <div className="propertiesView-presSelected">
- {PresBox.Instance?._selectedArray.length} selected
- <div className="propertiesView-selectedList">
- {PresBox.Instance?.listOfSelected}
- </div>
- </div>
- </div>
- {!selectedItem ? (null) : <div className="propertiesView-presTrails">
- <div className="propertiesView-presTrails-title"
- onPointerDown={action(() => { this.openPresTransitions = !this.openPresTransitions; })}
- style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}>
- &nbsp; <FontAwesomeIcon icon={"rocket"} /> &nbsp; Transitions
- <div className="propertiesView-presTrails-title-icon">
- <FontAwesomeIcon icon={this.openPresTransitions ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {this.openPresTransitions ? <div className="propertiesView-presTrails-content">
- {PresBox.Instance.transitionDropdown}
- </div> : null}
- </div>}
- {!selectedItem ? (null) : <div className="propertiesView-presTrails">
- <div className="propertiesView-presTrails-title"
- onPointerDown={action(() => { this.openPresProgressivize = !this.openPresProgressivize; })}
- style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}>
- &nbsp; <FontAwesomeIcon icon={"tasks"} /> &nbsp; Progressivize
- <div className="propertiesView-presTrails-title-icon">
- <FontAwesomeIcon icon={this.openPresProgressivize ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {this.openPresProgressivize ? <div className="propertiesView-presTrails-content">
- {PresBox.Instance.progressivizeDropdown}
- </div> : null}
- </div>}
- {!selectedItem ? (null) : <div className="propertiesView-presTrails">
- <div className="propertiesView-presTrails-title"
- onPointerDown={action(() => { this.openSlideOptions = !this.openSlideOptions; })}
- style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}>
- &nbsp; <FontAwesomeIcon icon={"cog"} /> &nbsp; {PresBox.Instance.stringType} options
- <div className="propertiesView-presTrails-title-icon">
- <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {this.openSlideOptions ? <div className="propertiesView-presTrails-content">
- {PresBox.Instance.optionsDropdown}
- </div> : null}
- </div>}
- <div className="propertiesView-presTrails">
- <div className="propertiesView-presTrails-title"
- onPointerDown={action(() => { this.openAddSlide = !this.openAddSlide; })}
- style={{ backgroundColor: this.openAddSlide ? "black" : "" }}>
- &nbsp; <FontAwesomeIcon icon={"plus"} /> &nbsp; Add new slide
- <div className="propertiesView-presTrails-title-icon">
- <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {this.openAddSlide ? <div className="propertiesView-presTrails-content">
- {PresBox.Instance.newDocumentDropdown}
- </div> : null}
- </div>
- {/* <div className="propertiesView-sharing">
- <div className="propertiesView-sharing-title"
- onPointerDown={acition(() => { this.openSharing = !this.openSharing; })}
- style={{ backgroundColor: this.openSharing ? "black" : "" }}>
- Sharing {"&"} Permissions
- <div className="propertiesView-sharing-title-icon">
- <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
- </div>
- </div>
- {this.openSharing ? <div className="propertiesView-sharing-content">
- {this.sharingTable}
- </div> : null}
- </div> */}
- </div>;
- }
- }
- }
-} \ No newline at end of file
diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.scss b/src/client/views/collections/collectionGrid/CollectionGridView.scss
index 4d8473be9..60ec02f47 100644
--- a/src/client/views/collections/collectionGrid/CollectionGridView.scss
+++ b/src/client/views/collections/collectionGrid/CollectionGridView.scss
@@ -134,17 +134,6 @@
}
-// .documentDecorations-container .documentDecorations-resizer {
-// pointer-events: none;
-// }
-
-// #documentDecorations-bottomRightResizer,
-// #documentDecorations-bottomLeftResizer,
-// #documentDecorations-topRightResizer,
-// #documentDecorations-topLeftResizer {
-// visibility: collapse;
-// }
-
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,