From 30338491c7b3cbba852931c76774f6bfd44d4060 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 10 Dec 2020 12:54:41 -0500 Subject: removed annotationsKey prop in favor of reusing fieldKey. Fixed web pages to allow dash annotations again. --- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 22e3ac1e9..33515e475 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -47,7 +47,7 @@ import { FootnoteView } from "./FootnoteView"; import { schema } from "./schema_rts"; import { SelectionManager } from "../../../util/SelectionManager"; import { undoBatch, UndoManager } from "../../../util/UndoManager"; -import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView'; +import { CollectionFreeFormView, collectionFreeformViewProps } from '../../collections/collectionFreeForm/CollectionFreeFormView'; import { ContextMenu } from '../../ContextMenu'; import { ContextMenuProps } from '../../ContextMenuItem'; import { ViewBoxAnnotatableComponent } from "../../DocComponent"; @@ -59,9 +59,10 @@ import { FormattedTextBoxComment, formattedTextBoxCommentPlugin, findLinkMark } import React = require("react"); import { DocumentManager } from '../../../util/DocumentManager'; import { CollectionStackingView } from '../../collections/CollectionStackingView'; -import { CollectionViewType } from '../../collections/CollectionView'; +import { CollectionViewType, CollectionViewProps } from '../../collections/CollectionView'; import { SnappingManager } from '../../../util/SnappingManager'; import { LinkDocPreview } from '../LinkDocPreview'; +import { SubCollectionViewProps } from '../../collections/CollectionSubView'; export interface FormattedTextBoxProps { makeLink?: () => Opt; // bcz: hack: notifies the text document when the container has made a link. allows the text doc to react and setup a hyeprlink for any selected text @@ -1606,7 +1607,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp sidebarContentScaling = () => this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1); @computed get sidebarCollection() { const fitToBox = this.props.Document._fitToBox; - const collectionProps = { + const collectionProps: SubCollectionViewProps & collectionFreeformViewProps = { ...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit, NativeWidth: returnZero, NativeHeight: returnZero, @@ -1616,8 +1617,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp yMargin: 0, chromeStatus: "enabled", scaleField: this.annotationKey + "-scale", - annotationsKey: this.annotationKey, isAnnotationOverlay: true, + fieldKey: this.annotationKey, fitToBox: fitToBox, focus: this.props.focus, isSelected: this.props.isSelected, @@ -1636,7 +1637,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp return !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) :
- {this.layoutDoc.sidebarViewType === CollectionViewType.Freeform ? : } + {this.layoutDoc.sidebarViewType === CollectionViewType.Freeform ? + : + }
; } -- cgit v1.2.3-70-g09d2 From d913740b994670b1b0eadd52069aeb69ef2b2380 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 10 Dec 2020 14:18:53 -0500 Subject: more cleanup/organization of 'props' . removed VisibleHeight props and cleaned up PDF and other props --- src/client/util/CurrentUserUtils.ts | 1 - .../util/Import & Export/DirectoryImportBox.tsx | 1 - src/client/views/PropertiesView.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 21 +++-- .../views/collections/CollectionTimeView.tsx | 7 +- src/client/views/collections/CollectionView.tsx | 36 ++++---- src/client/views/collections/SchemaTable.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 16 ++-- .../collectionGrid/CollectionGridView.tsx | 2 +- .../CollectionMulticolumnView.tsx | 2 +- .../CollectionMultirowView.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- .../views/nodes/ContentFittingDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/KeyValueBox.tsx | 1 - src/client/views/nodes/PDFBox.tsx | 96 +++++----------------- src/client/views/nodes/VideoBox.tsx | 11 +-- src/client/views/nodes/WebBox.tsx | 19 +---- .../views/nodes/formattedText/FormattedTextBox.tsx | 3 - src/client/views/pdf/PDFViewer.tsx | 50 +++-------- src/fields/documentSchemas.ts | 2 - 22 files changed, 84 insertions(+), 200 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 213bc3d88..676e7ce3e 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -801,7 +801,6 @@ export class CurrentUserUtils { } } - static setupUserDoc(doc: Doc) { if (doc.myUserDoc === undefined) { doc.treeViewOpen = true; diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 7f01966b9..d9f010557 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -158,7 +158,6 @@ export class DirectoryImportBox extends React.Component { importContainer = Docs.Create.SchemaDocument(headers, docs, options); } runInAction(() => this.phase = 'External: uploading files to Google Photos...'); - importContainer._columnsStack = false; await GooglePhotos.Export.CollectionToAlbum({ collection: importContainer }); Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer); !this.persistent && this.props.removeDocument && this.props.removeDocument(doc); diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 08394cd97..233429f4d 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -272,7 +272,7 @@ export class PropertiesView extends React.Component { treeViewDoc={undefined} styleProvider={this.props.styleProvider} fitToBox={true} - FreezeDimensions={true} + freezeDimensions={true} dontCenter={"y"} NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined} NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined} diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index e22b8effe..c64048345 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -401,7 +401,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { Document={this.previewDocument} DataDoc={undefined} fitToBox={true} - FreezeDimensions={true} + freezeDimensions={true} dontCenter={"y"} focus={emptyFunction} renderDepth={this.props.renderDepth} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 058536f69..b1c5dec84 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -3,7 +3,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { CursorProperty } from "csstype"; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import Switch from 'rc-switch'; import { DataSym, Doc, HeightSym, WidthSym } from "../../../fields/Doc"; import { collectionSchema, documentSchema } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; @@ -12,23 +11,23 @@ import { listSpec, makeInterface } from "../../../fields/Schema"; import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; import { TraceMobx } from "../../../fields/util"; -import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils, smoothScroll, returnVal } from "../../../Utils"; +import { emptyFunction, returnFalse, returnOne, returnVal, returnZero, setupMoveUpEvents, smoothScroll, Utils } from "../../../Utils"; +import { DocUtils } from "../../documents/Documents"; import { DragManager, dropActionType } from "../../util/DragManager"; +import { SnappingManager } from "../../util/SnappingManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { EditableView } from "../EditableView"; +import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView"; +import { DocAfterFocusFunc } from "../nodes/DocumentView"; import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow"; import "./CollectionStackingView.scss"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; import { CollectionSubView } from "./CollectionSubView"; import { CollectionViewType } from "./CollectionView"; -import { SnappingManager } from "../../util/SnappingManager"; -import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; -import { DocUtils } from "../../documents/Documents"; -import { DocAfterFocusFunc } from "../nodes/DocumentView"; const _global = (window /* browser */ || global /* node */) as any; type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>; @@ -56,7 +55,7 @@ export class CollectionStackingView extends CollectionSubView doc) { @computed get contents() { return
- +
; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 511fc723d..dbbb3e991 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -66,7 +66,6 @@ export interface CollectionViewProps extends FieldViewProps { layoutEngine?: () => string; parentActive: (outsideReaction: boolean) => boolean; filterAddDocument?: (doc: Doc | Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) - VisibleHeight?: () => number; setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void; // property overrides for child documents @@ -242,28 +241,27 @@ export class CollectionView extends Touchable { private SubView = (type: CollectionViewType, props: SubCollectionViewProps) => { TraceMobx(); switch (type) { - case CollectionViewType.Schema: return (); - case CollectionViewType.Docking: return (); - case CollectionViewType.Tree: return (); - //case CollectionViewType.Staff: return (); - case CollectionViewType.Multicolumn: return (); - case CollectionViewType.Multirow: return (); - case CollectionViewType.Linear: { return (); } - case CollectionViewType.Pile: { return (); } - case CollectionViewType.Carousel: { return (); } - case CollectionViewType.Carousel3D: { return (); } - case CollectionViewType.Stacking: { this.props.Document._columnsStack = true; return (); } - case CollectionViewType.Masonry: { this.props.Document._columnsStack = false; return (); } - case CollectionViewType.Time: { return (); } - case CollectionViewType.Map: return (); - case CollectionViewType.Grid: return (); - case CollectionViewType.Freeform: - default: { this.props.Document._freeformLayoutEngine = undefined; return (); } + default: + case CollectionViewType.Freeform: return ; + case CollectionViewType.Schema: return ; + case CollectionViewType.Docking: return ; + case CollectionViewType.Tree: return ; + case CollectionViewType.Multicolumn: return ; + case CollectionViewType.Multirow: return ; + case CollectionViewType.Linear: return ; + case CollectionViewType.Pile: return ; + case CollectionViewType.Carousel: return ; + case CollectionViewType.Carousel3D: return ; + case CollectionViewType.Stacking: return ; + case CollectionViewType.Masonry: return ; + case CollectionViewType.Time: return ; + case CollectionViewType.Map: return ; + case CollectionViewType.Grid: return ; + //case CollectionViewType.Staff: return ; } } setupViewTypes(category: string, func: (viewType: CollectionViewType) => Doc, addExtras: boolean) { - const subItems: ContextMenuProps[] = []; subItems.push({ description: "Freeform", event: () => func(CollectionViewType.Freeform), icon: "signature" }); if (addExtras && CollectionView._safeMode) { diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index b532d3302..24a67faaf 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -571,7 +571,7 @@ export class SchemaTable extends React.Component { Document={this._showDoc} DataDoc={this._showDataDoc} fitToBox={true} - FreezeDimensions={true} + freezeDimensions={true} focus={emptyFunction} renderDepth={this.props.renderDepth} rootSelected={() => false} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index e09abd017..94de40bc8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -918,7 +918,7 @@ export class CollectionFreeFormView extends CollectionSubView, bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica) })); diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index f3e385746..bef197bee 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -170,7 +170,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { PanelWidth={width} PanelHeight={height} ContentScaling={returnOne} - FreezeDimensions={true} + freezeDimensions={true} fitToBox={true} ScreenToLocalTransform={dxf} onClick={this.onChildClickHandler} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 586c5d1df..d4913a5ed 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -219,7 +219,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu styleProvider={this.props.styleProvider} LayoutTemplate={this.props.childLayoutTemplate} LayoutTemplateString={this.props.childLayoutString} - FreezeDimensions={this.props.childFreezeDimensions} + freezeDimensions={this.props.childFreezeDimensions} renderDepth={this.props.renderDepth + 1} PanelWidth={width} PanelHeight={height} diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 87c56de6f..9039090d1 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -219,7 +219,7 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) styleProvider={this.props.styleProvider} LayoutTemplate={this.props.childLayoutTemplate} LayoutTemplateString={this.props.childLayoutString} - FreezeDimensions={this.props.childFreezeDimensions} + freezeDimensions={this.props.childFreezeDimensions} renderDepth={this.props.renderDepth + 1} PanelWidth={width} PanelHeight={height} diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index b4b887617..d68184da6 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -52,7 +52,7 @@ export class CollectionFreeFormDocumentView extends DocComponent(Docu undefined); } @computed get topMost() { return this.props.renderDepth === 0; } - @computed get freezeDimensions() { return this.props.FreezeDimensions; } + @computed get freezeDimensions() { return this.props.freezeDimensions; } @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.dataDoc, this.freezeDimensions)); } @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.dataDoc, this.freezeDimensions)); } @computed get onClickHandler() { return this.props.onClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null)); } diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 4ac932c24..8acf4081c 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -169,7 +169,6 @@ export class KeyValueBox extends React.Component { getTemplate = async () => { const parent = Docs.Create.StackingDocument([], { _width: 800, _height: 800, title: "Template" }); - parent._columnsStack = false; parent._columnWidth = 100; for (const row of this.rows.filter(row => row.isChecked)) { await this.createTemplateField(parent, row); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 42b24f6f6..a2f3fb2d1 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -1,28 +1,27 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable, runInAction, reaction, IReactionDisposer, trace, untracked, computed } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; -import { Opt, WidthSym, Doc, HeightSym } from "../../../fields/Doc"; +import { Doc, Opt, WidthSym } from "../../../fields/Doc"; +import { documentSchema } from '../../../fields/documentSchemas'; import { makeInterface } from "../../../fields/Schema"; -import { ScriptField } from '../../../fields/ScriptField'; -import { Cast, NumCast, StrCast } from "../../../fields/Types"; -import { PdfField, URLField } from "../../../fields/URLField"; +import { Cast, NumCast } from "../../../fields/Types"; +import { PdfField } from "../../../fields/URLField"; +import { TraceMobx } from '../../../fields/util'; import { Utils } from '../../../Utils'; +import { KeyCodes } from '../../util/KeyCodes'; import { undoBatch } from '../../util/UndoManager'; import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView'; +import { CollectionViewType } from '../collections/CollectionView'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { PDFViewer } from "../pdf/PDFViewer"; import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; -import { KeyCodes } from '../../util/KeyCodes'; import "./PDFBox.scss"; import React = require("react"); -import { documentSchema } from '../../../fields/documentSchemas'; -import { CollectionViewType } from '../collections/CollectionView'; -import { TraceMobx } from '../../../fields/util'; type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @@ -30,17 +29,11 @@ const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @observer export class PDFBox extends ViewBoxAnnotatableComponent(PdfDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PDFBox, fieldKey); } - private _keyValue: string = ""; - private _valueValue: string = ""; - private _scriptValue: string = ""; private _searchString: string = ""; private _initialScale: number = 0; // the initial scale of the PDF when first rendered which determines whether the document will be live on startup or not. Getting bigger after startup won't make it automatically be live. private _displayPdfLive = false; // has this box ever had its contents activated -- if so, stop drawing the overlay title private _pdfViewer: PDFViewer | undefined; private _searchRef = React.createRef(); - private _keyRef = React.createRef(); - private _valueRef = React.createRef(); - private _scriptRef = React.createRef(); private _selectReactionDisposer: IReactionDisposer | undefined; @observable private _searching: boolean = false; @@ -130,25 +123,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent { - const scriptText = this._scriptValue ? this._scriptValue : - this._keyValue && this._valueValue ? `this.${this._keyValue} === ${this._valueValue}` : "true"; - this.props.Document.filterScript = ScriptField.MakeFunction(scriptText); - } - - private resetFilters = () => { - this._keyValue = this._valueValue = this._scriptValue = ""; - this._keyRef.current && (this._keyRef.current.value = ""); - this._valueRef.current && (this._valueRef.current.value = ""); - this._scriptRef.current && (this._scriptRef.current.value = ""); - this.applyFilter(); - } - private newKeyChange = (e: React.ChangeEvent) => this._keyValue = e.currentTarget.value; - private newValueChange = (e: React.ChangeEvent) => this._valueValue = e.currentTarget.value; - private newScriptChange = (e: React.ChangeEvent) => this._scriptValue = e.currentTarget.value; - whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); setPdfViewer = (pdfViewer: PDFViewer) => { this._pdfViewer = pdfViewer; }; searchStringChanged = (e: React.ChangeEvent) => this._searchString = e.currentTarget.value; @@ -197,36 +171,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._pageControls = !this._pageControls)} /> {this._pageControls ? pageBtns : (null)} - {/*
e.stopPropagation()}> - -
-
- Annotation View Settings -
-
- - -
-
- -
-
- - -
-
-
*/} ); } @@ -253,19 +197,19 @@ export class PDFBox extends ViewBoxAnnotatableComponent 600) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}> -
- 600) ? NumCast(this.Document._height) * this.props.PanelWidth() / NumCast(this.Document._width) : undefined }}> +
+ + startupLive={true} + /> {this.settingsPanel()}
; } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 8d10768ff..90a5dee23 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -427,11 +427,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent + renderDepth={this.props.renderDepth + 1}> {this.contentFunc} diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 197ff20d5..47464d794 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -646,14 +646,6 @@ export class WebBox extends ViewBoxAnnotatableComponent this._marqueeX; marqueeY = () => this._marqueeY; marqueeing = () => this._marqueeing; - visibleHeight = () => { - if (this._mainCont.current) { - const boundingRect = this._mainCont.current.getBoundingClientRect(); - const scaling = (Doc.NativeWidth(this.Document) || 0) / boundingRect.width; - return Math.min(boundingRect.height * scaling, this.props.PanelHeight() * scaling); - } - return this.props.PanelHeight(); - } scrollXf = () => this.props.ScreenToLocalTransform().translate(NumCast(this.layoutDoc._scrollLeft), NumCast(this.layoutDoc._scrollTop)); render() { const scaling = Number.isFinite(this.props.ContentScaling()) ? this.props.ContentScaling() || 1 : 1; @@ -697,13 +689,8 @@ export class WebBox extends ViewBoxAnnotatableComponent + renderDepth={this.props.renderDepth + 1}> diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 33515e475..bfbd7805d 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1620,8 +1620,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp isAnnotationOverlay: true, fieldKey: this.annotationKey, fitToBox: fitToBox, - focus: this.props.focus, - isSelected: this.props.isSelected, select: emptyFunction, active: this.annotationsActive, ContentScaling: this.sidebarContentScaling, @@ -1632,7 +1630,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp CollectionView: undefined, ScreenToLocalTransform: this.sidebarScreenToLocal, renderDepth: this.props.renderDepth + 1, - ContainingCollectionDoc: this.props.ContainingCollectionDoc, }; return !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) :
+ renderDepth={this.props.renderDepth + 1}>
; } @@ -778,7 +751,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent this._marqueeX; marqueeY = () => this._marqueeY; marqueeing = () => this._marqueeing; - visibleHeight = () => this.props.PanelHeight() / this.props.ContentScaling(); contentZoom = () => this._zoomed; render() { TraceMobx(); diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 979238767..67df56015 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -49,14 +49,12 @@ export const documentSchema = createSchema({ _showTitle: "string", // the fieldkey whose contents should be displayed at the top of the document _showTitleHover: "string", // the showTitle should be shown only on hover _showAudio: "boolean", // whether to show the audio record icon on documents - _freeformLayoutEngine: "string",// the string ID for the layout engine to use to layout freeform view documents _freeformLOD: "boolean", // whether to enable LOD switching for CollectionFreeFormViews _pivotField: "string", // specifies which field key should be used as the timeline/pivot axis _replacedChrome: "string", // what the default chrome is replaced with. Currently only supports the value of 'replaced' for PresBox's. _chromeStatus: "string", // determines the state of the collection chrome. values allowed are 'replaced', 'enabled', 'disabled', 'collapsed' _columnsFill: "boolean", // whether documents in a stacking view column should be sized to fill the column _columnsSort: "string", // how a document should be sorted "ascending", "descending", undefined (none) - _columnsStack: "boolean", // whether a stacking document stacks vertically (as opposed to masonry horizontal) _columnsHideIfEmpty: "boolean", // whether empty stacking view column headings should be hidden _columnHeaders: listSpec(SchemaHeaderField), // header descriptions for stacking/masonry _schemaHeaders: listSpec(SchemaHeaderField), // header descriptions for schema views -- cgit v1.2.3-70-g09d2 From 7a9d8f1e87f6f05433bbe4eab9fad85c3a07fa5a Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 11 Dec 2020 02:48:36 -0500 Subject: fixed pointerevents set through styleProvider. fixed crash when color strings use uppercase. fixed empty text boxes to set default font size/family --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/collections/TabDocView.tsx | 27 ++++++++++------------ src/client/views/nodes/DocumentView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 6 ++--- 5 files changed, 18 insertions(+), 21 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8a5f0fb5e..2f190fbfd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -711,7 +711,7 @@ export namespace Docs { export function LinkDocument(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, options: DocumentOptions = {}, id?: string) { const doc = InstanceFromProto(Prototypes.get(DocumentType.LINK), undefined, { dontRegisterChildViews: true, - isLinkButton: true, treeViewHideTitle: true, backgroundColor: "lightBlue", // lightBlue is default color for linking dot and link documents text comment area + isLinkButton: true, treeViewHideTitle: true, backgroundColor: "lightblue", // lightblue is default color for linking dot and link documents text comment area treeViewExpandedView: "fields", removeDropProperties: new List(["_layers", "isLinkButton"]), ...options }, id); const linkDocProto = Doc.GetProto(doc); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 676e7ce3e..2a7e95666 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -252,7 +252,7 @@ export class CurrentUserUtils { doc["template-note-Idea"] = new PrefetchProxy(noteView); } if (doc["template-note-Topic"] === undefined) { - const noteView = Docs.Create.TextDocument("", { title: "text", style: "Topic", backgroundColor: "lightBlue", system: true }); + const noteView = Docs.Create.TextDocument("", { title: "text", style: "Topic", backgroundColor: "lightblue", system: true }); noteView.isTemplateDoc = makeTemplate(noteView, true, "Topic"); doc["template-note-Topic"] = new PrefetchProxy(noteView); } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 0fac68582..ba8b5e418 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -433,7 +433,7 @@ export class TabDocView extends React.Component { // a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab // public static styleProvider = (doc: Opt, props: Opt, property: string): any => { - switch (property) { + switch (property.split(":")[0]) { case "docContents": return undefined; case "widgetColor": return TabDocView.darkScheme ? "lightgrey" : "dimgrey"; case "opacity": return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null)); @@ -459,7 +459,7 @@ export class TabDocView extends React.Component { default: docColor = TabDocView.darkScheme ? "black" : "white"; break; } } - if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = Color(docColor).fade(0.5).toString(); + if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = Color(docColor.toLowerCase()).fade(0.5).toString(); return docColor; } case "boxShadow": { @@ -475,15 +475,14 @@ export class TabDocView extends React.Component { StrCast(doc.boxShadow, ""); } } - default: - if (property.startsWith("pointerEvents")) { - const layer = doc && props?.layerProvider?.(doc); - if (props?.styleProvider?.(doc, props, "opacity") === 0 || doc?.type === DocumentType.INK || doc?.isInkMask) return "none"; - if (layer === false && !property.includes(":selected") && !SnappingManager.GetIsDragging()) return "none"; - if (doc?.type !== DocumentType.INK && layer === true) return "all"; - return undefined; - } - if (property.startsWith("decorations") && props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform) { + case "pointerEvents": + const layer = doc && props?.layerProvider?.(doc); + if (props?.styleProvider?.(doc, props, "opacity") === 0 || doc?.type === DocumentType.INK || doc?.isInkMask) return "none"; + if (layer === false && !property.includes(":selected") && !SnappingManager.GetIsDragging()) return "none"; + if (doc?.type !== DocumentType.INK && layer === true) return "all"; + return undefined; + case "decorations": + if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform) { const isBackground = StrListCast(doc?.layers).includes("background"); return doc && (isBackground || property.includes(":selected")) && (props?.renderDepth || 0) > 0 && ((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ? @@ -498,13 +497,11 @@ export class TabDocView extends React.Component { if (doc) { switch (property) { case "docContents": - if (doc.type === DocumentType.COL) return null; const background = doc.type === DocumentType.PDF ? "red" : doc.type === DocumentType.IMG ? "blue" : doc.type === DocumentType.RTF ? "orange" : doc.type === DocumentType.VID ? "purple" : doc.type === DocumentType.WEB ? "yellow" : "gray"; - return
; + return doc.type === DocumentType.COL ? undefined :
; default: - if (property.startsWith("pointerEvents")) return "none"; - return TabDocView.styleProvider(doc, props, property); + return (property.startsWith("pointerEvents")) ? "none" : TabDocView.styleProvider(doc, props, property); } } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9449f92ab..cbbb27450 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1093,7 +1093,6 @@ export class DocumentView extends DocComponent(Docu transformOrigin: this._animateScalingTo ? "center center" : undefined, transform: this._animateScalingTo ? `scale(${this._animateScalingTo})` : undefined, transition: !this._animateScalingTo ? StrCast(this.Document.dataTransition) : `transform 0.5s ease-${this._animateScalingTo < 1 ? "in" : "out"}`, - pointerEvents: this.pointerEvents, }}> {this.innards} {this.onClickHandler && this.props.ContainingCollectionView?.props.Document._viewType === CollectionViewType.Time ?
: (null)} @@ -1124,6 +1123,7 @@ export class DocumentView extends DocComponent(Docu !entered && Doc.UnBrushDoc(this.props.Document); })} style={{ + pointerEvents: this.pointerEvents, outline: highlighting && !borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : "solid 0px", border: highlighting && borderRounding && highlightStyle === "dashed" ? `${highlightStyle} ${highlightColor} ${highlightIndex}px` : undefined, boxShadow: highlighting && borderRounding && highlightStyle !== "dashed" ? `0 0 0 ${highlightIndex}px ${highlightColor}` : diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index bfbd7805d..415c8c184 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -270,8 +270,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._pause = false; this.insertTime(); } - !curText && tx.storedMarks?.map(m => m.type.name === "pFontSize" && (Doc.UserDoc().fontSize = this.layoutDoc._fontSize = m.attrs.fontSize)); - !curText && tx.storedMarks?.map(m => m.type.name === "pFontFamily" && (Doc.UserDoc().fontFamily = this.layoutDoc._fontFamily = m.attrs.fontFamily)); + !curText && tx.storedMarks?.filter(m => m.type.name === "pFontSize").map(m => Doc.UserDoc().fontSize = this.layoutDoc._fontSize = (m.attrs.fontSize + "px")); + !curText && tx.storedMarks?.filter(m => m.type.name === "pFontFamily").map(m => Doc.UserDoc().fontFamily = this.layoutDoc._fontFamily = m.attrs.fontFamily); this.dataDoc[this.props.fieldKey] = new RichTextField(json, curText); this.dataDoc[this.props.fieldKey + "-noTemplate"] = true;//(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 }); @@ -1599,7 +1599,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const annotated = DocListCast(this.dataDoc[this.annotationKey]).filter(d => d?.author).length; return !this.props.isSelected() && !(annotated && !this.sidebarWidth()) ? (null) :
; } -- cgit v1.2.3-70-g09d2 From 6346a318634f6d4ebe561a871905982d748bf43e Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 11 Dec 2020 12:25:06 -0500 Subject: converted all style sheet properties to enums. --- src/client/views/MainView.tsx | 13 +- src/client/views/OverlayView.tsx | 3 +- src/client/views/PropertiesView.tsx | 3 +- src/client/views/StyleProvider.scss | 19 +++ src/client/views/StyleProvider.tsx | 153 +++++++++++++++++++++ .../views/collections/CollectionCarouselView.tsx | 3 +- .../views/collections/CollectionStackingView.tsx | 3 +- .../views/collections/CollectionTreeView.tsx | 3 +- src/client/views/collections/CollectionView.tsx | 3 +- src/client/views/collections/TabDocView.tsx | 127 ++--------------- src/client/views/collections/TreeView.tsx | 17 +-- .../collectionFreeForm/CollectionFreeFormView.tsx | 23 ++-- .../collections/collectionFreeForm/MarqueeView.tsx | 4 +- .../collectionGrid/CollectionGridView.tsx | 2 - src/client/views/nodes/AudioBox.tsx | 9 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 11 +- .../views/nodes/ContentFittingDocumentView.tsx | 19 --- src/client/views/nodes/DocHolderBox.tsx | 3 +- src/client/views/nodes/DocumentView.scss | 19 --- src/client/views/nodes/DocumentView.tsx | 39 +++--- src/client/views/nodes/FontIconBox.tsx | 3 +- src/client/views/nodes/LabelBox.tsx | 3 +- src/client/views/nodes/LinkAnchorBox.tsx | 10 +- src/client/views/nodes/LinkBox.tsx | 3 +- src/client/views/nodes/SliderBox.tsx | 3 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 3 +- .../views/presentationview/PresElementBox.tsx | 5 +- 27 files changed, 280 insertions(+), 226 deletions(-) create mode 100644 src/client/views/StyleProvider.scss create mode 100644 src/client/views/StyleProvider.tsx (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 2705d2c34..2cb529317 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -59,6 +59,7 @@ import { TraceMobx } from '../../fields/util'; import { SelectionManager } from '../util/SelectionManager'; import { UndoManager } from '../util/UndoManager'; import { TabDocView } from './collections/TabDocView'; +import { DefaultStyleProvider } from './StyleProvider'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -319,7 +320,7 @@ export class MainView extends React.Component { PanelHeight={this.getContentsHeight} renderDepth={0} focus={emptyFunction} - styleProvider={TabDocView.styleProvider} + styleProvider={DefaultStyleProvider} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -352,7 +353,7 @@ export class MainView extends React.Component { PanelHeight={this.getContentsHeight} renderDepth={0} focus={emptyFunction} - styleProvider={TabDocView.styleProvider} + styleProvider={DefaultStyleProvider} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -404,7 +405,7 @@ export class MainView extends React.Component {
- {this.propertiesWidth() < 10 ? (null) : } + {this.propertiesWidth() < 10 ? (null) : }
; } @@ -457,7 +458,7 @@ export class MainView extends React.Component { fieldKey={"data"} dropAction={"alias"} parentActive={returnFalse} - styleProvider={TabDocView.styleProvider} + styleProvider={DefaultStyleProvider} rootSelected={returnTrue} bringToFront={emptyFunction} select={emptyFunction} @@ -532,7 +533,7 @@ export class MainView extends React.Component { pinToPres={emptyFunction} rootSelected={returnTrue} onClick={undefined} - styleProvider={TabDocView.styleProvider} + styleProvider={DefaultStyleProvider} removeDocument={undefined} ScreenToLocalTransform={Transform.Identity} ContentScaling={returnOne} @@ -595,7 +596,7 @@ export class MainView extends React.Component { {LinkDescriptionPopup.descriptionPopup ? : null} {DocumentLinksButton.EditLink ? : (null)} - {LinkDocPreview.LinkInfo ? : (null)} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index b7bd88344..124da6016 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -16,6 +16,7 @@ import { DragManager } from "../util/DragManager"; import { List } from "../../fields/List"; import { CurrentUserUtils } from "../util/CurrentUserUtils"; import { TabDocView } from "./collections/TabDocView"; +import { DefaultStyleProvider } from "./StyleProvider"; export type OverlayDisposer = () => void; @@ -195,7 +196,7 @@ export class OverlayView extends React.Component { parentActive={returnTrue} whenActiveChanged={emptyFunction} focus={emptyFunction} - styleProvider={TabDocView.styleProvider} + styleProvider={DefaultStyleProvider} addDocTab={returnFalse} pinToPres={emptyFunction} docFilters={returnEmptyFilter} diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 03e0a35ec..eb7df0248 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -29,6 +29,7 @@ import { PropertiesDocContextSelector } from "./PropertiesDocContextSelector"; import "./PropertiesView.scss"; import { CollectionViewType } from "./collections/CollectionView"; import { DocumentViewProps, StyleProviderFunc } from "./nodes/DocumentView"; +import { DefaultStyleProvider } from "./StyleProvider"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -269,7 +270,7 @@ export class PropertiesView extends React.Component { DataDoc={this.dataDoc} renderDepth={1} rootSelected={returnFalse} - styleProvider={this.props.styleProvider} + styleProvider={DefaultStyleProvider} fitToBox={true} freezeDimensions={true} dontCenter={"y"} diff --git a/src/client/views/StyleProvider.scss b/src/client/views/StyleProvider.scss new file mode 100644 index 000000000..df63288f1 --- /dev/null +++ b/src/client/views/StyleProvider.scss @@ -0,0 +1,19 @@ +.styleProvider-lock { + font-size: 12px; + width: 20; + height: 20; + position: absolute; + right: -5; + top: -5; + background: transparent; + pointer-events: all; + opacity: 0.3; + display: flex; + color: gold; + border-radius: 3px; + justify-content: center; + cursor: default; +} +.styleProvider-lock:hover { + opacity:1; +} \ No newline at end of file diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx new file mode 100644 index 000000000..0fe6df84c --- /dev/null +++ b/src/client/views/StyleProvider.tsx @@ -0,0 +1,153 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import 'golden-layout/src/css/goldenlayout-base.css'; +import 'golden-layout/src/css/goldenlayout-dark-theme.css'; +import { runInAction } from 'mobx'; +import { Doc, Opt, StrListCast } from "../../fields/Doc"; +import { List } from '../../fields/List'; +import { BoolCast, Cast, StrCast } from "../../fields/Types"; +import { DocumentType } from '../documents/DocumentTypes'; +import { CurrentUserUtils } from '../util/CurrentUserUtils'; +import { SnappingManager } from '../util/SnappingManager'; +import { UndoManager } from '../util/UndoManager'; +import { CollectionViewType } from './collections/CollectionView'; +import { DocumentViewProps } from "./nodes/DocumentView"; +import "./StyleProvider.scss"; +import React = require("react"); +import Color = require('color'); +import { listSpec } from '../../fields/Schema'; + +export enum StyleLayers { + Background = "background" +} + +export enum StyleProp { + DocContents = "docContents", + Opacity = "opacity", + Hidden = "hidden", + BoxShadow = "boxShadow", + BorderRounding = "borderRounding", + BackgroundColor = "backgroundColor", + WidgetColor = "widgetColor", + LinkBackgroundColor = "linkBackgroundColor", + HideLinkButton = "hideLinkButton", + LinkSource = "linkSource", + PointerEvents = "pointerEvents", + Decorations = "decorations", +} + +function darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkScheme); } + +function toggleBackground(doc: Doc) { + UndoManager.RunInBatch(() => runInAction(() => { + const layers = StrListCast(doc.layers); + if (!layers.includes(StyleLayers.Background)) { + if (!layers.length) doc.layers = new List([StyleLayers.Background]); + else layers.push(StyleLayers.Background); + } + else layers.splice(layers.indexOf(StyleLayers.Background), 1); + doc._overflow = !layers.includes(StyleLayers.Background) ? "visible" : undefined; + if (!layers.includes(StyleLayers.Background)) { + //this.props.bringToFront(doc, true); + // const wid = this.Document[WidthSym](); // change the nativewidth and height if the background is to be a collection that aggregates stuff that is added to it. + // const hgt = this.Document[HeightSym](); + // Doc.SetNativeWidth(this.props.Document[DataSym], wid); + // Doc.SetNativeHeight(this.props.Document[DataSym], hgt); + } + }), "toggleBackground"); +} + +// +// a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab +// +export function DefaultStyleProvider(doc: Opt, props: Opt, property: string): any { + switch (property.split(":")[0]) { + case StyleProp.DocContents: return undefined; + case StyleProp.WidgetColor: return darkScheme() ? "lightgrey" : "dimgrey"; + case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null)); + case StyleProp.Hidden: return BoolCast(doc?._hidden, BoolCast(doc?.hidden)); + case StyleProp.BorderRounding: return !doc ? undefined : StrCast(doc._borderRounding, StrCast(doc.borderRounding)); + case StyleProp.BackgroundColor: { + if (Doc.UserDoc().renderStyle === "comic") return undefined; + let docColor: Opt = StrCast(doc?._backgroundColor, StrCast(doc?.backgroundColor)); + if (!docColor) { + switch (doc?.type) { + case DocumentType.PRESELEMENT: docColor = darkScheme() ? "" : ""; break; + case DocumentType.PRES: docColor = darkScheme() ? "#3e3e3e" : "white"; break; + case DocumentType.FONTICON: docColor = "black"; break; + case DocumentType.RTF: docColor = darkScheme() ? "#2d2d2d" : "#f1efeb"; break; + case DocumentType.LABEL: + case DocumentType.BUTTON: docColor = darkScheme() ? "#2d2d2d" : "lightgray"; break; + case DocumentType.LINK: + case DocumentType.COL: + docColor = Doc.IsSystem(doc) ? (darkScheme() ? "rgb(62,62,62)" : "lightgrey") : + StrListCast(doc.layers).includes(StyleLayers.Background) ? "cyan" : + doc.annotationOn ? "#00000015" : + StrCast((props?.renderDepth || 0) > 0 ? + Doc.UserDoc().activeCollectionNestedBackground : + Doc.UserDoc().activeCollectionBackground); + break; + //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)"; + default: docColor = darkScheme() ? "black" : "white"; break; + } + } + if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = Color(docColor.toLowerCase()).fade(0.5).toString(); + return docColor; + } + case StyleProp.BoxShadow: { + if (!doc || props?.styleProvider?.(doc, props, StyleProp.Opacity) === 0) return undefined; // if it's not visible, then no shadow) + const isBackground = StrListCast(doc.layers).includes(StyleLayers.Background); + switch (doc?.type) { + case DocumentType.COL: return isBackground ? undefined : + `${darkScheme() ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(doc.boxShadow, "0.2vw 0.2vw 0.8vw")}`; + default: + return doc.z ? `#9c9396 ${StrCast(doc?.boxShadow, "10px 10px 0.9vw")}` : // if it's a floating doc, give it a big shadow + props?.backgroundHalo?.(doc) && doc.type !== DocumentType.INK ? (`${props?.styleProvider?.(doc, props, StyleProp.BackgroundColor)} ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground ? 100 : 50) / props.ContentScaling()}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent + isBackground ? undefined : // if it's a background & has a cluster color, make the shadow spread really big + StrCast(doc.boxShadow, ""); + } + } + case StyleProp.PointerEvents: + const layer = doc && props?.layerProvider?.(doc); + if (props?.styleProvider?.(doc, props, StyleProp.Opacity) === 0 || doc?.type === DocumentType.INK || doc?.isInkMask) return "none"; + if (layer === false && !property.includes(":selected") && !SnappingManager.GetIsDragging()) return "none"; + if (doc?.type !== DocumentType.INK && layer === true) return "all"; + return undefined; + case StyleProp.Decorations: + if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform) { + const isBackground = StrListCast(doc?.layers).includes(StyleLayers.Background); + return doc && (isBackground || property.includes(":selected")) && (props?.renderDepth || 0) > 0 && + ((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ? +
toggleBackground(doc)}> + +
+ : (null); + } + } +} + +// +// a preliminary semantic-"layering/grouping" mechanism for determining interactive properties of documents +// currently, the provider tests whether the docuemnt's layer field matches the activeLayer field of the tab. +// if it matches, then the document gets pointer events, otherwise it does not. +// +export function DefaultLayerProvider(thisDoc: Doc) { + return (doc: Doc, assign?: boolean) => { + if (doc.z) return true; + if (assign) { + const activeLayer = StrCast(thisDoc?.activeLayer); + if (activeLayer) { + const layers = Cast(doc.layers, listSpec("string"), []); + if (layers.length && !layers.includes(activeLayer)) layers.push(activeLayer); + else if (!layers.length) doc.layers = new List([activeLayer]); + if (activeLayer === "red" || activeLayer === "green" || activeLayer === "blue") doc._backgroundColor = activeLayer; + } + return true; + } else { + if (Doc.AreProtosEqual(doc, thisDoc)) return true; + const layers = Cast(doc.layers, listSpec("string"), []); + if (!layers.length && !thisDoc?.activeLayer) return true; + if (layers.includes(StrCast(thisDoc?.activeLayer))) return true; + return false; + } + }; +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 8b7a46e2f..26c36507a 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -15,6 +15,7 @@ import { ContextMenu } from '../ContextMenu'; import { ObjectField } from '../../../fields/ObjectField'; import { returnFalse, returnZero, OmitKeys } from '../../../Utils'; import { ScriptField } from '../../../fields/ScriptField'; +import { StyleProp } from '../StyleProvider'; type CarouselDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>; const CarouselDocument = makeInterface(documentSchema, collectionSchema); @@ -65,7 +66,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 8dfb7cefe..2896d244e 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -28,6 +28,7 @@ import "./CollectionStackingView.scss"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; import { CollectionSubView } from "./CollectionSubView"; import { CollectionViewType } from "./CollectionView"; +import { StyleProp } from "../StyleProvider"; const _global = (window /* browser */ || global /* node */) as any; type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>; @@ -188,7 +189,7 @@ export class CollectionStackingView extends CollectionSubView this.getDocHeight(doc); const styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { - if (property === "opacity" && doc) { + if (property === StyleProp.Opacity && doc) { if (this.props.childOpacity) { return this.props.childOpacity(); } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 89ed3a147..4e521956d 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -24,6 +24,7 @@ import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import { TreeView } from "./TreeView"; import React = require("react"); +import { StyleProp } from '../StyleProvider'; export type collectionTreeViewProps = { treeViewHideTitle?: boolean; @@ -211,7 +212,7 @@ export class CollectionTreeView extends CollectionSubView { CollectionView: this, }; const boxShadow = Doc.UserDoc().renderStyle === "comic" || this.props.Document.treeViewOutlineMode || this.collectionViewType === CollectionViewType.Linear ? undefined : - this.props.styleProvider?.(this.props.Document, this.props, "boxShadow"); + this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BoxShadow); return (
{this.showIsTagged()} diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index ba8b5e418..8b5143013 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -32,6 +32,7 @@ import React = require("react"); import { List } from '../../../fields/List'; import { DocumentType } from '../../documents/DocumentTypes'; import Color = require('color'); +import { StyleProp, DefaultStyleProvider, DefaultLayerProvider, StyleLayers } from '../StyleProvider'; const _global = (window /* browser */ || global /* node */) as any; interface TabDocViewProps { @@ -84,7 +85,7 @@ export class TabDocView extends React.Component { toggle.style.borderLeft = "solid 1px black"; toggle.onclick = (e: MouseEvent) => { if (tab.contentItem === tab.header.parent.getActiveContentItem()) { - tab.DashDoc.activeLayer = tab.DashDoc.activeLayer ? undefined : "background"; + tab.DashDoc.activeLayer = tab.DashDoc.activeLayer ? undefined : StyleLayers.Background; } }; tab.element[0].style.borderTopRightRadius = "8px"; @@ -279,7 +280,6 @@ export class TabDocView extends React.Component { @computed get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.ContentScaling()) / 2 : 0; } @computed get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.ContentScaling()) / this._panelWidth * 100}% ` : undefined; } @computed get layoutDoc() { return this._document && Doc.Layout(this._document); } - @computed static get darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkScheme); } // adds a tab to the layout based on the locaiton parameter which can be: // close[:{left,right,top,bottom}] - e.g., "close" will close the tab, "close:left" will close the left tab, @@ -303,7 +303,7 @@ export class TabDocView extends React.Component { } } - @computed get tabColor() { return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, TabDocView.styleProvider(this._document, undefined, "backgroundColor"))); } + @computed get tabColor() { return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, DefaultStyleProvider(this._document, undefined, StyleProp.BackgroundColor))); } @computed get renderBounds() { const bounds = this._document ? Cast(this._document._renderContentBounds, listSpec("number"), [0, 0, this.returnMiniSize(), this.returnMiniSize()]) : [0, 0, 0, 0]; const xbounds = bounds[2] - bounds[0]; @@ -374,7 +374,7 @@ export class TabDocView extends React.Component { {"toggle minimap"}
}>
e.stopPropagation()} onClick={action(e => { e.stopPropagation(); this._document!.hideMinimap = !this._document!.hideMinimap; })} - style={{ background: TabDocView.styleProvider(this._document, undefined, "backgroundColor") }} > + style={{ background: DefaultStyleProvider(this._document, undefined, StyleProp.BackgroundColor) }} >
@@ -388,123 +388,22 @@ export class TabDocView extends React.Component { } active = () => this._isActive; - // - // a preliminary semantic-"layering/grouping" mechanism for determining interactive properties of documents - // currently, the provider tests whether the docuemnt's layer field matches the activeLayer field of the tab. - // if it matches, then the document gets pointer events, otherwise it does not. - // - layerProvider = (doc: Doc, assign?: boolean) => { - if (doc.z) return true; - if (assign) { - const activeLayer = StrCast(this._document?.activeLayer); - if (activeLayer) { - const layers = Cast(doc.layers, listSpec("string"), []); - if (layers.length && !layers.includes(activeLayer)) layers.push(activeLayer); - else if (!layers.length) doc.layers = new List([activeLayer]); - if (activeLayer === "red" || activeLayer === "green" || activeLayer === "blue") doc._backgroundColor = activeLayer; - } - return true; - } else { - if (Doc.AreProtosEqual(doc, this._document)) return true; - const layers = Cast(doc.layers, listSpec("string"), []); - if (!layers.length && !this._document?.activeLayer) return true; - if (layers.includes(StrCast(this._document?.activeLayer))) return true; - return false; - } - } - static toggleBackground = undoBatch(action((doc: Doc) => { - const layers = StrListCast(doc.layers); - if (!layers.includes("background")) { - if (!layers.length) doc.layers = new List(["background"]); - else layers.push("background"); - } - else layers.splice(layers.indexOf("background"), 1); - doc._overflow = !layers.includes("background") ? "visible" : undefined; - if (!layers.includes("background")) { - //this.props.bringToFront(doc, true); - // const wid = this.Document[WidthSym](); // change the nativewidth and height if the background is to be a collection that aggregates stuff that is added to it. - // const hgt = this.Document[HeightSym](); - // Doc.SetNativeWidth(this.props.Document[DataSym], wid); - // Doc.SetNativeHeight(this.props.Document[DataSym], hgt); - } - })); - // - // a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab - // - public static styleProvider = (doc: Opt, props: Opt, property: string): any => { - switch (property.split(":")[0]) { - case "docContents": return undefined; - case "widgetColor": return TabDocView.darkScheme ? "lightgrey" : "dimgrey"; - case "opacity": return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null)); - case "hidden": return BoolCast(doc?._hidden, BoolCast(doc?.hidden)); - case "borderRounding": return !doc ? undefined : StrCast(doc._borderRounding, StrCast(doc.borderRounding)); - case "backgroundColor": { - if (Doc.UserDoc().renderStyle === "comic") return undefined; - let docColor: Opt = StrCast(doc?._backgroundColor, StrCast(doc?.backgroundColor)); - if (!docColor) { - switch (doc?.type) { - case DocumentType.PRESELEMENT: docColor = TabDocView.darkScheme ? "" : ""; break; - case DocumentType.PRES: docColor = TabDocView.darkScheme ? "#3e3e3e" : "white"; break; - case DocumentType.FONTICON: docColor = "black"; break; - case DocumentType.RTF: docColor = TabDocView.darkScheme ? "#2d2d2d" : "#f1efeb"; break; - case DocumentType.LABEL: - case DocumentType.BUTTON: docColor = TabDocView.darkScheme ? "#2d2d2d" : "lightgray"; break; - case DocumentType.LINK: - case DocumentType.COL: - docColor = Doc.IsSystem(doc) ? (TabDocView.darkScheme ? "rgb(62,62,62)" : "lightgrey") : - StrCast((props?.renderDepth || 0) > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground); - break; - //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)"; - default: docColor = TabDocView.darkScheme ? "black" : "white"; break; - } - } - if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = Color(docColor.toLowerCase()).fade(0.5).toString(); - return docColor; - } - case "boxShadow": { - if (!doc || props?.styleProvider?.(doc, props, "opacity") === 0) return undefined; // if it's not visible, then no shadow) - const isBackground = StrListCast(doc.layers).includes("background"); - switch (doc?.type) { - case DocumentType.COL: return isBackground ? undefined : - `${TabDocView.darkScheme ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(doc.boxShadow, "0.2vw 0.2vw 0.8vw")}`; - default: - return doc.z ? `#9c9396 ${StrCast(doc?.boxShadow, "10px 10px 0.9vw")}` : // if it's a floating doc, give it a big shadow - props?.backgroundHalo?.(doc) && doc.type !== DocumentType.INK ? (`${props?.styleProvider?.(doc, props, "backgroundColor")} ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground ? 100 : 50) / props.ContentScaling()}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent - isBackground ? undefined : // if it's a background & has a cluster color, make the shadow spread really big - StrCast(doc.boxShadow, ""); - } - } - case "pointerEvents": - const layer = doc && props?.layerProvider?.(doc); - if (props?.styleProvider?.(doc, props, "opacity") === 0 || doc?.type === DocumentType.INK || doc?.isInkMask) return "none"; - if (layer === false && !property.includes(":selected") && !SnappingManager.GetIsDragging()) return "none"; - if (doc?.type !== DocumentType.INK && layer === true) return "all"; - return undefined; - case "decorations": - if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform) { - const isBackground = StrListCast(doc?.layers).includes("background"); - return doc && (isBackground || property.includes(":selected")) && (props?.renderDepth || 0) > 0 && - ((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ? -
TabDocView.toggleBackground(doc)}> - -
- : (null); - } - } - } public static miniStyleProvider = (doc: Opt, props: Opt, property: string): any => { if (doc) { - switch (property) { - case "docContents": + switch (property.split(":")[0]) { + default: return DefaultStyleProvider(doc, props, property); + case StyleProp.PointerEvents: return "none"; + case StyleProp.DocContents: const background = doc.type === DocumentType.PDF ? "red" : doc.type === DocumentType.IMG ? "blue" : doc.type === DocumentType.RTF ? "orange" : doc.type === DocumentType.VID ? "purple" : doc.type === DocumentType.WEB ? "yellow" : "gray"; - return doc.type === DocumentType.COL ? undefined :
; - default: - return (property.startsWith("pointerEvents")) ? "none" : TabDocView.styleProvider(doc, props, property); + return doc.type === DocumentType.COL ? + undefined : +
; } } } + @computed get layerProvider() { return this._document && DefaultLayerProvider(this._document); } @computed get docView() { TraceMobx(); return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? (null) : @@ -526,7 +425,7 @@ export class TabDocView extends React.Component { parentActive={this.active} whenActiveChanged={emptyFunction} focus={this.focusFunc} - styleProvider={TabDocView.styleProvider} + styleProvider={DefaultStyleProvider} addDocTab={this.addDocTab} pinToPres={TabDocView.PinDoc} docFilters={CollectionDockingView.Instance.docFilters} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 53cdca2af..28503a23f 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -29,6 +29,7 @@ import { CollectionTreeView } from './CollectionTreeView'; import { CollectionView, CollectionViewType } from './CollectionView'; import "./TreeView.scss"; import React = require("react"); +import { StyleProp } from '../StyleProvider'; export interface TreeViewProps { document: Doc; @@ -441,7 +442,7 @@ export class TreeView extends React.Component { return
@@ -499,22 +500,22 @@ export class TreeView extends React.Component { titleStyleProvider = (doc: (Doc | undefined), props: Opt, property: string): any => { if (!doc || doc !== this.doc) return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView - switch (property) { - case "opacity": return this.outlineMode ? undefined : 1; - case "backgroundColor": return StrCast(doc._backgroundColor, StrCast(doc.backgroundColor)); - case "docContents": return !props?.treeViewDoc ? (null) : + switch (property.split(":")[0]) { + case StyleProp.Opacity: return this.outlineMode ? undefined : 1; + case StyleProp.BackgroundColor: return StrCast(doc._backgroundColor, StrCast(doc.backgroundColor)); + case StyleProp.DocContents: return !props?.treeViewDoc ? (null) :
{StrCast(doc?.title)}
; - default: if (property.startsWith("decorations")) return (null); + case StyleProp.Decorations: return (null); } } embeddedStyleProvider = (doc: (Doc | undefined), props: Opt, property: string): any => { - if (property.startsWith("decorations")) return (null); + if (property.startsWith(StyleProp.Decorations)) return (null); return this.props?.treeView?.props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView } onKeyDown = (e: React.KeyboardEvent) => { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 75411b3c5..cfc5e8b61 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -47,6 +47,7 @@ import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; +import { StyleProp, StyleLayers } from "../../StyleProvider"; export const panZoomSchema = createSchema({ _panX: "number", @@ -246,7 +247,7 @@ export class CollectionFreeFormView extends CollectionSubView, props: Opt, property: string) => { - let clusterColor = this.props.styleProvider?.(doc, props, property); // bcz: check 'props' used to be renderDepth + 1 - if (property !== "backgroundColor") return clusterColor; + let styleProp = this.props.styleProvider?.(doc, props, property); // bcz: check 'props' used to be renderDepth + 1 + if (property !== StyleProp.BackgroundColor) return styleProp; const cluster = NumCast(doc?.cluster); if (this.Document._useClusters) { if (this._clusterSets.length <= cluster) { @@ -413,14 +414,14 @@ export class CollectionFreeFormView extends CollectionSubView s.backgroundColor); // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document - set && set.filter(s => !Cast(s.layers, listSpec("string"), []).includes("background")).map(s => clusterColor = StrCast(s.backgroundColor)); - set && set.filter(s => Cast(s.layers, listSpec("string"), []).includes("background")).map(s => clusterColor = StrCast(s.backgroundColor)); + set && set.filter(s => !StrListCast(s.layers).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); + set && set.filter(s => StrListCast(s.layers).includes(StyleLayers.Background)).map(s => styleProp = StrCast(s.backgroundColor)); } - } else if (doc && NumCast(doc.group, -1) !== -1) clusterColor = "gray"; - return clusterColor; + } else if (doc && NumCast(doc.group, -1) !== -1) styleProp = "gray"; + return styleProp; } @action @@ -870,7 +871,7 @@ export class CollectionFreeFormView extends CollectionSubView { - if (sendToBack || Cast(doc.layers, listSpec("string"), []).includes("background")) { + if (sendToBack || StrListCast(doc.layers).includes(StyleLayers.Background)) { doc.zIndex = 0; } else if (doc.isInkMask) { doc.zIndex = 5000; @@ -1053,7 +1054,7 @@ export class CollectionFreeFormView extends CollectionSubView intersectRect(docDims(doc), rect); const otherBounds = { left: this.panX(), top: this.panY(), width: Math.abs(size[0]), height: Math.abs(size[1]) }; - let snappableDocs = activeDocs.filter(doc => !StrListCast(doc.layers).includes("background") && doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to + let snappableDocs = activeDocs.filter(doc => !StrListCast(doc.layers).includes(StyleLayers.Background) && doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect))); // if not, see if there are background docs to snap to !snappableDocs.length && (snappableDocs = activeDocs.filter(doc => doc.z !== undefined && isDocInView(doc, otherBounds))); // if not, then why not snap to floating docs diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 52310d628..f1f190bff 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -27,6 +27,7 @@ import { CollectionView } from "../CollectionView"; import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu"; import "./MarqueeView.scss"; import React = require("react"); +import { StyleLayers } from "../../StyleProvider"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -349,7 +350,6 @@ export class MarqueeView extends React.Component(layers); - newCollection.backgroundColor = this.props.isAnnotationOverlay ? "#00000015" : layers.includes("background") ? "cyan" : undefined; newCollection._width = this.Bounds.width; newCollection._height = this.Bounds.height; newCollection.x = this.Bounds.left; @@ -523,7 +523,7 @@ export class MarqueeView extends React.Component { - const newCollection = this.getCollection([], undefined, ["background"]); + const newCollection = this.getCollection([], undefined, [StyleLayers.Background]); this.props.addDocument?.(newCollection); MarqueeOptionsMenu.Instance.fadeOut(true); this.hideMarquee(); diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index bef197bee..1a4eb8b7b 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -165,8 +165,6 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} Document={layout} DataDoc={layout.resolvedDataDoc as Doc} - styleProvider={this.props.styleProvider} - ContainingCollectionDoc={this.props.Document} PanelWidth={width} PanelHeight={height} ContentScaling={returnOne} diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index c89e21312..b495cdd1b 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -29,6 +29,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import { FormattedTextBoxComment } from "./formattedText/FormattedTextBoxComment"; import { LinkAnchorBox } from "./LinkAnchorBox"; import { LinkDocPreview } from "./LinkDocPreview"; +import { StyleProp } from "../StyleProvider"; declare class MediaRecorder { // whatever MediaRecorder has @@ -538,7 +539,10 @@ export class AudioBox extends ViewBoxAnnotatableComponent AudioBox.RangeScript; labelScript = () => AudioBox.LabelScript; - + static audioStyleProvider = (doc: Doc | undefined, props: Opt, property: string) => { + if (property === StyleProp.BackgroundColor) return "transparent"; + if (property === StyleProp.PointerEvents) return "none"; + } render() { const interactive = SnappingManager.GetIsDragging() || this.active() ? "-interactive" : ""; this._first = true; // for indicating the first marker that is rendered @@ -637,8 +641,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent, props: Opt, property: string) => property === "backgroundColor" ? "transparent" : undefined} - pointerEvents={"none"} + styleProvider={AudioBox.audioStyleProvider} LayoutTemplate={undefined} LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(l, la2)}`)} /> diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 46c311350..1b47f4551 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -16,6 +16,7 @@ import "./CollectionFreeFormDocumentView.scss"; import { ContentFittingDocumentView } from "./ContentFittingDocumentView"; import { DocumentView, DocumentViewProps } from "./DocumentView"; import React = require("react"); +import { StyleProp } from "../StyleProvider"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined; @@ -59,7 +60,7 @@ export class CollectionFreeFormDocumentView extends DocComponent, property: string) => { - if (property === "opacity" && doc === this.layoutDoc) return this.Opacity; // only change the opacity for this specific document, not its children + if (property === StyleProp.Opacity && doc === this.layoutDoc) return this.Opacity; // only change the opacity for this specific document, not its children return this.props.styleProvider?.(doc, props, property); } @@ -147,13 +148,13 @@ export class CollectionFreeFormDocumentView extends DocComponent this; @computed get pointerEvents() { if (this.props.pointerEvents === "none") return "none"; - return this.props.styleProvider?.(this.Document, this.props, !this._contentView?.docView?.isSelected() ? "pointerEvents:selected" : "pointerEvents"); + return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents + (!this._contentView?.docView?.isSelected() ? ":selected" : "")); } render() { TraceMobx(); - const backgroundColor = this.props.styleProvider?.(this.Document, this.props, "backgroundColor"); - const borderRadius = this.props.styleProvider?.(this.Document, this.props, "borderRounding"); - const boxShadow = this.props.styleProvider?.(this.Document, this.props, "boxShadow"); + const backgroundColor = this.props.styleProvider?.(this.Document, this.props, StyleProp.BackgroundColor); + const borderRadius = this.props.styleProvider?.(this.Document, this.props, StyleProp.BorderRounding); + const boxShadow = this.props.styleProvider?.(this.Document, this.props, StyleProp.BoxShadow); const divProps: DocumentViewProps = { ...this.props, CollectionFreeFormDocumentView: this.returnThis, diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 7b767a10a..ae0275c3d 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -67,32 +67,13 @@ export class ContentFittingDocumentView extends React.Component this.docView = r)} - Document={this.props.Document} - DataDoc={this.props.DataDoc} LayoutTemplate={this.props.LayoutTemplate} - LayoutTemplateString={this.props.LayoutTemplateString} PanelWidth={this.PanelWidth} PanelHeight={this.PanelHeight} ContentScaling={returnOne} - fitToBox={this.props.fitToBox} - layoutKey={this.props.layoutKey} - dropAction={this.props.dropAction} - onClick={this.props.onClick} - styleProvider={this.props.styleProvider} - addDocument={this.props.addDocument} - removeDocument={this.props.removeDocument} - moveDocument={this.props.moveDocument} - whenActiveChanged={this.props.whenActiveChanged} - ContainingCollectionView={this.props.ContainingCollectionView} - ContainingCollectionDoc={this.props.ContainingCollectionDoc} - addDocTab={this.props.addDocTab} - pinToPres={this.props.pinToPres} - parentActive={this.props.parentActive} ScreenToLocalTransform={this.getTransform} - renderDepth={this.props.renderDepth} focus={this.props.focus || emptyFunction} bringToFront={emptyFunction} - dontRegisterView={this.props.dontRegisterView} />
)}
); diff --git a/src/client/views/nodes/DocHolderBox.tsx b/src/client/views/nodes/DocHolderBox.tsx index e14093e70..1bc7bc8d7 100644 --- a/src/client/views/nodes/DocHolderBox.tsx +++ b/src/client/views/nodes/DocHolderBox.tsx @@ -19,6 +19,7 @@ import "./DocHolderBox.scss"; import { DocumentView } from "./DocumentView"; import { FieldView, FieldViewProps } from "./FieldView"; import React = require("react"); +import { StyleProp } from "../StyleProvider"; type DocHolderBoxSchema = makeInterface<[typeof documentSchema, typeof collectionSchema]>; const DocHolderBoxDocument = makeInterface(documentSchema, collectionSchema); @@ -182,7 +183,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent boolean; export type DocFocusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, focused?: boolean) => void; export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; - export interface DocumentViewSharedProps { ContainingCollectionView: Opt; ContainingCollectionDoc: Opt; @@ -118,6 +118,7 @@ export class DocumentView extends DocComponent(Docu private _doubleTap = false; private _mainCont = React.createRef(); private _titleRef = React.createRef(); + private _timeout: NodeJS.Timeout | undefined; private _dropDisposer?: DragManager.DragDropDisposer; private _gestureEventDisposer?: GestureUtils.GestureEventDisposer; private _holdDisposer?: InteractionUtils.MultiTouchEventDisposer; @@ -310,14 +311,12 @@ export class DocumentView extends DocComponent(Docu } } - _timeout: NodeJS.Timeout | undefined; - onClick = action((e: React.MouseEvent | React.PointerEvent) => { if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && this.props.renderDepth >= 0 && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { let stopPropagate = true; let preventDefault = true; - !Cast(this.props.Document.layers, listSpec("string"), []).includes("background") && (this.rootDoc._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc); + !StrListCast(this.props.Document.layers).includes(StyleLayers.Background) && (this.rootDoc._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc); if (this._doubleTap && ((this.props.renderDepth && this.props.Document.type !== DocumentType.FONTICON) || this.onDoubleClickHandler)) {// && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click if (this._timeout) { clearTimeout(this._timeout); @@ -957,7 +956,7 @@ export class DocumentView extends DocComponent(Docu onClick={this.onClickFunc} layoutKey={this.finalLayoutKey} /> {this.layoutDoc.hideAllLinks ? (null) : this.allAnchors} - {this.props.styleProvider?.(this.layoutDoc, this.props, "hideLinkButton") || (!this.isSelected() && (this.layoutDoc.isLinkButton || this.layoutDoc.hideLinkButton)) || this.props.dontRegisterView ? (null) : + {this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkButton) || (!this.isSelected() && (this.layoutDoc.isLinkButton || this.layoutDoc.hideLinkButton)) || this.props.dontRegisterView ? (null) : }
); @@ -980,8 +979,13 @@ export class DocumentView extends DocComponent(Docu anchorPanelWidth = () => this.props.PanelWidth() || 1; anchorPanelHeight = () => this.props.PanelHeight() || 1; anchorStyleProvider = (doc: Opt, props: Opt, property: string): any => { - if (property === "backgroundColor") return props?.LayoutTemplateString ? "transparent" : this.props.styleProvider?.(doc, props, "backgroundColor"); - if (property === "hideLinkButton") return true; + switch (property.split(":")[0]) { + case StyleProp.BackgroundColor: return "transparent"; + case StyleProp.LinkBackgroundColor: return this.props.styleProvider?.(doc, props, StyleProp.BackgroundColor); + case StyleProp.HideLinkButton: return true; + case StyleProp.PointerEvents: return "none"; + case StyleProp.LinkSource: return this.props.Document; + } } @computed get directLinks() { TraceMobx(); return LinkManager.Instance.getAllDirectLinks(this.rootDoc); } @@ -999,15 +1003,12 @@ export class DocumentView extends DocComponent(Docu
); @@ -1056,7 +1057,7 @@ export class DocumentView extends DocComponent(Docu } @computed get pointerEvents() { if (this.props.pointerEvents === "none") return "none"; - return this.props.styleProvider?.(this.Document, this.props, this.isSelected() ? "pointerEvents:selected" : "pointerEvents"); + return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents + (this.isSelected() ? ":selected" : "")); } @undoBatch @action @@ -1080,13 +1081,13 @@ export class DocumentView extends DocComponent(Docu TraceMobx(); if (!(this.props.Document instanceof Doc)) return (null); if (GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate) return (null); - if (this.props.styleProvider?.(this.layoutDoc, this.props, "hidden")) return null; - return this.props.styleProvider?.(this.rootDoc, this.props, "docContents") ?? + if (this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Hidden)) return null; + return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.DocContents) ??
(Docu }}> {this.innards} {this.onClickHandler && this.props.ContainingCollectionView?.props.Document._viewType === CollectionViewType.Time ?
: (null)} - {this.props.styleProvider?.(this.rootDoc, this.props, this.isSelected() ? "decorations:selected" : "decorations") || (null)} + {this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Decorations + (this.isSelected() ? ":selected" : "")) || (null)}
; } render() { - const borderRounding = this.props.styleProvider?.(this.layoutDoc, this.props, "borderRounding"); + const borderRounding = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow); const highlightIndex = this.props.LayoutTemplateString ? (Doc.IsHighlighted(this.props.Document) ? 6 : 0) : Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString const highlightColor = (CurrentUserUtils.ActiveDashboard?.darkScheme ? ["transparent", "#65350c", "#65350c", "yellow", "magenta", "cyan", "orange"] : @@ -1127,7 +1128,7 @@ export class DocumentView extends DocComponent(Docu outline: highlighting && !borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : "solid 0px", border: highlighting && borderRounding && highlightStyle === "dashed" ? `${highlightStyle} ${highlightColor} ${highlightIndex}px` : undefined, boxShadow: highlighting && borderRounding && highlightStyle !== "dashed" ? `0 0 0 ${highlightIndex}px ${highlightColor}` : - this.Document.isLinkButton && !this.props.dontRegisterView && !this.props.styleProvider?.(this.layoutDoc, this.props, "hideLinkButton") ? + this.Document.isLinkButton && !this.props.dontRegisterView && !this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkButton) ? StrCast(this.layoutDoc._linkButtonShadow, "lightblue 0em 0em 1em") : this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined, diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index a1bb0604e..000c72e94 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -14,6 +14,7 @@ import { ScriptField } from '../../../fields/ScriptField'; import { Tooltip } from '@material-ui/core'; import { DragManager } from '../../util/DragManager'; import { GetEffectiveAcl } from '../../../fields/util'; +import { StyleProp } from '../StyleProvider'; const FontIconSchema = createSchema({ icon: "string", }); @@ -61,7 +62,7 @@ export class FontIconBox extends DocComponent( render() { const label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title)); const color = StrCast(this.layoutDoc.color, this._foregroundColor); - const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, "backgroundColor"); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); const shape = StrCast(this.layoutDoc.iconShape, label ? "round" : "circle"); const icon = StrCast(this.dataDoc.icon, "user") as any; const presSize = shape === 'round' ? 25 : 30; diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index dd751b802..bc2090a33 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -13,6 +13,7 @@ import { ContextMenuProps } from '../ContextMenuItem'; import { ViewBoxBaseComponent } from '../DocComponent'; import { FieldView, FieldViewProps } from './FieldView'; import './LabelBox.scss'; +import { StyleProp } from '../StyleProvider'; const LabelSchema = createSchema({}); @@ -72,7 +73,7 @@ export class LabelBox extends ViewBoxBaseComponent this._mouseOver = false)} onMouseOver={action(() => this._mouseOver = true)} ref={this.createDropTarget} onContextMenu={this.specificContextMenu} - style={{ boxShadow: this.props.styleProvider?.(this.layoutDoc, this.props, "boxShadow") }}> + style={{ boxShadow: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow) }}>
LinkDocPreview.LinkInfo = undefined)} onPointerEnter={action(e => LinkDocPreview.LinkInfo = { addDocTab: this.props.addDocTab, - linkSrc: this.props.ContainingCollectionDoc!, + linkSrc: linkSource, linkDoc: this.rootDoc, Location: [e.clientX, e.clientY + 20] })} onPointerDown={this.onPointerDown} onClick={this.onClick} title={targetTitle} onContextMenu={this.specificContextMenu} ref={this._ref} style={{ - background: c, + background, left: `calc(${x}% - ${small ? 2.5 : 7.5}px)`, top: `calc(${y}% - ${small ? 2.5 : 7.5}px)`, transform: `scale(${anchorScale / this.props.ContentScaling()})` diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index b3fd13a77..a12a23dff 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -8,6 +8,7 @@ import { ViewBoxBaseComponent } from "../DocComponent"; import { FieldView, FieldViewProps } from './FieldView'; import "./LinkBox.scss"; import { Cast } from "../../../fields/Types"; +import { StyleProp } from "../StyleProvider"; type LinkDocument = makeInterface<[typeof documentSchema]>; const LinkDocument = makeInterface(documentSchema); @@ -17,7 +18,7 @@ export class LinkBox extends ViewBoxBaseComponent( public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); } render() { return
+ style={{ background: this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BackgroundColor) }} > e.stopPropagation()} - style={{ boxShadow: this.props.styleProvider?.(this.layoutDoc, this.props, "boxShadow") }}> + style={{ boxShadow: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow) }}>
Opt; // bcz: hack: notifies the text document when the container has made a link. allows the text doc to react and setup a hyeprlink for any selected text @@ -1599,7 +1600,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const annotated = DocListCast(this.dataDoc[this.annotationKey]).filter(d => d?.author).length; return !this.props.isSelected() && !(annotated && !this.sidebarWidth()) ? (null) :
; } diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 45d943bff..3b6b0259d 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -22,6 +22,7 @@ import { undoBatch } from "../../util/UndoManager"; import { EditableView } from "../EditableView"; import { DocumentManager } from "../../util/DocumentManager"; import { DocumentViewProps } from "../nodes/DocumentView"; +import { StyleProp } from "../StyleProvider"; export const presSchema = createSchema({ presentationTargetDoc: Doc, @@ -78,7 +79,7 @@ export class PresElementBox extends ViewBoxBaseComponent Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight); embedWidth = (): number => this.props.PanelWidth() - 35; styleProvider = (doc: (Doc | undefined), props: Opt, property: string): any => { - if (property === "opacity") return 1; + if (property === StyleProp.Opacity) return 1; return this.props.styleProvider?.(doc, props, property); } /** @@ -326,7 +327,7 @@ export class PresElementBox extends ViewBoxBaseComponent} {miniView ? (null) :
-- cgit v1.2.3-70-g09d2 From fafd62df0a918a14ecc90d99236e5a87918646e1 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 11 Dec 2020 14:43:51 -0500 Subject: got rid of ChromeHeight and replaced with HeaderMargin in style provider. made text headers not overlap the tet itself. --- src/client/views/OverlayView.tsx | 1 - src/client/views/StyleProvider.tsx | 38 +++++---- .../views/collections/CollectionStackingView.tsx | 6 +- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 7 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 3 - src/client/views/nodes/DocumentView.tsx | 93 +++++++++++----------- src/client/views/nodes/LinkBox.tsx | 1 - .../views/nodes/formattedText/FormattedTextBox.tsx | 9 ++- 9 files changed, 79 insertions(+), 81 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 124da6016..ee1af8b13 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -183,7 +183,6 @@ export class OverlayView extends React.Component { return
{bounds.r - bounds.x < 15 && bounds.b - bounds.y < 15 ? (null) : <> @@ -618,7 +618,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b }}> {closeIcon} {bounds.r - bounds.x < 100 ? null : titleArea} - {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) : + {SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) : {`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}
} placement="top">
@@ -645,7 +645,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
{seldoc?.Document.type === DocumentType.FONTICON ? (null) :
- +
} }
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index a391bb550..3311a4dcc 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -93,7 +93,7 @@ export class KeyManager { return { stopPropagation: false, preventDefault: false }; } - const ungroupings = SelectionManager.SelectedDocuments().slice(); + const ungroupings = SelectionManager.Views().slice(); UndoManager.RunInBatch(() => ungroupings.map(dv => dv.layoutDoc.group = undefined), "ungroup"); SelectionManager.DeselectAll(); break; @@ -102,7 +102,7 @@ export class KeyManager { return { stopPropagation: false, preventDefault: false }; } - const groupings = SelectionManager.SelectedDocuments().slice(); + const groupings = SelectionManager.Views().slice(); const randomGroup = random(0, 1000); UndoManager.RunInBatch(() => groupings.map(dv => dv.layoutDoc.group = randomGroup), "group"); SelectionManager.DeselectAll(); @@ -139,14 +139,14 @@ export class KeyManager { return { stopPropagation: false, preventDefault: false }; } - const selected = SelectionManager.SelectedDocuments().slice(); + const selected = SelectionManager.Views().slice(); UndoManager.RunInBatch(() => selected.map(dv => !dv.props.Document._stayInCollection && dv.props.removeDocument?.(dv.props.Document)), "delete"); SelectionManager.DeselectAll(); break; - case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), "nudge left"); break; - case "arrowright": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), "nudge right"); break; - case "arrowup": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), "nudge up"); break; - case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), "nudge down"); break; + case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), "nudge left"); break; + case "arrowright": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), "nudge right"); break; + case "arrowup": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), "nudge up"); break; + case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), "nudge down"); break; } return { @@ -160,10 +160,10 @@ export class KeyManager { const preventDefault = false; switch (keyname) { - case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(-10, 0)), "nudge left"); break; - case "arrowright": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(10, 0)), "nudge right"); break; - case "arrowup": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -10)), "nudge up"); break; - case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 10)), "nudge down"); break; + case "arrowleft": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(-10, 0)), "nudge left"); break; + case "arrowright": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(10, 0)), "nudge right"); break; + case "arrowup": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -10)), "nudge up"); break; + case "arrowdown": UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 10)), "nudge down"); break; } return { @@ -179,7 +179,7 @@ export class KeyManager { switch (keyname) { case "Æ’": case "f": - const dv = SelectionManager.SelectedDocuments()?.[0]; + const dv = SelectionManager.Views()?.[0]; UndoManager.RunInBatch(() => dv?.float(), "float"); } @@ -219,7 +219,7 @@ export class KeyManager { SearchBox.Instance.enter(undefined); break; case "o": - const target = SelectionManager.SelectedDocuments()[0]; + const target = SelectionManager.Views()[0]; target && CollectionDockingView.OpenFullScreen(target.props.Document); break; case "r": @@ -246,11 +246,11 @@ export class KeyManager { preventDefault = false; break; case "x": - if (SelectionManager.SelectedDocuments().length) { + if (SelectionManager.Views().length) { const bds = DocumentDecorations.Instance.Bounds; - const pt = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); - const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); - SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText(text); + const pt = SelectionManager.Views()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); + const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views().map(dv => dv.Document[Id]).join(":"); + SelectionManager.Views().length && navigator.clipboard.writeText(text); DocumentDecorations.Instance.onCloseClick(undefined); stopPropagation = false; preventDefault = false; @@ -259,9 +259,9 @@ export class KeyManager { case "c": if (!PDFMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) { const bds = DocumentDecorations.Instance.Bounds; - const pt = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); - const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); - SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText(text); + const pt = SelectionManager.Views()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); + const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views().map(dv => dv.Document[Id]).join(":"); + SelectionManager.Views().length && navigator.clipboard.writeText(text); stopPropagation = false; } preventDefault = false; @@ -278,7 +278,7 @@ export class KeyManager { const plain = e.clipboardData?.getData("text/plain"); const clone = plain?.startsWith("__DashCloneId("); if (plain && (plain.startsWith("__DashDocId(") || clone)) { - const first = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; + const first = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; if (first?.props.Document.type === DocumentType.COL) { const docids = plain.split(":"); let count = 1; diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index ad5c70fb1..2dac44bf8 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -25,7 +25,7 @@ export class InkStrokeProperties { } @computed get selectedInk() { - const inks = SelectionManager.SelectedDocuments().filter(i => Document(i.rootDoc).type === DocumentType.INK); + const inks = SelectionManager.Views().filter(i => Document(i.rootDoc).type === DocumentType.INK); return inks.length ? inks : undefined; } @computed get unFilled() { return this.selectedInk?.reduce((p, i) => p && !i.rootDoc.fillColor ? true : false, true) || false; } @@ -150,7 +150,7 @@ export class InkStrokeProperties { @action rotate = (angle: number) => { const _centerPoints: { X: number, Y: number }[] = []; - SelectionManager.SelectedDocuments().forEach(action(inkView => { + SelectionManager.Views().forEach(action(inkView => { const doc = Document(inkView.rootDoc); if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { const ink = Cast(doc.data, InkField)?.inkData; @@ -167,7 +167,7 @@ export class InkStrokeProperties { })); var index = 0; - SelectionManager.SelectedDocuments().forEach(action(inkView => { + SelectionManager.Views().forEach(action(inkView => { const doc = Document(inkView.rootDoc); if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { doc.rotation = Number(doc.rotation) + Number(angle); diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 1731d715a..bc3be4076 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -55,8 +55,8 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; } @computed get selectedDocumentView() { - if (SelectionManager.SelectedDocuments().length) { - return SelectionManager.SelectedDocuments()[0]; + if (SelectionManager.Views().length) { + return SelectionManager.Views()[0]; } else return undefined; } @@ -187,7 +187,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @action @undoBatch onLock = () => { - SelectionManager.SelectedDocuments().forEach(dv => dv.docView?.toggleLockPosition()); + SelectionManager.Views().forEach(dv => dv.docView?.toggleLockPosition()); } @computed @@ -224,7 +224,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action setDictation = () => { - SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._showAudio = dv.rootDoc._showAudio === !dv.rootDoc._showAudio); + SelectionManager.Views().forEach(dv => dv.rootDoc._showAudio = dv.rootDoc._showAudio === !dv.rootDoc._showAudio); } @computed @@ -244,7 +244,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action setTitle = () => { - SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._showTitle = dv.rootDoc._showTitle === undefined ? "title" : undefined); + SelectionManager.Views().forEach(dv => dv.rootDoc._showTitle = dv.rootDoc._showTitle === undefined ? "title" : undefined); } @computed @@ -263,7 +263,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action setCaption = () => { - SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined); + SelectionManager.Views().forEach(dv => dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined); } @computed @@ -282,7 +282,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action setChrome = () => { - SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._chromeStatus = dv.rootDoc._chromeStatus === "disabled" ? "enabled" : "disabled"); + SelectionManager.Views().forEach(dv => dv.rootDoc._chromeStatus = dv.rootDoc._chromeStatus === "disabled" ? "enabled" : "disabled"); } @computed @@ -325,7 +325,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { const value = e.target.value; this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value); - SelectionManager.SelectedDocuments().forEach(dv => { + SelectionManager.Views().forEach(dv => { if (value === "nothing") { dv.docView?.noOnClick(); } else if (value === "enterPortal") { @@ -347,7 +347,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action editOnClickScript = () => { if (this.selectedDoc) { - if (SelectionManager.SelectedDocuments().length) SelectionManager.SelectedDocuments().forEach(dv => DocUtils.makeCustomViewClicked(dv.rootDoc, undefined, "onClick")); + if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => DocUtils.makeCustomViewClicked(dv.rootDoc, undefined, "onClick")); else DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick"); } } @@ -432,7 +432,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @action @undoBatch changeFitToBox = () => { if (this.selectedDoc) { - if (SelectionManager.SelectedDocuments().length) SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._fitToBox = !dv.rootDoc._fitToBox); + if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitToBox = !dv.rootDoc._fitToBox); else this.selectedDoc._fitToBox = !this.selectedDoc._fitToBox; } } @@ -440,7 +440,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { @action @undoBatch changeClusters = () => { if (this.selectedDoc) { - if (SelectionManager.SelectedDocuments().length) SelectionManager.SelectedDocuments().forEach(dv => dv.rootDoc._useClusters = !dv.rootDoc._useClusters); + if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._useClusters = !dv.rootDoc._useClusters); else this.selectedDoc._useClusters = !this.selectedDoc._useClusters; } } diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 1c14bc721..32342075c 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -48,7 +48,7 @@ export class PropertiesView extends React.Component { @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; } @computed get selectedDocumentView() { - if (SelectionManager.SelectedDocuments().length) return SelectionManager.SelectedDocuments()[0]; + if (SelectionManager.Views().length) return SelectionManager.Views()[0]; if (PresBox.Instance?._selectedArray.size) return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc); return undefined; } @@ -118,8 +118,8 @@ export class PropertiesView extends React.Component { @computed get expandedField() { if (this.dataDoc && this.selectedDoc) { const ids: { [key: string]: string } = {}; - const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : - SelectionManager.SelectedDocuments().map(dv => this.layoutFields ? Doc.Layout(dv.layoutDoc) : dv.dataDoc); + const docs = SelectionManager.Views().length < 2 ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : + SelectionManager.Views().map(dv => this.layoutFields ? Doc.Layout(dv.layoutDoc) : dv.dataDoc); docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key))); const rows: JSX.Element[] = []; for (const key of Object.keys(ids).slice().sort()) { @@ -162,7 +162,7 @@ export class PropertiesView extends React.Component { @computed get noviceFields() { if (this.dataDoc) { const ids: { [key: string]: string } = {}; - const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.dataDoc] : SelectionManager.SelectedDocuments().map(dv => dv.dataDoc); + const docs = SelectionManager.Views().length < 2 ? [this.dataDoc] : SelectionManager.Views().map(dv => dv.dataDoc); docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key))); const rows: JSX.Element[] = []; const noviceReqFields = ["author", "creationDate", "tags"]; @@ -217,7 +217,7 @@ export class PropertiesView extends React.Component { @undoBatch setKeyValue = (value: string) => { - const docs = SelectionManager.SelectedDocuments().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.SelectedDocuments().map(dv => this.layoutFields ? dv.layoutDoc : dv.dataDoc); + const docs = SelectionManager.Views().length < 2 && this.selectedDoc ? [this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc] : SelectionManager.Views().map(dv => this.layoutFields ? dv.layoutDoc : dv.dataDoc); docs.forEach(doc => { if (value.indexOf(":") !== -1) { const newVal = value[0].toUpperCase() + value.substring(1, value.length); @@ -256,7 +256,7 @@ export class PropertiesView extends React.Component { } @computed get layoutPreview() { - if (SelectionManager.SelectedDocuments().length > 1) { + if (SelectionManager.Views().length > 1) { return "-- multiple selected --"; } if (this.selectedDoc) { @@ -305,7 +305,7 @@ export class PropertiesView extends React.Component { */ @undoBatch changePermissions = (e: any, user: string) => { - const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.selectedDoc!] : SelectionManager.SelectedDocuments().map(docView => docView.props.Document); + const docs = SelectionManager.Views().length < 2 ? [this.selectedDoc!] : SelectionManager.Views().map(docView => docView.props.Document); SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs); } @@ -385,9 +385,9 @@ export class PropertiesView extends React.Component { ]); // all selected docs - const docs = SelectionManager.SelectedDocuments().length < 2 ? + const docs = SelectionManager.Views().length < 2 ? [this.layoutDocAcls ? this.selectedDoc! : this.selectedDoc![DataSym]] - : SelectionManager.SelectedDocuments().map(docView => this.layoutDocAcls ? docView.props.Document : docView.props.Document[DataSym]); + : SelectionManager.Views().map(docView => this.layoutDocAcls ? docView.props.Document : docView.props.Document[DataSym]); const target = docs[0]; @@ -438,7 +438,7 @@ export class PropertiesView extends React.Component { @computed get editableTitle() { const titles = new Set(); - SelectionManager.SelectedDocuments().forEach(dv => titles.add(StrCast(dv.rootDoc.title))); + SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.rootDoc.title))); const title = Array.from(titles.keys()).length > 1 ? "--multiple selected--" : StrCast(this.selectedDoc?.title); return
{ @undoBatch @action setTitle = (value: string) => { - if (SelectionManager.SelectedDocuments().length > 1) { - SelectionManager.SelectedDocuments().map(dv => Doc.SetInPlace(dv.rootDoc, "title", value, true)); + if (SelectionManager.Views().length > 1) { + SelectionManager.Views().map(dv => Doc.SetInPlace(dv.rootDoc, "title", value, true)); return true; } else if (this.dataDoc) { if (this.selectedDoc) Doc.SetInPlace(this.selectedDoc, "title", value, true); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index d6571276a..83192164f 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -135,7 +135,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt { } componentDidMount() { - reaction(() => SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0], + reaction(() => SelectionManager.Views().length && SelectionManager.Views()[0], (doc) => doc && this.SetSelection(doc)); } @@ -372,7 +372,7 @@ export class CollectionViewBaseChrome extends React.Component { - SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { + SelectionManager.Views().forEach(action((element: DocumentView) => { const doc = Document(element.rootDoc); if (doc.type === DocumentType.INK) { switch (field) { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f153f1cca..c39f8b255 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -352,7 +352,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action setFocused = (doc: Doc) => this._focusedTable = doc; @action setPreviewDoc = (doc: Opt) => { - SelectionManager.SelectSchemaDoc(this, doc); + SelectionManager.SelectSchemaView(this, doc); this._previewDoc = doc; } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 38e461e46..d7b9d9745 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -305,8 +305,8 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: } else { let srcUrl: string | undefined; let srcWeb: Doc | undefined; - if (SelectionManager.SelectedDocuments().length) { - srcWeb = SelectionManager.SelectedDocuments()[0].props.Document; + if (SelectionManager.Views().length) { + srcWeb = SelectionManager.Views()[0].props.Document; srcUrl = (srcWeb.data as WebField).url?.href?.match(/http[s]?:\/\/[^/]*/)?.[0]; } const reg = new RegExp(Utils.prepend(""), "g"); @@ -315,7 +315,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc).text = text; this.addDocument(htmlDoc); if (srcWeb) { - const iframe = SelectionManager.SelectedDocuments()[0].ContentDiv?.getElementsByTagName("iframe")?.[0]; + const iframe = SelectionManager.Views()[0].ContentDiv?.getElementsByTagName("iframe")?.[0]; const focusNode = (iframe?.contentDocument?.getSelection()?.focusNode as any); if (focusNode) { const rects = iframe?.contentWindow?.getSelection()?.getRangeAt(0).getClientRects(); diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index f774af74f..72ab51784 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -21,7 +21,7 @@ ul { list-style: none; - padding-left: 20px; + padding-left: $TREE_BULLET_WIDTH; margin-bottom: 1px; // otherwise vertical scrollbars may pop up for no apparent reason.... > .contentFittingDocumentView { width: unset; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a90edc2c9..344a6c103 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -189,6 +189,7 @@ export class CollectionTreeView extends CollectionSubView this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick); whenActiveChanged = (isActive: boolean) => { this.props.whenActiveChanged(this._isChildActive = isActive); }; active = (outsideReaction: boolean | undefined) => this.props.active(outsideReaction) || this._isChildActive; + panelWidth = () => this.props.PanelWidth() - 20; // bcz: 20 is the 10 + 10 for the left and right padding. @computed get treeChildren() { TraceMobx(); return this.props.childDocuments || this.childDocs; @@ -200,7 +201,7 @@ export class CollectionTreeView extends CollectionSubView boolean) => this.props.moveDocument?.(d, target, addDoc) || false; return TreeView.GetChildElements(this.treeChildren, this, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.styleProvider, this.props.ScreenToLocalTransform, - this.outerXf, this.active, this.props.PanelWidth, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), + this.outerXf, this.active, this.panelWidth, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), BoolCast(this.doc.treeViewPreventOpen), [], this.props.onCheckedClick, this.onChildClick, this.props.treeViewSkipFields, true, this.whenActiveChanged, this.props.dontRegisterView || Cast(this.props.Document.dontRegisterChildViews, "boolean", null)); } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index a4ab201bc..0d03936dc 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -117,14 +117,14 @@ export class TabDocView extends React.Component { // select the tab document when the tab is directly clicked and activate the tab whenver the tab document is selected titleEle.onpointerdown = action((e: any) => { if (e.target.className !== "lm_close_tab") { - if (this.view) SelectionManager.SelectDoc(this.view, false); + if (this.view) SelectionManager.SelectView(this.view, false); else this._activated = true; if (Date.now() - titleEle.lastClick < 1000) titleEle.select(); titleEle.lastClick = Date.now(); (document.activeElement !== titleEle) && titleEle.focus(); } }); - tab._disposers.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments().some(v => v.topMost && v.props.Document === doc), + tab._disposers.selectionDisposer = reaction(() => SelectionManager.Views().some(v => v.topMost && v.props.Document === doc), action((selected) => { if (selected) this._activated = true; const toggle = tab.element[0].children[1].children[0] as HTMLInputElement; @@ -222,7 +222,7 @@ export class TabDocView extends React.Component { } componentDidMount() { - const selected = () => SelectionManager.SelectedDocuments().some(v => v.props.Document === this._document); + const selected = () => SelectionManager.Views().some(v => v.props.Document === this._document); new _global.ResizeObserver(action((entries: any) => { for (const entry of entries) { this._panelWidth = entry.contentRect.width; diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index 8468e27df..7a654c7cf 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -37,7 +37,7 @@ } .bullet { position: relative; - width: 20px; + width: $TREE_BULLET_WIDTH; color: $intermediate-color; margin-top: 3px; transform: scale(1.3, 1.3); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 31a1a2b99..f51c745bb 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -1,6 +1,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; +import { TREE_BULLET_WIDTH } from '../globalCssVariables.scss'; import { DataSym, Doc, DocListCast, DocListCastOrNull, Field, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; @@ -64,6 +65,8 @@ export interface TreeViewProps { whenActiveChanged: (isActive: boolean) => void; } +let treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace("px", "")); } + @observer /** * Renders a treeView of a collection of documents @@ -83,6 +86,7 @@ export class TreeView extends React.Component { private _uniqueId = Utils.GenerateGuid(); private _editMaxWidth: number | string = 0; + @observable _dref: DocumentView | undefined | null; @computed get doc() { TraceMobx(); return this.props.document; } get noviceMode() { return BoolCast(Doc.UserDoc().noviceMode, false); } @@ -284,9 +288,9 @@ export class TreeView extends React.Component { docWidth = () => { const layoutDoc = this.layoutDoc; const aspect = Doc.NativeAspect(layoutDoc); - if (layoutDoc._fitWidth) return Math.min(this.props.panelWidth() - 20, layoutDoc[WidthSym]()); - if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.panelWidth() - 20)); - return Doc.NativeWidth(layoutDoc) ? Math.min(layoutDoc[WidthSym](), this.props.panelWidth() - 20) : Math.min(this.layoutDoc[WidthSym](), this.props.panelWidth() - 20); + if (layoutDoc._fitWidth) return Math.min(this.props.panelWidth() - treeBulletWidth(), layoutDoc[WidthSym]()); + if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT * aspect, this.props.panelWidth() - treeBulletWidth())); + return Math.min(this.props.panelWidth() - treeBulletWidth(), Doc.NativeWidth(layoutDoc) ? layoutDoc[WidthSym]() : this.layoutDoc[WidthSym]()); } docHeight = () => { const layoutDoc = this.layoutDoc; @@ -354,9 +358,9 @@ export class TreeView extends React.Component { return rows; } - rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.props.panelWidth() - 20); + rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.props.panelWidth() - treeBulletWidth()); rtfHeight = () => this.rtfWidth() <= this.layoutDoc?.[WidthSym]() ? Math.min(this.layoutDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; - rtfOutlineHeight = () => Math.max(this.layoutDoc?.[HeightSym](), 20); + rtfOutlineHeight = () => Math.max(this.layoutDoc?.[HeightSym](), treeBulletWidth()); expandPanelHeight = () => { if (this.layoutDoc._fitWidth) return this.docHeight(); const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym](); @@ -486,7 +490,7 @@ export class TreeView extends React.Component { showContextMenu = (e: React.MouseEvent) => simulateMouseClick(this._docRef.current?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : [{ script: ScriptField.MakeFunction(`openOnRight(self)`)!, label: "Open" }, { script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]; - truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, 0); + truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, this.props.panelWidth()); onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); onChildDoubleClick = () => (!this.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); @@ -553,8 +557,10 @@ export class TreeView extends React.Component { moveDocument={this.move} removeDocument={this.props.removeDoc} ScreenToLocalTransform={this.getTransform} + NativeHeight={returnZero} + NativeWidth={returnZero} PanelWidth={this.truncateTitleWidth} - PanelHeight={returnZero} + PanelHeight={() => 18} contextMenuItems={this.contextMenuItems} renderDepth={1} focus={returnTrue} @@ -746,7 +752,7 @@ export class TreeView extends React.Component { const docs = TreeView.sortDocs(childDocs, StrCast(containingCollection?.[key + "-sortCriteria"])); - const rowWidth = () => panelWidth() - 20; + const rowWidth = () => panelWidth() - treeBulletWidth(); return docs.filter(child => child instanceof Doc).map((child, i) => { const pair = Doc.GetLayoutDataDocPair(containingCollection, dataDoc, child); if (!pair.layout || pair.data instanceof Promise) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1add65c10..0fb1c0f9c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -208,7 +208,7 @@ export class CollectionFreeFormView extends CollectionSubView { SelectionManager.DeselectAll(); - docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)).map(dv => dv && SelectionManager.SelectDoc(dv, true)); + docs.map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)).map(dv => dv && SelectionManager.SelectView(dv, true)); } public isCurrent(doc: Doc) { return (Math.abs(NumCast(doc.displayTimecode, -1) - NumCast(this.Document._currentTimecode, -1)) < 1.5 || NumCast(doc.displayTimecode, -1) === -1); } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 47ffc48fb..d20d1abfc 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -152,7 +152,7 @@ export class MarqueeView extends React.Component SelectionManager.SelectDoc(DocumentManager.Instance.getDocumentView(slide)!, false)); e.stopPropagation(); - } else if (!e.ctrlKey && !e.metaKey && SelectionManager.SelectedDocuments().length < 2) { + } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) { FormattedTextBox.SelectOnLoadChar = FormattedTextBox.DefaultLayout && !this.props.childLayoutString ? e.key : ""; FormattedTextBox.LiveTextUndo = UndoManager.StartBatch("live text batch"); this.props.addLiveTextDocument(CurrentUserUtils.GetNewTextDoc("-typed text-", x, y, 200, 100, this.props.xMargin === 0)); diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss index b2ea87c06..ccc9306c4 100644 --- a/src/client/views/globalCssVariables.scss +++ b/src/client/views/globalCssVariables.scss @@ -39,6 +39,7 @@ $MINIMIZED_ICON_SIZE:25; $MAX_ROW_HEIGHT: 44px; $DFLT_IMAGE_NATIVE_DIM: 900px; $MENU_PANEL_WIDTH: 60px; +$TREE_BULLET_WIDTH: 20px; :export { contextMenuZindex: $contextMenu-zindex; @@ -51,4 +52,5 @@ $MENU_PANEL_WIDTH: 60px; SEARCH_PANEL_HEIGHT: $searchpanel-height; DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM; MENU_PANEL_WIDTH: $MENU_PANEL_WIDTH; + TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH; } \ No newline at end of file diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/globalCssVariables.scss.d.ts index c56b75d5e..11e62e1eb 100644 --- a/src/client/views/globalCssVariables.scss.d.ts +++ b/src/client/views/globalCssVariables.scss.d.ts @@ -10,6 +10,7 @@ interface IGlobalScss { SEARCH_PANEL_HEIGHT: string; DFLT_IMAGE_NATIVE_DIM: string; MENU_PANEL_WIDTH: string; + TREE_BULLET_WIDTH: string; } declare const globalCssVariables: IGlobalScss; diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 4b3c328b0..67d25e525 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -135,7 +135,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent SelectionManager.SelectedDocuments(), + this._disposers.reaction = reaction(() => SelectionManager.Views(), selected => { const sel = selected.length ? selected[0].props.Document : undefined; let link; diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx index 52236a648..d5b6a269e 100644 --- a/src/client/views/nodes/ColorBox.tsx +++ b/src/client/views/nodes/ColorBox.tsx @@ -31,7 +31,7 @@ export class ColorBox extends ViewBoxBaseComponent { const targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory : view.props.Document.layout instanceof Doc ? view.props.Document.layout : @@ -54,7 +54,7 @@ export class ColorBox extends ViewBoxBaseComponent e.button === 0 && !e.ctrlKey && e.stopPropagation()} onClick={e => { (e.nativeEvent as any).stuff = true; e.stopPropagation(); }} style={{ width: `${100}%`, height: `${100}%` }} > @@ -67,7 +67,7 @@ export class ColorBox extends ViewBoxBaseComponent {ActiveInkWidth() ?? 2}
) => { SetActiveInkWidth(e.target.value); - SelectionManager.SelectedDocuments().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(e.target.value)); + SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(e.target.value)); }} /> {/*
{ActiveInkBezierApprox() ?? 2}
) => { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3c140a22a..56982bd89 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -409,7 +409,7 @@ export class DocumentViewInternal extends DocComponent { @@ -616,7 +616,7 @@ export class DocumentViewInternal extends DocComponent SelectionManager.SelectedDocuments().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" }); - zorderItems.push({ description: "Send to Back", event: () => SelectionManager.SelectedDocuments().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" }); + zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" }); + zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" }); zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" }); !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" }); @@ -733,7 +733,7 @@ export class DocumentViewInternal extends DocComponent SelectionManager.SelectDoc(this.props.DocumentView, false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. + !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView, false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. }); } @@ -983,7 +983,7 @@ export class DocumentView extends React.Component { topDoc.x = fpt[0]; topDoc.y = fpt[1]; } - setTimeout(() => SelectionManager.SelectDoc(DocumentManager.Instance.getDocumentView(topDoc, container)!, false), 0); + setTimeout(() => SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, container)!, false), 0); } } @@ -1061,7 +1061,7 @@ export class DocumentView extends React.Component { }); isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction); - select = (ctrlPressed: boolean) => SelectionManager.SelectDoc(this, ctrlPressed); + select = (ctrlPressed: boolean) => SelectionManager.SelectView(this, ctrlPressed); NativeWidth = () => this.nativeWidth; NativeHeight = () => this.nativeHeight; PanelWidth = () => this.panelWidth; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index da74edbe3..42462000b 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -160,7 +160,7 @@ export class PresBox extends ViewBoxBaseComponent this.props.Document.presentationFieldKey = this.fieldKey; // provide info to the presElement script so that it can look up rendering information about the presBox } @computed get selectedDocumentView() { - if (SelectionManager.SelectedDocuments().length) return SelectionManager.SelectedDocuments()[0]; + if (SelectionManager.Views().length) return SelectionManager.Views()[0]; if (this._selectedArray.size) return DocumentManager.Instance.getDocumentView(this.rootDoc); } @computed get isPres(): boolean { @@ -195,7 +195,7 @@ export class PresBox extends ViewBoxBaseComponent this.turnOffEdit(true); DocListCastAsync((Doc.UserDoc().myPresentations as Doc).data).then(pres => !pres?.includes(this.rootDoc) && Doc.AddDocToList(Doc.UserDoc().myPresentations as Doc, "data", this.rootDoc)); - this._disposers.selection = reaction(() => SelectionManager.SelectedDocuments(), + this._disposers.selection = reaction(() => SelectionManager.Views(), views => views.some(view => view.props.Document === this.rootDoc) && this.updateCurrentPresentation()); } @@ -404,7 +404,7 @@ export class PresBox extends ViewBoxBaseComponent const self = this; const resetSelection = action(() => { const presDocView = DocumentManager.Instance.getDocumentView(self.rootDoc); - if (presDocView) SelectionManager.SelectDoc(presDocView, false); + if (presDocView) SelectionManager.SelectView(presDocView, false); self.rootDoc.presStatus = presStatus; self._selectedArray.clear(); selViewCache.forEach(doc => self._selectedArray.set(doc, undefined)); @@ -761,7 +761,7 @@ export class PresBox extends ViewBoxBaseComponent @action selectPres = () => { const presDocView = DocumentManager.Instance.getDocumentView(this.rootDoc); - presDocView && SelectionManager.SelectDoc(presDocView, false); + presDocView && SelectionManager.SelectView(presDocView, false); } //Regular click diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index cf9b03308..07439825f 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -144,7 +144,7 @@ export class RichTextMenu extends AntimodeMenu { } componentDidMount() { - this._reaction = reaction(() => SelectionManager.SelectedDocuments(), + this._reaction = reaction(() => SelectionManager.Views(), () => this._delayHide && !(this._delayHide = false) && this.fadeOut(true)); } componentWillUnmount() { @@ -836,7 +836,7 @@ export class RichTextMenu extends AntimodeMenu { if (linkDoc instanceof Doc) { const anchor1 = await Cast(linkDoc.anchor1, Doc); const anchor2 = await Cast(linkDoc.anchor2, Doc); - const currentDoc = SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0].props.Document; + const currentDoc = SelectionManager.Views().length && SelectionManager.Views()[0].props.Document; if (currentDoc && anchor1 && anchor2) { if (Doc.AreProtosEqual(currentDoc, anchor1)) { return StrCast(anchor2.title); @@ -987,11 +987,11 @@ export class RichTextMenu extends AntimodeMenu {
, {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size", action((val: string) => { this.activeFontSize = val; - SelectionManager.SelectedDocuments().map(dv => dv.props.Document._fontSize = val); + SelectionManager.Views().map(dv => dv.props.Document._fontSize = val); })), this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family", action((val: string) => { this.activeFontFamily = val; - SelectionManager.SelectedDocuments().map(dv => dv.props.Document._fontFamily = val); + SelectionManager.Views().map(dv => dv.props.Document._fontFamily = val); })),
, this.createNodesDropdown(this.activeListType, this.listTypeOptions, "list type", () => ({})), diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index d6d500702..02f7ada96 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -150,7 +150,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent this._savedAnnotations.setValue(k, [])); PDFMenu.Instance.fadeOut(true); } - (SelectionManager.SelectedDocuments().length === 1) && this.setupPdfJsViewer(); + (SelectionManager.Views().length === 1) && this.setupPdfJsViewer(); }, { fireImmediately: true }); this._disposers.scrollY = reaction( diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index d5f852c4d..e1ab1d3d3 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1329,7 +1329,7 @@ Scripting.addGlobal(function activePresentationItem() { return curPres && DocListCast(curPres[Doc.LayoutFieldKey(curPres)])[NumCast(curPres._itemIndex)]; }); Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) { - const docs = SelectionManager.SelectedDocuments().map(dv => dv.props.Document). + const docs = SelectionManager.Views().map(dv => dv.props.Document). filter(d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.DOCHOLDER && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null))); return docs.length ? new List(docs) : prevValue; -- cgit v1.2.3-70-g09d2 From 3484b7d92dfedf6319a0047f16bb0ce9cd59a625 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 16 Dec 2020 16:53:05 -0500 Subject: cleaned up some link following code. fixed problem following links from LinkAnchorBox's --- src/client/util/DocumentManager.ts | 36 +---------- src/client/util/LinkManager.ts | 73 +++++++++++++++++++++- src/client/views/MainView.tsx | 5 +- src/client/views/StyleProvider.tsx | 1 - src/client/views/collections/CollectionMapView.tsx | 12 ++-- src/client/views/linking/LinkMenuItem.tsx | 46 ++------------ src/client/views/nodes/DocumentView.tsx | 44 +++---------- src/client/views/nodes/LinkAnchorBox.tsx | 30 ++++----- src/client/views/nodes/LinkDocPreview.tsx | 18 +++--- .../views/nodes/formattedText/FormattedTextBox.tsx | 5 +- .../formattedText/FormattedTextBoxComment.tsx | 2 +- src/client/views/pdf/Annotation.tsx | 12 ++-- 12 files changed, 123 insertions(+), 161 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 1c81cf26c..1609e0af7 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,14 +1,12 @@ import { action, observable } from 'mobx'; import { Doc, DocListCast, DocListCastAsync, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; -import { Cast, NumCast, StrCast } from '../../fields/Types'; +import { Cast, NumCast } from '../../fields/Types'; import { returnFalse } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; import { CollectionView } from '../views/collections/CollectionView'; import { DocumentView } from '../views/nodes/DocumentView'; -import { FormattedTextBoxComment } from '../views/nodes/formattedText/FormattedTextBoxComment'; -import { LinkDocPreview } from '../views/nodes/LinkDocPreview'; import { LinkManager } from './LinkManager'; import { Scripting } from './Scripting'; @@ -223,37 +221,5 @@ export class DocumentManager { } } - public async FollowLink(link: Opt, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) { - LinkDocPreview.TargetDoc = undefined; - FormattedTextBoxComment.linkDoc = undefined; - const linkDocs = link ? [link] : DocListCast(doc.links); - const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor1 - const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor2 - const fwdLinkWithoutTargetView = firstDocs.find(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0); - const backLinkWithoutTargetView = secondDocs.find(d => DocumentManager.Instance.getDocumentViews(d.anchor1 as Doc).length === 0); - const linkWithoutTargetDoc = traverseBacklink === undefined ? fwdLinkWithoutTargetView || backLinkWithoutTargetView : traverseBacklink ? backLinkWithoutTargetView : fwdLinkWithoutTargetView; - const linkDocList = linkWithoutTargetDoc ? [linkWithoutTargetDoc] : (traverseBacklink === undefined ? firstDocs.concat(secondDocs) : traverseBacklink ? secondDocs : firstDocs); - const followLinks = linkDocList.length ? (doc.isPushpin ? linkDocList : [linkDocList[0]]) : []; - followLinks.forEach(async linkDoc => { - if (linkDoc) { - const target = (doc === linkDoc.anchor1 ? linkDoc.anchor2 : doc === linkDoc.anchor2 ? linkDoc.anchor1 : - (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc) ? linkDoc.anchor2 : linkDoc.anchor1)) as Doc; - const targetTimecode = (doc === linkDoc.anchor1 ? Cast(linkDoc.anchor2_timecode, "number") : - doc === linkDoc.anchor2 ? Cast(linkDoc.anchor1_timecode, "number") : - (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc) ? Cast(linkDoc.anchor2_timecode, "number") : Cast(linkDoc.anchor1_timecode, "number"))); - if (target) { - const containerDoc = (await Cast(target.annotationOn, Doc)) || target; - containerDoc._currentTimecode = targetTimecode; - const targetContext = await target?.context as Doc; - const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined; - DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, doc, finished); - } else { - finished?.(); - } - } else { - finished?.(); - } - }); - } } Scripting.addGlobal(function DocFocus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, true)); }); \ No newline at end of file diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 38e81cf99..accf53676 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -1,7 +1,12 @@ +import { computedFn } from "mobx-utils"; import { Doc, DocListCast, Opt } from "../../fields/Doc"; -import { Cast, StrCast } from "../../fields/Types"; +import { BoolCast, Cast, StrCast } from "../../fields/Types"; +import { DocFocusFunc, DocumentViewSharedProps } from "../views/nodes/DocumentView"; +import { FormattedTextBoxComment } from "../views/nodes/formattedText/FormattedTextBoxComment"; +import { LinkDocPreview } from "../views/nodes/LinkDocPreview"; +import { CreateViewFunc, DocumentManager } from "./DocumentManager"; import { SharingManager } from "./SharingManager"; -import { computedFn } from "mobx-utils"; +import { UndoManager } from "./UndoManager"; /* * link doc: @@ -89,4 +94,68 @@ export class LinkManager { if (Doc.AreProtosEqual(anchor, a2.annotationOn as Doc)) return a1; if (Doc.AreProtosEqual(anchor, linkDoc)) return linkDoc; } + + + // follows a link - if the target is on screen, it highlights/pans to it. + // if the target isn't onscreen, then it will open up the target in a tab, on the right, or in place + // depending on the followLinkLocation property of the source (or the link itself as a fallback); + public static FollowLink = async (linkDoc: Opt, sourceDoc: Doc, docViewProps: DocumentViewSharedProps, altKey: boolean) => { + const batch = UndoManager.StartBatch("follow link click"); + // open up target if it's not already in view ... + const createViewFunc = (doc: Doc, followLoc: string, finished: Opt<() => void>) => { + const targetFocusAfterDocFocus = () => { + const where = StrCast(sourceDoc.followLinkLocation) || followLoc; + const hackToCallFinishAfterFocus = () => { + finished && setTimeout(finished, 0); // finished() needs to be called right after hackToCallFinishAfterFocus(), but there's no callback for that so we use the hacky timeout. + return false; // we must return false here so that the zoom to the document is not reversed. If it weren't for needing to call finished(), we wouldn't need this function at all since not having it is equivalent to returning false + }; + const addTab = docViewProps.addDocTab(doc, where); + addTab && setTimeout(() => { + const targDocView = DocumentManager.Instance.getFirstDocumentView(doc); + targDocView?.props.focus(doc, BoolCast(sourceDoc.followLinkZoom, false), undefined, hackToCallFinishAfterFocus); + }); // add the target and focus on it. + return where !== "inPlace" || addTab; // return true to reset the initial focus&zoom (return false for 'inPlace' since resetting the initial focus&zoom will negate the zoom into the target) + }; + if (!sourceDoc.followLinkZoom) { + targetFocusAfterDocFocus(); + } else { + // first focus & zoom onto this (the clicked document). Then execute the function to focus on the target + docViewProps.focus(sourceDoc, BoolCast(sourceDoc.followLinkZoom, true), 1, targetFocusAfterDocFocus); + } + }; + await LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined); + } + public static async traverseLink(link: Opt, doc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) { + LinkDocPreview.TargetDoc = undefined; + FormattedTextBoxComment.linkDoc = undefined; + const linkDocs = link ? [link] : DocListCast(doc.links); + const firstDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor1 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor1 + const secondDocs = linkDocs.filter(linkDoc => Doc.AreProtosEqual(linkDoc.anchor2 as Doc, doc) || Doc.AreProtosEqual((linkDoc.anchor2 as Doc).annotationOn as Doc, doc)); // link docs where 'doc' is anchor2 + const fwdLinkWithoutTargetView = firstDocs.find(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0); + const backLinkWithoutTargetView = secondDocs.find(d => DocumentManager.Instance.getDocumentViews(d.anchor1 as Doc).length === 0); + const linkWithoutTargetDoc = traverseBacklink === undefined ? fwdLinkWithoutTargetView || backLinkWithoutTargetView : traverseBacklink ? backLinkWithoutTargetView : fwdLinkWithoutTargetView; + const linkDocList = linkWithoutTargetDoc ? [linkWithoutTargetDoc] : (traverseBacklink === undefined ? firstDocs.concat(secondDocs) : traverseBacklink ? secondDocs : firstDocs); + const followLinks = linkDocList.length ? (doc.isPushpin ? linkDocList : [linkDocList[0]]) : []; + followLinks.forEach(async linkDoc => { + if (linkDoc) { + const target = (doc === linkDoc.anchor1 ? linkDoc.anchor2 : doc === linkDoc.anchor2 ? linkDoc.anchor1 : + (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc) ? linkDoc.anchor2 : linkDoc.anchor1)) as Doc; + const targetTimecode = (doc === linkDoc.anchor1 ? Cast(linkDoc.anchor2_timecode, "number") : + doc === linkDoc.anchor2 ? Cast(linkDoc.anchor1_timecode, "number") : + (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) || Doc.AreProtosEqual((linkDoc.anchor1 as Doc).annotationOn as Doc, doc) ? Cast(linkDoc.anchor2_timecode, "number") : Cast(linkDoc.anchor1_timecode, "number"))); + if (target) { + const containerDoc = (await Cast(target.annotationOn, Doc)) || target; + containerDoc._currentTimecode = targetTimecode; + const targetContext = await target?.context as Doc; + const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined; + DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, doc, finished); + } else { + finished?.(); + } + } else { + finished?.(); + } + }); + } + } \ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 23c65fa53..0390bdf52 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -578,9 +578,8 @@ export class MainView extends React.Component { {LinkDescriptionPopup.descriptionPopup ? : null} {DocumentLinksButton.EditLink ? : (null)} - {LinkDocPreview.LinkInfo ? : (null)} + {LinkDocPreview.LinkInfo ? : (null)} {this.mainContent} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 83192164f..dd406abed 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -71,7 +71,6 @@ export function DefaultStyleProvider(doc: Opt, props: Opt; @@ -88,7 +88,7 @@ export class CollectionMapView extends CollectionSubView void) => { + await LinkManager.traverseLink(undefined, layout, (doc: Doc, where: string, finished?: () => void) => { this.props.addDocTab(doc, where); finished?.(); }, false, this.props.ContainingCollectionDoc, batch.end, undefined); diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 8e0004c87..50cb064b9 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -13,9 +13,8 @@ import { DragManager } from '../../util/DragManager'; import { Hypothesis } from '../../util/HypothesisUtils'; import { LinkManager } from '../../util/LinkManager'; import { undoBatch } from '../../util/UndoManager'; -import { ContextMenu } from '../ContextMenu'; import { DocumentLinksButton } from '../nodes/DocumentLinksButton'; -import { DocumentView } from '../nodes/DocumentView'; +import { DocumentView, DocumentViewSharedProps } from '../nodes/DocumentView'; import { LinkDocPreview } from '../nodes/LinkDocPreview'; import './LinkMenuItem.scss'; import React = require("react"); @@ -28,7 +27,7 @@ interface LinkMenuItemProps { sourceDoc: Doc; destinationDoc: Doc; showEditor: (linkDoc: Doc) => void; - addDocTab: (document: Doc, where: string) => boolean; + docprops: DocumentViewSharedProps, menuRef: React.Ref; } @@ -110,7 +109,7 @@ export class LinkMenuItem extends React.Component { onLinkButtonUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); - DocumentView.followLinkClick(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false); + LinkManager.FollowLink(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false); e.stopPropagation(); } @@ -126,41 +125,6 @@ export class LinkMenuItem extends React.Component { e.stopPropagation(); } - @action - onContextMenu = (e: React.MouseEvent) => { - DocumentLinksButton.EditLink = undefined; - LinkDocPreview.LinkInfo = undefined; - e.preventDefault(); - ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => LinkMenuItem.followDefault(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc, this.props.addDocTab), icon: "arrow-right" }); - ContextMenu.Instance.displayMenu(e.clientX, e.clientY); - } - - - @action - public static followDefault(linkDoc: Doc, sourceDoc: Doc, destinationDoc: Doc, addDocTab: (doc: Doc, where: string) => void) { - DocumentLinksButton.EditLink = undefined; - LinkDocPreview.LinkInfo = undefined; - - if (linkDoc.followLinkLocation === "openExternal" && destinationDoc.type === DocumentType.WEB) { - window.open(`${StrCast(linkDoc.annotationUri)}#annotations:${StrCast(linkDoc.annotationId)}`, '_blank'); - } - - if (linkDoc.followLinkLocation && linkDoc.followLinkLocation !== "default") { - const annotationOn = destinationDoc.annotationOn as Doc; - addDocTab(annotationOn instanceof Doc ? annotationOn : destinationDoc, StrCast(linkDoc.followLinkLocation)); - if (annotationOn) { - setTimeout(() => { - const dv = DocumentManager.Instance.getFirstDocumentView(destinationDoc); - dv?.props.focus(destinationDoc, false); - }); - } - } else { - DocumentManager.Instance.FollowLink(linkDoc, sourceDoc, addDocTab, false); - } - - linkDoc.linksToAnnotation && Hypothesis.scrollToAnnotation(StrCast(linkDoc.annotationId), destinationDoc); - } - @undoBatch @action deleteLink = (): void => { @@ -215,7 +179,7 @@ export class LinkMenuItem extends React.Component {
LinkDocPreview.LinkInfo = undefined)} onPointerEnter={action(e => this.props.linkDoc && (LinkDocPreview.LinkInfo = { - addDocTab: this.props.addDocTab, + docprops: this.props.docprops, linkSrc: this.props.sourceDoc, linkDoc: this.props.linkDoc, Location: [e.clientX, e.clientY + 20] @@ -260,8 +224,6 @@ export class LinkMenuItem extends React.Component {
- {/*
-
*/}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 56982bd89..15ba62e23 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -425,7 +425,7 @@ export class DocumentViewInternal extends DocComponent 0)) { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTemplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part stopPropagate = false; // don't stop propagation for field templates -- want the selection to propagate up to the root document of the template @@ -785,7 +785,12 @@ export class DocumentViewInternal extends DocComponent (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && (doc.hidden = true), true) anchorPanelWidth = () => this.props.PanelWidth() || 1; anchorPanelHeight = () => this.props.PanelHeight() || 1; - anchorStyleProvider = (doc: Opt, props: Opt, property: string): any => this.props.styleProvider?.(doc, props, property + ":anchor"); + anchorStyleProvider = (doc: Opt, props: Opt, property: string): any => { + switch (property.split(":")[0]) { + case StyleProp.LinkSource: return this.props.Document; // pass the LinkSource to the LinkAnchorBox + } + return this.props.styleProvider?.(doc, props, property + ":anchor"); + } @computed get directLinks() { TraceMobx(); return LinkManager.Instance.getAllDirectLinks(this.rootDoc); } @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); } @@ -930,40 +935,6 @@ export class DocumentView extends React.Component { toggleNativeDimensions = () => this.docView?.toggleNativeDimensions(); contentsActive = () => this.docView?.contentsActive(); - // follows a link - if the target is on screen, it highlights/pans to it. - // if the target isn't onscreen, then it will open up the target in a tab, on the right, or in place - // depending on the followLinkLocation property of the source (or the link itself as a fallback); - public static followLinkClick = async (linkDoc: Opt, sourceDoc: Doc, docView: { - focus: DocFocusFunc, - addDocTab: (doc: Doc, where: string) => boolean, - ContainingCollectionDoc?: Doc - }, altKey: boolean) => { - const batch = UndoManager.StartBatch("follow link click"); - // open up target if it's not already in view ... - const createViewFunc = (doc: Doc, followLoc: string, finished: Opt<() => void>) => { - const targetFocusAfterDocFocus = () => { - const where = StrCast(sourceDoc.followLinkLocation) || followLoc; - const hackToCallFinishAfterFocus = () => { - finished && setTimeout(finished, 0); // finished() needs to be called right after hackToCallFinishAfterFocus(), but there's no callback for that so we use the hacky timeout. - return false; // we must return false here so that the zoom to the document is not reversed. If it weren't for needing to call finished(), we wouldn't need this function at all since not having it is equivalent to returning false - }; - const addTab = docView.addDocTab(doc, where); - addTab && setTimeout(() => { - const targDocView = DocumentManager.Instance.getFirstDocumentView(doc); - targDocView?.props.focus(doc, BoolCast(sourceDoc.followLinkZoom, false), undefined, hackToCallFinishAfterFocus); - }); // add the target and focus on it. - return where !== "inPlace" || addTab; // return true to reset the initial focus&zoom (return false for 'inPlace' since resetting the initial focus&zoom will negate the zoom into the target) - }; - if (!sourceDoc.followLinkZoom) { - targetFocusAfterDocFocus(); - } else { - // first focus & zoom onto this (the clicked document). Then execute the function to focus on the target - docView.focus(sourceDoc, BoolCast(sourceDoc.followLinkZoom, true), 1, targetFocusAfterDocFocus); - } - }; - await DocumentManager.Instance.FollowLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docView.ContainingCollectionDoc, batch.end, altKey ? true : undefined); - } - @action public float = () => { const { Document: topDoc, ContainingCollectionView: container } = this.props; const screenXf = container?.screenToLocalTransform(); @@ -1106,7 +1077,6 @@ export class DocumentView extends React.Component { } } - Scripting.addGlobal(function toggleDetail(doc: any, layoutKey: string, otherKey: string = "layout") { const dv = DocumentManager.Instance.getDocumentView(doc); if (dv?.props.Document.layoutKey === layoutKey) dv?.switchViews(otherKey !== "layout", otherKey.replace("layout_", "")); diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index f035fba33..e347d1304 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -1,25 +1,25 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast } from "../../../fields/Doc"; +import { Doc } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; +import { Id } from "../../../fields/FieldSymbols"; import { makeInterface } from "../../../fields/Schema"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; -import { Utils, setupMoveUpEvents, emptyFunction, OmitKeys } from '../../../Utils'; -import { DocumentManager } from "../../util/DocumentManager"; +import { TraceMobx } from "../../../fields/util"; +import { emptyFunction, setupMoveUpEvents, Utils } from '../../../Utils'; import { DragManager } from "../../util/DragManager"; -import { ViewBoxBaseComponent } from "../DocComponent"; -import "./LinkAnchorBox.scss"; -import { FieldView, FieldViewProps } from "./FieldView"; -import React = require("react"); -import { ContextMenuProps } from "../ContextMenuItem"; +import { LinkManager } from "../../util/LinkManager"; +import { SelectionManager } from "../../util/SelectionManager"; import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from "../ContextMenuItem"; +import { ViewBoxBaseComponent } from "../DocComponent"; import { LinkEditor } from "../linking/LinkEditor"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { SelectionManager } from "../../util/SelectionManager"; -import { TraceMobx } from "../../../fields/util"; -import { Id } from "../../../fields/FieldSymbols"; -import { LinkDocPreview } from "./LinkDocPreview"; import { StyleProp } from "../StyleProvider"; +import { FieldView, FieldViewProps } from "./FieldView"; +import "./LinkAnchorBox.scss"; +import { LinkDocPreview } from "./LinkDocPreview"; +import React = require("react"); const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -74,7 +74,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent { - DocumentManager.Instance.FollowLink(this.rootDoc, anchorContainerDoc, (doc, where) => this.props.addDocTab(doc, where), false); + LinkManager.FollowLink(this.rootDoc, anchorContainerDoc, this.props, false); this._editing = false; }), 300 - (Date.now() - this._lastTap)); } @@ -136,7 +136,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent LinkDocPreview.LinkInfo = undefined)} onPointerEnter={action(e => LinkDocPreview.LinkInfo = { - addDocTab: this.props.addDocTab, + docprops: this.props, linkSrc: linkSource, linkDoc: this.rootDoc, Location: [e.clientX, e.clientY + 20] diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index c69fb5b33..07b2b6338 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -6,25 +6,24 @@ import { Id } from '../../../fields/FieldSymbols'; import { Cast, FieldValue, NumCast } from "../../../fields/Types"; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse } from "../../../Utils"; import { Docs } from "../../documents/Documents"; -import { DocumentManager } from "../../util/DocumentManager"; +import { LinkManager } from '../../util/LinkManager'; import { Transform } from "../../util/Transform"; import { ContextMenu } from '../ContextMenu'; import { DocumentLinksButton } from './DocumentLinksButton'; -import { DocumentView, StyleProviderFunc } from "./DocumentView"; +import { DocumentView, StyleProviderFunc, DocumentViewSharedProps } from "./DocumentView"; import React = require("react"); interface Props { linkDoc?: Doc; linkSrc?: Doc; href?: string; - styleProvider?: StyleProviderFunc; - addDocTab: (document: Doc, where: string) => boolean; + docprops: DocumentViewSharedProps; location: number[]; } @observer export class LinkDocPreview extends React.Component { static TargetDoc: Doc | undefined; - @observable public static LinkInfo: Opt<{ linkDoc?: Doc; addDocTab: (document: Doc, where: string) => boolean, linkSrc: Doc; href?: string; Location: number[] }>; + @observable public static LinkInfo: Opt<{ linkDoc?: Doc; linkSrc: Doc; href?: string; Location: number[], docprops: DocumentViewSharedProps }>; @observable _targetDoc: Opt; @observable _toolTipText = ""; _editRef = React.createRef(); @@ -42,7 +41,7 @@ export class LinkDocPreview extends React.Component { async followDefault() { DocumentLinksButton.EditLink = undefined; LinkDocPreview.LinkInfo = undefined; - this._targetDoc ? DocumentManager.Instance.FollowLink(this.props.linkDoc, this._targetDoc, (doc, where) => this.props.addDocTab(doc, where), false) : null; + this._targetDoc && LinkManager.FollowLink(this.props.linkDoc, this._targetDoc, this.props.docprops, false); } componentWillUnmount() { LinkDocPreview.TargetDoc = undefined; } @@ -75,10 +74,9 @@ export class LinkDocPreview extends React.Component { } pointerDown = (e: React.PointerEvent) => { if (this.props.linkDoc && this.props.linkSrc) { - DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.linkSrc, - (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation)); + LinkManager.FollowLink(this.props.linkDoc, this.props.linkSrc, this.props.docprops, false); } else if (this.props.href) { - this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { _fitWidth: true, title: this.props.href, _width: 200, _height: 400, useCors: true }), "add:right"); + this.props.docprops?.addDocTab(Docs.Create.WebDocument(this.props.href, { _fitWidth: true, title: this.props.href, _width: 200, _height: 400, useCors: true }), "add:right"); } } width = () => Math.min(225, NumCast(this._targetDoc?.[WidthSym](), 225)); @@ -113,7 +111,7 @@ export class LinkDocPreview extends React.Component { focus={emptyFunction} whenActiveChanged={returnFalse} bringToFront={returnFalse} - styleProvider={this.props.styleProvider} />; + styleProvider={this.props.docprops?.styleProvider} />; } render() { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 0bb483b41..2b9910dfb 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -57,7 +57,7 @@ import { FieldView, FieldViewProps } from "../FieldView"; import "./FormattedTextBox.scss"; import { FormattedTextBoxComment, formattedTextBoxCommentPlugin, findLinkMark } from './FormattedTextBoxComment'; import React = require("react"); -import { DocumentManager } from '../../../util/DocumentManager'; +import { LinkManager } from '../../../util/LinkManager'; import { CollectionStackingView } from '../../collections/CollectionStackingView'; import { CollectionViewType, CollectionViewProps } from '../../collections/CollectionView'; import { SnappingManager } from '../../../util/SnappingManager'; @@ -1331,8 +1331,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) { this.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "add" : "add:right"); } else { - DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, this.props.Document, - (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation)); + LinkManager.FollowLink(FormattedTextBoxComment.linkDoc, this.props.Document, this.props, false); } } diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index c6be25dc2..038a91aa3 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -116,7 +116,7 @@ export class FormattedTextBoxComment { textBox.props.addDocTab(linkDoc, e.ctrlKey ? "add" : "add:right"); } else { const target = LinkManager.getOppositeAnchor(linkDoc, textBox.dataDoc); - target && DocumentView.followLinkClick(linkDoc, textBox.dataDoc, textBox.props, e.altKey); + target && LinkManager.FollowLink(linkDoc, textBox.dataDoc, textBox.props, e.altKey); } } } diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 20ea7bfe4..5ef57f986 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -1,14 +1,14 @@ import React = require("react"); import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, HeightSym, WidthSym, Field, Opt } from "../../../fields/Doc"; +import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; -import { Cast, FieldValue, BoolCast, NumCast, StrCast, PromiseValue } from "../../../fields/Types"; -import { DocumentManager } from "../../util/DocumentManager"; -import { PDFMenu } from "./PDFMenu"; -import "./Annotation.scss"; +import { BoolCast, Cast, FieldValue, NumCast, PromiseValue, StrCast } from "../../../fields/Types"; +import { LinkManager } from "../../util/LinkManager"; import { undoBatch } from "../../util/UndoManager"; +import "./Annotation.scss"; +import { PDFMenu } from "./PDFMenu"; interface IAnnotationProps { anno: Doc; @@ -119,7 +119,7 @@ class RegionAnnotation extends React.Component { e.persist(); e.stopPropagation(); PromiseValue(this.props.document.group).then(annoGroup => annoGroup instanceof Doc && - DocumentManager.Instance.FollowLink(undefined, annoGroup, (doc, followLinkLocation) => this.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation), false, undefined, + LinkManager.traverseLink(undefined, annoGroup, (doc, followLinkLocation) => this.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation), false, undefined, () => this.props.select(false)) ); } -- cgit v1.2.3-70-g09d2