From 6b070202843e1e2a11c09c4d29aee4ab8750f31f Mon Sep 17 00:00:00 2001 From: geireann Date: Thu, 24 Oct 2024 12:01:21 -0400 Subject: fixed pinning of card and carousel views. --- src/client/views/collections/CollectionCardDeckView.tsx | 6 +++--- src/client/views/collections/CollectionCarousel3DView.tsx | 6 +++--- src/client/views/collections/CollectionCarouselView.tsx | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index beb45f326..3a5cb5f37 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -19,7 +19,7 @@ import { dropActionType } from '../../util/DropActionTypes'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoable } from '../../util/UndoManager'; -import { PinDocView } from '../PinFuncs'; +import { PinDocView, PinProps } from '../PinFuncs'; import { StyleProp } from '../StyleProp'; import { TagItem } from '../TagsView'; import { DocumentView, DocumentViewProps } from '../nodes/DocumentView'; @@ -608,9 +608,9 @@ export class CollectionCardView extends CollectionSubView() { } return undefined; }); - getAnchor = (addAsAnnotation: boolean) => { + getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { const anchor = Docs.Create.ConfigDocument({ annotationOn: this.Document, config_card_curDoc: this.curDoc() }); - PinDocView(anchor, { pinData: { collectionType: true, filters: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { collectionType: true, filters: true } }, this.Document); addAsAnnotation && Doc.AddDocToList(this.dataDoc, this.fieldKey + '_annotations', anchor); // when added as an annotation, links to anchors can be found as links to the document even if the anchors are not rendered return anchor; }; diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index c080ba27e..b7ecf9a2f 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -12,7 +12,7 @@ import { DocumentType } from '../../documents/DocumentTypes'; import { Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { Transform } from '../../util/Transform'; -import { PinDocView } from '../PinFuncs'; +import { PinDocView, PinProps } from '../PinFuncs'; import { StyleProp } from '../StyleProp'; import { DocumentView } from '../nodes/DocumentView'; import { FocusViewOptions } from '../nodes/FocusViewOptions'; @@ -107,9 +107,9 @@ export class CollectionCarousel3DView extends CollectionSubView() { } return undefined; }; - getAnchor = (addAsAnnotation: boolean) => { + getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { const anchor = Docs.Create.ConfigDocument({ annotationOn: this.Document, config_carousel_index: this.layoutDoc._carousel_index as number }); - PinDocView(anchor, { pinData: { collectionType: true, filters: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { collectionType: true, filters: true } }, this.Document); addAsAnnotation && Doc.AddDocToList(this.dataDoc, this.fieldKey + '_annotations', anchor); // when added as an annotation, links to anchors can be found as links to the document even if the anchors are not rendered return anchor; }; diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index f714e2a00..87c6e3e5c 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -8,7 +8,7 @@ import { BoolCast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields import { DocumentType } from '../../documents/DocumentTypes'; import { Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; -import { PinDocView } from '../PinFuncs'; +import { PinDocView, PinProps } from '../PinFuncs'; import { StyleProp } from '../StyleProp'; import { DocumentView } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; @@ -84,9 +84,9 @@ export class CollectionCarouselView extends CollectionSubView() { return undefined; }; - getAnchor = (addAsAnnotation: boolean) => { + getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { const anchor = Docs.Create.ConfigDocument({ annotationOn: this.Document, config_carousel_index: this.carouselIndex }); - PinDocView(anchor, { pinData: { collectionType: true, filters: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { collectionType: true, filters: true } }, this.Document); addAsAnnotation && Doc.AddDocToList(this.dataDoc, this.fieldKey + '_annotations', anchor); // when added as an annotation, links to anchors can be found as links to the document even if the anchors are not rendered return anchor; }; -- cgit v1.2.3-70-g09d2 From 311836b7a013d37dccb7b74d7ce787cea448de38 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 31 Oct 2024 10:07:27 -0400 Subject: restored smartdraw ink mode. siwtched to enums for setting ink properties. --- src/client/util/CurrentUserUtils.ts | 36 ++++++++++++++++---------------- src/client/views/global/globalScripts.ts | 21 +++++++------------ src/fields/InkField.ts | 8 +++++++ 3 files changed, 34 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 98a3e8914..fe23fe062 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -4,7 +4,7 @@ import * as rp from 'request-promise'; import { ClientUtils, OmitKeys } from "../../ClientUtils"; import { Doc, DocListCast, DocListCastAsync, FieldType, Opt } from "../../fields/Doc"; import { DocData } from "../../fields/DocSymbols"; -import { InkEraserTool, InkInkTool, InkTool } from "../../fields/InkField"; +import { InkEraserTool, InkInkTool, InkProperty, InkTool } from "../../fields/InkField"; import { List } from "../../fields/List"; import { PrefetchProxy } from "../../fields/Proxy"; import { RichTextField } from "../../fields/RichTextField"; @@ -759,27 +759,27 @@ pie title Minerals in my tap water static inkTools():Button[] { return [ - { title: "Circle", toolTip: "Circle (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "circle", toolType: Gestures.Circle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, - { title: "Square", toolTip: "Square (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "square", toolType: Gestures.Rectangle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, - { title: "Line", toolTip: "Line (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "minus", toolType: Gestures.Line, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, - { title: "Ink", toolTip: "Ink", btnType: ButtonType.MultiToggleButton, toolType: InkTool.Ink, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, + { title: "Circle", toolTip: "Circle (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "circle", toolType: Gestures.Circle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, + { title: "Square", toolTip: "Square (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "square", toolType: Gestures.Rectangle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, + { title: "Line", toolTip: "Line (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "minus", toolType: Gestures.Line, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} }, + { title: "Ink", toolTip: "Ink", btnType: ButtonType.MultiToggleButton, toolType: InkTool.Ink, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, subMenu: [ - { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", toolType: InkInkTool.Pen, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }}, - { title: "Highlight",toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", toolType: InkInkTool.Highlight, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }}, - { title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", toolType: InkInkTool.Write, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }}, + { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", toolType: InkInkTool.Pen, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }}, + { title: "Highlight",toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", toolType: InkInkTool.Highlight, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }}, + { title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", toolType: InkInkTool.Write, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }}, ]}, - { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: "strokeWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}, numBtnMin: 1, linearBtnWidth:40}, - { title: "Color", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: "strokeColor", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}}, - { title: "Eraser", toolTip: "Eraser (Ctrl+E)", btnType: ButtonType.MultiToggleButton, toolType: InkTool.Eraser, scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }, + { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: InkProperty.StrokeWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}, numBtnMin: 1, linearBtnWidth:40}, + { title: "Color", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: InkProperty.StrokeColor,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}}, + { title: "Eraser", toolTip: "Eraser (Ctrl+E)", btnType: ButtonType.MultiToggleButton, toolType: InkTool.Eraser, scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }, subMenu: [ - { title: "Stroke", toolTip: "Eraser complete strokes",btnType: ButtonType.ToggleButton, icon: "eraser", toolType:InkEraserTool.Stroke, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}}, - { title: "Segment", toolTip: "Erase segments up to intersections",btnType: ButtonType.ToggleButton,icon: "xmark",toolType:InkEraserTool.Segment,ignoreClick:true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}}, - { title: "Area", toolTip: "Erase like a pencil", btnType: ButtonType.ToggleButton, icon: "circle-xmark",toolType:InkEraserTool.Radius, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}}, + { title: "Stroke", toolTip: "Eraser complete strokes",btnType: ButtonType.ToggleButton, icon: "eraser", toolType:InkEraserTool.Stroke, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}}, + { title: "Segment", toolTip: "Erase between intersections",btnType:ButtonType.ToggleButton,icon:"xmark", toolType:InkEraserTool.Segment, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}}, + { title: "Area", toolTip: "Erase like a pencil", btnType: ButtonType.ToggleButton, icon: "circle-xmark",toolType:InkEraserTool.Radius, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}}, ]}, - { title: " Size", toolTip: "Size of area pencil eraser", btnType: ButtonType.NumberSliderButton, toolType: "eraserWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"NotRadiusEraser()"}, numBtnMin: 1, linearBtnWidth:40}, - { title: "Mask", toolTip: "Make Stroke a Stencil Mask", btnType: ButtonType.ToggleButton, icon: "user-circle",toolType: "inkMask", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"IsNoviceMode()" } }, - { title: "Labels", toolTip: "Show Labels Inside Shapes", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: "labels", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}}, - { title: "Smart Draw", toolTip: "Draw with GPT", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: "smartdraw", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}}, + { title: " Size", toolTip: "Size of area pencil eraser", btnType: ButtonType.NumberSliderButton, toolType: InkProperty.EraserWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"NotRadiusEraser()"}, numBtnMin: 1, linearBtnWidth:40}, + { title: "Mask", toolTip: "Make Stroke a Stencil Mask", btnType: ButtonType.ToggleButton, icon: "user-circle", toolType: InkProperty.Mask, scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"IsNoviceMode()" } }, + { title: "Labels", toolTip: "Show Labels Inside Shapes", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: InkProperty.Labels, scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}}, + { title: "Smart Draw", toolTip: "Draw with GPT", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: InkTool.SmartDraw, scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}}, ]; } diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 40144c4ce..5a17bc8f6 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -3,7 +3,7 @@ import { Colors } from 'browndash-components'; import { runInAction } from 'mobx'; import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; -import { InkEraserTool, InkInkTool, InkTool } from '../../../fields/InkField'; +import { InkEraserTool, InkInkTool, InkProperty, InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; @@ -430,36 +430,31 @@ ScriptingGlobals.add(function activeEraserTool() { // toggle: Set overlay status of selected document // eslint-disable-next-line prefer-arrow-callback -ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor' | 'eraserWidth', value: string | number, checkResult?: boolean) { +ScriptingGlobals.add(function setInkProperty(option: InkProperty, value: string | number, checkResult?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); // prettier-ignore - const map: Map<'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor' | 'eraserWidth', { checkResult: () => number|boolean|string|undefined; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([ - ['inkMask', { + const map: Map number|boolean|string|undefined; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([ + [InkProperty.Mask, { checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected[DocData].stroke_isInkMask) : ActiveIsInkMask())), setInk: (doc: Doc) => { doc[DocData].stroke_isInkMask = !doc.stroke_isInkMask; }, setMode: () => SetActiveIsInkMask(value ? true : false) }], - ['labels', { + [InkProperty.Labels, { checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected[DocData].stroke_showLabel) : !ActiveHideTextLabels())), setInk: (doc: Doc) => { doc[DocData].stroke_showLabel = value; }, setMode: () => SetactiveHideTextLabels(value? false : true), }], - ['fillColor', { - checkResult: () => (selected?._layout_isSvg ? StrCast(selected[DocData].fillColor) : ActiveInkFillColor() ?? "transparent"), - setInk: (doc: Doc) => { doc[DocData].fillColor = StrCast(value); }, - setMode: () => SetActiveInkFillColor(StrCast(value)), - }], - [ 'strokeWidth', { + [ InkProperty.StrokeWidth, { checkResult: () => (selected?._layout_isSvg ? NumCast(selected[DocData].stroke_width) : ActiveInkWidth()), setInk: (doc: Doc) => { doc[DocData].stroke_width = NumCast(value); }, setMode: () => SetActiveInkWidth(value.toString()), }], - ['strokeColor', { + [InkProperty.StrokeColor, { checkResult: () => (selected?._layout_isSvg? StrCast(selected[DocData].color) : ActiveInkColor()), setInk: (doc: Doc) => { doc[DocData].color = String(value); }, setMode: () => SetActiveInkColor(StrCast(value)) }], - [ 'eraserWidth', { + [ InkProperty.EraserWidth, { checkResult: () => ActiveEraserWidth() === 0 ? 1 : ActiveEraserWidth(), setInk: (doc: Doc) => { }, setMode: () => SetEraserWidth(+value), diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts index f3ff5f11f..936e45eb2 100644 --- a/src/fields/InkField.ts +++ b/src/fields/InkField.ts @@ -26,6 +26,14 @@ export enum InkEraserTool { Radius = 'Radius', } +export enum InkProperty { + Mask = 'inkMask', + Labels = 'labels', + StrokeWidth = 'strokeWidth', + StrokeColor = 'strokeColor', + EraserWidth = ' eraserWidth', +} + export type Segment = Array; // Defines an ink as an array of points. -- cgit v1.2.3-70-g09d2 From b6411c0c053db2b4495d0c545c491d9f18238e21 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 1 Nov 2024 10:53:37 -0400 Subject: fixed resize problem where NaN is generated by scaling very narrow in a card view. --- src/ClientUtils.ts | 2 +- src/client/documents/Documents.ts | 2 ++ src/client/views/DocumentDecorations.tsx | 4 ++-- src/client/views/collections/CollectionCardDeckView.tsx | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts index baad9a06c..8f62b9060 100644 --- a/src/ClientUtils.ts +++ b/src/ClientUtils.ts @@ -165,7 +165,7 @@ export namespace ClientUtils { return { scale: 0, translateX: 1, translateY: 1 }; } const rect = ele.getBoundingClientRect(); - const scale = ele.offsetWidth === 0 && rect.width === 0 ? 1 : rect.width / ele.offsetWidth; + const scale = ele.offsetWidth === 0 && rect.width === 0 ? 1 : rect.width / (ele.offsetWidth || 1); const translateX = rect.left; const translateY = rect.top; diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index efd6ce3c9..d898fe0c5 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -926,6 +926,8 @@ export namespace Docs { I.stroke_isInkMask = isInkMask; I.text_align = 'center'; I.rotation = 0; + I.width_min = 1; + I.height_min = 1; I.defaultDoubleClick = 'ignore'; I.author_date = new DateField(); I.acl_Guest = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 5a48b6c62..66043c033 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -559,8 +559,8 @@ export class DocumentDecorations extends ObservableReactComponent Date: Fri, 1 Nov 2024 12:04:28 -0400 Subject: fixed inifnite loop in card view caused by bug in formattedText of adding tagsView height to doc height. made selected docs also be focused docs in cardview. fixed tags text color to be set to black --- src/client/views/TagsView.scss | 1 + src/client/views/collections/CollectionCardDeckView.tsx | 12 ++++++++++-- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 6 +++--- 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/TagsView.scss b/src/client/views/TagsView.scss index 24f9e86bc..b741e7bfd 100644 --- a/src/client/views/TagsView.scss +++ b/src/client/views/TagsView.scss @@ -59,6 +59,7 @@ margin: auto; align-self: center; width: 90%; + color: black; } .tagsView-buttons { diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 39d9fe69d..836a5a2c3 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -1,4 +1,4 @@ -import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction } from 'mobx'; +import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, trace } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; @@ -113,6 +113,12 @@ export class CollectionCardView extends CollectionSubView() { } } ); + this._disposers.select = reaction( + () => this.childDocs.find(d => this._docRefs.get(d)?.IsSelected), + selected => { + selected && (this.layoutDoc._card_curDoc = selected); + } + ); } componentWillUnmount() { @@ -349,7 +355,7 @@ export class CollectionCardView extends CollectionSubView() { onClickScript={this.curDoc() === doc ? undefined : this._setCurDocScript} dontCenter="y" // Don't center it vertically, because the grid it's in is already doing that and we don't want to do it twice. dragAction={(this.Document.childDragAction ?? this._props.childDragAction) as dropActionType} - showTags={BoolCast(this.layoutDoc.showChildTags)} + showTags={BoolCast(this.layoutDoc.showChildTags) || BoolCast(this.Document._layout_showTags)} whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} dontHideOnDrag /> @@ -620,6 +626,7 @@ export class CollectionCardView extends CollectionSubView() { * Actually renders all the cards */ @computed get renderCards() { + trace(); // Map sorted documents to their rendered components return this.sortedDocs.map((doc, index) => { const cardsInRow = this.cardsInRowThatIncludesCardIndex(index); @@ -667,6 +674,7 @@ export class CollectionCardView extends CollectionSubView() { curDoc = () => DocCast(this.layoutDoc._card_curDoc); render() { + trace(); const fitContentScale = this.childCards.length === 0 ? 1 : this.fitContentScale; return (
({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layoutAutoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins, tagsHeight: this.tagsHeight }), - ({ sidebarHeight, textHeight, layoutAutoHeight, marginsHeight, tagsHeight }) => { - const newHeight = this.contentScaling * (tagsHeight + marginsHeight + Math.max(sidebarHeight, textHeight)); + () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layoutAutoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins }), + ({ sidebarHeight, textHeight, layoutAutoHeight, marginsHeight }) => { + const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight)); if ( (!Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') || this._props.isSelected()) && // layoutAutoHeight && -- cgit v1.2.3-70-g09d2 From 4ab636e338a11e8153d43adddb0e0d3e6bad57ec Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 3 Nov 2024 18:12:54 -0500 Subject: fixed parsing of chat's svg's to strokes --- src/client/util/bezierFit.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts index 4aef28e6b..d52460023 100644 --- a/src/client/util/bezierFit.ts +++ b/src/client/util/bezierFit.ts @@ -691,8 +691,9 @@ export function SVGToBezier(name: SVGType, attributes: any): Point[] { } case 'path': { const coordList: Point[] = []; - const startPt = attributes.d.match(/M(-?\d+\.?\d*),(-?\d+\.?\d*)/); - coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); + const [startX, startY] = attributes.d.match(/M(-?\d+\.?\d*),(-?\d+\.?\d*)/).slice(1); + const startPt = { X: parseInt(startX), Y: parseInt(startY) }; + coordList.push(startPt); const matches: RegExpMatchArray[] = Array.from( attributes.d.matchAll(/Q(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|C(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|L(-?\d+\.?\d*),(-?\d+\.?\d*)/g) ); @@ -721,8 +722,8 @@ export function SVGToBezier(name: SVGType, attributes: any): Point[] { const hasZ = attributes.d.match(/Z/); if (hasZ) { coordList.push(lastPt); - coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); - coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) }); + coordList.push(startPt); + coordList.push(startPt); } else { coordList.pop(); } -- cgit v1.2.3-70-g09d2 From 10a89be0b184df2750a4b3eceb48db205cb83e95 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 5 Nov 2024 10:22:31 -0500 Subject: fixed display of where control point will be added on mouse moves. fixed clickable ink line to not select fill area unless its actually painted. added end cap properties to ink stroke ui. enabled more than one ink stroke to show editable control points when multiselected. --- src/client/views/ComponentDecorations.tsx | 6 +----- src/client/views/DocumentDecorations.tsx | 10 ++++++++-- src/client/views/InkingStroke.tsx | 14 +++++++++---- src/client/views/PropertiesView.scss | 1 + src/client/views/PropertiesView.tsx | 33 ++++++++++++++++++++----------- 5 files changed, 42 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/client/views/ComponentDecorations.tsx b/src/client/views/ComponentDecorations.tsx index 929b549e0..28e9d9792 100644 --- a/src/client/views/ComponentDecorations.tsx +++ b/src/client/views/ComponentDecorations.tsx @@ -5,11 +5,7 @@ import { DocumentView } from './nodes/DocumentView'; @observer export class ComponentDecorations extends React.Component<{ boundsTop: number; boundsLeft: number }, { value: string }> { - // eslint-disable-next-line no-use-before-define - static Instance: ComponentDecorations; - render() { - const seldoc = DocumentView.Selected().lastElement(); - return seldoc?.ComponentView?.componentUI?.(this.props.boundsLeft, this.props.boundsTop) ?? null; + return DocumentView.Selected().map(seldoc => seldoc?.ComponentView?.componentUI?.(this.props.boundsLeft, this.props.boundsTop) ?? null); } } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 66043c033..492c2bda1 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -181,7 +181,13 @@ export class DocumentDecorations extends ObservableReactComponent { - setupMoveUpEvents(this, e, moveEv => this.onBackgroundMove(false, moveEv), emptyFunction, emptyFunction); + setupMoveUpEvents( + this, + e, + moveEv => this.onBackgroundMove(false, moveEv), + emptyFunction, + (clickEv, doubleTap) => doubleTap && DocumentView.Selected().some(dv => dv.Document.layout_isSvg) && (InkStrokeProperties.Instance._controlButton = true) + ); e.stopPropagation(); }; @action @@ -791,7 +797,7 @@ export class DocumentDecorations extends ObservableReactComponent() private _handledClick = false; // flag denoting whether ink stroke has handled a psuedo-click onPointerUp so that the real onClick event can be stopPropagated private _disposers: { [key: string]: IReactionDisposer } = {}; + constructor(props: FieldViewProps) { + super(props); + makeObservable(this); + } + @observable _nearestSeg?: number = undefined; // nearest Bezier segment along the ink stroke to the cursor (used for displaying the Add Point highlight) @observable _nearestT?: number = undefined; // nearest t value within the nearest Bezier segment " - @observable _nearestScrPt?: { X: number; Y: number }; // nearst screen point on the ink stroke "" + @observable _nearestScrPt?: { X: number; Y: number } = { X: 0, Y: 0 }; // nearst screen point on the ink stroke "" componentDidMount() { this._props.setContentViewBox?.(this); @@ -155,6 +160,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent() const wasSelected = InkStrokeProperties.Instance._currentPoint === controlIndex; const isEditing = InkStrokeProperties.Instance._controlButton && this._props.isSelected(); this.controlUndo = undefined; + this._nearestScrPt = undefined; setupMoveUpEvents( this, e, @@ -275,7 +281,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent() .map(p => ({ X: p[0], Y: p[1] })); const { distance, nearestT, nearestSeg, nearestPt } = InkStrokeProperties.nearestPtToStroke(screenPts, { X: e.clientX, Y: e.clientY }); - if (distance < 40) { + if (distance < 40 && !e.buttons) { this._nearestT = nearestT; this._nearestSeg = nearestSeg; this._nearestScrPt = nearestPt; @@ -427,7 +433,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent() StrCast(this.layoutDoc.stroke_lineJoin) as Property.StrokeLinejoin, StrCast(this.layoutDoc.stroke_lineCap) as Property.StrokeLinecap, StrCast(this.layoutDoc.stroke_bezier), - !closed || !fillColor || DashColor(fillColor).alpha() === 0 ? 'none' : fillColor, + 'none', startMarker, endMarker, markerScale, diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index a5e60b831..693c75ebf 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -508,6 +508,7 @@ display: flex; margin-bottom: 3px; margin-left: 4px; + justify-content: space-evenly; .arrows-head { display: flex; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index c539b1d0a..10c2a9898 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -3,6 +3,7 @@ import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-soli import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Checkbox, Tooltip } from '@mui/material'; import { Colors, EditableText, IconButton, NumberInput, Size, Slider, Toggle, ToggleType, Type } from 'browndash-components'; +import { Property } from 'csstype'; import { concat } from 'lodash'; import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; @@ -830,11 +831,7 @@ export class PropertiesView extends ObservableReactComponent { - doc[DocData].stroke_width = Math.round(value * 100) / 100; - }); - } + set strokeThk(value) { this.selectedStrokes.forEach(doc => { doc[DocData].stroke_width = Math.round(value * 100) / 100; }); } // prettier-ignore @computed get hgtInput() { return this.inputBoxDuo( @@ -1025,7 +1022,13 @@ export class PropertiesView extends ObservableReactComponent { + doc[DocData].stroke_lineCap = value; + }); + } + @computed get widthStk() { return this.getField('stroke') || '1'; } // prettier-ignore set widthStk(value) { this.selectedStrokes.forEach(doc => { doc[DocData].stroke_width = Number(value); @@ -1127,7 +1130,6 @@ export class PropertiesView extends ObservableReactComponent
Arrow Head:
Arrow End:
{ this.markTail = this.markTail ? '' : 'arrow'; }) ,"change arrow tail" - )} + onChange={undoable(action(() => { this.markTail = this.markTail ? '' : 'arrow'; }) ,"change arrow tail")} />
+
+ {["butt", "round", "square"].map(cap => +
+
{cap}
+ { this.lineCapStk = cap as Property.StrokeLinecap; }), `change lineCap ${cap}`)} + /> +
)} +
Dashed Line:
-- cgit v1.2.3-70-g09d2