aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Zeleznik <zzzman@gmail.com>2019-05-06 01:10:14 -0400
committerBob Zeleznik <zzzman@gmail.com>2019-05-06 01:10:14 -0400
commit9830eb15041fa8e99ef8f5bb6fdcf6b3c28c058d (patch)
tree27e229891592865ce310b9c7748da631d150519e
parent09a471ac693e8178598c0d953b83868db9e4c8b4 (diff)
added start of "minimap" support via better buttons and summaries.
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx36
-rw-r--r--src/client/views/collections/CollectionTreeView.scss39
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx13
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx37
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx28
-rw-r--r--src/client/views/nodes/DocumentView.tsx9
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx4
7 files changed, 118 insertions, 48 deletions
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 278065479..e4f02a4bc 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -72,6 +72,37 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
this.stateChanged();
}
+ @undoBatch
+ @action
+ public CloseRightSplit(document: Doc) {
+ if (this._goldenLayout.root.contentItems[0].isRow) {
+ this._goldenLayout.root.contentItems[0].contentItems.map((child: any, i: number) => {
+ if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" &&
+ child.contentItems[0].config.props.documentId == document[Id]) {
+ child.contentItems[0].remove();
+ //this._goldenLayout.root.contentItems[0].contentItems.splice(i, 1);
+ this.layoutChanged(document);
+ } else
+ child.contentItems.map((tab: any, j: number) => {
+ if (tab.config.component === "DocumentFrameRenderer" && tab.config.props.documentId === document[Id]) {
+ child.contentItems[j].remove();
+ let docs = Cast(this.props.Document.data, listSpec(Doc));
+ docs && docs.indexOf(document) !== -1 && docs.splice(docs.indexOf(document), 1);
+ }
+ });
+ })
+ }
+ }
+
+ @action
+ layoutChanged(removed?: Doc) {
+ this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
+ this._goldenLayout.emit('sbcreteChanged');
+ this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
+ if (removed) CollectionDockingView.Instance._removedDocs.push(removed);
+ this.stateChanged();
+ }
+
//
// Creates a vertical split on the right side of the docking view, and then adds the Document to that split
//
@@ -107,10 +138,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
newContentItem.config.height = 10;
}
newContentItem.callDownwards('_$init');
- this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
- this._goldenLayout.emit('stateChanged');
- this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
- this.stateChanged();
+ this.layoutChanged();
return newContentItem;
}
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 6ce13cf56..411d67ff7 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -23,10 +23,6 @@
margin: 5px 0;
}
- .collection-child {
- margin-top: 10px;
- margin-bottom: 10px;
- }
.no-indent {
padding-left: 0;
@@ -42,24 +38,18 @@
transform: scale(1.3,1.3);
}
- .coll-title {
- width:max-content;
- display: block;
- font-size: 24px;
- }
-
.docContainer {
margin-left: 10px;
display: block;
- width:100%;//width: max-content;
+ // width:100%;//width: max-content;
}
-
.docContainer:hover {
- .delete-button {
- display: inline;
- // width: auto;
+ .treeViewItem-openRight {
+ display:inline;
}
}
+
+
.editableView-container {
font-weight: bold;
}
@@ -71,7 +61,26 @@
// margin-top: 3px;
display: inline;
}
+ .treeViewItem-openRight {
+ margin-left: 5px;
+ display:none;
+ }
+ .docContainer:hover {
+ .delete-button {
+ display: inline;
+ // width: auto;
+ }
+ }
+ .coll-title {
+ width:max-content;
+ display: block;
+ font-size: 24px;
+ }
+ .collection-child {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ }
.collectionTreeView-keyHeader {
font-style: italic;
font-size: 8pt;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 17109508d..947a066d9 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,5 +1,5 @@
import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretDown, faCaretRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
+import { faCaretDown, faCaretRight, faTrashAlt, faAngleRight } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, observable, trace } from "mobx";
import { observer } from "mobx-react";
@@ -36,6 +36,7 @@ export enum BulletType {
}
library.add(faTrashAlt);
+library.add(faAngleRight);
library.add(faCaretDown);
library.add(faCaretRight);
@@ -48,6 +49,7 @@ class TreeView extends React.Component<TreeViewProps> {
@observable _collapsed: boolean = true;
delete = () => this.props.deleteDoc(this.props.document);
+ openRight = () => CollectionDockingView.Instance.AddRightSplit(this.props.document);
get children() {
return Cast(this.props.document.data, listSpec(Doc), []); // bcz: needed? .filter(doc => FieldValue(doc));
@@ -100,9 +102,11 @@ class TreeView extends React.Component<TreeViewProps> {
}}
/>);
return (
- <div className="docContainer" ref={reference} onPointerDown={onItemDown}>
+ <div className="docContainer" ref={reference} onPointerDown={onItemDown}
+ onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
{editableView(StrCast(this.props.document.title))}
- {/* <div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div> */}
+ <div className="treeViewItem-openRight" onClick={this.openRight}><FontAwesomeIcon icon="angle-right" size="lg" /><FontAwesomeIcon icon="angle-right" size="lg" /></div>
+ {/* {<div className="delete-button" onClick={this.delete}><FontAwesomeIcon icon="trash-alt" size="xs" /></div>} */}
</div >);
}
@@ -145,8 +149,7 @@ class TreeView extends React.Component<TreeViewProps> {
});
return <div className="treeViewItem-container"
style={{ background: BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0" }}
- onContextMenu={this.onWorkspaceContextMenu}
- onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+ onContextMenu={this.onWorkspaceContextMenu}>
<li className="collection-child">
{this.renderBullet(bulletType)}
{this.renderTitle()}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 8c81f6990..805921ad4 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -15,6 +15,8 @@ import { NumCast, Cast } from "../../../../new_fields/Types";
import { InkField, StrokeData } from "../../../../new_fields/InkField";
import { Templates } from "../../Templates";
import { List } from "../../../../new_fields/List";
+import { emitKeypressEvents } from "readline";
+import { listSpec } from "../../../../new_fields/Schema";
interface MarqueeViewProps {
getContainerTransform: () => Transform;
@@ -149,16 +151,17 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
this.cleanupInteractions(false);
e.stopPropagation();
}
- if (e.key === "c" || e.key === "r" || e.key === "e") {
+ if (e.key === "c" || e.key === "r" || e.key === "R" || e.key === "e") {
this._commandExecuted = true;
e.stopPropagation();
let bounds = this.Bounds;
let selected = this.marqueeSelect().map(d => {
- if (e.key !== "r")
+ if (e.key !== "R") {
this.props.removeDocument(d);
- d.x = NumCast(d.x) - bounds.left - bounds.width / 2;
- d.y = NumCast(d.y) - bounds.top - bounds.height / 2;
- d.page = -1;
+ d.x = NumCast(d.x) - bounds.left - bounds.width / 2;
+ d.y = NumCast(d.y) - bounds.top - bounds.height / 2;
+ d.page = -1;
+ }
return d;
});
let ink = Cast(this.props.container.props.Document.ink, InkField);
@@ -179,16 +182,23 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
this.marqueeInkDelete(inkData);
// SelectionManager.DeselectAll();
- if (e.key === "r") {
- let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
- summary.maximizedDocs = new List<Doc>(selected);
- // summary.doc1 = selected[0];
- // if (selected.length > 1)
- // summary.doc2 = selected[1];
- // summary.templates = new List<string>([Templates.Summary.Layout]);
- this.props.addLiveTextDocument(summary);
+ if (e.key === "r" || e.key === "R") {
e.preventDefault();
let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top);
+ let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" });
+
+ if (e.key === "r") {
+ summary.proto!.maximizeOnRight = true;
+ let list = Cast(newCollection.data, listSpec(Doc));
+ if (list && list.length === 1) {
+ selected = list;
+ } else {
+ selected = [newCollection];
+ this.props.addDocument(newCollection, false);
+ }
+ }
+ summary.proto!.maximizedDocs = new List<Doc>(selected);
+ summary.proto!.isButton = true;
selected.map(maximizedDoc => {
let maxx = NumCast(maximizedDoc.x, undefined);
let maxy = NumCast(maximizedDoc.y, undefined);
@@ -196,6 +206,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
let maxh = NumCast(maximizedDoc.height, undefined);
maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0])
});
+ this.props.addLiveTextDocument(summary);
}
else {
this.props.addDocument(newCollection, false);
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 2ba0458f5..cf08c1bc4 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -6,11 +6,12 @@ import "./DocumentView.scss";
import React = require("react");
import { DocComponent } from "../DocComponent";
import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema";
-import { FieldValue, Cast, NumCast, BoolCast } from "../../../new_fields/Types";
+import { FieldValue, Cast, NumCast, BoolCast, PromiseValue } from "../../../new_fields/Types";
import { OmitKeys, Utils } from "../../../Utils";
import { SelectionManager } from "../../util/SelectionManager";
import { Doc } from "../../../new_fields/Doc";
import { List } from "../../../new_fields/List";
+import { CollectionDockingView } from "../collections/CollectionDockingView";
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
}
@@ -86,7 +87,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
let scrpt = this.props.ScreenToLocalTransform().transformPoint(values[0], values[1]);
this.animateBetweenIcon(true, scrpt, [values[2], values[3]], values[4], values[5], values[6], this.props.Document, values[7] ? true : false);
}
- });
+ }, { fireImmediately: true });
}
componentWillUnmount() {
@@ -162,14 +163,31 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
onClick = async (e: React.MouseEvent) => {
e.stopPropagation();
let ctrlKey = e.ctrlKey;
+ let metaKey = e.metaKey;
if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
if (await BoolCast(this.props.Document.isButton, false)) {
let maximizedDocs = await Cast(this.props.Document.maximizedDocs, listSpec(Doc));
if (maximizedDocs) { // bcz: need a better way to associate behaviors with click events on widget-documents
- if (ctrlKey)
- this.props.addDocument && maximizedDocs.filter(d => d instanceof Doc).map(maxDoc => this.props.addDocument!(maxDoc, false));
- this.toggleIcon();
+ if ((metaKey && !this.props.Document.maximizeOnRight) || (!metaKey && this.props.Document.maximizeOnRight)) {
+ SelectionManager.DeselectAll();
+ maximizedDocs.map(async mdoc => {
+ let maxDoc = await mdoc;
+ let dataDocs = await Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc));
+ if (dataDocs) {
+ Promise.all(dataDocs.map(async doc => await doc)).then(docs => {
+ if (!docs || docs.indexOf(maxDoc) == -1) {
+ CollectionDockingView.Instance.AddRightSplit(maxDoc);
+ } else {
+ CollectionDockingView.Instance.CloseRightSplit(maxDoc);
+ }
+ })
+ }
+ });
+ } else {
+ this.props.addDocument && maximizedDocs.map(async maxDoc => this.props.addDocument!(await maxDoc, false));
+ this.toggleIcon();
+ }
}
}
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 096a02d9b..9d356cc30 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -202,10 +202,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
CollectionDockingView.Instance.AddRightSplit(kvp);
}
makeButton = (e: React.MouseEvent): void => {
- this.props.Document.isButton = !BoolCast(this.props.Document.isButton, false);
- if (this.props.Document.isButton && !this.props.Document.nativeWidth) {
- this.props.Document.nativeWidth = this.props.Document[WidthSym]();
- this.props.Document.nativeHeight = this.props.Document[HeightSym]();
+ let doc = this.props.Document.proto ? this.props.Document.proto : this.props.Document;
+ doc.isButton = !BoolCast(doc.isButton, false);
+ if (doc.isButton && !doc.nativeWidth) {
+ doc.nativeWidth = doc[WidthSym]();
+ doc.nativeHeight = doc[HeightSym]();
}
}
fullScreenClicked = (e: React.MouseEvent): void => {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index eeb60cb3d..65b8b805f 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -128,7 +128,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
);
} else {
this._proxyReactionDisposer = reaction(() => this.props.isSelected(),
- () => this.props.isSelected() && !BoolCast(this.props.Document.isButton, false) && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform));
+ () => this.props.isSelected() && MainOverlayTextBox.Instance.SetTextDoc(this.props.Document, this.props.fieldKey, this._ref.current!, this.props.ScreenToLocalTransform));
}
@@ -310,7 +310,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
// tfs: do we need this event handler
onWheel={this.onPointerWheel}
>
- <div className={`formattedTextBox-inner${rounded}`} style={{ pointerEvents: this.props.Document.isButton ? "none" : "all" }} ref={this._proseRef} />
+ <div className={`formattedTextBox-inner${rounded}`} style={{ pointerEvents: this.props.Document.isButton && !this.props.isSelected() ? "none" : "all" }} ref={this._proseRef} />
</div>
);
}