diff options
Diffstat (limited to 'src/client/views/collections/collectionFreeForm')
7 files changed, 192 insertions, 109 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index 9a864078a..a4fd5384f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -1,15 +1,15 @@ -import { Doc, Field, FieldResult, WidthSym, HeightSym } from "../../../../new_fields/Doc"; -import { NumCast, StrCast, Cast } from "../../../../new_fields/Types"; +import { Doc, Field, FieldResult, WidthSym, HeightSym } from "../../../../fields/Doc"; +import { NumCast, StrCast, Cast } from "../../../../fields/Types"; import { ScriptBox } from "../../ScriptBox"; import { CompileScript } from "../../../util/Scripting"; -import { ScriptField } from "../../../../new_fields/ScriptField"; +import { ScriptField } from "../../../../fields/ScriptField"; import { OverlayView, OverlayElementOptions } from "../../OverlayView"; import { emptyFunction, aggregateBounds } from "../../../../Utils"; import React = require("react"); -import { Id, ToString } from "../../../../new_fields/FieldSymbols"; -import { ObjectField } from "../../../../new_fields/ObjectField"; -import { RefField } from "../../../../new_fields/RefField"; -import { listSpec } from "../../../../new_fields/Schema"; +import { Id, ToString } from "../../../../fields/FieldSymbols"; +import { ObjectField } from "../../../../fields/ObjectField"; +import { RefField } from "../../../../fields/RefField"; +import { listSpec } from "../../../../fields/Schema"; export interface ViewDefBounds { type: string; @@ -25,6 +25,7 @@ export interface ViewDefBounds { fontSize?: number; highlight?: boolean; color?: string; + opacity?: number; replica?: string; pair?: { layout: Doc, data?: Doc }; } @@ -37,6 +38,7 @@ export interface PoolData { width?: number; height?: number; color?: string; + opacity?: number; transition?: string; highlight?: boolean; replica: string; @@ -416,7 +418,7 @@ function normalizeResults( height: newPosRaw.height! * scale, pair: ele[1].pair }; - poolData.set(newPos.pair.layout[Id] + (newPos.replica || ""), { transition: "transform 1s", ...newPos }); + poolData.set(newPos.pair.layout[Id] + (newPos.replica || ""), { transition: "all 1s", ...newPos }); } }); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index ba71aff32..f3fc04752 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -1,5 +1,5 @@ import { observer } from "mobx-react"; -import { Doc } from "../../../../new_fields/Doc"; +import { Doc } from "../../../../fields/Doc"; import { Utils } from '../../../../Utils'; import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinkView.scss"; @@ -7,8 +7,8 @@ import React = require("react"); import v5 = require("uuid/v5"); import { DocumentType } from "../../../documents/DocumentTypes"; import { observable, action, reaction, IReactionDisposer } from "mobx"; -import { StrCast, Cast } from "../../../../new_fields/Types"; -import { Id } from "../../../../new_fields/FieldSymbols"; +import { StrCast, Cast } from "../../../../fields/Types"; +import { Id } from "../../../../fields/FieldSymbols"; import { SnappingManager } from "../../../util/SnappingManager"; export interface CollectionFreeFormLinkViewProps { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 1208fb324..ae81b4b36 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -1,7 +1,7 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../../new_fields/Doc"; -import { Id } from "../../../../new_fields/FieldSymbols"; +import { Doc } from "../../../../fields/Doc"; +import { Id } from "../../../../fields/FieldSymbols"; import { DocumentManager } from "../../../util/DocumentManager"; import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinksView.scss"; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx index 9a5b2c27c..548ad78a5 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx @@ -1,16 +1,16 @@ import { observer } from "mobx-react"; import * as mobxUtils from 'mobx-utils'; -import CursorField from "../../../../new_fields/CursorField"; -import { listSpec } from "../../../../new_fields/Schema"; -import { Cast } from "../../../../new_fields/Types"; +import CursorField from "../../../../fields/CursorField"; +import { listSpec } from "../../../../fields/Schema"; +import { Cast } from "../../../../fields/Types"; import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; import { CollectionViewProps } from "../CollectionSubView"; import "./CollectionFreeFormView.scss"; import React = require("react"); import v5 = require("uuid/v5"); import { computed } from "mobx"; -import { FieldResult } from "../../../../new_fields/Doc"; -import { List } from "../../../../new_fields/List"; +import { FieldResult } from "../../../../fields/Doc"; +import { List } from "../../../../fields/List"; @observer export class CollectionFreeFormRemoteCursors extends React.Component<CollectionViewProps> { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 60c39c825..7a84fcde1 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -41,6 +41,24 @@ // touch action none means that the browser will handle none of the touch actions. this allows us to implement our own actions. touch-action: none; + .fwdKeyframe, .numKeyframe, .backKeyframe{ + cursor: pointer; + position: absolute; + width: 20; + height:20; + bottom:0; + background:gray; + } + .backKeyframe { + right:45; + } + .numKeyframe { + right:25; + } + .fwdKeyframe { + right:5; + } + .collectionfreeformview-placeholder { background: gray; width: 100%; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c3a77841e..0b61aad8a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -4,18 +4,18 @@ import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrows import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, _allowStateChangesInsideComputed } from "mobx"; import { observer } from "mobx-react"; import { computedFn } from "mobx-utils"; -import { Doc, HeightSym, Opt, WidthSym, DocListCast } from "../../../../new_fields/Doc"; -import { documentSchema, collectionSchema } from "../../../../new_fields/documentSchemas"; -import { Id } from "../../../../new_fields/FieldSymbols"; -import { InkData, InkField, InkTool, PointData } from "../../../../new_fields/InkField"; -import { List } from "../../../../new_fields/List"; -import { RichTextField } from "../../../../new_fields/RichTextField"; -import { createSchema, listSpec, makeInterface } from "../../../../new_fields/Schema"; -import { ScriptField } from "../../../../new_fields/ScriptField"; -import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../new_fields/Types"; -import { TraceMobx } from "../../../../new_fields/util"; +import { Doc, HeightSym, Opt, WidthSym, DocListCast } from "../../../../fields/Doc"; +import { documentSchema, collectionSchema } from "../../../../fields/documentSchemas"; +import { Id } from "../../../../fields/FieldSymbols"; +import { InkData, InkField, InkTool, PointData } from "../../../../fields/InkField"; +import { List } from "../../../../fields/List"; +import { RichTextField } from "../../../../fields/RichTextField"; +import { createSchema, listSpec, makeInterface } from "../../../../fields/Schema"; +import { ScriptField, ComputedField } from "../../../../fields/ScriptField"; +import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types"; +import { TraceMobx } from "../../../../fields/util"; import { GestureUtils } from "../../../../pen-gestures/GestureUtils"; -import { aggregateBounds, intersectRect, returnOne, Utils, returnZero, returnFalse } from "../../../../Utils"; +import { aggregateBounds, intersectRect, returnOne, Utils, returnZero, returnFalse, numberRange } from "../../../../Utils"; import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { DocServer } from "../../../DocServer"; import { Docs } from "../../../documents/Documents"; @@ -46,7 +46,7 @@ import React = require("react"); import { CollectionViewType } from "../CollectionView"; import { Timeline } from "../../animationtimeline/Timeline"; import { SnappingManager } from "../../../util/SnappingManager"; -import GestureOverlay from "../../GestureOverlay"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); @@ -54,6 +54,8 @@ export const panZoomSchema = createSchema({ _panX: "number", _panY: "number", scale: "number", + currentTimecode: "number", + displayTimecode: "number", arrangeScript: ScriptField, arrangeInit: ScriptField, useClusters: "boolean", @@ -124,7 +126,11 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed this.addDocument(newBox); } - private addDocument = (newBox: Doc | Doc[]) => { + addDocument = (newBox: Doc | Doc[]) => { + if (this.Document.currentTimecode !== undefined && !this.props.isAnnotationOverlay) { + CollectionFreeFormDocumentView.setupKeyframes((newBox instanceof Doc) ? [newBox] : newBox, this.Document.currentTimecode, this.props.Document); + } + if (newBox instanceof Doc) { const added = this.props.addDocument(newBox); added && this.bringToFront(newBox); @@ -135,6 +141,31 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P // bcz: deal with clusters } } + + @undoBatch + @action + nextKeyframe = (): void => { + const currentTimecode = this.Document.currentTimecode; + if (currentTimecode === undefined) { + this.Document.currentTimecode = 0; + CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0, this.props.Document); + } + CollectionFreeFormDocumentView.updateKeyframe(this.childDocs, currentTimecode || 0); + this.Document.currentTimecode = Math.max(0, (currentTimecode || 0) + 1); + this.Document.lastTimecode = Math.max(NumCast(this.Document.currentTimecode), NumCast(this.Document.lastTimecode)); + } + @undoBatch + @action + prevKeyframe = (): void => { + const currentTimecode = this.Document.currentTimecode; + if (currentTimecode === undefined) { + this.Document.currentTimecode = 0; + CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0, this.props.Document); + } + CollectionFreeFormDocumentView.gotoKeyframe(this.childDocs.slice()); + this.Document.currentTimecode = Math.max(0, (currentTimecode || 0) - 1); + } + private selectDocuments = (docs: Doc[]) => { SelectionManager.DeselectAll(); docs.map(doc => DocumentManager.Instance.getDocumentView(doc)).map(dv => dv && SelectionManager.SelectDoc(dv, true)); @@ -175,8 +206,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P for (let i = 0; i < droppedDocs.length; i++) { const d = droppedDocs[i]; const layoutDoc = Doc.Layout(d); - d.x = x + NumCast(d.x) - dropX; - d.y = y + NumCast(d.y) - dropY; + if (this.Document.currentTimecode !== undefined && !this.props.isAnnotationOverlay) { + CollectionFreeFormDocumentView.setValues(this.Document.currentTimecode, d, x + NumCast(d.x) - dropX, y + NumCast(d.y) - dropY, Cast(d.opacity, "number", null)); + } else { + d.x = x + NumCast(d.x) - dropX; + d.y = y + NumCast(d.y) - dropY; + } if (!NumCast(layoutDoc._width)) { layoutDoc._width = 300; } @@ -735,7 +770,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P @action onPointerWheel = (e: React.WheelEvent): void => { - if (this.props.Document.lockedTransform || this.props.Document.inOverlay) return; + if (this.layoutDoc._lockedTransform || this.props.Document.inOverlay) return; if (!e.ctrlKey && this.props.Document.scrollHeight !== undefined) { // things that can scroll vertically should do that instead of zooming e.stopPropagation(); } @@ -771,7 +806,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P else if (ranges.yrange.max <= (panY - panelDim[1] / 2)) panY = ranges.yrange.min - panelDim[1] / 2; } } - if (!this.Document.lockedTransform || this.Document.inOverlay) { + if (!this.layoutDoc._lockedTransform || this.Document.inOverlay) { this.Document.panTransformType = panType; const scale = this.getLocalTransform().inverse().Scale; const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX)); @@ -944,10 +979,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P return { x: 0, y: 0, transition: "transform 1s", ...result, pair: params.pair, replica: "" }; } const layoutDoc = Doc.Layout(params.pair.layout); - const { x, y, z, color, zIndex } = params.pair.layout; + const { x, y, opacity } = this.Document.currentTimecode === undefined ? params.pair.layout : + CollectionFreeFormDocumentView.getValues(params.pair.layout, this.Document.currentTimecode || 0); + const { z, color, zIndex } = params.pair.layout; return { x: NumCast(x), y: NumCast(y), z: Cast(z, "number"), color: StrCast(color), zIndex: Cast(zIndex, "number"), - transition: StrCast(layoutDoc.transition), + transition: StrCast(layoutDoc.transition), opacity: Cast(opacity, "number", null), width: Cast(layoutDoc._width, "number"), height: Cast(layoutDoc._height, "number"), pair: params.pair, replica: "" }; } @@ -1007,8 +1044,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P doFreeformLayout(poolData: Map<string, PoolData>) { const layoutDocs = this.childLayoutPairs.map(pair => pair.layout); const initResult = this.Document.arrangeInit && this.Document.arrangeInit.script.run({ docs: layoutDocs, collection: this.Document }, console.log); - const state = initResult && initResult.success ? initResult.result.scriptState : undefined; - const elements = initResult && initResult.success ? this.viewDefsToJSX(initResult.result.views) : []; + const state = initResult?.success ? initResult.result.scriptState : undefined; + const elements = initResult?.success ? this.viewDefsToJSX(initResult.result.views) : []; this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map((pair, i) => { const pos = this.getCalculatedPositions({ pair, index: i, collection: this.Document, docs: layoutDocs, state }); @@ -1036,11 +1073,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P const { newPool, computedElementData } = this.doInternalLayoutComputation; const array = Array.from(newPool.entries()); runInAction(() => { - for (let i = 0; i < array.length; i++) { - const entry = array[i]; + for (const entry of array) { const lastPos = this._cachedPool.get(entry[0]); // last computed pos const newPos = entry[1]; - if (!lastPos || newPos.x !== lastPos.x || newPos.y !== lastPos.y || newPos.z !== lastPos.z || newPos.zIndex !== lastPos.zIndex) { + if (!lastPos || newPos.opacity !== lastPos.opacity || newPos.x !== lastPos.x || newPos.y !== lastPos.y || newPos.z !== lastPos.z || newPos.zIndex !== lastPos.zIndex) { this._layoutPoolData.set(entry[0], newPos); } if (!lastPos || newPos.height !== lastPos.height || newPos.width !== lastPos.width) { @@ -1064,7 +1100,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P this.backgroundActive ? true : (this.props.viewDefDivClick || (engine === "pass" && !this.props.isSelected(true))) ? false : undefined} - jitterRotation={NumCast(this.props.Document._jitterRotation)} + jitterRotation={NumCast(this.props.Document._jitterRotation) || ((Doc.UserDoc().renderStyle === "comic" ? 10 : 0))} //fitToBox={this.props.fitToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this fitToBox={BoolCast(this.props.freezeChildDimensions)} // bcz: check this FreezeDimensions={BoolCast(this.props.freezeChildDimensions)} @@ -1134,6 +1170,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth(), this.props.NativeHeight()); } + @undoBatch + @action + toggleLockTransform = (): void => { + this.layoutDoc._lockedTransform = this.layoutDoc._lockedTransform ? undefined : true; + } + private thumbIdentifier?: number; onContextMenu = (e: React.MouseEvent) => { @@ -1154,6 +1196,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P optionItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" }); optionItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" }); this.props.ContainingCollectionView && optionItems.push({ description: "Promote Collection", event: this.promoteCollection, icon: "table" }); + optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" }); optionItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" }); // layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" }); optionItems.push({ @@ -1299,18 +1342,17 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P render() { TraceMobx(); const clientRect = this._mainCont?.getBoundingClientRect(); - // update the actual dimensions of the collection so that they can inquired (e.g., by a minimap) - // this.Document.fitX = this.contentBounds && this.contentBounds.x; - // this.Document.fitY = this.contentBounds && this.contentBounds.y; - // this.Document.fitW = this.contentBounds && (this.contentBounds.r - this.contentBounds.x); - // this.Document.fitH = this.contentBounds && (this.contentBounds.b - this.contentBounds.y); - // if isAnnotationOverlay is set, then children will be stored in the extension document for the fieldKey. - // otherwise, they are stored in fieldKey. All annotations to this document are stored in the extension document - return <div className={"collectionfreeformview-container"} - ref={this.createDashEventsTarget} + return <div className={"collectionfreeformview-container"} ref={this.createDashEventsTarget} onPointerOver={this.onPointerOver} - onWheel={this.onPointerWheel} onClick={this.onClick} //pointerEvents: DraggingManager.GetIsDragging() ? "all" : undefined, - onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onExternalDrop.bind(this)} onContextMenu={this.onContextMenu} + onWheel={this.onPointerWheel} + onClick={this.onClick} + onPointerDown={this.onPointerDown} + onPointerMove={this.onCursorMove} + onDrop={this.onExternalDrop.bind(this)} + onDragOver={e => { + e.preventDefault(); + }} + onContextMenu={this.onContextMenu} style={{ pointerEvents: this.backgroundEvents ? "all" : undefined, transform: this.contentScaling ? `scale(${this.contentScaling})` : "", @@ -1321,12 +1363,22 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P {!this.Document._LODdisable && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ? this.placeholder : this.marqueeView} <CollectionFreeFormOverlayView elements={this.elementFunc} /> - + {this.isAnnotationOverlay || !this.props.isSelected() ? (null) : + <> + <div key="back" className="backKeyframe" onClick={this.prevKeyframe}> + <FontAwesomeIcon icon={"caret-left"} size={"lg"} /> + </div> + <div key="num" className="numKeyframe" > + {NumCast(this.props.Document.currentTimecode)} + </div> + <div key="fwd" className="fwdKeyframe" onClick={this.nextKeyframe}> + <FontAwesomeIcon icon={"caret-right"} size={"lg"} /> + </div> + </>} <div className={"pullpane-indicator"} style={{ display: this._pullDirection ? "block" : "none", top: clientRect ? this._pullDirection === "bottom" ? this._pullCoords[1] - clientRect.y : 0 : "auto", - // left: clientRect ? this._pullDirection === "right" ? this._pullCoords[0] - clientRect.x - MainView.Instance.flyoutWidth : 0 : "auto", left: clientRect ? this._pullDirection === "right" ? this._pullCoords[0] - clientRect.x : 0 : "auto", width: clientRect ? this._pullDirection === "left" ? this._pullCoords[0] - clientRect.left : this._pullDirection === "right" ? clientRect.right - this._pullCoords[0] : clientRect.width : 0, height: clientRect ? this._pullDirection === "top" ? this._pullCoords[1] - clientRect.top : this._pullDirection === "bottom" ? clientRect.bottom - this._pullCoords[1] : clientRect.height : 0, diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 659509663..0244dfc56 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,11 +1,11 @@ import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc, Opt } from "../../../../new_fields/Doc"; -import { InkData, InkField } from "../../../../new_fields/InkField"; -import { List } from "../../../../new_fields/List"; -import { RichTextField } from "../../../../new_fields/RichTextField"; -import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField"; -import { Cast, FieldValue, NumCast, StrCast } from "../../../../new_fields/Types"; +import { Doc, Opt } from "../../../../fields/Doc"; +import { InkData, InkField } from "../../../../fields/InkField"; +import { List } from "../../../../fields/List"; +import { RichTextField } from "../../../../fields/RichTextField"; +import { SchemaHeaderField } from "../../../../fields/SchemaHeaderField"; +import { Cast, FieldValue, NumCast, StrCast } from "../../../../fields/Types"; import { Utils } from "../../../../Utils"; import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { Docs, DocumentOptions, DocUtils } from "../../../documents/Documents"; @@ -20,7 +20,6 @@ import { CollectionView } from "../CollectionView"; import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; import "./MarqueeView.scss"; import React = require("react"); -import { InteractionUtils } from "../../../util/InteractionUtils"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -66,58 +65,69 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque //make textbox and add it to this collection // tslint:disable-next-line:prefer-const let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY); - if (e.key === ":") { - DocUtils.addDocumentCreatorMenuItems(this.props.addLiveTextDocument, this.props.addDocument, x, y); + if (e.key === "?") { + ContextMenu.Instance.setDefaultItem("?", (str: string) => { + const textDoc = Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { + _width: 200, x, y, _nativeHeight: 962, _nativeWidth: 800, isAnnotating: false, + title: "bing", UseCors: true + }); + this.props.addDocTab(textDoc, "onRight"); + }); ContextMenu.Instance.displayMenu(this._downX, this._downY); - } else if (e.key === "q" && e.ctrlKey) { - e.preventDefault(); - (async () => { - const text: string = await navigator.clipboard.readText(); - const ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); - for (let i = 0; i < ns.length - 1; i++) { - while (!(ns[i].trim() === "" || ns[i].endsWith("-\r") || ns[i].endsWith("-") || - ns[i].endsWith(";\r") || ns[i].endsWith(";") || - ns[i].endsWith(".\r") || ns[i].endsWith(".") || - ns[i].endsWith(":\r") || ns[i].endsWith(":")) && i < ns.length - 1) { - const sub = ns[i].endsWith("\r") ? 1 : 0; - const br = ns[i + 1].trim() === ""; - ns.splice(i, 2, ns[i].substr(0, ns[i].length - sub) + ns[i + 1].trimLeft()); - if (br) break; + } else + if (e.key === ":") { + DocUtils.addDocumentCreatorMenuItems(this.props.addLiveTextDocument, this.props.addDocument, x, y); + + ContextMenu.Instance.displayMenu(this._downX, this._downY); + } else if (e.key === "q" && e.ctrlKey) { + e.preventDefault(); + (async () => { + const text: string = await navigator.clipboard.readText(); + const ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); + for (let i = 0; i < ns.length - 1; i++) { + while (!(ns[i].trim() === "" || ns[i].endsWith("-\r") || ns[i].endsWith("-") || + ns[i].endsWith(";\r") || ns[i].endsWith(";") || + ns[i].endsWith(".\r") || ns[i].endsWith(".") || + ns[i].endsWith(":\r") || ns[i].endsWith(":")) && i < ns.length - 1) { + const sub = ns[i].endsWith("\r") ? 1 : 0; + const br = ns[i + 1].trim() === ""; + ns.splice(i, 2, ns[i].substr(0, ns[i].length - sub) + ns[i + 1].trimLeft()); + if (br) break; + } + } + ns.map(line => { + const indent = line.search(/\S|$/); + const newBox = Docs.Create.TextDocument(line, { _width: 200, _height: 35, x: x + indent / 3 * 10, y: y, title: line }); + this.props.addDocument(newBox); + y += 40 * this.props.getTransform().Scale; + }); + })(); + } else if (e.key === "b" && e.ctrlKey) { + e.preventDefault(); + navigator.clipboard.readText().then(text => { + const ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); + if (ns.length === 1 && text.startsWith("http")) { + this.props.addDocument(Docs.Create.ImageDocument(text, { _nativeWidth: 300, _width: 300, x: x, y: y }));// paste an image from its URL in the paste buffer + } else { + this.pasteTable(ns, x, y); } - } - ns.map(line => { - const indent = line.search(/\S|$/); - const newBox = Docs.Create.TextDocument(line, { _width: 200, _height: 35, x: x + indent / 3 * 10, y: y, title: line }); - this.props.addDocument(newBox); - y += 40 * this.props.getTransform().Scale; }); - })(); - } else if (e.key === "b" && e.ctrlKey) { - e.preventDefault(); - navigator.clipboard.readText().then(text => { - const ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); - if (ns.length === 1 && text.startsWith("http")) { - this.props.addDocument(Docs.Create.ImageDocument(text, { _nativeWidth: 300, _width: 300, x: x, y: y }));// paste an image from its URL in the paste buffer - } else { - this.pasteTable(ns, x, y); + } else if (!e.ctrlKey) { + FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout ? e.key : ""; + const tbox = Docs.Create.TextDocument("", { + _width: 200, _height: 100, x: x, y: y, _autoHeight: true, _fontSize: NumCast(Doc.UserDoc().fontSize), + _fontFamily: StrCast(Doc.UserDoc().fontFamily), _backgroundColor: StrCast(Doc.UserDoc().backgroundColor), + title: "-typed text-" + }); + const template = FormattedTextBox.DefaultLayout; + if (template instanceof Doc) { + tbox._width = NumCast(template._width); + tbox.layoutKey = "layout_" + StrCast(template.title); + Doc.GetProto(tbox)[StrCast(tbox.layoutKey)] = template; } - }); - } else if (!e.ctrlKey) { - FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout ? e.key : ""; - const tbox = Docs.Create.TextDocument("", { - _width: 200, _height: 100, x: x, y: y, _autoHeight: true, _fontSize: NumCast(Doc.UserDoc().fontSize), - _backgroundColor: StrCast(Doc.UserDoc().backgroundColor), - title: "-typed text-" - }); - const template = FormattedTextBox.DefaultLayout; - if (template instanceof Doc) { - tbox._width = NumCast(template._width); - tbox.layoutKey = "layout_" + StrCast(template.title); - Doc.GetProto(tbox)[StrCast(tbox.layoutKey)] = template; + this.props.addLiveTextDocument(tbox); } - this.props.addLiveTextDocument(tbox); - } e.stopPropagation(); } //heuristically converts pasted text into a table. @@ -614,6 +624,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque render() { return <div className="marqueeView" style={{ overflow: StrCast(this.props.Document._overflow), cursor: MarqueeView.DragMarquee && this ? "crosshair" : "hand" }} + onDragOver={e => e.preventDefault()} onScroll={(e) => e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} onClick={this.onClick} onPointerDown={this.onPointerDown}> {this._visible ? this.marqueeDiv : null} {this.props.children} |
