From 4196252bbd1b34bcf7a25da923aadee70f66c5cf Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 28 Oct 2021 12:22:16 -0400 Subject: added rudimentary ability to select link lines --- .../collections/collectionFreeForm/CollectionFreeFormLinkView.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index bb4cae8c6..86f659868 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -5,13 +5,12 @@ import { Id } from "../../../../fields/FieldSymbols"; import { List } from "../../../../fields/List"; import { NumCast } from "../../../../fields/Types"; import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; -import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; import { LinkManager } from "../../../util/LinkManager"; -import { ColorScheme } from "../../../util/SettingsManager"; import { SnappingManager } from "../../../util/SnappingManager"; import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); +import { SelectionManager } from "../../../util/SelectionManager"; export interface CollectionFreeFormLinkViewProps { @@ -199,7 +198,8 @@ export class CollectionFreeFormLinkView extends React.Component - SelectionManager.SelectSchemaViewDoc(this.props.LinkDocs[0])} d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} /> {textX === undefined ? (null) : {Field.toString(this.props.LinkDocs[0].description as any as Field)} -- cgit v1.2.3-70-g09d2 From a5ea9777ced363e267743e8758d48b7e354b170b Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 28 Oct 2021 12:27:14 -0400 Subject: from last --- .../views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 86f659868..07b4789e7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -6,11 +6,11 @@ import { List } from "../../../../fields/List"; import { NumCast } from "../../../../fields/Types"; import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; import { LinkManager } from "../../../util/LinkManager"; +import { SelectionManager } from "../../../util/SelectionManager"; import { SnappingManager } from "../../../util/SnappingManager"; import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); -import { SelectionManager } from "../../../util/SelectionManager"; export interface CollectionFreeFormLinkViewProps { -- cgit v1.2.3-70-g09d2 From 2d96f9a25de2d3996a8663b4f459d3f482d51398 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 28 Oct 2021 12:35:33 -0400 Subject: selection of link lines deselects everything else first. --- src/client/util/SelectionManager.ts | 3 ++- .../collections/collectionFreeForm/CollectionFreeFormLinkView.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index dbe7b3ebc..2cba2c1f2 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -57,7 +57,8 @@ export namespace SelectionManager { export function SelectView(docView: DocumentView, ctrlPressed: boolean): void { manager.SelectView(docView, ctrlPressed); } - export function SelectSchemaViewDoc(document: Opt): void { + export function SelectSchemaViewDoc(document: Opt, deselectAllFirst?: boolean): void { + if (deselectAllFirst) manager.DeselectAll(); manager.SelectSchemaViewDoc(document); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 07b4789e7..9769453a0 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -199,7 +199,7 @@ export class CollectionFreeFormLinkView extends React.Component SelectionManager.SelectSchemaViewDoc(this.props.LinkDocs[0])} + onClick={() => SelectionManager.SelectSchemaViewDoc(this.props.LinkDocs[0], true)} d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} /> {textX === undefined ? (null) : {Field.toString(this.props.LinkDocs[0].description as any as Field)} -- cgit v1.2.3-70-g09d2 From 0691dc220f52643f4fd5fa9a29a5c52ef59321aa Mon Sep 17 00:00:00 2001 From: Lauren Choi Date: Fri, 29 Oct 2021 10:30:48 -0400 Subject: toggle properties on selection --- src/client/util/SelectionManager.ts | 4 + src/client/views/PropertiesView.tsx | 88 ++++++++++++++++++---- .../CollectionFreeFormLinkView.tsx | 23 +++++- 3 files changed, 99 insertions(+), 16 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 2cba2c1f2..6674f684d 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -4,6 +4,7 @@ import { Doc, Opt } from "../../fields/Doc"; import { DocumentType } from "../documents/DocumentTypes"; import { CollectionViewType } from "../views/collections/CollectionView"; import { DocumentView } from "../views/nodes/DocumentView"; +import { CurrentUserUtils } from "./CurrentUserUtils"; export namespace SelectionManager { @@ -43,6 +44,9 @@ export namespace SelectionManager { } @action DeselectAll(): void { + if (CurrentUserUtils.propertiesWidth > 0) { + CurrentUserUtils.propertiesWidth = 0; + } manager.SelectedSchemaDocument = undefined; Array.from(manager.SelectedViews.keys()).map(dv => dv.props.whenChildContentsActiveChanged(false)); manager.SelectedViews.clear(); diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index ab9022a84..334a44b3b 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -57,6 +57,9 @@ export class PropertiesView extends React.Component { @computed get isPres(): boolean { return this.selectedDoc?.type === DocumentType.PRES; } + @computed get isLink(): boolean { + return this.selectedDoc?.type === DocumentType.LINK; + } @computed get dataDoc() { return this.selectedDoc?.[DataSym]; } @observable layoutFields: boolean = false; @@ -146,8 +149,8 @@ export class PropertiesView extends React.Component { if (key[0] === "#") { rows.push(
{key} -   -
); +   + ); } else { const contentElement = { rows.push(
{key + ":"} -   - {contentElement} +   + {contentElement}
); } } @@ -855,7 +858,7 @@ export class PropertiesView extends React.Component { onPointerDown={action(() => this.openOptions = !this.openOptions)} style={{ backgroundColor: this.openOptions ? "black" : "" }}> Options -
+
@@ -872,7 +875,7 @@ export class PropertiesView extends React.Component { onPointerDown={action(() => this.openSharing = !this.openSharing)} style={{ backgroundColor: this.openSharing ? "black" : "" }}> Sharing {"&"} Permissions -
+
@@ -948,7 +951,7 @@ export class PropertiesView extends React.Component { onPointerDown={action(() => this.openFilters = !this.openFilters)} style={{ backgroundColor: this.openFilters ? "black" : "" }}> Filters -
+
@@ -997,7 +1000,7 @@ export class PropertiesView extends React.Component { onPointerDown={action(() => this.openAppearance = !this.openAppearance)} style={{ backgroundColor: this.openAppearance ? "black" : "" }}> Appearance -
+
@@ -1012,7 +1015,7 @@ export class PropertiesView extends React.Component { onPointerDown={action(() => this.openTransform = !this.openTransform)} style={{ backgroundColor: this.openTransform ? "black" : "" }}> Transform -
+
@@ -1029,7 +1032,7 @@ export class PropertiesView extends React.Component { onPointerDown={action(() => this.openFields = !this.openFields)} style={{ backgroundColor: this.openFields ? "black" : "" }}> Fields {"&"} Tags -
+
@@ -1050,7 +1053,7 @@ export class PropertiesView extends React.Component { onPointerDown={action(() => this.openContexts = !this.openContexts)} style={{ backgroundColor: this.openContexts ? "black" : "" }}> Contexts -
+
@@ -1064,7 +1067,7 @@ export class PropertiesView extends React.Component { onPointerDown={action(() => this.openLayout = !this.openLayout)} style={{ backgroundColor: this.openLayout ? "black" : "" }}> Layout -
+
@@ -1072,6 +1075,14 @@ export class PropertiesView extends React.Component { ; } + toggleAnchor = () => { + this.selectedDoc.anchor = !this.selectedDoc.anchor + } + + toggleArrow = () => { + this.selectedDoc.arrow = !this.selectedDoc.arrow + } + /** @@ -1095,6 +1106,57 @@ export class PropertiesView extends React.Component { ; } else { + if (this.selectedDoc && this.isLink) { + return
+
+ Linking +
+
+ Information +
+

Label

+ +
+
+

Label

+ +
+
+

Description

+ +
+
+
+ Behavior +
+ Follow + +
+
+ Auto-move anchor +
+
+ Auto-move arrow +
+
+
; + } if (this.selectedDoc && !this.isPres) { return
{ onPointerDown={action(() => { this.openPresTransitions = !this.openPresTransitions; })} style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}>     Transitions -
+
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 9769453a0..d4ef76221 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -11,6 +11,7 @@ import { SnappingManager } from "../../../util/SnappingManager"; import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); +import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; export interface CollectionFreeFormLinkViewProps { @@ -138,6 +139,20 @@ export class CollectionFreeFormLinkView extends React.Component { + if (CurrentUserUtils.propertiesWidth > 0) { + CurrentUserUtils.propertiesWidth = 0; + } else { + CurrentUserUtils.propertiesWidth = 250; + } + } + + onClickLine = () => { + SelectionManager.SelectSchemaViewDoc(this.props.LinkDocs[0], true) + this.toggleProperties() + } + @computed.struct get renderData() { this._start; SnappingManager.GetIsDragging(); const { A, B, LinkDocs } = this.props; @@ -198,9 +213,11 @@ export class CollectionFreeFormLinkView extends React.Component - SelectionManager.SelectSchemaViewDoc(this.props.LinkDocs[0], true)} - d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} /> + { + console.log(this.props.LinkDocs[0].directed) + }} /> {textX === undefined ? (null) : {Field.toString(this.props.LinkDocs[0].description as any as Field)} } -- cgit v1.2.3-70-g09d2 From 428b90b9e2e902b82f3406a5062f8be6950f4862 Mon Sep 17 00:00:00 2001 From: Lauren Choi Date: Fri, 29 Oct 2021 12:05:28 -0400 Subject: style properties panel --- src/client/views/PropertiesView.scss | 38 ++++++++++++++++++++ src/client/views/PropertiesView.tsx | 40 +++++++++++----------- .../CollectionFreeFormLinkView.tsx | 4 +-- 3 files changed, 59 insertions(+), 23 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index 554f137cb..b75e7182c 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -2,6 +2,7 @@ .propertiesView { height: 100%; + width: 250; font-family: "Roboto"; cursor: auto; @@ -836,3 +837,40 @@ .properties-flyout { grid-column: 2/4; } + +.propertiesView-linking { + padding: 5%; +} + +.propertiesView-section { + padding: 10px 0; +} + +.propertiesView-input { + padding: 4px 8px; + + .text { + width: 100%; + } + + &.first { + padding-top: 6px; + } + + &.inline { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + } +} + +.propertiesView-label { + font-weight: bold; + font-size: 12.5px; + padding: 4px; + display: flex; + color: white; + padding-left: 8px; + background-color: rgb(51, 51, 51); +} \ No newline at end of file diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 334a44b3b..b5bae6652 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1111,25 +1111,25 @@ export class PropertiesView extends React.Component {
Linking
-
- Information -
+
+

Information

+

Label

- +
-
-

Label

- +
+

Category

+
-
+

Description

- +
-
- Behavior -
- Follow +
+

Behavior

+
+

Follow

-
- Auto-move anchor +
+

Auto-move anchor

-
- Auto-move arrow +
+

Auto-move arrow

-
; +
; } if (this.selectedDoc && !this.isPres) { return
{ - console.log(this.props.LinkDocs[0].directed) - }} /> + d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} /> {textX === undefined ? (null) : {Field.toString(this.props.LinkDocs[0].description as any as Field)} } -- cgit v1.2.3-70-g09d2 From 6a8eee54689f4bbe24c884895e0d2af1f06c4aad Mon Sep 17 00:00:00 2001 From: Lauren Choi Date: Thu, 4 Nov 2021 14:20:58 -0400 Subject: change color of line, remove input --- src/client/views/PropertiesView.tsx | 6 +----- .../collections/collectionFreeForm/CollectionFreeFormLinkView.tsx | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 301936219..d65db3a6b 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1157,11 +1157,7 @@ export class PropertiesView extends React.Component {

Information

-
-

Label

- -
-
+

Category

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 5391061b1..9d256f18b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -12,6 +12,7 @@ import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; +import { Colors } from "../../global/globalEnums"; export interface CollectionFreeFormLinkViewProps { @@ -213,7 +214,7 @@ export class CollectionFreeFormLinkView extends React.Component - {textX === undefined ? (null) : -- cgit v1.2.3-70-g09d2 From dcd2fd6f3030f7b57000536005f6005a0abaa482 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 8 Nov 2021 12:14:31 -0500 Subject: fixed dragging snap lines to get recomputed properly (sometimes they didn't activate before) and fixed snapping to not be off by 1 screen space pixel --- .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 8 +++----- src/client/views/nodes/DocumentView.tsx | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index febccbfcc..37caf508f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -146,7 +146,7 @@ export class CollectionFreeFormView extends CollectionSubView this._keyframeEditing = set; @@ -169,7 +169,6 @@ export class CollectionFreeFormView extends CollectionSubView this.cachedGetTransform.copy(); getLocalTransform = () => this.cachedGetLocalTransform.copy(); getContainerTransform = () => this.cachedGetContainerTransform.copy(); - getTransformOverlay = () => this.getContainerTransform().translate(1, 1); getActiveDocuments = () => this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout); isAnyChildContentActive = () => this.props.isAnyChildContentActive(); addLiveTextBox = (newBox: Doc) => { @@ -221,7 +220,7 @@ export class CollectionFreeFormView extends CollectionSubView { - (DocumentDecorations.Instance.Interacting || (this.props.layerProvider?.(this.props.Document) !== false && SnappingManager.GetIsDragging())) && this.setupDragLines(e.ctrlKey || e.shiftKey); e.stopPropagation(); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c9b246c10..6c058ff97 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -415,6 +415,7 @@ export class DocumentViewInternal extends DocComponent (ffview.ChildDrag = this.props.DocumentView())); DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart) }, () => setTimeout(action(() => ffview && (ffview.ChildDrag = undefined)))); // this needs to happen after the drop event is processed. + ffview?.setupDragLines(false); } } -- cgit v1.2.3-70-g09d2 From 8f0353357f58ada81b40bd76d1958e35cbe21ea0 Mon Sep 17 00:00:00 2001 From: Lauren Choi Date: Tue, 9 Nov 2021 15:10:48 -0500 Subject: added arrowhead --- .../CollectionFreeFormLinkView.tsx | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 9d256f18b..27a34a9fa 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -154,6 +154,25 @@ export class CollectionFreeFormLinkView extends React.Component { + let hex = c.toString(16); + return hex.length == 1 ? "0" + hex : hex; + } + + rgbToHex = (rgbString: string) => { + let rgbVals = [] + for (let i = 0; i < rgbString.length; i++) { + if (parseInt(rgbString[i])) { + let curr = '' + while (parseInt(rgbString[i]) != NaN) { + curr += (rgbString[i]) + } + rgbVals.push(parseInt(curr)) + } + } + return "#" + this.componentToHex(rgbVals[0]) + this.componentToHex(rgbVals[1]) + this.componentToHex(rgbVals[2]); + } + @computed.struct get renderData() { this._start; SnappingManager.GetIsDragging(); const { A, B, LinkDocs } = this.props; @@ -208,15 +227,24 @@ export class CollectionFreeFormLinkView extends React.Component= linkColorList.length ? "black" : linkColorList[currRelationshipIndex]; + console.log(stroke) + console.log(this.rgbToHex(stroke)) //calculate stroke width/thickness based on the relative importance of the relationshipship (i.e. how many links the relationship has) //thickness varies linearly from 3px to 12px for increasing link count const strokeWidth = linkSize === -1 ? "3px" : Math.floor(2 + 10 * (linkSize / Math.max(...linkRelationshipSizes))) + "px"; return !a.width || !b.width || ((!this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<> + + + + + + d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`} + marker-end="url(#arrowhead)" /> {textX === undefined ? (null) : {Field.toString(this.props.LinkDocs[0].description as any as Field)} } -- cgit v1.2.3-70-g09d2 From fc9d892e1ae344bf12b5bc3fc7ff0fb5867d7dba Mon Sep 17 00:00:00 2001 From: Lauren Choi Date: Thu, 11 Nov 2021 15:53:16 -0500 Subject: color arrow head --- .../CollectionFreeFormLinkView.tsx | 25 +++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 27a34a9fa..43f181849 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -160,17 +160,17 @@ export class CollectionFreeFormLinkView extends React.Component { - let rgbVals = [] - for (let i = 0; i < rgbString.length; i++) { - if (parseInt(rgbString[i])) { - let curr = '' - while (parseInt(rgbString[i]) != NaN) { - curr += (rgbString[i]) + if (rgbString != "black") { + const splitString = rgbString.split(/rgb|\(|\)|,| /) + let values: number[] = [] + splitString.forEach(elt => { + if (elt) { + values.push(parseInt(elt)) } - rgbVals.push(parseInt(curr)) - } + }) + return "#" + this.componentToHex(values[0]) + this.componentToHex(values[1]) + this.componentToHex(values[2]); } - return "#" + this.componentToHex(rgbVals[0]) + this.componentToHex(rgbVals[1]) + this.componentToHex(rgbVals[2]); + return "#000000" } @computed.struct get renderData() { @@ -227,8 +227,7 @@ export class CollectionFreeFormLinkView extends React.Component= linkColorList.length ? "black" : linkColorList[currRelationshipIndex]; - console.log(stroke) - console.log(this.rgbToHex(stroke)) + const hexStroke = this.rgbToHex(stroke) //calculate stroke width/thickness based on the relative importance of the relationshipship (i.e. how many links the relationship has) //thickness varies linearly from 3px to 12px for increasing link count @@ -238,13 +237,13 @@ export class CollectionFreeFormLinkView extends React.Component - + + markerEnd="url(#arrowhead)" /> {textX === undefined ? (null) : {Field.toString(this.props.LinkDocs[0].description as any as Field)} } -- cgit v1.2.3-70-g09d2 From 3381bbb0ef5160707513f4bbbe551ca551b64b0d Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 13 Nov 2021 10:38:53 -0500 Subject: change isContentActive to a tri-state to allow turning on/off and default - fixes issues with videobox and others so that content can be turned off reliably. added annotation overlay for treeViews for ppt like slides. lots of fixes to tree view to get layout to be more robust. --- src/Utils.ts | 2 +- src/client/documents/Documents.ts | 4 +- src/client/util/CurrentUserUtils.ts | 20 +- src/client/views/DocComponent.tsx | 18 +- src/client/views/DocumentDecorations.scss | 6 +- src/client/views/DocumentDecorations.tsx | 27 +-- src/client/views/MainView.tsx | 6 +- src/client/views/OverlayView.tsx | 2 +- src/client/views/Palette.tsx | 2 +- src/client/views/PropertiesView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 7 +- .../views/collections/CollectionTreeView.scss | 9 + .../views/collections/CollectionTreeView.tsx | 252 ++++++++++++--------- src/client/views/collections/CollectionView.tsx | 12 +- src/client/views/collections/TabDocView.tsx | 3 +- src/client/views/collections/TreeView.scss | 7 +- src/client/views/collections/TreeView.tsx | 49 ++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 10 +- .../CollectionMulticolumnView.tsx | 4 +- .../CollectionMultirowView.tsx | 4 +- .../collectionMulticolumn/MulticolumnResizer.tsx | 2 +- .../collectionMulticolumn/MultirowResizer.tsx | 2 +- .../collectionSchema/CollectionSchemaHeaders.tsx | 2 +- .../collections/collectionSchema/SchemaTable.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 10 +- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/FilterBox.tsx | 2 +- src/client/views/nodes/LinkBox.tsx | 2 +- src/client/views/nodes/LinkDocPreview.tsx | 2 +- src/client/views/nodes/ScreenshotBox.tsx | 2 +- src/client/views/nodes/VideoBox.scss | 10 +- src/client/views/nodes/VideoBox.tsx | 11 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 18 +- src/mobile/AudioUpload.tsx | 2 +- src/mobile/MobileInterface.tsx | 2 +- 36 files changed, 298 insertions(+), 221 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm') diff --git a/src/Utils.ts b/src/Utils.ts index bfb29fe8d..ca1432de2 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -448,7 +448,7 @@ export function returnEmptyDoclist() { return [] as any[]; } export let emptyPath = []; -export function emptyFunction() { } +export function emptyFunction() { return undefined; } export function unimplementedFunction() { throw new Error("This function is not implemented, but should be."); } diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index da5c8efa9..219f51a3a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -94,6 +94,7 @@ type DROPt = DAInfo | dropActionType; export class DocumentOptions { system?: BOOLt = new BoolInfo("is this a system created/owned doc"); _dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else"); + allowOverlayDrop?: BOOLt = new BoolInfo("can documents be dropped onto this document without using dragging title bar or holding down embed key (ctrl)?"); childDropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto a child of a collection "); targetDropAction?: DROPt = new DAInfo("what should happen to the source document when ??? "); color?: string; // foreground color data doc @@ -289,6 +290,7 @@ export class DocumentOptions { treeViewExpandedViewLock?: boolean; // whether the expanded view can be changed treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked treeViewTruncateTitleWidth?: number; + treeViewHasOverlay?: boolean; // whether the treeview has an overlay for freeform annotations treeViewType?: string; // whether treeview is a Slide, file system, or (default) collection hierarchy sidebarColor?: string; // background color of text sidebar sidebarViewType?: string; // collection type of text sidebar @@ -821,7 +823,7 @@ export namespace Docs { } export function TreeDocument(documents: Array, options: DocumentOptions, id?: string, protoId?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Tree }, id, undefined, protoId); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xMargin: 5, _yMargin: 5, ...options, _viewType: CollectionViewType.Tree }, id, undefined, protoId); } export function StackingDocument(documents: Array, options: DocumentOptions, id?: string, protoId?: string) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 9d06ad8a3..c9bef5924 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -339,7 +339,7 @@ export class CurrentUserUtils { const clickTemplates = CurrentUserUtils.setupClickEditorTemplates(doc); if (doc.templateDocs === undefined) { doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([noteTemplates, userTemplateBtns, clickTemplates], { - title: "template layouts", _xPadding: 0, system: true, + title: "template layouts", _xMargin: 0, system: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }) })); } @@ -421,7 +421,11 @@ export class CurrentUserUtils { ((doc.emptyPane as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptySlide === undefined) { - const textDoc = Docs.Create.TreeDocument([], { title: "Slide", _viewType: CollectionViewType.Tree, _fontSize: "20px", _autoHeight: true, treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true, backgroundColor: "transparent", system: true, cloneFieldFilter: new List(["system"]) }); + const textDoc = Docs.Create.TreeDocument([], { + title: "Slide", _viewType: CollectionViewType.Tree, treeViewHasOverlay: true, _fontSize: "20px", _autoHeight: true, + allowOverlayDrop: true, treeViewType: "outline", _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'); FormattedTextBox.SelectOnLoad = textDoc[Id]; doc.emptySlide = textDoc; @@ -811,7 +815,7 @@ export class CurrentUserUtils { const newDashboardButton: Doc = Docs.Create.FontIconDocument({ onClick: newDashboard, _forceActive: true, toolTip: "Create new dashboard", _stayInCollection: true, _hideContextMenu: true, title: "new dashboard", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Dashboards", _showTitle: "title", _height: 400, childHideLinkButton: true, freezeChildren: "remove|add", - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newDashboardButton, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: "fileSystem", isFolder: true, system: true, explainer: "This is your collection of dashboards. A dashboard represents the tab configuration of your workspace. To manage documents as folders, go to the Files." @@ -840,7 +844,7 @@ export class CurrentUserUtils { const newTrailButton: Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "Create new trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); doc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Trails", _showTitle: "title", _height: 100, - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newTrailButton, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, explainer: "All of the trails that you have created will appear here." @@ -865,7 +869,7 @@ export class CurrentUserUtils { }); doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileOrphans as Doc], { title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true, @@ -884,7 +888,7 @@ export class CurrentUserUtils { const clearDocsButton: Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true }); doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Recently Closed", _showTitle: "title", buttonMenu: true, buttonMenuDoc: clearDocsButton, childHideLinkButton: true, - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewHideTitle: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, explainer: "Recently closed documents appear in this menu. They will only be deleted if you explicity empty this list." @@ -902,7 +906,7 @@ export class CurrentUserUtils { if (doc.currentFilter === undefined) { doc.currentFilter = Docs.Create.FilterDocument({ title: "Unnamed Filter", _height: 150, - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "none", + treeViewHideTitle: true, _xPadding: 5, _yPadding: 5, _gridGap: 5, _forceActive: true, childDropAction: "none", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, _autoHeight: true, _fitWidth: true }); @@ -918,7 +922,7 @@ export class CurrentUserUtils { doc.treeViewOpen = true; doc.treeViewExpandedView = "fields"; doc.myUserDoc = new PrefetchProxy(Docs.Create.TreeDocument([doc], { - treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, title: "My UserDoc", _showTitle: "title", + treeViewHideTitle: true, _gridGap: 5, _forceActive: true, title: "My UserDoc", _showTitle: "title", treeViewTruncateTitleWidth: 150, ignoreClick: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true })) as any as Doc; diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 32c351bf5..b9772fd57 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -44,7 +44,7 @@ interface ViewBoxBaseProps { fieldKey: string; layerProvider?: (doc: Doc, assign?: boolean) => boolean; isSelected: (outsideReaction?: boolean) => boolean; - isContentActive: () => boolean; + isContentActive: () => boolean | undefined; renderDepth: number; rootSelected: (outsideReaction?: boolean) => boolean; } @@ -65,10 +65,12 @@ 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; - isContentActive = (outsideReaction?: boolean) => (CurrentUserUtils.SelectedTool !== InkTool.None || - (this.props.isContentActive?.() || this.props.Document.forceActive || - this.props.isSelected(outsideReaction) || - this.props.rootSelected(outsideReaction)) ? true : false) + isContentActive = (outsideReaction?: boolean) => ( + this.props.isContentActive?.() === false ? false : + (CurrentUserUtils.SelectedTool !== InkTool.None || + (this.props.isContentActive?.() || this.props.Document.forceActive || + this.props.isSelected(outsideReaction) || + this.props.rootSelected(outsideReaction)) ? true : undefined)) protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; } return Component; @@ -82,7 +84,7 @@ export interface ViewBoxAnnotatableProps { fieldKey: string; filterAddDocument?: (doc: Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) layerProvider?: (doc: Doc, assign?: boolean) => boolean; - isContentActive: () => boolean; + isContentActive: () => boolean | undefined; select: (isCtrlPressed: boolean) => void; whenChildContentsActiveChanged: (isActive: boolean) => void; isSelected: (outsideReaction?: boolean) => boolean; @@ -165,13 +167,13 @@ export function ViewBoxAnnotatableComponent

boolean, annotationKey?: string): boolean => { + moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string): boolean => { if (Doc.AreProtosEqual(this.props.Document, targetCollection)) { return true; } const first = doc instanceof Doc ? doc : doc[0]; if (!first?._stayInCollection && addDocument !== returnFalse) { - return UndoManager.RunInTempBatch(() => this.removeDocument(doc, annotationKey, true) && addDocument(doc)); + return UndoManager.RunInTempBatch(() => this.removeDocument(doc, annotationKey, true) && addDocument(doc, annotationKey)); } return false; } diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index d8ad47ecb..82dca1287 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -240,8 +240,10 @@ $linkGap: 3px; text-align: center; display: flex; margin-left: 5px; - height: 22px; + height: 20px; position: absolute; + border-radius: 8px; + background: rgba(159,159,159,0.1); .documentDecorations-titleSpan, .documentDecorations-titleSpan-Dark { @@ -288,7 +290,7 @@ $linkGap: 3px; text-align: center; display: flex; margin-left: 5px; - height: 22px; + height: 20px; position: absolute; .documentDecorations-titleSpan { width: 100%; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 522995479..1c0b1b995 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -454,17 +454,18 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P ); const colorScheme = StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme); - const titleArea = this._edtingTitle ? - this.titleBlur()} - onChange={action(e => this._accumulatedTitle = e.target.value)} - onKeyPress={this.titleEntered} /> : -

- {`${this.selectionTitle}`} -
; + const titleArea = hideTitle ?
: + this._edtingTitle ? + this.titleBlur()} + onChange={action(e => this._accumulatedTitle = e.target.value)} + onKeyPress={this.titleEntered} /> : +
+ {`${this.selectionTitle}`} +
; let inMainMenuPanel = false; for (let node = seldoc.ContentDiv; node && !inMainMenuPanel; node = node?.parentNode as any) { @@ -498,8 +499,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight, }}> {!canDelete ?
: topBtn("close", "times", undefined, this.onCloseClick, "Close")} - {hideTitle ? (null) : titleArea}{!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")} - + {titleArea} + {!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")} {hideResizers ? (null) : <> {SelectionManager.Views().length !== 1 || hideTitle ? (null) : diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 9a885fbf8..546b0e360 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -511,7 +511,7 @@ export class MainView extends React.Component { bringToFront={emptyFunction} select={emptyFunction} isAnyChildContentActive={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} isSelected={returnFalse} docViewPath={returnEmptyDoclist} moveDocument={this.moveButtonDoc} @@ -592,7 +592,7 @@ export class MainView extends React.Component { pinToPres={returnFalse} ScreenToLocalTransform={Transform.Identity} bringToFront={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} whenChildContentsActiveChanged={returnFalse} focus={returnFalse} docViewPath={returnEmptyDoclist} @@ -669,7 +669,7 @@ export class MainView extends React.Component { pinToPres={returnFalse} ScreenToLocalTransform={Transform.Identity} bringToFront={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} whenChildContentsActiveChanged={returnFalse} focus={returnFalse} PanelWidth={() => 500} diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index af04b967a..7cf388872 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -191,7 +191,7 @@ export class OverlayView extends React.Component { ScreenToLocalTransform={Transform.Identity} renderDepth={1} isDocumentActive={returnTrue} - isContentActive={returnFalse} + isContentActive={emptyFunction} whenChildContentsActiveChanged={emptyFunction} focus={DocUtils.DefaultFocus} styleProvider={DefaultStyleProvider} diff --git a/src/client/views/Palette.tsx b/src/client/views/Palette.tsx index 86ab881bb..529697f71 100644 --- a/src/client/views/Palette.tsx +++ b/src/client/views/Palette.tsx @@ -50,7 +50,7 @@ export default class Palette extends React.Component { PanelHeight={() => window.screen.height} renderDepth={0} isDocumentActive={returnTrue} - isContentActive={returnFalse} + isContentActive={emptyFunction} focus={emptyFunction} docViewPath={returnEmptyDoclist} styleProvider={returnEmptyString} diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index ab9022a84..1083e0075 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -295,7 +295,7 @@ export class PropertiesView extends React.Component { freezeDimensions={true} dontCenter={"y"} isDocumentActive={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} 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/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 648ff5087..bffaf86b1 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -226,7 +226,7 @@ export class CollectionStackingView extends CollectionSubView; - SetSubView?: (subView: any) => void; isAnyChildContentActive: () => boolean; } @@ -49,10 +48,6 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: this.createDashEventsTarget(ele); } - componentDidMount() { - this.props.SetSubView?.(this); - } - componentWillUnmount() { this.gestureDisposer?.(); this._multiTouchDisposer?.(); @@ -220,7 +215,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d); const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d); if (movedDocs.length) { - const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || !this.props.isAnnotationOverlay || + const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || (!this.props.isAnnotationOverlay || this.props.Document.allowOverlayDrop) || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document); added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.addDocument : returnFalse); } else { diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index d370d21ab..b664d9d82 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -71,6 +71,15 @@ display: none; } +.collectionTreeView-titleBar { + display: inline-block; + width: 100%; + height: max-content; + .contentFittingDocumentView { + display: block; // makes titleBar take up full width of the treeView (flex doesn't for some reason) + } +} + .collectionTreeView-keyHeader:hover { background: #797777; cursor: pointer; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 3852987b9..6fb18d4c2 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,4 +1,3 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; import { observer } from "mobx-react"; import { DataSym, Doc, DocListCast, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc'; @@ -8,13 +7,14 @@ import { Document, listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, emptyFunction } from '../../../Utils'; +import { emptyFunction, OmitKeys, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { CurrentUserUtils } from '../../util/CurrentUserUtils'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from "../../util/DragManager"; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; +import { Transform } from '../../util/Transform'; import { undoBatch, UndoManager } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; @@ -22,11 +22,11 @@ import { EditableView } from "../EditableView"; import { DocumentView } from '../nodes/DocumentView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { StyleProp } from '../StyleProvider'; +import { CollectionFreeFormView } from './collectionFreeForm'; import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import { TreeView } from "./TreeView"; import React = require("react"); -import { Transform } from '../../util/Transform'; const _global = (window /* browser */ || global /* node */) as any; export type collectionTreeViewProps = { @@ -41,10 +41,13 @@ export type collectionTreeViewProps = { @observer export class CollectionTreeView extends CollectionSubView>(Document) { - private treedropDisposer?: DragManager.DragDropDisposer; + private _treedropDisposer?: DragManager.DragDropDisposer; private _mainEle?: HTMLDivElement; + private _titleRef?: HTMLDivElement | HTMLInputElement | null; private _disposers: { [name: string]: IReactionDisposer } = {}; - MainEle = () => this._mainEle; + private _isDisposing = false; // notes that instance is in process of being disposed + private refList: Set = new Set(); // list of tree view items to monitor for height changes + private observer: any; // observer for mnonitoring tree view items. @computed get doc() { return this.props.Document; } @computed get dataDoc() { return this.props.DataDoc || this.doc; } @@ -54,6 +57,10 @@ export class CollectionTreeView extends CollectionSubView this._mainEle; + // these should stay in synch with counterparts in DocComponent.ts ViewBoxAnnotatableComponent @observable _isAnyChildContentActive = false; whenChildContentsActiveChanged = action((isActive: boolean) => this.props.whenChildContentsActiveChanged(this._isAnyChildContentActive = isActive)); @@ -62,11 +69,10 @@ export class CollectionTreeView extends CollectionSubView disposer?.()); } @@ -76,13 +82,13 @@ export class CollectionTreeView extends CollectionSubView = new Set(); - observer: any; computeHeight = () => { - if (this.isDisposing) return; - const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), this.paddingTop() + this.paddingBot()); - this.layoutDoc._autoHeightMargins = bodyHeight; - this.props.setHeight(this.documentTitleHeight() + bodyHeight); + if (!this._isDisposing) { + const titleHeight = !this._titleRef ? this.marginTop() : Number(getComputedStyle(this._titleRef).height.replace("px", "")); + const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), this.marginBot()); + this.layoutDoc._autoHeightMargins = bodyHeight; + this.props.setHeight(bodyHeight + titleHeight); + } } unobserveHeight = (ref: any) => { this.refList.delete(ref); @@ -101,8 +107,8 @@ export class CollectionTreeView extends CollectionSubView { - this.treedropDisposer?.(); - if (this._mainEle = ele) this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.doc, this.onInternalPreDrop.bind(this)); + this._treedropDisposer?.(); + if (this._mainEle = ele) this._treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.doc, this.onInternalPreDrop.bind(this)); } protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => { @@ -165,60 +171,54 @@ export class CollectionTreeView extends CollectionSubView { - return !this.dataDoc ? (null) : - StrCast(this.dataDoc.title)} - SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => { - if (enter && this.props.Document.treeViewType === "outline") this.makeTextCollection(childDocs); - this.dataDoc.title = value; - return true; - })} />; + get editableTitle() { + return StrCast(this.dataDoc.title)} + SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => { + if (enter && this.props.Document.treeViewType === "outline") this.makeTextCollection(this.treeChildren); + this.dataDoc.title = value; + return true; + })} />; } - documentTitle = (childDocs: Doc[]) => { - return
{ - e.stopPropagation(); - e.key === "Enter" && this.makeTextCollection(childDocs); - }}> - -
; + get documentTitle() { + return ; } childContextMenuItems = () => { const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []); @@ -263,21 +263,31 @@ export class CollectionTreeView extends CollectionSubView this._titleRef = r} + onKeyDown={e => { + if (this.outlineMode) { + e.stopPropagation(); + e.key === "Enter" && this.makeTextCollection(this.treeChildren); + } + }}> + {this.outlineMode ? this.documentTitle : this.editableTitle} +
; + } + + @computed get noviceExplainer() { + return !Doc.UserDoc().noviceMode || !this.rootDoc.explainer ? (null) : +
{this.rootDoc.explainer}
; } return35 = () => 35; @computed get buttonMenu() { - const menuDoc: Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null); + const menuDoc = Cast(this.rootDoc.buttonMenuDoc, Doc, null); // To create a multibutton menu add a CollectionLinearView - if (menuDoc) { - - const width: number = NumCast(menuDoc._width, 30); - const height: number = NumCast(menuDoc._height, 30); - console.log(menuDoc.title, width, height); - return (
+ return !menuDoc ? null : + (
); - } } - @observable _explainerHeight: number = 0; - @computed get nativeWidth() { return Doc.NativeWidth(this.Document, undefined, true); } @computed get nativeHeight() { return Doc.NativeHeight(this.Document, undefined, true); } @@ -321,47 +328,82 @@ export class CollectionTreeView extends CollectionSubView NumCast(this.doc._xPadding, 15); - paddingTop = () => NumCast(this.doc._yPadding, 20); - paddingBot = () => NumCast(this.doc._yPadding, 20); + marginX = () => NumCast(this.doc._xMargin); + marginTop = () => NumCast(this.doc._yMargin); + marginBot = () => NumCast(this.doc._yMargin); documentTitleWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.panelWidth()); documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.autoHeightMargins); titleTransform = () => this.props.ScreenToLocalTransform().translate(-NumCast(this.doc._xPadding, 10), -NumCast(this.doc._yPadding, 20)); truncateTitleWidth = () => this.treeViewtruncateTitleWidth; onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick); - panelWidth = () => (this.props.PanelWidth() - 2 * this.paddingX()) * (this.props.scaling?.() || 1); - render() { - TraceMobx(); + panelWidth = () => (this.props.PanelWidth() - 2 * this.marginX()) * (this.props.scaling?.() || 1); + + addAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.addDocument(doc, `${this.props.fieldKey}-annotations`) || false; + remAnnotationDocument = (doc: Doc | Doc[]) => this.props.CollectionView?.removeDocument(doc, `${this.props.fieldKey}-annotations`) || false; + moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) => + this.props.CollectionView?.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}-annotations`) || false + + contentFunc = () => { const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor); const pointerEvents = () => !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined; - const buttonMenu = this.rootDoc.buttonMenu; - const noviceExplainer = this.rootDoc.explainer; - - return !(this.doc instanceof Doc) || !this.treeChildren ? (null) : - <> - {this.titleBar} + const titleBar = this.props.treeViewHideTitle || this.doc.treeViewHideTitle ? (null) : this.titleBar; + return [ +
+ {titleBar}
- {buttonMenu || noviceExplainer ?
r && (this._explainerHeight = r.getBoundingClientRect().height))}> - {buttonMenu ? this.buttonMenu : null} - {Doc.UserDoc().noviceMode && noviceExplainer ? -
- {noviceExplainer} -
- : null - } -
: null} + {!this.buttonMenu && !this.noviceExplainer ? (null) : +
r && (this._explainerHeight = r.getBoundingClientRect().height))}> + {this.buttonMenu} + {this.noviceExplainer} +
+ }
e.stopPropagation()} onDrop={this.onTreeDrop} - ref={this.createTreeDropTarget}> + ref={r => !this.doc.treeViewHasOverlay && r && this.createTreeDropTarget(r)}>
    {this.treeViewElements}
- ; +
+ ]; + } + render() { + TraceMobx(); + + return !(this.doc instanceof Doc) || !this.treeChildren ? (null) : + this.doc.treeViewHasOverlay ? + + {this.contentFunc} + : + this.contentFunc(); } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 38e027fb3..8e84b59de 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -63,6 +63,7 @@ export enum CollectionViewType { } export interface CollectionViewProps extends FieldViewProps { isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc) + isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently) layoutEngine?: () => string; setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void; @@ -125,8 +126,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth()); - private SubView = (type: CollectionViewType, props: SubCollectionViewProps) => { + private renderSubView = (type: CollectionViewType | undefined, props: SubCollectionViewProps) => { TraceMobx(); + if (type === undefined) return null; switch (type) { default: case CollectionViewType.Freeform: return ; @@ -246,17 +248,13 @@ export class CollectionView extends ViewBoxAnnotatableComponent this.props.childLayoutTemplate?.() || Cast(this.rootDoc.childLayoutTemplate, Doc, null); @computed get childLayoutString() { return StrCast(this.rootDoc.childLayoutString); } - - @observable _subView: any = undefined; - isContentActive = (outsideReaction?: boolean) => { - return this.props.isContentActive() ? true : false; + return this.props.isContentActive(); } render() { TraceMobx(); const props: SubCollectionViewProps = { ...this.props, - SetSubView: action((subView: any) => this._subView = subView), addDocument: this.addDocument, moveDocument: this.moveDocument, removeDocument: this.removeDocument, @@ -273,7 +271,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent {this.showIsTagged()} - {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)} + {this.renderSubView(this.collectionViewType, props)}
); } } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index eb95bb913..5ba019698 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -476,7 +476,6 @@ export class TabMinimapView extends React.Component {
this} CollectionView={undefined} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} @@ -484,7 +483,7 @@ export class TabMinimapView extends React.Component { 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 setHeight={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} isAnyChildContentActive={returnFalse} select={emptyFunction} dropAction={undefined} diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index 1ebc5873e..2e33d3564 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -53,14 +53,11 @@ } } +.treeView-container-outline-active .treeView-container-active { z-index: 100; position: relative; - - .formattedTextbox-sidebar { - background-color: #ffff001f !important; - height: 500px !important; - } + pointer-events: all; } .treeView-openRight { diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 7f2128230..a266c301f 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -81,7 +81,7 @@ export class TreeView extends React.Component { static _openLevelScript: Opt; private _header: React.RefObject = React.createRef(); private _tref = React.createRef(); - private _docRef: Opt; + @observable _docRef: Opt; private _selDisposer: Opt; private _editTitleScript: (() => ScriptField) | undefined; private _openScript: (() => ScriptField) | undefined; @@ -116,7 +116,8 @@ export class TreeView extends React.Component { @computed get childLinks() { return this.childDocList("links"); } @computed get childAliases() { return this.childDocList("aliases"); } @computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); } - @computed get selected() { return SelectionManager.Views().lastElement()?.props.Document === this.props.document; } + @computed get selected() { return SelectionManager.IsSelected(this._docRef); } + // SelectionManager.Views().lastElement()?.props.Document === this.props.document; } childDocList(field: string) { const layout = Cast(Doc.LayoutField(this.doc), Doc, null); @@ -125,7 +126,12 @@ export class TreeView extends React.Component { DocListCastOrNull(this.doc[field]); // otherwise use the document's data field } @undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { - return this.doc !== target && this.props.removeDoc?.(doc) === true && addDoc(doc); + if (this.doc !== target && addDoc !== returnFalse) { // bcz: this should all be running in a Temp undo batch instead of hackily testing for returnFalse + if (this.props.removeDoc?.(doc) === true) { + return addDoc(doc); + } + } + return false; } @undoBatch @action remove = (doc: Doc | Doc[], key: string) => { this.props.treeView.props.select(false); @@ -141,8 +147,10 @@ export class TreeView extends React.Component { this._editTitle = false; } else if (docView.isSelected()) { + const doc = docView.Document; + SelectionManager.SelectSchemaViewDoc(doc); this._editTitle = true; - this._selDisposer = reaction(() => docView.isSelected(), sel => !sel && this.setEditTitle(undefined)); + this._selDisposer = reaction(() => SelectionManager.SelectedSchemaDoc(), seldoc => seldoc !== doc && this.setEditTitle(undefined)); } else { docView.select(false); } @@ -222,7 +230,7 @@ export class TreeView extends React.Component { public static makeTextBullet() { const bullet = Docs.Create.TextDocument("-text-", { layout: CollectionView.LayoutString("data"), - title: "-title-", "sidebarColor": "transparent", "sidebarViewType": CollectionViewType.Freeform, + title: "-title-", treeViewExpandedViewLock: true, treeViewExpandedView: "data", _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewType: "outline", x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, backgroundColor: "transparent", _width: 1000, _height: 10 @@ -266,23 +274,25 @@ export class TreeView extends React.Component { e.stopPropagation(); } const docDragData = de.complete.docDragData; - if (docDragData) { - e.stopPropagation(); + if (docDragData && pt[0] < rect.left + rect.width) { if (docDragData.draggedDocuments[0] === this.doc) return true; - this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document); + if (this.dropDocuments(docDragData.droppedDocuments, before, inside, docDragData.dropAction, docDragData.moveDocument, docDragData.treeViewDoc === this.props.treeView.props.Document)) { + e.stopPropagation(); + } } } dropDocuments(droppedDocuments: Doc[], before: boolean, inside: number | boolean, dropAction: dropActionType, moveDocument: DragManager.MoveFunction | undefined, forceAdd: boolean) { const parentAddDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before); - const canAdd = !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes("add") || forceAdd; + const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.containerCollection)?.freezeChildren).includes("add")) || forceAdd; const localAdd = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) && ((doc.context = this.doc.context) || true) ? true : false; const addDoc = !inside ? parentAddDoc : (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc), true as boolean); const move = (!dropAction || dropAction === "proto" || dropAction === "move" || dropAction === "same") && moveDocument; if (canAdd) { - UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === "proto" ? addDoc(d) : false) : addDoc(d)) || added, false)); + return UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === "proto" ? addDoc(d) : false) : addDoc(d)) || added, false)); } + return false; } refTransform = (ref: HTMLDivElement | undefined | null) => { @@ -432,7 +442,7 @@ export class TreeView extends React.Component {
; } - return
    {this.renderEmbeddedDocument(false)}
; // "layout" + return
    { e.preventDefault(); e.stopPropagation(); }}>{this.renderEmbeddedDocument(false, returnFalse)}
; // "layout" } get onCheckedClick() { return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick); } @@ -581,6 +591,7 @@ export class TreeView extends React.Component { } titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth())); + return18 = () => 18; /** * Renders the EditableView title element for placement into the tree. */ @@ -636,10 +647,10 @@ export class TreeView extends React.Component { moveDocument={this.move} removeDocument={this.props.removeDoc} ScreenToLocalTransform={this.getTransform} - NativeHeight={() => 18} + NativeHeight={this.return18} NativeWidth={this.titleWidth} PanelWidth={this.titleWidth} - PanelHeight={() => 18} + PanelHeight={this.return18} contextMenuItems={this.contextMenuItems} renderDepth={1} isContentActive={this.props.isContentActive} @@ -679,6 +690,7 @@ export class TreeView extends React.Component { renderBulletHeader = (contents: JSX.Element, editing: boolean) => { return <>
{ } - renderEmbeddedDocument = (asText: boolean) => { + renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => { const layout = StrCast(Doc.LayoutField(this.layoutDoc)); const isExpandable = layout.includes(FormattedTextBox.name) || layout.includes(SliderBox.name); const panelWidth = asText || isExpandable ? this.rtfWidth : this.expandPanelWidth; @@ -704,8 +716,8 @@ export class TreeView extends React.Component { NativeWidth={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfWidth : undefined} NativeHeight={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfHeight : undefined} LayoutTemplateString={asText ? FormattedTextBox.LayoutString("text") : undefined} - isContentActive={asText ? this.props.isContentActive : returnFalse} - isDocumentActive={asText ? this.props.isContentActive : returnFalse} + isContentActive={isActive} + isDocumentActive={isActive} styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider} hideTitle={asText} fitContentsToDoc={returnTrue} @@ -749,7 +761,7 @@ export class TreeView extends React.Component { @computed get renderDocumentAsHeader() { return <> {this.renderBullet} - {this.renderEmbeddedDocument(true)} + {this.renderEmbeddedDocument(true, this.props.isContentActive)} ; } @@ -776,13 +788,12 @@ export class TreeView extends React.Component { return this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? "<" + this.doc.title + ">" : // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles
this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document onKeyDown={this.onKeyDown}>
  • {hideTitle && this.doc.type !== DocumentType.RTF ? - this.renderEmbeddedDocument(false) : + this.renderEmbeddedDocument(false, returnFalse) : this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader : this.renderTitleAsHeader, this._editTitle)}
  • ; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 37caf508f..190d0e76a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -165,7 +165,7 @@ export class CollectionFreeFormView extends CollectionSubView this.freeformData()?.bounds.cx ?? NumCast(this.Document._panX); panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document._panY); zoomScaling = () => (this.freeformData()?.scale ?? NumCast(this.Document[this.scaleFieldKey], 1)); - contentTransform = () => `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`; + contentTransform = () => !this.cachedCenteringShiftX && !this.cachedCenteringShiftY && this.zoomScaling() === 1 ? "" : `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`; getTransform = () => this.cachedGetTransform.copy(); getLocalTransform = () => this.cachedGetLocalTransform.copy(); getContainerTransform = () => this.cachedGetContainerTransform.copy(); @@ -802,7 +802,7 @@ export class CollectionFreeFormView extends CollectionSubView boolean; + isContentActive?: () => boolean | undefined; columnUnitLength(): number | undefined; toLeft?: Doc; toRight?: Doc; diff --git a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx index 5478bf709..006ef4df6 100644 --- a/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx +++ b/src/client/views/collections/collectionMulticolumn/MultirowResizer.tsx @@ -11,7 +11,7 @@ import { StyleProviderFunc } from "../../nodes/DocumentView"; interface ResizerProps { height: number; styleProvider?: StyleProviderFunc; - isContentActive?: () => boolean; + isContentActive?: () => boolean | undefined; columnUnitLength(): number | undefined; toTop?: Doc; toBottom?: Doc; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx index 1306b79cb..dc35b5749 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx @@ -225,7 +225,7 @@ export interface KeysDropdownProps { fieldKey: string; ContainingCollectionDoc: Doc | undefined; ContainingCollectionView: Opt; - active?: (outsideReaction?: boolean) => boolean; + active?: (outsideReaction?: boolean) => boolean | undefined; openHeader: (column: any, screenx: number, screeny: number) => void; col: SchemaHeaderField; icon: IconProp; diff --git a/src/client/views/collections/collectionSchema/SchemaTable.tsx b/src/client/views/collections/collectionSchema/SchemaTable.tsx index bc5a9559f..2219345f6 100644 --- a/src/client/views/collections/collectionSchema/SchemaTable.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTable.tsx @@ -68,7 +68,7 @@ export interface SchemaTableProps { addDocument?: (document: Doc | Doc[]) => boolean; moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; ScreenToLocalTransform: () => Transform; - active: (outsideReaction: boolean | undefined) => boolean; + active: (outsideReaction: boolean | undefined) => boolean | undefined; onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined) => void; addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6c058ff97..c8a32a911 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -138,6 +138,7 @@ export interface DocumentViewSharedProps { hideLinkButton?: boolean; hideCaptions?: boolean; ignoreAutoHeight?: boolean; + forceAutoHeight?: boolean; disableDocBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. pointerEvents?: string; scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document @@ -224,7 +225,7 @@ export class DocumentViewInternal extends DocComponent Doc, forward?: () => boolean, back?: () => boolean }) => this._componentView = view); isContentActive = (outsideReaction?: boolean) => { - return CurrentUserUtils.SelectedTool !== InkTool.None || + return this.props.isContentActive() === false ? false : ( + CurrentUserUtils.SelectedTool !== InkTool.None || SnappingManager.GetIsDragging() || this.props.rootSelected() || this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._componentView?.isAnyChildContentActive?.() || - this.props.isContentActive() ? true : false; + this.props.isContentActive()) ? true : undefined; } @computed get contents() { TraceMobx(); @@ -1256,7 +1258,7 @@ export class DocumentView extends React.Component { position: this.props.Document.isInkMask ? "absolute" : undefined, transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`, width: isButton ? "100%" : xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`, - height: isButton ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` : + height: isButton || this.props.forceAutoHeight ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` : `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`), }}> void; - isContentActive: (outsideReaction?: boolean) => boolean; + isContentActive: (outsideReaction?: boolean) => boolean | undefined; isDocumentActive?: () => boolean; isSelected: (outsideReaction?: boolean) => boolean; scaling?: () => number; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 2041c7399..fb8e89da9 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -225,7 +225,7 @@ export class FilterBox extends ViewBoxBaseComponent(LinkDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); } - isContentActiveFunc = () => this.isContentActive() ? true : false; + isContentActiveFunc = () => this.isContentActive(); render() { if (this.dataDoc.treeViewOpen === undefined) setTimeout(() => this.dataDoc.treeViewOpen = true); return
    { docViewPath={returnEmptyDoclist} ScreenToLocalTransform={Transform.Identity} isDocumentActive={returnFalse} - isContentActive={returnFalse} + isContentActive={emptyFunction} addDocument={returnFalse} removeDocument={returnFalse} addDocTab={returnFalse} diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 7ad96bf05..0c631e5f9 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -313,7 +313,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponentLoading
    : -
    -
    +
    +