From e262d9ac73af5b2cef384468c47d69917e205d44 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 7 Apr 2020 23:01:46 -0400 Subject: lots of code cleanup - removed all northstar db stuff. added scriptingBox. renamed things. made collectiontypes strings not numbers. --- src/client/views/collections/CollectionSubView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 746b2e174..41f4fb3f0 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -99,7 +99,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: this.props.Document.resolvedDataDoc ? this.props.Document : Doc.GetProto(this.props.Document)); // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template } - rootSelected = (outsideReaction: boolean) => { + rootSelected = (outsideReaction?: boolean) => { return this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument || this.props.Document.forceActive ? this.props.rootSelected(outsideReaction) : false); } -- cgit v1.2.3-70-g09d2 From e4b22138e39244728144fbdd4c06e439be1b519a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 10 Apr 2020 13:24:07 -0400 Subject: more cleanup for layoutDoc/dataDoc/rootDoc updates. fix to doc filtering checkboxes getting filtered. fix to template captions. fixes to generalize LabelDoc's buttonParms --- src/client/documents/Documents.ts | 10 ++--- src/client/util/DragManager.ts | 2 +- src/client/util/DropConverter.ts | 2 +- src/client/util/RichTextRules.ts | 2 +- src/client/views/DocComponent.tsx | 16 +++---- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/InkingStroke.tsx | 4 +- src/client/views/TemplateMenu.tsx | 6 +-- src/client/views/collections/CollectionSubView.tsx | 4 +- .../views/collections/CollectionTreeView.tsx | 16 ++++--- src/client/views/collections/CollectionView.tsx | 17 ++++---- .../views/collections/CollectionViewChromes.tsx | 23 ++-------- src/client/views/nodes/AudioBox.tsx | 8 ++-- src/client/views/nodes/ColorBox.tsx | 4 +- src/client/views/nodes/DocumentBox.tsx | 6 +-- src/client/views/nodes/DocumentView.tsx | 6 +-- src/client/views/nodes/FontIconBox.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 4 +- src/client/views/nodes/ImageBox.tsx | 4 +- src/client/views/nodes/LabelBox.tsx | 48 +++++++++----------- src/client/views/nodes/LinkAnchorBox.tsx | 4 +- src/client/views/nodes/LinkBox.tsx | 4 +- src/client/views/nodes/PDFBox.tsx | 4 +- src/client/views/nodes/PresBox.tsx | 4 +- src/client/views/nodes/QueryBox.tsx | 4 +- src/client/views/nodes/ScreenshotBox.tsx | 6 +-- src/client/views/nodes/ScriptingBox.tsx | 4 +- src/client/views/nodes/SliderBox.tsx | 51 ++++++++++------------ src/client/views/nodes/VideoBox.tsx | 4 +- src/client/views/nodes/WebBox.tsx | 4 +- src/client/views/pdf/PDFViewer.tsx | 4 +- .../views/presentationview/PresElementBox.tsx | 4 +- src/new_fields/Doc.ts | 9 ++-- src/new_fields/RichTextField.ts | 4 ++ 34 files changed, 137 insertions(+), 159 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index c823c3233..22f22cbfd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -566,8 +566,8 @@ export namespace Docs { LinkManager.Instance.addLink(doc); - Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(this)"); - Doc.GetProto(target.doc).links = ComputedField.MakeFunction("links(this)"); + Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(self)"); + Doc.GetProto(target.doc).links = ComputedField.MakeFunction("links(self)"); return doc; } @@ -908,10 +908,10 @@ export namespace DocUtils { if (target.doc === CurrentUserUtils.UserDocument) return undefined; const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship }, id); - Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('this.anchor1.title +" (" + (this.linkRelationship||"to") +") " + this.anchor2.title'); + Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('self.anchor1.title +" (" + (self.linkRelationship||"to") +") " + self.anchor2.title'); - Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(this)"); - Doc.GetProto(target.doc).links = ComputedField.MakeFunction("links(this)"); + Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(self)"); + Doc.GetProto(target.doc).links = ComputedField.MakeFunction("links(self)"); return linkDoc; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c856bbb1e..346eb2fb4 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -222,7 +222,7 @@ export namespace DragManager { const bd = Docs.Create.ButtonDocument({ _width: 150, _height: 50, title, onClick: ScriptField.MakeScript(script) }); params.map(p => Object.keys(vars).indexOf(p) !== -1 && (Doc.GetProto(bd)[p] = new PrefetchProxy(vars[p] as Doc))); initialize?.(bd); - bd.buttonParams = new List(params); + bd["onclick-params"] = new List(params); e.docDragData && (e.docDragData.droppedDocuments = [bd]); }; StartDrag(eles, new DragManager.DocumentDragData([]), downX, downY, options, finishDrag); diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index eb4d3a9b0..8cea120cd 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -35,7 +35,7 @@ export function makeTemplate(doc: Doc, first: boolean = true, rename: Opt Opt; @@ -22,15 +22,15 @@ export function DocComponent

