aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/SelectionManager.ts5
-rw-r--r--src/client/views/GlobalKeyHandler.ts141
-rw-r--r--src/client/views/MainView.tsx62
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx21
-rw-r--r--src/client/views/nodes/DocumentView.tsx4
5 files changed, 176 insertions, 57 deletions
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 7dbb81e76..3bc71ad42 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,11 +1,13 @@
-import { observable, action, runInAction } from "mobx";
+import { observable, action, runInAction, IReactionDisposer, reaction, autorun } from "mobx";
import { Doc } from "../../new_fields/Doc";
import { DocumentView } from "../views/nodes/DocumentView";
import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
import { NumCast } from "../../new_fields/Types";
export namespace SelectionManager {
+
class Manager {
+
@observable IsDragging: boolean = false;
@observable SelectedDocuments: Array<DocumentView> = [];
@@ -18,6 +20,7 @@ export namespace SelectionManager {
}
manager.SelectedDocuments.push(docView);
+ // console.log(manager.SelectedDocuments);
docView.props.whenActiveChanged(true);
}
}
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
new file mode 100644
index 000000000..bb10f27cf
--- /dev/null
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -0,0 +1,141 @@
+import { UndoManager } from "../util/UndoManager";
+import { SelectionManager } from "../util/SelectionManager";
+import { CollectionDockingView } from "./collections/CollectionDockingView";
+import { MainView } from "./MainView";
+import { DragManager } from "../util/DragManager";
+import { action } from "mobx";
+
+const modifiers = ["Control", "Meta", "Shift", "Alt"];
+type KeyHandler = (keycode: string) => KeyControlInfo;
+type KeyControlInfo = {
+ preventDefault: boolean,
+ stopPropagation: boolean
+};
+
+export default class KeyManager {
+ public static Handler: KeyManager;
+ private mainView: MainView;
+ private router = new Map<string, KeyHandler>();
+
+ constructor(mainView: MainView) {
+ this.mainView = mainView;
+ this.router.set("0000", this.unmodified);
+ this.router.set("0100", this.ctrl);
+ this.router.set("0010", this.alt);
+ this.router.set("1100", this.ctrl_shift);
+ }
+
+ public handle = (e: KeyboardEvent) => {
+ let keyname = e.key.toLowerCase();
+ this.handleGreedy(keyname);
+
+ if (modifiers.includes(keyname)) {
+ return;
+ }
+
+ let bit = (value: boolean) => value ? "1" : "0";
+ let modifierIndex = bit(e.shiftKey) + bit(e.ctrlKey) + bit(e.altKey) + bit(e.metaKey);
+
+ let handleConstrained = this.router.get(modifierIndex);
+ if (!handleConstrained) {
+ return;
+ }
+
+ let control = handleConstrained(keyname);
+
+ control.stopPropagation && e.stopPropagation();
+ control.preventDefault && e.preventDefault();
+ }
+
+ private handleGreedy = action((keyname: string) => {
+ switch (keyname) {
+ }
+ });
+
+ private unmodified = action((keyname: string) => {
+ switch (keyname) {
+ case "escape":
+ if (CollectionDockingView.Instance.HasFullScreen()) {
+ CollectionDockingView.Instance.CloseFullScreen();
+ } else {
+ SelectionManager.DeselectAll();
+ }
+ DragManager.AbortDrag();
+ break;
+ }
+
+ return {
+ stopPropagation: false,
+ preventDefault: false
+ };
+ });
+
+ private alt = action((keyname: string) => {
+ let stopPropagation = true;
+ let preventDefault = true;
+
+ switch (keyname) {
+ case "n":
+ let toggle = this.mainView.addMenuToggle.current!;
+ toggle.checked = !toggle.checked;
+ break;
+ }
+
+ return {
+ stopPropagation: stopPropagation,
+ preventDefault: preventDefault
+ };
+ });
+
+ private ctrl = action((keyname: string) => {
+ let stopPropagation = true;
+ let preventDefault = true;
+
+ switch (keyname) {
+ case "arrowright":
+ this.mainView.mainFreeform && CollectionDockingView.Instance.AddRightSplit(this.mainView.mainFreeform, undefined);
+ break;
+ case "arrowleft":
+ this.mainView.mainFreeform && CollectionDockingView.Instance.CloseRightSplit(this.mainView.mainFreeform);
+ break;
+ case "f":
+ this.mainView.isSearchVisible = !this.mainView.isSearchVisible;
+ break;
+ case "o":
+ let target = SelectionManager.SelectedDocuments()[0];
+ target && target.fullScreenClicked();
+ break;
+ case "r":
+ preventDefault = false;
+ break;
+ case "y":
+ UndoManager.Redo();
+ break;
+ case "z":
+ UndoManager.Undo();
+ break;
+ }
+
+ return {
+ stopPropagation: stopPropagation,
+ preventDefault: preventDefault
+ };
+ });
+
+ private ctrl_shift = action((keyname: string) => {
+ let stopPropagation = true;
+ let preventDefault = true;
+
+ switch (keyname) {
+ case "z":
+ UndoManager.Redo();
+ break;
+ }
+
+ return {
+ stopPropagation: stopPropagation,
+ preventDefault: preventDefault
+ };
+ });
+
+} \ No newline at end of file
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 6290d8985..157512aa0 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -36,18 +36,20 @@ import { CollectionBaseView } from './collections/CollectionBaseView';
import { List } from '../../new_fields/List';
import PDFMenu from './pdf/PDFMenu';
import { InkTool } from '../../new_fields/InkField';
-import * as _ from "lodash";
+import _ from "lodash";
+import KeyManager from './GlobalKeyHandler';
@observer
export class MainView extends React.Component {
public static Instance: MainView;
+ @observable addMenuToggle = React.createRef<HTMLInputElement>();
@observable private _workspacesShown: boolean = false;
@observable public pwidth: number = 0;
@observable public pheight: number = 0;
@computed private get mainContainer(): Opt<Doc> {
return FieldValue(Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc));
}
- @computed private get mainFreeform(): Opt<Doc> {
+ @computed get mainFreeform(): Opt<Doc> {
let docs = DocListCast(this.mainContainer!.data);
return (docs && docs.length > 1) ? docs[1] : undefined;
}
@@ -64,12 +66,13 @@ export class MainView extends React.Component {
}
componentWillMount() {
- document.removeEventListener("keydown", this.globalKeyHandler);
- document.addEventListener("keydown", this.globalKeyHandler);
+ KeyManager.Handler = new KeyManager(this);
+ document.removeEventListener("keydown", KeyManager.Handler.handle);
+ document.addEventListener("keydown", KeyManager.Handler.handle);
}
componentWillUnMount() {
- document.removeEventListener("keydown", this.globalKeyHandler);
+ document.removeEventListener("keydown", KeyManager.Handler.handle);
}
constructor(props: Readonly<{}>) {
@@ -122,18 +125,6 @@ export class MainView extends React.Component {
// window.addEventListener("pointermove", (e) => this.reportLocation(e))
window.addEventListener("drop", (e) => e.preventDefault(), false); // drop event handler
window.addEventListener("dragover", (e) => e.preventDefault(), false); // drag event handler
- window.addEventListener("keydown", (e) => {
- if (e.key === "Escape") {
- DragManager.AbortDrag();
- SelectionManager.DeselectAll();
- } else if (e.key === "z" && e.ctrlKey) {
- e.preventDefault();
- UndoManager.Undo();
- } else if ((e.key === "y" && e.ctrlKey) || (e.key === "z" && e.ctrlKey && e.shiftKey)) {
- e.preventDefault();
- UndoManager.Redo();
- }
- }, false); // drag event handler
// click interactions for the context menu
document.addEventListener("pointerdown", action(function (e: PointerEvent) {
@@ -292,7 +283,7 @@ export class MainView extends React.Component {
];
return < div id="add-nodes-menu" >
- <input type="checkbox" id="add-menu-toggle" />
+ <input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
<label htmlFor="add-menu-toggle" title="Add Node"><p>+</p></label>
<div id="add-options-content">
@@ -300,8 +291,7 @@ export class MainView extends React.Component {
<li key="search"><button className="add-button round-button" title="Search" onClick={this.toggleSearch}><FontAwesomeIcon icon="search" size="sm" /></button></li>
<li key="undo"><button className="add-button round-button" title="Undo" onClick={() => UndoManager.Undo()}><FontAwesomeIcon icon="undo-alt" size="sm" /></button></li>
<li key="redo"><button className="add-button round-button" title="Redo" onClick={() => UndoManager.Redo()}><FontAwesomeIcon icon="redo-alt" size="sm" /></button></li>
- <li key="color"><button className="add-button round-button" title="Redo" onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
-
+ <li key="color"><button className="add-button round-button" title="Select Color" onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
<div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}>
<SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} />
</div>
@@ -362,38 +352,6 @@ export class MainView extends React.Component {
this.isSearchVisible = !this.isSearchVisible;
}
- @action
- globalKeyHandler = (e: KeyboardEvent) => {
- if (e.key === "Control" || !e.ctrlKey) return;
-
- if (e.key === "v") return;
- if (e.key === "c") return;
-
- e.preventDefault();
- e.stopPropagation();
-
- switch (e.key) {
- case "ArrowRight":
- if (this.mainFreeform) {
- CollectionDockingView.Instance.AddRightSplit(this.mainFreeform, undefined);
- }
- break;
- case "ArrowLeft":
- if (this.mainFreeform) {
- CollectionDockingView.Instance.CloseRightSplit(this.mainFreeform);
- }
- break;
- case "o":
- this.globalDisplayFlags.jumpToVisible = true;
- break;
- case "escape":
- _.mapValues(this.globalDisplayFlags, () => false);
- break;
- case "f":
- this.isSearchVisible = !this.isSearchVisible;
- }
- }
-
render() {
return (
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 938674c48..64e0ececb 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -52,6 +52,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
private _flush: boolean = false;
private _ignoreStateChange = "";
private _isPointerDown = false;
+ private _maximizedSrc: Opt<DocumentView>;
constructor(props: SubCollectionViewProps) {
super(props);
@@ -71,7 +72,9 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
}
@action
- public OpenFullScreen(document: Doc, dataDoc: Doc) {
+ public OpenFullScreen(docView: DocumentView) {
+ let document = Doc.MakeAlias(docView.props.Document);
+ let dataDoc = docView.dataDoc;
let newItemStackConfig = {
type: 'stack',
content: [CollectionDockingView.makeDocumentConfig(document, dataDoc)]
@@ -80,10 +83,25 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
this._goldenLayout.root.contentItems[0].addChild(docconfig);
docconfig.callDownwards('_$init');
this._goldenLayout._$maximiseItem(docconfig);
+ this._maximizedSrc = docView;
this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
this.stateChanged();
}
+ public CloseFullScreen = () => {
+ let target = this._goldenLayout._maximisedItem;
+ if (target !== null && this._maximizedSrc) {
+ this._goldenLayout._maximisedItem.remove();
+ SelectionManager.SelectDoc(this._maximizedSrc, false);
+ this._maximizedSrc = undefined;
+ this.stateChanged();
+ }
+ }
+
+ public HasFullScreen = () => {
+ return this._goldenLayout._maximisedItem !== null;
+ }
+
@undoBatch
@action
public CloseRightSplit = (document: Doc): boolean => {
@@ -257,7 +275,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
@action
onPointerUp = (e: React.PointerEvent): void => {
- this._isPointerDown = false;
if (this._flush) {
this._flush = false;
setTimeout(() => this.stateChanged(), 10);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ada28d57b..525ca52a6 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -406,8 +406,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
doc.nativeWidth = doc.nativeHeight = undefined;
}
}
- fullScreenClicked = (): void => {
- CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(Doc.MakeAlias(this.props.Document), this.dataDoc);
+ public fullScreenClicked = (): void => {
+ CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this);
SelectionManager.DeselectAll();
}