From e14f9c12eba91bb5ecd3935ccbd3d20928e263a9 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 10 Nov 2020 17:45:50 -0500 Subject: fixes for tree view to display embedded documents correclty -- nested collections didn't have a width before and vertical sizing was off. --- src/client/views/collections/TreeView.tsx | 2 +- .../views/nodes/ContentFittingDocumentView.tsx | 31 ++++++++++++++++------ 2 files changed, 24 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 925eb4be6..2c504a020 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -281,7 +281,7 @@ export class TreeView extends React.Component { const layoutDoc = this.layoutDoc; const aspect = Doc.NativeAspect(layoutDoc); 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) : 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); } docHeight = () => { const layoutDoc = this.layoutDoc; diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 0c52b9044..082f9a9e8 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -7,6 +7,7 @@ import { TraceMobx } from "../../../fields/util"; import { emptyFunction, OmitKeys, returnVal } from "../../../Utils"; import { DocumentView, DocumentViewProps } from "../nodes/DocumentView"; import "./ContentFittingDocumentView.scss"; +import { CollectionViewType } from "../collections/CollectionView"; interface ContentFittingDocumentViewProps { dontCenter?: boolean; @@ -22,9 +23,10 @@ export class ContentFittingDocumentView extends React.Component this.nativeWidth(); // returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, false)); nativeWidth = () => returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelWidth()); nativeHeight = () => returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelHeight()); - @computed get scaling() { + @computed get nativeScaling() { const wscale = this.props.PanelWidth() / this.nativeWidth(); const hscale = this.props.PanelHeight() / this.nativeHeight(); if (wscale * this.nativeHeight() > this.props.PanelHeight()) { @@ -32,15 +34,13 @@ export class ContentFittingDocumentView extends React.Component this.scaling; - private PanelWidth = () => this.panelWidth; private PanelHeight = () => this.panelHeight; - @computed get panelWidth() { return this.nativeWidth() && !this.props.Document._fitWidth ? this.nativeWidth() * this.contentScaling() : this.props.PanelWidth(); } + @computed get panelWidth() { return this.nativeWidth() && !this.props.Document._fitWidth ? this.nativeWidth() * this.nativeScaling : this.props.PanelWidth(); } @computed get panelHeight() { if (this.nativeHeight()) { - if (!this.props.Document._fitWidth) return this.nativeHeight() * this.contentScaling(); + if (!this.props.Document._fitWidth) return this.nativeHeight() * this.nativeScaling; else return this.panelWidth / Doc.NativeAspect(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 1; } return this.props.PanelHeight(); @@ -50,11 +50,26 @@ export class ContentFittingDocumentView extends React.Component this.props.dontCenter ? this.props.ScreenToLocalTransform().scale(this.childXf) : this.props.ScreenToLocalTransform().translate(-this.centeringOffset, -this.centeringYOffset).scale(this.childXf) - private get centeringOffset() { return this.nativeWidth() && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth() * this.contentScaling()) / 2 : 0; } - private get centeringYOffset() { return Math.abs(this.centeringOffset) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight() * this.contentScaling()) / 2 : 0; } + private get centeringOffset() { return this.trueNativeWidth() && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth() * this.nativeScaling) / 2 : 0; } + private get centeringYOffset() { return Math.abs(this.centeringOffset) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight() * this.nativeScaling) / 2 : 0; } @computed get borderRounding() { return StrCast(this.props.Document?.borderRounding); } + contentScaling = () => { + return this.nativeScaling * Math.min(this.props.PanelWidth(), this.layoutDoc[WidthSym]()) / this.layoutWidth(); + } + + layoutWidth = () => { + let layoutWidth = this.layoutDoc[WidthSym](); + if ((this.props.LayoutTemplateString || StrCast(this.layoutDoc.layout)).includes("CollectionView")) {//} && this.layoutDoc._viewType === CollectionViewType.Freeform) { + const layoutAspect = layoutWidth / this.layoutDoc[HeightSym](); + if (this.props.PanelWidth() / this.props.PanelHeight() > layoutAspect) { + layoutWidth = this.props.PanelHeight() * layoutAspect; + } + } + return Math.min(this.props.PanelWidth(), layoutWidth); + } + render() { TraceMobx(); return (
@@ -64,7 +79,7 @@ export class ContentFittingDocumentView extends React.Component 0.001 ? `${100 * this.nativeHeight() / this.nativeWidth() * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(), - width: Math.abs(this.centeringOffset) > 0.001 ? `${100 * (this.props.PanelWidth() - this.centeringOffset * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth() + width: Math.abs(this.centeringOffset) > 0.001 ? `${100 * (this.props.PanelWidth() - this.centeringOffset * 2) / this.props.PanelWidth()}%` : this.nativeWidth() ? this.layoutWidth() : this.props.PanelWidth(), }}> Date: Tue, 10 Nov 2020 20:59:44 -0500 Subject: fixed Slides to be Colllections (not text) and fixed dockingView to display collections properly. --- src/client/util/CurrentUserUtils.ts | 4 +-- src/client/views/collections/TreeView.tsx | 36 ++++++++++++++++------ .../collectionFreeForm/CollectionFreeFormView.tsx | 1 + .../views/nodes/ContentFittingDocumentView.tsx | 6 ++-- 4 files changed, 32 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 4f054269f..cae359362 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -378,10 +378,8 @@ export class CurrentUserUtils { ((doc.emptyPane as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptySlide === undefined) { - const textDoc = Docs.Create.TextDocument("Slide", { title: "Slide", _viewType: CollectionViewType.Tree, _fontSize: "20px", treeViewOutlineMode: true, _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, _backgroundColor: "transparent", system: true, cloneFieldFilter: new List(["system"]) }); - Doc.GetProto(textDoc).layout = CollectionView.LayoutString("data"); + const textDoc = Docs.Create.TreeDocument([], { title: "Slide", _viewType: CollectionViewType.Tree, _fontSize: "20px", treeViewOutlineMode: true, _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, _backgroundColor: "transparent", system: true, cloneFieldFilter: new List(["system"]) }); Doc.GetProto(textDoc).title = ComputedField.MakeFunction('self.text?.Text'); - Doc.GetProto(textDoc).data = new List([]); FormattedTextBox.SelectOnLoad = textDoc[Id]; doc.emptySlide = textDoc; } diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 2c504a020..233b6092c 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -185,8 +185,12 @@ export class TreeView extends React.Component { } public static makeTextBullet() { - const bullet = Docs.Create.TextDocument("-text-", { title: "-title-", "sidebarColor": "transparent", "sidebarViewType": CollectionViewType.Freeform, forceActive: true, _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewOutlineMode: true, x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _backgroundColor: "transparent", _width: 1000, _height: 10 }); - Doc.GetProto(bullet).layout = CollectionView.LayoutString("data"); + const bullet = Docs.Create.TextDocument("-text-", { + layout: CollectionView.LayoutString("data"), + title: "-title-", "sidebarColor": "transparent", "sidebarViewType": CollectionViewType.Freeform, + forceActive: true, _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewOutlineMode: true, + x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _backgroundColor: "transparent", _width: 1000, _height: 10 + }); Doc.GetProto(bullet).title = ComputedField.MakeFunction('self.text?.Text'); Doc.GetProto(bullet).data = new List([]); Doc.SetInPlace(bullet, "editTitle", "*", false); @@ -285,15 +289,17 @@ export class TreeView extends React.Component { } docHeight = () => { const layoutDoc = this.layoutDoc; - const bounds = this.boundsOfCollectionDocument; return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => { const aspect = Doc.NativeAspect(layoutDoc); if (aspect) return this.docWidth() / (aspect || 1); - if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x); - return layoutDoc._fitWidth ? (!Doc.NativeHeight(this.doc) ? NumCast(this.props.containingCollection._height) : - Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc)) / - (Doc.NativeWidth(layoutDoc) || NumCast(this.props.containingCollection._height)) - )) : (layoutDoc[HeightSym]() || 50); + return layoutDoc._fitWidth ? + (!Doc.NativeHeight(this.doc) ? + NumCast(this.props.containingCollection._height) + : + Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc)) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.containingCollection._height)) + )) + : + (layoutDoc[HeightSym]() || 50); })())); } @@ -350,6 +356,16 @@ export class TreeView extends React.Component { rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.props.panelWidth() - 20); 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); + docFinalHeight = () => { + const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym](); + const docAspect = this.docWidth() / this.docHeight(); + return (docAspect < aspect) ? this.docWidth() / aspect : this.docHeight(); + } + docFinalWidth = () => { + const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym](); + const docAspect = this.docWidth() / this.docHeight(); + return (docAspect > aspect) ? this.docHeight() * aspect : this.docWidth(); + } @computed get renderContent() { TraceMobx(); @@ -381,8 +397,8 @@ export class TreeView extends React.Component {
; } else { const layoutDoc = this.layoutDoc; - const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docHeight; - const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docWidth; + const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docFinalHeight; + const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docFinalWidth; return
this.nativeWidth(); // returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, false)); + trueNativeWidth = () => returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, false)); nativeWidth = () => returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelWidth()); nativeHeight = () => returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelHeight()); @computed get nativeScaling() { @@ -56,7 +57,8 @@ export class ContentFittingDocumentView extends React.Component { - return this.nativeScaling * Math.min(this.props.PanelWidth(), this.layoutDoc[WidthSym]()) / this.layoutWidth(); + if ((this.props.LayoutTemplateString || StrCast(this.layoutDoc.layout)).includes("FormattedTextBox")) return this.nativeScaling; + return this.nativeScaling * this.layoutDoc[WidthSym]() / this.layoutWidth(); } layoutWidth = () => { -- cgit v1.2.3-70-g09d2 From 70e79356ce89f4afb47220393c541f74eada62fc Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 11 Nov 2020 02:09:18 -0500 Subject: turned off selection highlighting in TreeView because it is way too inefficient. more fixes to laying out fitWidth and other documents in ContentFittingDocViews. testing against GridViews and TreeViews things seem to work. --- src/client/util/DocumentManager.ts | 1 - .../views/collections/CollectionTreeView.tsx | 3 +- src/client/views/collections/TreeView.tsx | 22 ++++---- .../collectionGrid/CollectionGridView.tsx | 9 ++-- .../views/nodes/ContentFittingDocumentView.tsx | 58 +++++++++------------- 5 files changed, 44 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index a6816c7f9..eaccbdb63 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -9,7 +9,6 @@ import { CollectionView } from '../views/collections/CollectionView'; import { DocumentView } from '../views/nodes/DocumentView'; import { LinkManager } from './LinkManager'; import { Scripting } from './Scripting'; -import { SelectionManager } from './SelectionManager'; import { LinkDocPreview } from '../views/nodes/LinkDocPreview'; import { FormattedTextBoxComment } from '../views/nodes/formattedText/FormattedTextBoxComment'; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a7c8a7cdc..be31ca6e5 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -26,6 +26,7 @@ import { TreeView } from "./TreeView"; import React = require("react"); import { DocumentManager } from '../../util/DocumentManager'; import { FormattedTextBoxComment } from '../nodes/formattedText/FormattedTextBoxComment'; +import { DocumentView } from '../nodes/DocumentView'; export type collectionTreeViewProps = { treeViewHideTitle?: boolean; @@ -158,7 +159,7 @@ export class CollectionTreeView extends CollectionSubView - { @computed get childDocs() { TraceMobx(); return this.childDocList(this.fieldKey); } @computed get childLinks() { return this.childDocList("links"); } @computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); } - @computed get boundsOfCollectionDocument() { - return StrCast(this.props.document.type).indexOf(DocumentType.COL) === -1 || !DocListCast(this.props.document[this.fieldKey]).length ? undefined : - Doc.ComputeContentBounds(DocListCast(this.props.document[this.fieldKey])); + @computed get isCollectionDoc() { + return !StrCast(this.props.document.type).includes(DocumentType.COL) || !DocListCast(this.props.document[this.fieldKey]).length ? false : true } @undoBatch openRight = () => this.props.addDocTab(this.doc, "add:right"); @@ -284,6 +283,7 @@ 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); } @@ -356,12 +356,14 @@ export class TreeView extends React.Component { rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.props.panelWidth() - 20); 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); - docFinalHeight = () => { + expandPanelHeight = () => { + if (this.layoutDoc._fitWidth) return this.docHeight(); const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym](); const docAspect = this.docWidth() / this.docHeight(); return (docAspect < aspect) ? this.docWidth() / aspect : this.docHeight(); } - docFinalWidth = () => { + expandPanelWidth = () => { + if (this.layoutDoc._fitWidth) return this.docWidth(); const aspect = this.layoutDoc[WidthSym]() / this.layoutDoc[HeightSym](); const docAspect = this.docWidth() / this.docHeight(); return (docAspect > aspect) ? this.docHeight() * aspect : this.docWidth(); @@ -397,8 +399,8 @@ export class TreeView extends React.Component {
; } else { const layoutDoc = this.layoutDoc; - const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docFinalHeight; - const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docFinalWidth; + const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.expandPanelHeight; + const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.expandPanelWidth; return
{ rootSelected={returnTrue} treeViewDoc={undefined} backgroundColor={this.props.backgroundColor} - fitToBox={this.boundsOfCollectionDocument !== undefined} + fitToBox={this.isCollectionDoc !== undefined} FreezeDimensions={true} NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined} NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined} @@ -567,7 +569,7 @@ export class TreeView extends React.Component { } } else this._editMaxWidth = ""; - const selected = SelectionManager.IsSelected(DocumentManager.Instance.getFirstDocumentView(this.doc)); + const selected = false;// SelectionManager.IsSelected(DocumentManager.Instance.getFirstDocumentView(this.doc)); // bcz: need to fix so that this doesn't get called for every selection/view creation. this is used to highlight bullet items in Slide views return this.doc.treeViewHideHeader || this.outlineMode ? !StrCast(Doc.LayoutField(this.doc)).includes("CollectionView") ? this.renderContent @@ -597,7 +599,7 @@ export class TreeView extends React.Component { rootSelected={returnTrue} treeViewDoc={undefined} backgroundColor={this.props.backgroundColor} - fitToBox={this.boundsOfCollectionDocument !== undefined} + fitToBox={this.isCollectionDoc !== undefined} PanelWidth={this.rtfWidth} PanelHeight={this.rtfOutlineHeight} focus={this.refocus} diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index d31427829..57f845961 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -1,12 +1,12 @@ import { action, computed, Lambda, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from "react"; -import { Doc, Opt, WidthSym } from '../../../../fields/Doc'; +import { Doc, Opt } from '../../../../fields/Doc'; import { documentSchema } from '../../../../fields/documentSchemas'; import { Id } from '../../../../fields/FieldSymbols'; import { makeInterface } from '../../../../fields/Schema'; import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, OmitKeys } from '../../../../Utils'; +import { emptyFunction, OmitKeys, returnFalse, returnOne, setupMoveUpEvents } from '../../../../Utils'; import { Docs } from '../../../documents/Documents'; import { DragManager } from '../../../util/DragManager'; import { SnappingManager } from '../../../util/SnappingManager'; @@ -169,11 +169,14 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { ContainingCollectionDoc={this.props.Document} PanelWidth={width} PanelHeight={height} + ContentScaling={returnOne} + fitToBox={false} + FreezeDimensions={true} ScreenToLocalTransform={dxf} onClick={this.onChildClickHandler} renderDepth={this.props.renderDepth + 1} parentActive={this.props.active} - dontCenter={true} + dontCenter={false} />; } diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 70a40f39e..7b698c8bd 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -2,13 +2,11 @@ import React = require("react"); import { computed } from "mobx"; import { observer } from "mobx-react"; import { Doc, HeightSym, WidthSym } from "../../../fields/Doc"; -import { Cast, NumCast, StrCast } from "../../../fields/Types"; +import { Cast, StrCast } from "../../../fields/Types"; import { TraceMobx } from "../../../fields/util"; import { emptyFunction, OmitKeys, returnVal } from "../../../Utils"; import { DocumentView, DocumentViewProps } from "../nodes/DocumentView"; import "./ContentFittingDocumentView.scss"; -import { CollectionViewType } from "../collections/CollectionView"; -import { DocumentType } from "../../documents/DocumentTypes"; interface ContentFittingDocumentViewProps { dontCenter?: boolean; @@ -17,32 +15,30 @@ interface ContentFittingDocumentViewProps { @observer export class ContentFittingDocumentView extends React.Component { public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive - private get layoutDoc() { + @computed get layoutDoc() { return this.props.LayoutTemplate?.() || (this.props.layoutKey && Doc.Layout(this.props.Document, Cast(this.props.Document[this.props.layoutKey], Doc, null))) || Doc.Layout(this.props.Document); } @computed get freezeDimensions() { return this.props.FreezeDimensions; } - - trueNativeWidth = () => returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, false)); - nativeWidth = () => returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelWidth()); - nativeHeight = () => returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelHeight()); + @computed get trueNativeWidth() { return !this.layoutDoc._fitWidth && returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, false)); } + @computed get nativeWidth() { return returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 0); } + @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 0); } @computed get nativeScaling() { - const wscale = this.props.PanelWidth() / this.nativeWidth(); - const hscale = this.props.PanelHeight() / this.nativeHeight(); - if (wscale * this.nativeHeight() > this.props.PanelHeight()) { + if (!this.nativeWidth || !this.nativeHeight) return 1; + const wscale = this.props.PanelWidth() / this.nativeWidth; + const hscale = this.props.PanelHeight() / this.nativeHeight; + if (wscale * this.nativeHeight > this.props.PanelHeight()) { return hscale || 1; } return wscale || 1; } - private PanelWidth = () => this.panelWidth; - private PanelHeight = () => this.panelHeight; - @computed get panelWidth() { return this.nativeWidth() && !this.props.Document._fitWidth ? this.nativeWidth() * this.nativeScaling : this.props.PanelWidth(); } + @computed get panelWidth() { return this.trueNativeWidth ? this.nativeWidth * this.nativeScaling : this.props.PanelWidth(); } @computed get panelHeight() { - if (this.nativeHeight()) { - if (!this.props.Document._fitWidth) return this.nativeHeight() * this.nativeScaling; - else return this.panelWidth / Doc.NativeAspect(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 1; + if (this.nativeHeight) { + if (this.props.Document._fitWidth) return Math.min(this.props.PanelHeight(), this.panelWidth / Doc.NativeAspect(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 1); + return Math.min(this.props.PanelHeight(), this.nativeHeight * this.nativeScaling); } return this.props.PanelHeight(); } @@ -51,25 +47,19 @@ export class ContentFittingDocumentView extends React.Component this.props.dontCenter ? this.props.ScreenToLocalTransform().scale(this.childXf) : this.props.ScreenToLocalTransform().translate(-this.centeringOffset, -this.centeringYOffset).scale(this.childXf) - private get centeringOffset() { return this.trueNativeWidth() && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth() * this.nativeScaling) / 2 : 0; } - private get centeringYOffset() { return Math.abs(this.centeringOffset) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight() * this.nativeScaling) / 2 : 0; } + private get centeringOffset() { return this.trueNativeWidth && !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; } @computed get borderRounding() { return StrCast(this.props.Document?.borderRounding); } + PanelWidth = () => this.panelWidth; + PanelHeight = () => this.panelHeight; contentScaling = () => { - if ((this.props.LayoutTemplateString || StrCast(this.layoutDoc.layout)).includes("FormattedTextBox")) return this.nativeScaling; - return this.nativeScaling * this.layoutDoc[WidthSym]() / this.layoutWidth(); - } - - layoutWidth = () => { - let layoutWidth = this.layoutDoc[WidthSym](); - if ((this.props.LayoutTemplateString || StrCast(this.layoutDoc.layout)).includes("CollectionView")) {//} && this.layoutDoc._viewType === CollectionViewType.Freeform) { - const layoutAspect = layoutWidth / this.layoutDoc[HeightSym](); - if (this.props.PanelWidth() / this.props.PanelHeight() > layoutAspect) { - layoutWidth = this.props.PanelHeight() * layoutAspect; - } - } - return Math.min(this.props.PanelWidth(), layoutWidth); + const layoutStr = (this.props.LayoutTemplateString || StrCast(this.layoutDoc.layout)); + if (layoutStr.includes("FormattedTextBox")) return this.nativeScaling; + const wscale = this.trueNativeWidth ? 1 : this.layoutDoc[WidthSym]() / this.props.PanelWidth(); + const hscale = this.trueNativeWidth ? 1 : this.layoutDoc[HeightSym]() / this.props.PanelHeight(); + return this.nativeScaling * Math.max(wscale, hscale); } render() { @@ -80,8 +70,8 @@ export class ContentFittingDocumentView extends React.Component 0.001 ? `${100 * this.nativeHeight() / this.nativeWidth() * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(), - width: Math.abs(this.centeringOffset) > 0.001 ? `${100 * (this.props.PanelWidth() - this.centeringOffset * 2) / this.props.PanelWidth()}%` : this.nativeWidth() ? this.layoutWidth() : this.props.PanelWidth(), + height: Math.abs(this.centeringYOffset) > 0.001 ? `${100 * this.nativeHeight / this.nativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(), + width: Math.abs(this.centeringOffset) > 0.001 ? `${100 * (this.props.PanelWidth() - this.centeringOffset * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth(), }}> Date: Wed, 11 Nov 2020 13:45:20 -0500 Subject: fixes to centering of documents in ContentFittingDocumentView. fixed display of document title in tree view when it was alrady rendered in the tree view. --- src/client/views/PropertiesView.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 1 + .../views/collections/CollectionStackingView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 141 ++++++++++----------- .../collectionGrid/CollectionGridView.tsx | 3 +- .../views/nodes/ContentFittingDocumentView.tsx | 28 ++-- 6 files changed, 86 insertions(+), 91 deletions(-) (limited to 'src') diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index fad2f5284..17cfb5a5a 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -273,7 +273,7 @@ export class PropertiesView extends React.Component { backgroundColor={this.props.backgroundColor} fitToBox={true} FreezeDimensions={true} - dontCenter={true} + dontCenter={"y"} NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined} NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined} PanelWidth={panelWidth} diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 9f8468253..a1df9d214 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -402,6 +402,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { DataDoc={undefined} fitToBox={true} FreezeDimensions={true} + dontCenter={"y"} focus={emptyFunction} LibraryPath={this.props.LibraryPath} renderDepth={this.props.renderDepth} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 97eacaeab..cf9ced849 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -202,7 +202,7 @@ export class CollectionStackingView extends CollectionSubView { private _openScript: (() => ScriptField) | undefined; private _header?: React.RefObject = React.createRef(); private _treedropDisposer?: DragManager.DragDropDisposer; - private _dref = React.createRef(); + private _dref = React.createRef(); private _tref = React.createRef(); private _docRef = React.createRef(); private _uniqueId = Utils.GenerateGuid(); @@ -112,7 +112,7 @@ export class TreeView extends React.Component { @computed get childLinks() { return this.childDocList("links"); } @computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); } @computed get isCollectionDoc() { - return !StrCast(this.props.document.type).includes(DocumentType.COL) || !DocListCast(this.props.document[this.fieldKey]).length ? false : true + return !StrCast(this.props.document.type).includes(DocumentType.COL) || !DocListCast(this.props.document[this.fieldKey]).length ? false : true; } @undoBatch openRight = () => this.props.addDocTab(this.doc, "add:right"); @@ -272,14 +272,15 @@ export class TreeView extends React.Component { return false; } - refTransform = (ref: HTMLDivElement) => { + refTransform = (ref: HTMLDivElement | undefined | null) => { + if (!ref) return this.props.ScreenToLocalTransform(); const { scale, translateX, translateY } = Utils.GetScreenTransform(ref); const outerXf = this.props.outerXf(); const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]); } - docTransform = () => this.refTransform(this._dref.current!); - getTransform = () => this.refTransform(this._tref.current!); + docTransform = () => this.refTransform(this._dref.current?.ContentRef?.current); + getTransform = () => this.refTransform(this._tref.current); docWidth = () => { const layoutDoc = this.layoutDoc; const aspect = Doc.NativeAspect(layoutDoc); @@ -394,47 +395,45 @@ export class TreeView extends React.Component { [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields, false, this.props.whenActiveChanged, this.props.dontRegisterView)} ; } else if (this.treeViewExpandedView === "fields") { - return
    + return
      {this.expandedField}
    ; } else { const layoutDoc = this.layoutDoc; const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.expandPanelHeight; const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.expandPanelWidth; - return
    - -
    ; + return ; } } @@ -557,7 +556,7 @@ export class TreeView extends React.Component { render() { TraceMobx(); - if (this.props.renderedIds.indexOf(this.doc[Id]) !== -1) return null; + if (this.props.renderedIds.indexOf(this.doc[Id]) !== -1) return "<" + this.doc.title + ">"; const sorting = this.doc[`${this.fieldKey}-sortAscending`]; if (this.showTitleEditorControl) { // find containing CollectionTreeView and set our maximum width so the containing tree view won't have to scroll let par: any = this._header?.current; @@ -589,37 +588,35 @@ export class TreeView extends React.Component { onPointerDown={e => { if (this.props.active(true)) { e.stopPropagation(); e.preventDefault(); } }} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}> {this.renderBullet} -
    - -
    +
    diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 57f845961..5c7373a2f 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -170,13 +170,12 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { PanelWidth={width} PanelHeight={height} ContentScaling={returnOne} - fitToBox={false} FreezeDimensions={true} ScreenToLocalTransform={dxf} onClick={this.onChildClickHandler} renderDepth={this.props.renderDepth + 1} parentActive={this.props.active} - dontCenter={false} + dontCenter={"y"} />; } diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 7b698c8bd..99b5f7478 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -9,7 +9,7 @@ import { DocumentView, DocumentViewProps } from "../nodes/DocumentView"; import "./ContentFittingDocumentView.scss"; interface ContentFittingDocumentViewProps { - dontCenter?: boolean; + dontCenter?: string; // "x" ,"y", "xy" } @observer @@ -21,8 +21,7 @@ export class ContentFittingDocumentView extends React.Component this.props.dontCenter ? - this.props.ScreenToLocalTransform().scale(this.childXf) : - this.props.ScreenToLocalTransform().translate(-this.centeringOffset, -this.centeringYOffset).scale(this.childXf) - private get centeringOffset() { return this.trueNativeWidth && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth * this.nativeScaling) / 2 : 0; } + private getTransform = () => this.props.ScreenToLocalTransform(). + translate(this.props.dontCenter?.includes("x") ? 0 : -this.centeringOffset, this.props.dontCenter?.includes("y") ? 0 : -this.centeringYOffset). + scale(this.childXf) + 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; } @computed get borderRounding() { return StrCast(this.props.Document?.borderRounding); } @@ -57,20 +56,21 @@ export class ContentFittingDocumentView extends React.Component { const layoutStr = (this.props.LayoutTemplateString || StrCast(this.layoutDoc.layout)); if (layoutStr.includes("FormattedTextBox")) return this.nativeScaling; - const wscale = this.trueNativeWidth ? 1 : this.layoutDoc[WidthSym]() / this.props.PanelWidth(); - const hscale = this.trueNativeWidth ? 1 : this.layoutDoc[HeightSym]() / this.props.PanelHeight(); + const wscale = this.nativeWidth ? 1 : this.layoutDoc[WidthSym]() / this.props.PanelWidth(); + const hscale = this.nativeWidth ? 1 : this.layoutDoc[HeightSym]() / this.props.PanelHeight(); return this.nativeScaling * Math.max(wscale, hscale); } + public ContentRef = React.createRef(); render() { TraceMobx(); return (
    {!this.props.Document || !this.props.PanelWidth ? (null) : ( -
    0.001 ? `${100 * this.nativeHeight / this.nativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(), + height: Math.abs(this.centeringYOffset) > 0.001 && this.nativeWidth ? `${100 * this.nativeHeight / this.nativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(), width: Math.abs(this.centeringOffset) > 0.001 ? `${100 * (this.props.PanelWidth() - this.centeringOffset * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth(), }}> Date: Thu, 12 Nov 2020 12:23:20 -0500 Subject: only use arrow keys to pan freeform views that are at the top level --- src/client/views/PreviewCursor.tsx | 15 +++++---------- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../views/collections/collectionFreeForm/MarqueeView.tsx | 4 +++- 3 files changed, 9 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index f5f115e01..d756227f6 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -2,20 +2,15 @@ import { action, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; -import "./PreviewCursor.scss"; -import { Docs, DocUtils } from '../documents/Documents'; import { Doc } from '../../fields/Doc'; -import { Transform } from "../util/Transform"; +import { Cast, NumCast } from '../../fields/Types'; import { DocServer } from '../DocServer'; +import { Docs, DocUtils } from '../documents/Documents'; +import { CurrentUserUtils } from '../util/CurrentUserUtils'; +import { Transform } from "../util/Transform"; import { undoBatch, UndoManager } from '../util/UndoManager'; -import { NumCast, Cast } from '../../fields/Types'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import * as rp from 'request-promise'; -import { Utils } from '../../Utils'; -import { Networking } from '../Network'; -import { Upload } from '../../server/SharedMediaTypes'; -import { basename } from 'path'; -import { CurrentUserUtils } from '../util/CurrentUserUtils'; +import "./PreviewCursor.scss"; @observer export class PreviewCursor extends React.Component<{}> { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c50b962dd..19dc97399 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1479,7 +1479,7 @@ export class CollectionFreeFormView extends CollectionSubView 0 ? undefined : this.nudge} addDocTab={this.addDocTab} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 7040b5e56..796f02deb 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -285,7 +285,9 @@ export class MarqueeView extends React.Component Date: Fri, 13 Nov 2020 13:50:21 -0500 Subject: fixed treeView to be able to access active() on contained document in order to keep slide sidebar active when sidebar documents are selected. fixed ContetntFittingDocumentView to show fitToBox correctly and more simplhy --- src/client/views/collections/TreeView.scss | 2 +- src/client/views/collections/TreeView.tsx | 197 ++++++++++++--------- .../collectionGrid/CollectionGridView.tsx | 1 + .../views/nodes/ContentFittingDocumentView.tsx | 21 +-- src/client/views/nodes/DocumentView.scss | 6 + src/client/views/nodes/DocumentView.tsx | 10 +- src/client/views/nodes/FieldView.tsx | 1 + .../nodes/formattedText/FormattedTextBox.scss | 3 + .../views/nodes/formattedText/FormattedTextBox.tsx | 12 +- 9 files changed, 144 insertions(+), 109 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index 17c6b0750..580fec9d6 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -22,7 +22,7 @@ } .treeView-container-active { z-index: 100; - position: relative;; + position: relative; .formattedTextbox-sidebar { background-color: #ffff001f !important; height: 500px !important; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index ef46be175..8746e7e0a 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable } from "mobx"; +import { action, computed, observable, trace } from "mobx"; import { observer } from "mobx-react"; import { DataSym, Doc, DocListCast, DocListCastOrNull, Field, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; @@ -78,12 +78,12 @@ export class TreeView extends React.Component { private _openScript: (() => ScriptField) | undefined; private _header?: React.RefObject = React.createRef(); private _treedropDisposer?: DragManager.DragDropDisposer; - private _dref = React.createRef(); private _tref = React.createRef(); private _docRef = React.createRef(); private _uniqueId = Utils.GenerateGuid(); private _editMaxWidth: number | string = 0; + @observable _dref: ContentFittingDocumentView | undefined | null; @computed get doc() { TraceMobx(); return this.props.document; } get noviceMode() { return BoolCast(Doc.UserDoc().noviceMode, false); } get displayName() { return "TreeView(" + this.props.document.title + ")"; } // this makes mobx trace() statements more descriptive @@ -187,7 +187,7 @@ export class TreeView extends React.Component { const bullet = Docs.Create.TextDocument("-text-", { layout: CollectionView.LayoutString("data"), title: "-title-", "sidebarColor": "transparent", "sidebarViewType": CollectionViewType.Freeform, - forceActive: true, _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewOutlineMode: true, + _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewOutlineMode: true, x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _backgroundColor: "transparent", _width: 1000, _height: 10 }); Doc.GetProto(bullet).title = ComputedField.MakeFunction('self.text?.Text'); @@ -279,7 +279,7 @@ export class TreeView extends React.Component { const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]); } - docTransform = () => this.refTransform(this._dref.current?.ContentRef?.current); + docTransform = () => this.refTransform(this._dref?.ContentRef?.current); getTransform = () => this.refTransform(this._tref.current); docWidth = () => { const layoutDoc = this.layoutDoc; @@ -402,7 +402,7 @@ export class TreeView extends React.Component { const layoutDoc = this.layoutDoc; const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.expandPanelHeight; const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.expandPanelWidth; - return this._dref = r)} Document={this.doc} DataDoc={undefined} LibraryPath={emptyPath} @@ -457,7 +457,8 @@ export class TreeView extends React.Component { @computed get renderBullet() { TraceMobx(); const checked = this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined; - return
    { truncateTitleWidth = () => NumCast(this.props.treeView.props.Document.treeViewTruncateTitleWidth, 0); onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); onChildDoubleClick = () => (!this.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); + + refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document); + ignoreEvent = (e: any) => { + if (this.props.active(true)) { + e.stopPropagation(); + e.preventDefault(); + } + } + onKeyDown = (e: React.KeyboardEvent) => { + if (this.doc.treeViewHideHeader || this.outlineMode) { + e.stopPropagation(); + e.preventDefault(); + switch (e.key) { + case "Tab": setTimeout(() => RichTextMenu.Instance.TextView?.EditorView?.focus(), 150); + return UndoManager.RunInBatch(() => e.shiftKey ? this.props.outdentDocument?.() : this.props.indentDocument?.(), "tab"); + case "Backspace": return !(this.doc.text as RichTextField)?.Text && this.props.removeDoc?.(this.doc); + case "Enter": return UndoManager.RunInBatch(this.makeTextCollection, "bullet"); + } + } + } + /** * Renders the EditableView title element for placement into the tree. */ @@ -505,7 +527,7 @@ export class TreeView extends React.Component { get renderTitle() { TraceMobx(); const view = this.showTitleEditorControl ? this.editableView("title") : - { ; } - refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document); + renderBulletHeader = (contents: JSX.Element) => { + return
    + {contents} +
    ; + } + + @computed get renderTitleAsText() { + return <> + {this.renderBullet} + {this.renderTitle} + ; + } + + @computed get renderDocumentInHeader() { + return <> + {this.renderBullet} + this._dref = r)} + Document={this.doc} + DataDoc={undefined} + LayoutTemplateString={FormattedTextBox.LayoutString("text")} + LibraryPath={emptyPath} + renderDepth={this.props.renderDepth + 1} + rootSelected={returnTrue} + treeViewDoc={undefined} + backgroundColor={this.props.backgroundColor} + fitToBox={this.isCollectionDoc !== undefined} + PanelWidth={this.rtfWidth} + PanelHeight={this.rtfOutlineHeight} + focus={this.refocus} + ScreenToLocalTransform={this.docTransform} + docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + ContainingCollectionDoc={this.props.containingCollection} + ContainingCollectionView={undefined} + addDocument={this.props.addDocument} + moveDocument={this.move} + removeDocument={this.props.removeDoc} + parentActive={this.props.active} + whenActiveChanged={this.props.whenActiveChanged} + addDocTab={this.props.addDocTab} + pinToPres={this.props.pinToPres} + bringToFront={returnFalse} + ContentScaling={returnOne} + /> + ; + } + + @computed get renderBorder() { + const sorting = this.doc[`${this.fieldKey}-sortAscending`]; + return
    + {!this.treeViewOpen ? (null) : this.renderContent} +
    ; + } render() { TraceMobx(); if (this.props.renderedIds.indexOf(this.doc[Id]) !== -1) return "<" + this.doc.title + ">"; - const sorting = this.doc[`${this.fieldKey}-sortAscending`]; if (this.showTitleEditorControl) { // find containing CollectionTreeView and set our maximum width so the containing tree view won't have to scroll let par: any = this._header?.current; while (par && par.className !== "collectionTreeView-dropTarget") par = par.parentNode; @@ -568,88 +649,28 @@ export class TreeView extends React.Component { } } else this._editMaxWidth = ""; - const selected = false;// SelectionManager.IsSelected(DocumentManager.Instance.getFirstDocumentView(this.doc)); // bcz: need to fix so that this doesn't get called for every selection/view creation. this is used to highlight bullet items in Slide views - return this.doc.treeViewHideHeader || this.outlineMode ? - !StrCast(Doc.LayoutField(this.doc)).includes("CollectionView") ? - this.renderContent - :
    this.props.active(true) && SelectionManager.DeselectAll()} - onKeyDown={e => { - e.stopPropagation(); - e.preventDefault(); - switch (e.key) { - case "Backspace": return !(this.doc.text as RichTextField)?.Text && this.props.removeDoc?.(this.doc); - case "Enter": return UndoManager.RunInBatch(() => this.makeTextCollection(), "bullet"); - case "Tab": setTimeout(() => RichTextMenu.Instance.TextView?.EditorView?.focus(), 150); - return UndoManager.RunInBatch(() => e.shiftKey ? this.props.outdentDocument?.() : this.props.indentDocument?.(), "tab"); - } - }} > -
    { if (this.props.active(true)) { e.stopPropagation(); e.preventDefault(); } }} - onPointerDown={e => { if (this.props.active(true)) { e.stopPropagation(); e.preventDefault(); } }} - onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}> - {this.renderBullet} - -
    - -
    - {!this.treeViewOpen ? (null) : this.renderContent} -
    -
    : -
    this.props.active(true) && SelectionManager.DeselectAll()}> -
  • -
    { - if (this.props.active(true)) { - e.stopPropagation(); - e.preventDefault(); - SelectionManager.DeselectAll(); - } - }} - onPointerDown={e => { - if (this.props.active(true)) { - e.stopPropagation(); - e.preventDefault(); - } - }} - onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}> - {this.renderBullet} - {this.renderTitle} -
    -
    - {!this.treeViewOpen ? (null) : this.renderContent} -
    -
  • + + const hideTitle = this.doc.treeViewHideHeader || this.outlineMode; + return hideTitle && !StrCast(Doc.LayoutField(this.doc)).includes("CollectionView") ? + this.renderContent + : +
    this.props.active(true) && SelectionManager.DeselectAll()} + onKeyDown={this.onKeyDown}> + {hideTitle ? +
  • + {this.renderBulletHeader(this.renderDocumentInHeader)} + {this.renderBorder} +
  • : +
  • + {this.renderBulletHeader(this.renderTitleAsText)} + {this.renderBorder} +
  • + }
    ; } - public static GetChildElements( childDocs: Doc[], treeView: CollectionTreeView, diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 5c7373a2f..8e86b6d0d 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -171,6 +171,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { PanelHeight={height} ContentScaling={returnOne} FreezeDimensions={true} + fitToBox={true} ScreenToLocalTransform={dxf} onClick={this.onChildClickHandler} renderDepth={this.props.renderDepth + 1} diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 99b5f7478..d5b91f4a7 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -1,10 +1,10 @@ import React = require("react"); -import { computed } from "mobx"; +import { computed, observable, action } from "mobx"; import { observer } from "mobx-react"; import { Doc, HeightSym, WidthSym } from "../../../fields/Doc"; import { Cast, StrCast } from "../../../fields/Types"; import { TraceMobx } from "../../../fields/util"; -import { emptyFunction, OmitKeys, returnVal } from "../../../Utils"; +import { emptyFunction, OmitKeys, returnVal, returnOne } from "../../../Utils"; import { DocumentView, DocumentViewProps } from "../nodes/DocumentView"; import "./ContentFittingDocumentView.scss"; @@ -15,6 +15,8 @@ interface ContentFittingDocumentViewProps { @observer export class ContentFittingDocumentView extends React.Component { public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive + public ContentRef = React.createRef(); + @observable public docView: DocumentView | undefined | null; @computed get layoutDoc() { return this.props.LayoutTemplate?.() || (this.props.layoutKey && Doc.Layout(this.props.Document, Cast(this.props.Document[this.props.layoutKey], Doc, null))) || @@ -42,10 +44,8 @@ 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). - scale(this.childXf) + 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; } @@ -53,15 +53,7 @@ export class ContentFittingDocumentView extends React.Component this.panelWidth; PanelHeight = () => this.panelHeight; - contentScaling = () => { - const layoutStr = (this.props.LayoutTemplateString || StrCast(this.layoutDoc.layout)); - if (layoutStr.includes("FormattedTextBox")) return this.nativeScaling; - const wscale = this.nativeWidth ? 1 : this.layoutDoc[WidthSym]() / this.props.PanelWidth(); - const hscale = this.nativeWidth ? 1 : this.layoutDoc[HeightSym]() / this.props.PanelHeight(); - return this.nativeScaling * Math.max(wscale, hscale); - } - public ContentRef = React.createRef(); render() { TraceMobx(); return (
    @@ -74,6 +66,7 @@ export class ContentFittingDocumentView extends React.Component 0.001 ? `${100 * (this.props.PanelWidth() - this.centeringOffset * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth(), }}> this.docView = r)} Document={this.props.Document} DataDoc={this.props.DataDoc} LayoutTemplate={this.props.LayoutTemplate} @@ -81,7 +74,7 @@ export class ContentFittingDocumentView extends React.Component; ContainingCollectionDoc: Opt; docFilters: () => string[]; + contentsActive?: (setActive: () => boolean) => void; docRangeFilters: () => string[]; searchFilterDocs: () => Doc[]; FreezeDimensions?: boolean; @@ -118,7 +119,7 @@ export class DocumentView extends DocComponent(Docu private _holdDisposer?: InteractionUtils.MultiTouchEventDisposer; protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; - private get active() { return SelectionManager.IsSelected(this, true) || this.props.parentActive(true); } + private get active() { return this.isSelected(true) || this.props.parentActive(true); } public get displayName() { return "DocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive public get ContentDiv() { return this._mainCont.current; } public get LayoutFieldKey() { return this.props.layoutKey || Doc.LayoutFieldKey(this.layoutDoc); } @@ -918,11 +919,14 @@ 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; } @computed get contents() { TraceMobx(); - return (
    + return (
    boolean) => void; onClick?: () => ScriptField; dropAction: dropActionType; backgroundHalo?: () => boolean; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index b75cc230f..b04f60500 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -113,6 +113,9 @@ .ProseMirror { padding:10px; } +} +.formattedTextBox-outer-selected { + .ProseMirror:hover { background: unset; } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index fe38939c5..dec81236d 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -810,7 +810,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.dataDoc[UpdatingFromServer] = this.dataDoc[ForceServerWrite] = false; } } + + IsActive = () => { + return this.active();//this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0; + } + componentDidMount() { + this.props.contentsActive?.(this.IsActive); this._cachedLinks = DocListCast(this.Document.links); this._disposers.sidebarheight = reaction( () => ({ annoHeight: NumCast(this.rootDoc[this.annotationKey + "-height"]), textHeight: NumCast(this.rootDoc[this.fieldKey + "-height"]) }), @@ -1622,7 +1628,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const margins = NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0); const selPad = Math.min(margins, 10); const padding = Math.max(margins + ((selected && !this.layoutDoc._singleLine) || minimal ? -selPad : 0), 0); - const selclass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : ""; + const selPaddingClass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : ""; return (
    -
    -
    Date: Sat, 14 Nov 2020 07:55:41 -0500 Subject: refactored treeview code slightly --- src/.DS_Store | Bin 8196 -> 8196 bytes src/client/views/collections/TreeView.tsx | 103 +++++++++++------------------- 2 files changed, 39 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/.DS_Store b/src/.DS_Store index 02618014e..bdc161da2 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 8746e7e0a..4d4531ba8 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -399,41 +399,7 @@ export class TreeView extends React.Component { {this.expandedField}
; } else { - const layoutDoc = this.layoutDoc; - const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.expandPanelHeight; - const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.expandPanelWidth; - return this._dref = r)} - Document={this.doc} - DataDoc={undefined} - LibraryPath={emptyPath} - dontRegisterView={this.props.dontRegisterView} - renderDepth={this.props.renderDepth + 1} - rootSelected={returnTrue} - treeViewDoc={undefined} - backgroundColor={this.props.backgroundColor} - fitToBox={this.isCollectionDoc !== undefined} - FreezeDimensions={true} - NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined} - NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined} - PanelWidth={panelWidth} - PanelHeight={panelHeight} - focus={returnFalse} - ScreenToLocalTransform={this.docTransform} - docFilters={returnEmptyFilter} - docRangeFilters={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={this.props.containingCollection} - ContainingCollectionView={undefined} - addDocument={returnFalse} - moveDocument={this.move} - removeDocument={this.props.removeDoc} - parentActive={this.props.active} - whenActiveChanged={this.props.whenActiveChanged} - addDocTab={this.props.addDocTab} - pinToPres={this.props.pinToPres} - bringToFront={returnFalse} - ContentScaling={returnOne} - />; + return this.renderDocument(false); } } @@ -593,38 +559,47 @@ export class TreeView extends React.Component { ; } + renderDocument = (asText: boolean) => { + const panelWidth = asText || StrCast(Doc.LayoutField(this.layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.expandPanelWidth; + const panelHeight = asText ? this.rtfOutlineHeight : StrCast(Doc.LayoutField(this.layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.expandPanelHeight; + return this._dref = r)} + Document={this.doc} + DataDoc={undefined} + PanelWidth={panelWidth} + PanelHeight={panelHeight} + NativeWidth={!asText && this.layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined} + NativeHeight={!asText && this.layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined} + fitToBox={!asText && this.isCollectionDoc !== undefined} + LayoutTemplateString={asText ? FormattedTextBox.LayoutString("text") : undefined} + focus={asText ? this.refocus : returnFalse} + dontRegisterView={asText ? undefined : this.props.dontRegisterView} + ScreenToLocalTransform={this.docTransform} + LibraryPath={emptyPath} + renderDepth={this.props.renderDepth + 1} + rootSelected={returnTrue} + treeViewDoc={undefined} + backgroundColor={this.props.backgroundColor} + docFilters={returnEmptyFilter} + docRangeFilters={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + ContainingCollectionDoc={this.props.containingCollection} + ContainingCollectionView={undefined} + addDocument={this.props.addDocument} + moveDocument={this.move} + removeDocument={this.props.removeDoc} + parentActive={this.props.active} + whenActiveChanged={this.props.whenActiveChanged} + addDocTab={this.props.addDocTab} + pinToPres={this.props.pinToPres} + bringToFront={returnFalse} + ContentScaling={returnOne} + />; + } + @computed get renderDocumentInHeader() { return <> {this.renderBullet} - this._dref = r)} - Document={this.doc} - DataDoc={undefined} - LayoutTemplateString={FormattedTextBox.LayoutString("text")} - LibraryPath={emptyPath} - renderDepth={this.props.renderDepth + 1} - rootSelected={returnTrue} - treeViewDoc={undefined} - backgroundColor={this.props.backgroundColor} - fitToBox={this.isCollectionDoc !== undefined} - PanelWidth={this.rtfWidth} - PanelHeight={this.rtfOutlineHeight} - focus={this.refocus} - ScreenToLocalTransform={this.docTransform} - docFilters={returnEmptyFilter} - docRangeFilters={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - ContainingCollectionDoc={this.props.containingCollection} - ContainingCollectionView={undefined} - addDocument={this.props.addDocument} - moveDocument={this.move} - removeDocument={this.props.removeDoc} - parentActive={this.props.active} - whenActiveChanged={this.props.whenActiveChanged} - addDocTab={this.props.addDocTab} - pinToPres={this.props.pinToPres} - bringToFront={returnFalse} - ContentScaling={returnOne} - /> + {this.renderDocument(true)} ; } -- cgit v1.2.3-70-g09d2 From c440d2d48ca3ade4f7d3ac0a7f9f54eaacd4074d Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 14 Nov 2020 19:47:17 -0500 Subject: fixed height of autoHeight masonry (tools panel was messed up showing nothing). fixed drag to hide the dragged feedback before hit testing which prevented dragging buttons from working. removed 'dropAction' from removeDropProperties on buttons --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/DragManager.ts | 5 +++-- src/client/views/collections/CollectionStackingView.tsx | 6 +++--- src/client/views/collections/TreeView.tsx | 9 +++++---- 4 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index cae359362..202cd7b1f 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -494,7 +494,7 @@ export class CurrentUserUtils { activeInkPen, backgroundColor, _hideContextMenu: true, - removeDropProperties: new List(["dropAction", "_stayInCollection"]), + removeDropProperties: new List(["_stayInCollection"]), _stayInCollection: true, dragFactory, clickFactory, diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 86e2d339e..e3019d288 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -127,7 +127,6 @@ export namespace DragManager { droppedDocuments: Doc[]; dragDivName?: string; treeViewDoc?: Doc; - dontHideOnDrop?: boolean; offset: number[]; canEmbed?: boolean; userDropAction: dropActionType; // the user requested drop action -- this will be honored as specified by modifier keys @@ -347,6 +346,7 @@ export namespace DragManager { dragDiv.appendChild(dragLabel); DragManager.Root().appendChild(dragDiv); } + dragDiv.hidden = false; dragLabel.style.display = ""; const scaleXs: number[] = []; const scaleYs: number[] = []; @@ -546,13 +546,14 @@ export namespace DragManager { function dispatchDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, xFromLeft: number, yFromTop: number, xFromRight: number, yFromBottom: number, options?: DragOptions, finishDrag?: (e: DragCompleteEvent) => void) { - const removed = dragData.dontHideOnDrop ? [] : dragEles.map(dragEle => { + const removed = dragEles.map(dragEle => { const ret = { ele: dragEle, w: dragEle.style.width, h: dragEle.style.height, o: dragEle.style.overflow }; dragEle.style.width = "0"; dragEle.style.height = "0"; dragEle.style.overflow = "hidden"; return ret; }); + dragDiv.hidden = true; const target = document.elementFromPoint(e.x, e.y); removed.map(r => { r.ele.style.width = r.w; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index cf9ced849..5c28d8969 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -292,9 +292,9 @@ export class CollectionStackingView extends CollectionSubView ind >= oldDocs); + const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= oldDocs); // dropping a document that wasn't in the list or one that creates something new (eg., a button that creates a note) adds a document to the end of the list + const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; // if nothing was added to the end of the list, then presumably the dropped documents were already in the list, but possibly got reordered so we use them. - //de.complete.docDragData.droppedDocuments; const docs = this.childDocList; DragManager.docsBeingDragged = []; if (docs && newDocs.length) { @@ -410,7 +410,7 @@ export class CollectionStackingView extends CollectionSubView { if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0); - Doc.Layout(doc)._height = Math.max(height * NumCast(doc[this.props.fieldKey + "-height"]), NumCast(doc[this.props.fieldKey + "-height"])); + Doc.Layout(doc)._height = Math.max(height, NumCast(doc[this.props.fieldKey + "-height"])); } })); this.observer.observe(ref); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 4d4531ba8..ce13c1d38 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -552,7 +552,8 @@ export class TreeView extends React.Component {
; } - @computed get renderTitleAsText() { + // renders the text version of a document as the header (e.g., useful for Slide views where the "") + @computed get renderTitleAsHeader() { return <> {this.renderBullet} {this.renderTitle} @@ -596,7 +597,7 @@ export class TreeView extends React.Component { />; } - @computed get renderDocumentInHeader() { + @computed get renderDocumentAsHeader() { return <> {this.renderBullet} {this.renderDocument(true)} @@ -635,11 +636,11 @@ export class TreeView extends React.Component { onKeyDown={this.onKeyDown}> {hideTitle ?
  • - {this.renderBulletHeader(this.renderDocumentInHeader)} + {this.renderBulletHeader(this.renderDocumentAsHeader)} {this.renderBorder}
  • :
  • - {this.renderBulletHeader(this.renderTitleAsText)} + {this.renderBulletHeader(this.renderTitleAsHeader)} {this.renderBorder}
  • } -- cgit v1.2.3-70-g09d2 From e0456a5b9f0200dc993baeedfdb3f8b239a13791 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 14 Nov 2020 20:09:16 -0500 Subject: fixed mobx strict run-time exception when opening the presentation trail, then dragging a collection menu item into it. --- .../views/collections/CollectionStackingView.tsx | 2 +- src/client/views/collections/TabDocView.tsx | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 5c28d8969..41e2ad81a 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -292,7 +292,7 @@ export class CollectionStackingView extends CollectionSubView ind >= oldDocs); // dropping a document that wasn't in the list or one that creates something new (eg., a button that creates a note) adds a document to the end of the list + const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= oldDocs); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note). const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; // if nothing was added to the end of the list, then presumably the dropped documents were already in the list, but possibly got reordered so we use them. const docs = this.childDocList; diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 530595cd0..6079b2eb6 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -3,7 +3,7 @@ import { Tooltip } from '@material-ui/core'; import 'golden-layout/src/css/goldenlayout-base.css'; import 'golden-layout/src/css/goldenlayout-dark-theme.css'; import { clamp } from 'lodash'; -import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as ReactDOM from 'react-dom'; import { DataSym, Doc, DocListCast, Opt, DocListCastAsync } from "../../../fields/Doc"; @@ -148,14 +148,16 @@ export class TabDocView extends React.Component { const sublists = DocListCast(dview[fieldKey]); const tabs = Cast(sublists[0], Doc, null); const tabdocs = await DocListCastAsync(tabs.data); - if (!tabdocs?.includes(curPres)) { - tabdocs?.push(curPres); // bcz: Argh! this is annoying. if multiple documents are pinned, this will get called multiple times before the presentation view is drawn. Thus it won't be in the tabdocs list and it will get created multple times. so need to explicilty add the presbox to the list of open tabs - CollectionDockingView.AddSplit(curPres, "right"); - } - PresBox.Instance?._selectedArray.clear(); - pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array - DocumentManager.Instance.jumpToDocument(doc, false, undefined); - batch.end(); + runInAction(() => { + if (!tabdocs?.includes(curPres)) { + tabdocs?.push(curPres); // bcz: Argh! this is annoying. if multiple documents are pinned, this will get called multiple times before the presentation view is drawn. Thus it won't be in the tabdocs list and it will get created multple times. so need to explicilty add the presbox to the list of open tabs + CollectionDockingView.AddSplit(curPres, "right"); + } + PresBox.Instance?._selectedArray.clear(); + pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array + DocumentManager.Instance.jumpToDocument(doc, false, undefined); + batch.end(); + }); } } -- cgit v1.2.3-70-g09d2 From 67435353b39071fbe3295cc80e35ee3df952f082 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 19 Nov 2020 10:11:29 -0500 Subject: made inkingStroke honor _isBackground. prevented link anchor dots from moving when target isn't visible. made ui option for showing/hiding link lines and for autoMoving anchor dots. --- src/client/views/InkingStroke.tsx | 6 ++-- .../CollectionFreeFormLinkView.tsx | 15 ++++++---- src/client/views/linking/LinkMenuItem.tsx | 34 ++++++++++++++++++---- 3 files changed, 41 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 7e424d8f0..5fd9d5fe4 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, "", "visiblepainted", false, true); + "none", "none", undefined, scaleX, scaleY, "", this.props.Document._isBackground ? "none" : "visiblepainted", false, true); //points for adding const apoints = InteractionUtils.CreatePoints(data, left, top, strokeColor, strokeWidth, strokeWidth, @@ -178,7 +178,7 @@ export class InkingStroke extends ViewBoxBaseComponent this.onControlDown(e, pts.I)} pointerEvents="all" cursor="all-scroll" display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} /> ); const handleLines = handleLine.map((pts, i) => - + @@ -191,7 +191,7 @@ export class InkingStroke extends ViewBoxBaseComponent this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. + if (!linkDoc.linkAutoMove) return; const acont = A.props.Document.type === DocumentType.LINK ? A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; const bcont = B.props.Document.type === DocumentType.LINK ? B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; const adiv = (acont.length ? acont[0] : A.ContentDiv); @@ -60,6 +61,7 @@ export class CollectionFreeFormLinkView extends React.Component ele.dataset.targetids?.includes((linkDoc[afield] as Doc)[Id])); const targetBhyperlink = linkEles.find((ele: any) => ele.dataset.targetids?.includes((linkDoc[bfield] as Doc)[Id])); + if ((!targetAhyperlink && !a.width) || (!targetBhyperlink && !b.width)) return; if (!targetBhyperlink) { A.rootDoc[afield + "_x"] = (apt.point.x - aleft) / awidth * 100; A.rootDoc[afield + "_y"] = (apt.point.y - atop) / aheight * 100; @@ -101,8 +103,8 @@ export class CollectionFreeFormLinkView extends React.Component { @undoBatch @action - showLink = () => { - this.props.linkDoc.hidden = !this.props.linkDoc.hidden; + autoMove = (e: React.PointerEvent) => { + e.stopPropagation(); + this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove; } - render() { + @undoBatch + @action + showLink = (e: React.PointerEvent) => { + e.stopPropagation(); + this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay; + } - const eyeIcon = this.props.linkDoc.hidden ? "eye-slash" : "eye"; + @undoBatch + @action + showAnchor = (e: React.PointerEvent) => { + e.stopPropagation(); + this.props.linkDoc.hidden = !this.props.linkDoc.hidden; + } + render() { let destinationIcon: FontAwesomeIconProps["icon"] = "question"; switch (this.props.destinationDoc.type) { case DocumentType.IMG: destinationIcon = "image"; break; @@ -243,9 +255,19 @@ export class LinkMenuItem extends React.Component {
    -
    {this.props.linkDoc.hidden ? "Show link" : "Hide link"}
    }> +
    {this.props.linkDoc.hidden ? "Show Anchor" : "Hide Anchor"}
    }> +
    +
    +
    + +
    {!this.props.linkDoc.linkDisplay ? "Show link" : "Hide link"}
    }>
    -
    +
    + + +
    {!this.props.linkDoc.linkAutoMove ? "Auto move dot" : "Freeze dot position"}
    }> +
    +
    Edit Link
    }> -- cgit v1.2.3-70-g09d2 From 0a0f408b5319d7c8dea747907b4c6f5e8f012dec Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 19 Nov 2020 13:09:17 -0500 Subject: fixed singleLine text to not show scroll bars. made Ink honor _isBackground. --- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4485c744d..f6262310f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1097,7 +1097,7 @@ 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.COL && this.Document._viewType !== CollectionViewType.Pile) || this.Document.type === DocumentType.IMG || this.Document.type === DocumentType.INK) && this.props.renderDepth > 0 && !this.props.treeViewDoc ?
    diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index dec81236d..8fc8fb402 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1672,11 +1672,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp onDoubleClick={this.onDoubleClick} >
    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) :
    Date: Sat, 21 Nov 2020 10:47:47 -0500 Subject: turned off automatic loading of non-active tabs. fixed placement of contentfittingview content for link preview of web/pdf etc (was vertically displaced). turned off javascript in webBox's. --- src/client/views/collections/TabDocView.tsx | 9 ++++++--- src/client/views/nodes/ContentFittingDocumentView.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 76efe7ec9..471cc639e 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -40,6 +40,7 @@ interface TabDocViewProps { export class TabDocView extends React.Component { _mainCont: HTMLDivElement | null = null; _tabReaction: IReactionDisposer | undefined; + @observable _activated: boolean = false; @observable private _panelWidth = 0; @observable private _panelHeight = 0; @@ -53,6 +54,7 @@ export class TabDocView extends React.Component { @action init = (tab: any, doc: Opt) => { + if (tab.contentItem === tab.header.parent.getActiveContentItem()) this._activated = true; if (tab.DashDoc !== doc && doc && tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") { tab._disposers = {} as { [name: string]: IReactionDisposer }; tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true); @@ -109,13 +111,14 @@ export class TabDocView extends React.Component { } }; tab._disposers.selectionDisposer = reaction(() => SelectionManager.SelectedDocuments().some(v => (v.topMost || v.props.treeViewDoc) && v.props.Document === doc), - (selected) => { + action((selected) => { + if (selected) this._activated = true; 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; @@ -403,7 +406,7 @@ export class TabDocView extends React.Component { } @computed get docView() { TraceMobx(); - return !this._document || this._document._viewType === CollectionViewType.Docking ? (null) : + return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? (null) : <> this.props.ScreenToLocalTransform(). 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; } + private get centeringYOffset() { return this.nativeWidth && Math.abs(this.centeringOffset) < 0.001 && this.nativeHeight ? (this.props.PanelHeight() - this.nativeHeight * this.nativeScaling) / 2 : 0; } @computed get borderRounding() { return StrCast(this.props.Document?.borderRounding); } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index ab97f9f7e..2818ef5c4 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -442,7 +442,8 @@ export class WebBox extends ViewBoxAnnotatableComponent this._iframe = r)} src={url} onLoad={this.iframeLoaded} // the 'allow-top-navigation' and 'allow-top-navigation-by-user-activation' attributes are left out to prevent iframes from redirecting the top-level Dash page - sandbox={"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts"} />; + // sandbox={"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts"} />; + sandbox={"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin"} />; } else { view =