diff options
author | Bob Zeleznik <zzzman@gmail.com> | 2019-04-12 21:18:30 -0400 |
---|---|---|
committer | Bob Zeleznik <zzzman@gmail.com> | 2019-04-12 21:18:30 -0400 |
commit | db9ee4f0d710d132e33e48cf6f105fd945941003 (patch) | |
tree | 505c1b4ecba7b1b7cce4a77f3e3e55b5933a8e03 | |
parent | e3caa89d36c501c16acbc56900546d8a4522584a (diff) |
combined preview cursor with marquee. moved preview cursor prompt to its own file.
-rw-r--r-- | src/client/views/DocumentDecorations.scss | 2 | ||||
-rw-r--r-- | src/client/views/Main.scss | 2 | ||||
-rw-r--r-- | src/client/views/Main.tsx | 39 | ||||
-rw-r--r-- | src/client/views/PreviewCursor.scss | 9 | ||||
-rw-r--r-- | src/client/views/PreviewCursor.tsx | 37 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 33 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 43 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/PreviewCursor.scss | 27 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/PreviewCursor.tsx | 85 |
9 files changed, 103 insertions, 174 deletions
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index ce84b6106..c1a949639 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -78,6 +78,7 @@ grid-column-end: 6; pointer-events: all; text-align: center; + cursor: pointer; } .documentDecorations-minimizeButton { background:$alt-accent; @@ -86,6 +87,7 @@ grid-column-end: 3; pointer-events: all; text-align: center; + cursor: pointer; } .documentDecorations-background { background: lightblue; diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index f3af26f37..13cadb10d 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -184,7 +184,7 @@ button:hover { position:absolute; top: 0; left: 0; -} + } } #mainContent-div { width:100%; diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 80e19c4f5..ed61aa5a7 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -40,44 +40,9 @@ import { DocumentView } from './nodes/DocumentView'; import { FormattedTextBox } from './nodes/FormattedTextBox'; import { REPLCommand } from 'repl'; import { Key } from '../../fields/Key'; -import { truncate } from 'fs'; +import { PreviewCursor } from './PreviewCursor'; -export interface PromptProps { -} - -@observer -export class PreviewCursorPrompt extends React.Component<PromptProps> { - private _prompt = React.createRef<HTMLDivElement>(); - //when focus is lost, this will remove the preview cursor - @action onBlur = (): void => { - PreviewCursorPrompt.Visible = false; - PreviewCursorPrompt.hide(); - } - - @observable static clickPoint = [0, 0]; - @observable public static Visible = false; - @observable public static hide = () => { }; - @action - public static Show(hide: any, x: number, y: number) { - this.clickPoint = [x, y]; - this.hide = hide; - setTimeout(action(() => this.Visible = true), (1)); - } - render() { - if (!PreviewCursorPrompt.clickPoint) { - return (null); - } - if (PreviewCursorPrompt.Visible && this._prompt.current) { - this._prompt.current.focus(); - } - let p = PreviewCursorPrompt.clickPoint; - return <div className="previewCursor" id="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={this._prompt} - style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, opacity: PreviewCursorPrompt.Visible ? 1 : 0 }}> - I - </div >; - } -} @observer export class Main extends React.Component { // dummy initializations keep the compiler happy @@ -429,7 +394,7 @@ export class Main extends React.Component { {({ measureRef }) => <div ref={measureRef} id="mainContent-div"> {this.mainContent} - <PreviewCursorPrompt /> + <PreviewCursor /> </div> } </Measure> diff --git a/src/client/views/PreviewCursor.scss b/src/client/views/PreviewCursor.scss new file mode 100644 index 000000000..20f9b9a49 --- /dev/null +++ b/src/client/views/PreviewCursor.scss @@ -0,0 +1,9 @@ + +.previewCursor { + color: black; + position: absolute; + transform-origin: left top; + top: 0; + left:0; + pointer-events: none; +}
\ No newline at end of file diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx new file mode 100644 index 000000000..ff8434681 --- /dev/null +++ b/src/client/views/PreviewCursor.tsx @@ -0,0 +1,37 @@ +import { action, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import "normalize.css"; +import * as React from 'react'; +import "./PreviewCursor.scss"; + +@observer +export class PreviewCursor extends React.Component<{}> { + private _prompt = React.createRef<HTMLDivElement>(); + //when focus is lost, this will remove the preview cursor + @action onBlur = (): void => { + PreviewCursor.Visible = false; + PreviewCursor.hide(); + } + + @observable static clickPoint = [0, 0]; + @observable public static Visible = false; + @observable public static hide = () => { }; + @action + public static Show(hide: any, x: number, y: number) { + this.clickPoint = [x, y]; + this.hide = hide; + setTimeout(action(() => this.Visible = true), (1)); + } + render() { + if (!PreviewCursor.clickPoint) { + return (null); + } + if (PreviewCursor.Visible && this._prompt.current) { + this._prompt.current.focus(); + } + return <div className="previewCursor" id="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={this._prompt} + style={{ transform: `translate(${PreviewCursor.clickPoint[0]}px, ${PreviewCursor.clickPoint[1]}px)`, opacity: PreviewCursor.Visible ? 1 : 0 }}> + I + </div >; + } +}
\ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 98ebbf1b3..e19dc98fa 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -23,7 +23,6 @@ import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView"; import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors"; import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; -import { PreviewCursor } from "./PreviewCursor"; import React = require("react"); import v5 = require("uuid/v5"); @@ -311,9 +310,9 @@ export class CollectionFreeFormView extends CollectionSubView { const [dx, dy] = [this.centeringShiftX, this.centeringShiftY]; const panx: number = -this.props.Document.GetNumber(KeyStore.PanX, 0); const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0); - const zoom: number = this.zoomScaling; - const blay = this.backgroundView; - const olay = this.overlayView; + const zoom: number = this.zoomScaling;// needs to be a variable outside of the <Measure> otherwise, reactions won't fire + const backgroundView = this.backgroundView; // needs to be a variable outside of the <Measure> otherwise, reactions won't fire + const overlayView = this.overlayView;// needs to be a variable outside of the <Measure> otherwise, reactions won't fire return ( <Measure onResize={(r: any) => runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height; })}> @@ -323,21 +322,19 @@ export class CollectionFreeFormView extends CollectionSubView { onPointerDown={this.onPointerDown} onPointerMove={(e) => super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} ref={this.createDropTarget}> <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} - addDocument={this.addDocument} removeDocument={this.props.removeDocument} + addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox} getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}> - <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox} getTransform={this.getTransform} > - <div className="collectionfreeformview" ref={this._canvasRef} - style={{ transform: `translate(${dx}px, ${dy}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}> - {blay} - <CollectionFreeFormLinksView {...this.props}> - <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} > - {this.childViews} - </InkingCanvas> - </CollectionFreeFormLinksView> - <CollectionFreeFormRemoteCursors {...this.props} /> - </div> - {olay} - </PreviewCursor> + <div className="collectionfreeformview" ref={this._canvasRef} + style={{ transform: `translate(${dx}px, ${dy}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}> + {backgroundView} + <CollectionFreeFormLinksView {...this.props}> + <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} > + {this.childViews} + </InkingCanvas> + </CollectionFreeFormLinksView> + <CollectionFreeFormRemoteCursors {...this.props} /> + </div> + {overlayView} </MarqueeView> </div> </div>)} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 1e6faafb3..9c0d75c22 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,4 +1,4 @@ -import { action, computed, observable, trace } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../../fields/Document"; import { FieldWaiting } from "../../../../fields/Field"; @@ -8,9 +8,9 @@ import { Documents } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; import { Transform } from "../../../util/Transform"; import { InkingCanvas } from "../../InkingCanvas"; +import { PreviewCursor } from "../../PreviewCursor"; import { CollectionFreeFormView } from "./CollectionFreeFormView"; import "./MarqueeView.scss"; -import { PreviewCursor } from "./PreviewCursor"; import React = require("react"); interface MarqueeViewProps { @@ -21,6 +21,7 @@ interface MarqueeViewProps { activeDocuments: () => Document[]; selectDocuments: (docs: Document[]) => void; removeDocument: (doc: Document) => boolean; + addLiveTextDocument: (doc: Document) => void; } @observer @@ -32,6 +33,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps> @observable _downY: number = 0; @observable _used: boolean = false; @observable _visible: boolean = false; + _showOnUp: boolean = false; static DRAG_THRESHOLD = 4; @action @@ -47,11 +49,31 @@ export class MarqueeView extends React.Component<MarqueeViewProps> } @action + onKeyPress = (e: KeyboardEvent) => { + // Mixing events between React and Native is finicky. In FormattedTextBox, we set the + // DASHFormattedTextBoxHandled flag when a text box consumes a key press so that we can ignore + // the keyPress here. + //if not these keys, make a textbox if preview cursor is active! + if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) { + //make textbox and add it to this collection + let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY); + let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "typed text" }); + this.props.addLiveTextDocument(newBox); + PreviewCursor.Visible = false; + e.stopPropagation(); + } + } + hideCursor = () => { + document.removeEventListener("keypress", this.onKeyPress, false); + } + @action onPointerDown = (e: React.PointerEvent): void => { if (e.buttons === 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) { this._downX = this._lastX = e.pageX; this._downY = this._lastY = e.pageY; this._used = false; + this._showOnUp = true; + document.removeEventListener("keypress", this.onKeyPress, false); document.addEventListener("pointermove", this.onPointerMove, true); document.addEventListener("pointerup", this.onPointerUp, true); document.addEventListener("keydown", this.marqueeCommand, true); @@ -63,6 +85,10 @@ export class MarqueeView extends React.Component<MarqueeViewProps> this._lastX = e.pageX; this._lastY = e.pageY; if (!e.cancelBubble) { + if (Math.abs(this._downX - e.clientX) > 4 || Math.abs(this._downY - e.clientY) > 4) { + this._showOnUp = false; + PreviewCursor.Visible = false; + } if (!this._used && e.buttons === 1 && !e.altKey && !e.metaKey && (Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) { this._visible = true; @@ -76,11 +102,16 @@ export class MarqueeView extends React.Component<MarqueeViewProps> onPointerUp = (e: PointerEvent): void => { this.cleanupInteractions(true); this._visible = false; - let mselect = this.marqueeSelect(); - if (!e.shiftKey) { - SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document); + if (this._showOnUp) { + PreviewCursor.Show(this.hideCursor, this._downX, this._downY); + document.addEventListener("keypress", this.onKeyPress, false); + } else { + let mselect = this.marqueeSelect(); + if (!e.shiftKey) { + SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document); + } + this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]); } - this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]); } intersectRect(r1: { left: number, top: number, width: number, height: number }, diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss deleted file mode 100644 index 7a67c29bf..000000000 --- a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss +++ /dev/null @@ -1,27 +0,0 @@ - -.previewCursor { - color: black; - position: absolute; - transform-origin: left top; - top: 0; - left:0; - pointer-events: none; -} -.previewCursorView { - top: 0; - left:0; - position: absolute; - width:100%; - height:100%; -} - -//this is an animation for the blinking cursor! -// @keyframes blink { -// 0% {opacity: 0} -// 49%{opacity: 0} -// 50% {opacity: 1} -// } - -// #previewCursor { -// animation: blink 1s infinite; -// }
\ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx deleted file mode 100644 index 64da8ecc6..000000000 --- a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { action, observable, trace, computed, reaction } from "mobx"; -import { observer } from "mobx-react"; -import { Document } from "../../../../fields/Document"; -import { Documents } from "../../../documents/Documents"; -import { Transform } from "../../../util/Transform"; -import { CollectionFreeFormView } from "./CollectionFreeFormView"; -import "./PreviewCursor.scss"; -import React = require("react"); -import { Main, PreviewCursorPrompt } from "../../Main"; - - -export interface PreviewCursorProps { - getTransform: () => Transform; - container: CollectionFreeFormView; - addLiveTextDocument: (doc: Document) => void; -} - -@observer -export class PreviewCursor extends React.Component<PreviewCursorProps> { - @observable _lastX: number = 0; - @observable _lastY: number = 0; - @observable public DownX: number = 0; - @observable public DownY: number = 0; - _showOnUp: boolean = false; - - @action - cleanupInteractions = () => { - document.removeEventListener("pointerup", this.onPointerUp, true); - document.removeEventListener("pointermove", this.onPointerMove, true); - } - - @action - onPointerDown = (e: React.PointerEvent) => { - if (e.button === 0 && this.props.container.props.active()) { - document.removeEventListener("keypress", this.onKeyPress, false); - this._showOnUp = true; - this.DownX = e.pageX; - this.DownY = e.pageY; - document.addEventListener("pointerup", this.onPointerUp, true); - document.addEventListener("pointermove", this.onPointerMove, true); - } - } - @action - onPointerMove = (e: PointerEvent): void => { - if (Math.abs(this.DownX - e.clientX) > 4 || Math.abs(this.DownY - e.clientY) > 4) { - this._showOnUp = false; - PreviewCursorPrompt.Visible = false; - } - } - - onPointerUp = (e: PointerEvent): void => { - if (this._showOnUp) { - PreviewCursorPrompt.Show(this.hideCursor, this.DownX, this.DownY); - document.addEventListener("keypress", this.onKeyPress, false); - } - this.cleanupInteractions(); - } - - @action - onKeyPress = (e: KeyboardEvent) => { - // Mixing events between React and Native is finicky. In FormattedTextBox, we set the - // DASHFormattedTextBoxHandled flag when a text box consumes a key press so that we can ignore - // the keyPress here. - //if not these keys, make a textbox if preview cursor is active! - if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) { - //make textbox and add it to this collection - let [x, y] = this.props.getTransform().transformPoint(this.DownX, this.DownY); - let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "typed text" }); - this.props.addLiveTextDocument(newBox); - PreviewCursorPrompt.Visible = false; - e.stopPropagation(); - } - } - - hideCursor = () => { - document.removeEventListener("keypress", this.onKeyPress, false); - } - render() { - return ( - <div className="previewCursorView" onPointerDown={this.onPointerDown}> - {this.props.children} - </div> - ); - } -}
\ No newline at end of file |