From 661c1367d27fa23c3aeb62369e92cd36eb5edabd Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 21 Oct 2023 00:41:23 -0400 Subject: change to doc decorations to be more "lightweight". made linkBox render links in a freeform view as a DocView. added an auto-reset view option for freeforms. fixed highlighting ink strokes. Made groups behave better for selecting things 'inside' the group bounding box that aren't in the group. Added vertically centered text option. --- src/client/util/InteractionUtils.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/util/InteractionUtils.tsx') diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 4e32ed67f..6406624bb 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -172,7 +172,7 @@ export namespace InteractionUtils { Date: Wed, 25 Oct 2023 11:40:58 -0400 Subject: fixed problem setting ink arrows where they don't show up until the line is modified. --- src/client/util/InteractionUtils.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/util/InteractionUtils.tsx') diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 6406624bb..7caeee588 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -170,7 +170,7 @@ export namespace InteractionUtils { )} Date: Tue, 31 Oct 2023 12:21:30 -0400 Subject: fixed groups to use actual document boundaries for ink or link lines, instead of boundingbox. fixed doc title css. started to make link lines more compatible with ink. --- src/client/util/InteractionUtils.tsx | 6 +++--- src/client/views/DocumentDecorations.tsx | 11 ++++------- src/client/views/EditableView.tsx | 2 ++ src/client/views/InkingStroke.tsx | 1 - src/client/views/PropertiesButtons.tsx | 2 +- src/client/views/PropertiesView.tsx | 7 +------ src/client/views/StyleProvider.scss | 2 +- src/client/views/StyleProvider.tsx | 19 ++++++++++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 5 +---- .../views/nodes/CollectionFreeFormDocumentView.tsx | 17 +++++++++++++---- src/client/views/nodes/DocumentView.tsx | 17 +++++++++-------- src/client/views/nodes/LinkBox.tsx | 12 ++++++++++-- src/client/views/nodes/trails/PresBox.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 2 +- 14 files changed, 57 insertions(+), 48 deletions(-) (limited to 'src/client/util/InteractionUtils.tsx') diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 7caeee588..be885312d 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -94,7 +94,7 @@ export namespace InteractionUtils { width: number, strokeWidth: number, lineJoin: string, - lineCap: string, + strokeLineCap: string, bezier: string, fill: string, arrowStart: string, @@ -181,8 +181,8 @@ export namespace InteractionUtils { // opacity: strokeWidth !== width ? 0.5 : undefined, pointerEvents: (pevents as any) === 'all' ? 'visiblepainted' : (pevents as any), stroke: color ?? 'rgb(0, 0, 0)', - strokeWidth: strokeWidth, - strokeLinecap: lineCap as any, + strokeWidth, + strokeLinecap: strokeLineCap as any, strokeDasharray: dashArray, transition: 'inherit', }} diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 9dafb12fb..65f7c7a70 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -475,6 +475,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P @action onPointerDown = (e: React.PointerEvent): void => { + this._isResizing = true; setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction); DocumentView.Interacting = true; // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them this._resizeHdlId = e.currentTarget.className; @@ -685,6 +686,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P @action onPointerUp = (e: PointerEvent): void => { + this._isResizing = false; this._resizeHdlId = ''; DocumentView.Interacting = false; this._resizeUndo?.end(); @@ -772,7 +774,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P var shareSymbolIcon = ReverseHierarchyMap.get(shareMode)?.image; // hide the decorations if the parent chooses to hide it or if the document itself hides it - const hideDecorations = seldocview.props.hideDecorations || seldocview.rootDoc.hideDecorations; + const hideDecorations = this._isResizing || seldocview.props.hideDecorations || seldocview.rootDoc.layout_hideDecorations; const hideResizers = ![AclAdmin, AclEdit, AclAugment].includes(GetEffectiveAcl(seldocview.rootDoc)) || hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.layout_hideResizeHandles || this._isRounding || this._isRotating; const hideTitle = this._showNothing || hideDecorations || seldocview.props.hideDecorationTitle || seldocview.rootDoc.layout_hideDecorationTitle || this._isRounding || this._isRotating; @@ -861,12 +863,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P onPointerDown={e => e.stopPropagation()} /> ) : ( -
{ - e.stopPropagation; - }}> +
e.stopPropagation}> {hideTitle ? null : ( {this.selectionTitle} diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index ed7c544fc..abb7ed7ee 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -290,6 +290,8 @@ export class EditableView extends React.Component { whiteSpace: this.props.oneLine ? 'nowrap' : 'pre-line', height: this.props.height, maxHeight: this.props.maxHeight, + fontStyle: this.props.fontStyle, + fontSize: this.props.fontSize, }} //onPointerDown={this.stopPropagation} onClick={this.onClick} diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index d619f5123..c3a6b1607 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -372,7 +372,6 @@ export class InkingStroke extends ViewBoxBaseComponent() { } render() { TraceMobx(); - if (!this.rootDoc._layout_isSvg) setTimeout(action(() => (this.rootDoc._layout_isSvg = true))); const { inkData, inkStrokeWidth, inkLeft, inkTop, inkScaleX, inkScaleY, inkWidth, inkHeight } = this.inkScaledData(); const startMarker = StrCast(this.layoutDoc.stroke_startMarker); diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index ff79a8390..18f53b8e7 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -492,7 +492,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { render() { const layoutField = this.selectedDoc?.[Doc.LayoutFieldKey(this.selectedDoc)]; const isText = layoutField instanceof RichTextField; - const isInk = layoutField instanceof InkField; + const isInk = this.selectedDoc?.layout_isSvg; const isImage = layoutField instanceof ImageField; const isMap = this.selectedDoc?.type === DocumentType.MAP; const isCollection = this.selectedDoc?.type === DocumentType.COL; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 04a948a27..d37971517 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -73,9 +73,6 @@ export class PropertiesView extends React.Component { @computed get isPres(): boolean { return this.selectedDoc?.type === DocumentType.PRES; } - @computed get isLink(): boolean { - return this.selectedDoc?.type === DocumentType.LINK; - } @computed get dataDoc() { return this.selectedDoc?.[DocData]; } @@ -1174,12 +1171,10 @@ export class PropertiesView extends React.Component { } @computed get inkSubMenu() { - let isDouble = false; - return ( <> (this.openAppearance = bool)} onDoubleClick={() => this.CloseAll()}> - {this.isInk ? this.appearanceEditor : null} + {this.selectedDoc?.layout_isSvg ? this.appearanceEditor : null} (this.openTransform = bool)} onDoubleClick={() => this.CloseAll()}> {this.transformEditor} diff --git a/src/client/views/StyleProvider.scss b/src/client/views/StyleProvider.scss index f069e7e1b..4d3096f71 100644 --- a/src/client/views/StyleProvider.scss +++ b/src/client/views/StyleProvider.scss @@ -12,7 +12,7 @@ opacity: 0.3; display: flex; flex-direction: column; - color: gold; + color: red; border-radius: 3px; justify-content: center; cursor: default; diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 5ff743a30..c6d3efd0c 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -83,8 +83,9 @@ export function DefaultStyleProvider(doc: Opt, props: Opt doc && doc._layout_isSvg && !props?.LayoutTemplateString; + const isInk = () => doc?._layout_isSvg && !props?.LayoutTemplateString; const isOpen = property.includes(':open'); const isEmpty = property.includes(':empty'); const boxBackground = property.includes(':box'); @@ -121,14 +122,14 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt, props: Opt, props: Opt, props: Opt, props: Opt toggleLockedPosition(doc)}> - +
); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 9639ec73c..0d43d6ab8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1300,16 +1300,15 @@ export class CollectionFreeFormView extends CollectionSubView this.childPointerEvents; childContentsActive = () => (this.props.childContentsActive ?? this.isContentActive() === false ? returnFalse : emptyFunction)(); - groupChildPointerEvents = () => (this.props.isDocumentActive?.() && !this.isContentActive() ? 'all' : 'none'); getChildDocView(entry: PoolData) { const childLayout = entry.pair.layout; const childData = entry.pair.data; return ( this.transcribeStrokes(false), icon: 'font' }); - // this.props.Document._isGroup && this.childDocs.filter(s => s.type === DocumentType.INK).length > 0 && appearanceItems.push({ description: "Ink to math", event: () => this.transcribeStrokes(true), icon: "square-root-alt" }); - !Doc.noviceMode ? appearanceItems.push({ description: 'Arrange contents in grid', event: this.layoutDocsInGrid, icon: 'table' }) : null; !appearance && ContextMenu.Instance.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'eye' }); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 199835dd9..9f7ebc5d9 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -25,7 +25,6 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { dataTransition?: string; replica: string; CollectionFreeFormView: CollectionFreeFormView; - GroupPointerEvents?: () => 'none' | 'all' | undefined; // pointer events for this freeform doc view wrapper that are not passed to the docView. This allows items in a group to trigger the group to be selected, without selecting the items themselves } @observer @@ -192,17 +191,27 @@ export class CollectionFreeFormDocumentView extends DocComponent this.props.ScreenToLocalTransform().translate(-this.X, -this.Y); returnThis = () => this; + /// this indicates whether the doc view is activated because of its relationshop to a group + // 'group' - this is a group that is activated because it's on an active canvas, but is not part of some other group + // 'child' - this is a group child that is activated because its containing group is activated + // 'inactive' - this is a group child but it is not active + // undefined - this is not activated by a group + isGroupActive = () => { + if (this.props.CollectionFreeFormView.isAnyChildContentActive()) return undefined; + const isGroup = this.rootDoc._isGroup && (!this.rootDoc.backgroundColor || this.rootDoc.backgroundColor === 'transparent'); + return isGroup ? (this.props.isDocumentActive?.() ? 'group' : this.props.isGroupActive?.() ? 'child' : 'inactive') : this.props.isGroupActive?.() ? 'child' : undefined; + }; render() { TraceMobx(); const divProps: DocumentViewProps = { - ...OmitKeys(this.props, ['GroupPointerEvents']).omit, + ...this.props, CollectionFreeFormDocumentView: this.returnThis, styleProvider: this.styleProvider, ScreenToLocalTransform: this.screenToLocalTransform, PanelWidth: this.panelWidth, PanelHeight: this.panelHeight, + isGroupActive: this.isGroupActive, }; - const isInk = this.layoutDoc._layout_isSvg && !this.props.LayoutTemplateString && !this.layoutDoc._stroke_isInkMask; return (
{this.props.renderCutoffProvider(this.props.Document) ? (
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 43be4b724..a2a084200 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,5 +1,6 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; -import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx'; +import { Dropdown, DropdownType, Type } from 'browndash-components'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; @@ -38,7 +39,6 @@ import { ContextMenuProps } from '../ContextMenuItem'; import { DocComponent } from '../DocComponent'; import { EditableView } from '../EditableView'; import { GestureOverlay } from '../GestureOverlay'; -import { InkingStroke } from '../InkingStroke'; import { LightboxView } from '../LightboxView'; import { StyleProp } from '../StyleProvider'; import { UndoStack } from '../UndoStack'; @@ -48,14 +48,11 @@ import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; import { FieldViewProps } from './FieldView'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; +import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; import React = require('react'); -import { KeyValueBox } from './KeyValueBox'; -import { LinkBox } from './LinkBox'; -import { FilterPanel } from '../FilterPanel'; -import { Dropdown, DropdownType, Type } from 'browndash-components'; const { Howl } = require('howler'); interface Window { @@ -159,6 +156,7 @@ export interface DocumentViewSharedProps { Document: Doc; DataDoc?: Doc; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document + isGroupActive?: () => string | undefined; // is this document part of a group that is active suppressSetHeight?: boolean; setContentView?: (view: DocComponentView) => any; CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView; @@ -428,6 +426,7 @@ export class DocumentViewInternal extends DocComponent boolean = returnFalse; onClick = action((e: React.MouseEvent | React.PointerEvent) => { + if (this.props.isGroupActive?.() === 'child' && !this.props.isDocumentActive?.()) return; if (!this.Document.ignoreClick && this.props.renderDepth >= 0 && Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) { let stopPropagate = true; let preventDefault = true; @@ -516,6 +515,7 @@ export class DocumentViewInternal extends DocComponent { + if (this.props.isGroupActive?.() === 'child' && !this.props.isDocumentActive?.()) return; this._longPressSelector = setTimeout(() => { if (DocumentView.LongPress) { if (this.rootDoc.undoIgnoreFields) { @@ -906,11 +906,12 @@ export class DocumentViewInternal extends DocComponent !isParentOf(this.ContentDiv, document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y)) && Doc.UnBrushDoc(this.rootDoc)} style={{ borderRadius: this.borderRounding, - pointerEvents: this.pointerEvents === 'visiblePainted' ? 'none' : this.pointerEvents, + pointerEvents: this.pointerEvents === 'visiblePainted' ? 'none' : this.pointerEvents, // visible painted means that the underlying doc contents are irregular and will process their own pointer events (otherwise, the contents are expected to fill the entire doc view box so we can handle pointer events here) }}> <> {this._componentView instanceof KeyValueBox ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.rootDoc[Animation], this.rootDoc)} diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index d871c88ba..682267ef1 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -4,7 +4,7 @@ import { computed, action } from 'mobx'; import { observer } from 'mobx-react'; import { Height, Width } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; -import { DocCast, StrCast } from '../../../fields/Types'; +import { DocCast, NumCast, StrCast } from '../../../fields/Types'; import { aggregateBounds, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils'; import { DocumentManager } from '../../util/DocumentManager'; import { ViewBoxBaseComponent } from '../DocComponent'; @@ -92,6 +92,9 @@ export class LinkBox extends ViewBoxBaseComponent() { const bez = new Bezier(pts.map(p => ({ x: p[0], y: p[1] }))); const text = bez.get(0.5); const linkDesc = StrCast(this.rootDoc.link_description) || 'description'; + const strokeWidth = NumCast(this.rootDoc.stroke_width, 4); + const dash = StrCast(this.rootDoc.stroke_dash); + const strokeDasharray = dash && Number(dash) ? String(strokeWidth * Number(dash)) : undefined; return (
@@ -106,7 +109,12 @@ export class LinkBox extends ViewBoxBaseComponent() { diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index ceeb10d93..70d9443a2 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -792,7 +792,7 @@ export class PresBox extends ViewBoxBaseComponent() { willPan: activeItem.presentation_movement !== PresMovement.None, willZoomCentered: activeItem.presentation_movement === PresMovement.Zoom || activeItem.presentation_movement === PresMovement.Jump || activeItem.presentation_movement === PresMovement.Center, zoomScale: activeItem.presentation_movement === PresMovement.Center ? 0 : NumCast(activeItem.config_zoom, 1), - zoomTime: activeItem.presentation_movement === PresMovement.Jump ? 0 : Math.min(Math.max(effect ? 750 : 500, (effect ? 1 : 1) * presTime), presTime), + zoomTime: activeItem.presentation_movement === PresMovement.Jump ? 0 : Math.min(Math.max(effect ? 750 : 500, (effect ? 0.2 : 1) * presTime), presTime), effect: activeItem, noSelect: true, openLocation: OpenWhere.addLeft, diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 58a54764d..939928c1c 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -519,7 +519,7 @@ export class PDFViewer extends React.Component { childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { if (this.inlineTextAnnotations.includes(doc) || this.props.isContentActive() === false) return 'none'; - const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name) && !props?.LayoutTemplateString; + const isInk = doc.layout_isSvg && !props?.LayoutTemplateString; return isInk ? 'visiblePainted' : 'all'; } return this.props.styleProvider?.(doc, props, property); -- cgit v1.2.3-70-g09d2