From c63b780580b5cd9c079da361ff65019641782226 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 17 Jul 2020 03:26:29 -0400 Subject: fixed issues with embedded text boxes in text boxes when displayed multiple times (alias or minimap). fixed richtextmenu to always "point to" the selected text box. --- .../views/collections/CollectionDockingView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 20 ++++++++++++-------- .../views/nodes/formattedText/RichTextMenu.tsx | 9 +++++---- .../views/nodes/formattedText/RichTextSchema.tsx | 10 +++++++++- 4 files changed, 27 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index be1ef56d0..8938541ac 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -916,7 +916,7 @@ export class DockedFrameRenderer extends React.Component { docFilters={returnEmptyFilter} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} /> - {document._viewType === CollectionViewType.Freeform ? this.renderMiniMap() : (null)} + {document._viewType === CollectionViewType.Freeform && !this._document?.hideMinimap ? this.renderMiniMap() : (null)} ; } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index f87b28c7f..30e1fa9cd 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -232,6 +232,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const curProto = Cast(Cast(this.dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null); // the default text inherited from a prototype const curLayout = this.rootDoc !== this.layoutDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField, null) : undefined; // the default text stored in a layout template const json = JSON.stringify(state.toJSON()); + let unchanged = true; if (!this.dataDoc[AclSym]) { if (!this._applyingChange && json.replace(/"selection":.*/, "") !== curProto?.Data.replace(/"selection":.*/, "")) { this._applyingChange = true; @@ -243,21 +244,25 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.dataDoc[this.props.fieldKey] = new RichTextField(json, curText); this.dataDoc[this.props.fieldKey + "-noTemplate"] = (curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText }); + unchanged = false; } } else { // if we've deleted all the text in a note driven by a template, then restore the template data this.dataDoc[this.props.fieldKey] = undefined; this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse((curProto || curTemp).Data))); this.dataDoc[this.props.fieldKey + "-noTemplate"] = undefined; // mark the data field as not being split from any template it might have + unchanged = false; } this._applyingChange = false; + if (!unchanged) { + this.updateTitle(); + this.tryUpdateHeight(); + } } } else { const json = JSON.parse(Cast(this.dataDoc[this.fieldKey], RichTextField)?.Data!); json.selection = state.toJSON().selection; this._editorView.updateState(EditorState.fromJSON(this.config, json)); } - this.updateTitle(); - this.tryUpdateHeight(); } } @@ -1036,7 +1041,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._editorView?.destroy(); } - static _downEvent: any; + _downEvent: any; _downX = 0; _downY = 0; _break = false; @@ -1056,7 +1061,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._downX = e.clientX; this._downY = e.clientY; this.doLinkOnDeselect(); - FormattedTextBox._downEvent = true; + this._downEvent = true; FormattedTextBoxComment.textBox = this; if (this.props.onClick && e.button === 0 && !this.props.isSelected(false)) { e.preventDefault(); @@ -1072,8 +1077,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } onPointerUp = (e: React.PointerEvent): void => { - if (!FormattedTextBox._downEvent) return; - FormattedTextBox._downEvent = false; + if (!this._downEvent) return; + this._downEvent = false; if (!(e.nativeEvent as any).formattedHandled) { const editor = this._editorView!; FormattedTextBoxComment.textBox = this; @@ -1092,7 +1097,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp onDoubleClick = (e: React.MouseEvent): void => { this.doLinkOnDeselect(); - FormattedTextBox._downEvent = true; FormattedTextBoxComment.textBox = this; if (this.props.onClick && e.button === 0 && !this.props.isSelected(false)) { e.preventDefault(); @@ -1244,7 +1248,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp richTextMenuPlugin() { return new Plugin({ view(newView) { - RichTextMenu.Instance && RichTextMenu.Instance.changeView(newView); + RichTextMenu.Instance?.changeView(newView); return RichTextMenu.Instance; } }); diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 63f6fdc54..9890ef2c1 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -156,7 +156,9 @@ export default class RichTextMenu extends AntimodeMenu { @action changeView(view: EditorView) { - this.view = view; + if ((view as any)?.TextView?.props.isSelected(true)) { + this.view = view; + } } update(view: EditorView, lastState: EditorState | undefined) { @@ -165,8 +167,7 @@ export default class RichTextMenu extends AntimodeMenu { @action public async updateFromDash(view: EditorView, lastState: EditorState | undefined, props: any) { - if (!view) { - console.log("no editor? why?"); + if (!view || !(view as any).TextView?.props.isSelected(true)) { return; } this.view = view; @@ -318,7 +319,7 @@ export default class RichTextMenu extends AntimodeMenu { } destroy() { - this.fadeOut(true); + !this.TextView.props.isSelected(false) && this.fadeOut(true); } @action diff --git a/src/client/views/nodes/formattedText/RichTextSchema.tsx b/src/client/views/nodes/formattedText/RichTextSchema.tsx index a989abd6a..7a50ec3af 100644 --- a/src/client/views/nodes/formattedText/RichTextSchema.tsx +++ b/src/client/views/nodes/formattedText/RichTextSchema.tsx @@ -54,6 +54,8 @@ export class DashDocView { this._dashSpan.style.height = node.attrs.height; this._dashSpan.style.position = "absolute"; this._dashSpan.style.display = "inline-block"; + this._dashSpan.style.left = "0"; + this._dashSpan.style.top = "0"; this._dashSpan.style.whiteSpace = "normal"; this._dashSpan.onpointerleave = () => { @@ -160,7 +162,13 @@ export class DashDocView { if (node.attrs.width !== dashDoc._width + "px" || node.attrs.height !== dashDoc._height + "px") { try { // bcz: an exception will be thrown if two aliases are open at the same time when a doc view comment is made - view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc._width + "px", height: dashDoc._height + "px" })); + if (getPos() !== undefined) { + const node = view.state.tr.doc.nodeAt(getPos()); + if (node.attrs.width !== dashDoc._width + "px" || + node.attrs.height !== dashDoc._height + "px") { + view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc._width + "px", height: dashDoc._height + "px" })); + } + } } catch (e) { console.log(e); } -- cgit v1.2.3-70-g09d2 From 934fd41b249533ced87b5869c116f628f4a013b9 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 17 Jul 2020 11:19:03 -0400 Subject: changed dropping menu items from collectionMenu to create fonticonbuttons if all parameters are filled in. . and buttons are placed in overlay layer. added labels to all fonticons usin title + added a tooltip field. turned off autoscroll of freeform view when dragign buttons (which will be in the overlay) --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 44 +++++++++++----------- src/client/util/DragManager.ts | 8 +++- src/client/views/collections/CollectionMenu.tsx | 22 +++++------ .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- src/client/views/nodes/FontIconBox.tsx | 21 ++++++----- .../views/nodes/formattedText/RichTextMenu.tsx | 4 +- src/fields/Doc.ts | 9 +++-- 8 files changed, 62 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5b58aa2e3..8e7d125b0 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -91,7 +91,7 @@ export interface DocumentOptions { layoutKey?: string; type?: string; title?: string; - label?: string; // short form of title for use as an icon label + toolTip?: string; // tooltip to display on hover style?: string; page?: number; description?: string; // added for links diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index e0cb90b46..892d0ca1d 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -373,7 +373,7 @@ export class CurrentUserUtils { } static creatorBtnDescriptors(doc: Doc): { - title: string, label: string, icon: string, drag?: string, ignoreClick?: boolean, + title: string, toolTip: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activeInkPen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] { if (doc.emptyPresentation === undefined) { @@ -402,27 +402,27 @@ export class CurrentUserUtils { this.setupActiveMobileMenu(doc); } return [ - { title: "Drag a collection", label: "Col", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc }, - { title: "Drag a web page", label: "Web", icon: "globe-asia", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyWebpage as Doc }, - { title: "Drag a cat image", label: "Image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth:250, title: "an image of a cat" })' }, - { title: "Drag a comparison box", label: "Comp", icon: "columns", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyComparison as Doc }, - { title: "Drag a screengrabber", label: "Grab", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' }, - // { title: "Drag a webcam", label: "Cam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' }, - { title: "Drag a audio recorder", label: "Audio", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` }, - { title: "Drag a button", label: "Button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding:10, _yPadding: 10, title: "Button" })' }, - { title: "Drag a presentation view", label: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory,true)`, dragFactory: doc.emptyPresentation as Doc }, - { title: "Drag a search box", label: "Query", icon: "search", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' }, - { title: "Drag a scripting box", label: "Script", icon: "terminal", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScript as Doc }, - // { title: "Drag an import folder", label: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, - { title: "Drag a mobile view", label: "Phone", icon: "mobile", click: 'openOnRight(Doc.UserDoc().activeMobileMenu)', drag: 'this.dragFactory', dragFactory: doc.activeMobileMenu as Doc }, - // { title: "Drag an instance of the device collection", label: "Buxton", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.Buxton()' }, + { toolTip: "Drag a collection", title: "Col", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc }, + { toolTip: "Drag a web page", title: "Web", icon: "globe-asia", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyWebpage as Doc }, + { toolTip: "Drag a cat image", title: "Image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth:250, title: "an image of a cat" })' }, + { toolTip: "Drag a comparison box", title: "Comp", icon: "columns", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyComparison as Doc }, + { toolTip: "Drag a screengrabber", title: "Grab", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' }, + // { title: "Drag a webcam", title: "Cam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' }, + { toolTip: "Drag a audio recorder", title: "Audio", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` }, + { toolTip: "Drag a button", title: "Button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding:10, _yPadding: 10, title: "Button" })' }, + { toolTip: "Drag a presentation view", title: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory,true)`, dragFactory: doc.emptyPresentation as Doc }, + { toolTip: "Drag a search box", title: "Query", icon: "search", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' }, + { toolTip: "Drag a scripting box", title: "Script", icon: "terminal", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScript as Doc }, + // { title: "Drag an import folder", title: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, + { toolTip: "Drag a mobile view", title: "Phone", icon: "mobile", click: 'openOnRight(Doc.UserDoc().activeMobileMenu)', drag: 'this.dragFactory', dragFactory: doc.activeMobileMenu as Doc }, + // { title: "Drag an instance of the device collection", title: "Buxton", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.Buxton()' }, // { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this)', backgroundColor: "blue", ischecked: `sameDocs(this.activeInkPen, this)`, activeInkPen: doc }, // { title: "use highlighter", icon: "highlighter", click: 'activateBrush(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this,20,this.backgroundColor)', backgroundColor: "yellow", ischecked: `sameDocs(this.activeInkPen, this)`, activeInkPen: doc }, // { title: "use stamp", icon: "stamp", click: 'activateStamp(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this)', backgroundColor: "orange", ischecked: `sameDocs(this.activeInkPen, this)`, activeInkPen: doc }, // { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this);', ischecked: `sameDocs(this.activeInkPen, this)`, backgroundColor: "pink", activeInkPen: doc }, // { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activeInkPen = this;', ischecked: `sameDocs(this.activeInkPen, this)`, backgroundColor: "white", activeInkPen: doc }, - { title: "Drag a document previewer", label: "Prev", icon: "expand", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory,true)', dragFactory: doc.emptyDocHolder as Doc }, - { title: "Toggle a Calculator REPL", label: "repl", icon: "calculator", click: 'addOverlayWindow("ScriptingRepl", { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" })' }, + { toolTip: "Drag a document previewer", title: "Prev", icon: "expand", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory,true)', dragFactory: doc.emptyDocHolder as Doc }, + { toolTip: "Toggle a Calculator REPL", title: "repl", icon: "calculator", click: 'addOverlayWindow("ScriptingRepl", { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" })' }, ]; } @@ -439,11 +439,11 @@ export class CurrentUserUtils { } } const buttons = CurrentUserUtils.creatorBtnDescriptors(doc).filter(d => !alreadyCreatedButtons?.includes(d.title)); - const creatorBtns = buttons.map(({ title, label, icon, ignoreClick, drag, click, ischecked, activeInkPen, backgroundColor, dragFactory }) => Docs.Create.FontIconDocument({ + const creatorBtns = buttons.map(({ title, toolTip, icon, ignoreClick, drag, click, ischecked, activeInkPen, backgroundColor, dragFactory }) => Docs.Create.FontIconDocument({ _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, icon, title, - label, + toolTip, ignoreClick, dropAction: "copy", onDragStart: drag ? ScriptField.MakeFunction(drag) : undefined, @@ -735,14 +735,14 @@ export class CurrentUserUtils { if (doc["dockedBtn-pen"] === undefined) { doc["dockedBtn-pen"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("activatePen(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this)"), - author: "systemTemplates", title: "ink mode", icon: "pen-nib", ischecked: ComputedField.MakeFunction(`sameDocs(this.activeInkPen, this)`), activeInkPen: doc + author: "systemTemplates", toolTip: "open drawing tools", title: "draw", icon: "pen-nib", ischecked: ComputedField.MakeFunction(`sameDocs(this.activeInkPen, this)`), activeInkPen: doc }); } if (doc["dockedBtn-undo"] === undefined) { - doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), title: "undo button", icon: "undo-alt" }); + doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), toolTip: "click to undo", title: "undo", icon: "undo-alt" }); } if (doc["dockedBtn-redo"] === undefined) { - doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), title: "redo button", icon: "redo-alt" }); + doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), toolTip: "click to redo", title: "redo", icon: "redo-alt" }); } if (doc.dockedBtns === undefined) { doc.dockedBtns = CurrentUserUtils.blist({ title: "docked buttons", ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc, doc["dockedBtn-pen"] as Doc]); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 5f34509a1..6a3108157 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -83,6 +83,7 @@ export namespace DragManager { hideSource?: boolean; // hide source document during drag offsetX?: number; // offset of top left of source drag visual from cursor offsetY?: number; + noAutoscroll?: boolean; } // event called when the drag operation results in a drop action @@ -225,13 +226,16 @@ export namespace DragManager { // drag a button template and drop a new button export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: Field }, params: string[], initialize: (button: Doc) => void, downX: number, downY: number, options?: DragOptions) { const finishDrag = (e: DragCompleteEvent) => { - const bd = Docs.Create.ButtonDocument({ _width: 150, _height: 50, title, onClick: ScriptField.MakeScript(script) }); + const bd = params.length > Object.keys(vars).length ? + Docs.Create.ButtonDocument({ toolTip: title, z: 1, _width: 150, _height: 50, title, onClick: ScriptField.MakeScript(script) }) : + Docs.Create.FontIconDocument({ toolTip: title, z: 1, _nativeWidth: 30, _nativeHeight: 30, _width: 30, _height: 30, title, onClick: ScriptField.MakeScript(script) }); params.map(p => Object.keys(vars).indexOf(p) !== -1 && (Doc.GetProto(bd)[p] = new PrefetchProxy(vars[p] as Doc))); // copy all "captured" arguments into document parameterfields initialize?.(bd); Doc.GetProto(bd)["onClick-paramFieldKeys"] = new List(params); e.docDragData && (e.docDragData.droppedDocuments = [bd]); return e; }; + options && (options.noAutoscroll = true); StartDrag(eles, new DragManager.DocumentDragData([]), downX, downY, options, finishDrag); } @@ -431,7 +435,7 @@ export namespace DragManager { const complete = new DragCompleteEvent(false, dragData); - if (target) { + if (target && !options?.noAutoscroll) { target.dispatchEvent( new CustomEvent("dashDragging", { bubbles: true, diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index cdd653823..84e5d56cb 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -62,37 +62,37 @@ export class CollectionViewBaseChrome extends React.Component item view", - script: "this.target.childLayout = getDocTemplate(this.source?.[0])", - immediate: undoBatch((source: Doc[]) => source.length && (this.target.childLayout = Doc.getDocTemplate(source?.[0]))), + params: ["target", "source"], title: "item view", + script: "this.target.childLayoutTemplate = getDocTemplate(this.source?.[0])", + immediate: undoBatch((source: Doc[]) => source.length && (this.target.childLayoutTemplate = Doc.getDocTemplate(source?.[0]))), initialize: emptyFunction, }; _narrativeCommand = { - params: ["target", "source"], title: "=> child click view", + params: ["target", "source"], title: "child click view", script: "this.target.childClickedOpenTemplateView = getDocTemplate(this.source?.[0])", immediate: undoBatch((source: Doc[]) => source.length && (this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]))), initialize: emptyFunction, }; _contentCommand = { - params: ["target", "source"], title: "=> clear content", + params: ["target", "source"], title: "clear content", script: "getProto(this.target).data = copyField(this.source);", immediate: undoBatch((source: Doc[]) => Doc.GetProto(this.target).data = new List(source)), // Doc.aliasDocs(source), initialize: emptyFunction, }; _viewCommand = { - params: ["target"], title: "=> reset view", - script: "this.target._panX = this.restoredPanX; this.target._panY = this.restoredPanY; this.target.scale = this.restoredScale;", - immediate: undoBatch((source: Doc[]) => { this.target._panX = 0; this.target._panY = 0; this.target.scale = 1; }), - initialize: (button: Doc) => { button.restoredPanX = this.target._panX; button.restoredPanY = this.target._panY; button.restoredScale = this.target.scale; }, + params: ["target"], title: "bookmark view", + script: "this.target._panX = this['target-panX']; this.target._panY = this['target-panY']; this.target._viewScale = this['target-viewScale'];", + immediate: undoBatch((source: Doc[]) => { this.target._panX = 0; this.target._panY = 0; this.target._viewScale = 1; }), + initialize: (button: Doc) => { button['target-panX'] = this.target._panX; button['target-panY'] = this.target._panY; button['target-viewScale'] = this.target._viewScale; }, }; _clusterCommand = { - params: ["target"], title: "=> fit content", + params: ["target"], title: "fit content", script: "this.target._fitToBox = !this.target._fitToBox;", immediate: undoBatch((source: Doc[]) => this.target._fitToBox = !this.target._fitToBox), initialize: emptyFunction }; _fitContentCommand = { - params: ["target"], title: "=> toggle clusters", + params: ["target"], title: "toggle clusters", script: "this.target.useClusters = !this.target.useClusters;", immediate: undoBatch((source: Doc[]) => this.target.useClusters = !this.target.useClusters), initialize: emptyFunction diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 922cb17fe..e119910bd 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -953,8 +953,8 @@ export class CollectionFreeFormView extends CollectionSubView( render() { const referenceDoc = (this.layoutDoc.dragFactory instanceof Doc ? this.layoutDoc.dragFactory : this.layoutDoc); const refLayout = Doc.Layout(referenceDoc); - return ; + return {StrCast(this.layoutDoc.toolTip)}}> + + ; } } \ No newline at end of file diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 9890ef2c1..3c7c58126 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -319,7 +319,7 @@ export default class RichTextMenu extends AntimodeMenu { } destroy() { - !this.TextView.props.isSelected(false) && this.fadeOut(true); + !this.TextView?.props.isSelected(false) && this.fadeOut(true); } @action @@ -657,7 +657,7 @@ export default class RichTextMenu extends AntimodeMenu { @action toggleColorDropdown() { this.showColorDropdown = !this.showColorDropdown; } @action setActiveColor(color: string) { this.activeFontColor = color; } - get TextView() { return (this.view as any).TextView as FormattedTextBox; } + get TextView() { return (this.view as any)?.TextView as FormattedTextBox; } createColorButton() { const self = this; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 7aa1d528d..3ad9f4e41 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -899,9 +899,12 @@ export namespace Doc { } export function getDocTemplate(doc?: Doc) { - return doc?.isTemplateDoc ? doc : - Cast(doc?.dragFactory, Doc, null)?.isTemplateDoc ? doc?.dragFactory : - Cast(doc?.layout, Doc, null)?.isTemplateDoc ? doc?.layout : undefined; + return !doc ? undefined : + doc.isTemplateDoc ? doc : + Cast(doc.dragFactory, Doc, null)?.isTemplateDoc ? doc.dragFactory : + Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc ? + (Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc ? Doc.Layout(doc).proto : Doc.Layout(doc)) : + undefined; } export function matchFieldValue(doc: Doc, key: string, value: any): boolean { -- cgit v1.2.3-70-g09d2 From a55e62848e7c796776af932f5935165d3d67e8cb Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 17 Jul 2020 11:32:52 -0400 Subject: fixes for minimap when collections have an overlay layer or template child views. --- src/client/views/collections/CollectionDockingView.tsx | 3 +++ .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 8938541ac..53b2d5254 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -829,6 +829,7 @@ export class DockedFrameRenderer extends React.Component { @computed get miniTop() { return 50 + (NumCast(this._document?._panY) - this.renderContentBounds.cy) / this.renderContentBounds.dim * 100 - this.miniHeight / 2; } @computed get miniWidth() { return this.panelWidth() / NumCast(this._document?._viewScale, 1) / this.renderContentBounds.dim * 100; } @computed get miniHeight() { return this.panelHeight() / NumCast(this._document?._viewScale, 1) / this.renderContentBounds.dim * 100; } + childLayoutTemplate = () => Cast(this._document?.childLayoutTemplate, Doc, null); returnMiniSize = () => NumCast(this._document?._miniMapSize, 150); miniDown = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => { @@ -848,6 +849,8 @@ export class DockedFrameRenderer extends React.Component { CollectionView={undefined} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} + ChildLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid havin to set stuff like this. + noOverlay={true} // don't render overlay Docs since they won't scale active={returnTrue} select={emptyFunction} dropAction={undefined} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index e119910bd..01b0c81d8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -75,7 +75,8 @@ export type collectionFreeformViewProps = { forceScaling?: boolean; // whether to force scaling of content (needed by ImageBox) viewDefDivClick?: ScriptField; childPointerEvents?: boolean; - scaleField?: string; + scaleField?: string; // used by formattedTextBox when displaying a sidebar freeform view which needs its own scale field + noOverlay?: boolean; // used to suppress docs in the overlay (z) layer (ie, for minimap since overlay doesn't scale) }; @observer @@ -1444,7 +1445,7 @@ export class CollectionFreeFormView extends CollectionSubView {this.Document._freeformLOD && !this.props.active() && !this.props.isAnnotationOverlay && !this.props.annotationsKey && this.props.renderDepth > 0 ? this.placeholder : this.marqueeView} - + {!this.props.noOverlay ? : (null)}
Date: Fri, 17 Jul 2020 14:40:01 -0400 Subject: fixes for collectionMenu button sizes. --- src/client/views/collections/CollectionMenu.scss | 20 ++++++++++++-------- src/client/views/collections/CollectionMenu.tsx | 20 ++++++++++---------- 2 files changed, 22 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index 348b9e6ea..0da78df9f 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -16,7 +16,7 @@ .antimodeMenu-button { padding:0; - width:40px; + width:30px; display: flex; svg { margin:auto; @@ -37,13 +37,11 @@ .collectionViewBaseChrome-viewPicker { font-size: 75%; - //text-transform: uppercase; - //letter-spacing: 2px; background: #121721; - color: white; outline-color: black; + color: white; border: none; - //padding: 12px 10px 11px 10px; + border-right: solid gray 1px; } .collectionViewBaseChrome-viewPicker:active { @@ -67,8 +65,9 @@ margin-right: 0px; font-size: 75%; background: #121721; - border: none; color: white; + border: none; + border-right: solid gray 1px; } .commandEntry-outerDiv { @@ -89,7 +88,7 @@ .collectionViewBaseChrome-collapse { transition: all .5s, opacity 0.3s; position: absolute; - width: 40px; + width: 30px; transform-origin: top left; pointer-events: all; // margin-top: 10px; @@ -112,6 +111,8 @@ .collectionViewBaseChrome-viewSpecs { margin-left: 5px; display: grid; + border: none; + border-right: solid gray 1px; .collectionViewBaseChrome-filterIcon { position: relative; @@ -123,6 +124,8 @@ height: 30px; align-items: center; justify-content: center; + border: none; + border-right: solid gray 1px; } .collectionViewBaseChrome-viewSpecsInput { @@ -201,8 +204,9 @@ background: #121721; color: white; outline-color: black; + color: white; border: none; - //padding: 12px 10px 11px 10px; + border-right: solid gray 1px; } .collectionGridViewChrome-viewPicker:active { diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 84e5d56cb..f3ad21949 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -211,9 +211,9 @@ export class CollectionViewBaseChrome extends React.Component
-
- -
+
{this.viewModes} + {this.templateChrome}
-
- -
+
- {this.templateChrome}
{this.subChrome}
-- cgit v1.2.3-70-g09d2 From 2df5e1fb9c249ab29c0d8fc56d0a2ce394ae6643 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 17 Jul 2020 17:10:43 -0400 Subject: got rid of InkOptionsMenu. Merged into CollectionFreeFormViewChrome. --- src/client/util/CurrentUserUtils.ts | 8 +- src/client/views/GestureOverlay.tsx | 10 +- src/client/views/GlobalKeyHandler.ts | 2 + src/client/views/MainView.tsx | 6 +- src/client/views/collections/CollectionMenu.scss | 61 +++++-- src/client/views/collections/CollectionMenu.tsx | 161 ++++++++++++++++- .../collectionFreeForm/InkOptionsMenu.scss | 83 --------- .../collectionFreeForm/InkOptionsMenu.tsx | 194 --------------------- src/mobile/MobileInterface.tsx | 4 +- 9 files changed, 213 insertions(+), 316 deletions(-) delete mode 100644 src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss delete mode 100644 src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 892d0ca1d..58d3848a3 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -732,12 +732,6 @@ export class CurrentUserUtils { /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window static setupDockedButtons(doc: Doc) { - if (doc["dockedBtn-pen"] === undefined) { - doc["dockedBtn-pen"] = CurrentUserUtils.ficon({ - onClick: ScriptField.MakeScript("activatePen(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this)"), - author: "systemTemplates", toolTip: "open drawing tools", title: "draw", icon: "pen-nib", ischecked: ComputedField.MakeFunction(`sameDocs(this.activeInkPen, this)`), activeInkPen: doc - }); - } if (doc["dockedBtn-undo"] === undefined) { doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), toolTip: "click to undo", title: "undo", icon: "undo-alt" }); } @@ -745,7 +739,7 @@ export class CurrentUserUtils { doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), toolTip: "click to redo", title: "redo", icon: "redo-alt" }); } if (doc.dockedBtns === undefined) { - doc.dockedBtns = CurrentUserUtils.blist({ title: "docked buttons", ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc, doc["dockedBtn-pen"] as Doc]); + doc.dockedBtns = CurrentUserUtils.blist({ title: "docked buttons", ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc]); } } // sets up the default set of documents to be shown in the Overlay layer diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 2f34cbc05..b0b0d72b1 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -22,7 +22,7 @@ import { RadialMenu } from "./nodes/RadialMenu"; import HorizontalPalette from "./Palette"; import { Touchable } from "./Touchable"; import TouchScrollableMenu, { TouchScrollableMenuItem } from "./TouchScrollableMenu"; -import InkOptionsMenu from "./collections/collectionFreeForm/InkOptionsMenu"; +import { CollectionFreeFormViewChrome } from "./collections/CollectionMenu"; @observer export default class GestureOverlay extends Touchable { @@ -603,12 +603,12 @@ export default class GestureOverlay extends Touchable { break; } } - //if any of the shape is activated in the InkOptionsMenu + //if any of the shape is activated in the CollectionFreeFormViewChrome else if (this.InkShape) { this.makePolygon(this.InkShape, false); this.dispatchGesture(GestureUtils.Gestures.Stroke); this._points = []; - if (!InkOptionsMenu.Instance._keepMode) { + if (!CollectionFreeFormViewChrome.Instance._keepMode) { this.InkShape = ""; } } @@ -639,9 +639,9 @@ export default class GestureOverlay extends Touchable { this._points = []; } //get out of ink mode after each stroke= - if (!InkOptionsMenu.Instance._keepMode) { + if (!CollectionFreeFormViewChrome.Instance._keepMode) { Doc.SetSelectedTool(InkTool.None); - InkOptionsMenu.Instance._selected = InkOptionsMenu.Instance._shapesNum; + CollectionFreeFormViewChrome.Instance._selected = CollectionFreeFormViewChrome.Instance._shapesNum; SetActiveArrowStart("none"); GestureOverlay.Instance.SavedArrowStart = ActiveArrowStart(); SetActiveArrowEnd("none"); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index a3a023164..8c233489e 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -22,6 +22,7 @@ import { DocumentView } from "./nodes/DocumentView"; import { DocumentLinksButton } from "./nodes/DocumentLinksButton"; import PDFMenu from "./pdf/PDFMenu"; import { ContextMenu } from "./ContextMenu"; +import { CollectionFreeFormViewChrome } from "./collections/CollectionMenu"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -107,6 +108,7 @@ export default class KeyManager { GoogleAuthenticationManager.Instance.cancel(); HypothesisAuthenticationManager.Instance.cancel(); SharingManager.Instance.close(); + CollectionFreeFormViewChrome.Instance.clearKeep(); break; case "delete": case "backspace": diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index e50ff342c..46eeac77a 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -38,7 +38,6 @@ import SharingManager from '../util/SharingManager'; import { Transform } from '../util/Transform'; import { CollectionDockingView } from './collections/CollectionDockingView'; import MarqueeOptionsMenu from './collections/collectionFreeForm/MarqueeOptionsMenu'; -import InkOptionsMenu from './collections/collectionFreeForm/InkOptionsMenu'; import { CollectionLinearView } from './collections/CollectionLinearView'; import { CollectionView, CollectionViewType } from './collections/CollectionView'; import { ContextMenu } from './ContextMenu'; @@ -392,7 +391,7 @@ export class MainView extends React.Component { doc.dockingConfig ? this.openWorkspace(doc) : CollectionDockingView.AddRightSplit(doc, libraryPath); } - sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (InkOptionsMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1); + sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1); mainContainerXf = () => this.sidebarScreenToLocal().translate(0, -this._buttonBarHeight); @computed get flyout() { @@ -469,7 +468,7 @@ export class MainView extends React.Component { @computed get mainContent() { const sidebar = this.userDoc?.["tabs-panelContainer"]; - const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (InkOptionsMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0); + const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0); const height = `calc(100% - ${n * Number(ANTIMODEMENU_HEIGHT.replace("px", ""))}px)`; return !this.userDoc || !(sidebar instanceof Doc) ? (null) : (
- {LinkDescriptionPopup.descriptionPopup ? : null} diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index 0da78df9f..9da204787 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -8,15 +8,15 @@ opacity: 0.9; z-index: 9001; transition: top .5s; - background: #121721; + background: #323232; color: white; transform-origin: top left; top: 0; width:100%; .antimodeMenu-button { - padding:0; - width:30px; + padding: 0; + width: 30px; display: flex; svg { margin:auto; @@ -37,7 +37,7 @@ .collectionViewBaseChrome-viewPicker { font-size: 75%; - background: #121721; + background: #323232; outline-color: black; color: white; border: none; @@ -64,7 +64,7 @@ margin-left: 3px; margin-right: 0px; font-size: 75%; - background: #121721; + background: #323232; color: white; border: none; border-right: solid gray 1px; @@ -72,7 +72,7 @@ .commandEntry-outerDiv { pointer-events: all; - background-color: #121721; + background-color: #323232; display: flex; flex-direction: row; height: 30px; @@ -118,7 +118,7 @@ position: relative; display: flex; margin: auto; - background: #121721; + background: #323232; color: white; width: 30px; height: 30px; @@ -310,28 +310,54 @@ } .collectionFreeFormMenu-cont { - width: 60px; - display: flex; + display: inline-flex; position: relative; align-items: center; + .antimodeMenu-button { + text-align: center; + display: block; + } + .color-previewI { + width: 80%; + height: 20%; + bottom: 0; + position: absolute; + } + .color-previewII { + width: 80%; + height: 80%; + margin-left: 10%; + } + + .btn-group { + display: grid; + grid-template-columns: auto auto auto auto; + margin: auto; + /* Make the buttons appear below each other */ + } + + .btn-draw { + display: inline-flex; + margin: auto; + /* Make the buttons appear below each other */ + } + .fwdKeyframe, .numKeyframe, .backKeyframe { cursor: pointer; - position: absolute; + position: relative; width: 20; height: 30; bottom: 0; - background: #121721; - display: flex; + background: #323232; + display: inline-flex; align-items: center; color: white; } .backKeyframe { - left: 0; - svg { display: block; margin: auto; @@ -339,19 +365,16 @@ } .numKeyframe { - left: 20; - display: flex; flex-direction: column; - padding: 5px; + padding-top: 5px; } .fwdKeyframe { - left: 40; - svg { display: block; margin: auto; } + border-right: solid gray 1px; } } diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index f3ad21949..2be57b6d2 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -1,5 +1,5 @@ import React = require("react"); -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { FontAwesomeIcon, FontAwesomeIconProps } from "@fortawesome/react-fontawesome"; import { action, computed, observable, reaction, runInAction, Lambda } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, Opt } from "../../../fields/Doc"; @@ -15,6 +15,15 @@ import { List } from "../../../fields/List"; import { EditableView } from "../EditableView"; import { Id } from "../../../fields/FieldSymbols"; import { listSpec } from "../../../fields/Schema"; +import FormatShapePane from "./collectionFreeForm/FormatShapePane"; +import { ActiveFillColor, SetActiveInkWidth, ActiveInkColor, SetActiveBezierApprox, SetActiveArrowEnd, SetActiveArrowStart, SetActiveFillColor, SetActiveInkColor } from "../InkingStroke"; +import GestureOverlay from "../GestureOverlay"; +import { InkTool } from "../../../fields/InkField"; +import { DocumentType } from "../../documents/DocumentTypes"; +import { Document } from "../../../fields/documentSchemas"; +import { SelectionManager } from "../../util/SelectionManager"; +import { DocumentView } from "../nodes/DocumentView"; +import { ColorState } from "react-color"; @observer export default class CollectionMenu extends AntimodeMenu { @@ -272,7 +281,11 @@ export class CollectionViewBaseChrome extends React.Component { - + public static Instance: CollectionFreeFormViewChrome; + constructor(props: any) { + super(props); + CollectionFreeFormViewChrome.Instance = this; + } get Document() { return this.props.CollectionView.props.Document; } @computed get dataField() { return this.props.CollectionView.props.Document[Doc.LayoutFieldKey(this.props.CollectionView.props.Document)]; @@ -303,6 +316,144 @@ export class CollectionFreeFormViewChrome extends React.Component { + const col: ColorState = { + hex: color, hsl: { a: 0, h: 0, s: 0, l: 0, source: "" }, hsv: { a: 0, h: 0, s: 0, v: 0, source: "" }, + rgb: { a: 0, r: 0, b: 0, g: 0, source: "" }, oldHue: 0, source: "", + }; + if (type === "color") { + SetActiveInkColor(Utils.colorString(col)); + } else if (type === "fill") { + SetActiveFillColor(Utils.colorString(col)); + } + } + + @action + editProperties = (value: any, field: string) => { + SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { + const doc = Document(element.rootDoc); + if (doc.type === DocumentType.INK) { + switch (field) { + case "width": doc.strokeWidth = Number(value); break; + case "color": doc.color = String(value); break; + case "fill": doc.fillColor = String(value); break; + case "dash": doc.strokeDash = value; + } + } + })); + } + + @computed get drawButtons() { + const func = action((i: number, keep: boolean) => { + this._keepMode = keep; + if (this._selected !== i) { + this._selected = i; + Doc.SetSelectedTool(InkTool.Pen); + SetActiveArrowStart(this._head[i]); + SetActiveArrowEnd(this._end[i]); + SetActiveBezierApprox("300"); + + GestureOverlay.Instance.InkShape = this._shape[i]; + } else { + this._selected = this._shapesNum; + Doc.SetSelectedTool(InkTool.None); + SetActiveArrowStart(""); + SetActiveArrowEnd(""); + GestureOverlay.Instance.InkShape = ""; + SetActiveBezierApprox("0"); + } + }); + return
+ {this._draw.map((icon, i) => + )} +
; + } + + toggleButton = (key: string, value: boolean, setter: () => {}, icon: FontAwesomeIconProps["icon"], ele: JSX.Element | null) => { + return ; + } + + @computed get widthPicker() { + var widthPicker = this.toggleButton("stroke width", this._widthBtn, () => this._widthBtn = !this._widthBtn, "bars", null); + return !this._widthBtn ? widthPicker : +
+ {widthPicker} + {this._width.map(wid => + )} +
; + } + + @computed get colorPicker() { + var colorPicker = this.toggleButton("stroke color", this._colorBtn, () => this._colorBtn = !this._colorBtn, "pen-nib", +
); + return !this._colorBtn ? colorPicker : +
+ {colorPicker} + {this._palette.map(color => + )} +
; + } + @computed get fillPicker() { + var fillPicker = this.toggleButton("shape fill color", this._fillBtn, () => this._fillBtn = !this._fillBtn, "fill-drip", +
); + return !this._fillBtn ? fillPicker : +
+ {fillPicker} + {this._palette.map(color => + )} + +
; + } + + @computed get formatPane() { + return ; + } + render() { return this.Document.isAnnotationOverlay ? (null) :
@@ -316,6 +467,12 @@ export class CollectionFreeFormViewChrome extends React.Component
+ + {this.widthPicker} + {this.colorPicker} + {this.fillPicker} + {this.drawButtons} + {this.formatPane}
; } } diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss deleted file mode 100644 index 03c6c97ab..000000000 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.scss +++ /dev/null @@ -1,83 +0,0 @@ -.antimodeMenu-button { - .color-previewI { - width: 100%; - height: 40%; - } - - .color-previewII { - width: 100%; - height: 100%; - } - -} - -.sketch-picker { - background: #323232; - - .flexbox-fit { - background: #323232; - } -} - -.btn-group { - display: grid; - grid-template-columns: auto auto auto auto; - /* Make the buttons appear below each other */ -} - -.btn-draw { - display: inline; - /* Make the buttons appear below each other */ -} - -.btn2-group { - display: grid; - background: #323232; - grid-template-columns: auto; - - /* Make the buttons appear below each other */ - .antimodeMenu-button { - background: #323232; - display: block; - - } -} - -@media only screen and (max-device-width: 480px) { - .antimodeMenu-button { - font-size: 50%; - - .color-preview { - width: 100%; - height: 100%; - } - - } - - .sketch-picker { - background: #323232; - - .flexbox-fit { - background: #323232; - } - } - - .btn-group { - display: grid; - grid-template-columns: auto auto; - /* Make the buttons appear below each other */ - } - - .btn2-group { - display: block; - background: #323232; - grid-template-columns: auto; - - /* Make the buttons appear below each other */ - .antimodeMenu-button { - background: #323232; - display: block; - font-size: 50%; - } - } -} \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx deleted file mode 100644 index 23e1c194a..000000000 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx +++ /dev/null @@ -1,194 +0,0 @@ -import React = require("react"); -import AntimodeMenu from "../../AntimodeMenu"; -import { observer } from "mobx-react"; -import { observable, action, computed } from "mobx"; -import "./InkOptionsMenu.scss"; -import { ActiveInkColor, ActiveFillColor, SetActiveInkWidth, SetActiveInkColor, SetActiveBezierApprox, SetActiveFillColor, SetActiveArrowStart, SetActiveArrowEnd, ActiveDash, SetActiveDash } from "../../InkingStroke"; -import { Scripting } from "../../../util/Scripting"; -import { InkTool } from "../../../../fields/InkField"; -import { ColorState } from "react-color"; -import { Utils } from "../../../../Utils"; -import GestureOverlay from "../../GestureOverlay"; -import { Doc } from "../../../../fields/Doc"; -import { SelectionManager } from "../../../util/SelectionManager"; -import { DocumentView } from "../../../views/nodes/DocumentView"; -import { Document } from "../../../../fields/documentSchemas"; -import { DocumentType } from "../../../documents/DocumentTypes"; -import { FontAwesomeIcon, FontAwesomeIconProps } from "@fortawesome/react-fontawesome"; -import { BoolCast } from "../../../../fields/Types"; -import FormatShapePane from "./FormatShapePane"; - -@observer -export default class InkOptionsMenu extends AntimodeMenu { - static Instance: InkOptionsMenu; - - private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", ""]; - private _width = ["1", "5", "10", "100"]; - private _draw = ["⎯", "→", "↔︎", "∿", "↝", "↭", "ロ", "O", "∆"]; - private _head = ["", "", "arrow", "", "", "arrow", "", "", ""]; - private _end = ["", "arrow", "arrow", "", "arrow", "arrow", "", "", ""]; - private _shape = ["line", "line", "line", "", "", "", "rectangle", "circle", "triangle"]; - - @observable _shapesNum = this._shape.length; - @observable _selected = this._shapesNum; - - @observable _collapsed = false; - @observable _keepMode = false; - - @observable _colorBtn = false; - @observable _widthBtn = false; - @observable _fillBtn = false; - - constructor(props: Readonly<{}>) { - super(props); - InkOptionsMenu.Instance = this; - this._canFade = false; // don't let the inking menu fade away - this.Pinned = BoolCast(Doc.UserDoc()["menuInkOptions-pinned"]); - } - - @action - toggleMenuPin = (e: React.MouseEvent) => { - Doc.UserDoc()["menuInkOptions-pinned"] = this.Pinned = !this.Pinned; - } - - @action - changeColor = (color: string, type: string) => { - const col: ColorState = { - hex: color, hsl: { a: 0, h: 0, s: 0, l: 0, source: "" }, hsv: { a: 0, h: 0, s: 0, v: 0, source: "" }, - rgb: { a: 0, r: 0, b: 0, g: 0, source: "" }, oldHue: 0, source: "", - }; - if (type === "color") { - SetActiveInkColor(Utils.colorString(col)); - } else if (type === "fill") { - SetActiveFillColor(Utils.colorString(col)); - } - } - - @action - editProperties = (value: any, field: string) => { - SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { - const doc = Document(element.rootDoc); - if (doc.type === DocumentType.INK) { - switch (field) { - case "width": doc.strokeWidth = Number(value); break; - case "color": doc.color = String(value); break; - case "fill": doc.fillColor = String(value); break; - case "dash": doc.strokeDash = value; - } - } - })); - } - - @computed get drawButtons() { - const func = action((i: number, keep: boolean) => { - this._keepMode = keep; - if (this._selected !== i) { - this._selected = i; - Doc.SetSelectedTool(InkTool.Pen); - SetActiveArrowStart(this._head[i]); - SetActiveArrowEnd(this._end[i]); - SetActiveBezierApprox("300"); - - GestureOverlay.Instance.InkShape = this._shape[i]; - } else { - this._selected = this._shapesNum; - Doc.SetSelectedTool(InkTool.None); - SetActiveArrowStart(""); - SetActiveArrowEnd(""); - GestureOverlay.Instance.InkShape = ""; - SetActiveBezierApprox("0"); - } - }); - return
- {this._draw.map((icon, i) => - )} -
; - } - - toggleButton = (key: string, value: boolean, setter: () => {}, icon: FontAwesomeIconProps["icon"], ele: JSX.Element | null) => { - return ; - } - - @computed get widthPicker() { - var widthPicker = this.toggleButton("stroke width", this._widthBtn, () => this._widthBtn = !this._widthBtn, "bars", null); - return !this._widthBtn ? widthPicker : -
- {widthPicker} - {this._width.map(wid => - )} -
; - } - - @computed get colorPicker() { - var colorPicker = this.toggleButton("stroke color", this._colorBtn, () => this._colorBtn = !this._colorBtn, "pen-nib", -
); - return !this._colorBtn ? colorPicker : -
- {colorPicker} - {this._palette.map(color => - )} -
; - } - @computed get fillPicker() { - var fillPicker = this.toggleButton("shape fill color", this._fillBtn, () => this._fillBtn = !this._fillBtn, "fill-drip", -
); - return !this._fillBtn ? fillPicker : -
- {fillPicker} - {this._palette.map(color => - )} - -
; - } - - @computed get formatPane() { - return ; - } - - render() { - return this.getElement([ - this.widthPicker, - this.colorPicker, - this.fillPicker, - this.drawButtons, - this.formatPane, - - ]); - } -} -Scripting.addGlobal(function activatePen(penBtn: any) { - if (penBtn) { - InkOptionsMenu.Instance.jumpTo(300, 300); - InkOptionsMenu.Instance.Pinned = true; - } else { - InkOptionsMenu.Instance.Pinned = false; - InkOptionsMenu.Instance.fadeOut(true); - } -}); diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index fafa94a11..3a889b0db 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -28,7 +28,6 @@ import { DockedFrameRenderer } from '../client/views/collections/CollectionDocki import { InkTool } from '../fields/InkField'; import GestureOverlay from "../client/views/GestureOverlay"; import { ScriptField } from "../fields/ScriptField"; -import InkOptionsMenu from "../client/views/collections/collectionFreeForm/InkOptionsMenu"; import { RadialMenu } from "../client/views/nodes/RadialMenu"; import { UndoManager } from "../client/util/UndoManager"; import { List } from "../fields/List"; @@ -38,6 +37,7 @@ import RichTextMenu from "../client/views/nodes/formattedText/RichTextMenu"; import { AudioBox } from "../client/views/nodes/AudioBox"; import { CollectionViewType } from "../client/views/collections/CollectionView"; import { DocumentType } from "../client/documents/DocumentTypes"; +import { CollectionFreeFormViewChrome } from "../client/views/collections/CollectionMenu"; library.add(faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngleDoubleLeft, faExternalLinkSquareAlt, faMobile, faThLarge, faWindowClose, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus, faTerminal, faToggleOn, fileSolid, faExternalLinkAlt, faLocationArrow, faSearch, faFileDownload, faStop, faCalculator, faWindowMaximize, faAddressCard, @@ -429,7 +429,7 @@ export class MobileInterface extends React.Component { @computed get inkMenu() { return this._activeDoc._viewType !== CollectionViewType.Docking || !this._ink ? (null) :
- + {/* */}
; } -- cgit v1.2.3-70-g09d2 From 9cba3f3a7285b08d3b805a39294b731ae0cd1de2 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 18 Jul 2020 17:43:21 -0400 Subject: fixed long linking to work with text selections --- src/client/views/DocumentButtonBar.tsx | 1 - src/client/views/nodes/DocumentLinksButton.tsx | 9 +++------ 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 45f4c7393..c99034d81 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -51,7 +51,6 @@ enum UtilityButtonState { @observer export class DocumentButtonBar extends React.Component<{ views: () => (DocumentView | undefined)[], stack?: any }, {}> { - private _linkButton = React.createRef(); private _dragRef = React.createRef(); private _pullAnimating = false; private _pushAnimating = false; diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index bbef48e44..13bec5d7f 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -93,9 +93,6 @@ export class DocumentLinksButton extends React.Component) => { - // Doc.UnBrushDoc(this.props.View.Document); - // }); } else { if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) { @@ -126,13 +123,13 @@ export class DocumentLinksButton extends React.Component { if (DocumentLinksButton.StartLink === this.props.View) { DocumentLinksButton.StartLink = undefined; - // action((e: React.PointerEvent) => { - // Doc.UnBrushDoc(this.props.View.Document); - // }); } else { if (this.props.InMenu && !!!this.props.StartLink) { if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) { const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag"); + // this notifies any of the subviews that a document is made so that they can make finer-grained hyperlinks (). see note above in onLInkButtonMoved + runInAction(() => DocumentLinksButton.StartLink!._link = this.props.View._link = linkDoc); + setTimeout(action(() => DocumentLinksButton.StartLink!._link = this.props.View._link = undefined), 0); LinkManager.currentLink = linkDoc; runInAction(() => { -- cgit v1.2.3-70-g09d2 From 9aad53f026f463d15769dcfed47d6ce4df61e143 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 18 Jul 2020 17:47:32 -0400 Subject: from last --- src/client/views/nodes/formattedText/RichTextMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 3c7c58126..2e0b0e659 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -319,7 +319,7 @@ export default class RichTextMenu extends AntimodeMenu { } destroy() { - !this.TextView?.props.isSelected(false) && this.fadeOut(true); + !this.TextView?.props.isSelected(true) && this.fadeOut(true); } @action -- cgit v1.2.3-70-g09d2 From d21ef189f2c160d3d80a5cf7d824c314262a59ac Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 19 Jul 2020 22:24:19 -0400 Subject: removed spurious point --- src/client/util/InteractionUtils.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 07adbb8b1..473d4a263 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -112,7 +112,11 @@ export namespace InteractionUtils { } } } else { - pts = points; + pts = points.slice(); + // bcz: Ugh... this is ugly, but shapes apprently have an extra point added that is = (p[0].x,p[0].y+1) as some sort of flag. need to remove it here. + if (pts.length > 2 && pts[pts.length - 2].X === pts[0].X && pts[pts.length - 2].Y === pts[0].Y) { + pts.pop(); + } } const strpts = pts.reduce((acc: string, pt: { X: number, Y: number }) => acc + `${(pt.X - left - width / 2) * scalex + width / 2}, -- cgit v1.2.3-70-g09d2