From a37559a417b8a19ee56ac3b2f5dd46ef70ca53a6 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 23 Apr 2020 20:52:09 -0400 Subject: fixed loading of notes with template types. changed noteTypes to ["template-notes"]. Added pass through free form layout engine. --- src/client/views/nodes/FormattedTextBox.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index fd7462a10..6ed2a1b9e 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -405,7 +405,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp !this.props.Document.rootDocument && funcs.push({ description: "Make Template", event: () => { this.props.Document.isTemplateDoc = makeTemplate(this.props.Document, true); - Doc.AddDocToList(Cast(Doc.UserDoc().noteTypes, Doc, null), "data", this.props.Document); + Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.props.Document); }, icon: "eye" }); funcs.push({ description: "Toggle Single Line", event: () => this.props.Document._singleLine = !this.props.Document._singleLine, icon: "expand-arrows-alt" }); @@ -433,9 +433,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const change = cm.findByDescription("Change Perspective..."); const changeItems: ContextMenuProps[] = change && "subitems" in change ? change.subitems : []; - const noteTypesDoc = Cast(Doc.UserDoc().noteTypes, Doc, null); - const noteTypes = DocListCast(noteTypesDoc?.data); - noteTypes.forEach(note => { + const noteTypesDoc = Cast(Doc.UserDoc()["template-notes"], Doc, null); + DocListCast(noteTypesDoc?.data).forEach(note => { changeItems.push({ description: StrCast(note.title), event: () => { Doc.setNativeView(this.props.Document); -- cgit v1.2.3-70-g09d2 From 08fbeaf2ebf4ee2466fa156e6e8c663d2bef7864 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 24 Apr 2020 00:06:48 -0400 Subject: moved iconify code into Doc from DocumentView. fixed up starburst a bit. --- .../apis/google_docs/GooglePhotosClientUtils.ts | 21 +++--- src/client/util/RichTextSchema.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 16 +--- src/client/views/TemplateMenu.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 15 ++-- .../CollectionFreeFormLayoutEngines.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 31 +++++--- .../collections/collectionFreeForm/MarqueeView.tsx | 24 ++++-- src/client/views/nodes/DocumentView.tsx | 85 ++++++---------------- src/client/views/nodes/FormattedTextBox.tsx | 25 +++---- src/client/views/pdf/PDFViewer.tsx | 43 ++++++----- src/new_fields/Doc.ts | 85 ++++++++++++++++++++-- src/new_fields/RichTextUtils.ts | 32 ++++---- 13 files changed, 208 insertions(+), 177 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index 7c4137f59..8c0149a89 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -1,19 +1,18 @@ -import { Utils } from "../../../Utils"; -import { ImageField } from "../../../new_fields/URLField"; -import { Cast, StrCast } from "../../../new_fields/Types"; -import { Doc, Opt, DocListCastAsync } from "../../../new_fields/Doc"; +import { AssertionError } from "assert"; +import { EditorState } from "prosemirror-state"; +import { Doc, DocListCastAsync, Opt } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; -import Photos = require('googlephotos'); import { RichTextField } from "../../../new_fields/RichTextField"; import { RichTextUtils } from "../../../new_fields/RichTextUtils"; -import { EditorState } from "prosemirror-state"; -import { FormattedTextBox } from "../../views/nodes/FormattedTextBox"; +import { Cast, StrCast } from "../../../new_fields/Types"; +import { ImageField } from "../../../new_fields/URLField"; +import { MediaItem, NewMediaItemResult } from "../../../server/apis/google/SharedTypes"; +import { Utils } from "../../../Utils"; import { Docs, DocumentOptions } from "../../documents/Documents"; -import { NewMediaItemResult, MediaItem } from "../../../server/apis/google/SharedTypes"; -import { AssertionError } from "assert"; -import { DocumentView } from "../../views/nodes/DocumentView"; import { Networking } from "../../Network"; +import { FormattedTextBox } from "../../views/nodes/FormattedTextBox"; import GoogleAuthenticationManager from "../GoogleAuthenticationManager"; +import Photos = require('googlephotos'); export namespace GooglePhotos { @@ -340,7 +339,7 @@ export namespace GooglePhotos { const url = data.url.href; const target = Doc.MakeAlias(source); const description = parseDescription(target, descriptionKey); - await DocumentView.makeCustomViewClicked(target, Docs.Create.FreeformDocument); + await Doc.makeCustomViewClicked(target, Docs.Create.FreeformDocument); media.push({ url, description }); } if (media.length) { diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index d23962d5c..b88a7b017 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -780,7 +780,7 @@ export class DashDocView { if (dashDocBase instanceof Doc) { const aliasedDoc = Doc.MakeAlias(dashDocBase, docid + alias); aliasedDoc.layoutKey = "layout"; - node.attrs.fieldKey && DocumentView.makeCustomViewClicked(aliasedDoc, Docs.Create.StackingDocument, node.attrs.fieldKey, undefined); + node.attrs.fieldKey && Doc.makeCustomViewClicked(aliasedDoc, Docs.Create.StackingDocument, node.attrs.fieldKey, undefined); self.doRender(aliasedDoc, removeDoc, node, view, getPos); } }); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index e4ceb75bd..312acd5b2 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -193,7 +193,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> const selectedDocs = SelectionManager.SelectedDocuments(); if (selectedDocs.length) { //CollectionDockingView.Instance?.OpenFullScreen(selectedDocs[0], selectedDocs[0].props.LibraryPath); - CollectionDockingView.AddRightSplit(selectedDocs[0].props.Document, selectedDocs[0].props.LibraryPath); + CollectionDockingView.AddRightSplit(Doc.MakeAlias(selectedDocs[0].props.Document), selectedDocs[0].props.LibraryPath); } } SelectionManager.DeselectAll(); @@ -202,19 +202,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @action onIconifyClick = (e: PointerEvent): void => { if (e.button === 0) { - const selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd); - selectedDocs.map(dv => { - const layoutKey = Cast(dv.props.Document.layoutKey, "string", null); - const collapse = layoutKey !== "layout_icon"; - if (collapse) { - dv.switchViews(collapse, "icon"); - if (layoutKey && layoutKey !== "layout") dv.props.Document.deiconifyLayout = layoutKey.replace("layout_", ""); - } else { - const deiconifyLayout = Cast(dv.props.Document.deiconifyLayout, "string", null); - dv.switchViews(deiconifyLayout ? true : false, deiconifyLayout); - dv.props.Document.deiconifyLayout = undefined; - } - }); + SelectionManager.SelectedDocuments().forEach(dv => dv?.iconify()); } SelectionManager.DeselectAll(); } diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index e3c749a4d..4c84a22ad 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -169,7 +169,7 @@ Scripting.addGlobal(function switchView(doc: Doc, template: Doc | undefined) { template = Cast(template.dragFactory, Doc, null); } const templateTitle = StrCast(template?.title); - return templateTitle && DocumentView.makeCustomViewClicked(doc, Docs.Create.FreeformDocument, templateTitle, template); + return templateTitle && Doc.makeCustomViewClicked(doc, Docs.Create.FreeformDocument, templateTitle, template); }); Scripting.addGlobal(function templateIsUsed(templateDoc: Doc, selDoc: Doc) { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a052d045c..ca2004b79 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -3,13 +3,14 @@ import { faAngleRight, faArrowsAltH, faBell, faCamera, faCaretDown, faCaretRight import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, runInAction, untracked } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, Field, HeightSym, WidthSym, DataSym, Opt } from '../../../new_fields/Doc'; +import { DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { List } from '../../../new_fields/List'; +import { RichTextField } from '../../../new_fields/RichTextField'; import { Document, listSpec } from '../../../new_fields/Schema'; import { ComputedField, ScriptField } from '../../../new_fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../new_fields/Types'; -import { emptyFunction, emptyPath, returnFalse, Utils, returnOne, returnZero, returnTransparent, returnTrue, simulateMouseClick } from '../../../Utils'; +import { emptyFunction, emptyPath, returnFalse, returnOne, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from "../../documents/DocumentTypes"; import { DocumentManager } from '../../util/DocumentManager'; @@ -24,16 +25,14 @@ import { ContextMenuProps } from '../ContextMenuItem'; import { EditableView } from "../EditableView"; import { MainView } from '../MainView'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; +import { DocumentView } from '../nodes/DocumentView'; import { ImageBox } from '../nodes/ImageBox'; import { KeyValueBox } from '../nodes/KeyValueBox'; -import { ScriptBox } from '../ScriptBox'; import { Templates } from '../Templates'; -import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView"; +import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; +import { CollectionViewType } from './CollectionView'; import React = require("react"); -import { CollectionViewType, CollectionView } from './CollectionView'; -import { RichTextField } from '../../../new_fields/RichTextField'; -import { DocumentView } from '../nodes/DocumentView'; export interface TreeViewProps { @@ -768,7 +767,7 @@ export class CollectionTreeView extends CollectionSubView UndoManager.RunInBatch(() => DocumentView.makeCustomViewClicked(this.props.Document, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit" + description: "Edit onChecked Script", event: () => UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit" }); !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index 1ec0542a3..57f62347a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -113,8 +113,8 @@ export function computerStarburstLayout( const deg = i / childDocs.length * Math.PI * 2; docMap.set(doc, { type: "doc", - x: Math.sin(deg) * burstDim[0] / 3 - NumCast(pivotDoc.starburstX), - y: Math.cos(deg) * burstDim[1] / 3 - NumCast(pivotDoc.starburstY), + x: Math.cos(deg) * (burstDim[0] / 3) - doc[WidthSym]() / 2, + y: Math.sin(deg) * (burstDim[1] / 3) - doc[HeightSym]() / 2, width: doc[WidthSym](), height: doc[HeightSym](), payload: undefined diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index e8738b292..63199ccbb 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -885,13 +885,20 @@ export class CollectionFreeFormView extends CollectionSubView { + addDocTab = action((doc: Doc, where: string) => { + if (where === "inParent") { + const pt = this.getTransform().transformPoint(NumCast(doc.x), NumCast(doc.y)); + doc.x = pt[0]; + doc.y = pt[1]; + this.props.addDocument(doc); + return true; + } if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { this.dataDoc[this.props.fieldKey] = new List([doc]); return true; } return this.props.addDocTab(doc, where); - } + }) getCalculatedPositions(params: { doc: Doc, index: number, collection: Doc, docs: Doc[], state: any }): PoolData { const result = this.Document.arrangeScript?.script.run(params, console.log); if (result?.success) { @@ -1031,15 +1038,15 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this.layoutDoc._layoutEngine === undefined) { - Doc.makeStarburst(this.layoutDoc); - } else { - this.layoutDoc._layoutEngine = undefined; - this.layoutDoc.overflow = "hidden"; - this.layoutDoc._fitToBox = undefined; - } - }); + promoteCollection = undoBatch(action(() => { + this.childDocs.forEach(doc => { + const scr = this.getTransform().inverse().transformPoint(NumCast(doc.x), NumCast(doc.y)); + doc.x = scr?.[0]; + doc.y = scr?.[1]; + this.props.addDocTab(doc, "inParent") && this.props.removeDocument(doc); + }) + this.props.ContainingCollectionView?.removeDocument(this.props.Document); + })); layoutDocsInGrid = () => { UndoManager.RunInBatch(() => { const docs = this.childLayoutPairs; @@ -1073,7 +1080,7 @@ export class CollectionFreeFormView extends CollectionSubView this.Document._LODdisable = !this.Document._LODdisable, icon: "table" }); optionItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" }); optionItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" }); - optionItems.push({ description: "Arrange Starburst", event: this.layoutStarburst, icon: "table" }); + this.props.ContainingCollectionView && optionItems.push({ description: "Promote Collection", event: this.promoteCollection, icon: "table" }); optionItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" }); // layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" }); optionItems.push({ description: "Jitter Rotation", event: action(() => this.props.Document.jitterRotation = (this.props.Document.jitterRotation ? 0 : 10)), icon: "paint-brush" }); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 2518ac629..d8e73a820 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -335,21 +335,33 @@ export class MarqueeView extends React.Component { - const bounds = this.Bounds; const selected = this.marqueeSelect(false); - selected.map(d => { + 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 = NumCast(d.x) - bounds.left - bounds.width / 2; - d.y = NumCast(d.y) - bounds.top - bounds.height / 2; + 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 - return 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"; this.props.addDocument(newCollection); this.props.selectDocuments([newCollection], []); MarqueeOptionsMenu.Instance.fadeOut(true); this.hideMarquee(); - Doc.makeStarburst(newCollection); + Doc.pileup(newCollection); } @action diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6c8e44e95..cc8773ed5 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -307,7 +307,7 @@ export class DocumentView extends DocComponent(Docu UndoManager.RunInBatch(func, "on click"); } else func(); } else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself - UndoManager.RunInBatch(() => DocumentView.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"); + UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"); //ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY), "on button click"); } else if (this.Document.isLinkButton) { DocListCast(this.props.Document.links).length && this.followLinkClick(e.altKey, e.ctrlKey, e.shiftKey); @@ -403,6 +403,19 @@ export class DocumentView extends DocComponent(Docu } } + public iconify() { + const layoutKey = Cast(this.props.Document.layoutKey, "string", null); + const collapse = layoutKey !== "layout_icon"; + if (collapse) { + this.switchViews(collapse, "icon"); + if (layoutKey && layoutKey !== "layout") this.props.Document.deiconifyLayout = layoutKey.replace("layout_", ""); + } else { + const deiconifyLayout = Cast(this.props.Document.deiconifyLayout, "string", null); + this.switchViews(deiconifyLayout ? true : false, deiconifyLayout); + this.props.Document.deiconifyLayout = undefined; + } + } + @action handle2PointersMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent) => { const myTouches = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true); @@ -547,56 +560,6 @@ export class DocumentView extends DocComponent(Docu @undoBatch deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument?.(this.props.Document); } - // applies a custom template to a document. the template is identified by it's short name (e.g, slideView not layout_slideView) - static makeCustomViewClicked = (doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) => { - const batch = UndoManager.StartBatch("makeCustomViewClicked"); - runInAction(() => { - doc.layoutKey = "layout_" + templateSignature; - if (doc[doc.layoutKey] === undefined) { - DocumentView.createCustomView(doc, creator, templateSignature, docLayoutTemplate); - } - }); - batch.end(); - } - static findTemplate(templateName: string, type: string, signature: string) { - let docLayoutTemplate: Opt; - const iconViews = DocListCast(Cast(Doc.UserDoc()["template-icons"], Doc, null)?.data); - const templBtns = DocListCast(Cast(Doc.UserDoc()["template-buttons"], Doc, null)?.data); - const noteTypes = DocListCast(Cast(Doc.UserDoc()["template-notes"], Doc, null)?.data); - const clickFuncs = DocListCast(Cast(Doc.UserDoc().clickFuncs, Doc, null)?.data); - const allTemplates = iconViews.concat(templBtns).concat(noteTypes).concat(clickFuncs).map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc).filter(doc => doc.isTemplateDoc); - // bcz: this is hacky -- want to have different templates be applied depending on the "type" of a document. but type is not reliable and there could be other types of template searches so this should be generalized - // first try to find a template that matches the specific document type (_). otherwise, fallback to a general match on - !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName + "_" + type && (docLayoutTemplate = tempDoc)); - !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName && (docLayoutTemplate = tempDoc)); - return docLayoutTemplate; - } - static createCustomView = (doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) => { - const templateName = templateSignature.replace(/\(.*\)/, ""); - docLayoutTemplate = docLayoutTemplate || DocumentView.findTemplate(templateName, StrCast(doc.type), templateSignature); - - const customName = "layout_" + templateSignature; - const _width = NumCast(doc._width); - const _height = NumCast(doc._height); - const options = { title: "data", backgroundColor: StrCast(doc.backgroundColor), _autoHeight: true, _width, x: -_width / 2, y: - _height / 2, _showSidebar: false }; - - let fieldTemplate: Opt; - if (doc.data instanceof RichTextField || typeof (doc.data) === "string") { - fieldTemplate = Docs.Create.TextDocument("", options); - } else if (doc.data instanceof PdfField) { - fieldTemplate = Docs.Create.PdfDocument("http://www.msn.com", options); - } else if (doc.data instanceof VideoField) { - fieldTemplate = Docs.Create.VideoDocument("http://www.cs.brown.edu", options); - } else if (doc.data instanceof AudioField) { - fieldTemplate = Docs.Create.AudioDocument("http://www.cs.brown.edu", options); - } else if (doc.data instanceof ImageField) { - fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options); - } - const docTemplate = docLayoutTemplate || creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) }); - - fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, docTemplate ? Doc.GetProto(docTemplate) : docTemplate); - docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined); - } @undoBatch toggleLinkButtonBehavior = (): void => { @@ -667,15 +630,6 @@ export class DocumentView extends DocComponent(Docu this.Document.isLinkButton = true; } - @undoBatch - @action - setCustomView = (custom: boolean, layout: string): void => { - Doc.setNativeView(this.props.Document); - if (custom) { - DocumentView.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined); - } - } - @undoBatch @action toggleBackground = (temporary: boolean): void => { @@ -747,7 +701,7 @@ export class DocumentView extends DocComponent(Docu onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: this.toggleFollowInPlace, icon: "concierge-bell" }); onClicks.push({ description: this.Document.isLinkButton || this.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.toggleLinkButtonBehavior, icon: "concierge-bell" }); - onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocumentView.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" }); + onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" }); !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); const funcs: ContextMenuProps[] = []; @@ -1114,7 +1068,14 @@ export class DocumentView extends DocComponent(Docu @computed get ignorePointerEvents() { return this.props.pointerEvents === false || (this.Document.isBackground && !this.isSelected() && !SelectionManager.GetIsDragging()) || (this.Document.type === DocumentType.INK && InkingControl.Instance.selectedTool !== InkTool.None); } - + @undoBatch + @action + setCustomView = (custom: boolean, layout: string): void => { + Doc.setNativeView(this.props.Document); + if (custom) { + Doc.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined); + } + } @observable _animate = 0; switchViews = action((custom: boolean, view: string) => { SelectionManager.SetIsDragging(true); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 6ed2a1b9e..f71343176 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -13,22 +13,24 @@ import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from " import { ReplaceStep } from 'prosemirror-transform'; import { EditorView } from "prosemirror-view"; import { DateField } from '../../../new_fields/DateField'; -import { DataSym, Doc, DocListCastAsync, Field, HeightSym, Opt, WidthSym, DocListCast } from "../../../new_fields/Doc"; +import { DataSym, Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; import { documentSchema } from '../../../new_fields/documentSchemas'; import { Id } from '../../../new_fields/FieldSymbols'; import { InkTool } from '../../../new_fields/InkField'; +import { PrefetchProxy } from '../../../new_fields/Proxy'; import { RichTextField } from "../../../new_fields/RichTextField"; import { RichTextUtils } from '../../../new_fields/RichTextUtils'; import { createSchema, makeInterface } from "../../../new_fields/Schema"; -import { Cast, NumCast, StrCast, BoolCast, DateCast } from "../../../new_fields/Types"; +import { Cast, DateCast, NumCast, StrCast } from "../../../new_fields/Types"; import { TraceMobx } from '../../../new_fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, Utils, returnTrue, returnZero } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, returnZero, Utils } from '../../../Utils'; import { GoogleApiClientUtils, Pulls, Pushes } from '../../apis/google_docs/GoogleApiClientUtils'; import { DocServer } from "../../DocServer"; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DictationManager } from '../../util/DictationManager'; import { DragManager } from "../../util/DragManager"; +import { makeTemplate } from '../../util/DropConverter'; import buildKeymap from "../../util/ProsemirrorExampleTransfer"; import RichTextMenu from '../../util/RichTextMenu'; import { RichTextRules } from "../../util/RichTextRules"; @@ -46,9 +48,6 @@ import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import { FormattedTextBoxComment, formattedTextBoxCommentPlugin } from './FormattedTextBoxComment'; import React = require("react"); -import { PrefetchProxy } from '../../../new_fields/Proxy'; -import { makeTemplate } from '../../util/DropConverter'; -import { DocumentView } from './DocumentView'; library.add(faEdit); library.add(faSmile, faTextHeight, faUpload); @@ -436,24 +435,24 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const noteTypesDoc = Cast(Doc.UserDoc()["template-notes"], Doc, null); DocListCast(noteTypesDoc?.data).forEach(note => { changeItems.push({ - description: StrCast(note.title), event: () => { + description: StrCast(note.title), event: undoBatch(() => { Doc.setNativeView(this.props.Document); - DocumentView.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note); - }, icon: "eye" + Doc.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note); + }), icon: "eye" }); }); - changeItems.push({ description: "FreeForm", event: () => DocumentView.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), icon: "eye" }); + changeItems.push({ description: "FreeForm", event: undoBatch(() => Doc.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), "change view"), icon: "eye" }); !change && cm.addItem({ description: "Change Perspective...", subitems: changeItems, icon: "external-link-alt" }); const open = cm.findByDescription("Open New Perspective..."); const openItems: ContextMenuProps[] = open && "subitems" in open ? open.subitems : []; openItems.push({ - description: "FreeForm", event: () => { + description: "FreeForm", event: undoBatch(() => { const alias = Doc.MakeAlias(this.rootDoc); - DocumentView.makeCustomViewClicked(alias, Docs.Create.FreeformDocument, "freeform"); + Doc.makeCustomViewClicked(alias, Docs.Create.FreeformDocument, "freeform"); this.props.addDocTab(alias, "onRight"); - }, icon: "eye" + }), icon: "eye" }); !open && cm.addItem({ description: "Open New Perspective...", subitems: openItems, icon: "external-link-alt" }); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 46b60b554..acaa4363e 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -1,37 +1,36 @@ -import { action, computed, IReactionDisposer, observable, reaction, trace, runInAction } from "mobx"; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; +import * as rp from "request-promise"; import { Dictionary } from "typescript-collections"; -import { Doc, DocListCast, FieldResult, WidthSym, Opt, HeightSym } from "../../../new_fields/Doc"; -import { Id, Copy } from "../../../new_fields/FieldSymbols"; +import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { InkTool } from "../../../new_fields/InkField"; import { List } from "../../../new_fields/List"; -import { makeInterface, createSchema } from "../../../new_fields/Schema"; -import { ScriptField, ComputedField } from "../../../new_fields/ScriptField"; -import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; -import { smoothScroll, Utils, emptyFunction, returnOne, intersectRect, addStyleSheet, addStyleSheetRule, clearStyleSheetRules, returnZero, emptyPath } from "../../../Utils"; +import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { ScriptField } from "../../../new_fields/ScriptField"; +import { Cast, NumCast } from "../../../new_fields/Types"; +import { PdfField } from "../../../new_fields/URLField"; +import { TraceMobx } from "../../../new_fields/util"; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, emptyPath, intersectRect, returnZero, smoothScroll, Utils } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; +import { DocumentType } from "../../documents/DocumentTypes"; import { DragManager } from "../../util/DragManager"; import { CompiledScript, CompileScript } from "../../util/Scripting"; -import { Transform } from "../../util/Transform"; -import PDFMenu from "./PDFMenu"; -import "./PDFViewer.scss"; -import React = require("react"); -import * as rp from "request-promise"; -import { CollectionView } from "../collections/CollectionView"; -import Annotation from "./Annotation"; -import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; import { SelectionManager } from "../../util/SelectionManager"; +import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; +import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; +import { CollectionView } from "../collections/CollectionView"; import { ViewBoxAnnotatableComponent } from "../DocComponent"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { documentSchema } from "../../../new_fields/documentSchemas"; import { DocumentDecorations } from "../DocumentDecorations"; import { InkingControl } from "../InkingControl"; -import { InkTool } from "../../../new_fields/InkField"; -import { TraceMobx } from "../../../new_fields/util"; -import { PdfField } from "../../../new_fields/URLField"; -import { DocumentView } from "../nodes/DocumentView"; +import Annotation from "./Annotation"; +import PDFMenu from "./PDFMenu"; +import "./PDFViewer.scss"; +import React = require("react"); const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer"); const pdfjsLib = require("pdfjs-dist"); @@ -574,7 +573,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent([clipDoc]); clipDoc.rootDocument = targetDoc; - DocumentView.makeCustomViewClicked(targetDoc, Docs.Create.StackingDocument, "slideView", undefined); + Doc.makeCustomViewClicked(targetDoc, Docs.Create.StackingDocument, "slideView", undefined); targetDoc.layoutKey = "layout"; // const targetDoc = Docs.Create.TextDocument("", { _width: 200, _height: 200, title: "Note linked to " + this.props.Document.title }); // Doc.GetProto(targetDoc).snipped = this.dataDoc[this.props.fieldKey][Copy](); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 1373431b8..cc929c040 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -17,7 +17,8 @@ import { listSpec } from "./Schema"; import { ComputedField, ScriptField } from "./ScriptField"; import { Cast, FieldValue, NumCast, StrCast, ToConstructor, ScriptCast } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util"; -import { Docs } from "../client/documents/Documents"; +import { Docs, DocumentOptions } from "../client/documents/Documents"; +import { PdfField, VideoField, AudioField, ImageField } from "./URLField"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -913,18 +914,86 @@ export namespace Doc { return false; } - export function makeStarburst(newCollection: Doc) { - newCollection._layoutEngine = "starburst"; - newCollection._fitToBox = true; + // applies a custom template to a document. the template is identified by it's short name (e.g, slideView not layout_slideView) + export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) { + const batch = UndoManager.StartBatch("makeCustomViewClicked"); + runInAction(() => { + doc.layoutKey = "layout_" + templateSignature; + if (doc[doc.layoutKey] === undefined) { + createCustomView(doc, creator, templateSignature, docLayoutTemplate); + } + }); + batch.end(); + } + export function findTemplate(templateName: string, type: string, signature: string) { + let docLayoutTemplate: Opt; + const iconViews = DocListCast(Cast(Doc.UserDoc()["template-icons"], Doc, null)?.data); + const templBtns = DocListCast(Cast(Doc.UserDoc()["template-buttons"], Doc, null)?.data); + const noteTypes = DocListCast(Cast(Doc.UserDoc()["template-notes"], Doc, null)?.data); + const clickFuncs = DocListCast(Cast(Doc.UserDoc().clickFuncs, Doc, null)?.data); + const allTemplates = iconViews.concat(templBtns).concat(noteTypes).concat(clickFuncs).map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc).filter(doc => doc.isTemplateDoc); + // bcz: this is hacky -- want to have different templates be applied depending on the "type" of a document. but type is not reliable and there could be other types of template searches so this should be generalized + // first try to find a template that matches the specific document type (_). otherwise, fallback to a general match on + !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName + "_" + type && (docLayoutTemplate = tempDoc)); + !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName && (docLayoutTemplate = tempDoc)); + return docLayoutTemplate; + } + export function createCustomView(doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) { + const templateName = templateSignature.replace(/\(.*\)/, ""); + docLayoutTemplate = docLayoutTemplate || findTemplate(templateName, StrCast(doc.type), templateSignature); + + const customName = "layout_" + templateSignature; + const _width = NumCast(doc._width); + const _height = NumCast(doc._height); + const options = { title: "data", backgroundColor: StrCast(doc.backgroundColor), _autoHeight: true, _width, x: -_width / 2, y: - _height / 2, _showSidebar: false }; + + let fieldTemplate: Opt; + if (doc.data instanceof RichTextField || typeof (doc.data) === "string") { + fieldTemplate = Docs.Create.TextDocument("", options); + } else if (doc.data instanceof PdfField) { + fieldTemplate = Docs.Create.PdfDocument("http://www.msn.com", options); + } else if (doc.data instanceof VideoField) { + fieldTemplate = Docs.Create.VideoDocument("http://www.cs.brown.edu", options); + } else if (doc.data instanceof AudioField) { + fieldTemplate = Docs.Create.AudioDocument("http://www.cs.brown.edu", options); + } else if (doc.data instanceof ImageField) { + fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options); + } + const docTemplate = docLayoutTemplate || creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) }); + + fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, docTemplate ? Doc.GetProto(docTemplate) : docTemplate); + docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined); + } + export function makeCustomView(doc: Doc, custom: boolean, layout: string) { + Doc.setNativeView(doc); + if (custom) { + makeCustomViewClicked(doc, Docs.Create.StackingDocument, layout, undefined); + } + } + export function iconify(doc: Doc) { + const layoutKey = Cast(doc.layoutKey, "string", null); + Doc.makeCustomViewClicked(doc, Docs.Create.StackingDocument, "icon", undefined); + if (layoutKey && layoutKey !== "layout") doc.deiconifyLayout = layoutKey.replace("layout_", ""); + } + + export function pileup(newCollection: Doc) { + newCollection._layoutEngine = "pass"; newCollection.overflow = "visible"; const script = "if (self._layoutEngine === 'starburst') {" + - " self._layoutEngine = 'pass';" + " self.overflow = undefined;" + - " self.fitToContentScaling=undefined;" + + " self.x = self.x + self._width/2 - 55; " + + " self.y = self.y + self._height/2 - 55; " + + " self._width = self._height = 110;" + + " self._layoutEngine = 'pass';" + " } else {" + - " self._layoutEngine = 'starburst';" + " self.overflow = 'visible';" + - " self.fitToContentScaling=10;" + + " !self.starburstRadius && (self.starburstRadius = 500);" + + " if (self._layoutEngine === 'pass') { " + + " self.x = self.x + self._width/2 - 12.5; " + + " self.y = self.y + self._height/2 - 12.5; " + + " }; " + + " self._width = self._height = 25;" + + " self._layoutEngine = 'starburst';" + " };"; newCollection.onClick = ScriptField.MakeScript(script, { self: Doc.name }); } diff --git a/src/new_fields/RichTextUtils.ts b/src/new_fields/RichTextUtils.ts index c211b3d3c..635fd053d 100644 --- a/src/new_fields/RichTextUtils.ts +++ b/src/new_fields/RichTextUtils.ts @@ -1,23 +1,21 @@ -import { EditorState, Transaction, TextSelection } from "prosemirror-state"; -import { Node, Fragment, Mark } from "prosemirror-model"; -import { RichTextField } from "./RichTextField"; +import { AssertionError } from "assert"; import { docs_v1 } from "googleapis"; -import { GoogleApiClientUtils } from "../client/apis/google_docs/GoogleApiClientUtils"; -import { FormattedTextBox } from "../client/views/nodes/FormattedTextBox"; -import { Opt, Doc } from "./Doc"; -import Color = require('color'); +import { Fragment, Mark, Node } from "prosemirror-model"; import { sinkListItem } from "prosemirror-schema-list"; -import { Utils } from "../Utils"; -import { Docs } from "../client/documents/Documents"; -import { schema } from "../client/util/RichTextSchema"; +import { EditorState, TextSelection, Transaction } from "prosemirror-state"; +import { GoogleApiClientUtils } from "../client/apis/google_docs/GoogleApiClientUtils"; import { GooglePhotos } from "../client/apis/google_docs/GooglePhotosClientUtils"; import { DocServer } from "../client/DocServer"; -import { Cast, StrCast } from "./Types"; -import { Id } from "./FieldSymbols"; -import { DocumentView } from "../client/views/nodes/DocumentView"; -import { AssertionError } from "assert"; +import { Docs } from "../client/documents/Documents"; import { Networking } from "../client/Network"; -import { extname } from "path"; +import { schema } from "../client/util/RichTextSchema"; +import { FormattedTextBox } from "../client/views/nodes/FormattedTextBox"; +import { Utils } from "../Utils"; +import { Doc, Opt } from "./Doc"; +import { Id } from "./FieldSymbols"; +import { RichTextField } from "./RichTextField"; +import { Cast, StrCast } from "./Types"; +import Color = require('color'); export namespace RichTextUtils { @@ -274,7 +272,7 @@ export namespace RichTextUtils { const backingDocId = StrCast(textNote[guid]); if (!backingDocId) { const backingDoc = Docs.Create.ImageDocument(agnostic, { _width: 300, _height: 300 }); - DocumentView.makeCustomViewClicked(backingDoc, Docs.Create.FreeformDocument); + Doc.makeCustomViewClicked(backingDoc, Docs.Create.FreeformDocument); docid = backingDoc[Id]; textNote[guid] = docid; } else { @@ -403,7 +401,7 @@ export namespace RichTextUtils { let exported = (await Cast(linkDoc.anchor2, Doc))!; if (!exported.customLayout) { exported = Doc.MakeAlias(exported); - DocumentView.makeCustomViewClicked(exported, Docs.Create.FreeformDocument); + Doc.makeCustomViewClicked(exported, Docs.Create.FreeformDocument); linkDoc.anchor2 = exported; } url = Utils.shareUrl(exported[Id]); -- cgit v1.2.3-70-g09d2 From 81229ca27c6e21d4b5f0ee3a5168c766dcfb954a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 24 Apr 2020 13:28:05 -0400 Subject: fixed presbox navigation bar layout height. --- src/client/views/collections/CollectionView.tsx | 4 ++-- src/client/views/nodes/DocumentView.tsx | 4 ++-- src/client/views/nodes/FormattedTextBox.tsx | 4 ++-- src/client/views/nodes/PresBox.scss | 5 +++++ 4 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 4f1242c33..47e79f088 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -201,7 +201,7 @@ export class CollectionView extends Touchable { ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => func(CollectionViewType.Invalid), icon: "project-diagram" }); } subItems.push({ description: "Schema", event: () => func(CollectionViewType.Schema), icon: "th-list" }); - subItems.push({ description: "Treeview", event: () => func(CollectionViewType.Tree), icon: "tree" }); + subItems.push({ description: "Tree", event: () => func(CollectionViewType.Tree), icon: "tree" }); subItems.push({ description: "Stacking", event: () => func(CollectionViewType.Stacking), icon: "ellipsis-v" }); subItems.push({ description: "Stacking (AutoHeight)", event: () => func(CollectionViewType.Stacking)._autoHeight = true, icon: "ellipsis-v" }); subItems.push({ description: "Staff", event: () => func(CollectionViewType.Staff), icon: "music" }); @@ -222,7 +222,7 @@ export class CollectionView extends Touchable { if (!e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 this.setupViewTypes("Change Perspective...", (vtype => { this.props.Document._viewType = vtype; return this.props.Document; }), true); - this.setupViewTypes("Open New Perspective...", vtype => { + this.setupViewTypes("New Perspective...", vtype => { const newRendition = Doc.MakeAlias(this.props.Document); newRendition._viewType = vtype; this.props.addDocTab(newRendition, "onRight"); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index cc8773ed5..4bbdde3ea 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -687,11 +687,11 @@ export class DocumentView extends DocComponent(Docu layoutItems.push({ description: this.Document.lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" }); !existing && cm.addItem({ description: "Options...", subitems: layoutItems, icon: "compass" }); - const open = cm.findByDescription("Open New Perspective..."); + const open = cm.findByDescription("New Perspective..."); const openItems: ContextMenuProps[] = open && "subitems" in open ? open.subitems : []; openItems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); templateDoc && openItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" }); - !open && cm.addItem({ description: "Open New Perspective...", subitems: openItems, icon: "external-link-alt" }); + !open && cm.addItem({ description: "New Perspective...", subitems: openItems, icon: "external-link-alt" }); const existingOnClick = cm.findByDescription("OnClick..."); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f71343176..a018f17e8 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -444,7 +444,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp changeItems.push({ description: "FreeForm", event: undoBatch(() => Doc.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), "change view"), icon: "eye" }); !change && cm.addItem({ description: "Change Perspective...", subitems: changeItems, icon: "external-link-alt" }); - const open = cm.findByDescription("Open New Perspective..."); + const open = cm.findByDescription("New Perspective..."); const openItems: ContextMenuProps[] = open && "subitems" in open ? open.subitems : []; openItems.push({ @@ -454,7 +454,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.props.addDocTab(alias, "onRight"); }), icon: "eye" }); - !open && cm.addItem({ description: "Open New Perspective...", subitems: openItems, icon: "external-link-alt" }); + !open && cm.addItem({ description: "New Perspective...", subitems: openItems, icon: "external-link-alt" }); } diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 6676d8cd2..78c19f351 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -11,6 +11,11 @@ overflow: hidden; transition: 0.7s opacity ease; + .presBox-listCont { + position: absolute; + height: calc(100% - 25px); + width: 100%; + } .presBox-buttons { padding: 10px; width: 100%; -- cgit v1.2.3-70-g09d2 From 308ae1521cbd58126d35239cfdd5a138f6fa1fe0 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 25 Apr 2020 15:40:07 -0400 Subject: got rid of focus mechanism on click. fixed shift-click to multiselect. fixed pile view interactions. added FollowLink on click menu items. --- src/client/util/DragManager.ts | 9 +++- src/client/util/ProsemirrorExampleTransfer.ts | 18 +++++-- src/client/views/ContextMenu.tsx | 9 ++++ src/client/views/TemplateMenu.tsx | 5 +- .../views/collections/CollectionPileView.tsx | 38 +++++++++++-- src/client/views/collections/CollectionView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 20 +++---- src/client/views/nodes/DocumentView.tsx | 63 +++++++++++++++------- src/client/views/nodes/FormattedTextBox.tsx | 4 +- src/client/views/nodes/FormattedTextBoxComment.tsx | 1 - src/client/views/nodes/LinkAnchorBox.tsx | 1 - src/client/views/pdf/Annotation.tsx | 1 - 12 files changed, 124 insertions(+), 47 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 42a78a4bf..6bb44f7d6 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -83,6 +83,7 @@ export namespace DragManager { } export let AbortDrag: () => void = emptyFunction; export type MoveFunction = (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; + export type RemoveFunction = (document: Doc) => boolean; export interface DragDropDisposer { (): void; } export interface DragOptions { @@ -138,6 +139,7 @@ export namespace DragManager { userDropAction: dropActionType; embedDoc?: boolean; moveDocument?: MoveFunction; + removeDocument?: RemoveFunction; isSelectionMove?: boolean; // indicates that an explicitly selected Document is being dragged. this will suppress onDragStart scripts } export class LinkDragData { @@ -351,12 +353,17 @@ export namespace DragManager { let lastX = downX; let lastY = downY; + let alias = "alias"; const moveHandler = (e: PointerEvent) => { e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey && e.altKey ? "copy" : e.ctrlKey ? "alias" : undefined; } if (e.shiftKey && CollectionDockingView.Instance && dragData.droppedDocuments.length === 1) { + !dragData.dropAction && (dragData.dropAction = alias); + if (dragData.dropAction === "move") { + dragData.removeDocument?.(dragData.draggedDocuments[0]); + } AbortDrag(); finishDrag?.(new DragCompleteEvent(true, dragData)); CollectionDockingView.Instance.StartOtherDrag({ @@ -366,7 +373,7 @@ export namespace DragManager { button: 0 }, dragData.droppedDocuments); } - //TODO: Why can't we use e.movementX and e.movementY? + alias = "move"; const moveX = e.pageX - lastX; const moveY = e.pageY - lastY; lastX = e.pageX; diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts index 680f48f70..356f20ce6 100644 --- a/src/client/util/ProsemirrorExampleTransfer.ts +++ b/src/client/util/ProsemirrorExampleTransfer.ts @@ -7,7 +7,7 @@ import { splitListItem, wrapInList, } from "prosemirror-schema-list"; import { EditorState, Transaction, TextSelection } from "prosemirror-state"; import { SelectionManager } from "./SelectionManager"; import { Docs } from "../documents/Documents"; -import { NumCast, BoolCast, Cast } from "../../new_fields/Types"; +import { NumCast, BoolCast, Cast, StrCast } from "../../new_fields/Types"; import { Doc } from "../../new_fields/Doc"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; import { Id } from "../../new_fields/FieldSymbols"; @@ -153,10 +153,16 @@ export default function buildKeymap>(schema: S, props: any const layoutDoc = props.Document; const originalDoc = layoutDoc.rootDocument || layoutDoc; if (originalDoc instanceof Doc) { + const layoutKey = StrCast(originalDoc.layoutKey); const newDoc = Docs.Create.TextDocument("", { - layout: Cast(originalDoc.layout, Doc, null) || FormattedTextBox.DefaultLayout, _singleLine: BoolCast(originalDoc._singleLine), + layout: Cast(originalDoc.layout, Doc, null) || FormattedTextBox.DefaultLayout, + layoutKey, + _singleLine: BoolCast(originalDoc._singleLine), x: NumCast(originalDoc.x), y: NumCast(originalDoc.y) + NumCast(originalDoc._height) + 10, _width: NumCast(layoutDoc._width), _height: NumCast(layoutDoc._height) }); + if (layoutKey !== "layout" && originalDoc[layoutKey] instanceof Doc) { + newDoc[layoutKey] = originalDoc[layoutKey]; + } FormattedTextBox.SelectOnLoad = newDoc[Id]; props.addDocument(newDoc); } @@ -171,10 +177,16 @@ export default function buildKeymap>(schema: S, props: any const layoutDoc = props.Document; const originalDoc = layoutDoc.rootDocument || layoutDoc; if (force || props.Document._singleLine) { + const layoutKey = StrCast(originalDoc.layoutKey); const newDoc = Docs.Create.TextDocument("", { - layout: Cast(originalDoc.layout, Doc, null) || FormattedTextBox.DefaultLayout, _singleLine: BoolCast(originalDoc._singleLine), + layout: Cast(originalDoc.layout, Doc, null) || FormattedTextBox.DefaultLayout, + layoutKey, + _singleLine: BoolCast(originalDoc._singleLine), x: NumCast(originalDoc.x) + NumCast(originalDoc._width) + 10, y: NumCast(originalDoc.y), _width: NumCast(layoutDoc._width), _height: NumCast(layoutDoc._height) }); + if (layoutKey !== "layout" && originalDoc[layoutKey] instanceof Doc) { + newDoc[layoutKey] = originalDoc[layoutKey]; + } FormattedTextBox.SelectOnLoad = newDoc[Id]; props.addDocument(newDoc); return true; diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 4d04d4e89..5b66b63ed 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -99,6 +99,15 @@ export class ContextMenu extends React.Component { } } @action + moveAfter(item: ContextMenuProps, after: ContextMenuProps) { + if (this.findByDescription(after.description)) { + const curInd = this._items.findIndex((i) => i.description === item.description); + this._items.splice(curInd, 1); + const afterInd = this._items.findIndex((i) => i.description === after.description); + this._items.splice(afterInd + 1, 0, item); + } + } + @action setDefaultItem(prefix: string, item: (name: string) => void) { this._defaultPrefix = prefix; this._defaultItem = item; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 4c84a22ad..665ab4e41 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -14,6 +14,7 @@ import { returnTrue, emptyFunction, returnFalse, returnOne, emptyPath, returnZer import { Transform } from "../util/Transform"; import { ScriptField, ComputedField } from "../../new_fields/ScriptField"; import { Scripting } from "../util/Scripting"; +import { List } from "../../new_fields/List"; @observer class TemplateToggle extends React.Component<{ template: Template, checked: boolean, toggle: (event: React.ChangeEvent, template: Template) => void }> { @@ -106,8 +107,8 @@ export class TemplateMenu extends React.Component { return100 = () => 100; @computed get scriptField() { - return ScriptField.MakeScript("switchView(firstDoc, this)", { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name, firstDoc: Doc.name }, - { firstDoc: this.props.docViews[0].props.Document }); + return ScriptField.MakeScript("docs.map(d => switchView(d, this))", { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name, firstDoc: Doc.name }, + { docs: new List(this.props.docViews.map(dv => dv.props.Document)) }); } render() { const firstDoc = this.props.docViews[0].props.Document; diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx index 511efe0a7..410b16ec7 100644 --- a/src/client/views/collections/CollectionPileView.tsx +++ b/src/client/views/collections/CollectionPileView.tsx @@ -11,6 +11,7 @@ import "./CollectionPileView.scss"; import React = require("react"); import { setupMoveUpEvents, emptyFunction, returnFalse } from "../../../Utils"; import { SelectionManager } from "../../util/SelectionManager"; +import { UndoManager } from "../../util/UndoManager"; @observer export class CollectionPileView extends CollectionSubView(doc => doc) { @@ -34,7 +35,10 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { layoutEngine = () => this._layoutEngine; @computed get contents() { - return
+ return
; } @@ -71,9 +75,32 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { } }); + _undoBatch: UndoManager.Batch | undefined; pointerDown = (e: React.PointerEvent) => { + let dist = 0; // 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 + setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => { + if (this.layoutEngine() === "pass" && this.childDocs.length && this.props.isSelected(true)) { + dist += Math.sqrt(delta[0] * delta[0] + delta[1] * delta[1]); + if (dist > 100) { + if (!this._undoBatch) { + this._undoBatch = UndoManager.StartBatch("layout pile"); + } + const doc = this.childDocs[0]; + doc.x = e.clientX; + doc.y = e.clientY; + this.props.addDocTab(doc, "inParent") && this.props.removeDocument(doc); + dist = 0; + } + } + return false; + }, () => { + this._undoBatch?.end(); + this._undoBatch = undefined; + if (!this.childDocs.length) { + this.props.ContainingCollectionView?.removeDocument(this.props.Document); + } + }, emptyFunction, false, this.layoutEngine() === "pass" && this.props.isSelected(true)); // this sets _doubleTap } onClick = (e: React.MouseEvent) => { @@ -81,10 +108,11 @@ export class CollectionPileView extends CollectionSubView(doc => doc) { SelectionManager.DeselectAll(); this.toggleStarburst(); e.stopPropagation(); - } else if (this.layoutEngine() === "pass") { - runInAction(() => this._contentsActive = false); - setTimeout(action(() => this._contentsActive = true), 300); } + // else if (this.layoutEngine() === "pass") { + // runInAction(() => this._contentsActive = false); + // setTimeout(action(() => this._contentsActive = true), 300); + // } } render() { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index f82c6d8a6..2bd37bda5 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -225,7 +225,7 @@ export class CollectionView extends Touchable { if (!e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 this.setupViewTypes("Change Perspective...", (vtype => { this.props.Document._viewType = vtype; return this.props.Document; }), true); - this.setupViewTypes("New Perspective...", vtype => { + this.setupViewTypes("Add a Perspective...", vtype => { const newRendition = Doc.MakeAlias(this.props.Document); newRendition._viewType = vtype; this.props.addDocTab(newRendition, "onRight"); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index af9d3c5be..6a3764bb7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -821,18 +821,18 @@ export class CollectionFreeFormView extends CollectionSubView { if (afterFocus?.()) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 06bd40992..f9d9ca9a1 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -234,6 +234,7 @@ export class DocumentView extends DocComponent(Docu const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0); dragData.offset = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); dragData.dropAction = dropAction; + dragData.removeDocument = this.props.removeDocument; dragData.moveDocument = this.props.moveDocument;// this.Document.onDragStart ? undefined : this.props.moveDocument; dragData.dragDivName = this.props.dragDivName; DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.Document.onDragStart }); @@ -309,19 +310,19 @@ export class DocumentView extends DocComponent(Docu } else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"); //ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY), "on button click"); - } else if (this.Document.isLinkButton) { + } else if (this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) { DocListCast(this.props.Document.links).length && this.followLinkClick(e.altKey, e.ctrlKey, e.shiftKey); } else { if ((this.props.Document.onDragStart || (this.props.Document.rootDocument)) && !(e.ctrlKey || e.button > 0)) { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTEmplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part stopPropagate = false; // don't stop propagation for field templates -- want the selection to propagate up to the root document of the template } else { - if (this.props.Document.type === DocumentType.RTF) { - DocumentView._focusHack = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY) || [0, 0]; - DocumentView._focusHack = [DocumentView._focusHack[0] + NumCast(this.props.Document.x), DocumentView._focusHack[1] + NumCast(this.props.Document.y)]; + // if (this.props.Document.type === DocumentType.RTF) { + // DocumentView._focusHack = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY) || [0, 0]; + // DocumentView._focusHack = [DocumentView._focusHack[0] + NumCast(this.props.Document.x), DocumentView._focusHack[1] + NumCast(this.props.Document.y)]; - this.props.focus(this.props.Document, false); - } - SelectionManager.SelectDoc(this, e.ctrlKey); + // this.props.focus(this.props.Document, false); + // } + SelectionManager.SelectDoc(this, e.ctrlKey || e.shiftKey); } preventDefault = false; } @@ -329,7 +330,6 @@ export class DocumentView extends DocComponent(Docu preventDefault && e.preventDefault(); } } - static _focusHack: number[] = []; // bcz :this will get fixed... // follows a link - if the target is on screen, it highlights/pans to it. // if the target isn't onscreen, then it will open up the target in a tab, on the right, or in place @@ -344,11 +344,11 @@ export class DocumentView extends DocComponent(Docu finished && setTimeout(finished, 0); // finished() needs to be called right after hackToCallFinishAfterFocus(), but there's no callback for that so we use the hacky timeout. return false; // we must return false here so that the zoom to the document is not reversed. If it weren't for needing to call finished(), we wouldn't need this function at all since not having it is equivalent to returning false }; - this.props.addDocTab(doc, where) && this.props.focus(doc, true, undefined, hackToCallFinishAfterFocus); // add the target and focus on it. + this.props.addDocTab(doc, where) && this.props.focus(doc, BoolCast(this.Document.followLinkZoom, true), undefined, hackToCallFinishAfterFocus); // add the target and focus on it. return where !== "inPlace"; // return true to reset the initial focus&zoom (return false for 'inPlace' since resetting the initial focus&zoom will negate the zoom into the target) }; // first focus & zoom onto this (the clicked document). Then execute the function to focus on the target - this.props.focus(this.props.Document, true, 1, targetFocusAfterDocFocus); + this.props.focus(this.props.Document, BoolCast(this.Document.followLinkZoom, true), 1, targetFocusAfterDocFocus); }; await DocumentManager.Instance.FollowLink(undefined, this.props.Document, createViewFunc, shiftKey, this.props.ContainingCollectionDoc, batch.end, altKey ? true : undefined); } @@ -569,6 +569,7 @@ export class DocumentView extends DocComponent(Docu this.Document.onClick = undefined; } else { this.Document.isLinkButton = true; + this.Document.followLinkZoom = false; this.Document.followLinkLocation = undefined; } } @@ -579,10 +580,24 @@ export class DocumentView extends DocComponent(Docu this.Document.isLinkButton = false; } else { this.Document.isLinkButton = true; + this.Document.followLinkZoom = true; this.Document.followLinkLocation = "inPlace"; } } + @undoBatch + toggleFollowOnRight = (): void => { + if (this.Document.isLinkButton) { + this.Document.isLinkButton = false; + } else { + this.Document.isLinkButton = true; + this.Document.followLinkZoom = false; + const first = DocListCast(this.Document.links).find(d => d instanceof Doc); + first && (first.hidden = true); + this.Document.followLinkLocation = "onRight"; + } + } + @undoBatch @action drop = async (e: Event, de: DragManager.DropEvent) => { @@ -679,20 +694,27 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" })); - const existing = cm.findByDescription("Options..."); - const layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : []; - layoutItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" }); - layoutItems.push({ description: `${this.Document._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" }); - layoutItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" }); - layoutItems.push({ description: this.Document.lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" }); - !existing && cm.addItem({ description: "Options...", subitems: layoutItems, icon: "compass" }); - - const open = cm.findByDescription("New Perspective..."); + let open = cm.findByDescription("Add a Perspective..."); const openItems: ContextMenuProps[] = open && "subitems" in open ? open.subitems : []; openItems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); templateDoc && openItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" }); - !open && cm.addItem({ description: "New Perspective...", subitems: openItems, icon: "external-link-alt" }); + if (!open) { + open = { description: "Add a Perspective....", subitems: openItems, icon: "external-link-alt" }; + cm.addItem(open); + } + + let options = cm.findByDescription("Options..."); + const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; + optionItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" }); + optionItems.push({ description: `${this.Document._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" }); + optionItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" }); + optionItems.push({ description: this.Document.lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" }); + if (!options) { + options = { description: "Options...", subitems: optionItems, icon: "compass" }; + cm.addItem(options); + } + cm.moveAfter(options, open); const existingOnClick = cm.findByDescription("OnClick..."); const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; @@ -700,6 +722,7 @@ export class DocumentView extends DocComponent(Docu onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.props.Document.layoutKey}")`), icon: "window-restore" }); onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: this.toggleFollowInPlace, icon: "concierge-bell" }); + onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link on Right", event: this.toggleFollowOnRight, icon: "concierge-bell" }); onClicks.push({ description: this.Document.isLinkButton || this.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.toggleLinkButtonBehavior, icon: "concierge-bell" }); onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" }); !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index a018f17e8..d7cfbae9f 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -444,7 +444,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp changeItems.push({ description: "FreeForm", event: undoBatch(() => Doc.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), "change view"), icon: "eye" }); !change && cm.addItem({ description: "Change Perspective...", subitems: changeItems, icon: "external-link-alt" }); - const open = cm.findByDescription("New Perspective..."); + const open = cm.findByDescription("Add a Perspective..."); const openItems: ContextMenuProps[] = open && "subitems" in open ? open.subitems : []; openItems.push({ @@ -454,7 +454,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.props.addDocTab(alias, "onRight"); }), icon: "eye" }); - !open && cm.addItem({ description: "New Perspective...", subitems: openItems, icon: "external-link-alt" }); + !open && cm.addItem({ description: "Add a Perspective...", subitems: openItems, icon: "external-link-alt" }); } diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index 41df5b3c1..a9f76ae8f 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -88,7 +88,6 @@ export class FormattedTextBoxComment { if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) { textBox.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "inTab" : "onRight"); } else { - DocumentView._focusHack = []; DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, (doc: Doc, followLinkLocation: string) => textBox.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation)); } diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index eb647d0e4..707b9d12a 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -75,7 +75,6 @@ export class LinkAnchorBox extends ViewBoxBaseComponent { - DocumentView._focusHack = []; DocumentManager.Instance.FollowLink(this.rootDoc, anchorContainerDoc, document => this.props.addDocTab(document, StrCast(this.layoutDoc.linkOpenLocation, "inTab")), false); this._editing = false; }), 300 - (Date.now() - this._lastTap)); diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index eaf80d252..672d3adb8 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -98,7 +98,6 @@ class RegionAnnotation extends React.Component { else if (e.button === 0) { const annoGroup = await Cast(this.props.document.group, Doc); if (annoGroup) { - DocumentView._focusHack = []; DocumentManager.Instance.FollowLink(undefined, annoGroup, (doc, followLinkLocation) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation), false, undefined); e.stopPropagation(); } -- 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/nodes/FormattedTextBox.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 From e6549d43be83b50d364c4a3ab1e8e7381ce2fd59 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 26 Apr 2020 01:56:41 -0400 Subject: fixed title layout for text. fixed documentBox for nested collections. fixed tree view for text boxes. changed labelbox formatting. --- src/client/util/DragManager.ts | 8 ++++---- src/client/views/collections/CollectionTreeView.tsx | 13 +++++++++---- .../collectionFreeForm/CollectionFreeFormView.tsx | 3 ++- src/client/views/nodes/ColorBox.scss | 1 + src/client/views/nodes/DocumentBox.tsx | 4 ++-- src/client/views/nodes/DocumentView.tsx | 7 ++----- src/client/views/nodes/FormattedTextBox.scss | 1 - src/client/views/nodes/FormattedTextBox.tsx | 4 ++-- src/client/views/nodes/LabelBox.scss | 2 -- src/client/views/nodes/LabelBox.tsx | 8 +++++++- src/server/authentication/models/current_user_utils.ts | 4 ++-- 11 files changed, 31 insertions(+), 24 deletions(-) (limited to 'src/client/views/nodes/FormattedTextBox.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 577366cd4..35694a6bd 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -180,7 +180,7 @@ export namespace DragManager { export function MakeDropTarget( element: HTMLElement, dropFunc: (e: Event, de: DropEvent) => void, - doc?:Doc + doc?: Doc ): DragDropDisposer { if ("canDrop" in element.dataset) { throw new Error( @@ -189,12 +189,12 @@ export namespace DragManager { } element.dataset.canDrop = "true"; const handler = (e: Event) => dropFunc(e, (e as CustomEvent).detail); - const preDropHandler = (e:Event) => { + 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; + de.complete.docDragData.dropAction = StrCast(doc.targetDropAction) as dropActionType; } - } + }; element.addEventListener("dashOnDrop", handler); doc && element.addEventListener("dashPreDrop", preDropHandler); return () => { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 8c5a4538e..ddd7474bd 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -261,7 +261,7 @@ class TreeView extends React.Component { docHeight = () => { const layoutDoc = Doc.Layout(this.props.document); const bounds = this.boundsOfCollectionDocument; - return Math.min(this.MAX_EMBED_HEIGHT, (() => { + return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => { const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); if (aspect) return this.docWidth() * aspect; if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x); @@ -269,7 +269,7 @@ class TreeView extends React.Component { Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth, NumCast(this.props.containingCollection._height)))) : NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50; - })()); + })())); } @computed get expandedField() { @@ -321,6 +321,9 @@ class TreeView extends React.Component { return rows; } + rtfWidth = () => Math.min(Doc.Layout(this.props.document)?.[WidthSym](), this.props.panelWidth() - 20); + rtfHeight = () => this.rtfWidth() < Doc.Layout(this.props.document)?.[WidthSym]() ? Math.min(Doc.Layout(this.props.document)?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; + @computed get renderContent() { const expandKey = this.treeViewExpandedView === this.fieldKey ? this.fieldKey : this.treeViewExpandedView === "links" ? "links" : undefined; if (expandKey !== undefined) { @@ -355,8 +358,10 @@ class TreeView extends React.Component { backgroundColor={this.props.backgroundColor} fitToBox={this.boundsOfCollectionDocument !== undefined} FreezeDimensions={true} - PanelWidth={this.docWidth} - PanelHeight={this.docHeight} + NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined} + NativeHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : undefined} + PanelWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : this.docWidth} + PanelHeight={layoutDoc.type === DocumentType.RTF ? this.rtfHeight : this.docHeight} getTransform={this.docTransform} CollectionDoc={this.props.containingCollection} CollectionView={undefined} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 852442fd4..28b461313 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1026,7 +1026,8 @@ export class CollectionFreeFormView extends CollectionSubView, bounds: this.childDataProvider(entry[1].pair.layout, entry[1].replica) diff --git a/src/client/views/nodes/ColorBox.scss b/src/client/views/nodes/ColorBox.scss index bf334c939..da3266dc1 100644 --- a/src/client/views/nodes/ColorBox.scss +++ b/src/client/views/nodes/ColorBox.scss @@ -3,6 +3,7 @@ height:100%; position: relative; pointer-events: none; + transform-origin: top left; .sketch-picker { margin:auto; diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx index 0111cadd5..0d18baaed 100644 --- a/src/client/views/nodes/DocumentBox.tsx +++ b/src/client/views/nodes/DocumentBox.tsx @@ -120,8 +120,8 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent(Docu layoutKey={this.finalLayoutKey} />
); const titleView = (!showTitle ? (null) : -
@@ -1086,10 +1086,7 @@ export class DocumentView extends DocComponent(Docu return !showTitle && !showCaption ? this.contents :
-
- {this.contents} -
- {titleView} + {this.Document.type !== DocumentType.RTF ? <> {this.contents} {titleView} : <> {titleView} {this.contents} } {captionView}
; } diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 7a05ec3a3..3bedb7127 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -24,7 +24,6 @@ overflow-y: auto; overflow-x: hidden; color: initial; - height: 100%; max-height: 100%; display: flex; flex-direction: row; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 815b8b3ae..425af8ccf 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -194,7 +194,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const tsel = this._editorView.state.selection.$from; tsel.marks().filter(m => m.type === this._editorView!.state.schema.marks.user_mark).map(m => AudioBox.SetScrubTime(Math.max(0, m.attrs.modified * 1000))); - const curText = state.doc.textBetween(0, state.doc.content.size, "\n\n"); + const curText = state.doc.textBetween(0, state.doc.content.size, " \n"); const curTemp = Cast(this.props.Document[this.props.fieldKey + "-textTemplate"], RichTextField); if (!this._applyingChange) { this._applyingChange = true; @@ -1211,7 +1211,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp return (
{StrCast(this.rootDoc.text, StrCast(this.rootDoc.title))} diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index afde524b6..25775edef 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -167,7 +167,7 @@ export class CurrentUserUtils { doc["template-icon-view"] = new PrefetchProxy(iconView); } if (doc["template-icon-view-rtf"] === undefined) { - const iconRtfView = Docs.Create.LabelDocument({ title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset", _width: 150, _height: 30, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") }); + const iconRtfView = Docs.Create.LabelDocument({ title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") }); iconRtfView.isTemplateDoc = makeTemplate(iconRtfView, true, "icon_" + DocumentType.RTF); doc["template-icon-view-rtf"] = new PrefetchProxy(iconRtfView); } @@ -214,7 +214,7 @@ export class CurrentUserUtils { { title: "Drag a screenshot", label: "Grab", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' }, { title: "Drag a webcam", label: "Cam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' }, { title: "Drag a audio recorder", label: "Audio", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` }, - { title: "Drag a clickable button", label: "Btn", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, title: "Button" })' }, + { title: "Drag a clickable button", label: "Btn", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding:10, _yPadding: 10, title: "Button" })' }, { title: "Drag a presentation view", label: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory,true)`, dragFactory: doc.emptyPresentation as Doc }, { title: "Drag a search box", label: "Query", icon: "search", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' }, { title: "Drag a scripting box", label: "Script", icon: "terminal", ignoreClick: true, drag: 'Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250 title: "untitled script" })' }, -- cgit v1.2.3-70-g09d2