aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/DocServer.ts15
-rw-r--r--src/client/documents/Documents.ts5
-rw-r--r--src/client/util/CurrentUserUtils.ts19
-rw-r--r--src/client/util/DocumentManager.ts2
-rw-r--r--src/client/util/DragManager.ts6
-rw-r--r--src/client/views/DocumentDecorations.tsx2
-rw-r--r--src/client/views/EditableView.tsx39
-rw-r--r--src/client/views/Main.tsx2
-rw-r--r--src/client/views/MainView.tsx3
-rw-r--r--src/client/views/animationtimeline/Timeline.tsx4
-rw-r--r--src/client/views/collections/CollectionSubView.tsx3
-rw-r--r--src/client/views/collections/CollectionTreeView.scss3
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx392
-rw-r--r--src/client/views/collections/CollectionView.tsx6
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss7
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx27
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx34
-rw-r--r--src/client/views/nodes/DocumentView.scss11
-rw-r--r--src/client/views/nodes/DocumentView.tsx46
-rw-r--r--src/client/views/nodes/LinkAnchorBox.tsx10
-rw-r--r--src/client/views/nodes/PresBox.tsx4
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx4
-rw-r--r--src/client/views/pdf/PDFViewer.tsx14
-rw-r--r--src/client/views/search/SearchItem.tsx2
-rw-r--r--src/fields/Doc.ts2
-rw-r--r--src/fields/util.ts6
27 files changed, 362 insertions, 311 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index c7dfb0b23..2a7a7c59a 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -31,16 +31,19 @@ export namespace DocServer {
export enum WriteMode {
Default = 0, //Anything goes
- Playground = 1,
- LiveReadonly = 2,
- LivePlayground = 3,
+ Playground = 1, //Playground (write own/no read)
+ LiveReadonly = 2,//Live Readonly (no write/read others)
+ LivePlayground = 3,//Live Playground (write own/read others)
}
-
- export let AclsMode = WriteMode.Default;
-
const fieldWriteModes: { [field: string]: WriteMode } = {};
const docsWithUpdates: { [field: string]: Set<Doc> } = {};
+ export var PlaygroundFields: string[];
+ export function setPlaygroundFields(livePlayougroundFields: string[]) {
+ DocServer.PlaygroundFields = livePlayougroundFields;
+ livePlayougroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.LivePlayground));
+ }
+
export function setFieldWriteMode(field: string, writeMode: WriteMode) {
fieldWriteModes[field] = writeMode;
if (writeMode !== WriteMode.Playground) {
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index ec1a33d17..5cbbe526e 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -92,7 +92,7 @@ export interface DocumentOptions {
label?: string; // short form of title for use as an icon label
style?: string;
page?: number;
- scale?: number;
+ _viewScale?: number;
isDisplayPanel?: boolean; // whether the panel functions as GoldenLayout "stack" used to display documents
forceActive?: boolean;
layout?: string | Doc; // default layout string for a document
@@ -168,6 +168,7 @@ export interface DocumentOptions {
treeViewOpen?: boolean; // whether this document is expanded in a tree view
treeViewExpandedView?: string; // which field/thing is displayed when this item is opened in tree view
treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked
+ treeViewTruncateTitleWidth?: number;
limitHeight?: number; // maximum height for newly created (eg, from pasting) text documents
// [key: string]: Opt<Field>;
pointerHack?: boolean; // for buttons, allows onClick handler to fire onPointerDown
@@ -227,7 +228,7 @@ export namespace Docs {
}],
[DocumentType.COL, {
layout: { view: CollectionView, dataField: defaultDataKey },
- options: { _panX: 0, _panY: 0, scale: 1 } // , _width: 500, _height: 500 }
+ options: { _panX: 0, _panY: 0, _viewScale: 1 } // , _width: 500, _height: 500 }
}],
[DocumentType.KVP, {
layout: { view: KeyValueBox, dataField: defaultDataKey },
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 9a4c95571..2b0b2c738 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -306,21 +306,17 @@ export class CurrentUserUtils {
// setup templates for different document types when they are iconified from Document Decorations
static setupDefaultIconTemplates(doc: Doc) {
if (doc["template-icon-view"] === undefined) {
- const iconView = Docs.Create.TextDocument("", {
- title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
+ const iconView = Docs.Create.LabelDocument({
+ title: "icon", textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("title"), _backgroundColor: "dimGray",
+ _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
});
- Doc.GetProto(iconView).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
+ // Docs.Create.TextDocument("", {
+ // title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
+ // });
+ // Doc.GetProto(iconView).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
iconView.isTemplateDoc = makeTemplate(iconView);
doc["template-icon-view"] = new PrefetchProxy(iconView);
}
- if (doc["template-icon-view-pdf"] === undefined) {
- const iconPdfView = Docs.Create.LabelDocument({
- title: "icon_" + DocumentType.PDF, textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("title"), _backgroundColor: "dimGray",
- _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
- });
- iconPdfView.isTemplateDoc = makeTemplate(iconPdfView, true, "icon_" + DocumentType.PDF);
- doc["template-icon-view-pdf"] = new PrefetchProxy(iconPdfView);
- }
if (doc["template-icon-view-rtf"] === undefined) {
const iconRtfView = Docs.Create.LabelDocument({
title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("text"),
@@ -605,6 +601,7 @@ export class CurrentUserUtils {
if (doc["tabs-button-library"] === undefined) {
const libraryStack = new PrefetchProxy(Docs.Create.TreeDocument([workspaces, documents, recentlyClosed, doc], {
title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
+ treeViewTruncateTitleWidth: 150,
lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
})) as any as Doc;
doc["tabs-button-library"] = new PrefetchProxy(Docs.Create.ButtonDocument({
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 40d6b039a..fb5d1717e 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -170,7 +170,7 @@ export class DocumentManager {
const targetDocContextView = getFirstDocView(targetDocContext);
targetDocContext._scrollY = 0; // this will force PDFs to activate and load their annotations / allow scrolling
if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first..
- targetDocContext.panTransformType = "Ease";
+ targetDocContext._viewTransition = "transform 500ms";
targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom);
// now find the target document within the context
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 417ddf989..0db3963b2 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -19,8 +19,6 @@ export function SetupDrag(
docFunc: () => Doc | Promise<Doc> | undefined,
moveFunc?: DragManager.MoveFunction,
dropAction?: dropActionType,
- treeViewId?: string,
- dontHideOnDrop?: boolean,
dragStarted?: () => void
) {
const onRowMove = async (e: PointerEvent) => {
@@ -34,8 +32,6 @@ export function SetupDrag(
const dragData = new DragManager.DocumentDragData([doc]);
dragData.dropAction = dropAction;
dragData.moveDocument = moveFunc;
- dragData.treeViewId = treeViewId;
- dragData.dontHideOnDrop = dontHideOnDrop;
DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y);
dragStarted?.();
}
@@ -128,7 +124,7 @@ export namespace DragManager {
draggedDocuments: Doc[];
droppedDocuments: Doc[];
dragDivName?: string;
- treeViewId?: string;
+ treeViewDoc?: Doc;
dontHideOnDrop?: boolean;
offset: number[];
dropAction: dropActionType;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index f5454216a..6e28ad654 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -77,7 +77,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
get Bounds(): { x: number, y: number, b: number, r: number } {
return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => {
if (documentView.props.renderDepth === 0 ||
- documentView.props.treeViewId ||
+ documentView.props.treeViewDoc ||
Doc.AreProtosEqual(documentView.props.Document, Doc.UserDoc())) {
return bounds;
}
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index afe9321f4..a4f2f17fc 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -31,6 +31,7 @@ export interface EditableProps {
fontStyle?: string;
fontSize?: number;
height?: number | "auto";
+ sizeToContent?: boolean;
maxHeight?: number;
display?: string;
autosuggestProps?: {
@@ -60,13 +61,11 @@ export interface EditableProps {
*/
@observer
export class EditableView extends React.Component<EditableProps> {
- public static loadId = "";
@observable _editing: boolean = false;
constructor(props: EditableProps) {
super(props);
this._editing = this.props.editing ? true : false;
- EditableView.loadId = "";
}
// @action
@@ -150,13 +149,40 @@ export class EditableView extends React.Component<EditableProps> {
@action
setIsFocused = (value: boolean) => {
const wasFocused = this._editing;
- this._editing = value;
+ //this._editing = value;
return wasFocused !== this._editing;
}
_ref = React.createRef<HTMLDivElement>();
+ renderEditor() {
+ return this.props.autosuggestProps
+ ? <Autosuggest
+ {...this.props.autosuggestProps.autosuggestProps}
+ inputProps={{
+ className: "editableView-input",
+ onKeyDown: this.onKeyDown,
+ autoFocus: true,
+ onBlur: e => this.finalizeEdit(e.currentTarget.value, false, true),
+ onPointerDown: this.stopPropagation,
+ onClick: this.stopPropagation,
+ onPointerUp: this.stopPropagation,
+ value: this.props.autosuggestProps.value,
+ onChange: this.props.autosuggestProps.onChange
+ }}
+ />
+ : <input className="editableView-input"
+ defaultValue={this.props.GetValue()}
+ onKeyDown={this.onKeyDown}
+ autoFocus={true}
+ onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true)}
+ onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation}
+ style={{ display: this.props.display, fontSize: this.props.fontSize, minWidth: 20 }}
+ placeholder={this.props.placeholder}
+ />;
+ }
render() {
if (this._editing && this.props.GetValue() !== undefined) {
+<<<<<<< HEAD
return this.props.autosuggestProps
? <Autosuggest
{...this.props.autosuggestProps.autosuggestProps}
@@ -182,6 +208,13 @@ export class EditableView extends React.Component<EditableProps> {
style={{ display: this.props.display, fontSize: this.props.fontSize }}
placeholder={this.props.placeholder}
/>;
+=======
+ return this.props.sizeToContent ?
+ <div style={{ display: "grid", minWidth: 100 }}>
+ <div style={{ display: "inline-block", position: "relative", height: 0, width: "100%", overflow: "hidden" }}>{this.props.GetValue()}</div>
+ {this.renderEditor()}
+ </div> : this.renderEditor();
+>>>>>>> 790cc785a5cad47f0dd274c7f4773eff7d7d9c2e
} else {
this.props.autosuggestProps?.resetValue();
return (this.props.contents instanceof ObjectField ? (null) :
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 6878658a8..77e37834d 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -6,12 +6,14 @@ import * as React from 'react';
import { DocServer } from "../DocServer";
import { AssignAllExtensions } from "../../extensions/General/Extensions";
import { Networking } from "../Network";
+import { CollectionView } from "./collections/CollectionView";
AssignAllExtensions();
export let resolvedPorts: { server: number, socket: number };
(async () => {
+ window.location.search.includes("safe") && CollectionView.SetSafeMode(true);
const info = await CurrentUserUtils.loadCurrentUser();
resolvedPorts = JSON.parse(await Networking.FetchFromServer("/resolvedPorts"));
DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, info.email);
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index d1957c4af..68b81ab4f 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -81,7 +81,10 @@ export class MainView extends React.Component {
public isPointerDown = false;
+
componentDidMount() {
+ DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType"]); // can play with these fields on someone else's
+
const tag = document.createElement('script');
const proto = DocServer.GetRefField("rtfProto").then(proto => {
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index ab984f727..f54bd3aff 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -288,13 +288,13 @@ export class Timeline extends React.Component<FieldViewProps> {
resetView(doc: Doc) {
doc._panX = doc._customOriginX ?? 0;
doc._panY = doc._customOriginY ?? 0;
- doc.scale = doc._customOriginScale ?? 1;
+ doc._viewScale = doc._customOriginScale ?? 1;
}
setView(doc: Doc) {
doc._customOriginX = doc._panX;
doc._customOriginY = doc._panY;
- doc._customOriginScale = doc.scale;
+ doc._customOriginScale = doc._viewScale;
}
/**
* zooming mechanism (increment and spacing changes)
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 570f9375e..3a13ac822 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -104,8 +104,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
}
docFilters = () => {
return this.props.ignoreFields?.includes("_docFilters") ? [] :
- this.props.docFilters !== returnEmptyFilter ? this.props.docFilters() :
- Cast(this.props.Document._docFilters, listSpec("string"), []);
+ [...this.props.docFilters(), ...Cast(this.props.Document._docFilters, listSpec("string"), [])];
}
@computed get childDocs() {
const docFilters = this.docFilters();
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 2aac81146..50f0534bd 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -82,8 +82,6 @@
text-overflow: ellipsis;
white-space: pre-wrap;
min-width: 10px;
- // width:100%;//width: max-content;
-
}
.treeViewItem-openRight {
@@ -100,6 +98,7 @@
border-left: dashed 1px #00000042;
}
+.treeViewItem-header-editing,
.treeViewItem-header {
border: transparent 1px solid;
display: flex;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 68dc0ced2..1088577d2 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -13,7 +13,7 @@ import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentType } from "../../documents/DocumentTypes";
import { DocumentManager } from '../../util/DocumentManager';
import { SnappingManager } from '../../util/SnappingManager';
-import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
+import { DragManager, dropActionType } from "../../util/DragManager";
import { Scripting } from '../../util/Scripting';
import { SelectionManager } from '../../util/SelectionManager';
import { Transform } from '../../util/Transform';
@@ -55,7 +55,7 @@ export interface TreeViewProps {
ScreenToLocalTransform: () => Transform;
backgroundColor?: (doc: Doc) => string | undefined;
outerXf: () => { translateX: number, translateY: number };
- treeViewId: Doc;
+ treeViewDoc: Doc;
parentKey: string;
active: (outsideReaction?: boolean) => boolean;
treeViewHideHeaderFields: () => boolean;
@@ -76,31 +76,32 @@ export interface TreeViewProps {
* treeViewExpandedView : name of field whose contents are being displayed as the document's subtree
*/
class TreeView extends React.Component<TreeViewProps> {
- static _editTitleScript: ScriptField | undefined;
+ private _editTitleScript: ScriptField | undefined;
private _header?: React.RefObject<HTMLDivElement> = React.createRef();
private _treedropDisposer?: DragManager.DragDropDisposer;
private _dref = React.createRef<HTMLDivElement>();
private _tref = React.createRef<HTMLDivElement>();
private _docRef = React.createRef<DocumentView>();
+ private _uniqueId = Utils.GenerateGuid();
+ private _editMaxWidth: number | string = 0;
+ get doc() { 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
- get defaultExpandedView() { return this.childDocs ? this.fieldKey : StrCast(this.props.document.defaultExpandedView, this.noviceMode ? "layout" : "fields"); }
+ get displayName() { return "TreeView(" + this.doc.title + ")"; } // this makes mobx trace() statements more descriptive
+ get defaultExpandedView() { return this.childDocs ? this.fieldKey : StrCast(this.doc.defaultExpandedView, this.noviceMode ? "layout" : "fields"); }
@observable _overrideTreeViewOpen = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state
- set treeViewOpen(c: boolean) { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.props.document.treeViewOpen = this._overrideTreeViewOpen = c; }
- @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.props.document.treeViewPreventOpen && BoolCast(this.props.document.treeViewOpen)) || this._overrideTreeViewOpen; }
- @computed get treeViewExpandedView() { return StrCast(this.props.document.treeViewExpandedView, this.defaultExpandedView); }
+ set treeViewOpen(c: boolean) { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.doc.treeViewOpen = this._overrideTreeViewOpen = c; }
+ @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen; }
+ @computed get treeViewExpandedView() { return StrCast(this.doc.treeViewExpandedView, this.defaultExpandedView); }
@computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); }
- @computed get dataDoc() { return this.props.document[DataSym]; }
- @computed get fieldKey() {
- const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\'");
- return splits.length > 1 ? splits[1].split("\'")[0] : "data";
- }
+ @computed get dataDoc() { return this.doc[DataSym]; }
+ @computed get layoutDoc() { return Doc.Layout(this.doc); }
+ @computed get fieldKey() { const splits = StrCast(Doc.LayoutField(this.doc)).split("fieldKey={\'"); return splits.length > 1 ? splits[1].split("\'")[0] : "data"; }
childDocList(field: string) {
- const layout = Doc.LayoutField(this.props.document) instanceof Doc ? Doc.LayoutField(this.props.document) as Doc : undefined;
+ const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined;
return ((this.props.dataDoc ? DocListCast(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
(layout ? Cast(layout[field], listSpec(Doc)) : undefined) || // else if there's a layout doc, display it's fields
- Cast(this.props.document[field], listSpec(Doc))) as Doc[]; // otherwise use the document's data field
+ Cast(this.doc[field], listSpec(Doc))) as Doc[]; // otherwise use the document's data field
}
@computed get childDocs() { return this.childDocList(this.fieldKey); }
@computed get childLinks() { return this.childDocList("links"); }
@@ -109,22 +110,27 @@ class TreeView extends React.Component<TreeViewProps> {
Doc.ComputeContentBounds(DocListCast(this.props.document[this.fieldKey]));
}
- @undoBatch openRight = () => this.props.addDocTab(this.props.document, "onRight", this.props.libraryPath);
+ @undoBatch openRight = () => this.props.addDocTab(this.doc, "onRight", this.props.libraryPath);
@undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => {
- return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc);
+ return this.doc !== target && this.props.deleteDoc(doc) && addDoc(doc);
}
@undoBatch @action remove = (doc: Doc | Doc[], key: string) => {
- return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) =>
- flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true);
+ return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true);
}
@undoBatch @action removeDoc = (doc: Doc | Doc[]) => {
return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) =>
flg && Doc.RemoveDocFromList(this.props.containingCollection, Doc.LayoutFieldKey(this.props.containingCollection), doc), true);
}
+ constructor(props: any) {
+ super(props);
+ this._editTitleScript = ScriptField.MakeFunction(`setInPlace(self, 'editTitle', '${this._uniqueId}')`);
+ if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false);
+ }
+
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this._treedropDisposer?.();
- ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), undefined, this.preTreeDrop.bind(this)), this.props.document);
+ ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), undefined, this.preTreeDrop.bind(this)), this.doc);
}
onPointerEnter = (e: React.PointerEvent): void => {
@@ -136,7 +142,9 @@ class TreeView extends React.Component<TreeViewProps> {
}
onPointerLeave = (e: React.PointerEvent): void => {
Doc.UnBrushDoc(this.dataDoc);
- this._header!.current!.className = "treeViewItem-header";
+ if (this._header?.current?.className !== "treeViewItem-header-editing") {
+ this._header!.current!.className = "treeViewItem-header";
+ }
document.removeEventListener("pointermove", this.onDragMove, true);
}
onDragMove = (e: PointerEvent): void => {
@@ -144,7 +152,7 @@ class TreeView extends React.Component<TreeViewProps> {
const pt = [e.clientX, e.clientY];
const rect = this._header!.current!.getBoundingClientRect();
const before = pt[1] < rect.top + rect.height / 2;
- const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && DocListCast(this.dataDoc[this.fieldKey]).length);
+ const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length);
this._header!.current!.className = "treeViewItem-header";
if (inside) this._header!.current!.className += " treeViewItem-header-inside";
else if (before) this._header!.current!.className += " treeViewItem-header-above";
@@ -155,42 +163,38 @@ class TreeView extends React.Component<TreeViewProps> {
editableView = (key: string, style?: string) => (<EditableView
oneLine={true}
display={"inline-block"}
- editing={true /*this.dataDoc[Id] === EditableView.loadId*/}
- contents={StrCast(this.props.document[key])}
+ editing={true}
+ contents={StrCast(this.doc[key])}
height={12}
+ sizeToContent={true}
fontStyle={style}
fontSize={12}
- GetValue={() => StrCast(this.props.document[key])}
+ GetValue={() => StrCast(this.doc[key])}
SetValue={undoBatch((value: string) => {
- Doc.SetInPlace(this.props.document, key, value, false) || true;
- Doc.SetInPlace(this.props.document, "editTitle", undefined, false);
+ Doc.SetInPlace(this.doc, key, value, false) || true;
+ Doc.SetInPlace(this.doc, "editTitle", undefined, false);
})}
OnFillDown={undoBatch((value: string) => {
- Doc.SetInPlace(this.props.document, key, value, false);
+ Doc.SetInPlace(this.doc, key, value, false);
const doc = Docs.Create.FreeformDocument([], { title: "-", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List<string>([Templates.Title.Layout]) });
- Doc.SetInPlace(this.props.document, "editTitle", undefined, false);
- Doc.SetInPlace(doc, "editTitle", true, false);
+ Doc.SetInPlace(this.doc, "editTitle", undefined, false);
+ Doc.SetInPlace(doc, "editTitle", "*", false);
return this.props.addDocument(doc);
})}
onClick={() => {
SelectionManager.DeselectAll();
- Doc.UserDoc().activeSelection = new List([this.props.document]);
+ Doc.UserDoc().activeSelection = new List([this.doc]);
return false;
}}
OnTab={undoBatch((shift?: boolean) => {
- EditableView.loadId = this.dataDoc[Id];
shift ? this.props.outdentDocument?.() : this.props.indentDocument?.();
- setTimeout(() => { // unsetting/setting brushing for this doc will recreate & refocus this editableView after all other treeview changes have been made to the Dom (which may remove focus from this document).
- Doc.UnBrushDoc(this.props.document);
- Doc.BrushDoc(this.props.document);
- EditableView.loadId = "";
- }, 0);
+ setTimeout(() => Doc.SetInPlace(this.doc, "editTitle", "*", false), 0);
})}
/>)
preTreeDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => {
const dragData = de.complete.docDragData;
- dragData && (dragData.dropAction = this.props.treeViewId[Id] === dragData.treeViewId ? "same" : dragData.dropAction);
+ dragData && (dragData.dropAction = this.props.treeViewDoc === dragData.treeViewDoc ? "same" : dragData.dropAction);
}
@undoBatch
@@ -198,18 +202,18 @@ class TreeView extends React.Component<TreeViewProps> {
const pt = [de.x, de.y];
const rect = this._header!.current!.getBoundingClientRect();
const before = pt[1] < rect.top + rect.height / 2;
- const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && DocListCast(this.dataDoc[this.fieldKey]).length);
+ const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length);
const complete = de.complete;
if (complete.linkDragData) {
const sourceDoc = complete.linkDragData.linkSourceDocument;
- const destDoc = this.props.document;
+ const destDoc = this.doc;
DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }, "tree link");
e.stopPropagation();
}
const docDragData = complete.docDragData;
if (docDragData) {
e.stopPropagation();
- if (docDragData.draggedDocuments[0] === this.props.document) return true;
+ if (docDragData.draggedDocuments[0] === this.doc) return true;
const parentAddDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before);
let addDoc = parentAddDoc;
if (inside) {
@@ -222,35 +226,28 @@ class TreeView extends React.Component<TreeViewProps> {
return false;
}
- docTransform = () => {
- const { scale, translateX, translateY } = Utils.GetScreenTransform(this._dref.current!);
- const outerXf = this.props.outerXf();
- const offset = this.props.ScreenToLocalTransform().transformDirection((outerXf.translateX - translateX), outerXf.translateY - translateY);
- const finalXf = this.props.ScreenToLocalTransform().translate(offset[0], offset[1]);
-
- return finalXf;
- }
- getTransform = () => {
- const { scale, translateX, translateY } = Utils.GetScreenTransform(this._tref.current!);
+ refTransform = (ref: HTMLDivElement) => {
+ const { scale, translateX, translateY } = Utils.GetScreenTransform(ref);
const outerXf = this.props.outerXf();
const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY);
- const finalXf = this.props.ScreenToLocalTransform().translate(offset[0], offset[1]);
- return finalXf;
+ return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]);
}
+ docTransform = () => this.refTransform(this._dref.current!)
+ getTransform = () => this.refTransform(this._tref.current!);
docWidth = () => {
- const layoutDoc = Doc.Layout(this.props.document);
+ const layoutDoc = this.layoutDoc;
const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.panelWidth() - 20));
return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.panelWidth() - 20) : this.props.panelWidth() - 20;
}
docHeight = () => {
- const layoutDoc = Doc.Layout(this.props.document);
+ const layoutDoc = this.layoutDoc;
const bounds = this.boundsOfCollectionDocument;
return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => {
const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
if (aspect) return this.docWidth() * aspect;
if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x);
- return layoutDoc._fitWidth ? (!this.props.document._nativeHeight ? NumCast(this.props.containingCollection._height) :
+ return layoutDoc._fitWidth ? (!this.doc._nativeHeight ? NumCast(this.props.containingCollection._height) :
Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth,
NumCast(this.props.containingCollection._height)))) :
NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50;
@@ -259,7 +256,7 @@ class TreeView extends React.Component<TreeViewProps> {
@computed get expandedField() {
const ids: { [key: string]: string } = {};
- const doc = this.props.document;
+ const doc = this.doc;
doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
const rows: JSX.Element[] = [];
@@ -273,13 +270,12 @@ class TreeView extends React.Component<TreeViewProps> {
const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce(
(flg, doc) => flg && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true), true);
contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] :
- DocListCast(contents), this.props.treeViewId, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
+ DocListCast(contents), this.props.treeViewDoc, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active,
this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen,
[...this.props.renderedIds, doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields);
} else {
- contentElement = <EditableView
- key="editableView"
+ contentElement = <EditableView key="editableView"
contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
height={13}
fontSize={12}
@@ -307,8 +303,8 @@ class TreeView extends React.Component<TreeViewProps> {
return rows;
}
- rtfWidth = () => Math.min(Doc.Layout(this.props.document)?.[WidthSym](), this.props.panelWidth() - 20);
- rtfHeight = () => this.rtfWidth() < Doc.Layout(this.props.document)?.[WidthSym]() ? Math.min(Doc.Layout(this.props.document)?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
+ 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;
@computed get renderContent() {
TraceMobx();
@@ -320,32 +316,32 @@ class TreeView extends React.Component<TreeViewProps> {
const docs = expandKey === "links" ? this.childLinks : this.childDocs;
const sortKey = `${this.fieldKey}-sortAscending`;
return <ul key={expandKey + "more"} onClick={(e) => {
- this.props.document[sortKey] = (this.props.document[sortKey] ? false : (this.props.document[sortKey] === false ? undefined : true));
+ this.doc[sortKey] = (this.doc[sortKey] ? false : (this.doc[sortKey] === false ? undefined : true));
e.stopPropagation();
}}>
{!docs ? (null) :
- TreeView.GetChildElements(docs, this.props.treeViewId, Doc.Layout(this.props.document),
+ TreeView.GetChildElements(docs, this.props.treeViewDoc, this.layoutDoc,
this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
- StrCast(this.props.document.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform,
+ StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform,
this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen,
- [...this.props.renderedIds, this.props.document[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields)}
+ [...this.props.renderedIds, this.doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields)}
</ul >;
} else if (this.treeViewExpandedView === "fields") {
- return <ul><div ref={this._dref} style={{ display: "inline-block" }} key={this.props.document[Id] + this.props.document.title}>
+ return <ul><div ref={this._dref} style={{ display: "inline-block" }} key={this.doc[Id] + this.doc.title}>
{this.expandedField}
</div></ul>;
} else {
- const layoutDoc = Doc.Layout(this.props.document);
+ const layoutDoc = this.layoutDoc;
const panelHeight = layoutDoc.type === DocumentType.RTF ? this.rtfHeight : this.docHeight;
const panelWidth = layoutDoc.type === DocumentType.RTF ? this.rtfWidth : this.docWidth;
- return <div ref={this._dref} style={{ display: "inline-block", height: panelHeight() }} key={this.props.document[Id]}>
+ return <div ref={this._dref} style={{ display: "inline-block", height: panelHeight() }} key={this.doc[Id]}>
<ContentFittingDocumentView
Document={layoutDoc}
DataDoc={this.dataDoc}
LibraryPath={emptyPath}
renderDepth={this.props.renderDepth + 1}
rootSelected={returnTrue}
- treeViewId={this.props.treeViewId[Id]}
+ treeViewDoc={undefined}
backgroundColor={this.props.backgroundColor}
fitToBox={this.boundsOfCollectionDocument !== undefined}
FreezeDimensions={true}
@@ -372,17 +368,17 @@ class TreeView extends React.Component<TreeViewProps> {
}
}
- get onCheckedClick() { return this.props.onCheckedClick || ScriptCast(this.props.document.onCheckedClick); }
+ get onCheckedClick() { return this.props.onCheckedClick || ScriptCast(this.doc.onCheckedClick); }
@action
bulletClick = (e: React.MouseEvent) => {
- if (this.onCheckedClick && this.props.document.type !== DocumentType.COL) {
+ if (this.onCheckedClick && this.doc.type !== DocumentType.COL) {
// this.props.document.treeViewChecked = this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check";
this.onCheckedClick.script.run({
- this: this.props.document.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.props.document,
+ this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc,
heading: this.props.containingCollection.title,
- checked: this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check",
- containingTreeView: this.props.treeViewId,
+ checked: this.doc.treeViewChecked === "check" ? "x" : this.doc.treeViewChecked === "x" ? undefined : "check",
+ containingTreeView: this.props.treeViewDoc,
}, console.log);
} else {
this.treeViewOpen = !this.treeViewOpen;
@@ -392,104 +388,110 @@ class TreeView extends React.Component<TreeViewProps> {
@computed
get renderBullet() {
- const checked = this.props.document.type === DocumentType.COL ? undefined : this.onCheckedClick ? (this.props.document.treeViewChecked ? this.props.document.treeViewChecked : "unchecked") : undefined;
+ const checked = this.doc.type === DocumentType.COL ? undefined : this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined;
return <div className="bullet"
title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"}
onClick={this.bulletClick}
- style={{ color: StrCast(this.props.document.color, checked === "unchecked" ? "white" : "inherit"), opacity: checked === "unchecked" ? undefined : 0.4 }}>
+ style={{ color: StrCast(this.doc.color, checked === "unchecked" ? "white" : "inherit"), opacity: checked === "unchecked" ? undefined : 0.4 }}>
{<FontAwesomeIcon icon={checked === "check" ? "check" : (checked === "x" ? "times" : checked === "unchecked" ? "square" : !this.treeViewOpen ? (this.childDocs ? "caret-square-right" : "caret-right") : (this.childDocs ? "caret-square-down" : "caret-down"))} />}
</div>;
}
showContextMenu = (e: React.MouseEvent) => {
this._docRef.current?.ContentDiv && simulateMouseClick(this._docRef.current.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
- e.stopPropagation();
}
focusOnDoc = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(doc)?.props.focus(doc, true);
- contextMenuItems = () => {
- const focusScript = ScriptField.MakeFunction(`DocFocus(self)`);
- return [{ script: focusScript!, label: "Focus" }];
- }
+ contextMenuItems = () => [{ script: ScriptField.MakeFunction(`DocFocus(self)`)!, label: "Focus" }]
+ truncateTitleWidth = () => NumCast(this.props.treeViewDoc.treeViewTruncateTitleWidth, 0);
+ showTitleEdit = () => ["*", this._uniqueId].includes(Doc.GetT(this.doc, "editTitle", "string", true) || "")
/**
* Renders the EditableView title element for placement into the tree.
*/
@computed
get renderTitle() {
TraceMobx();
- (!TreeView._editTitleScript) && (TreeView._editTitleScript = ScriptField.MakeFunction("setInPlace(self, 'editTitle', true)"));
- const headerElements = (
+ const headerElements = this.props.treeViewHideHeaderFields() ? (null) :
<>
- <FontAwesomeIcon icon="cog" size="sm" onClick={e => this.showContextMenu(e)}></FontAwesomeIcon>
+ <FontAwesomeIcon icon="cog" size="sm" onClick={e => { this.showContextMenu(e); e.stopPropagation(); }} />
<span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView}
onPointerDown={action(() => {
if (this.treeViewOpen) {
- this.props.document.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? (Doc.UserDoc().noviceMode ? "layout" : "fields") :
- this.treeViewExpandedView === "fields" && Doc.Layout(this.props.document) ? "layout" :
- this.treeViewExpandedView === "layout" && this.props.document.links ? "links" :
+ this.doc.treeViewExpandedView = this.treeViewExpandedView === this.fieldKey ? (Doc.UserDoc().noviceMode ? "layout" : "fields") :
+ this.treeViewExpandedView === "fields" && this.layoutDoc ? "layout" :
+ this.treeViewExpandedView === "layout" && DocListCast(this.doc.links).length ? "links" :
this.childDocs ? this.fieldKey : (Doc.UserDoc().noviceMode ? "layout" : "fields");
}
this.treeViewOpen = true;
})}>
{this.treeViewExpandedView}
</span>
- </>);
- const openRight = (<div className="treeViewItem-openRight" onClick={this.openRight}>
- <FontAwesomeIcon title="open in pane on right" icon="angle-right" size="lg" />
- </div>);
+ </>;
+ const view = this.showTitleEdit() ? this.editableView("title") :
+ <DocumentView
+ ref={this._docRef}
+ Document={this.doc}
+ DataDoc={undefined}
+ treeViewDoc={this.props.treeViewDoc}
+ LibraryPath={this.props.libraryPath || emptyPath}
+ addDocument={undefined}
+ addDocTab={this.props.addDocTab}
+ rootSelected={returnTrue}
+ pinToPres={emptyFunction}
+ onClick={this.props.onChildClick || this._editTitleScript}
+ dropAction={this.props.dropAction}
+ moveDocument={this.move}
+ removeDocument={this.removeDoc}
+ ScreenToLocalTransform={this.getTransform}
+ ContentScaling={returnOne}
+ PanelWidth={this.truncateTitleWidth}
+ PanelHeight={returnZero}
+ NativeHeight={returnZero}
+ NativeWidth={returnZero}
+ contextMenuItems={this.contextMenuItems}
+ renderDepth={1}
+ focus={returnTrue}
+ parentActive={returnTrue}
+ whenActiveChanged={emptyFunction}
+ bringToFront={emptyFunction}
+ dontRegisterView={BoolCast(this.props.treeViewDoc.dontRegisterChildViews)}
+ docFilters={returnEmptyFilter}
+ ContainingCollectionView={undefined}
+ ContainingCollectionDoc={this.props.containingCollection}
+ />;
return <>
<div className="docContainer" ref={this._tref} title="click to edit title" id={`docContainer-${this.props.parentKey}`}
style={{
- fontWeight: this.props.document.searchMatch ? "bold" : undefined,
- textDecoration: Doc.GetT(this.props.document, "title", "string", true) ? "underline" : undefined,
- outline: BoolCast(this.props.document.workspaceBrush) ? "dashed 1px #06123232" : undefined,
+ fontWeight: this.doc.searchMatch ? "bold" : undefined,
+ textDecoration: Doc.GetT(this.doc, "title", "string", true) ? "underline" : undefined,
+ outline: BoolCast(this.doc.workspaceBrush) ? "dashed 1px #06123232" : undefined,
pointerEvents: this.props.active() || SnappingManager.GetIsDragging() ? undefined : "none"
}} >
- {Doc.GetT(this.props.document, "editTitle", "boolean", true) ?
- this.editableView("title") :
- <DocumentView
- ref={this._docRef}
- Document={this.props.document}
- DataDoc={undefined}
- treeViewId={this.props.treeViewId[Id]}
- LibraryPath={this.props.libraryPath || emptyPath}
- addDocument={undefined}
- addDocTab={this.props.addDocTab}
- rootSelected={returnTrue}
- pinToPres={emptyFunction}
- onClick={this.props.onChildClick || TreeView._editTitleScript}
- dropAction={this.props.dropAction}
- moveDocument={this.move}
- removeDocument={this.removeDoc}
- ScreenToLocalTransform={this.getTransform}
- ContentScaling={returnOne}
- PanelWidth={returnZero}
- PanelHeight={returnZero}
- NativeHeight={returnZero}
- NativeWidth={returnZero}
- contextMenuItems={this.contextMenuItems}
- renderDepth={1}
- focus={returnTrue}
- parentActive={returnTrue}
- whenActiveChanged={emptyFunction}
- bringToFront={emptyFunction}
- dontRegisterView={BoolCast(this.props.treeViewId.dontRegisterChildViews)}
- docFilters={returnEmptyFilter}
- ContainingCollectionView={undefined}
- ContainingCollectionDoc={this.props.containingCollection}
- />}
+ {view}
</div >
- {this.props.treeViewHideHeaderFields() ? (null) : headerElements}
- {openRight}
+ {headerElements}
+ <div className="treeViewItem-openRight" onClick={this.openRight}>
+ <FontAwesomeIcon title="open in pane on right" icon="external-link-alt" size="sm" />
+ </div>
</>;
}
render() {
TraceMobx();
- const sorting = this.props.document[`${this.fieldKey}-sortAscending`];
- //setTimeout(() => runInAction(() => untracked(() => this._overrideTreeViewOpen = this.treeViewOpen)), 0);
+ const sorting = this.doc[`${this.fieldKey}-sortAscending`];
+ if (this.showTitleEdit()) { // find containing CollectionTreeView and set our maximum width so the containing tree view won't have to scroll
+ let par: any = this._header?.current;
+ if (par) {
+ while (par && par.className !== "collectionTreeView-dropTarget") par = par.parentNode;
+ if (par) {
+ const par_rect = (par as HTMLElement).getBoundingClientRect();
+ const my_recct = this._docRef.current?.ContentDiv?.getBoundingClientRect();
+ this._editMaxWidth = Math.max(100, par_rect.right - (my_recct?.left || 0));
+ }
+ }
+ } else this._editMaxWidth = "";
return <div className="treeViewItem-container" ref={this.createTreeDropTarget} onPointerDown={e => this.props.active() && SelectionManager.DeselectAll()}>
<li className="collection-child">
- <div className="treeViewItem-header" ref={this._header} onClick={e => {
+ <div className={`treeViewItem-header` + (this._editMaxWidth ? "-editing" : "")} ref={this._header} style={{ maxWidth: this._editMaxWidth }} onClick={e => {
if (this.props.active(true)) {
e.stopPropagation();
e.preventDefault();
@@ -507,14 +509,14 @@ class TreeView extends React.Component<TreeViewProps> {
{this.renderTitle}
</div>
<div className="treeViewItem-border" style={{ borderColor: sorting === undefined ? undefined : sorting ? "crimson" : "blue" }}>
- {!this.treeViewOpen || this.props.renderedIds.indexOf(this.props.document[Id]) !== -1 ? (null) : this.renderContent}
+ {!this.treeViewOpen || this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? (null) : this.renderContent}
</div>
</li>
</div>;
}
public static GetChildElements(
childDocs: Doc[],
- treeViewId: Doc,
+ treeViewDoc: Doc,
containingCollection: Doc,
dataDoc: Doc | undefined,
key: string,
@@ -624,7 +626,7 @@ class TreeView extends React.Component<TreeViewProps> {
libraryPath={libraryPath ? [...libraryPath, containingCollection] : undefined}
containingCollection={containingCollection}
prevSibling={docs[i]}
- treeViewId={treeViewId}
+ treeViewDoc={treeViewDoc}
key={child[Id]}
indentDocument={indent}
outdentDocument={outdent}
@@ -665,21 +667,22 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
private treedropDisposer?: DragManager.DragDropDisposer;
private _mainEle?: HTMLDivElement;
- @computed get dataDoc() { return this.props.DataDoc || this.props.Document; }
+ @computed get doc() { return this.props.Document; }
+ @computed get dataDoc() { return this.props.DataDoc || this.doc; }
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this.treedropDisposer?.();
if (this._mainEle = ele) {
- this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.props.Document, this.onInternalPreDrop.bind(this));
+ this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.doc, this.onInternalPreDrop.bind(this));
}
}
protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => {
const dragData = de.complete.docDragData;
if (dragData) {
- if (targetAction && !dragData.draggedDocuments.some(d => d.context === this.props.Document && this.childDocs.includes(d))) {
+ if (targetAction && !dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d))) {
dragData.dropAction = targetAction;
- } else dragData.dropAction = this.props.Document[Id] === dragData?.treeViewId ? "same" : dragData.dropAction;
+ } else dragData.dropAction = this.doc === dragData?.treeViewDoc ? "same" : dragData.dropAction;
}
}
@@ -691,7 +694,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
@action
remove = (doc: Doc | Doc[]): boolean => {
const docs = doc instanceof Doc ? [doc] : doc;
- const targetDataDoc = this.props.Document[DataSym];
+ const targetDataDoc = this.doc[DataSym];
const value = DocListCast(targetDataDoc[this.props.fieldKey]);
const result = value.filter(v => !docs.includes(v));
if (result.length !== value.length) {
@@ -704,9 +707,9 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
addDoc = (doc: Doc | Doc[], relativeTo: Opt<Doc>, before?: boolean): boolean => {
const doAddDoc = (doc: Doc | Doc[]) =>
(doc instanceof Doc ? [doc] : doc).reduce((flg, doc) =>
- flg && Doc.AddDocToList(this.props.Document[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false), true);
- if (this.props.Document.resolvedDataDoc instanceof Promise) {
- this.props.Document.resolvedDataDoc.then((resolved: any) => doAddDoc(doc));
+ flg && Doc.AddDocToList(this.doc[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false), true);
+ if (this.doc.resolvedDataDoc instanceof Promise) {
+ this.doc.resolvedDataDoc.then((resolved: any) => doAddDoc(doc));
} else {
doAddDoc(doc);
}
@@ -714,22 +717,23 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
}
onContextMenu = (e: React.MouseEvent): void => {
// need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
- if (!e.isPropagationStopped() && this.props.Document === Doc.UserDoc().myWorkspaces) {
+ if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myWorkspaces) {
ContextMenu.Instance.addItem({ description: "Create Workspace", event: () => MainView.Instance.createNewWorkspace(), icon: "plus" });
- ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.remove(this.props.Document), icon: "minus" });
+ ContextMenu.Instance.addItem({ description: "Delete Workspace", event: () => this.remove(this.doc), icon: "minus" });
e.stopPropagation();
e.preventDefault();
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
- } else if (!e.isPropagationStopped() && this.props.Document === Doc.UserDoc().myRecentlyClosed) {
+ } else if (!e.isPropagationStopped() && this.doc === Doc.UserDoc().myRecentlyClosed) {
ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.UserDoc().myRecentlyClosed = new List<Doc>(), icon: "plus" });
e.stopPropagation();
e.preventDefault();
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
} else {
const layoutItems: ContextMenuProps[] = [];
- layoutItems.push({ description: (this.props.Document.treeViewPreventOpen ? "Persist" : "Abandon") + "Treeview State", event: () => this.props.Document.treeViewPreventOpen = !this.props.Document.treeViewPreventOpen, icon: "paint-brush" });
- layoutItems.push({ description: (this.props.Document.treeViewHideHeaderFields ? "Show" : "Hide") + " Header Fields", event: () => this.props.Document.treeViewHideHeaderFields = !this.props.Document.treeViewHideHeaderFields, icon: "paint-brush" });
- layoutItems.push({ description: (this.props.Document.treeViewHideTitle ? "Show" : "Hide") + " Title", event: () => this.props.Document.treeViewHideTitle = !this.props.Document.treeViewHideTitle, icon: "paint-brush" });
+ layoutItems.push({ description: (this.doc.treeViewPreventOpen ? "Persist" : "Abandon") + "Treeview State", event: () => this.doc.treeViewPreventOpen = !this.doc.treeViewPreventOpen, icon: "paint-brush" });
+ layoutItems.push({ description: (this.doc.treeViewHideHeaderFields ? "Show" : "Hide") + " Header Fields", event: () => this.doc.treeViewHideHeaderFields = !this.doc.treeViewHideHeaderFields, icon: "paint-brush" });
+ layoutItems.push({ description: (this.doc.treeViewHideTitle ? "Show" : "Hide") + " Title", event: () => this.doc.treeViewHideTitle = !this.doc.treeViewHideTitle, icon: "paint-brush" });
+ layoutItems.push({ description: (this.doc.treeViewHideLinkLines ? "Show" : "Hide") + " Link Lines", event: () => this.doc.treeViewHideLinkLines = !this.doc.treeViewHideLinkLines, icon: "paint-brush" });
ContextMenu.Instance.addItem({ description: "Options...", subitems: layoutItems, icon: "eye" });
}
!Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({
@@ -745,7 +749,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
const fallback = ImageDocument("http://cs.brown.edu/~bcz/face.gif", { _width: 400 }); // replace with desired double click target
let pdfContent: string;
- DocListCast(this.dataDoc[this.props.fieldKey]).map(d => {
+ this.childDocs?.map(d => {
DocListCast(d.data).map((img, i) => {
const caption = (d.captions as any)[i];
if (caption) {
@@ -774,7 +778,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
const existingOnClick = ContextMenu.Instance.findByDescription("OnClick...");
const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
onClicks.push({
- description: "Edit onChecked Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit"
+ description: "Edit onChecked Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.doc, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit"
});
!existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
}
@@ -784,7 +788,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
@computed get renderClearButton() {
return <div id="toolbar" key="toolbar">
<button className="toolbar-button round-button" title="Empty"
- onClick={undoBatch(action(() => Doc.GetProto(this.props.Document)[this.props.fieldKey] = undefined))}>
+ onClick={undoBatch(action(() => Doc.GetProto(this.doc)[this.props.fieldKey] = undefined))}>
<FontAwesomeIcon icon={"trash"} size="sm" />
</button>
</div >;
@@ -795,51 +799,51 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
}
render() {
TraceMobx();
- if (!(this.props.Document instanceof Doc)) return (null);
- const dropAction = StrCast(this.props.Document.childDropAction) as dropActionType;
+ if (!(this.doc instanceof Doc)) return (null);
+ const dropAction = StrCast(this.doc.childDropAction) as dropActionType;
const addDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument(d, target, addDoc);
const childDocs = this.props.overrideDocuments ? this.props.overrideDocuments : this.childDocs;
return !childDocs ? (null) : (
- <div className="collectionTreeView-dropTarget" id="body"
- style={{
- background: this.props.backgroundColor?.(this.props.Document),
- paddingLeft: `${NumCast(this.props.Document._xPadding, 10)}px`,
- paddingRight: `${NumCast(this.props.Document._xPadding, 10)}px`,
- paddingTop: `${NumCast(this.props.Document._yPadding, 20)}px`,
- pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined
- }}
- onKeyPress={this.onKeyPress}
- onContextMenu={this.onContextMenu}
- onWheel={(e: React.WheelEvent) => this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()}
- onDrop={this.onTreeDrop}
- ref={this.createTreeDropTarget}>
- {(this.props.treeViewHideTitle || this.props.Document.treeViewHideTitle ? (null) : <EditableView
- contents={this.dataDoc.title}
- editing={false}
- display={"block"}
- maxHeight={72}
- height={"auto"}
- GetValue={() => StrCast(this.dataDoc.title)}
- SetValue={undoBatch((value: string) => Doc.SetInPlace(this.dataDoc, "title", value, false) || true)}
- OnFillDown={undoBatch((value: string) => {
- Doc.SetInPlace(this.dataDoc, "title", value, false);
- const doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List<string>([Templates.Title.Layout]) });
- EditableView.loadId = doc[Id];
- Doc.SetInPlace(doc, "editTitle", true, false);
- this.addDoc(doc, childDocs.length ? childDocs[0] : undefined, true);
- })} />)}
- {this.props.Document.allowClear ? this.renderClearButton : (null)}
- <ul className="no-indent" style={{ width: "max-content" }} >
- {
- TreeView.GetChildElements(childDocs, this.props.Document, this.props.Document, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove,
- moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform,
- this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.props.Document.treeViewHideHeaderFields),
- BoolCast(this.props.Document.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick,
- this.props.onChildClick || ScriptCast(this.props.Document.onChildClick), this.props.ignoreFields)
- }
- </ul>
- </div >
+ <div className="collectionTreeView-container" onContextMenu={this.onContextMenu}>
+ <div className="collectionTreeView-dropTarget" id="body"
+ style={{
+ background: this.props.backgroundColor?.(this.doc),
+ paddingLeft: `${NumCast(this.doc._xPadding, 10)}px`,
+ paddingRight: `${NumCast(this.doc._xPadding, 10)}px`,
+ paddingTop: `${NumCast(this.doc._yPadding, 20)}px`,
+ pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined
+ }}
+ onKeyPress={this.onKeyPress}
+ onWheel={(e) => this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()}
+ onDrop={this.onTreeDrop}
+ ref={this.createTreeDropTarget}>
+ {this.props.treeViewHideTitle || this.doc.treeViewHideTitle ? (null) : <EditableView
+ contents={this.dataDoc.title}
+ editing={false}
+ display={"block"}
+ maxHeight={72}
+ height={"auto"}
+ GetValue={() => StrCast(this.dataDoc.title)}
+ SetValue={undoBatch((value: string) => Doc.SetInPlace(this.dataDoc, "title", value, false) || true)}
+ OnFillDown={undoBatch((value: string) => {
+ Doc.SetInPlace(this.dataDoc, "title", value, false);
+ const doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, _width: 100, _height: 25, _LODdisable: true, templates: new List<string>([Templates.Title.Layout]) });
+ Doc.SetInPlace(doc, "editTitle", "*", false);
+ this.addDoc(doc, childDocs.length ? childDocs[0] : undefined, true);
+ })} />}
+ {this.doc.allowClear ? this.renderClearButton : (null)}
+ <ul className="no-indent" style={{ width: "max-content" }} >
+ {
+ TreeView.GetChildElements(childDocs, this.doc, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove,
+ moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform,
+ this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
+ BoolCast(this.doc.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick,
+ this.props.onChildClick || ScriptCast(this.doc.onChildClick), this.props.ignoreFields)
+ }
+ </ul>
+ </div >
+ </div>
);
}
}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 508b9e5e7..469ae9f0e 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -106,7 +106,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
get collectionViewType(): CollectionViewType | undefined {
const viewField = StrCast(this.props.Document._viewType);
if (CollectionView._safeMode) {
- if (viewField === CollectionViewType.Freeform) {
+ if (viewField === CollectionViewType.Freeform || viewField === CollectionViewType.Schema) {
return CollectionViewType.Tree;
}
if (viewField === CollectionViewType.Invalid) {
@@ -191,7 +191,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
// return !allTagged ? (null) : <img id={"google-tags"} src={"/assets/google_tags.png"} />;
}
- screenToLocalTransform = () => this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth());
+ screenToLocalTransform = () => this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth());
private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
const props: SubCollectionViewProps = { ...this.props, ...renderProps, ScreenToLocalTransform: this.screenToLocalTransform, CollectionView: this, annotationsKey: "" };
switch (type) {
@@ -521,7 +521,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
return (<div className={"collectionView"} onContextMenu={this.onContextMenu}
style={{ pointerEvents: this.props.Document.isBackground ? "none" : undefined, boxShadow }}>
{this.showIsTagged()}
- <div className="collectionView-facetCont" style={{ width: `calc(100% - ${this.facetWidth()}px)` }}>
+ <div className="collectionView-facetCont" style={{ height: "100%", position: "absolute", width: this.props.PanelWidth() - this.facetWidth() }}>
{this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)}
</div>
{this.lightbox(DocListCast(this.props.Document[this.props.fieldKey]).filter(d => d.type === DocumentType.IMG).map(d =>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index ae81b4b36..1a2421bfd 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -10,6 +10,7 @@ import React = require("react");
import { Utils, emptyFunction } from "../../../../Utils";
import { DocumentType } from "../../../documents/DocumentTypes";
import { SnappingManager } from "../../../util/SnappingManager";
+import { Cast } from "../../../../fields/Types";
@observer
export class CollectionFreeFormLinksView extends React.Component {
@@ -30,8 +31,8 @@ export class CollectionFreeFormLinksView extends React.Component {
return drawnPairs;
}, [] as { a: DocumentView, b: DocumentView, l: Doc[] }[]);
return connections.filter(c =>
- c.a.props.Document.type === DocumentType.LINK &&
- c.a.props.pinToPres !== emptyFunction && c.b.props.pinToPres !== emptyFunction // bcz: this prevents links to be drawn to anchors in CollectionTree views -- this is a hack that should be fixed
+ c.a.props.Document.type === DocumentType.LINK
+ && !c.a.props.treeViewDoc?.treeViewHideLinkLines && !c.b.props.treeViewDoc?.treeViewHideLinkLines
).map(c => <CollectionFreeFormLinkView key={Utils.GenerateGuid()} A={c.a} B={c.b} LinkDocs={c.l} />);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index d9011c9d3..92aee3776 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -1,7 +1,6 @@
@import "../../globalCssVariables";
-.collectionfreeformview-none,
-.collectionfreeformview-ease {
+.collectionfreeformview-none {
position: inherit;
top: 0;
left: 0;
@@ -22,10 +21,6 @@
}
}
-.collectionfreeformview-ease {
- transition: transform 500ms;
-}
-
.collectionfreeformview-none {
touch-action: none;
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 2e543f137..5135c4ae4 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -63,7 +63,7 @@ export const panZoomSchema = createSchema({
fitToBox: "boolean",
_xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set
_yPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set
- panTransformType: "string",
+ _viewTransition: "string",
scrollHeight: "number",
fitX: "number",
fitY: "number",
@@ -110,9 +110,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@computed get nativeWidth() { return this.fitToContent ? 0 : NumCast(this.Document._nativeWidth, this.props.NativeWidth()); }
@computed get nativeHeight() { return this.fitToContent ? 0 : NumCast(this.Document._nativeHeight, this.props.NativeHeight()); }
private get isAnnotationOverlay() { return this.props.isAnnotationOverlay; }
- private get scaleFieldKey() { return this.props.scaleField || "scale"; }
+ private get scaleFieldKey() { return this.props.scaleField || "_viewScale"; }
private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; }
- private easing = () => this.props.Document.panTransformType === "Ease";
private panX = () => this.fitToContent ? (this.contentBounds.x + this.contentBounds.r) / 2 : this.Document._panX || 0;
private panY = () => this.fitToContent ? (this.contentBounds.y + this.contentBounds.b) / 2 : this.Document._panY || 0;
private zoomScaling = () => (this.fitToContentScaling / this.parentScaling) * (this.fitToContent ?
@@ -832,7 +831,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
}
}
if (!this.layoutDoc._lockedTransform || this.Document.inOverlay) {
- this.Document.panTransformType = panType;
+ this.Document._viewTransition = panType;
const scale = this.getLocalTransform().inverse().Scale;
const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX));
const newPanY = Math.min((this.props.Document.scrollHeight !== undefined ? NumCast(this.Document.scrollHeight) : (1 - 1 / scale) * this.nativeHeight), Math.max(0, panY));
@@ -860,7 +859,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
scaleAtPt(docpt: number[], scale: number) {
const screenXY = this.getTransform().inverse().transformPoint(docpt[0], docpt[1]);
- this.Document.panTransformType = "Ease";
+ this.Document._viewTransition = "transform 500ms";
this.layoutDoc[this.scaleFieldKey] = scale;
const newScreenXY = this.getTransform().inverse().transformPoint(docpt[0], docpt[1]);
const scrDelta = { x: screenXY[0] - newScreenXY[0], y: screenXY[1] - newScreenXY[1] };
@@ -905,14 +904,14 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
newState.initializers![this.Document[Id]] = { panX: newPanX, panY: newPanY };
HistoryUtil.pushState(newState);
- const savedState = { px: this.Document._panX, py: this.Document._panY, s: this.Document[this.scaleFieldKey], pt: this.Document.panTransformType };
+ const savedState = { px: this.Document._panX, py: this.Document._panY, s: this.Document[this.scaleFieldKey], pt: this.Document._viewTransition };
// if (!willZoom && DocumentView._focusHack.length) {
// Doc.BrushDoc(this.props.Document);
// !doc.z && NumCast(this.layoutDoc.scale) < 1 && this.scaleAtPt(DocumentView._focusHack, 1); // [NumCast(doc.x), NumCast(doc.y)], 1);
// } else {
if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) {
- if (!doc.z) this.setPan(newPanX, newPanY, "Ease", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
+ if (!doc.z) this.setPan(newPanX, newPanY, "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
}
Doc.BrushDoc(this.props.Document);
this.props.focus(this.props.Document);
@@ -925,7 +924,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this.Document._panX = savedState.px;
this.Document._panY = savedState.py;
this.Document[this.scaleFieldKey] = savedState.s;
- this.Document.panTransformType = savedState.pt;
+ this.Document._viewTransition = savedState.pt;
}
}, 500);
}
@@ -1011,7 +1010,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
const { z, color, zIndex } = params.pair.layout;
return {
x: NumCast(x), y: NumCast(y), z: Cast(z, "number"), color: StrCast(color), zIndex: Cast(zIndex, "number"),
- transition: StrCast(layoutDoc.transition), opacity: this.Document.editing ? 1 : Cast(opacity, "number", null),
+ transition: StrCast(layoutDoc.dataTransition), opacity: this.Document.editing ? 1 : Cast(opacity, "number", null),
width: Cast(layoutDoc._width, "number"), height: Cast(layoutDoc._height, "number"), pair: params.pair, replica: ""
};
}
@@ -1333,9 +1332,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
nudge = action((x: number, y: number) => {
if (this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform) { // bcz: this isn't ideal, but want to try it out...
this.setPan(NumCast(this.layoutDoc._panX) + this.props.PanelWidth() / 2 * x / this.zoomScaling(),
- NumCast(this.layoutDoc._panY) + this.props.PanelHeight() / 2 * (-y) / this.zoomScaling(), "Ease", true);
+ NumCast(this.layoutDoc._panY) + this.props.PanelHeight() / 2 * (-y) / this.zoomScaling(), "transform 500ms", true);
this._nudgeTime = Date.now();
- setTimeout(() => (Date.now() - this._nudgeTime >= 500) && (this.Document.panTransformType = undefined), 500);
+ setTimeout(() => (Date.now() - this._nudgeTime >= 500) && (this.Document._viewTransition = undefined), 500);
return true;
}
return false;
@@ -1354,8 +1353,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
<CollectionFreeFormViewPannableContents
centeringShiftX={this.centeringShiftX}
centeringShiftY={this.centeringShiftY}
- easing={this.easing}
- transition={Cast(this.layoutDoc.transition, "string", null)}
+ transition={Cast(this.layoutDoc._viewTransition, "string", null)}
viewDefDivClick={this.props.viewDefDivClick}
zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
{this.children}
@@ -1434,7 +1432,6 @@ interface CollectionFreeFormViewPannableContentsProps {
panX: () => number;
panY: () => number;
zoomScaling: () => number;
- easing: () => boolean;
viewDefDivClick?: ScriptField;
children: () => JSX.Element[];
transition?: string;
@@ -1443,7 +1440,7 @@ interface CollectionFreeFormViewPannableContentsProps {
@observer
class CollectionFreeFormViewPannableContents extends React.Component<CollectionFreeFormViewPannableContentsProps>{
render() {
- const freeformclass = "collectionfreeformview" + (this.props.viewDefDivClick ? "-viewDef" : (this.props.easing() ? "-ease" : "-none"));
+ const freeformclass = "collectionfreeformview" + (this.props.viewDefDivClick ? "-viewDef" : "-none");
const cenx = this.props.centeringShiftX();
const ceny = this.props.centeringShiftY();
const panx = -this.props.panX();
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 404d69730..090beba0b 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -22,7 +22,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
zIndex?: number;
highlight?: boolean;
jitterRotation: number;
- transition?: string;
+ dataTransition?: string;
fitToBox?: boolean;
replica: string;
}
@@ -60,10 +60,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
const someView = Cast(this.props.Document.someView, Doc);
const minimap = Cast(this.props.Document.minimap, Doc);
if (someView instanceof Doc && minimap instanceof Doc) {
- const x = (NumCast(someView._panX) - NumCast(someView._width) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitX) - NumCast(minimap.fitW) / 2)) / NumCast(minimap.fitW) * NumCast(minimap._width) - NumCast(minimap._width) / 2;
- const y = (NumCast(someView._panY) - NumCast(someView._height) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitY) - NumCast(minimap.fitH) / 2)) / NumCast(minimap.fitH) * NumCast(minimap._height) - NumCast(minimap._height) / 2;
- const w = NumCast(someView._width) / NumCast(someView.scale) / NumCast(minimap.fitW) * NumCast(minimap.width);
- const h = NumCast(someView._height) / NumCast(someView.scale) / NumCast(minimap.fitH) * NumCast(minimap.height);
+ const x = (NumCast(someView._panX) - NumCast(someView._width) / 2 / NumCast(someView._viewScale) - (NumCast(minimap.fitX) - NumCast(minimap.fitW) / 2)) / NumCast(minimap.fitW) * NumCast(minimap._width) - NumCast(minimap._width) / 2;
+ const y = (NumCast(someView._panY) - NumCast(someView._height) / 2 / NumCast(someView._viewScale) - (NumCast(minimap.fitY) - NumCast(minimap.fitH) / 2)) / NumCast(minimap.fitH) * NumCast(minimap._height) - NumCast(minimap._height) / 2;
+ const w = NumCast(someView._width) / NumCast(someView._viewScale) / NumCast(minimap.fitW) * NumCast(minimap.width);
+ const h = NumCast(someView._height) / NumCast(someView._viewScale) / NumCast(minimap.fitH) * NumCast(minimap.height);
return { x: x, y: y, width: w, height: h };
}
}
@@ -81,9 +81,15 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
public static setValues(time: number, d: Doc, x?: number, y?: number, opacity?: number) {
const timecode = Math.round(time);
- Cast(d["x-indexed"], listSpec("number"), [])[timecode] = x as any as number;
- Cast(d["y-indexed"], listSpec("number"), [])[timecode] = y as any as number;
- Cast(d["opacity-indexed"], listSpec("number"), null)[timecode] = opacity as any as number;
+ const xindexed = Cast(d["x-indexed"], listSpec("number"), []).slice();
+ const yindexed = Cast(d["y-indexed"], listSpec("number"), []).slice();
+ const oindexed = Cast(d["opacity-indexed"], listSpec("number"), []).slice();
+ xindexed[timecode] = x as any as number;
+ yindexed[timecode] = y as any as number;
+ oindexed[timecode] = opacity as any as number;
+ d["x-indexed"] = new List<number>(xindexed);
+ d["y-indexed"] = new List<number>(yindexed);
+ d["opacity-indexed"] = new List<number>(oindexed);
}
public static updateKeyframe(docs: Doc[], time: number) {
const timecode = Math.round(time);
@@ -94,14 +100,14 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
xindexed?.length <= timecode + 1 && xindexed.push(undefined as any as number);
yindexed?.length <= timecode + 1 && yindexed.push(undefined as any as number);
opacityindexed?.length <= timecode + 1 && opacityindexed.push(undefined as any as number);
- doc.transition = "all 1s";
+ doc.dataTransition = "all 1s";
});
- setTimeout(() => docs.forEach(doc => doc.transition = "inherit"), 1010);
+ setTimeout(() => docs.forEach(doc => doc.dataTransition = "inherit"), 1010);
}
public static gotoKeyframe(docs: Doc[]) {
- docs.forEach(doc => doc.transition = "all 1s");
- setTimeout(() => docs.forEach(doc => doc.transition = "inherit"), 1010);
+ docs.forEach(doc => doc.dataTransition = "all 1s");
+ setTimeout(() => docs.forEach(doc => doc.dataTransition = "inherit"), 1010);
}
public static setupKeyframes(docs: Doc[], timecode: number, progressivize: boolean = false) {
@@ -119,7 +125,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
doc.x = ComputedField.MakeInterpolated("x", "activeFrame");
doc.y = ComputedField.MakeInterpolated("y", "activeFrame");
doc.opacity = ComputedField.MakeInterpolated("opacity", "activeFrame");
- doc.transition = "inherit";
+ doc.dataTransition = "inherit";
});
}
@@ -150,7 +156,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
borderRadius: StrCast(Doc.Layout(this.layoutDoc).borderRounding),
outline: this.Highlight ? "orange solid 2px" : "",
transform: this.transform,
- transition: this.props.transition ? this.props.transition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.transition),
+ transition: this.props.transition ? this.props.transition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.dataTransition),
width: this.props.Document.isInkMask ? 5000 : this.width,
height: this.props.Document.isInkMask ? 5000 : this.height,
zIndex: this.ZInd,
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index b7726f7ba..b978f6245 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -42,6 +42,17 @@
width:10px !important;
}
}
+ .documentView-treeView {
+ max-height: 1.5em;
+ text-overflow: ellipsis;
+ display: inline-block;
+ white-space: pre;
+ width: 100%;
+ overflow: hidden;
+ > .documentView-node {
+ position: absolute;
+ }
+ }
.documentView-lock {
width: 20;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a2bb9700e..342bbc606 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -69,7 +69,7 @@ export interface DocumentViewProps {
onDoubleClick?: ScriptField;
onPointerDown?: ScriptField;
onPointerUp?: ScriptField;
- treeViewId?: string;
+ treeViewDoc?: Doc;
dropAction?: dropActionType;
dragDivName?: string;
nudge?: (x: number, y: number) => void;
@@ -237,7 +237,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
dragData.removeDocument = this.props.removeDocument;
dragData.moveDocument = this.props.moveDocument;// this.layoutDoc.onDragStart ? undefined : this.props.moveDocument;
dragData.dragDivName = this.props.dragDivName;
- dragData.treeViewId = this.props.treeViewId;
+ dragData.treeViewDoc = this.props.treeViewDoc;
DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.layoutDoc.onDragStart });
}
}
@@ -1071,30 +1071,34 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
anchorPanelHeight = () => this.props.PanelHeight() || 1;
@computed get anchors() {
TraceMobx();
- return this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.layoutDoc.presBox || this.props.dontRegisterView ? (null) : DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) =>
- <DocumentView {...this.props} key={i + 1}
- Document={d}
- ContainingCollectionView={this.props.ContainingCollectionView}
- ContainingCollectionDoc={this.props.Document} // bcz: hack this.props.Document is not a collection Need a better prop for passing the containing document to the LinkAnchorBox
- PanelWidth={this.anchorPanelWidth}
- PanelHeight={this.anchorPanelHeight}
- ContentScaling={returnOne}
- dontRegisterView={false}
- forcedBackgroundColor={returnTransparent}
- removeDocument={this.hideLinkAnchor}
- pointerEvents={false}
- LayoutTemplate={undefined}
- LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(d, this.props.Document)}`)}
- />);
+ return (this.props.treeViewDoc && this.props.LayoutTemplateString) || // render nothing for: tree view anchor dots
+ this.layoutDoc.presBox || // presentationbox nodes
+ this.props.dontRegisterView ? (null) : // view that are not registered
+ DocListCast(this.Document.links).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) =>
+ <DocumentView {...this.props} key={i + 1}
+ Document={d}
+ ContainingCollectionView={this.props.ContainingCollectionView}
+ ContainingCollectionDoc={this.props.Document} // bcz: hack this.props.Document is not a collection Need a better prop for passing the containing document to the LinkAnchorBox
+ PanelWidth={this.anchorPanelWidth}
+ PanelHeight={this.anchorPanelHeight}
+ ContentScaling={returnOne}
+ dontRegisterView={false}
+ forcedBackgroundColor={returnTransparent}
+ removeDocument={this.hideLinkAnchor}
+ pointerEvents={false}
+ LayoutTemplate={undefined}
+ LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(d, this.props.Document)}`)}
+ />);
}
@computed get innards() {
TraceMobx();
- if (!this.props.PanelWidth()) { // this happens when the document is a tree view label
- return <div className="documentView-linkAnchorBoxAnchor" >
+ if (this.props.treeViewDoc && !this.props.LayoutTemplateString) { // this happens when the document is a tree view label (but not an anchor dot)
+ return <div className="documentView-treeView" style={{ maxWidth: this.props.PanelWidth() || undefined }}>
{StrCast(this.props.Document.title)}
{this.anchors}
</div>;
}
+
const showTitle = StrCast(this.layoutDoc._showTitle);
const showTitleHover = StrCast(this.layoutDoc._showTitleHover);
const showCaption = StrCast(this.layoutDoc._showCaption);
@@ -1156,7 +1160,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(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.props.renderDepth > 0 && this.props.PanelWidth() > 0 ?
+ this.props.renderDepth > 0 && !this.props.treeViewDoc ?
<div className="documentView-lock" onClick={() => this.toggleBackground(true)}>
<FontAwesomeIcon icon={this.Document.isBackground ? "unlock" : "lock"} style={{ color: this.Document.isBackground ? "red" : undefined }} size="lg" />
</div>
@@ -1198,7 +1202,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
style={{
transformOrigin: this._animateScalingTo ? "center center" : undefined,
transform: this._animateScalingTo ? `scale(${this._animateScalingTo})` : undefined,
- transition: !this._animateScalingTo ? StrCast(this.Document.transition) : this._animateScalingTo < 1 ? "transform 0.5s ease-in" : "transform 0.5s ease-out",
+ transition: !this._animateScalingTo ? StrCast(this.Document.dataTransition) : this._animateScalingTo < 1 ? "transform 0.5s ease-in" : "transform 0.5s ease-out",
pointerEvents: this.ignorePointerEvents ? "none" : undefined,
color: StrCast(this.layoutDoc.color, "inherit"),
outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px",
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 2bcc6168b..d4ab70200 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -115,8 +115,9 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch
render() {
TraceMobx();
- const x = this.props.PanelWidth() > 1 ? NumCast(this.rootDoc[this.fieldKey + "_x"], 100) : 0;
- const y = this.props.PanelWidth() > 1 ? NumCast(this.rootDoc[this.fieldKey + "_y"], 100) : 0;
+ const small = this.props.PanelWidth() <= 1; // this happens when rendered in a treeView
+ const x = NumCast(this.rootDoc[this.fieldKey + "_x"], 100);
+ const y = NumCast(this.rootDoc[this.fieldKey + "_y"], 100);
const c = StrCast(this.layoutDoc._backgroundColor, StrCast(this.layoutDoc.backgroundColor, StrCast(this.dataDoc.backgroundColor, "lightBlue"))); // note this is not where the typical lightBlue default color comes from. See Documents.Create.LinkDocument()
const anchor = this.fieldKey === "anchor1" ? "anchor2" : "anchor1";
const anchorScale = (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : .25;
@@ -131,7 +132,6 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch
</div>}
</div>
);
- const small = this.props.PanelWidth() <= 1;
return <div className={`linkAnchorBox-cont${small ? "-small" : ""} ${this.rootDoc[Id]}`}
onPointerLeave={action(() => LinkDocPreview.LinkInfo = undefined)}
onPointerEnter={action(e => LinkDocPreview.LinkInfo = {
@@ -143,8 +143,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch
onPointerDown={this.onPointerDown} onClick={this.onClick} title={targetTitle} onContextMenu={this.specificContextMenu}
ref={this._ref} style={{
background: c,
- left: !small ? `calc(${x}% - 7.5px)` : undefined,
- top: !small ? `calc(${y}% - 7.5px)` : undefined,
+ left: `calc(${x}% - ${small ? 2.5 : 7.5}px)`,
+ top: `calc(${y}% - ${small ? 2.5 : 7.5}px)`,
transform: `scale(${anchorScale / this.props.ContentScaling()})`
}} >
{!this._editing && !this._forceOpen ? (null) :
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index dbc879920..8818d375e 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -62,8 +62,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
const lastFrame = Cast(presTargetDoc.lastFrame, "number", null);
const curFrame = NumCast(presTargetDoc.currentFrame);
if (lastFrame !== undefined && curFrame < lastFrame) {
- presTargetDoc.transition = "all 1s";
- setTimeout(() => presTargetDoc.transition = undefined, 1010);
+ presTargetDoc._viewTransition = "all 1s";
+ setTimeout(() => presTargetDoc._viewTransition = undefined, 1010);
presTargetDoc.currentFrame = curFrame + 1;
}
else if (this.childDocs[this.itemIndex + 1] !== undefined) {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 135ab8cbc..7bc1078d7 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1221,7 +1221,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
tryUpdateHeight(limitHeight?: number) {
let scrollHeight = this._ref.current?.scrollHeight;
if (this.props.renderDepth && this.layoutDoc._autoHeight && !this.props.ignoreAutoHeight && scrollHeight) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation
- scrollHeight = scrollHeight * NumCast(this.layoutDoc.scale, 1);
+ scrollHeight = scrollHeight * NumCast(this.layoutDoc._viewScale, 1);
if (limitHeight && scrollHeight > limitHeight) {
scrollHeight = limitHeight;
this.layoutDoc.limitHeight = undefined;
@@ -1250,7 +1250,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
@computed get sidebarColor() { return StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "transparent")); }
render() {
TraceMobx();
- const scale = this.props.ContentScaling() * NumCast(this.layoutDoc.scale, 1);
+ const scale = this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
const interactive = Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground;
if (this.props.isSelected()) {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index bd74e0dd0..64f150dd5 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -433,7 +433,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
this._downX = e.clientX;
this._downY = e.clientY;
addStyleSheetRule(PDFViewer._annotationStyle, "pdfAnnotation", { "pointer-events": "none" });
- if ((this.Document.scale || 1) !== 1) return;
+ if ((this.Document._viewScale || 1) !== 1) return;
if ((e.button !== 0 || e.altKey) && this.active(true)) {
this._setPreviewCursor?.(e.clientX, e.clientY, true);
//e.stopPropagation();
@@ -641,11 +641,13 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
@action
onZoomWheel = (e: React.WheelEvent) => {
- e.stopPropagation();
- if (e.ctrlKey) {
- const curScale = Number(this._pdfViewer.currentScaleValue);
- this._pdfViewer.currentScaleValue = Math.max(1, Math.min(10, curScale - curScale * e.deltaY / 1000));
- this._zoomed = Number(this._pdfViewer.currentScaleValue);
+ if (this.active()) {
+ e.stopPropagation();
+ if (e.ctrlKey) {
+ const curScale = Number(this._pdfViewer.currentScaleValue);
+ this._pdfViewer.currentScaleValue = Math.max(1, Math.min(10, curScale - curScale * e.deltaY / 1000));
+ this._zoomed = Number(this._pdfViewer.currentScaleValue);
+ }
}
}
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index 74262d81a..2436bf418 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -85,7 +85,7 @@ export class SelectorContextMenu extends React.Component<SearchItemProps> {
const item = React.createRef<HTMLDivElement>();
return <div className="collection" key={doc.col[Id] + doc.target[Id]} ref={item}>
<div className="collection-item" onPointerDown={
- SetupDrag(item, () => doc.col, undefined, undefined, undefined, undefined, () => SearchBox.Instance.closeSearch())}>
+ SetupDrag(item, () => doc.col, undefined, undefined, () => SearchBox.Instance.closeSearch())}>
<FontAwesomeIcon icon={faStickyNote} />
</div>
<a onClick={this.getOnClick(doc)}>{doc.col.title}</a>
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 8c8720179..231ee88e3 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -973,7 +973,7 @@ export namespace Doc {
export function toggleNativeDimensions(layoutDoc: Doc, contentScale: number, panelWidth: number, panelHeight: number) {
runInAction(() => {
if (layoutDoc._nativeWidth || layoutDoc._nativeHeight) {
- layoutDoc.scale = NumCast(layoutDoc.scale, 1) * contentScale;
+ layoutDoc._viewScale = NumCast(layoutDoc._viewScale, 1) * contentScale;
layoutDoc._nativeWidth = undefined;
layoutDoc._nativeHeight = undefined;
}
diff --git a/src/fields/util.ts b/src/fields/util.ts
index ad7b6ea7a..c4affb2d7 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -10,6 +10,7 @@ import { DocServer } from "../client/DocServer";
import { ComputedField } from "./ScriptField";
import { ScriptCast } from "./Types";
+
function _readOnlySetter(): never {
throw new Error("Documents can't be modified in read-only mode");
}
@@ -110,7 +111,7 @@ const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHe
"LODdisable", "chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"];
export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean {
let prop = in_prop;
- if (target[AclSym] && !_overrideAcl) return true;
+ if (target[AclSym] && !_overrideAcl && !DocServer.PlaygroundFields.includes(in_prop.toString())) return true;
if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) {
if (!prop.startsWith("_")) {
console.log(prop + " is deprecated - switch to _" + prop);
@@ -155,9 +156,6 @@ export function getter(target: any, in_prop: string | symbol | number, receiver:
function getFieldImpl(target: any, prop: string | number, receiver: any, ignoreProto: boolean = false): any {
receiver = receiver || target[SelfProxy];
- if (target === undefined) {
- console.log("");
- }
let field = target.__fields[prop];
for (const plugin of getterPlugins) {
const res = plugin(receiver, prop, field);