From 175d3fca55bd1838203d67884bb5206597e68b60 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 20 Nov 2020 19:23:02 -0500 Subject: added a preliminary Layer mechanism. changed documentDecrations to not go out of the mainDocument area. changed parentActive to work "recursively" through stacks of background documents. --- src/client/documents/Documents.ts | 4 +- src/client/views/DocComponent.tsx | 6 +- src/client/views/DocumentDecorations.tsx | 20 +++--- src/client/views/InkingStroke.tsx | 4 +- src/client/views/MainView.tsx | 73 +++++++++++++--------- src/client/views/TemplateMenu.tsx | 1 + .../views/collections/CollectionCarouselView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 1 + .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 17 ++++- src/client/views/collections/TabDocView.tsx | 57 +++++++++++++++-- .../collectionFreeForm/CollectionFreeFormView.scss | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 29 +++++---- .../collections/collectionFreeForm/MarqueeView.tsx | 12 ++-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 24 +++++-- .../views/nodes/ContentFittingDocumentView.tsx | 2 +- src/client/views/nodes/DocHolderBox.tsx | 2 +- src/client/views/nodes/DocumentContentsView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 45 ++++++++----- src/client/views/nodes/FieldView.tsx | 4 +- src/client/views/nodes/FilterBox.tsx | 1 + src/client/views/nodes/FontIconBox.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 3 +- src/client/views/nodes/KeyValuePair.tsx | 1 + src/client/views/nodes/LinkAnchorBox.tsx | 2 +- src/client/views/nodes/LinkBox.tsx | 2 +- src/client/views/nodes/PresBox.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 8 +-- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- .../views/presentationview/PresElementBox.tsx | 10 +-- src/fields/documentSchemas.ts | 2 +- 32 files changed, 228 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2d8a897a5..ae0cd8b92 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -138,7 +138,7 @@ export interface DocumentOptions { isAnnotating?: boolean; // whether we web document is annotation mode where links can't be clicked to allow annotations to be created opacity?: number; defaultBackgroundColor?: string; - _isBackground?: boolean; + _layers?: List; _raiseWhenDragged?: boolean; // whether a document is brought to front when dragged. isLinkButton?: boolean; _columnWidth?: number; @@ -712,7 +712,7 @@ export namespace Docs { 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 - treeViewExpandedView: "fields", removeDropProperties: new List(["_isBackground", "isLinkButton"]), ...options + treeViewExpandedView: "fields", removeDropProperties: new List(["_layers", "isLinkButton"]), ...options }, id); const linkDocProto = Doc.GetProto(doc); linkDocProto.treeViewOpen = true;// setting this in the instance creator would set it on the view document. diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index a55f4adaf..d6116fd23 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -37,6 +37,7 @@ interface ViewBoxBaseProps { DataDoc?: Doc; ContainingCollectionDoc: Opt; fieldKey: string; + layerProvider?: (doc: Doc, assign?: boolean) => boolean; isSelected: (outsideReaction?: boolean) => boolean; renderDepth: number; rootSelected: (outsideReaction?: boolean) => boolean; @@ -58,7 +59,7 @@ export function ViewBoxBaseComponent

(schemaCtor: lookupField = (field: string) => ScriptCast(this.layoutDoc.lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field, container: this.props.ContainingCollectionDoc }).result; - active = (outsideReaction?: boolean) => !this.props.Document._isBackground && (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0 || this.layoutDoc.forceActive);// && !Doc.SelectedTool(); // bcz: inking state shouldn't affect static tools + active = (outsideReaction?: boolean) => this.props.layerProvider?.(this.props.Document) !== false && (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0 || this.layoutDoc.forceActive);// && !Doc.SelectedTool(); // bcz: inking state shouldn't affect static tools protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; } return Component; @@ -70,6 +71,7 @@ export interface ViewBoxAnnotatableProps { Document: Doc; DataDoc?: Doc; fieldKey: string; + layerProvider?: (doc: Doc) => boolean; active: () => boolean; whenActiveChanged: (isActive: boolean) => void; isSelected: (outsideReaction?: boolean) => boolean; @@ -190,7 +192,7 @@ export function ViewBoxAnnotatableComponent

this.props.whenActiveChanged(this._isChildActive = isActive)); active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.props.Document._) && (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0 || BoolCast((this.layoutDoc as any).forceActive)) ? true : false) - annotationsActive = (outsideReaction?: boolean) => (Doc.GetSelectedTool() !== InkTool.None || (this.props.Document._isBackground && this.props.active()) || + annotationsActive = (outsideReaction?: boolean) => (Doc.GetSelectedTool() !== InkTool.None || (this.props.layerProvider?.(this.props.Document) === false && this.props.active()) || (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) } return Component; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 63b99cd85..8d905bcac 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -28,7 +28,7 @@ import { InkStrokeProperties } from './InkStrokeProperties'; import { KeyManager } from './GlobalKeyHandler'; @observer -export class DocumentDecorations extends React.Component<{}, { value: string }> { +export class DocumentDecorations extends React.Component<{ boundsLeft: number, boundsTop: number }, { value: string }> { static Instance: DocumentDecorations; private _resizeHdlId = ""; private _keyinput = React.createRef(); @@ -54,7 +54,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @observable public pullIcon: IconProp = "arrow-alt-circle-down"; @observable public pullColor: string = "white"; - constructor(props: Readonly<{}>) { + constructor(props: any) { super(props); DocumentDecorations.Instance = this; reaction(() => SelectionManager.SelectedDocuments().slice(), docs => this.titleBlur(false)); @@ -603,17 +603,13 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> {`${this.selectionTitle}`} ; - bounds.x = Math.max(0, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2; - bounds.y = Math.max(0, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight; + const leftBounds = this.props.boundsLeft; + const topBounds = this.props.boundsTop; + bounds.x = Math.max(leftBounds, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2; + bounds.y = Math.max(topBounds, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight; const borderRadiusDraggerWidth = 15; - bounds.r = Math.min(window.innerWidth, bounds.r + borderRadiusDraggerWidth + this._resizeBorderWidth / 2) - this._resizeBorderWidth / 2 - borderRadiusDraggerWidth; - bounds.b = Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth / 2 + this._linkBoxHeight) - this._resizeBorderWidth / 2 - this._linkBoxHeight; - if (bounds.x > bounds.r) { - bounds.x = bounds.r - this._resizeBorderWidth; - } - if (bounds.y > bounds.b) { - bounds.y = bounds.b - (this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight); - } + bounds.r = Math.max(bounds.x, Math.max(leftBounds, Math.min(window.innerWidth, bounds.r + borderRadiusDraggerWidth + this._resizeBorderWidth / 2) - this._resizeBorderWidth / 2 - borderRadiusDraggerWidth)); + bounds.b = Math.max(bounds.y, Math.max(topBounds, Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth / 2 + this._linkBoxHeight) - this._resizeBorderWidth / 2 - this._linkBoxHeight)); const useRotation = seldoc.rootDoc.type === DocumentType.INK; return (

diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 5fd9d5fe4..8ed6fbd85 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -120,7 +120,7 @@ export class InkingStroke extends ViewBoxBaseComponent 5 ? strokeColor : "transparent", strokeWidth, (strokeWidth + 15), StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"), - "none", "none", undefined, scaleX, scaleY, "", this.props.Document._isBackground ? "none" : "visiblepainted", false, true); + "none", "none", undefined, scaleX, scaleY, "", this.props.layerProvider?.(this.props.Document) === false ? "none" : "visiblepainted", false, true); //points for adding const apoints = InteractionUtils.CreatePoints(data, left, top, strokeColor, strokeWidth, strokeWidth, @@ -191,7 +191,7 @@ export class InkingStroke extends ViewBoxBaseComponent this._panelHeight; getContentsHeight = () => this._panelHeight - Number(SEARCH_PANEL_HEIGHT.replace("px", "")); - defaultBackgroundColors = (doc: Opt, renderDepth: number) => { - if (this.darkScheme) { - switch (doc?.type) { - case DocumentType.PRESELEMENT: return "dimgrey"; - case DocumentType.PRES: return "#3e3e3e"; - case DocumentType.FONTICON: return "black"; - case DocumentType.RTF || DocumentType.LABEL || DocumentType.BUTTON: return "#2d2d2d"; - case DocumentType.LINK: - case DocumentType.COL: - return Doc.IsSystem(doc) ? "rgb(62,62,62)" : StrCast(renderDepth > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground); - //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)"; - default: return "black"; - } - } else { - switch (doc?.type) { - case DocumentType.PRESELEMENT: return ""; - case DocumentType.FONTICON: return "black"; - case DocumentType.RTF: return "#f1efeb"; - case DocumentType.BUTTON: - case DocumentType.LABEL: return "lightgray"; - case DocumentType.LINK: - case DocumentType.COL: - return Doc.IsSystem(doc) ? "lightgrey" : StrCast(renderDepth > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground); - //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "lightgray"; - default: return "white"; + defaultBackgroundColors = (doc: Opt, renderDepth: number, layerProvider?: (doc: Doc, assign?: boolean) => boolean) => { + let docColor = StrCast(doc?._backgroundColor, StrCast(doc?.backgroundColor)); + if (!docColor) { + if (this.darkScheme) { + switch (doc?.type) { + case DocumentType.PRESELEMENT: docColor = "dimgrey"; break; + case DocumentType.PRES: docColor = "#3e3e3e"; break; + case DocumentType.FONTICON: docColor = "black"; break; + case DocumentType.RTF || DocumentType.LABEL || DocumentType.BUTTON: docColor = "#2d2d2d"; break; + case DocumentType.LINK: + case DocumentType.COL: + docColor = Doc.IsSystem(doc) ? "rgb(62,62,62)" : StrCast(renderDepth > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground); + break; + //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)"; + default: docColor = "black"; break; + } + } else { + switch (doc?.type) { + case DocumentType.PRESELEMENT: docColor = ""; break; + case DocumentType.FONTICON: docColor = "black"; break; + case DocumentType.RTF: docColor = "#f1efeb"; break; + case DocumentType.BUTTON: + case DocumentType.LABEL: docColor = "lightgray"; break; + case DocumentType.LINK: + case DocumentType.COL: + docColor = Doc.IsSystem(doc) ? "lightgrey" : + StrCast(renderDepth > 0 ? Doc.UserDoc().activeCollectionNestedBackground : + Doc.UserDoc().activeCollectionBackground); + break; + //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "lightgray"; + default: docColor = "white"; break; + } } } + if (!doc || layerProvider?.(doc) === false) { + return Color(docColor).fade(0.5).toString(); + } + return docColor; } @computed get mainDocView() { @@ -310,8 +323,8 @@ export class MainView extends React.Component { } flyoutWidthFunc = () => this._flyoutWidth; - sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0) - Number(SEARCH_PANEL_HEIGHT.replace("px", "")), 1); - mainContainerXf = () => this.sidebarScreenToLocal().translate(-58, 0); + sidebarScreenToLocal = () => new Transform(0, -this.topOffset, 1); + mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftOffset, 0); addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => { return where === "close" ? CollectionDockingView.CloseSplit(doc) : doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) : CollectionDockingView.AddSplit(doc, "right"); @@ -480,6 +493,7 @@ export class MainView extends React.Component { fieldKey={"data"} dropAction={"alias"} annotationsKey={""} + parentActive={returnFalse} backgroundColor={this.defaultBackgroundColors} rootSelected={returnTrue} bringToFront={emptyFunction} @@ -564,6 +578,7 @@ export class MainView extends React.Component { PanelHeight={this.getPHeight} renderDepth={0} focus={emptyFunction} + parentActive={returnFalse} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} @@ -588,6 +603,7 @@ export class MainView extends React.Component { select={returnFalse} rootSelected={returnFalse} renderDepth={0} + parentActive={returnFalse} addDocTab={returnFalse} pinToPres={returnFalse} ScreenToLocalTransform={Transform.Identity} @@ -613,7 +629,7 @@ export class MainView extends React.Component { - + {this.search} {LinkDescriptionPopup.descriptionPopup ? : null} @@ -659,6 +675,7 @@ export class MainView extends React.Component { ScreenToLocalTransform={Transform.Identity} bringToFront={returnFalse} active={returnFalse} + parentActive={returnFalse} whenActiveChanged={returnFalse} focus={returnFalse} PanelWidth={() => 500} diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 94efff4ee..68f30d58c 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -139,6 +139,7 @@ export class TemplateMenu extends React.Component { LibraryPath={emptyPath} dropAction={undefined} active={returnTrue} + parentActive={returnFalse} ContentScaling={returnOne} bringToFront={emptyFunction} focus={emptyFunction} diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index c5910b0be..8c58a5679 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -65,7 +65,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index b27f64ff0..10459a497 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -46,6 +46,7 @@ export interface SubCollectionViewProps extends CollectionViewProps { freezeChildDimensions?: boolean; // used by TimeView to coerce documents to treat their width height as their native width/height overrideDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox) ignoreFields?: string[]; // used in TreeView to ignore specified fields (see LinkBox) + parentActive: (outsideReaction: boolean) => boolean; isAnnotationOverlay?: boolean; annotationsKey: string; layoutEngine?: () => string; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index be31ca6e5..56c6978f1 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -216,7 +216,7 @@ export class CollectionTreeView extends CollectionSubView boolean; moveDocument: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; active: () => boolean; + parentActive: (outsideReaction: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; PanelWidth: () => number; PanelHeight: () => number; @@ -116,7 +118,13 @@ export class CollectionView extends Touchable (this.props.isSelected(outsideReaction) || this.props.rootSelected(outsideReaction) || this.props.Document.forceActive || this._isChildActive || this.props.renderDepth === 0) ? true : false; + active = (outsideReaction?: boolean) => (this.props.isSelected(outsideReaction) || + this.props.rootSelected(outsideReaction) || + this.props.Document.forceActive || + this._isChildActive || + this.props.renderDepth === 0) ? + true : + false whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive); @@ -152,6 +160,7 @@ export class CollectionView extends Touchable { + this.props.layerProvider?.(doc, true); Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc); doc.context = this.props.Document; }); @@ -176,6 +185,7 @@ export class CollectionView extends Touchable this.props.layerProvider?.(doc, true)); (targetDataDoc[this.props.fieldKey] as List).push(...added); targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); } @@ -382,15 +392,16 @@ export class CollectionView extends Touchable + style={{ pointerEvents: this.props.layerProvider?.(this.props.Document) === false ? "none" : undefined, boxShadow }}> {this.showIsTagged()} {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)} {this.lightbox(DocListCast(this.props.Document[this.props.fieldKey]).filter(d => Cast(d.data, ImageField, null)).map(d => diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 6079b2eb6..76efe7ec9 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -29,6 +29,7 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV import { CollectionViewType } from './CollectionView'; import "./TabDocView.scss"; import React = require("react"); +import { List } from '../../../fields/List'; const _global = (window /* browser */ || global /* node */) as any; interface TabDocViewProps { @@ -66,6 +67,27 @@ export class TabDocView extends React.Component { titleEle.size = e.currentTarget.value.length + 3; Doc.GetProto(doc).title = e.currentTarget.value; })); + if (tab.element[0].children[1].children.length === 1) { + const toggle = document.createElement("div"); + toggle.style.width = "10px"; + toggle.style.height = "calc(100% - 2px)"; + toggle.style.left = "-2px"; + toggle.style.bottom = "1px"; + toggle.style.borderTopRightRadius = "7px"; + toggle.style.position = "relative"; + toggle.style.display = "inline-block"; + toggle.style.background = "gray"; + 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.element[0].style.borderTopRightRadius = "8px"; + tab.element[0].children[1].appendChild(toggle); + tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }), + ({ layer, color }) => toggle.style.background = !layer ? color : "dimgrey", { fireImmediately: true }); + } // shifts the focus to this tab when another tab is dragged over it tab.element[0].onmouseenter = (e: MouseEvent) => { if (SnappingManager.GetIsDragging() && tab.contentItem !== tab.header.parent.getActiveContentItem()) { @@ -87,8 +109,13 @@ export class TabDocView extends React.Component { } }; tab._disposers.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments().some(v => (v.topMost || v.props.treeViewDoc) && v.props.Document === doc), - (selected) => selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && - UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), "tab switch")); + (selected) => { + const toggle = tab.element[0].children[1].children[0] as HTMLInputElement; + selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && + UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), "tab switch"); + toggle.style.fontWeight = selected ? "bold" : ""; + toggle.style.textTransform = selected ? "uppercase" : ""; + }); //attach the selection doc buttons menu to the drag handle const stack = tab.contentItem.parent; @@ -184,8 +211,8 @@ export class TabDocView extends React.Component { })).observe(this.props.glContainer._element[0]); this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged); this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged(); - this._tabReaction = reaction(() => ({ selected: selected(), color: this.tabColor, title: this.tab?.titleElement[0] }), - ({ selected, color, title }) => title && (title.style.backgroundColor = selected ? color : ""), + this._tabReaction = reaction(() => ({ selected: this.active(), title: this.tab?.titleElement[0] }), + ({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""), { fireImmediately: true }); } @@ -303,6 +330,7 @@ export class TabDocView extends React.Component { CollectionView={undefined} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} + parentActive={returnFalse} ChildLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid having to set stuff like this. noOverlay={true} // don't render overlay Docs since they won't scale active={returnTrue} @@ -353,6 +381,26 @@ export class TabDocView extends React.Component { } setView = action((view: DocumentView) => this._view = view); active = () => this._isActive; + + 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; + } + } @computed get docView() { TraceMobx(); return !this._document || this._document._viewType === CollectionViewType.Docking ? (null) : @@ -363,6 +411,7 @@ export class TabDocView extends React.Component { DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined} bringToFront={emptyFunction} rootSelected={returnTrue} + layerProvider={this.layerProvider} addDocument={undefined} removeDocument={undefined} ContentScaling={this.ContentScaling} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index a50b41198..a05c25c9b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -17,6 +17,7 @@ position: absolute; top: 0; left: 0; + pointer-events: none; } .collectionfreeformview-viewdef { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 19dc97399..77c29d6ef 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -73,6 +73,7 @@ export type collectionFreeformViewProps = { forceScaling?: boolean; // whether to force scaling of content (needed by ImageBox) viewDefDivClick?: ScriptField; childPointerEvents?: boolean; + parentActive: (outsideReaction: boolean) => boolean; scaleField?: string; noOverlay?: boolean; // used to suppress docs in the overlay (z) layer (ie, for minimap since overlay doesn't scale) }; @@ -235,7 +236,7 @@ export class CollectionFreeFormView extends CollectionSubView { - // if (this.props.Document._isBackground) return false; const [xp, yp] = this.getTransform().transformPoint(de.x, de.y); if (this.isAnnotationOverlay !== true && de.complete.linkDragData) { return this.internalLinkDrop(e, de, de.complete.linkDragData, xp, yp); @@ -390,8 +390,8 @@ export class CollectionFreeFormView extends CollectionSubView) => { - let clusterColor = this.props.backgroundColor?.(doc, this.props.renderDepth + 1); + getClusterColor = (doc: Opt, renderDepth: number, layerProvider?: (doc: Doc, assign?: boolean) => boolean) => { + let clusterColor = this.props.backgroundColor?.(doc, this.props.renderDepth + 1, layerProvider); const cluster = NumCast(doc?.cluster); if (this.Document._useClusters) { if (this._clusterSets.length <= cluster) { @@ -402,8 +402,8 @@ 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 => !s._isBackground).map(s => clusterColor = StrCast(s.backgroundColor)); - set && set.filter(s => s._isBackground).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 => Cast(s.layers, listSpec("string"), []).includes("background")).map(s => clusterColor = StrCast(s.backgroundColor)); } } return clusterColor; @@ -861,7 +861,7 @@ export class CollectionFreeFormView extends CollectionSubView { - if (sendToBack || doc._isBackground) { + if (sendToBack || Cast(doc.layers, listSpec("string"), []).includes("background")) { doc.zIndex = 0; } else if (doc.isInkMask) { doc.zIndex = 5000; @@ -976,11 +976,11 @@ export class CollectionFreeFormView extends CollectionSubView this.props.childClickScript || ScriptCast(this.Document.onChildClick); onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); backgroundHalo = () => BoolCast(this.Document._useClusters); - parentActive = (outsideReaction: boolean) => this.props.active(outsideReaction) || this.backgroundActive || this.layoutDoc._viewType === CollectionViewType.Pile ? true : false; + parentActive = (outsideReaction: boolean) => this.props.active(outsideReaction) || this.props.parentActive?.(outsideReaction) || this.backgroundActive || this.layoutDoc._viewType === CollectionViewType.Pile ? true : false; getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps { return { addDocument: this.props.addDocument, @@ -988,6 +988,7 @@ export class CollectionFreeFormView extends CollectionSubView(); const engine = this.props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine); switch (engine) { @@ -1161,6 +1160,7 @@ export class CollectionFreeFormView extends CollectionSubView !doc._isBackground && doc.z === undefined).map(doc => isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to + this.getActiveDocuments().filter(doc => !Cast(doc.layers, listSpec("string"), []).includes("background") && doc.z === undefined).map(doc => isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to !snappableDocs.length && this.getActiveDocuments().filter(doc => doc.z === undefined).map(doc => isDocInView(doc, selRect)); // if not, see if there are background docs to snap to !snappableDocs.length && this.getActiveDocuments().filter(doc => doc.z !== undefined).map(doc => isDocInView(doc, otherBounds)); // if not, then why not snap to floating docs @@ -1491,6 +1491,7 @@ export class CollectionFreeFormView extends CollectionSubView {this.layoutDoc["_backgroundGrid-show"] ? this.grid : (null)} {this.props.children()} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 796f02deb..8ed198b4a 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -357,7 +357,7 @@ export class MarqueeView extends React.Component, options: DocumentOptions, id?: string) => Doc>, _isBackground?: boolean) => { + getCollection = action((selected: Doc[], creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, layers: string[]) => { const newCollection = creator ? creator(selected, { title: "nested stack", }) : ((doc: Doc) => { Doc.GetProto(doc).data = new List(selected); Doc.GetProto(doc).title = "nested freeform"; @@ -365,8 +365,8 @@ 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; @@ -447,7 +447,7 @@ export class MarqueeView extends React.Component { - const newCollection = this.getCollection([], undefined, true); + const newCollection = this.getCollection([], undefined, ["background"]); this.props.addDocument(newCollection); MarqueeOptionsMenu.Instance.fadeOut(true); this.hideMarquee(); @@ -693,7 +693,7 @@ export class MarqueeView extends React.Component !doc._isBackground && !doc.z).map(doc => { + this.props.activeDocuments().filter(doc => this.props.layerProvider?.(doc) !== false && !doc.z).map(doc => { const layoutDoc = Doc.Layout(doc); const x = NumCast(doc.x); const y = NumCast(doc.y); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index c87239ee9..e6cb160dd 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,4 +1,4 @@ -import { computed, IReactionDisposer, observable, reaction, trace } from "mobx"; +import { computed, IReactionDisposer, observable, reaction, trace, action } from "mobx"; import { observer } from "mobx-react"; import { Doc, HeightSym, WidthSym } from "../../../fields/Doc"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; @@ -18,10 +18,13 @@ import { DocumentType } from "../../documents/DocumentTypes"; import { Zoom, Fade, Flip, Rotate, Bounce, Roll, LightSpeed } from 'react-reveal'; import { PresBox, PresEffect } from "./PresBox"; import { InkingStroke } from "../InkingStroke"; +import { SnappingManager } from "../../util/SnappingManager"; +import { InkTool } from "../../../fields/InkField"; 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; sizeProvider?: (doc: Doc, replica: string) => { width: number, height: number } | undefined; + layerProvider?: (doc: Doc, assign?: boolean) => boolean; zIndex?: number; highlight?: boolean; jitterRotation: number; @@ -33,6 +36,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { @observer export class CollectionFreeFormDocumentView extends DocComponent(Document) { @observable _animPos: number[] | undefined = undefined; + @observable _contentView: ContentFittingDocumentView | undefined | null; random(min: number, max: number) { // min should not be equal to max const mseed = Math.abs(this.X * this.Y); const seed = (mseed * 9301 + 49297) % 233280; @@ -206,6 +210,7 @@ export class CollectionFreeFormDocumentView extends DocComponent this.Opacity; NativeWidth = () => this.nativeWidth; NativeHeight = () => this.nativeHeight; + @computed get pointerEvents() { + if (this.props.pointerEvents === "none") return "none"; + const layer = this.props.layerProvider?.(this.Document); + if (layer === false && !this._contentView?.docView?.isSelected() && !SnappingManager.GetIsDragging()) return "none"; + if (this.Document.type === DocumentType.INK && Doc.GetSelectedTool() !== InkTool.None) return "none"; + if (layer === true) return "all"; + return this.props.pointerEvents; + } render() { TraceMobx(); - const backgroundColor = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document, this.props.renderDepth); + const backgroundColor = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document, this.props.renderDepth, this.props.layerProvider); const borderRounding = StrCast(Doc.Layout(this.layoutDoc).borderRounding) || StrCast(this.layoutDoc.borderRounding) || StrCast(this.Document.borderRounding) || undefined; return
{Doc.UserDoc().renderStyle !== "comic" ? (null) : @@ -280,6 +293,7 @@ export class CollectionFreeFormDocumentView extends DocComponent{this.freeformNodeDiv} : this._contentView = r)} ContainingCollectionDoc={this.props.ContainingCollectionDoc} DataDoc={this.props.DataDoc} ScreenToLocalTransform={this.getTransform} diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index d5b91f4a7..d963369f8 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -45,7 +45,7 @@ export class ContentFittingDocumentView extends React.Component this.props.ScreenToLocalTransform(). - translate(this.props.dontCenter?.includes("x") ? 0 : -this.centeringOffset, this.props.dontCenter?.includes("y") ? 0 : -this.centeringYOffset); + translate(this.props.dontCenter?.includes("x") ? 0 : -this.centeringOffset, this.props.dontCenter?.includes("y") ? 0 : -this.centeringYOffset) private get centeringOffset() { return this.nativeWidth && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth * this.nativeScaling) / 2 : 0; } private get centeringYOffset() { return Math.abs(this.centeringOffset) < 0.001 && this.nativeHeight ? (this.props.PanelHeight() - this.nativeHeight * this.nativeScaling) / 2 : 0; } diff --git a/src/client/views/nodes/DocHolderBox.tsx b/src/client/views/nodes/DocHolderBox.tsx index dd254ae93..b5e0df659 100644 --- a/src/client/views/nodes/DocHolderBox.tsx +++ b/src/client/views/nodes/DocHolderBox.tsx @@ -184,7 +184,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent, onInput: Opt): JsxBindings { const list = { - ...OmitKeys(this.props, ['parentActive', 'NativeWidth', 'NativeHeight'], "", (obj: any) => obj.active = this.props.parentActive).omit, + ...OmitKeys(this.props, ['NativeWidth', 'NativeHeight'], "", (obj: any) => obj.active = this.props.parentActive).omit, RootDoc: Cast(this.layoutDoc?.rootDocument, Doc, null) || this.layoutDoc, Document: this.layoutDoc, DataDoc: this.dataDoc, diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f6262310f..9b26094b3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -41,6 +41,7 @@ import { LinkDescriptionPopup } from './LinkDescriptionPopup'; import { RadialMenu } from './RadialMenu'; import { TaskCompletionBox } from './TaskCompletedBox'; import React = require("react"); +import { List } from '../../../fields/List'; export type DocAfterFocusFunc = (notFocused: boolean) => boolean; export type DocFocusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, focused?: boolean) => void; @@ -57,6 +58,7 @@ export interface DocumentViewProps { NativeHeight?: () => number; Document: Doc; DataDoc?: Doc; + layerProvider?: (doc: Doc, assign?: boolean) => boolean; getView?: (view: DocumentView) => any; LayoutTemplateString?: string; LayoutTemplate?: () => Opt; @@ -91,7 +93,7 @@ export interface DocumentViewProps { addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; backgroundHalo?: () => boolean; - backgroundColor?: (doc: Opt, renderDepth: number) => string | undefined; + backgroundColor?: (doc: Opt, renderDepth: number, layerProvider?: (doc: Doc, assign?: boolean) => boolean) => string | undefined; forcedBackgroundColor?: (doc: Doc) => string | undefined; opacity?: () => number | undefined; ChromeHeight?: () => number; @@ -313,7 +315,7 @@ export class DocumentView extends DocComponent(Docu (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { let stopPropagate = true; let preventDefault = true; - !this.props.Document._isBackground && (this.rootDoc._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc); + !Cast(this.props.Document.layers, listSpec("string"), []).includes("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); @@ -746,9 +748,14 @@ export class DocumentView extends DocComponent(Docu @undoBatch @action toggleBackground = () => { - this.Document._isBackground = (this.Document._isBackground ? undefined : true); - this.Document._overflow = this.Document._isBackground ? "visible" : undefined; - if (this.Document._isBackground) { + const layers = Cast(this.Document.layers, listSpec("string"), []); + if (!layers.includes("background")) { + if (!layers.length) this.Document.layers = new List(["background"]); + else layers.push("background"); + } + else layers.splice(layers.indexOf("background"), 1); + this.Document._overflow = !layers.includes("background") ? "visible" : undefined; + if (!layers.includes("background")) { this.props.bringToFront(this.props.Document, 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](); @@ -920,7 +927,8 @@ export class DocumentView extends DocComponent(Docu childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling()); @computed.struct get linkOffset() { return this.topMost ? [0, undefined, undefined, 10] : [-15, undefined, undefined, -20]; } @observable contentsActive: () => boolean = returnFalse; - @action setContentsActive = (setActive: () => boolean) => { this.contentsActive = setActive; } + @action setContentsActive = (setActive: () => boolean) => this.contentsActive = setActive; + parentActive = (outsideReaction: boolean) => this.props.layerProvider?.(this.layoutDoc) === false ? this.props.parentActive(outsideReaction) : false; @computed get contents() { TraceMobx(); return (
@@ -935,6 +943,7 @@ export class DocumentView extends DocComponent(Docu NativeHeight={this.NativeHeight} Document={this.props.Document} DataDoc={this.props.DataDoc} + layerProvider={this.props.layerProvider} LayoutTemplateString={this.props.LayoutTemplateString} LayoutTemplate={this.props.LayoutTemplate} makeLink={this.makeLink} @@ -952,7 +961,7 @@ export class DocumentView extends DocComponent(Docu PanelHeight={this.props.PanelHeight} ignoreAutoHeight={this.props.ignoreAutoHeight} focus={this.props.focus} - parentActive={this.props.parentActive} + parentActive={this.parentActive} whenActiveChanged={this.props.whenActiveChanged} bringToFront={this.props.bringToFront} addDocTab={this.props.addDocTab} @@ -1072,10 +1081,13 @@ export class DocumentView extends DocComponent(Docu {captionView}
; } - @computed get ignorePointerEvents() { - return this.props.pointerEvents === "none" || - (this.Document._isBackground && !this.isSelected() && !SnappingManager.GetIsDragging()) || - (this.Document.type === DocumentType.INK && Doc.GetSelectedTool() !== InkTool.None); + @computed get pointerEvents() { + if (this.props.pointerEvents === "none") return "none"; + const layer = this.props.layerProvider?.(this.Document); + if (layer === false && !this.isSelected() && !SnappingManager.GetIsDragging()) return "none"; + if (this.Document.type === DocumentType.INK && Doc.GetSelectedTool() !== InkTool.None) return "none"; + if (layer === true) return "all"; + return undefined; } @undoBatch @action @@ -1096,11 +1108,12 @@ export class DocumentView extends DocComponent(Docu }); renderLock() { - return (this.Document._isBackground !== undefined || this.isSelected(false)) && - ((this.Document.type === DocumentType.COL && this.Document._viewType !== CollectionViewType.Pile) || this.Document.type === DocumentType.IMG || this.Document.type === DocumentType.INK) && + const isBackground = Cast(this.Document.layers, listSpec("string"), []).includes("background"); + return (isBackground || this.isSelected(false)) && + ((this.Document.type === DocumentType.COL && this.Document._viewType !== CollectionViewType.Pile) || this.Document.type === DocumentType.RTF || this.Document.type === DocumentType.IMG || this.Document.type === DocumentType.INK) && this.props.renderDepth > 0 && !this.props.treeViewDoc ?
- +
: (null); } @@ -1110,7 +1123,7 @@ export class DocumentView extends DocComponent(Docu if (!(this.props.Document instanceof Doc)) return (null); if (GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate) return (null); if (this.props.Document.hidden) return (null); - const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document, this.props.renderDepth); + const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || this.props.backgroundColor?.(this.layoutDoc, this.props.renderDepth, this.props.layerProvider); const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null))); const finalOpacity = this.props.opacity ? this.props.opacity() : opacity; const finalColor = this.layoutDoc.type === DocumentType.FONTICON || this.layoutDoc._viewType === CollectionViewType.Linear ? undefined : backgroundColor; @@ -1146,7 +1159,7 @@ 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.ignorePointerEvents ? "none" : undefined, + pointerEvents: this.pointerEvents, color: StrCast(this.layoutDoc.color, "inherit"), outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", border: highlighting && borderRounding && highlightStyles[fullDegree] === "dashed" ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index d7ff051cf..b8f2d5d6f 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -26,6 +26,7 @@ export interface FieldViewProps { Document: Doc; DataDoc?: Doc; LibraryPath: Doc[]; + layerProvider?: (doc: Doc, assign?: boolean) => boolean; contentsActive?: (setActive: () => boolean) => void; onClick?: () => ScriptField; dropAction: dropActionType; @@ -42,9 +43,10 @@ export interface FieldViewProps { pinToPres: (document: Doc) => void; removeDocument?: (document: Doc | Doc[]) => boolean; moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; - backgroundColor?: (document: Opt, renderDepth: number) => string | undefined; + backgroundColor?: (document: Opt, renderDepth: number, layerProvider?: (doc: Doc, assign?: boolean) => boolean) => string | undefined; ScreenToLocalTransform: () => Transform; bringToFront: (doc: Doc, sendToBack?: boolean) => void; + parentActive: (outsideReaction: boolean) => boolean; active: (outsideReaction?: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; LayoutTemplateString?: string; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 6f01e5916..24cd6f21f 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -204,6 +204,7 @@ export class FilterBox extends ViewBoxBaseComponent( render() { const label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title)); const color = StrCast(this.layoutDoc.color, this._foregroundColor); - const backgroundColor = StrCast(this.layoutDoc._backgroundColor, StrCast(this.rootDoc.backgroundColor, this.props.backgroundColor?.(this.rootDoc, this.props.renderDepth))); + const backgroundColor = StrCast(this.layoutDoc._backgroundColor, StrCast(this.rootDoc.backgroundColor, this.props.backgroundColor?.(this.rootDoc, this.props.renderDepth, this.props.layerProvider))); 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/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 88dc3b241..1c1a13061 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -161,7 +161,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent { this.layoutDoc._isBackground = true; this.props.bringToFront?.(this.rootDoc); }, icon: "expand-arrows-alt" }); if (!Doc.UserDoc().noviceMode) { funcs.push({ description: "Export to Google Photos", event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: "caret-square-right" }); funcs.push({ description: "Copy path", event: () => Utils.CopyText(field.url.href), icon: "expand-arrows-alt" }); @@ -411,7 +410,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { dropAction: "alias", bringToFront: emptyFunction, renderDepth: 1, + parentActive: returnFalse, active: returnFalse, whenActiveChanged: emptyFunction, ScreenToLocalTransform: Transform.Identity, diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index ec8c43ab4..7ce9abf27 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -92,7 +92,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent { const alias = Doc.MakeAlias(Cast(this.layoutDoc[this.fieldKey], Doc, null)); alias.isLinkButton = undefined; - alias._isBackground = undefined; + alias.layers = undefined; alias.layoutKey = "layout"; this.props.addDocTab(alias, "add:right"); } diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 64ae1051b..f80eb8f79 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -17,7 +17,7 @@ export class LinkBox extends ViewBoxBaseComponent( public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); } render() { return
+ style={{ background: this.props.backgroundColor?.(this.props.Document, this.props.renderDepth, this.props.layerProvider) }} > removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc); getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight panelHeight = () => this.props.PanelHeight() - 40; - active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc._isBackground) && + active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && this.props.layerProvider?.(this.layoutDoc) !== false) && (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) /** diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index bc69a3954..8ce76a347 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -393,7 +393,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 80e2d3ce2..ab97f9f7e 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -461,7 +461,7 @@ export class WebBox extends ViewBoxAnnotatableComponent {!frozen ? (null) : -
@@ -663,7 +663,7 @@ export class WebBox extends ViewBoxAnnotatableComponent @@ -671,7 +671,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { const target = this._outerRef.current; @@ -693,7 +693,7 @@ export class WebBox extends ViewBoxAnnotatableComponent
FormattedTextBoxComment.Hide()); const minimal = this.props.ignoreAutoHeight; const margins = NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0); diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 7b4afeb69..574bda970 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -1,12 +1,12 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, IReactionDisposer, reaction, runInAction, observable, trace } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DataSym, DocListCast } from "../../../fields/Doc"; +import { Doc, DataSym } from "../../../fields/Doc"; import { documentSchema } from '../../../fields/documentSchemas'; import { Id } from "../../../fields/FieldSymbols"; -import { createSchema, makeInterface, listSpec } from '../../../fields/Schema'; -import { Cast, NumCast, BoolCast, ScriptCast, StrCast } from "../../../fields/Types"; -import { emptyFunction, emptyPath, returnFalse, returnTrue, returnOne, returnZero, numberRange, setupMoveUpEvents } from "../../../Utils"; +import { createSchema, makeInterface } from '../../../fields/Schema'; +import { Cast, NumCast, StrCast } from "../../../fields/Types"; +import { emptyFunction, emptyPath, returnFalse, returnTrue, returnOne, setupMoveUpEvents } from "../../../Utils"; import { Transform } from "../../util/Transform"; import { ViewBoxBaseComponent } from '../DocComponent'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; @@ -312,7 +312,7 @@ export class PresElementBox extends ViewBoxBaseComponent {`${this.indexInPres + 1}.`}
} - {miniView ? (null) :
+ {miniView ? (null) :