(schemaCtor: (doc: D // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info @computed get layoutDoc() { return Doc.Layout(this.props.Document); } // This is the data part of a document -- ie, the data that is constant across all views of the document - @computed get dataDoc() { return this.props.Document[DataSym]; } + @computed get dataDoc() { return this.props.Document[DataSym] as Doc; } protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; } return Component; } -/// DocStaticProps return a base class for React document views that have data extensions but aren't annotatable (e.g. AudioBox, FormattedTextBox) -interface DocExtendableProps { +/// FieldViewBoxProps - a generic base class for field views that are not annotatable (e.g. AudioBox, FormattedTextBox) +interface ViewBoxBaseProps { Document: Doc; DataDoc?: Doc; fieldKey: string; @@ -38,7 +38,7 @@ interface DocExtendableProps { renderDepth: number; rootSelected: (outsideReaction?: boolean) => boolean; } -export function DocExtendableComponent

(schemaCtor: (doc: Doc) => T) { +export function ViewBoxBaseComponent

(schemaCtor: (doc: Doc) => T) { class Component extends Touchable

{ //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then //@computed get Document(): T { return schemaCtor(this.props.Document); } @@ -60,8 +60,8 @@ export function DocExtendableComponent

(schemaCt } -/// DocAnnotatbleComponent return a base class for React views of document fields that are annotatable *and* interactive when selected (e.g., pdf, image) -export interface DocAnnotatableProps { +/// DocAnnotatbleComponent -return a base class for React views of document fields that are annotatable *and* interactive when selected (e.g., pdf, image) +export interface ViewBoxAnnotatableProps { Document: Doc; DataDoc?: Doc; fieldKey: string; @@ -71,7 +71,7 @@ export interface DocAnnotatableProps { rootSelected: (outsideReaction?: boolean) => boolean; renderDepth: number; } -export function DocAnnotatableComponent

(schemaCtor: (doc: Doc) => T) { +export function ViewBoxAnnotatableComponent

(schemaCtor: (doc: Doc) => T) { class Component extends Touchable

{ @observable _isChildActive = false; //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index bd72385ef..c49fe157c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -393,7 +393,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (SelectionManager.SelectedDocuments().length === 1) { const selected = SelectionManager.SelectedDocuments()[0]; if (this._titleControlString.startsWith("=")) { - return ScriptField.MakeFunction(this._titleControlString.substring(1), { doc: Doc.name })!.script.run({ this: selected.props.Document }, console.log).result?.toString() || ""; + return ScriptField.MakeFunction(this._titleControlString.substring(1), { doc: Doc.name })!.script.run({ self: selected.rootDoc, this: selected.layoutDoc }, console.log).result?.toString() || ""; } if (this._titleControlString.startsWith("#")) { return selected.props.Document[this._titleControlString.substring(1)]?.toString() || "-unset-"; diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index ff63a7c33..f66c04e1f 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -4,7 +4,7 @@ import { documentSchema } from "../../new_fields/documentSchemas"; import { InkData, InkField, InkTool } from "../../new_fields/InkField"; import { makeInterface } from "../../new_fields/Schema"; import { Cast, StrCast, NumCast } from "../../new_fields/Types"; -import { DocExtendableComponent } from "./DocComponent"; +import { ViewBoxBaseComponent } from "./DocComponent"; import { InkingControl } from "./InkingControl"; import "./InkingStroke.scss"; import { FieldView, FieldViewProps } from "./nodes/FieldView"; @@ -22,7 +22,7 @@ type InkDocument = makeInterface<[typeof documentSchema]>; const InkDocument = makeInterface(documentSchema); @observer -export class InkingStroke extends DocExtendableComponent(InkDocument) { +export class InkingStroke extends ViewBoxBaseComponent(InkDocument) { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); } private analyzeStrokes = () => { diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 8fb8e7516..4d7f1e443 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -76,7 +76,7 @@ export class TemplateMenu extends React.Component { @undoBatch @action toggleTemplate = (event: React.ChangeEvent, template: Template): void => { - this.props.docViews.forEach(d => Doc.Layout(d.Document)["_show" + template.Name] = event.target.checked ? template.Name.toLowerCase() : ""); + this.props.docViews.forEach(d => Doc.Layout(d.layoutDoc)["_show" + template.Name] = event.target.checked ? template.Name.toLowerCase() : ""); } @action @@ -87,7 +87,7 @@ export class TemplateMenu extends React.Component { @undoBatch @action toggleChrome = (): void => { - this.props.docViews.map(dv => Doc.Layout(dv.Document)).forEach(layout => + this.props.docViews.map(dv => Doc.Layout(dv.layoutDoc)).forEach(layout => layout._chromeStatus = (layout._chromeStatus !== "disabled" ? "disabled" : StrCast(layout._replacedChrome, "enabled"))); } @@ -124,7 +124,7 @@ export class TemplateMenu extends React.Component { templateMenu.push(); templateMenu.push(); if (noteTypesDoc) { - addedTypes.concat(noteTypes).map(template => template.treeViewChecked = ComputedField.MakeFunction(`templateIsUsed(this)`)); + addedTypes.concat(noteTypes).map(template => template.treeViewChecked = ComputedField.MakeFunction(`templateIsUsed(self)`)); this._addedKeys && Array.from(this._addedKeys).filter(key => !noteTypes.some(nt => nt.title === key)).forEach(template => templateMenu.push( this.toggleLayout(e, template)} />)); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 41f4fb3f0..0c00a1f22 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -120,8 +120,8 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: return Cast(this.dataField, listSpec(Doc)); } @computed get childDocs() { - const docFilters = Cast(this.props.Document._docFilters, listSpec("string"), []); - const docRangeFilters = Cast(this.props.Document._docRangeFilters, listSpec("string"), []); + const docFilters = this.props.ignoreFields?.includes("_docFilters") ? [] : Cast(this.props.Document._docFilters, listSpec("string"), []); + const docRangeFilters = this.props.ignoreFields?.includes("_docRangeFilters") ? [] : Cast(this.props.Document._docRangeFilters, listSpec("string"), []); const filterFacets: { [key: string]: { [value: string]: string } } = {}; // maps each filter key to an object with value=>modifier fields for (let i = 0; i < docFilters.length; i += 3) { const [key, value, modifiers] = docFilters.slice(i, i + 3); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 7edda5a4f..fd84c6498 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -735,16 +735,18 @@ export class CollectionTreeView extends CollectionSubView(Document, undefined as heroView._showTitle = "title"; heroView._showTitleHover = "titlehover"; - Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", + Doc.AddDocToList(Doc.UserDoc().expandingButtons as Doc, "data", Docs.Create.FontIconDocument({ - _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), - dragFactory: heroView, removeDropProperties: new List(["dropAction"]), title: "hero view", icon: "portrait" + title: "hero view", _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias", + dragFactory: heroView, removeDropProperties: new List(["dropAction"]), icon: "portrait", + onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), })); - Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", + Doc.AddDocToList(Doc.UserDoc().expandingButtons as Doc, "data", Docs.Create.FontIconDocument({ - _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias", onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), - dragFactory: detailView, removeDropProperties: new List(["dropAction"]), title: "detail view", icon: "file-alt" + title: "detail view", _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, dropAction: "alias", + dragFactory: detailView, removeDropProperties: new List(["dropAction"]), icon: "file-alt", + onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), })); Document.childLayout = heroView; @@ -837,7 +839,7 @@ Scripting.addGlobal(function readFacetData(layoutDoc: Doc, dataDoc: Doc, dataKey Docs.Create.TextDocument("", { title: facetValue.toString(), treeViewChecked: ComputedField.MakeFunction("determineCheckedState(layoutDoc, facetHeader, facetValue)", - { layoutDoc: Doc.name, facetHeader: "string", facetValue: "string" }, + {}, { layoutDoc, facetHeader, facetValue }) })); return new List(facetValueDocSet); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 8192e6751..821840e0b 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -354,14 +354,15 @@ export class CollectionView extends Touchable { let newFacet: Opt; if (nonNumbers / allCollectionDocs.length < .1) { newFacet = Docs.Create.SliderDocument({ title: facetHeader }); + const newFacetField = Doc.LayoutFieldKey(newFacet); const ranged = Doc.readDocRangeFilter(this.props.Document, facetHeader); Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox newFacet.treeViewExpandedView = "layout"; newFacet.treeViewOpen = true; - newFacet._sliderMin = ranged === undefined ? minVal : ranged[0]; - newFacet._sliderMax = ranged === undefined ? maxVal : ranged[1]; - newFacet._sliderMinThumb = minVal; - newFacet._sliderMaxThumb = maxVal; + newFacet[newFacetField + "-min"] = ranged === undefined ? minVal : ranged[0]; + newFacet[newFacetField + "-max"] = ranged === undefined ? maxVal : ranged[1]; + Doc.GetProto(newFacet)[newFacetField + "-minThumb"] = minVal; + Doc.GetProto(newFacet)[newFacetField + "-maxThumb"] = maxVal; newFacet.target = this.props.Document; const scriptText = `setDocFilterRange(this.target, "${facetHeader}", range)`; newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: "number" }); @@ -370,14 +371,12 @@ export class CollectionView extends Touchable { } else { newFacet = Docs.Create.TreeDocument([], { title: facetHeader, treeViewOpen: true, isFacetFilter: true }); const capturedVariables = { layoutDoc: this.props.Document, dataDoc: this.dataDoc }; - const params = { layoutDoc: Doc.name, dataDoc: Doc.name, }; - newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, params, capturedVariables); + newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, {}, capturedVariables); } newFacet && Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet); } } - onPointerDown = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => { this._facetWidth = Math.max(this.props.ScreenToLocalTransform().transformPoint(e.clientX, 0)[0], 0); @@ -385,11 +384,11 @@ export class CollectionView extends Touchable { }), returnFalse, action(() => this._facetWidth = this.facetWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0)); } filterBackground = () => "dimGray"; + get ignoreFields() { return ["_docFilters", "_docRangeFilters"]; } // this makes the tree view collection ignore these filters (otherwise, the filters would filter themselves) @computed get scriptField() { const scriptText = "setDocFilter(containingTreeView, heading, this.title, checked)"; return ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name }); } - @computed get treeIgnoreFields() { return ["_facetCollection", "_docFilters"]; } @computed get filterView() { const facetCollection = this.props.Document; const flyout = ( @@ -419,7 +418,7 @@ export class CollectionView extends Touchable { NativeWidth={returnZero} treeViewHideHeaderFields={true} onCheckedClick={this.scriptField!} - ignoreFields={this.treeIgnoreFields} + ignoreFields={this.ignoreFields} annotationsKey={""} dontRegisterView={true} PanelWidth={this.facetWidth} diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index b2ca3c19f..ba95dce00 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -361,28 +361,13 @@ export class CollectionViewBaseChrome extends React.Component { - this._startDragPosition = { x: e.clientX, y: e.clientY }; - document.addEventListener("pointermove", this.dragPointerMove); - document.addEventListener("pointerup", this.dragPointerUp); - e.stopPropagation(); - e.preventDefault(); - } - - dragPointerMove = (e: PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); - const [dx, dy] = [e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y]; - if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { + setupMoveUpEvents(this, e, (e, down, delta) => { this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c => DragManager.StartButtonDrag([this._commandRef.current!], c.script, c.title, { target: this.props.CollectionView.props.Document }, c.params, c.initialize, e.clientX, e.clientY)); - document.removeEventListener("pointermove", this.dragPointerMove); - document.removeEventListener("pointerup", this.dragPointerUp); - } - } - dragPointerUp = (e: PointerEvent) => { - document.removeEventListener("pointermove", this.dragPointerMove); - document.removeEventListener("pointerup", this.dragPointerUp); + return true; + }, emptyFunction, emptyFunction); + this._startDragPosition = { x: e.clientX, y: e.clientY }; } render() { diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index c08a2b808..7078cc01c 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -4,7 +4,7 @@ import { observer } from "mobx-react"; import "./AudioBox.scss"; import { Cast, DateCast, NumCast } from "../../../new_fields/Types"; import { AudioField, nullAudio } from "../../../new_fields/URLField"; -import { DocExtendableComponent } from "../DocComponent"; +import { ViewBoxBaseComponent } from "../DocComponent"; import { makeInterface, createSchema } from "../../../new_fields/Schema"; import { documentSchema } from "../../../new_fields/documentSchemas"; import { Utils, returnTrue, emptyFunction, returnOne, returnTransparent, returnFalse, returnZero } from "../../../Utils"; @@ -39,7 +39,7 @@ type AudioDocument = makeInterface<[typeof documentSchema, typeof audioSchema]>; const AudioDocument = makeInterface(documentSchema, audioSchema); @observer -export class AudioBox extends DocExtendableComponent(AudioDocument) { +export class AudioBox extends ViewBoxBaseComponent(AudioDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(AudioBox, fieldKey); } public static Enabled = false; @@ -194,8 +194,8 @@ export class AudioBox extends DocExtendableComponent; const ColorDocument = makeInterface(documentSchema); @observer -export class ColorBox extends DocExtendableComponent(ColorDocument) { +export class ColorBox extends ViewBoxBaseComponent(ColorDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ColorBox, fieldKey); } render() { diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx index 4f2b3b656..ac562f19a 100644 --- a/src/client/views/nodes/DocumentBox.tsx +++ b/src/client/views/nodes/DocumentBox.tsx @@ -9,7 +9,7 @@ import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { emptyPath } from "../../../Utils"; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; -import { DocAnnotatableComponent } from "../DocComponent"; +import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { ContentFittingDocumentView } from "./ContentFittingDocumentView"; import "./DocumentBox.scss"; import { FieldView, FieldViewProps } from "./FieldView"; @@ -22,7 +22,7 @@ type DocHolderBoxSchema = makeInterface<[typeof documentSchema]>; const DocHolderBoxDocument = makeInterface(documentSchema); @observer -export class DocHolderBox extends DocAnnotatableComponent(DocHolderBoxDocument) { +export class DocHolderBox extends ViewBoxAnnotatableComponent(DocHolderBoxDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DocHolderBox, fieldKey); } _prevSelectionDisposer: IReactionDisposer | undefined; _selections: Doc[] = []; @@ -54,7 +54,7 @@ export class DocHolderBox extends DocAnnotatableComponent { - this.contentDoc[this.props.fieldKey] = ComputedField.MakeFunction(`selectedDocs(this,this.excludeCollections,[_last_])?.[0]`); + this.contentDoc[this.props.fieldKey] = ComputedField.MakeFunction(`selectedDocs(self,this.excludeCollections,[_last_])?.[0]`); } isSelectionLocked = () => { const kvpstring = Field.toKeyValueString(this.contentDoc, this.props.fieldKey); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1bccce054..1e22dbc0b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -298,7 +298,7 @@ export class DocumentView extends DocComponent(Docu } else if (this.onClickHandler?.script) { SelectionManager.DeselectAll(); const func = () => this.onClickHandler.script.run({ - this: this.props.Document, + this: this.layoutDoc, self: this.rootDoc, thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey }, console.log); @@ -512,8 +512,8 @@ export class DocumentView extends DocComponent(Docu onPointerUp = (e: PointerEvent): void => { this.cleanUpInteractions(); - if (this.onPointerUpHandler && this.onPointerUpHandler.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { - this.onPointerUpHandler.script.run({ this: this.Document.isTemplateForField && this.props.DataDoc ? this.props.DataDoc : this.props.Document }, console.log); + if (this.onPointerUpHandler?.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { + this.onPointerUpHandler.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log); document.removeEventListener("pointerup", this.onPointerUp); return; } diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index bd7ea4c92..9329cf210 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -56,7 +56,7 @@ export class FontIconBox extends DocComponent( background: StrCast(referenceLayout.backgroundColor), boxShadow: this.props.Document.ischecked ? `4px 4px 12px black` : undefined }}> - + ; } } \ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index fb919a716..d641dc791 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -38,7 +38,7 @@ import { undoBatch, UndoManager } from "../../util/UndoManager"; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { DocAnnotatableComponent } from "../DocComponent"; +import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { DocumentButtonBar } from '../DocumentButtonBar'; import { InkingControl } from "../InkingControl"; import { AudioBox } from './AudioBox'; @@ -69,7 +69,7 @@ const RichTextDocument = makeInterface(richTextSchema, documentSchema); type PullHandler = (exportState: Opt, dataDoc: Doc) => void; @observer -export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & FormattedTextBoxProps), RichTextDocument>(RichTextDocument) { +export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProps & FormattedTextBoxProps), RichTextDocument>(RichTextDocument) { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(FormattedTextBox, fieldStr); } public static blankState = () => EditorState.create(FormattedTextBox.Instance.config); public static Instance: FormattedTextBox; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index bb7d78ace..5b0edf34f 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -24,7 +24,7 @@ import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from "../../views/ContextMenu"; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { ContextMenuProps } from '../ContextMenuItem'; -import { DocAnnotatableComponent } from '../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; import FaceRectangles from './FaceRectangles'; import { FieldView, FieldViewProps } from './FieldView'; import "./ImageBox.scss"; @@ -65,7 +65,7 @@ const uploadIcons = { }; @observer -export class ImageBox extends DocAnnotatableComponent(ImageDocument) { +export class ImageBox extends ViewBoxAnnotatableComponent(ImageDocument) { protected multiTouchDisposer?: import("../../util/InteractionUtils").InteractionUtils.MultiTouchEventDisposer | undefined; public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ImageBox, fieldKey); } private _imgRef: React.RefObject = React.createRef(); diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 0ec6af93a..b9701f923 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -7,10 +7,10 @@ import { Doc, DocListCast } from '../../../new_fields/Doc'; import { List } from '../../../new_fields/List'; import { createSchema, makeInterface, listSpec } from '../../../new_fields/Schema'; import { ScriptField } from '../../../new_fields/ScriptField'; -import { BoolCast, StrCast, Cast, FieldValue } from '../../../new_fields/Types'; +import { BoolCast, StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; -import { DocComponent } from '../DocComponent'; +import { ViewBoxBaseComponent } from '../DocComponent'; import './LabelBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; import { ContextMenuProps } from '../ContextMenuItem'; @@ -20,27 +20,16 @@ import { documentSchema } from '../../../new_fields/documentSchemas'; library.add(faEdit as any); -const LabelSchema = createSchema({ - onClick: ScriptField, - buttonParams: listSpec("string"), - text: "string" -}); +const LabelSchema = createSchema({}); type LabelDocument = makeInterface<[typeof LabelSchema, typeof documentSchema]>; const LabelDocument = makeInterface(LabelSchema, documentSchema); @observer -export class LabelBox extends DocComponent(LabelDocument) { +export class LabelBox extends ViewBoxBaseComponent(LabelDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LabelBox, fieldKey); } private dropDisposer?: DragManager.DragDropDisposer; - @computed get dataDoc() { - return this.props.DataDoc && - (this.Document.isTemplateForField || BoolCast(this.props.DataDoc.isTemplateForField) || - this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); - } - - protected createDropTarget = (ele: HTMLDivElement) => { this.dropDisposer?.(); if (ele) { @@ -52,8 +41,8 @@ export class LabelBox extends DocComponent(LabelD const funcs: ContextMenuProps[] = []; funcs.push({ description: "Clear Script Params", event: () => { - const params = FieldValue(this.Document.buttonParams); - params?.map(p => this.props.Document[p] = undefined); + const params = Cast(this.dataDoc[this.fieldKey + "-params"], listSpec("string"), []); + params?.map(p => this.dataDoc[p] = undefined); }, icon: "trash" }); @@ -64,32 +53,35 @@ export class LabelBox extends DocComponent(LabelD @action drop = (e: Event, de: DragManager.DropEvent) => { const docDragData = de.complete.docDragData; - const params = this.Document.buttonParams; - const missingParams = params?.filter(p => this.props.Document[p] === undefined); + const params = Cast(this.dataDoc[this.fieldKey + "-params"], listSpec("string"), []); + const missingParams = params?.filter(p => this.dataDoc[p] === undefined); if (docDragData && missingParams?.includes((e.target as any).textContent)) { - this.props.Document[(e.target as any).textContent] = new List(docDragData.droppedDocuments.map((d, i) => + this.dataDoc[(e.target as any).textContent] = new List(docDragData.droppedDocuments.map((d, i) => d.onDragStart ? docDragData.draggedDocuments[i] : d)); e.stopPropagation(); } } // (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")") render() { - const params = this.Document.buttonParams; - const missingParams = params?.filter(p => this.props.Document[p] === undefined); - params?.map(p => DocListCast(this.props.Document[p])); // bcz: really hacky form of prefetching ... + const params = Cast(this.dataDoc[this.fieldKey + "-params"], listSpec("string"), []); + const missingParams = params?.filter(p => this.dataDoc[p] === undefined); + params?.map(p => DocListCast(this.dataDoc[p])); // bcz: really hacky form of prefetching ... return (

+ style={{ boxShadow: this.layoutDoc.opacity ? StrCast(this.layoutDoc.boxShadow) : "" }}>
- {(this.Document.text || this.Document.title)} + {StrCast(this.layoutDoc.text, StrCast(this.layoutDoc.title))}
- {!missingParams || !missingParams.length ? (null) : missingParams.map(m =>
{m}
)} + {!missingParams?.length ? (null) : missingParams.map(m =>
{m}
)}
); diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index f3e099dd6..13ffc6956 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -7,7 +7,7 @@ import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { Utils, setupMoveUpEvents } from '../../../Utils'; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager } from "../../util/DragManager"; -import { DocExtendableComponent } from "../DocComponent"; +import { ViewBoxBaseComponent } from "../DocComponent"; import "./LinkAnchorBox.scss"; import { FieldView, FieldViewProps } from "./FieldView"; import React = require("react"); @@ -25,7 +25,7 @@ type LinkAnchorSchema = makeInterface<[typeof documentSchema]>; const LinkAnchorDocument = makeInterface(documentSchema); @observer -export class LinkAnchorBox extends DocExtendableComponent(LinkAnchorDocument) { +export class LinkAnchorBox extends ViewBoxBaseComponent(LinkAnchorDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkAnchorBox, fieldKey); } _doubleTap = false; _lastTap: number = 0; diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 542c86049..af4bf420f 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -4,7 +4,7 @@ import { documentSchema } from "../../../new_fields/documentSchemas"; import { makeInterface, listSpec } from "../../../new_fields/Schema"; import { returnFalse, returnZero } from "../../../Utils"; import { CollectionTreeView } from "../collections/CollectionTreeView"; -import { DocExtendableComponent } from "../DocComponent"; +import { ViewBoxBaseComponent } from "../DocComponent"; import { FieldView, FieldViewProps } from './FieldView'; import "./LinkBox.scss"; import { Cast } from "../../../new_fields/Types"; @@ -13,7 +13,7 @@ type LinkDocument = makeInterface<[typeof documentSchema]>; const LinkDocument = makeInterface(documentSchema); @observer -export class LinkBox extends DocExtendableComponent(LinkDocument) { +export class LinkBox extends ViewBoxBaseComponent(LinkDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); } render() { return
(PdfDocument) { +export class PDFBox extends ViewBoxAnnotatableComponent(PdfDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PDFBox, fieldKey); } private _keyValue: string = ""; private _valueValue: string = ""; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index bea3170ac..e428e16da 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -16,7 +16,7 @@ import { CollectionView, CollectionViewType } from "../collections/CollectionVie import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; -import { DocExtendableComponent } from "../DocComponent"; +import { ViewBoxBaseComponent } from "../DocComponent"; import { makeInterface } from "../../../new_fields/Schema"; library.add(faArrowLeft); @@ -33,7 +33,7 @@ type PresBoxSchema = makeInterface<[typeof documentSchema]>; const PresBoxDocument = makeInterface(documentSchema); @observer -export class PresBox extends DocExtendableComponent(PresBoxDocument) { +export class PresBox extends ViewBoxBaseComponent(PresBoxDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } _childReaction: IReactionDisposer | undefined; @observable _isChildActive = false; diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx index 7016b4f04..947167200 100644 --- a/src/client/views/nodes/QueryBox.tsx +++ b/src/client/views/nodes/QueryBox.tsx @@ -6,7 +6,7 @@ import { Id } from '../../../new_fields/FieldSymbols'; import { makeInterface } from "../../../new_fields/Schema"; import { StrCast } from "../../../new_fields/Types"; import { SelectionManager } from "../../util/SelectionManager"; -import { DocAnnotatableComponent } from '../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { SearchBox } from "../search/SearchBox"; import { FieldView, FieldViewProps } from './FieldView'; import "./QueryBox.scss"; @@ -15,7 +15,7 @@ type QueryDocument = makeInterface<[typeof documentSchema]>; const QueryDocument = makeInterface(documentSchema); @observer -export class QueryBox extends DocAnnotatableComponent(QueryDocument) { +export class QueryBox extends ViewBoxAnnotatableComponent(QueryDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(QueryBox, fieldKey); } _docListChangedReaction: IReactionDisposer | undefined; componentDidMount() { diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 1a991f1eb..11b24b059 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -14,7 +14,7 @@ import { Docs, DocUtils } from "../../documents/Documents"; import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; -import { DocComponent } from "../DocComponent"; +import { ViewBoxBaseComponent } from "../DocComponent"; import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from './FieldView'; import "./ScreenshotBox.scss"; @@ -26,7 +26,7 @@ const ScreenshotDocument = makeInterface(documentSchema, positionSchema); library.add(faVideo); @observer -export class ScreenshotBox extends DocComponent(ScreenshotDocument) { +export class ScreenshotBox extends ViewBoxBaseComponent(ScreenshotDocument) { private _reactionDisposer?: IReactionDisposer; private _videoRef: HTMLVideoElement | null = null; public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ScreenshotBox, fieldKey); } @@ -109,7 +109,7 @@ export class ScreenshotBox extends DocComponent { - const field = Cast(this.dataDoc[this.props.fieldKey], VideoField); + const field = Cast(this.dataDoc[this.fieldKey], VideoField); if (field) { const url = field.url.href; const subitems: ContextMenuProps[] = []; diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 309ee3620..70f29e1dc 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -7,7 +7,7 @@ import { ScriptField } from "../../../new_fields/ScriptField"; import { StrCast, ScriptCast, Cast } from "../../../new_fields/Types"; import { InteractionUtils } from "../../util/InteractionUtils"; import { CompileScript, isCompileError, ScriptParam } from "../../util/Scripting"; -import { DocAnnotatableComponent } from "../DocComponent"; +import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { EditableView } from "../EditableView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./ScriptingBox.scss"; @@ -20,7 +20,7 @@ type ScriptingDocument = makeInterface<[typeof ScriptingSchema, typeof documentS const ScriptingDocument = makeInterface(ScriptingSchema, documentSchema); @observer -export class ScriptingBox extends DocAnnotatableComponent(ScriptingDocument) { +export class ScriptingBox extends ViewBoxAnnotatableComponent(ScriptingDocument) { protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer | undefined; public static LayoutString(fieldStr: string) { return FieldView.LayoutString(ScriptingBox, fieldStr); } diff --git a/src/client/views/nodes/SliderBox.tsx b/src/client/views/nodes/SliderBox.tsx index 844d95d11..746ea0b64 100644 --- a/src/client/views/nodes/SliderBox.tsx +++ b/src/client/views/nodes/SliderBox.tsx @@ -1,22 +1,20 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faEdit } from '@fortawesome/free-regular-svg-icons'; -import { computed, runInAction } from 'mobx'; +import { runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Handles, Rail, Slider, Tracks, Ticks } from 'react-compound-slider'; -import { Doc } from '../../../new_fields/Doc'; +import { Handles, Rail, Slider, Ticks, Tracks } from 'react-compound-slider'; import { documentSchema } from '../../../new_fields/documentSchemas'; -import { createSchema, listSpec, makeInterface } from '../../../new_fields/Schema'; +import { createSchema, makeInterface } from '../../../new_fields/Schema'; import { ScriptField } from '../../../new_fields/ScriptField'; -import { BoolCast, FieldValue, StrCast, NumCast, Cast } from '../../../new_fields/Types'; -import { DragManager } from '../../util/DragManager'; +import { Cast, NumCast, StrCast } from '../../../new_fields/Types'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { DocComponent } from '../DocComponent'; -import './SliderBox.scss'; -import { Handle, TooltipRail, Track, Tick } from './SliderBox-components'; -import { FieldView, FieldViewProps } from './FieldView'; +import { ViewBoxBaseComponent } from '../DocComponent'; import { ScriptBox } from '../ScriptBox'; +import { FieldView, FieldViewProps } from './FieldView'; +import { Handle, Tick, TooltipRail, Track } from './SliderBox-components'; +import './SliderBox.scss'; library.add(faEdit as any); @@ -32,36 +30,33 @@ type SliderDocument = makeInterface<[typeof SliderSchema, typeof documentSchema] const SliderDocument = makeInterface(SliderSchema, documentSchema); @observer -export class SliderBox extends DocComponent(SliderDocument) { +export class SliderBox extends ViewBoxBaseComponent(SliderDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SliderBox, fieldKey); } - private dropDisposer?: DragManager.DragDropDisposer; - - @computed get dataDoc() { - return this.props.DataDoc && - (this.Document.isTemplateForField || BoolCast(this.props.DataDoc.isTemplateForField) || - this.props.DataDoc.layout === this.Document) ? this.props.DataDoc : Doc.GetProto(this.Document); - } + get minThumbKey() { return this.fieldKey + "-minThumb"; } + get maxThumbKey() { return this.fieldKey + "-maxThumb"; } + get minKey() { return this.fieldKey + "-min"; } + get maxKey() { return this.fieldKey + "-max"; } specificContextMenu = (e: React.MouseEvent): void => { const funcs: ContextMenuProps[] = []; funcs.push({ description: "Edit Thumb Change Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Thumb Change ...", this.props.Document, "onThumbChange", obj.x, obj.y) }); ContextMenu.Instance.addItem({ description: "Slider Funcs...", subitems: funcs, icon: "asterisk" }); } onChange = (values: readonly number[]) => runInAction(() => { - this.Document._sliderMinThumb = values[0]; - this.Document._sliderMaxThumb = values[1]; - Cast(this.Document.onThumbChanged, ScriptField, null)?.script.run({ range: values, this: this.props.Document }); + this.dataDoc[this.minThumbKey] = values[0]; + this.dataDoc[this.maxThumbKey] = values[1]; + Cast(this.layoutDoc.onThumbChanged, ScriptField, null)?.script.run({ self: this.rootDoc, range: values, this: this.layoutDoc }); }) render() { - const domain = [NumCast(this.props.Document._sliderMin), NumCast(this.props.Document._sliderMax)]; - const defaultValues = [NumCast(this.props.Document._sliderMinThumb), NumCast(this.props.Document._sliderMaxThumb)]; - return ( + const domain = [NumCast(this.layoutDoc[this.minKey]), NumCast(this.layoutDoc[this.maxKey])]; + const defaultValues = [NumCast(this.dataDoc[this.minThumbKey]), NumCast(this.dataDoc[this.maxThumbKey])]; + return domain[1] <= domain[0] ? (null) : (
e.stopPropagation()} - style={{ boxShadow: this.Document.opacity === 0 ? undefined : StrCast(this.Document.boxShadow, "") }}> + style={{ boxShadow: this.layoutDoc.opacity === 0 ? undefined : StrCast(this.layoutDoc.boxShadow, "") }}>
(Slid {({ handles, activeHandleID, getHandleProps }) => (
{handles.map((handle, i) => { - const value = i === 0 ? this.Document._sliderMinThumb : this.Document._sliderMaxThumb; + const value = i === 0 ? defaultValues[0] : defaultValues[1]; return (
(VideoDocument) { +export class VideoBox extends ViewBoxAnnotatableComponent(VideoDocument) { static _youtubeIframeCounter: number = 0; private _reactionDisposer?: IReactionDisposer; private _youtubeReactionDisposer?: IReactionDisposer; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index ea5d601ec..55ad7eb0f 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -14,7 +14,7 @@ import { Docs } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; import { ImageUtils } from "../../util/Import & Export/ImageUtils"; import { SelectionManager } from "../../util/SelectionManager"; -import { DocAnnotatableComponent } from "../DocComponent"; +import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { DocumentDecorations } from "../DocumentDecorations"; import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from './FieldView'; @@ -33,7 +33,7 @@ type WebDocument = makeInterface<[typeof documentSchema]>; const WebDocument = makeInterface(documentSchema); @observer -export class WebBox extends DocAnnotatableComponent(WebDocument) { +export class WebBox extends ViewBoxAnnotatableComponent(WebDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(WebBox, fieldKey); } @observable private collapsed: boolean = true; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index f93c1fa97..c49e6512a 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -23,7 +23,7 @@ import Annotation from "./Annotation"; import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; import { SelectionManager } from "../../util/SelectionManager"; import { undoBatch } from "../../util/UndoManager"; -import { DocAnnotatableComponent } from "../DocComponent"; +import { ViewBoxAnnotatableComponent } from "../DocComponent"; import { DocumentType } from "../../documents/DocumentTypes"; import { documentSchema } from "../../../new_fields/documentSchemas"; import { DocumentDecorations } from "../DocumentDecorations"; @@ -79,7 +79,7 @@ interface IViewerProps { * Handles rendering and virtualization of the pdf */ @observer -export class PDFViewer extends DocAnnotatableComponent(PdfDocument) { +export class PDFViewer extends ViewBoxAnnotatableComponent(PdfDocument) { static _annotationStyle: any = addStyleSheet(); @observable private _pageSizes: { width: number, height: number }[] = []; @observable private _annotations: Doc[] = []; diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index bed181ab9..dd0cbf929 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -12,7 +12,7 @@ import { Cast, NumCast } from "../../../new_fields/Types"; import { emptyFunction, emptyPath, returnFalse, returnTrue } from "../../../Utils"; import { Transform } from "../../util/Transform"; import { CollectionViewType } from '../collections/CollectionView'; -import { DocExtendableComponent } from '../DocComponent'; +import { ViewBoxBaseComponent } from '../DocComponent'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./PresElementBox.scss"; @@ -44,7 +44,7 @@ const PresDocument = makeInterface(presSchema, documentSchema); * It involves some functionality for its buttons and options. */ @observer -export class PresElementBox extends DocExtendableComponent(PresDocument) { +export class PresElementBox extends ViewBoxBaseComponent(PresDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); } _heightDisposer: IReactionDisposer | undefined; diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index a9c97fc19..934ba0f60 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -645,11 +645,12 @@ export namespace Doc { Cast(templateFieldValue, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc)); (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateFieldValue)); } - if (templateCaptionValue instanceof RichTextField && (templateCaptionValue.Text || templateCaptionValue.Data.toString().includes("dashField"))) { - templateField["caption-textTemplate"] = ComputedField.MakeFunction(`copyField(this.caption)`, { this: Doc.name }); + // copy the textTemplates from 'this' (not 'self') because the layout contains the template info, not the original doc + if (templateCaptionValue instanceof RichTextField && !templateCaptionValue.Empty()) { + templateField["caption-textTemplate"] = ComputedField.MakeFunction(`copyField(this.caption)`); } - if (templateFieldValue instanceof RichTextField && (templateFieldValue.Text || templateFieldValue.Data.toString().includes("dashField"))) { - templateField[metadataFieldKey + "-textTemplate"] = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name }); + if (templateFieldValue instanceof RichTextField && !templateFieldValue.Empty()) { + templateField[metadataFieldKey + "-textTemplate"] = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`); } // get the layout string that the template uses to specify its layout diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index a5a81f4a4..5cf0e0cc3 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -19,6 +19,10 @@ export class RichTextField extends ObjectField { this.Text = text; } + Empty() { + return !(this.Text || this.Data.toString().includes("dashField")); + } + [Copy]() { return new RichTextField(this.Data, this.Text); } -- cgit v1.2.3-70-g09d2 From 22d1499703ddb20d0f937364085e46fefcc663da Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 12 Apr 2020 19:23:21 -0400 Subject: added nudging of documents --- src/client/views/GlobalKeyHandler.ts | 35 +++++++++++++++++----- src/client/views/collections/CollectionSubView.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 5 ++++ src/client/views/nodes/DocumentView.tsx | 1 + 4 files changed, 34 insertions(+), 9 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 52801b570..d01f3f1e5 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -8,7 +8,7 @@ import { Doc } from "../../new_fields/Doc"; import { DictationManager } from "../util/DictationManager"; import SharingManager from "../util/SharingManager"; import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; -import { Cast, PromiseValue } from "../../new_fields/Types"; +import { Cast, PromiseValue, NumCast } from "../../new_fields/Types"; import { ScriptField } from "../../new_fields/ScriptField"; import { InkingControl } from "./InkingControl"; import { InkTool } from "../../new_fields/InkField"; @@ -89,13 +89,20 @@ export default class KeyManager { return { stopPropagation: false, preventDefault: false }; } } - UndoManager.RunInBatch(() => { - SelectionManager.SelectedDocuments().map(docView => { - const doc = docView.props.Document; - const remove = docView.props.removeDocument; - remove && remove(doc); - }); - }, "delete"); + UndoManager.RunInBatch(() => + SelectionManager.SelectedDocuments().map(dv => dv.props.removeDocument?.(dv.props.Document)), "delete"); + break; + case "arrowleft": + UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.nudge?.(-1, 0)), "nudge left"); + break; + case "arrowright": + UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.nudge?.(1, 0)), "nudge right"); + break; + case "arrowup": + UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.nudge?.(0, -1)), "nudge up"); + break; + case "arrowdown": + UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.nudge?.(0, 1)), "nudge down"); break; } @@ -114,6 +121,18 @@ export default class KeyManager { // DictationManager.Controls.listen({ useOverlay: true, tryExecute: true }); // stopPropagation = true; // preventDefault = true; + case "arrowleft": + UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.nudge?.(-10, 0)), "nudge left"); + break; + case "arrowright": + UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.nudge?.(10, 0)), "nudge right"); + break; + case "arrowup": + UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.nudge?.(0, -10)), "nudge up"); + break; + case "arrowdown": + UndoManager.RunInBatch(() => SelectionManager.SelectedDocuments().map(dv => dv.props.nudge?.(0, 10)), "nudge down"); + break; } return { diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 0c00a1f22..6b7c3de56 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -381,7 +381,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: alert(`Upload failed: ${result.message}`); return; } - const full = { ...options, _width: 300, title: name }; + const full = { ...options, _width: 400, title: name }; const pathname = Utils.prepend(result.accessPaths.agnostic.client); const doc = await Docs.Get.DocumentFromType(type, pathname, full); if (!doc) { diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index f9f5f449c..3503af442 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -59,6 +59,10 @@ export class CollectionFreeFormDocumentView extends DocComponent { + this.layoutDoc.x = NumCast(this.layoutDoc.x) + x; + this.layoutDoc.y = NumCast(this.layoutDoc.y) + y; + } contentScaling = () => this.nativeWidth > 0 && !this.props.fitToBox && !this.freezeDimensions ? this.width / this.nativeWidth : 1; panelWidth = () => (this.dataProvider?.width || this.props.PanelWidth?.()); @@ -93,6 +97,7 @@ export class CollectionFreeFormDocumentView extends DocComponent void; addDocument?: (doc: Doc) => boolean; removeDocument?: (doc: Doc) => boolean; moveDocument?: (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; -- cgit v1.2.3-70-g09d2 From b235c94614141752c98d24a395682a02297d9e6a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 13 Apr 2020 11:15:59 -0400 Subject: cleaned up rootSelected() to work with templates. adjusted nudge to favor moving documents over panning collection --- src/client/views/DocComponent.tsx | 4 ++-- src/client/views/PreviewCursor.tsx | 14 +++++--------- src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 17 +++++++++++------ .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 4 ++-- src/client/views/nodes/DocumentView.tsx | 16 +++++++++------- 8 files changed, 32 insertions(+), 29 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index b1bd4191c..f19f9308a 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -53,7 +53,7 @@ export function ViewBoxBaseComponent

(schemaCtor: // key where data is stored @computed get fieldKey() { return this.props.fieldKey; } - active = (outsideReaction?: boolean) => !this.props.Document.isBackground && ((this.props.Document.forceActive && this.props.rootSelected(outsideReaction)) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0);// && !InkingControl.Instance.selectedTool; // bcz: inking state shouldn't affect static tools + active = (outsideReaction?: boolean) => !this.props.Document.isBackground && (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0);// && !InkingControl.Instance.selectedTool; // bcz: inking state shouldn't affect static tools protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; } return Component; @@ -114,7 +114,7 @@ export function ViewBoxAnnotatableComponent

this.props.whenActiveChanged(this._isChildActive = isActive)); active = (outsideReaction?: boolean) => ((InkingControl.Instance.selectedTool === InkTool.None && !this.props.Document.isBackground) && - ((this.props.Document.forceActive && this.props.rootSelected(outsideReaction)) || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) + (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) annotationsActive = (outsideReaction?: boolean) => (InkingControl.Instance.selectedTool !== InkTool.None || (this.props.Document.isBackground && this.props.active()) || (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) } diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index ecebadd2a..92ba13d2f 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -13,7 +13,7 @@ export class PreviewCursor extends React.Component<{}> { static _getTransform: () => Transform; static _addLiveTextDoc: (doc: Doc) => void; static _addDocument: (doc: Doc) => boolean; - static _nudge: (x: number, y: number) => void; + static _nudge: (x: number, y: number) => boolean; @observable static _clickPoint = [0, 0]; @observable public static Visible = false; constructor(props: any) { @@ -91,17 +91,13 @@ export class PreviewCursor extends React.Component<{}> { } } else if (PreviewCursor.Visible) { if (e.key === "ArrowRight") { - PreviewCursor._nudge?.(1 * (e.shiftKey ? 2 : 1), 0); - e.stopPropagation(); + PreviewCursor._nudge?.(1 * (e.shiftKey ? 2 : 1), 0) && e.stopPropagation(); } else if (e.key === "ArrowLeft") { - PreviewCursor._nudge?.(-1 * (e.shiftKey ? 2 : 1), 0); - e.stopPropagation(); + PreviewCursor._nudge?.(-1 * (e.shiftKey ? 2 : 1), 0) && e.stopPropagation(); } else if (e.key === "ArrowUp") { - PreviewCursor._nudge?.(0, 1 * (e.shiftKey ? 2 : 1)); - e.stopPropagation(); + PreviewCursor._nudge?.(0, 1 * (e.shiftKey ? 2 : 1)) && e.stopPropagation(); } else if (e.key === "ArrowDown") { - PreviewCursor._nudge?.(0, -1 * (e.shiftKey ? 2 : 1)); - e.stopPropagation(); + PreviewCursor._nudge?.(0, -1 * (e.shiftKey ? 2 : 1)) && e.stopPropagation(); } } } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 6b7c3de56..37cf942c6 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -100,7 +100,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: } rootSelected = (outsideReaction?: boolean) => { - return this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument || this.props.Document.forceActive ? this.props.rootSelected(outsideReaction) : false); + return this.props.isSelected(outsideReaction) || (this.rootDoc && this.props.rootSelected(outsideReaction)); } // The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc. diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 821840e0b..86df9c080 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -102,7 +102,7 @@ export class CollectionView extends Touchable { return viewField as any as CollectionViewType; } - active = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.rootSelected(outsideReaction) && BoolCast(this.props.Document.forceActive)) || this._isChildActive || this.props.renderDepth === 0; + active = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || this.props.rootSelected(outsideReaction) || this.props.Document.forceActive || this._isChildActive || this.props.renderDepth === 0; whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7dca19073..a77f09163 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -15,7 +15,7 @@ import { ScriptField } from "../../../../new_fields/ScriptField"; import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../new_fields/Types"; import { TraceMobx } from "../../../../new_fields/util"; import { GestureUtils } from "../../../../pen-gestures/GestureUtils"; -import { aggregateBounds, intersectRect, returnOne, Utils, returnZero } from "../../../../Utils"; +import { aggregateBounds, intersectRect, returnOne, Utils, returnZero, returnFalse } from "../../../../Utils"; import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; import { DocServer } from "../../../DocServer"; import { Docs } from "../../../documents/Documents"; @@ -43,6 +43,7 @@ import "./CollectionFreeFormView.scss"; import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); +import { CollectionViewType } from "../CollectionView"; library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); @@ -860,7 +861,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument, u LibraryPath: this.libraryPath, FreezeDimensions: this.props.freezeChildDimensions, layoutKey: undefined, - rootSelected: this.rootSelected, + rootSelected: childData ? this.rootSelected : returnFalse, dropAction: StrCast(this.props.Document.childDropAction) as dropActionType, //onClick: undefined, // this.props.onClick, // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them onClick: this.onChildClickHandler, @@ -1105,10 +1106,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument, u _nudgeTime = 0; nudge = action((x: number, y: number) => { - 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); - this._nudgeTime = Date.now(); - setTimeout(() => (Date.now() - this._nudgeTime >= 500) && (this.Document.panTransformType = undefined), 500); + 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); + this._nudgeTime = Date.now(); + setTimeout(() => (Date.now() - this._nudgeTime >= 500) && (this.Document.panTransformType = undefined), 500); + return true; + } + return false; }); @computed get marqueeView() { return void; isSelected: () => boolean; isAnnotationOverlay?: boolean; - nudge:(x:number, y:number) => void; + nudge: (x: number, y: number) => boolean; setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void; } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 3503af442..e7cb2c015 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -60,8 +60,8 @@ export class CollectionFreeFormDocumentView extends DocComponent { - this.layoutDoc.x = NumCast(this.layoutDoc.x) + x; - this.layoutDoc.y = NumCast(this.layoutDoc.y) + y; + this.props.Document.x = NumCast(this.props.Document.x) + x; + this.props.Document.y = NumCast(this.props.Document.y) + y; } contentScaling = () => this.nativeWidth > 0 && !this.props.fitToBox && !this.freezeDimensions ? this.width / this.nativeWidth : 1; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3784c5c9c..cc3c39154 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -289,13 +289,15 @@ export class DocumentView extends DocComponent(Docu let preventDefault = true; this.props.Document.isBackground === undefined && this.props.bringToFront(this.props.Document); if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click - const fullScreenAlias = Doc.MakeAlias(this.props.Document); - if (StrCast(fullScreenAlias.layoutKey) !== "layout_fullScreen" && fullScreenAlias.layout_fullScreen) { - fullScreenAlias.layoutKey = "layout_fullScreen"; + if (!(e.nativeEvent as any).formattedHandled) { + const fullScreenAlias = Doc.MakeAlias(this.props.Document); + if (StrCast(fullScreenAlias.layoutKey) !== "layout_fullScreen" && fullScreenAlias.layout_fullScreen) { + fullScreenAlias.layoutKey = "layout_fullScreen"; + } + UndoManager.RunInBatch(() => this.props.addDocTab(fullScreenAlias, "inTab"), "double tap"); + SelectionManager.DeselectAll(); + Doc.UnBrushDoc(this.props.Document); } - UndoManager.RunInBatch(() => this.props.addDocTab(fullScreenAlias, "inTab"), "double tap"); - SelectionManager.DeselectAll(); - Doc.UnBrushDoc(this.props.Document); } else if (this.onClickHandler?.script) { SelectionManager.DeselectAll(); const func = () => this.onClickHandler.script.run({ @@ -978,7 +980,7 @@ export class DocumentView extends DocComponent(Docu return typeof fallback === "string" ? fallback : "layout"; } rootSelected = (outsideReaction?: boolean) => { - return this.isSelected(outsideReaction) || (this.props.Document.forceActive && this.props.rootSelected?.(outsideReaction) ? true : false); + return this.isSelected(outsideReaction) || (this.rootDoc && this.props.rootSelected?.(outsideReaction)); } childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling()); panelWidth = () => this.props.PanelWidth(); -- cgit v1.2.3-70-g09d2 From 30db3b71d3661d7cd41ed32f4004069cb10ec2b4 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 22 Apr 2020 12:31:40 -0400 Subject: added raw text field for PDFs. fixed search scrolling in text boxes. --- src/client/views/collections/CollectionSubView.tsx | 1 + src/client/views/nodes/FormattedTextBox.tsx | 13 +++++-------- src/server/DashUploadUtils.ts | 7 ++++--- src/server/SharedMediaTypes.ts | 1 + 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 37cf942c6..ca38a21b8 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -388,6 +388,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: continue; } const proto = Doc.GetProto(doc); + proto.text = result.rawText; proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, ""); if (Upload.isImageInformation(result)) { proto["data-nativeWidth"] = (result.nativeWidth > result.nativeHeight) ? 400 * result.nativeWidth / result.nativeHeight : 400; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 62911dc5c..c8eb4c23c 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -596,7 +596,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.setupEditor(this.config, this.props.fieldKey); - this._searchReactionDisposer = reaction(() => this.layoutDoc.searchMatch, + this._searchReactionDisposer = reaction(() => this.rootDoc.searchMatch, search => search ? this.highlightSearchTerms([Doc.SearchQuery()]) : this.unhighlightSearchTerms(), { fireImmediately: true }); @@ -821,13 +821,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._editorView = new EditorView(this.ProseRef, { state: rtfField?.Data ? EditorState.fromJSON(config, JSON.parse(rtfField.Data)) : EditorState.create(config), handleScrollToSelection: (editorView) => { - const ref = editorView.domAtPos(editorView.state.selection.from); - let refNode = ref.node as any; - while (refNode && !("getBoundingClientRect" in refNode)) refNode = refNode.parentElement; - const r1 = refNode?.getBoundingClientRect(); - const r3 = self._ref.current!.getBoundingClientRect(); - if (r1.top < r3.top || r1.top > r3.bottom) { - r1 && (self._scrollRef.current!.scrollTop += (r1.top - r3.top) * self.props.ScreenToLocalTransform().Scale); + const docPos = editorView.coordsAtPos(editorView.state.selection.from); + const viewRect = self._ref.current!.getBoundingClientRect(); + if (docPos.top < viewRect.top || docPos.top > viewRect.bottom) { + docPos && (self._scrollRef.current!.scrollTop += (docPos.top - viewRect.top) * self.props.ScreenToLocalTransform().Scale); } return true; }, diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 9b518749c..3f903a861 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -100,7 +100,7 @@ export namespace DashUploadUtils { const writeStream = createWriteStream(serverPathToFile(Directory.text, textFilename)); writeStream.write(result.text, error => error ? reject(error) : resolve()); }); - return MoveParsedFile(file, Directory.pdfs); + return MoveParsedFile(file, Directory.pdfs, undefined, result.text); } const manualSuffixes = [".webm"]; @@ -237,7 +237,7 @@ export namespace DashUploadUtils { * @param suffix If the file doesn't have a suffix and you want to provide it one * to appear in the new location */ - export async function MoveParsedFile(file: File, destination: Directory, suffix: string | undefined = undefined): Promise { + export async function MoveParsedFile(file: File, destination: Directory, suffix: string | undefined = undefined, text?: string): Promise { const { path: sourcePath } = file; let name = path.basename(sourcePath); suffix && (name += suffix); @@ -249,7 +249,8 @@ export namespace DashUploadUtils { result: error ? error : { accessPaths: { agnostic: getAccessPaths(destination, name) - } + }, + rawText: text } }); }); diff --git a/src/server/SharedMediaTypes.ts b/src/server/SharedMediaTypes.ts index 2495123b7..0f788f6c5 100644 --- a/src/server/SharedMediaTypes.ts +++ b/src/server/SharedMediaTypes.ts @@ -21,6 +21,7 @@ export namespace Upload { export interface FileInformation { accessPaths: AccessPathInfo; + rawText?: string; } export type FileResponse = { source: File, result: T | Error }; -- cgit v1.2.3-70-g09d2 From a51439a6569079ca2652ce28745317fecce3a353 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 24 Apr 2020 10:53:51 -0400 Subject: changing how multiple images are imported -- now a pile. imagebox chooses render quality based on image width. --- src/client/views/collections/CollectionSubView.tsx | 11 +++++++++-- .../collections/collectionFreeForm/MarqueeView.tsx | 22 ++-------------------- src/client/views/nodes/ImageBox.tsx | 4 ++-- src/new_fields/Doc.ts | 21 ++++++++++++++++++++- 4 files changed, 33 insertions(+), 25 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index ca38a21b8..78ba3d6e6 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -398,8 +398,15 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: generatedDocuments.push(doc); } if (generatedDocuments.length) { - generatedDocuments.forEach(addDocument); - completed && completed(); + const set = generatedDocuments.length > 1 && generatedDocuments.map(d => Doc.iconify(d)); + if (set) { + const pile = Docs.Create.FreeformDocument(generatedDocuments, { ...options, title: "pile", _LODdisable: true, }); + Doc.pileup(pile, generatedDocuments); + addDocument(pile); + } else { + generatedDocuments.forEach(addDocument); + } + completed?.(); } else { if (text && !text.includes("https://")) { addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 })); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index d8e73a820..ab8174ba1 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -337,31 +337,13 @@ export class MarqueeView extends React.Component { const selected = this.marqueeSelect(false); SelectionManager.DeselectAll(); - - let w = 0, h = 0; - selected.forEach((d, i) => { - Doc.iconify(d); - w = Math.max(d[WidthSym](), w); - h = Math.max(d[HeightSym](), h); - }); - selected.forEach((d, i) => { - this.props.removeDocument(d); - d.x = Math.cos(Math.PI * 2 * i / selected.length) * 10 - w / 2; - d.y = Math.sin(Math.PI * 2 * i / selected.length) * 10 - h / 2; - d.displayTimecode = undefined; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - }); + selected.forEach(d => this.props.removeDocument(d)); const newCollection = this.getCollection(selected, false); - newCollection.x = NumCast(newCollection.x) + NumCast(newCollection._width) / 2 - 55; - newCollection.y = NumCast(newCollection.y) + NumCast(newCollection._height) / 2 - 55; - newCollection._width = newCollection._height = 110; - //newCollection.borderRounding = "40px"; - newCollection.jitterRotation = 10; - newCollection._backgroundColor = "yellow"; + Doc.pileup(newCollection, selected); this.props.addDocument(newCollection); this.props.selectDocuments([newCollection], []); MarqueeOptionsMenu.Instance.fadeOut(true); this.hideMarquee(); - Doc.pileup(newCollection); } @action diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index cf6a7ba5b..e189f5814 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -223,8 +223,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent { + Doc.iconify(d); + w = Math.max(d[WidthSym](), w); + h = Math.max(d[HeightSym](), h); + }); + h = Math.max(h, w * 4 / 3); // converting to an icon does not update the height right away. so this is a fallback hack to try to do something reasonable + selected.forEach((d, i) => { + d.x = Math.cos(Math.PI * 2 * i / selected.length) * 10 - w / 2; + d.y = Math.sin(Math.PI * 2 * i / selected.length) * 10 - h / 2; + d.displayTimecode = undefined; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection + }); + newCollection.x = NumCast(newCollection.x) + NumCast(newCollection._width) / 2 - 55; + newCollection.y = NumCast(newCollection.y) + NumCast(newCollection._height) / 2 - 55; + newCollection._width = newCollection._height = 110; + //newCollection.borderRounding = "40px"; + newCollection.jitterRotation = 10; + newCollection._backgroundColor = "gray"; + newCollection._layoutEngine = "pass"; newCollection.overflow = "visible"; const script = "if (self._layoutEngine === 'starburst') {" + -- cgit v1.2.3-70-g09d2 From efd038bd12de35abc80141b130be523e3fea077a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 25 Apr 2020 03:42:51 -0400 Subject: hopefully final cleanup of pile up collection view. added doubleTap support in setupMoveUpEvents --- src/Utils.ts | 12 ++- src/client/documents/Documents.ts | 4 + .../views/collections/CollectionPileView.scss | 8 ++ .../views/collections/CollectionPileView.tsx | 97 ++++++++++++++++++++++ src/client/views/collections/CollectionSubView.tsx | 4 +- .../views/collections/CollectionTimeView.tsx | 3 +- src/client/views/collections/CollectionView.tsx | 5 +- .../CollectionFreeFormLayoutEngines.tsx | 95 ++++++++++----------- .../collectionFreeForm/CollectionFreeFormView.tsx | 19 +++-- .../collections/collectionFreeForm/MarqueeView.tsx | 16 ++-- src/new_fields/Doc.ts | 35 ++------ 11 files changed, 189 insertions(+), 109 deletions(-) create mode 100644 src/client/views/collections/CollectionPileView.scss create mode 100644 src/client/views/collections/CollectionPileView.tsx (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 9acdc8731..ad12c68a1 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -504,8 +504,9 @@ export function setupMoveUpEvents( e: React.PointerEvent, moveEvent: (e: PointerEvent, down: number[], delta: number[]) => boolean, upEvent: (e: PointerEvent) => void, - clickEvent: (e: PointerEvent) => void, - stopPropagation: boolean = true + clickEvent: (e: PointerEvent, doubleTap?: boolean) => void, + stopPropagation: boolean = true, + stopMovePropagation: boolean = true ) { (target as any)._downX = (target as any)._lastX = e.clientX; (target as any)._downY = (target as any)._lastY = e.clientY; @@ -520,12 +521,15 @@ export function setupMoveUpEvents( } (target as any)._lastX = e.clientX; (target as any)._lastY = e.clientY; - e.stopPropagation(); + stopMovePropagation && e.stopPropagation(); }; + (target as any)._doubleTap = false; const _upEvent = (e: PointerEvent): void => { + (target as any)._doubleTap = (Date.now() - (target as any)._lastTap < 300); + (target as any)._lastTap = Date.now(); upEvent(e); if (Math.abs(e.clientX - (target as any)._downX) < 4 && Math.abs(e.clientY - (target as any)._downY) < 4) { - clickEvent(e); + clickEvent(e, (target as any)._doubleTap); } document.removeEventListener("pointermove", _moveEvent); document.removeEventListener("pointerup", _upEvent); diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 578d337d6..1268c97b0 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -612,6 +612,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Freeform }, id); } + export function PileDocument(documents: Array, options: DocumentOptions, id?: string) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Pile }, id); + } + export function LinearDocument(documents: Array, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Linear }, id); } diff --git a/src/client/views/collections/CollectionPileView.scss b/src/client/views/collections/CollectionPileView.scss new file mode 100644 index 000000000..ac874b663 --- /dev/null +++ b/src/client/views/collections/CollectionPileView.scss @@ -0,0 +1,8 @@ +.collectionPileView { + display: flex; + flex-direction: row; + position: absolute; + height: 100%; + width: 100%; + overflow: visible; +} diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx new file mode 100644 index 000000000..511efe0a7 --- /dev/null +++ b/src/client/views/collections/CollectionPileView.tsx @@ -0,0 +1,97 @@ +import { action, computed, observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; +import { HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; +import { ScriptField } from "../../../new_fields/ScriptField"; +import { BoolCast, NumCast, StrCast } from "../../../new_fields/Types"; +import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from "../ContextMenuItem"; +import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView"; +import { CollectionSubView } from "./CollectionSubView"; +import "./CollectionPileView.scss"; +import React = require("react"); +import { setupMoveUpEvents, emptyFunction, returnFalse } from "../../../Utils"; +import { SelectionManager } from "../../util/SelectionManager"; + +@observer +export class CollectionPileView extends CollectionSubView(doc => doc) { + _lastTap = 0; + _doubleTap: boolean | undefined = false; + _originalChrome: string = ""; + @observable _contentsActive = true; + @observable _layoutEngine = "pass"; + @observable _collapsed: boolean = false; + @observable _childClickedScript: Opt; + componentDidMount() { + this._originalChrome = StrCast(this.layoutDoc._chromeStatus); + this.layoutDoc._chromeStatus = "disabled"; + this.layoutDoc.hideFilterView = true; + } + componentWillUnmount() { + this.layoutDoc.hideFilterView = false; + this.layoutDoc._chromeStatus = this._originalChrome; + } + + layoutEngine = () => this._layoutEngine; + + @computed get contents() { + return

+ +
; + } + + specificMenu = (e: React.MouseEvent) => { + const layoutItems: ContextMenuProps[] = []; + const doc = this.props.Document; + + ContextMenu.Instance.addItem({ description: "Options...", subitems: layoutItems, icon: "eye" }); + } + + toggleStarburst = action(() => { + if (this._layoutEngine === 'starburst') { + const defaultSize = 110; + this.layoutDoc.overflow = undefined; + this.rootDoc.x = NumCast(this.rootDoc.x) + this.layoutDoc[WidthSym]() / 2 - NumCast(this.layoutDoc._starburstPileWidth, defaultSize) / 2; + this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[HeightSym]() / 2 - NumCast(this.layoutDoc._starburstPileHeight, defaultSize) / 2; + this.layoutDoc._width = NumCast(this.layoutDoc._starburstPileWidth, defaultSize); + this.layoutDoc._height = NumCast(this.layoutDoc._starburstPileHeight, defaultSize); + this._layoutEngine = 'pass'; + } else { + const defaultSize = 25; + this.layoutDoc.overflow = 'visible'; + !this.layoutDoc._starburstRadius && (this.layoutDoc._starburstRadius = 500); + !this.layoutDoc._starburstDocScale && (this.layoutDoc._starburstDocScale = 2.5); + if (this._layoutEngine === 'pass') { + this.rootDoc.x = NumCast(this.rootDoc.x) + this.layoutDoc[WidthSym]() / 2 - defaultSize / 2; + this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[HeightSym]() / 2 - defaultSize / 2; + this.layoutDoc._starburstPileWidth = this.layoutDoc[WidthSym](); + this.layoutDoc._starburstPileHeight = this.layoutDoc[HeightSym](); + } + this.layoutDoc._width = this.layoutDoc._height = defaultSize; + this._layoutEngine = 'starburst'; + } + }); + + pointerDown = (e: React.PointerEvent) => { + // this._lastTap should be set to 0, and this._doubleTap should be set to false in the class header + setupMoveUpEvents(this, e, returnFalse, emptyFunction, emptyFunction, false, false); // this sets _doubleTap + } + + onClick = (e: React.MouseEvent) => { + if (e.button === 0 && (this._doubleTap || this.layoutEngine() === "starburst")) { + SelectionManager.DeselectAll(); + this.toggleStarburst(); + e.stopPropagation(); + } else if (this.layoutEngine() === "pass") { + runInAction(() => this._contentsActive = false); + setTimeout(action(() => this._contentsActive = true), 300); + } + } + + render() { + + return
+ {this.contents} +
; + } +} diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 78ba3d6e6..c530b24fb 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -400,9 +400,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: if (generatedDocuments.length) { const set = generatedDocuments.length > 1 && generatedDocuments.map(d => Doc.iconify(d)); if (set) { - const pile = Docs.Create.FreeformDocument(generatedDocuments, { ...options, title: "pile", _LODdisable: true, }); - Doc.pileup(pile, generatedDocuments); - addDocument(pile); + addDocument(Doc.pileup(generatedDocuments, options.x!, options.y!)); } else { generatedDocuments.forEach(addDocument); } diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 63498cea1..045134225 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -19,7 +19,6 @@ const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; import React = require("react"); -import { DocumentView } from "../nodes/DocumentView"; @observer export class CollectionTimeView extends CollectionSubView(doc => doc) { @@ -84,7 +83,7 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { } @computed get contents() { - return
+ return
; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 47e79f088..f82c6d8a6 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -46,6 +46,7 @@ import { InteractionUtils } from '../../util/InteractionUtils'; import { ObjectField } from '../../../new_fields/ObjectField'; import CollectionMapView from './CollectionMapView'; import { Transform } from 'prosemirror-transform'; +import { CollectionPileView } from './CollectionPileView'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -67,7 +68,8 @@ export enum CollectionViewType { Carousel = "carousel", Linear = "linear", Staff = "staff", - Map = "map" + Map = "map", + Pile = "pileup" } export interface CollectionRenderProps { @@ -169,6 +171,7 @@ export class CollectionView extends Touchable { case CollectionViewType.Multicolumn: return (); case CollectionViewType.Multirow: return (); case CollectionViewType.Linear: { return (); } + case CollectionViewType.Pile: { return (); } case CollectionViewType.Carousel: { return (); } case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index d8bd18ec7..9ca747113 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -13,10 +13,11 @@ import { listSpec } from "../../../../new_fields/Schema"; export interface ViewDefBounds { type: string; - text?: string; + payload: any; x: number; y: number; z?: number; + text?: string; zIndex?: number; width?: number; height?: number; @@ -24,14 +25,13 @@ export interface ViewDefBounds { fontSize?: number; highlight?: boolean; color?: string; - payload: any; replica?: string; pair?: { layout: Doc, data?: Doc }; } export interface PoolData { - x?: number; - y?: number; + x: number; + y: number; z?: number; zIndex?: number; width?: number; @@ -40,7 +40,7 @@ export interface PoolData { transition?: string; highlight?: boolean; replica?: string; - pair: { layout: Doc, data?: Doc } + pair: { layout: Doc, data?: Doc }; } export interface ViewDefResult { @@ -84,96 +84,88 @@ interface PivotColumn { export function computerPassLayout( poolData: Map, pivotDoc: Doc, - filterDocs: Doc[], childPairs: { layout: Doc, data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[] ) { - const docMap = new Map(); + const docMap = new Map(); childPairs.forEach(({ layout, data }, i) => { docMap.set(layout[Id], { - type: "doc", x: NumCast(layout.x), y: NumCast(layout.y), width: layout[WidthSym](), height: layout[HeightSym](), - payload: undefined, pair: { layout, data }, replica: "" }); }); - return normalizeResults(panelDim, 12, childPairs, docMap, poolData, viewDefsToJSX, [], 0, [], childPairs.filter(c => !filterDocs.includes(c.layout))); + return normalizeResults(panelDim, 12, docMap, poolData, viewDefsToJSX, [], 0, []); } export function computerStarburstLayout( poolData: Map, pivotDoc: Doc, - filterDocs: Doc[], childPairs: { layout: Doc, data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[] ) { - const docMap = new Map(); + const docMap = new Map(); const burstRadius = [NumCast(pivotDoc._starburstRadius, panelDim[0]), NumCast(pivotDoc._starburstRadius, panelDim[1])]; const docScale = NumCast(pivotDoc._starburstDocScale); const docSize = docScale * 100; // assume a icon sized at 100 const scaleDim = [burstRadius[0] + docSize, burstRadius[1] + docSize]; - childPairs.forEach((pair, i) => { + childPairs.forEach(({ layout, data }, i) => { const deg = i / childPairs.length * Math.PI * 2; - docMap.set(pair.layout[Id], { - type: "doc", - x: Math.cos(deg) * (burstRadius[0] / 3) - docScale * pair.layout[WidthSym]() / 2, - y: Math.sin(deg) * (burstRadius[1] / 3) - docScale * pair.layout[HeightSym]() / 2, - width: docScale * pair.layout[WidthSym](), - height: docScale * pair.layout[HeightSym](), - payload: undefined, + docMap.set(layout[Id], { + x: Math.cos(deg) * (burstRadius[0] / 3) - docScale * layout[WidthSym]() / 2, + y: Math.sin(deg) * (burstRadius[1] / 3) - docScale * layout[HeightSym]() / 2, + width: docScale * layout[WidthSym](), + height: docScale * layout[HeightSym](), + pair: { layout, data }, replica: "" }); }); - return normalizeResults(scaleDim, 12, childPairs, docMap, poolData, viewDefsToJSX, [], 0, [], childPairs.filter(c => !filterDocs.includes(c.layout))); + return normalizeResults(scaleDim, 12, docMap, poolData, viewDefsToJSX, [], 0, []); } export function computePivotLayout( poolData: Map, pivotDoc: Doc, - filterDocs: Doc[], childPairs: { layout: Doc, data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[] ) { - const docMap = new Map(); + const docMap = new Map(); const fieldKey = "data"; const pivotColumnGroups = new Map, PivotColumn>(); const pivotFieldKey = toLabel(pivotDoc._pivotField); - for (const doc of filterDocs) { - const lval = Cast(doc[pivotFieldKey], listSpec("string"), null); - const val = Field.toString(doc[pivotFieldKey] as Field); + childPairs.map(pair => { + const lval = Cast(pair.layout[pivotFieldKey], listSpec("string"), null); + const val = Field.toString(pair.layout[pivotFieldKey] as Field); if (lval) { lval.forEach((val, i) => { !pivotColumnGroups.get(val) && pivotColumnGroups.set(val, { docs: [], filters: [val], replicas: [] }); - pivotColumnGroups.get(val)!.docs.push(doc); + pivotColumnGroups.get(val)!.docs.push(pair.layout); pivotColumnGroups.get(val)!.replicas.push(i.toString()); }); } else if (val) { !pivotColumnGroups.get(val) && pivotColumnGroups.set(val, { docs: [], filters: [val], replicas: [] }); - pivotColumnGroups.get(val)!.docs.push(doc); + pivotColumnGroups.get(val)!.docs.push(pair.layout); pivotColumnGroups.get(val)!.replicas.push(""); } else { - docMap.set(doc[Id], { - type: "doc", + docMap.set(pair.layout[Id], { x: 0, y: 0, zIndex: -99, width: 0, height: 0, - payload: undefined, - pair: { layout: doc }, + pair, replica: "" - }) + }); } - } + }); let nonNumbers = 0; childPairs.map(pair => { const num = toNumber(pair.layout[pivotFieldKey]); @@ -252,12 +244,10 @@ export function computePivotLayout( wid = layoutDoc._nativeHeight ? (NumCast(layoutDoc._nativeWidth) / NumCast(layoutDoc._nativeHeight)) * pivotAxisWidth : pivotAxisWidth; } docMap.set(doc[Id] + (val.replicas || ""), { - type: "doc", x: x + xCount * pivotAxisWidth * expander + (pivotAxisWidth - wid) / 2 + (val.docs.length < numCols ? (numCols - val.docs.length) * pivotAxisWidth / 2 : 0), y: -y + (pivotAxisWidth - hgt) / 2, width: wid, height: hgt, - payload: undefined, pair: { layout: doc }, replica: val.replicas[i] }); @@ -273,7 +263,7 @@ export function computePivotLayout( const dividers = sortedPivotKeys.map((key, i) => ({ type: "div", color: "lightGray", x: i * pivotAxisWidth * (numCols * expander + gap) - pivotAxisWidth * (expander - 1) / 2, y: -maxColHeight + pivotAxisWidth, width: pivotAxisWidth * numCols * expander, height: maxColHeight, payload: pivotColumnGroups.get(key)!.filters })); groupNames.push(...dividers); - return normalizeResults(panelDim, max_text, childPairs, docMap, poolData, viewDefsToJSX, groupNames, 0, [], childPairs.filter(c => !filterDocs.includes(c.layout))); + return normalizeResults(panelDim, max_text, docMap, poolData, viewDefsToJSX, groupNames, 0, []); } function toNumber(val: FieldResult) { @@ -283,14 +273,13 @@ function toNumber(val: FieldResult) { export function computeTimelineLayout( poolData: Map, pivotDoc: Doc, - filterDocs: Doc[], childPairs: { layout: Doc, data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[] ) { const fieldKey = "data"; const pivotDateGroups = new Map(); - const docMap = new Map(); + const docMap = new Map(); const groupNames: ViewDefBounds[] = []; const timelineFieldKey = Field.toString(pivotDoc._pivotField as Field); const curTime = toNumber(pivotDoc[fieldKey + "-timelineCur"]); @@ -306,11 +295,11 @@ export function computeTimelineLayout( let minTime = minTimeReq === undefined ? Number.MAX_VALUE : minTimeReq; let maxTime = maxTimeReq === undefined ? -Number.MAX_VALUE : maxTimeReq; - filterDocs.map(doc => { - const num = NumCast(doc[timelineFieldKey], Number(StrCast(doc[timelineFieldKey]))); + childPairs.forEach(pair => { + const num = NumCast(pair.layout[timelineFieldKey], Number(StrCast(pair.layout[timelineFieldKey]))); if (!Number.isNaN(num) && (!minTimeReq || num >= minTimeReq) && (!maxTimeReq || num <= maxTimeReq)) { !pivotDateGroups.get(num) && pivotDateGroups.set(num, []); - pivotDateGroups.get(num)!.push(doc); + pivotDateGroups.get(num)!.push(pair.layout); minTime = Math.min(num, minTime); maxTime = Math.max(num, maxTime); } @@ -369,7 +358,7 @@ export function computeTimelineLayout( } const divider = { type: "div", color: Cast(Doc.UserDoc().activeWorkspace, Doc, null)?.darkScheme ? "dimGray" : "black", x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined }; - return normalizeResults(panelDim, fontHeight, childPairs, docMap, poolData, viewDefsToJSX, groupNames, (maxTime - minTime) * scaling, [divider], childPairs.filter(c => !filterDocs.includes(c.layout))); + return normalizeResults(panelDim, fontHeight, docMap, poolData, viewDefsToJSX, groupNames, (maxTime - minTime) * scaling, [divider]); function layoutDocsAtTime(keyDocs: Doc[], key: number) { keyDocs.forEach(doc => { @@ -382,13 +371,11 @@ export function computeTimelineLayout( wid = layoutDoc._nativeHeight ? (NumCast(layoutDoc._nativeWidth) / NumCast(layoutDoc._nativeHeight)) * pivotAxisWidth : pivotAxisWidth; } docMap.set(doc[Id], { - type: "doc", x: x, y: -Math.sqrt(stack) * pivotAxisWidth / 2 - pivotAxisWidth + (pivotAxisWidth - hgt) / 2, zIndex: (curTime === key ? 1000 : zind++), highlight: curTime === key, width: wid / (Math.max(stack, 1)), height: hgt / (Math.max(stack, 1)), - payload: undefined, pair: { layout: doc }, replica: "" }); @@ -397,12 +384,19 @@ export function computeTimelineLayout( } } -function normalizeResults(panelDim: number[], fontHeight: number, childPairs: { data?: Doc, layout: Doc }[], docMap: Map, - poolData: Map, viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], groupNames: ViewDefBounds[], minWidth: number, extras: ViewDefBounds[], - extraDocs: { data?: Doc, layout: Doc }[]): ViewDefResult[] { +function normalizeResults( + panelDim: number[], + fontHeight: number, + docMap: Map, + poolData: Map, + viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], + groupNames: ViewDefBounds[], + minWidth: number, + extras: ViewDefBounds[] +): ViewDefResult[] { const grpEles = groupNames.map(gn => ({ x: gn.x, y: gn.y, width: gn.width, height: gn.height }) as ViewDefBounds); const docEles = Array.from(docMap.entries()).map(ele => ele[1]); - const aggBounds = aggregateBounds(docEles.concat(grpEles).filter(e => e.zIndex !== -99), 0, 0); + const aggBounds = aggregateBounds(grpEles.concat(docEles.map(de => ({ ...de, type: "doc", payload: "" }))).filter(e => e.zIndex !== -99), 0, 0); aggBounds.r = Math.max(minWidth, aggBounds.r - aggBounds.x); const wscale = panelDim[0] / (aggBounds.r - aggBounds.x); let scale = wscale * (aggBounds.b - aggBounds.y) > panelDim[1] ? (panelDim[1]) / (aggBounds.b - aggBounds.y) : wscale; @@ -420,12 +414,11 @@ function normalizeResults(panelDim: number[], fontHeight: number, childPairs: { zIndex: newPosRaw.zIndex, width: (newPosRaw.width || 0) * scale, height: newPosRaw.height! * scale, - pair: ele[1].pair! + pair: ele[1].pair }; poolData.set(newPos.pair.layout[Id] + (newPos.replica || ""), { transition: "transform 1s", ...newPos }); } }); - extraDocs.map(ed => poolData.set(ed.layout[Id], { x: 0, y: 0, zIndex: -99, pair: ed })); return viewDefsToJSX(extras.concat(groupNames).map(gname => ({ type: gname.type, diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 5555d9e84..af9d3c5be 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -902,7 +902,7 @@ export class CollectionFreeFormView extends CollectionSubView, pivotDoc: Doc, - filterDocs: Doc[], childPairs: { layout: Doc, data?: Doc }[], panelDim: number[], - viewDefsToJSX: ((views: ViewDefBounds[]) => ViewDefResult[])) => ViewDefResult[]) { - return engine(poolData, this.props.Document, this.childDocs, - this.childLayoutPairs, [this.props.PanelWidth(), this.props.PanelHeight()], this.viewDefsToJSX); + viewDefsToJSX: ((views: ViewDefBounds[]) => ViewDefResult[])) => ViewDefResult[] + ) { + return engine(poolData, this.props.Document, this.childLayoutPairs, [this.props.PanelWidth(), this.props.PanelHeight()], this.viewDefsToJSX); } doFreeformLayout(poolData: Map) { @@ -977,7 +976,7 @@ export class CollectionFreeFormView extends CollectionSubView(); - const engine = StrCast(this.layoutDoc._layoutEngine) || this.props.layoutEngine?.(); + const engine = this.props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine); switch (engine) { case "pass": return { newPool, computedElementData: this.doEngineLayout(newPool, computerPassLayout) }; case "timeline": return { newPool, computedElementData: this.doEngineLayout(newPool, computeTimelineLayout) }; @@ -1001,6 +1000,7 @@ export class CollectionFreeFormView extends CollectionSubView this._cachedPool.set(k[0], k[1])); const elements: ViewDefResult[] = computedElementData.slice(); + const engine = this.props.layoutEngine?.() || StrCast(this.props.Document._layoutEngine); Array.from(newPool.entries()).filter(entry => this.isCurrent(entry[1].pair.layout)).forEach(entry => elements.push({ ele: , @@ -1082,7 +1083,7 @@ export class CollectionFreeFormView extends CollectionSubView this.props.Document.jitterRotation = (this.props.Document.jitterRotation ? 0 : 10)), icon: "paint-brush" }); + optionItems.push({ description: "Jitter Rotation", event: action(() => this.props.Document._jitterRotation = (this.props.Document._jitterRotation ? 0 : 10)), icon: "paint-brush" }); optionItems.push({ description: "Import document", icon: "upload", event: ({ x, y }) => { const input = document.createElement("input"); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index ab8174ba1..cd8166309 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,12 +1,12 @@ import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, DataSym, WidthSym, HeightSym } from "../../../../new_fields/Doc"; +import { Doc, DocListCast, DataSym, WidthSym, HeightSym, Opt } from "../../../../new_fields/Doc"; import { InkField, InkData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField"; import { Cast, NumCast, FieldValue, StrCast } from "../../../../new_fields/Types"; import { Utils } from "../../../../Utils"; -import { Docs, DocUtils } from "../../../documents/Documents"; +import { Docs, DocUtils, DocumentOptions } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; import { Transform } from "../../../util/Transform"; import { undoBatch } from "../../../util/UndoManager"; @@ -310,11 +310,10 @@ export class MarqueeView extends React.Component { + getCollection = (selected: Doc[], creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, isBackground?: boolean) => { const bounds = this.Bounds; // const inkData = this.ink ? this.ink.inkData : undefined; - const creator = asTemplate ? Docs.Create.StackingDocument : Docs.Create.FreeformDocument; - const newCollection = creator(selected, { + const newCollection = (creator || Docs.Create.FreeformDocument)(selected, { x: bounds.left, y: bounds.top, _panX: 0, @@ -338,8 +337,7 @@ export class MarqueeView extends React.Component this.props.removeDocument(d)); - const newCollection = this.getCollection(selected, false); - Doc.pileup(newCollection, selected); + const newCollection = Doc.pileup(selected, this.Bounds.left + this.Bounds.width / 2, this.Bounds.top + this.Bounds.height / 2); this.props.addDocument(newCollection); this.props.selectDocuments([newCollection], []); MarqueeOptionsMenu.Instance.fadeOut(true); @@ -359,7 +357,7 @@ export class MarqueeView extends React.Component { - const newCollection = this.getCollection([], false, true); + const newCollection = this.getCollection([], undefined, true); this.props.addDocument(newCollection); MarqueeOptionsMenu.Instance.fadeOut(true); this.hideMarquee(); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 18ffc38f5..337274774 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -976,7 +976,8 @@ export namespace Doc { if (layoutKey && layoutKey !== "layout" && layoutKey !== "layout_icon") doc.deiconifyLayout = layoutKey.replace("layout_", ""); } - export function pileup(newCollection: Doc, selected: Doc[]) { + export function pileup(selected: Doc[], x: number, y: number) { + const newCollection = Docs.Create.PileDocument(selected, { title: "pileup", x: x - 55, y: y - 55, _width: 110, _height: 100, _LODdisable: true }); let w = 0, h = 0; selected.forEach((d, i) => { Doc.iconify(d); @@ -993,12 +994,10 @@ export namespace Doc { newCollection.y = NumCast(newCollection.y) + NumCast(newCollection._height) / 2 - 55; newCollection._width = newCollection._height = 110; //newCollection.borderRounding = "40px"; - newCollection.jitterRotation = 10; + newCollection._jitterRotation = 10; newCollection._backgroundColor = "gray"; - - newCollection._layoutEngine = "pass"; newCollection.overflow = "visible"; - newCollection.onClick = ScriptField.MakeScript("toggleStarburst(self, this)", { self: Doc.name, this: Doc.name }); + return newCollection; } @@ -1055,28 +1054,4 @@ Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: bo return docs.length ? new List(docs) : prevValue; }); Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: "check" | "x" | undefined) { Doc.setDocFilter(container, key, value, modifiers); }); -Scripting.addGlobal(function setDocFilterRange(container: Doc, key: string, range: number[]) { Doc.setDocFilterRange(container, key, range); }); -Scripting.addGlobal(function toggleStarburst(self: Doc, tLayout: Doc) { - if (self._layoutEngine === 'starburst') { - const defaultSize = 110; - tLayout.overflow = undefined; - self.x = NumCast(self.x) + tLayout[WidthSym]() / 2 - NumCast(tLayout._starburstPileWidth, defaultSize) / 2; - self.y = NumCast(self.y) + tLayout[HeightSym]() / 2 - NumCast(tLayout._starburstPileHeight, defaultSize) / 2; - tLayout._width = NumCast(tLayout._starburstPileWidth, defaultSize); - tLayout._height = NumCast(tLayout._starburstPileHeight, defaultSize); - self._layoutEngine = 'pass'; - } else { - const defaultSize = 25; - tLayout.overflow = 'visible'; - !tLayout._starburstRadius && (tLayout._starburstRadius = 500); - !tLayout._starburstDocScale && (tLayout._starburstDocScale = 2.5); - if (self._layoutEngine === 'pass') { - self.x = NumCast(self.x) + tLayout[WidthSym]() / 2 - defaultSize / 2; - self.y = NumCast(self.y) + tLayout[HeightSym]() / 2 - defaultSize / 2; - tLayout._starburstPileWidth = tLayout[WidthSym](); - tLayout._starburstPileHeight = tLayout[HeightSym](); - } - tLayout._width = tLayout._height = defaultSize; - self._layoutEngine = 'starburst'; - } -}); \ No newline at end of file +Scripting.addGlobal(function setDocFilterRange(container: Doc, key: string, range: number[]) { Doc.setDocFilterRange(container, key, range); }); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 627adb92b604e117694e26af65afdc19920ac509 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 25 Apr 2020 21:26:28 -0400 Subject: added internalPreDrop to set dropActions. made linksView turn off during dragging. --- src/client/util/DragManager.ts | 22 ++++++++++++++++++++-- .../views/collections/CollectionPileView.tsx | 2 ++ src/client/views/collections/CollectionSubView.tsx | 7 ++++++- .../CollectionFreeFormLinksView.tsx | 2 +- 4 files changed, 29 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 6bb44f7d6..6a55f4a00 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -179,7 +179,8 @@ export namespace DragManager { export function MakeDropTarget( element: HTMLElement, - dropFunc: (e: Event, de: DropEvent) => void + dropFunc: (e: Event, de: DropEvent) => void, + preDropFunc?: (e: Event, de: DropEvent) => void ): DragDropDisposer { if ("canDrop" in element.dataset) { throw new Error( @@ -187,10 +188,13 @@ export namespace DragManager { ); } element.dataset.canDrop = "true"; - const handler = (e: Event) => { dropFunc(e, (e as CustomEvent).detail); }; + const handler = (e: Event) => dropFunc(e, (e as CustomEvent).detail); + const preDropHandler = (e: Event) => preDropFunc?.(e, (e as CustomEvent).detail); element.addEventListener("dashOnDrop", handler); + preDropFunc && element.addEventListener("dashPreDrop", preDropHandler); return () => { element.removeEventListener("dashOnDrop", handler); + preDropFunc && element.removeEventListener("dashPreDrop", preDropHandler); delete element.dataset.canDrop; }; } @@ -425,6 +429,20 @@ export namespace DragManager { }); if (target) { const complete = new DragCompleteEvent(false, dragData); + target.dispatchEvent( + new CustomEvent("dashPreDrop", { + bubbles: true, + detail: { + x: e.x, + y: e.y, + complete: complete, + shiftKey: e.shiftKey, + altKey: e.altKey, + metaKey: e.metaKey, + ctrlKey: e.ctrlKey + } + }) + ); finishDrag?.(complete); target.dispatchEvent( new CustomEvent("dashOnDrop", { diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index 410b16ec7..3bbfcc4d7 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -78,6 +78,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { _undoBatch: UndoManager.Batch | undefined; pointerDown = (e: React.PointerEvent) => { let dist = 0; + SelectionManager.SetIsDragging(true); // this._lastTap should be set to 0, and this._doubleTap should be set to false in the class header setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => { if (this.layoutEngine() === "pass" && this.childDocs.length && this.props.isSelected(true)) { @@ -97,6 +98,7 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { }, () => { this._undoBatch?.end(); this._undoBatch = undefined; + SelectionManager.SetIsDragging(false); if (!this.childDocs.length) { this.props.ContainingCollectionView?.removeDocument(this.props.Document); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index c530b24fb..60cc1bd49 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -64,7 +64,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: this.multiTouchDisposer?.(); if (ele) { this._mainCont = ele; - this.dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this)); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.onInternalPreDrop.bind(this)); this.gestureDisposer = GestureUtils.MakeGestureTarget(ele, this.onGesture.bind(this)); this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(ele, this.onTouchStart.bind(this)); } @@ -208,6 +208,11 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: protected onGesture(e: Event, ge: GestureUtils.GestureEvent) { } + protected onInternalPreDrop(e: Event, de: DragManager.DropEvent): boolean { + // de.complete.docDragData!.dropAction = "alias"; bcz: for example, you can convert all drops to aliases here + return true; + } + @undoBatch @action protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 702b02a20..4b5e977df 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -36,7 +36,7 @@ export class CollectionFreeFormLinksView extends React.Component { } render() { - return
+ return SelectionManager.GetIsDragging() ? (null) :
{this.uniqueConnections} -- cgit v1.2.3-70-g09d2 From f1ac48c19b4683668b0df91bd4ad68690a069029 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 25 Apr 2020 21:43:21 -0400 Subject: added a targetDropAction field to specify the drop action from the target's side --- src/client/util/DragManager.ts | 15 ++++++++++----- src/client/views/collections/CollectionCarouselView.tsx | 2 +- src/client/views/collections/CollectionLinearView.tsx | 2 +- .../views/collections/CollectionSchemaMovableTableHOC.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 9 ++------- src/client/views/collections/CollectionTreeView.tsx | 4 ++-- src/client/views/collections/CollectionViewChromes.tsx | 4 ++-- src/client/views/nodes/DocumentView.tsx | 4 ++-- src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/LabelBox.tsx | 2 +- src/new_fields/documentSchemas.ts | 3 ++- 12 files changed, 26 insertions(+), 25 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 6a55f4a00..577366cd4 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,5 +1,5 @@ import { Doc, Field, DocListCast } from "../../new_fields/Doc"; -import { Cast, ScriptCast } from "../../new_fields/Types"; +import { Cast, ScriptCast, StrCast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; @@ -180,7 +180,7 @@ export namespace DragManager { export function MakeDropTarget( element: HTMLElement, dropFunc: (e: Event, de: DropEvent) => void, - preDropFunc?: (e: Event, de: DropEvent) => void + doc?:Doc ): DragDropDisposer { if ("canDrop" in element.dataset) { throw new Error( @@ -189,12 +189,17 @@ export namespace DragManager { } element.dataset.canDrop = "true"; const handler = (e: Event) => dropFunc(e, (e as CustomEvent).detail); - const preDropHandler = (e: Event) => preDropFunc?.(e, (e as CustomEvent).detail); + const preDropHandler = (e:Event) => { + const de = (e as CustomEvent).detail; + if (de.complete.docDragData && doc?.targetDropAction) { + de.complete.docDragData!.dropAction = StrCast(doc.targetDropAction) as dropActionType; + } + } element.addEventListener("dashOnDrop", handler); - preDropFunc && element.addEventListener("dashPreDrop", preDropHandler); + doc && element.addEventListener("dashPreDrop", preDropHandler); return () => { element.removeEventListener("dashOnDrop", handler); - preDropFunc && element.removeEventListener("dashPreDrop", preDropHandler); + doc && element.removeEventListener("dashPreDrop", preDropHandler); delete element.dataset.canDrop; }; } diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 9e7248db2..2453acddf 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -27,7 +27,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument) protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view this._dropDisposer?.(); if (ele) { - this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this)); + this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); } } diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index cb0206260..344dca23a 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -64,7 +64,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view this._dropDisposer && this._dropDisposer(); if (ele) { - this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this)); + this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); } } diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 670d6dbb2..972714e34 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -54,7 +54,7 @@ export class MovableColumn extends React.Component { } createColDropTarget = (ele: HTMLDivElement) => { - this._colDropDisposer && this._colDropDisposer(); + this._colDropDisposer?.(); if (ele) { this._colDropDisposer = DragManager.MakeDropTarget(ele, this.colDrop.bind(this)); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 60cc1bd49..49abc6ee6 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -11,7 +11,7 @@ import { Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { DocumentType } from "../../documents/DocumentTypes"; import { Docs, DocumentOptions } from "../../documents/Documents"; -import { DragManager } from "../../util/DragManager"; +import { DragManager, dropActionType } from "../../util/DragManager"; import { undoBatch, UndoManager } from "../../util/UndoManager"; import { DocComponent } from "../DocComponent"; import { FieldViewProps } from "../nodes/FieldView"; @@ -64,7 +64,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: this.multiTouchDisposer?.(); if (ele) { this._mainCont = ele; - this.dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.onInternalPreDrop.bind(this)); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); this.gestureDisposer = GestureUtils.MakeGestureTarget(ele, this.onGesture.bind(this)); this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(ele, this.onTouchStart.bind(this)); } @@ -208,11 +208,6 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: protected onGesture(e: Event, ge: GestureUtils.GestureEvent) { } - protected onInternalPreDrop(e: Event, de: DragManager.DropEvent): boolean { - // de.complete.docDragData!.dropAction = "alias"; bcz: for example, you can convert all drops to aliases here - return true; - } - @undoBatch @action protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index ca2004b79..8c5a4538e 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -143,7 +143,7 @@ class TreeView extends React.Component { protected createTreeDropTarget = (ele: HTMLDivElement) => { this._treedropDisposer && this._treedropDisposer(); - ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this))); + ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this)), this.props.document); } onPointerEnter = (e: React.PointerEvent): void => { @@ -663,7 +663,7 @@ export class CollectionTreeView extends CollectionSubView { this.treedropDisposer?.(); if (this._mainEle = ele) { - this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this)); + this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.props.Document); } } diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 7315d2c4e..d26e3a38b 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -215,9 +215,9 @@ export class CollectionViewBaseChrome extends React.Component { - this.dropDisposer && this.dropDisposer(); + this.dropDisposer?.(); if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.document); } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7ae77fc65..2aee49ad3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -191,7 +191,7 @@ export class DocumentView extends DocComponent(Docu @action componentDidMount() { - this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this))); + this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.props.Document)); this._mainCont.current && (this._gestureEventDisposer = GestureUtils.MakeGestureTarget(this._mainCont.current, this.onGesture.bind(this))); this._mainCont.current && (this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(this._mainCont.current, this.onTouchStart.bind(this))); // this._mainCont.current && (this.holdDisposer = InteractionUtils.MakeHoldTouchTarget(this._mainCont.current, this.handle1PointerHoldStart.bind(this))); @@ -208,7 +208,7 @@ export class DocumentView extends DocComponent(Docu this.multiTouchDisposer?.(); this.holdDisposer?.(); if (this._mainCont.current) { - this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this)); + this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, this.drop.bind(this), this.props.Document); this._gestureEventDisposer = GestureUtils.MakeGestureTarget(this._mainCont.current, this.onGesture.bind(this)); this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(this._mainCont.current, this.onTouchStart.bind(this)); this.holdDisposer = InteractionUtils.MakeHoldTouchTarget(this._mainCont.current, this.handle1PointerHoldStart.bind(this)); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index d7cfbae9f..815b8b3ae 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -253,7 +253,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp protected createDropTarget = (ele: HTMLDivElement) => { this.ProseRef = ele; this.dropDisposer?.(); - ele && (this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this))); + ele && (this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document)); } @undoBatch diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 14b367868..08917d281 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -76,7 +76,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { this._dropDisposer && this._dropDisposer(); - ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this))); + ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document)); } @undoBatch diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 5c2fc3ffe..a41e4fac4 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -32,7 +32,7 @@ export class LabelBox extends ViewBoxBaseComponent { this.dropDisposer?.(); if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document); } } diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index 61b185e5c..f24ad42b2 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -8,7 +8,8 @@ export const documentSchema = createSchema({ layout: "string", // this is the native layout string for the document. templates can be added using other fields and setting layoutKey below layoutKey: "string", // holds the field key for the field that actually holds the current lyoat title: "string", // document title (can be on either data document or layout) - dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy") + dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias", "copy", "move") + targetDropAction: "string", // allows the target of a drop event to specify the dropAction ("alias", "copy", "move") childDropAction: "string", // specify the override for what should happen when the child of a collection is dragged from it and dropped (can be "alias" or "copy") _autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents _nativeWidth: "number", // native width of document which determines how much document contents are scaled when the document's width is set -- cgit v1.2.3-70-g09d2