From 4823e1c7ceb0e58cdb515e2bb013632d81767ae3 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Tue, 5 Apr 2022 20:03:36 -0400 Subject: added basic grouping when exiting pen mode --- src/client/views/nodes/button/FontIconBox.tsx | 83 ++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes/button') diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index ca13590de..fc0cc87ca 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -5,17 +5,19 @@ import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { ColorState, SketchPicker } from 'react-color'; -import { Doc, StrListCast } from '../../../../fields/Doc'; +import { DataSym, Doc, DocListCast, HeightSym, StrListCast, WidthSym } from '../../../../fields/Doc'; import { InkTool } from '../../../../fields/InkField'; import { createSchema } from '../../../../fields/Schema'; import { ScriptField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { WebField } from '../../../../fields/URLField'; -import { Utils } from '../../../../Utils'; +import { aggregateBounds, Utils } from '../../../../Utils'; import { DocumentType } from '../../../documents/DocumentTypes'; +import { DocumentManager } from '../../../util/DocumentManager'; import { ScriptingGlobals } from "../../../util/ScriptingGlobals"; import { SelectionManager } from '../../../util/SelectionManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; +import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { CollectionViewType } from '../../collections/CollectionView'; import { ContextMenu } from '../../ContextMenu'; import { DocComponent } from '../../DocComponent'; @@ -701,6 +703,80 @@ ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) { **/ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boolean) { + // if the global collection has documents + // const unallocInk: Doc[] = DocListCast(Doc.UserDoc().unallocatedInkDocs) + // if (unallocInk.length) { + // get collection freeform view from the ink documents + // with that, we can call gesture overlay getCollection on the view + // use getDocumentView + // You would want to call: DocumentManager.Instance.getDocumentView + // const docView = DocumentManager.Instance.getDocumentView(unallocInk[0]) + // if (docView) { + // docView.props.ContainingCollectionView + // } + + // easy way without backing up to the server + // + CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { + const selected = ffView.unprocessedDocs; + ffView._marqueeViewRef.current?.getCollection(ffView.unprocessedDocs, undefined, [], true); + // loop through selected an get the bound + const bounds: { x: number, y: number, width?: number, height?: number }[] = [] + + selected.map(action(d => { + const x = NumCast(d.x); + const y = NumCast(d.y); + const width = d[WidthSym](); + const height = d[HeightSym](); + bounds.push({x, y, width, height}); + })) + + const aggregBounds = aggregateBounds(bounds, 0, 0); + const marqViewRef = ffView._marqueeViewRef.current; + + // set the vals for bounds in marqueeView + if (marqViewRef) { + marqViewRef._downX = aggregBounds.x; + marqViewRef._downY = aggregBounds.y; + marqViewRef._lastX = aggregBounds.r; + marqViewRef._lastY = aggregBounds.b; + } + + selected.map(action(d => { + const dx = NumCast(d.x); + const dy = NumCast(d.y); + delete d.x; + delete d.y; + delete d.activeFrame; + delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + // TODO: nda - actually calc the bounds + // get the bounds + // d.x = dx - aggregBounds.x; + // d.y = dy - aggregBounds.y; + + // d.x = dx - aggregBounds.x ; + // d.y = dy; + if (marqViewRef?.Bounds) { + d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds?.width / 2; + d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; + } + console.log(d[DataSym], d.x, d.y) + return d; + })); + ffView.props.removeDocument?.(selected); + // TODO: nda - this is the code to actually get a new grouped collection + // const newCollection = ffView._marqueeViewRef.current?.getCollection(ffView.unprocessedDocs, undefined, [], true); + const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); + console.log("newcoll:", newCollection?.[DataSym]); + + // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs + newCollection && ffView.props.addDocument?.(newCollection); + ffView.unprocessedDocs = []; + }); + + CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); + if (checkResult) { return ((Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ? Colors.MEDIUM_BLUE : "transparent"; @@ -716,6 +792,9 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole } else if (tool) { // pen or eraser if (Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance.InkShape) { Doc.UserDoc().activeInkTool = InkTool.None; + } else if (tool == "write") { + console.log("write mode selected - create groupDoc here!") + // } else { Doc.UserDoc().activeInkTool = tool; GestureOverlay.Instance.InkShape = ""; -- cgit v1.2.3-70-g09d2 From ef63a072a586f51e8fa51b4684987491287540b2 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Thu, 7 Apr 2022 17:21:01 -0400 Subject: added grouping and write mode vs pen mode --- src/client/util/CurrentUserUtils.ts | 4 +- src/client/views/GestureOverlay.tsx | 5 +- .../views/collections/CollectionDockingView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 12 +-- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/MapBox/MapBox.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 2 +- src/client/views/nodes/button/FontIconBox.tsx | 112 ++++++++++----------- src/client/views/pdf/PDFViewer.tsx | 2 +- src/fields/InkField.ts | 3 +- webpack.config.js | 2 +- 14 files changed, 77 insertions(+), 79 deletions(-) (limited to 'src/client/views/nodes/button') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 6cab8c100..f08f13bbc 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -1010,8 +1010,8 @@ export class CurrentUserUtils { static inkTools(doc: Doc) { const tools: Button[] = [ - { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen", click: 'setActiveInkTool("pen", _readOnly_)' }, - { title: "Mode", toolTip: "Mode (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen", click: 'setActiveInkTool("write", _readOnly_)' }, + { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", click: 'setActiveInkTool("pen", _readOnly_)' }, + { title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", click: 'setActiveInkTool("write", _readOnly_)' }, { title: "Eraser", toolTip: "Eraser (Ctrl+E)", btnType: ButtonType.ToggleButton, icon: "eraser", click: 'setActiveInkTool("eraser", _readOnly_)' }, // { title: "Highlighter", toolTip: "Highlighter (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", click: 'setActiveInkTool("highlighter")' }, { title: "Circle", toolTip: "Circle (Ctrl+Shift+C)", btnType: ButtonType.ToggleButton, icon: "circle", click: 'setActiveInkTool("circle", _readOnly_)' }, diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 87b006a93..53b360e60 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -491,7 +491,10 @@ export class GestureOverlay extends Touchable { @action onPointerDown = (e: React.PointerEvent) => { - if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || [InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || [InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool)) { + if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { + CurrentUserUtils.SelectedTool = InkTool.Write; + } this._points.push({ X: e.clientX, Y: e.clientY }); setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction); // if (CurrentUserUtils.SelectedTool === InkTool.Highlighter) SetActiveInkColor("rgba(245, 230, 95, 0.75)"); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 9e8374605..c9f55a7bd 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -358,7 +358,7 @@ export class CollectionDockingView extends CollectionSubView() { } } if (!e.nativeEvent.cancelBubble && !InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) && - ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool)) { e.stopPropagation(); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a694ca2b3..40164313c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -468,6 +468,8 @@ export class CollectionFreeFormView extends CollectionSubView e.preventDefault()} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7092b335c..2e822bb6a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -517,7 +517,7 @@ export class DocumentViewInternal extends DocComponent { // continue if the event hasn't been canceled AND we are using a mouse or this has an onClick or onDragStart function (meaning it is a button document) - if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || [InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool))) { + if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || [InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool))) { if (!InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { e.stopPropagation(); if (SelectionManager.IsSelected(this.props.DocumentView(), true) && this.props.Document._viewType !== CollectionViewType.Docking) e.preventDefault(); // goldenlayout needs to be able to move its tabs, so can't preventDefault for it @@ -550,7 +550,7 @@ export class DocumentViewInternal extends DocComponent { if (e.cancelBubble) return; - if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || [InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool))) return; + if ((InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || [InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool))) return; if ((this.props.isDocumentActive?.() || this.layoutDoc.onDragStart) && !this.layoutDoc._lockedPosition && !CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) { if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 0a4168698..a8da22b61 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -322,7 +322,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent; } marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool)) { setupMoveUpEvents(this, e, action(e => { MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index aa2130af5..9bf7c2e8c 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -471,7 +471,7 @@ export class MapBox extends ViewBoxAnnotatableComponent { - if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool)) { setupMoveUpEvents(this, e, action(e => { MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 33fdc4935..a5b8967c4 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -549,7 +549,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent { - if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + if (!e.altKey && e.button === 0 && this.layoutDoc._viewScale === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool)) { setupMoveUpEvents(this, e, action(e => { MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 7ff47107e..54c49ecad 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -529,7 +529,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { - if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool)) { setupMoveUpEvents(this, e, action(e => { MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index fc0cc87ca..7f3a667a9 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -13,6 +13,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields import { WebField } from '../../../../fields/URLField'; import { aggregateBounds, Utils } from '../../../../Utils'; import { DocumentType } from '../../../documents/DocumentTypes'; +import { CurrentUserUtils } from '../../../util/CurrentUserUtils'; import { DocumentManager } from '../../../util/DocumentManager'; import { ScriptingGlobals } from "../../../util/ScriptingGlobals"; import { SelectionManager } from '../../../util/SelectionManager'; @@ -717,64 +718,56 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole // easy way without backing up to the server // - CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { - const selected = ffView.unprocessedDocs; - ffView._marqueeViewRef.current?.getCollection(ffView.unprocessedDocs, undefined, [], true); - // loop through selected an get the bound - const bounds: { x: number, y: number, width?: number, height?: number }[] = [] - - selected.map(action(d => { - const x = NumCast(d.x); - const y = NumCast(d.y); - const width = d[WidthSym](); - const height = d[HeightSym](); - bounds.push({x, y, width, height}); - })) - - const aggregBounds = aggregateBounds(bounds, 0, 0); - const marqViewRef = ffView._marqueeViewRef.current; - - // set the vals for bounds in marqueeView - if (marqViewRef) { - marqViewRef._downX = aggregBounds.x; - marqViewRef._downY = aggregBounds.y; - marqViewRef._lastX = aggregBounds.r; - marqViewRef._lastY = aggregBounds.b; - } - - selected.map(action(d => { - const dx = NumCast(d.x); - const dy = NumCast(d.y); - delete d.x; - delete d.y; - delete d.activeFrame; - delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - // TODO: nda - actually calc the bounds - // get the bounds - // d.x = dx - aggregBounds.x; - // d.y = dy - aggregBounds.y; + if (CurrentUserUtils.SelectedTool === InkTool.Write) { + CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { + const selected = ffView.unprocessedDocs; + // loop through selected an get the bound + const bounds: { x: number, y: number, width?: number, height?: number }[] = [] - // d.x = dx - aggregBounds.x ; - // d.y = dy; - if (marqViewRef?.Bounds) { - d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds?.width / 2; - d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; - } - console.log(d[DataSym], d.x, d.y) - return d; - })); - ffView.props.removeDocument?.(selected); - // TODO: nda - this is the code to actually get a new grouped collection - // const newCollection = ffView._marqueeViewRef.current?.getCollection(ffView.unprocessedDocs, undefined, [], true); - const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); - console.log("newcoll:", newCollection?.[DataSym]); - - // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs - newCollection && ffView.props.addDocument?.(newCollection); - ffView.unprocessedDocs = []; - }); - + selected.map(action(d => { + const x = NumCast(d.x); + const y = NumCast(d.y); + const width = d[WidthSym](); + const height = d[HeightSym](); + bounds.push({x, y, width, height}); + })) + + const aggregBounds = aggregateBounds(bounds, 0, 0); + const marqViewRef = ffView._marqueeViewRef.current; + + // set the vals for bounds in marqueeView + if (marqViewRef) { + marqViewRef._downX = aggregBounds.x; + marqViewRef._downY = aggregBounds.y; + marqViewRef._lastX = aggregBounds.r; + marqViewRef._lastY = aggregBounds.b; + } + + selected.map(action(d => { + const dx = NumCast(d.x); + const dy = NumCast(d.y); + delete d.x; + delete d.y; + delete d.activeFrame; + delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + // TODO: nda - actually calc the bounds + // calculate pos based on bounds + if (marqViewRef?.Bounds) { + d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; + d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; + } + return d; + })); + ffView.props.removeDocument?.(selected); + // TODO: nda - this is the code to actually get a new grouped collection + const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); + + // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs + newCollection && ffView.props.addDocument?.(newCollection); + ffView.unprocessedDocs = []; + }); + } CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); if (checkResult) { @@ -793,8 +786,9 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole if (Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance.InkShape) { Doc.UserDoc().activeInkTool = InkTool.None; } else if (tool == "write") { - console.log("write mode selected - create groupDoc here!") - // + console.log("write mode selected - create groupDoc here!", tool) + Doc.UserDoc().activeInkTool = tool; + GestureOverlay.Instance.InkShape = ""; } else { Doc.UserDoc().activeInkTool = tool; GestureOverlay.Instance.InkShape = ""; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 1856c5353..37fbd7a1d 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -371,7 +371,7 @@ export class PDFViewer extends React.Component { if ((e.button !== 0 || e.altKey) && this.props.isContentActive(true)) { this._setPreviewCursor?.(e.clientX, e.clientY, true, false); } - if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { + if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.SelectedTool)) { this.props.select(false); MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts index 31024e805..c34e8f93d 100644 --- a/src/fields/InkField.ts +++ b/src/fields/InkField.ts @@ -11,7 +11,8 @@ export enum InkTool { Pen = "pen", Highlighter = "highlighter", Eraser = "eraser", - Stamp = "stamp" + Stamp = "stamp", + Write = "write" } diff --git a/webpack.config.js b/webpack.config.js index 3fd00bcf3..5a954db19 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -49,7 +49,7 @@ module.exports = { repl: ["./src/debug/Repl.tsx", 'webpack-hot-middleware/client?reload=true'], test: ["./src/debug/Test.tsx", 'webpack-hot-middleware/client?reload=true'], inkControls: ["./src/mobile/InkControls.tsx", 'webpack-hot-middleware/client?reload=true'], - mobileInterface: ["./src/mobile/MobileMain.tsx", 'webpack-hot-middleware/client?reload=true'], + mobileInterface: ["./src/client/views/Main.tsx", 'webpack-hot-middleware/client?reload=true'], }, devtool: "source-map", output: { -- cgit v1.2.3-70-g09d2 From 40d746706d4ac3d5c3302d1fe66e6ce1685251f1 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Thu, 7 Apr 2022 17:21:51 -0400 Subject: removed redundant commit --- src/client/views/nodes/button/FontIconBox.tsx | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'src/client/views/nodes/button') diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index 7f3a667a9..4b7540e1d 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -704,20 +704,6 @@ ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) { **/ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boolean) { - // if the global collection has documents - // const unallocInk: Doc[] = DocListCast(Doc.UserDoc().unallocatedInkDocs) - // if (unallocInk.length) { - // get collection freeform view from the ink documents - // with that, we can call gesture overlay getCollection on the view - // use getDocumentView - // You would want to call: DocumentManager.Instance.getDocumentView - // const docView = DocumentManager.Instance.getDocumentView(unallocInk[0]) - // if (docView) { - // docView.props.ContainingCollectionView - // } - - // easy way without backing up to the server - // if (CurrentUserUtils.SelectedTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { const selected = ffView.unprocessedDocs; @@ -751,7 +737,6 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole delete d.activeFrame; delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - // TODO: nda - actually calc the bounds // calculate pos based on bounds if (marqViewRef?.Bounds) { d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; -- cgit v1.2.3-70-g09d2 From b3424535cb746ff9fba35375d9abf07ba174dcf0 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Tue, 12 Apr 2022 18:07:49 -0400 Subject: made changes to ink grouping --- src/Utils.ts | 6 ++ src/client/views/GestureOverlay.tsx | 12 ++- .../collectionFreeForm/CollectionFreeFormView.tsx | 30 -------- src/client/views/nodes/button/FontIconBox.tsx | 85 ++++++++++++++++++++-- 4 files changed, 93 insertions(+), 40 deletions(-) (limited to 'src/client/views/nodes/button') diff --git a/src/Utils.ts b/src/Utils.ts index 6519b5d13..8d71ca6eb 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -5,6 +5,12 @@ import { Socket } from 'socket.io'; import { Colors } from './client/views/global/globalEnums'; import { Message } from './server/Message'; import Color = require('color'); +import { InkTool } from './fields/InkField'; +import { action } from 'mobx'; +import { CurrentUserUtils } from './client/util/CurrentUserUtils'; +import { CollectionFreeFormView } from './client/views/collections/collectionFreeForm'; +import { WidthSym, HeightSym } from './fields/Doc'; +import { NumCast } from './fields/Types'; export namespace Utils { export let DRAG_THRESHOLD = 4; diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 54fb50db9..24df3925b 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -24,6 +24,7 @@ import { RadialMenu } from "./nodes/RadialMenu"; import HorizontalPalette from "./Palette"; import { Touchable } from "./Touchable"; import TouchScrollableMenu, { TouchScrollableMenuItem } from "./TouchScrollableMenu"; +import { checkInksToGroup } from "./nodes/button/FontIconBox"; @observer export class GestureOverlay extends Touchable { @@ -82,6 +83,7 @@ export class GestureOverlay extends Touchable { const ntt: (React.Touch | Touch)[] = Array.from(e.targetTouches); const nct: (React.Touch | Touch)[] = Array.from(e.changedTouches); const nt: (React.Touch | Touch)[] = Array.from(e.touches); + console.log("getNewTouches"); this._hands.forEach((hand) => { for (let i = 0; i < e.targetTouches.length; i++) { const pt = e.targetTouches.item(i); @@ -108,6 +110,7 @@ export class GestureOverlay extends Touchable { } onReactTouchStart = (te: React.TouchEvent) => { + console.log("react touch start"); document.removeEventListener("touchmove", this.onReactHoldTouchMove); document.removeEventListener("touchend", this.onReactHoldTouchEnd); if (RadialMenu.Instance?._display === true) { @@ -204,6 +207,7 @@ export class GestureOverlay extends Touchable { } onReactTouchMove = (e: TouchEvent) => { + console.log("react touch move"); const nts: any = this.getNewTouches(e); this._holdTimer && clearTimeout(this._holdTimer); this._holdTimer = undefined; @@ -620,6 +624,7 @@ export class GestureOverlay extends Touchable { if (!actionPerformed) { const newPoints = this._points.reduce((p, pts) => { p.push([pts.X, pts.Y]); return p; }, [] as number[][]); newPoints.pop(); + console.log("getting to bezier math"); const controlPoints: { X: number, Y: number }[] = []; const bezierCurves = fitCurve(newPoints, 10); @@ -630,14 +635,15 @@ export class GestureOverlay extends Touchable { controlPoints.push({ X: curve[2][0], Y: curve[2][1] }); controlPoints.push({ X: curve[3][0], Y: curve[3][1] }); - } const dist = Math.sqrt((controlPoints[0].X - controlPoints.lastElement().X) * (controlPoints[0].X - controlPoints.lastElement().X) + (controlPoints[0].Y - controlPoints.lastElement().Y) * (controlPoints[0].Y - controlPoints.lastElement().Y)); if (controlPoints.length > 4 && dist < 10) controlPoints[controlPoints.length - 1] = controlPoints[0]; - this._points = controlPoints; - + this._points = controlPoints; + this.dispatchGesture(GestureUtils.Gestures.Stroke); + // TODO: nda - check inks to group here + checkInksToGroup(); } this._points = []; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 40164313c..f927c7934 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -441,13 +441,6 @@ export class CollectionFreeFormView extends CollectionSubView { + // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those + // find all inkDocs in ffView.unprocessedDocs that are within 200 pixels of each other + const inksToGroup = ffView.unprocessedDocs.filter(inkDoc => { + console.log(inkDoc.x, inkDoc.y); + }); + }); + } +} -ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boolean) { +export function createInkGroup(inksToGroup?: Doc[]) { + // TODO nda - if document being added to is a inkGrouping then we can just add to that group if (CurrentUserUtils.SelectedTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { + // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those const selected = ffView.unprocessedDocs; // loop through selected an get the bound const bounds: { x: number, y: number, width?: number, height?: number }[] = [] @@ -750,10 +759,72 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs newCollection && ffView.props.addDocument?.(newCollection); + // TODO: nda - will probably need to go through and only remove the unprocessed selected docs ffView.unprocessedDocs = []; }); } CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); +} + + +/** INK + * setActiveInkTool + * setStrokeWidth + * setStrokeColor + **/ + +ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boolean) { + createInkGroup(); + // if (CurrentUserUtils.SelectedTool === InkTool.Write) { + // CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { + // const selected = ffView.unprocessedDocs; + // // loop through selected an get the bound + // const bounds: { x: number, y: number, width?: number, height?: number }[] = [] + + // selected.map(action(d => { + // const x = NumCast(d.x); + // const y = NumCast(d.y); + // const width = d[WidthSym](); + // const height = d[HeightSym](); + // bounds.push({x, y, width, height}); + // })) + + // const aggregBounds = aggregateBounds(bounds, 0, 0); + // const marqViewRef = ffView._marqueeViewRef.current; + + // // set the vals for bounds in marqueeView + // if (marqViewRef) { + // marqViewRef._downX = aggregBounds.x; + // marqViewRef._downY = aggregBounds.y; + // marqViewRef._lastX = aggregBounds.r; + // marqViewRef._lastY = aggregBounds.b; + // } + + // selected.map(action(d => { + // const dx = NumCast(d.x); + // const dy = NumCast(d.y); + // delete d.x; + // delete d.y; + // delete d.activeFrame; + // delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + // delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + // // calculate pos based on bounds + // if (marqViewRef?.Bounds) { + // d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; + // d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; + // } + // return d; + // })); + // ffView.props.removeDocument?.(selected); + // // TODO: nda - this is the code to actually get a new grouped collection + // const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); + + // // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs + // newCollection && ffView.props.addDocument?.(newCollection); + // ffView.unprocessedDocs = []; + // }); + // } + // CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); if (checkResult) { return ((Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ? -- cgit v1.2.3-70-g09d2 From ab5a0bd7cee9366dabf4ce40bde89b67730da2a5 Mon Sep 17 00:00:00 2001 From: mehekj Date: Thu, 14 Apr 2022 18:06:34 -0400 Subject: auto transcribes on grouping --- src/client/views/InkTranscription.tsx | 50 ++++++++++------------ .../collectionFreeForm/CollectionFreeFormView.tsx | 29 +++++++------ src/client/views/nodes/button/FontIconBox.tsx | 33 +++++++------- 3 files changed, 57 insertions(+), 55 deletions(-) (limited to 'src/client/views/nodes/button') diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx index 4957446dc..ea5d5a1ec 100644 --- a/src/client/views/InkTranscription.tsx +++ b/src/client/views/InkTranscription.tsx @@ -5,7 +5,7 @@ import * as React from 'react'; import { Doc } from '../../fields/Doc'; import { InkData, InkField } from "../../fields/InkField"; import { Cast, NumCast, StrCast } from '../../fields/Types'; -import { Docs } from "../documents/Documents"; +import { DocumentType } from "../documents/DocumentTypes"; import './InkTranscription.scss'; export class InkTranscription extends React.Component { @@ -15,8 +15,7 @@ export class InkTranscription extends React.Component { @observable _mathRef: any; @observable _textRegister: any; @observable _textRef: any; - private addDocument?: (doc: Doc | Doc[]) => boolean; - private bounds: { x: number, y: number, width: number, height: number } = { x: 0, y: 0, width: 0, height: 0 }; + private currGroup?: Doc; constructor(props: Readonly<{}>) { super(props); @@ -27,9 +26,6 @@ export class InkTranscription extends React.Component { componentWillUnmount() { this._mathRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); this._textRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); - - this._mathRef.removeEventListener('changed', (e: any) => this.callExport(this._mathRef)); - this._textRef.removeEventListener('changed', (e: any) => this.callExport(this._textRef)); } @action @@ -58,15 +54,11 @@ export class InkTranscription extends React.Component { } } } - }, - triggers: { - exportContent: 'DEMAND' } }) : null; } r.addEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); - r.addEventListener('changed', (e: any) => this.callExport(this._mathRef)); return this._mathRef = r; } @@ -97,22 +89,22 @@ export class InkTranscription extends React.Component { } } } - }, - triggers: { - exportContent: 'DEMAND' } }) : null; } r.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); - r.addEventListener('changed', (e: any) => this.callExport(this._textRef)); return this._textRef = r; } - transcribeInk = (inkdocs: Doc[], math: boolean, bounds: { x: number, y: number, width: number, height: number }, addDocument?: (doc: Doc | Doc[]) => boolean) => { + transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => { + if (!groupDoc) return; + + const validInks = inkDocs.filter(s => s.type === DocumentType.INK); + const strokes: InkData[] = []; - inkdocs.filter(i => Cast(i.data, InkField)).forEach(i => { + validInks.filter(i => Cast(i.data, InkField)).forEach(i => { // TODO: interpolate missing times stamps const d = Cast(i.data, InkField, null); const left = Math.min(...d?.inkData.map(pd => pd.X) ?? [0]); @@ -120,8 +112,7 @@ export class InkTranscription extends React.Component { strokes.push(d.inkData.map(pd => ({ X: pd.X + NumCast(i.x) - left, Y: pd.Y + NumCast(i.y) - top, time: pd.time }))); }); - this.addDocument = addDocument; - this.bounds = bounds; + this.currGroup = groupDoc; const pointerData = { "events": strokes.map(stroke => this.inkJSON(stroke)) }; // console.log(JSON.stringify(pointerData)); @@ -135,12 +126,6 @@ export class InkTranscription extends React.Component { } } - callExport(ref: any) { - if (ref.editor.canExport) { - ref.editor.export_(); - } - } - inkJSON = (stroke: InkData) => { return { "pointerType": "PEN", @@ -159,15 +144,24 @@ export class InkTranscription extends React.Component { const latex = exports['application/x-latex']; console.log(latex); - this.addDocument?.(Docs.Create.EquationDocument({ title: latex, x: this.bounds.x + this.bounds.width, y: this.bounds.y, _width: this.bounds.width, _height: this.bounds.height })); + if (this.currGroup) { + this.currGroup.text = latex; + this.currGroup.title = latex; + } + + ref.editor.clear(); } else if (exports['text/plain']) { const text = exports['text/plain']; console.log(text); - this.addDocument?.(Docs.Create.TextDocument(text, { title: text, x: this.bounds.x + this.bounds.width, y: this.bounds.y, _width: this.bounds.width, _height: this.bounds.height })); - } - ref.editor.clear(); + if (this.currGroup) { + this.currGroup.text = text; + this.currGroup.title = text; + } + + ref.editor.clear(); + } } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c9465e7a4..023953658 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -98,7 +98,7 @@ export class CollectionFreeFormView extends CollectionSubView = new Map(); private _lastTap = 0; private _batch: UndoManager.Batch | undefined = undefined; - + // private isWritingMode: boolean = true; // private writingModeDocs: Doc[] = []; @@ -461,10 +461,10 @@ export class CollectionFreeFormView extends CollectionSubView(); @undoBatch onGesture = (e: Event, ge: GestureUtils.GestureEvent) => { @@ -521,11 +521,11 @@ export class CollectionFreeFormView extends CollectionSubView { return { X: pt.X, Y: pt.Y, time: times[i] } }); const inkDoc = Docs.Create.InkDocument(ActiveInkColor(), CurrentUserUtils.SelectedTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), strokes, { title: "ink stroke", x: B.x - ActiveInkWidth() / 2, y: B.y - ActiveInkWidth() / 2, _width: B.width + ActiveInkWidth(), _height: B.height + ActiveInkWidth() }); - if (CurrentUserUtils.SelectedTool === InkTool.Write) { - this.unprocessedDocs.push(inkDoc); - CollectionFreeFormView.collectionsWithUnprocessedInk.add(this); - } - this.addDocument(inkDoc); + if (CurrentUserUtils.SelectedTool === InkTool.Write) { + this.unprocessedDocs.push(inkDoc); + CollectionFreeFormView.collectionsWithUnprocessedInk.add(this); + } + this.addDocument(inkDoc); e.stopPropagation(); break; case GestureUtils.Gestures.Box: @@ -1577,9 +1577,14 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this.props.Document._isGroup) { - const inkdocs = this.childDocs.filter(s => s.type === DocumentType.INK); - InkTranscription.Instance.transcribeInk(inkdocs, math, { x: NumCast(this.layoutDoc.x) ?? 0, y: NumCast(this.layoutDoc.y) ?? 0, width: NumCast(this.layoutDoc._width) ?? 0, height: NumCast(this.layoutDoc._height) ?? 0 }, this.props.ContainingCollectionView?.addDocument); + if (this.props.Document._isGroup && this.props.Document.text) { + const text = StrCast(this.props.Document.text); + + const lines = text.split("\n"); + const width = 30 + 7 * Math.max(...lines.map(line => line.length)); + const height = 30 + 15 * lines.length; + + this.props.ContainingCollectionView?.addDocument(Docs.Create.TextDocument(text, { title: text, x: NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc._width) + 20, y: NumCast(this.layoutDoc.y), _width: width, _height: height })); } } diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index 862c16050..fc358f106 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -26,6 +26,7 @@ import { EditableView } from '../../EditableView'; import { GestureOverlay } from '../../GestureOverlay'; import { Colors } from '../../global/globalEnums'; import { ActiveFillColor, ActiveInkColor, ActiveInkWidth, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke'; +import { InkTranscription } from '../../InkTranscription'; import { StyleProp } from '../../StyleProvider'; import { FieldView, FieldViewProps } from '.././FieldView'; import { RichTextMenu } from '../formattedText/RichTextMenu'; @@ -702,9 +703,9 @@ export function checkInksToGroup() { if (CurrentUserUtils.SelectedTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those - // find all inkDocs in ffView.unprocessedDocs that are within 200 pixels of each other - const inksToGroup = ffView.unprocessedDocs.filter(inkDoc => { - console.log(inkDoc.x, inkDoc.y); + // find all inkDocs in ffView.unprocessedDocs that are within 200 pixels of each other + const inksToGroup = ffView.unprocessedDocs.filter(inkDoc => { + console.log(inkDoc.x, inkDoc.y); }); }); } @@ -718,26 +719,26 @@ export function createInkGroup(inksToGroup?: Doc[]) { const selected = ffView.unprocessedDocs; // loop through selected an get the bound const bounds: { x: number, y: number, width?: number, height?: number }[] = [] - + selected.map(action(d => { const x = NumCast(d.x); const y = NumCast(d.y); const width = d[WidthSym](); const height = d[HeightSym](); - bounds.push({x, y, width, height}); + bounds.push({ x, y, width, height }); })) - + const aggregBounds = aggregateBounds(bounds, 0, 0); const marqViewRef = ffView._marqueeViewRef.current; - + // set the vals for bounds in marqueeView if (marqViewRef) { marqViewRef._downX = aggregBounds.x; marqViewRef._downY = aggregBounds.y; marqViewRef._lastX = aggregBounds.r; marqViewRef._lastY = aggregBounds.b; - } - + } + selected.map(action(d => { const dx = NumCast(d.x); const dy = NumCast(d.y); @@ -756,11 +757,13 @@ export function createInkGroup(inksToGroup?: Doc[]) { ffView.props.removeDocument?.(selected); // TODO: nda - this is the code to actually get a new grouped collection const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); - + // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs newCollection && ffView.props.addDocument?.(newCollection); // TODO: nda - will probably need to go through and only remove the unprocessed selected docs ffView.unprocessedDocs = []; + + InkTranscription.Instance.transcribeInk(newCollection, selected, false); }); } CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); @@ -780,7 +783,7 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole // const selected = ffView.unprocessedDocs; // // loop through selected an get the bound // const bounds: { x: number, y: number, width?: number, height?: number }[] = [] - + // selected.map(action(d => { // const x = NumCast(d.x); // const y = NumCast(d.y); @@ -788,10 +791,10 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole // const height = d[HeightSym](); // bounds.push({x, y, width, height}); // })) - + // const aggregBounds = aggregateBounds(bounds, 0, 0); // const marqViewRef = ffView._marqueeViewRef.current; - + // // set the vals for bounds in marqueeView // if (marqViewRef) { // marqViewRef._downX = aggregBounds.x; @@ -799,7 +802,7 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole // marqViewRef._lastX = aggregBounds.r; // marqViewRef._lastY = aggregBounds.b; // } - + // selected.map(action(d => { // const dx = NumCast(d.x); // const dy = NumCast(d.y); @@ -818,7 +821,7 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole // ffView.props.removeDocument?.(selected); // // TODO: nda - this is the code to actually get a new grouped collection // const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); - + // // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs // newCollection && ffView.props.addDocument?.(newCollection); // ffView.unprocessedDocs = []; -- cgit v1.2.3-70-g09d2 From 73d52c3c1a0b06e0180999cb876feb6025df31b2 Mon Sep 17 00:00:00 2001 From: mehekj Date: Thu, 28 Apr 2022 16:31:57 -0400 Subject: fixed timestamps and added some scaling --- src/client/documents/Documents.ts | 1 - src/client/views/GestureOverlay.tsx | 22 +++---------- src/client/views/InkTranscription.tsx | 38 +++++++++++++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 15 ++++----- src/client/views/nodes/button/FontIconBox.tsx | 10 +++--- src/fields/InkField.ts | 3 +- src/pen-gestures/GestureUtils.ts | 3 +- 7 files changed, 41 insertions(+), 51 deletions(-) (limited to 'src/client/views/nodes/button') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 884cc781d..aee9ef49d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1161,7 +1161,6 @@ export namespace DocUtils { created = Docs.Create.AudioDocument((field).url.href, resolved); layout = AudioBox.LayoutString; } else if (field instanceof InkField) { - console.log("Documents " + field.inkData) created = Docs.Create.InkDocument(ActiveInkColor(), CurrentUserUtils.SelectedTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), (field).inkData, resolved); layout = InkingStroke.LayoutString; } else if (field instanceof List && field[0] instanceof Doc) { diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 5f0311d38..fc0a214a6 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -42,7 +42,6 @@ export class GestureOverlay extends Touchable { @observable private _menuY: number = -300; @observable private _pointerY?: number; @observable private _points: { X: number, Y: number }[] = []; - @observable private _timeStamps: number[] = []; @observable private _strokes: InkData[] = []; @observable private _palette?: JSX.Element; @observable private _clipboardDoc?: JSX.Element; @@ -61,7 +60,6 @@ export class GestureOverlay extends Touchable { private pointerIdentifier?: number; private _hands: Map = new Map(); private _holdTimer: NodeJS.Timeout | undefined; - private _strokeStartTime: number = 0; protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; @@ -299,7 +297,7 @@ export class GestureOverlay extends Touchable { pointer = fingers.reduce((a, v) => a.clientX < v.clientX || v.identifier === thumb.identifier ? a : v); } else { - console.log("not hand"); + // console.log("not hand"); } this.pointerIdentifier = pointer?.identifier; @@ -425,7 +423,6 @@ export class GestureOverlay extends Touchable { this._strokes = []; this._points = []; - this._timeStamps = []; this._possibilities = []; document.removeEventListener("touchend", this.handleHandUp); } @@ -509,8 +506,6 @@ export class GestureOverlay extends Touchable { CurrentUserUtils.SelectedTool = InkTool.Write; } this._points.push({ X: e.clientX, Y: e.clientY }); - this._timeStamps.push(0); - this._strokeStartTime = new Date().getTime(); setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction); // if (CurrentUserUtils.SelectedTool === InkTool.Highlighter) SetActiveInkColor("rgba(245, 230, 95, 0.75)"); } @@ -519,7 +514,6 @@ export class GestureOverlay extends Touchable { @action onPointerMove = (e: PointerEvent) => { this._points.push({ X: e.clientX, Y: e.clientY }); - this._timeStamps.push(new Date().getTime() - this._strokeStartTime); if (this._points.length > 1) { const B = this.svgBounds; @@ -566,7 +560,6 @@ export class GestureOverlay extends Touchable { const points = this._points.map(p => ({ X: p.X - B.left, Y: p.Y - B.top })); //push first points to so interactionUtil knows pointer is up this._points.push({ X: this._points[0].X, Y: this._points[0].Y }); - this._timeStamps.push(this._timeStamps[0]); const initialPoint = this._points[0.]; const xInGlass = initialPoint.X > (this._thumbX ?? Number.MAX_SAFE_INTEGER) && initialPoint.X < (this._thumbX ?? Number.MAX_SAFE_INTEGER) + (this.height); @@ -578,7 +571,6 @@ export class GestureOverlay extends Touchable { case ToolglassTools.InkToText: this._strokes.push(new Array(...this._points)); this._points = []; - this._timeStamps = []; CognitiveServices.Inking.Appliers.InterpretStrokes(this._strokes).then((results) => { const wordResults = results.filter((r: any) => r.category === "line"); const possibilities: string[] = []; @@ -602,7 +594,6 @@ export class GestureOverlay extends Touchable { case ToolglassTools.IgnoreGesture: this.dispatchGesture(GestureUtils.Gestures.Stroke); this._points = []; - this._timeStamps = []; break; } } @@ -611,7 +602,6 @@ export class GestureOverlay extends Touchable { this.makePolygon(this.InkShape, false); this.dispatchGesture(GestureUtils.Gestures.Stroke); this._points = []; - this._timeStamps = []; if (!CollectionFreeFormViewChrome.Instance?._keepPrimitiveMode) { this.InkShape = ""; Doc.UserDoc().activeInkTool = InkTool.None; @@ -638,7 +628,7 @@ export class GestureOverlay extends Touchable { if (!actionPerformed) { const newPoints = this._points.reduce((p, pts) => { p.push([pts.X, pts.Y]); return p; }, [] as number[][]); newPoints.pop(); - console.log("getting to bezier math"); + // console.log("getting to bezier math"); const controlPoints: { X: number, Y: number }[] = []; const bezierCurves = fitCurve(newPoints, 10); @@ -649,21 +639,19 @@ export class GestureOverlay extends Touchable { controlPoints.push({ X: curve[2][0], Y: curve[2][1] }); controlPoints.push({ X: curve[3][0], Y: curve[3][1] }); - } + } const dist = Math.sqrt((controlPoints[0].X - controlPoints.lastElement().X) * (controlPoints[0].X - controlPoints.lastElement().X) + (controlPoints[0].Y - controlPoints.lastElement().Y) * (controlPoints[0].Y - controlPoints.lastElement().Y)); if (controlPoints.length > 4 && dist < 10) controlPoints[controlPoints.length - 1] = controlPoints[0]; - this._points = controlPoints; + this._points = controlPoints; this.dispatchGesture(GestureUtils.Gestures.Stroke); // TODO: nda - check inks to group here checkInksToGroup(); } this._points = []; - this._timeStamps = []; } } else { this._points = []; - this._timeStamps = []; } CollectionFreeFormViewChrome.Instance?.primCreated(); } @@ -712,7 +700,6 @@ export class GestureOverlay extends Touchable { } } this._points = []; - this._timeStamps = []; switch (shape) { //must push an extra point in the end so InteractionUtils knows pointer is up. //must be (points[0].X,points[0]-1) @@ -836,7 +823,6 @@ export class GestureOverlay extends Touchable { gesture: gesture as any, bounds: this.getBounds(stroke ?? this._points), text: data, - times: this._timeStamps } } ) diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx index ea5d5a1ec..a96cda743 100644 --- a/src/client/views/InkTranscription.tsx +++ b/src/client/views/InkTranscription.tsx @@ -1,12 +1,13 @@ -import { timeStamp } from 'console'; import * as iink from 'iink-js'; import { action, observable } from 'mobx'; import * as React from 'react'; -import { Doc } from '../../fields/Doc'; +import { Doc, DocListCast } from '../../fields/Doc'; import { InkData, InkField } from "../../fields/InkField"; -import { Cast, NumCast, StrCast } from '../../fields/Types'; +import { Cast, NumCast } from '../../fields/Types'; import { DocumentType } from "../documents/DocumentTypes"; import './InkTranscription.scss'; +import { Utils } from '../../Utils'; +import { timesSeries } from 'async'; export class InkTranscription extends React.Component { static Instance: InkTranscription; @@ -16,6 +17,7 @@ export class InkTranscription extends React.Component { @observable _textRegister: any; @observable _textRef: any; private currGroup?: Doc; + private containingLayout?: Doc; constructor(props: Readonly<{}>) { super(props); @@ -98,24 +100,26 @@ export class InkTranscription extends React.Component { return this._textRef = r; } - transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => { + transcribeInk = (groupDoc: Doc | undefined, containingLayout: Doc, inkDocs: Doc[], math: boolean) => { if (!groupDoc) return; const validInks = inkDocs.filter(s => s.type === DocumentType.INK); const strokes: InkData[] = []; + const times: number[] = []; validInks.filter(i => Cast(i.data, InkField)).forEach(i => { - // TODO: interpolate missing times stamps const d = Cast(i.data, InkField, null); const left = Math.min(...d?.inkData.map(pd => pd.X) ?? [0]); const top = Math.min(...d?.inkData.map(pd => pd.Y) ?? [0]); - strokes.push(d.inkData.map(pd => ({ X: pd.X + NumCast(i.x) - left, Y: pd.Y + NumCast(i.y) - top, time: pd.time }))); + strokes.push(d.inkData.map(pd => ({ X: pd.X + NumCast(i.x) - left, Y: pd.Y + NumCast(i.y) - top }))); + times.push(NumCast(i.creationDate, 1)); }); this.currGroup = groupDoc; + this.containingLayout = containingLayout; - const pointerData = { "events": strokes.map(stroke => this.inkJSON(stroke)) }; - // console.log(JSON.stringify(pointerData)); + const pointerData = { "events": strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) }; + console.log(JSON.stringify(pointerData)); const processGestures = false; if (math) { @@ -126,13 +130,17 @@ export class InkTranscription extends React.Component { } } - inkJSON = (stroke: InkData) => { + inkJSON = (stroke: InkData, time: number) => { + const scale = NumCast(this.containingLayout?._viewScale, 1); + const panX = NumCast(this.containingLayout?._panX); + const panY = NumCast(this.containingLayout?._panY); + return { "pointerType": "PEN", "pointerId": 1, - "x": stroke.map(point => point.X), - "y": stroke.map(point => point.Y), - "t": stroke.map(point => point.time), + "x": stroke.map(point => (point.X - panX) * scale), + "y": stroke.map(point => (point.Y - panY) * scale), + "t": new Array(stroke.length).fill(time), "p": new Array(stroke.length).fill(1.0) }; } @@ -142,7 +150,7 @@ export class InkTranscription extends React.Component { if (exports) { if (exports['application/x-latex']) { const latex = exports['application/x-latex']; - console.log(latex); + // console.log(latex); if (this.currGroup) { this.currGroup.text = latex; @@ -153,11 +161,11 @@ export class InkTranscription extends React.Component { } else if (exports['text/plain']) { const text = exports['text/plain']; - console.log(text); + // console.log(text); if (this.currGroup) { this.currGroup.text = text; - this.currGroup.title = text; + this.currGroup.title = text.split("\n")[0]; } ref.editor.clear(); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 023953658..3c5cdb444 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -517,9 +517,7 @@ export class CollectionFreeFormView extends CollectionSubView { return { X: pt.X, Y: pt.Y, time: times[i] } }); - const inkDoc = Docs.Create.InkDocument(ActiveInkColor(), CurrentUserUtils.SelectedTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), strokes, + const inkDoc = Docs.Create.InkDocument(ActiveInkColor(), CurrentUserUtils.SelectedTool, ActiveInkWidth(), ActiveInkBezierApprox(), ActiveFillColor(), ActiveArrowStart(), ActiveArrowEnd(), ActiveDash(), points, { title: "ink stroke", x: B.x - ActiveInkWidth() / 2, y: B.y - ActiveInkWidth() / 2, _width: B.width + ActiveInkWidth(), _height: B.height + ActiveInkWidth() }); if (CurrentUserUtils.SelectedTool === InkTool.Write) { this.unprocessedDocs.push(inkDoc); @@ -1578,13 +1576,14 @@ export class CollectionFreeFormView extends CollectionSubView { if (this.props.Document._isGroup && this.props.Document.text) { - const text = StrCast(this.props.Document.text); + if (!math) { + const text = StrCast(this.props.Document.text); - const lines = text.split("\n"); - const width = 30 + 7 * Math.max(...lines.map(line => line.length)); - const height = 30 + 15 * lines.length; + const lines = text.split("\n"); + const height = 30 + 15 * lines.length; - this.props.ContainingCollectionView?.addDocument(Docs.Create.TextDocument(text, { title: text, x: NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc._width) + 20, y: NumCast(this.layoutDoc.y), _width: width, _height: height })); + this.props.ContainingCollectionView?.addDocument(Docs.Create.TextDocument(text, { title: lines[0], x: NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc._width) + 20, y: NumCast(this.layoutDoc.y), _width: 200, _height: height })); + } } } diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index fc358f106..aca393c1a 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -262,7 +262,7 @@ export class FontIconBox extends DocComponent() { "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]; } } catch (e) { - console.log(e); + // console.log(e); } // Get items to place into the list @@ -699,13 +699,13 @@ ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) { export function checkInksToGroup() { - console.log("getting here to inks group"); + // console.log("getting here to inks group"); if (CurrentUserUtils.SelectedTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those // find all inkDocs in ffView.unprocessedDocs that are within 200 pixels of each other const inksToGroup = ffView.unprocessedDocs.filter(inkDoc => { - console.log(inkDoc.x, inkDoc.y); + // console.log(inkDoc.x, inkDoc.y); }); }); } @@ -763,7 +763,7 @@ export function createInkGroup(inksToGroup?: Doc[]) { // TODO: nda - will probably need to go through and only remove the unprocessed selected docs ffView.unprocessedDocs = []; - InkTranscription.Instance.transcribeInk(newCollection, selected, false); + InkTranscription.Instance.transcribeInk(newCollection, ffView.layoutDoc, selected, false); }); } CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); @@ -845,7 +845,7 @@ ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boole if (Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance.InkShape) { Doc.UserDoc().activeInkTool = InkTool.None; } else if (tool == "write") { - console.log("write mode selected - create groupDoc here!", tool) + // console.log("write mode selected - create groupDoc here!", tool) Doc.UserDoc().activeInkTool = tool; GestureOverlay.Instance.InkShape = ""; } else { diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts index 6d24c6cbc..31fa6dfac 100644 --- a/src/fields/InkField.ts +++ b/src/fields/InkField.ts @@ -20,7 +20,6 @@ export enum InkTool { export interface PointData { X: number; Y: number; - time?: number; } export type Segment = Array; @@ -85,7 +84,7 @@ export class InkField extends ObjectField { } [ToScriptString]() { - return "new InkField([" + this.inkData.map(i => `{X: ${i.X}, Y: ${i.Y}, time: ${i.time || 0}} `) + "])"; + return "new InkField([" + this.inkData.map(i => `{X: ${i.X}, Y: ${i.Y}`) + "])"; } [ToString]() { return "InkField"; diff --git a/src/pen-gestures/GestureUtils.ts b/src/pen-gestures/GestureUtils.ts index cf59cb3c6..65f2bf80c 100644 --- a/src/pen-gestures/GestureUtils.ts +++ b/src/pen-gestures/GestureUtils.ts @@ -8,8 +8,7 @@ export namespace GestureUtils { readonly gesture: Gestures, readonly points: PointData[], readonly bounds: Rect, - readonly text?: any, - readonly times?: number[] + readonly text?: any ) { } } -- cgit v1.2.3-70-g09d2 From 4f6b6306803437851959e9ad214fd61a14207a20 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Thu, 28 Apr 2022 16:34:31 -0400 Subject: added basic code for subgrouping transcribed text --- src/client/util/InteractionUtils.tsx | 1 + src/client/views/GestureOverlay.tsx | 2 +- src/client/views/InkTranscription.tsx | 71 +++++++++++++++++++++- src/client/views/LightboxView.tsx | 3 +- src/client/views/Touchable.tsx | 2 + .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- src/client/views/nodes/DocumentLinksButton.tsx | 2 + src/client/views/nodes/button/FontIconBox.tsx | 56 ++--------------- 8 files changed, 86 insertions(+), 55 deletions(-) (limited to 'src/client/views/nodes/button') diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 675dff00b..e2c5fab64 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -357,6 +357,7 @@ export namespace InteractionUtils { } export function IsDragging(oldTouches: Map, newTouches: React.Touch[], leniency: number): boolean { + console.log("getting here"); for (const touch of newTouches) { if (touch) { const oldTouch = oldTouches.get(touch.identifier); diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 5f0311d38..e689cd43c 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -212,7 +212,7 @@ export class GestureOverlay extends Touchable { const nts: any = this.getNewTouches(e); this._holdTimer && clearTimeout(this._holdTimer); this._holdTimer = undefined; - + document.dispatchEvent( new CustomEvent>("dashOnTouchMove", { diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx index ea5d5a1ec..3b464db10 100644 --- a/src/client/views/InkTranscription.tsx +++ b/src/client/views/InkTranscription.tsx @@ -5,6 +5,7 @@ import * as React from 'react'; import { Doc } from '../../fields/Doc'; import { InkData, InkField } from "../../fields/InkField"; import { Cast, NumCast, StrCast } from '../../fields/Types'; +import { aggregateBounds } from '../../Utils'; import { DocumentType } from "../documents/DocumentTypes"; import './InkTranscription.scss'; @@ -15,12 +16,18 @@ export class InkTranscription extends React.Component { @observable _mathRef: any; @observable _textRegister: any; @observable _textRef: any; + private lastJiix: any; private currGroup?: Doc; + private wordsBoundMapping: any; + private inkDocs: Doc[]; + private ffView: any; constructor(props: Readonly<{}>) { super(props); InkTranscription.Instance = this; + this.wordsBoundMapping = new Map(); + this.inkDocs = new Array(); } componentWillUnmount() { @@ -98,8 +105,10 @@ export class InkTranscription extends React.Component { return this._textRef = r; } - transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => { + transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean, ffView?: any) => { if (!groupDoc) return; + this.inkDocs = inkDocs; + this.ffView = ffView; const validInks = inkDocs.filter(s => s.type === DocumentType.INK); @@ -137,8 +146,20 @@ export class InkTranscription extends React.Component { }; } + mmToPixel = (mm: number) => { + return ((96 * mm) / 25.4); + } + + calcBounds = (coords: any) => { + // find max and min x values and subtract + const max = Math.max(...coords); + const min = Math.min(...coords); + return max - min; + } + exportInk = (e: any, ref: any) => { const exports = e.detail.exports; + console.log(e); if (exports) { if (exports['application/x-latex']) { const latex = exports['application/x-latex']; @@ -152,12 +173,60 @@ export class InkTranscription extends React.Component { ref.editor.clear(); } else if (exports['text/plain']) { + if (exports['application/vnd.myscript.jiix']) { + this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']); + // console.log("lastJiix:", this.lastJiix); + // TODO: nda - go through all the words and look at x,y values and figure out the selection + this.lastJiix.words.forEach((word: any) => { + // map each word to a new map + this.wordsBoundMapping[word] = new Map(); + if (word.items) { + word.items.map((item: any) => { + this.wordsBoundMapping.set(word, {xList: item.X, yList: item.Y, width: this.calcBounds(item.X), height: this.calcBounds(item.Y)}); + }) + } + }) + // make groups for each of the words + // loop through this.wordsBoundMapping + + this.wordsBoundMapping.forEach((value: any, key: any) => { + const xList = value.xList; + const yList = value.yList; + const width = value.width; + const height = value.height; + const bounds: { x: number, y: number, width?: number, height?: number }[] = [] + // loop through xList + for (let i = 0; i < xList.length; i++) { + const x = xList[i]; + const y = yList[i]; + const newBounds = { x: x, y: y }; + bounds.push(newBounds); + } + const aggregBounds = aggregateBounds(bounds, 0, 0); + + const marqViewRef = this.ffView?._marqueeViewRef.current; + + // set the vals for bounds in marqueeView + if (marqViewRef) { + marqViewRef._downX = aggregBounds.x; + marqViewRef._downY = aggregBounds.y; + marqViewRef._lastX = aggregBounds.r; + marqViewRef._lastY = aggregBounds.b; + } + + }); + + // console.log(this.wordsBoundMapping); + } const text = exports['text/plain']; console.log(text); if (this.currGroup) { + console.log("curr grouping"); this.currGroup.text = text; this.currGroup.title = text; + console.log(this.lastJiix); + console.log(this.currGroup); } ref.editor.clear(); diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index ec3bf6c18..c8f6b5f0b 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -5,7 +5,7 @@ import "normalize.css"; import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { Cast, NumCast, StrCast } from '../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, Utils } from '../../Utils'; import { DocUtils } from '../documents/Documents'; import { DocumentManager } from '../util/DocumentManager'; import { LinkManager } from '../util/LinkManager'; @@ -17,6 +17,7 @@ import "./LightboxView.scss"; import { DocumentView } from './nodes/DocumentView'; import { DefaultStyleProvider, wavyBorderPath } from './StyleProvider'; import { CollectionMenu } from './collections/CollectionMenu'; +import { utils } from 'mocha'; interface LightboxViewProps { PanelWidth: number; diff --git a/src/client/views/Touchable.tsx b/src/client/views/Touchable.tsx index 789756a78..c712e7ed3 100644 --- a/src/client/views/Touchable.tsx +++ b/src/client/views/Touchable.tsx @@ -127,11 +127,13 @@ export abstract class Touchable extends React.Component { } handle1PointerMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent): any => { + console.log("getting to handle1PointersMove"); e.stopPropagation(); e.preventDefault(); } handle2PointersMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent): any => { + console.log("getting to handle2PointersMove"); e.stopPropagation(); e.preventDefault(); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 023953658..7c11c252a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -702,9 +702,9 @@ export class CollectionFreeFormView extends CollectionSubView { + console.log("this is onPointerMove"); if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) return; if (InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) { - console.log("is touch"); Doc.UserDoc().activeInkTool = InkTool.None; if (this.props.isContentActive(true)) e.stopPropagation(); } else if (!e.cancelBubble) { @@ -825,6 +825,7 @@ export class CollectionFreeFormView extends CollectionSubView) => { + console.log("getting here yeet"); if (!e.cancelBubble) { const myTouches = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true); if (myTouches[0]) { @@ -836,6 +837,7 @@ export class CollectionFreeFormView extends CollectionSubView only want to do this when collection is selected' this.pan(myTouches[0]); } } diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 7e6ca4248..f9d2b9917 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -21,6 +21,8 @@ import { LinkDescriptionPopup } from "./LinkDescriptionPopup"; import { TaskCompletionBox } from "./TaskCompletedBox"; import React = require("react"); import { Transform } from "../../util/Transform"; +import { InkTool } from "../../../fields/InkField"; +import { CurrentUserUtils } from "../../util/CurrentUserUtils"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index fc358f106..85130e69e 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -757,13 +757,17 @@ export function createInkGroup(inksToGroup?: Doc[]) { ffView.props.removeDocument?.(selected); // TODO: nda - this is the code to actually get a new grouped collection const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); + if (newCollection) { + newCollection.height = newCollection[HeightSym](); + newCollection.width = newCollection[WidthSym](); + } // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs newCollection && ffView.props.addDocument?.(newCollection); // TODO: nda - will probably need to go through and only remove the unprocessed selected docs ffView.unprocessedDocs = []; - InkTranscription.Instance.transcribeInk(newCollection, selected, false); + InkTranscription.Instance.transcribeInk(newCollection, selected, false, ffView); }); } CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); @@ -778,56 +782,6 @@ export function createInkGroup(inksToGroup?: Doc[]) { ScriptingGlobals.add(function setActiveInkTool(tool: string, checkResult?: boolean) { createInkGroup(); - // if (CurrentUserUtils.SelectedTool === InkTool.Write) { - // CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { - // const selected = ffView.unprocessedDocs; - // // loop through selected an get the bound - // const bounds: { x: number, y: number, width?: number, height?: number }[] = [] - - // selected.map(action(d => { - // const x = NumCast(d.x); - // const y = NumCast(d.y); - // const width = d[WidthSym](); - // const height = d[HeightSym](); - // bounds.push({x, y, width, height}); - // })) - - // const aggregBounds = aggregateBounds(bounds, 0, 0); - // const marqViewRef = ffView._marqueeViewRef.current; - - // // set the vals for bounds in marqueeView - // if (marqViewRef) { - // marqViewRef._downX = aggregBounds.x; - // marqViewRef._downY = aggregBounds.y; - // marqViewRef._lastX = aggregBounds.r; - // marqViewRef._lastY = aggregBounds.b; - // } - - // selected.map(action(d => { - // const dx = NumCast(d.x); - // const dy = NumCast(d.y); - // delete d.x; - // delete d.y; - // delete d.activeFrame; - // delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - // delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - // // calculate pos based on bounds - // if (marqViewRef?.Bounds) { - // d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; - // d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; - // } - // return d; - // })); - // ffView.props.removeDocument?.(selected); - // // TODO: nda - this is the code to actually get a new grouped collection - // const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); - - // // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs - // newCollection && ffView.props.addDocument?.(newCollection); - // ffView.unprocessedDocs = []; - // }); - // } - // CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); if (checkResult) { return ((Doc.UserDoc().activeInkTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ? -- cgit v1.2.3-70-g09d2 From 8147fd7d80746114a2245237e4dab2c89e2d49a2 Mon Sep 17 00:00:00 2001 From: Naafiyan Ahmed Date: Mon, 2 May 2022 16:27:49 -0400 Subject: working on getting subgroups to work --- src/client/views/InkTranscription.tsx | 87 ++++++++++++++++++++++++--- src/client/views/nodes/button/FontIconBox.tsx | 4 +- 2 files changed, 82 insertions(+), 9 deletions(-) (limited to 'src/client/views/nodes/button') diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx index b1f807bdf..f7260c5b4 100644 --- a/src/client/views/InkTranscription.tsx +++ b/src/client/views/InkTranscription.tsx @@ -1,13 +1,14 @@ import * as iink from 'iink-js'; import { action, observable } from 'mobx'; import * as React from 'react'; -import { DataSym, Doc, DocListCast } from '../../fields/Doc'; +import { DataSym, Doc, DocListCast, HeightSym, WidthSym } from '../../fields/Doc'; import { InkData, InkField } from "../../fields/InkField"; import { Cast, DateCast, NumCast } from '../../fields/Types'; import { DocumentType } from "../documents/DocumentTypes"; import './InkTranscription.scss'; import { aggregateBounds, Utils } from '../../Utils'; import { timesSeries } from 'async'; +import { CollectionFreeFormView } from './collections/collectionFreeForm'; export class InkTranscription extends React.Component { static Instance: InkTranscription; @@ -106,9 +107,12 @@ export class InkTranscription extends React.Component { return this._textRef = r; } - transcribeInk = (groupDoc: Doc | undefined, containingLayout: Doc, inkDocs: Doc[], math: boolean) => { + transcribeInk = (groupDoc: Doc | undefined, containingLayout: Doc, inkDocs: Doc[], math: boolean, ffView?: CollectionFreeFormView) => { if (!groupDoc) return; this.inkDocs = inkDocs; + if (ffView) { + this.ffView = ffView; + } const validInks = inkDocs.filter(s => s.type === DocumentType.INK); @@ -165,6 +169,69 @@ export class InkTranscription extends React.Component { return max - min; } + subgroupsTranscriptions = (wordInkDocMap: Map) => { + // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those + // loop through the words in wordInkDocMap + // for each word, get the inkDocs + + // iterate through the keys of wordInkDocMap + wordInkDocMap.forEach((inkDocs: Doc[], word: string) => { + const selected = wordInkDocMap.get(word); + if (!selected) { + return; + } + // loop through selected an get the bound + const bounds: { x: number, y: number, width?: number, height?: number }[] = [] + + selected.map(action(d => { + const x = NumCast(d.x); + const y = NumCast(d.y); + const width = d[WidthSym](); + const height = d[HeightSym](); + bounds.push({ x, y, width, height }); + })) + + const aggregBounds = aggregateBounds(bounds, 0, 0); + const marqViewRef = this.ffView._marqueeViewRef.current; + + // set the vals for bounds in marqueeView + if (marqViewRef) { + marqViewRef._downX = aggregBounds.x; + marqViewRef._downY = aggregBounds.y; + marqViewRef._lastX = aggregBounds.r; + marqViewRef._lastY = aggregBounds.b; + } + + selected.map(action(d => { + const dx = NumCast(d.x); + const dy = NumCast(d.y); + delete d.x; + delete d.y; + delete d.activeFrame; + delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + // calculate pos based on bounds + if (marqViewRef?.Bounds) { + d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; + d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; + } + return d; + })); + this.ffView.props.removeDocument?.(selected); + // TODO: nda - this is the code to actually get a new grouped collection + const newCollection = marqViewRef?.getCollection(selected, undefined, [], true); + if (newCollection) { + newCollection.height = newCollection[HeightSym](); + newCollection.width = newCollection[WidthSym](); + newCollection.title = word; + } + + + // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs + newCollection && this.ffView.props.addDocument?.(newCollection); + }); + } + exportInk = (e: any, ref: any) => { const exports = e.detail.exports; console.log(e); @@ -186,10 +253,12 @@ export class InkTranscription extends React.Component { // map timestamp to strokes const timestampWord = new Map(); this.lastJiix.words.map((word: any) => { - word.items.map((i: any) => { - const ms = Date.parse(i.timestamp); - timestampWord.set(ms, word.label); - }) + if (word.items) { + word.items.forEach((i: {id: string, timestamp: string, X: Array, Y: Array, F: Array}) => { + const ms = Date.parse(i.timestamp); + timestampWord.set(ms, word.label); + }) + } }) const wordInkDocMap = new Map(); @@ -210,8 +279,12 @@ export class InkTranscription extends React.Component { const newEntry = [inkDoc]; wordInkDocMap.set(word, newEntry); } - }); + // do the fun marq stuff + // generate subgroups + + console.log(wordInkDocMap); + this.subgroupsTranscriptions(wordInkDocMap); } // we can iterate through docs and for each doc index into the map by timestamp diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index 1c2a22226..d87b23d86 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -711,7 +711,7 @@ export function checkInksToGroup() { } } -export function createInkGroup(inksToGroup?: Doc[]) { +export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) { // TODO nda - if document being added to is a inkGrouping then we can just add to that group if (CurrentUserUtils.SelectedTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { @@ -767,7 +767,7 @@ export function createInkGroup(inksToGroup?: Doc[]) { // TODO: nda - will probably need to go through and only remove the unprocessed selected docs ffView.unprocessedDocs = []; - InkTranscription.Instance.transcribeInk(newCollection, ffView.layoutDoc, selected, false); + InkTranscription.Instance.transcribeInk(newCollection, ffView.layoutDoc, selected, false, ffView); }); } CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); -- cgit v1.2.3-70-g09d2