diff options
author | Sam Wilkins <samwilkins333@gmail.com> | 2020-01-31 11:05:03 -0500 |
---|---|---|
committer | Sam Wilkins <samwilkins333@gmail.com> | 2020-01-31 11:05:03 -0500 |
commit | 5ad15ac012262ac15e152b995cbcb042c5b7cf89 (patch) | |
tree | fcd3404add281aff240aeb4c9546d0ba16b7d8ec | |
parent | 96de4bf18d5721d2b7957d7adb8ad3393462c4d1 (diff) | |
parent | b0544ea44ef78a93deb9290815f95d6d9308447d (diff) |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web
26 files changed, 189 insertions, 103 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index fa5707288..49c03a96f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -75,7 +75,7 @@ export interface DocumentOptions { _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts _textTemplate?: RichTextField; // template used by a formattedTextBox to create a text box to render _itemIndex?: number; // which item index the carousel viewer is showing - _hideSidebar?: boolean; //whether an annotationsidebar should be displayed for text docuemnts + _showSidebar?: boolean; //whether an annotationsidebar should be displayed for text docuemnts x?: number; y?: number; z?: number; @@ -340,7 +340,7 @@ export namespace Docs { export namespace Create { const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "_dropAction", "_annotationOn", - "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_hideSidebar"]; + "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar"]; /** * This function receives the relevant document prototype and uses diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index fb4c2155a..f024b9116 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -140,7 +140,7 @@ export class DocumentManager { if (first) annotatedDoc = first.props.Document; } if (docView) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? - docView.props.focus(docView.props.Document, false); + docView.props.focus(docView.props.Document, willZoom); highlight(); } else { const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 669ac5336..d0f1d86cb 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -35,10 +35,11 @@ export function convertDropDataToButtons(data: DragManager.DocumentDragData) { if (!doc.onDragStart && !doc.onClick && !doc.isButtonBar) { const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; if (layoutDoc.type === DocumentType.COL || layoutDoc.type === DocumentType.TEXT || layoutDoc.type === DocumentType.IMG) { - layoutDoc.isTemplateDoc = makeTemplate(layoutDoc); + makeTemplate(layoutDoc); } else { - layoutDoc.isTemplateDoc = (layoutDoc.layout instanceof Doc) && !data.userDropAction; + (layoutDoc.layout instanceof Doc) && !data.userDropAction; } + layoutDoc.isTemplateDoc = true; dbox = Docs.Create.FontIconDocument({ _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: layoutDoc.isTemplateDoc ? "font" : "bolt" }); dbox.dragFactory = layoutDoc; dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 1fe95474c..7194feb2e 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -63,7 +63,7 @@ export namespace InteractionUtils { export function GetMyTargetTouches(mte: InteractionUtils.MultiTouchEvent<React.TouchEvent | TouchEvent>, prevPoints: Map<number, React.Touch>, ignorePen: boolean): React.Touch[] { const myTouches = new Array<React.Touch>(); for (const pt of mte.touches) { - if (!ignorePen || (pt.radiusX > 1 && pt.radiusY > 1)) { + if (!ignorePen || ((pt as any).radiusX > 1 && (pt as any).radiusY > 1)) { for (const tPt of mte.targetTouches) { if (tPt?.screenX === pt?.screenX && tPt?.screenY === pt?.screenY) { if (pt && prevPoints.has(pt.identifier)) { @@ -73,6 +73,9 @@ export namespace InteractionUtils { } } } + // if (mte.touches.length !== myTouches.length) { + // throw Error("opo") + // } return myTouches; } diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index 00ce3ef73..8411cc6ee 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -101,7 +101,7 @@ export const inpRules = { } }); const node = (state.doc.resolve(start) as any).nodeAfter; - const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 75, title: "dashDoc", docid: docId, float: "right", fieldKey: match[2], alias: Utils.GenerateGuid() }); + const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 75, title: "dashDoc", docid: docId, float: "right", fieldKey: match[2]?.substring(1), alias: Utils.GenerateGuid() }); const sm = state.storedMarks || undefined; return node ? state.tr.replaceRangeWith(start, end, dashDoc).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; }), diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index d1e0f07cb..9e4f06919 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -21,6 +21,7 @@ import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; import { ObjectField } from "../../new_fields/ObjectField"; import { ComputedField } from "../../new_fields/ScriptField"; import { observer } from "mobx-react"; +import { Id } from "../../new_fields/FieldSymbols"; const blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"], preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]; @@ -759,11 +760,15 @@ export class DashDocView { return true; }; const alias = node.attrs.alias; - DocServer.GetRefField(node.attrs.docid + alias).then(async dashDoc => { + + const docid = node.attrs.docid || tbox.props.DataDoc?.[Id] || tbox.dataDoc?.[Id]; + DocServer.GetRefField(docid + alias).then(async dashDoc => { if (!(dashDoc instanceof Doc)) { - alias && DocServer.GetRefField(node.attrs.docid).then(async dashDocBase => { + alias && DocServer.GetRefField(docid).then(async dashDocBase => { if (dashDocBase instanceof Doc) { - self.doRender(Doc.MakeAlias(dashDocBase), removeDoc, node, view, getPos); + const aliasedDoc = Doc.MakeDelegate(dashDocBase, docid + alias); + aliasedDoc.layoutKey = "layout_" + node.attrs.fieldKey; + self.doRender(aliasedDoc, removeDoc, node, view, getPos); } }); } else { @@ -785,7 +790,6 @@ export class DashDocView { } doRender(dashDoc: Doc, removeDoc: any, node: any, view: any, getPos: any) { this._dashDoc = dashDoc; - dashDoc._hideSidebar = true; if (node.attrs.width !== dashDoc._width + "px" || node.attrs.height !== dashDoc._height + "px") { try { // bcz: an exception will be thrown if two aliases are open at the same time when a doc view comment is made view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc._width + "px", height: dashDoc._height + "px" })); @@ -812,7 +816,7 @@ export class DashDocView { }, { fireImmediately: true }); ReactDOM.render(<DocumentView Document={finalLayout} - DataDoc={Doc.AreProtosEqual(this._textBox.Document, dashDoc) ? this._textBox.dataDoc : undefined} + DataDoc={!node.attrs.docid ? this._textBox.dataDoc : undefined} LibraryPath={this._textBox.props.LibraryPath} fitToBox={BoolCast(dashDoc._fitToBox)} addDocument={returnFalse} diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index ac803d977..4d04d4e89 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -134,13 +134,13 @@ export class ContextMenu extends React.Component { } @action - displayMenu = (x: number, y: number) => { + displayMenu = (x: number, y: number, initSearch = "") => { //maxX and maxY will change if the UI/font size changes, but will work for any amount //of items added to the menu this._pageX = x; this._pageY = y; - this._searchString = ""; + this._searchString = initSearch; this._shouldDisplay = true; } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 7c4391ec0..c5034b901 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -265,7 +265,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> const layoutKey = Cast(dv.props.Document.layoutKey, "string", null); const collapse = layoutKey !== "layout_icon"; if (collapse) { - if (layoutKey) dv.props.Document.deiconifyLayout = layoutKey.replace("layout_", ""); + if (layoutKey && layoutKey !== "layout") dv.props.Document.deiconifyLayout = layoutKey.replace("layout_", ""); dv.setCustomView(collapse, "icon"); } else { const deiconifyLayout = Cast(dv.props.Document.deiconifyLayout, "string", null); diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 780c5b2f4..84c6b0dfd 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -46,6 +46,7 @@ export interface EditableProps { onClick?: (e: React.MouseEvent) => boolean; isEditingCallback?: (isEditing: boolean) => void; menuCallback?: (x: number, y: number) => void; + showMenuOnLoad?: boolean; HeadingObject?: SchemaHeaderField | undefined; HeadingsHack?: number; toggle?: () => void; @@ -77,6 +78,8 @@ export class EditableView extends React.Component<EditableProps> { } } + _didShow = false; + @action onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { if (e.key === "Tab") { @@ -97,16 +100,20 @@ export class EditableView extends React.Component<EditableProps> { this._editing = false; this.props.isEditingCallback?.(false); } else if (e.key === ":") { - this.props.menuCallback?.(e.currentTarget.offsetLeft, e.currentTarget.offsetTop); + this.props.menuCallback?.(e.currentTarget.getBoundingClientRect().x, e.currentTarget.getBoundingClientRect().y); } } @action onClick = (e: React.MouseEvent) => { e.nativeEvent.stopPropagation(); - if (!this.props.onClick || !this.props.onClick(e)) { - this._editing = true; - this.props.isEditingCallback?.(true); + if (this._ref.current && this.props.showMenuOnLoad) { + this.props.menuCallback?.(this._ref.current.getBoundingClientRect().x, this._ref.current.getBoundingClientRect().y); + } else { + if (!this.props.onClick || !this.props.onClick(e)) { + this._editing = true; + this.props.isEditingCallback?.(true); + } } e.stopPropagation(); } @@ -130,6 +137,7 @@ export class EditableView extends React.Component<EditableProps> { return wasFocused !== this._editing; } + _ref = React.createRef<HTMLDivElement>(); render() { if (this._editing && this.props.GetValue() !== undefined) { return this.props.autosuggestProps @@ -156,9 +164,10 @@ export class EditableView extends React.Component<EditableProps> { style={{ display: this.props.display, fontSize: this.props.fontSize }} />; } else { - if (this.props.autosuggestProps) this.props.autosuggestProps.resetValue(); + this.props.autosuggestProps?.resetValue(); return (this.props.contents instanceof ObjectField ? (null) : <div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`} + ref={this._ref} style={{ display: this.props.display, minHeight: "20px", height: `${this.props.height ? this.props.height : "auto"}`, maxHeight: `${this.props.maxHeight}` }} onClick={this.onClick}> <span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize }}>{this.props.contents}</span> diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index d5554fd4f..f61eb9cd0 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -90,22 +90,22 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { // todo: add brushes to brushMap to save with a style name onCustomKeypress = (e: React.KeyboardEvent) => { if (e.key === "Enter") { - runInAction(() => TemplateMenu._addedKeys.add(this._customRef.current!.value)); + runInAction(() => this._addedKeys.add(this._customRef.current!.value)); } } componentDidMount() { - !TemplateMenu._addedKeys && (TemplateMenu._addedKeys = new ObservableSet(["narrative"])); + !this._addedKeys && (this._addedKeys = new ObservableSet()); Array.from(Object.keys(Doc.GetProto(this.props.docViews[0].props.Document))). filter(key => key.startsWith("layout_")). - map(key => runInAction(() => TemplateMenu._addedKeys.add(key.replace("layout_", "")))); + map(key => runInAction(() => this._addedKeys.add(key.replace("layout_", "")))); DocListCast(Cast(CurrentUserUtils.UserDocument.expandingButtons, Doc, null)?.data)?.map(btnDoc => { if (StrCast(Cast(btnDoc?.dragFactory, Doc, null)?.title)) { - runInAction(() => TemplateMenu._addedKeys.add(StrCast(Cast(btnDoc?.dragFactory, Doc, null)?.title))); + runInAction(() => this._addedKeys.add(StrCast(Cast(btnDoc?.dragFactory, Doc, null)?.title))); } }); } - static _addedKeys = new ObservableSet(["narrative"]); + _addedKeys = new ObservableSet(); _customRef = React.createRef<HTMLInputElement>(); render() { const layout = Doc.Layout(this.props.docViews[0].Document); @@ -114,7 +114,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { templateMenu.push(<TemplateToggle key={template.Name} template={template} checked={checked} toggle={this.toggleTemplate} />)); templateMenu.push(<OtherToggle key={"float"} name={"Float"} checked={this.props.docViews[0].Document.z ? true : false} toggle={this.toggleFloat} />); templateMenu.push(<OtherToggle key={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== "disabled"} toggle={this.toggleChrome} />); - TemplateMenu._addedKeys && Array.from(TemplateMenu._addedKeys).map(layout => + this._addedKeys && Array.from(this._addedKeys).map(layout => templateMenu.push(<OtherToggle key={layout} name={layout} checked={StrCast(this.props.docViews[0].Document.layoutKey, "layout") === "layout_" + layout} toggle={e => this.toggleLayout(e, layout)} />) ); return <ul className="template-list" style={{ display: "block" }}> diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 82cb3bc88..159a1cded 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -643,7 +643,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { //add this new doc to props.Document const curPres = Cast(CurrentUserUtils.UserDocument.curPresentation, Doc) as Doc; if (curPres) { - const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent" }); + const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5 }); Doc.GetProto(pinDoc).presentationTargetDoc = doc; Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('(this.presentationTargetDoc instanceof Doc) && this.presentationTargetDoc.title?.toString()'); const data = Cast(curPres.data, listSpec(Doc)); diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index 440b6856b..1a84a34a0 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -16,6 +16,10 @@ import "./CollectionPivotView.scss"; import { CollectionSubView } from "./CollectionSubView"; import { CollectionTreeView } from "./CollectionTreeView"; import React = require("react"); +import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from "../ContextMenuItem"; +import { RichTextField } from "../../../new_fields/RichTextField"; +import { ImageField } from "../../../new_fields/URLField"; @observer export class CollectionPivotView extends CollectionSubView(doc => doc) { @@ -36,7 +40,7 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { } } bodyPanelWidth = () => this.props.PanelWidth() - this._facetWidth; - getTransform = () => this.props.ScreenToLocalTransform().translate(-200, 0); + getTransform = () => this.props.ScreenToLocalTransform().translate(-this._facetWidth, 0); @computed get _allFacets() { const facets = new Set<string>(); @@ -98,6 +102,25 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { document.removeEventListener("pointerup", this.onPointerUp); } + menuCallback = (x: number, y: number) => { + ContextMenu.Instance.clearItems(); + const docItems: ContextMenuProps[] = []; + const keySet: Set<string> = new Set(); + + this.childLayoutPairs.map(pair => + Array.from(Object.keys(Doc.GetProto(pair.layout))).filter(fieldKey => pair.layout[fieldKey] instanceof RichTextField || typeof (pair.layout[fieldKey]) === "string").map(fieldKey => + keySet.add(fieldKey))); + keySet.toArray().map(fieldKey => + docItems.push({ description: ":" + fieldKey, event: () => this.props.Document.pivotField = fieldKey, icon: "compress-arrows-alt" })); + docItems.push({ description: ":(null)", event: () => this.props.Document.pivotField = undefined, icon: "compress-arrows-alt" }) + ContextMenu.Instance.addItem({ description: "Pivot Fields ...", subitems: docItems, icon: "eye" }); + const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(x, y); + ContextMenu.Instance.displayMenu(x, y, ":"); + } + + @observable private collapsed: boolean = false; + private toggleVisibility = action(() => this.collapsed = !this.collapsed); + render() { const facetCollection = Cast(this.props.Document?._facetCollection, Doc, null); const flyout = ( @@ -109,20 +132,24 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { </label>)} </div> ); + const newEditableViewProps = { + GetValue: () => "", + SetValue: (value: any) => { + if (value?.length) { + this.props.Document.pivotField = value; + return true; + } + return false; + }, + showMenuOnLoad: true, + contents: ":" + StrCast(this.props.Document.pivotField), + toggle: this.toggleVisibility, + color: "#f1efeb" // this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; + }; return !facetCollection ? (null) : <div className="collectionPivotView" style={{ height: `calc(100% - ${this.props.Document._chromeStatus === "enabled" ? 51 : 0}px)` }}> <div className={"pivotKeyEntry"}> - <EditableView - contents={this.props.Document.pivotField} - GetValue={() => StrCast(this.props.Document.pivotField)} - SetValue={value => { - if (value && value.length) { - this.props.Document.pivotField = value; - return true; - } - return false; - }} - /> + <EditableView {...newEditableViewProps} menuCallback={this.menuCallback} /> </div> <div className="collectionPivotView-dragger" key="dragger" onPointerDown={this.onPointerDown} style={{ transform: `translate(${this._facetWidth}px, 0px)` }} > <span title="library View Dragger" style={{ width: "5px", position: "absolute", top: "0" }} /> diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 2a9f903bb..d00ddde6a 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -312,7 +312,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC } }); const pt = this.props.screenToLocalTransform().inverse().transformPoint(x, y); - ContextMenu.Instance.displayMenu(pt[0], pt[1]); + ContextMenu.Instance.displayMenu(x, y); } render() { diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 8679c8bd1..9482435a0 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -98,7 +98,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { get childLayoutPairs(): { layout: Doc; data: Doc; }[] { const { Document, DataDoc } = this.props; - const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, DataDoc, doc)).filter(pair => pair.layout); + const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.annotationsKey ? DataDoc : undefined, doc)).filter(pair => pair.layout); return validPairs.map(({ data, layout }) => ({ data: data!, layout: layout! })); // this mapping is a bit of a hack to coerce types } get childDocList() { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 803454113..3cb24f079 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -636,7 +636,6 @@ export class CollectionTreeView extends CollectionSubView(Document) { if (caption instanceof ObjectField) { Doc.GetProto(img).caption = ObjectField.MakeCopy(caption); } - img._hideSidebar = true; d.captions = undefined; }); }); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index be1317b25..18ca71c2a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -4,7 +4,7 @@ import { ScriptBox } from "../../ScriptBox"; import { CompileScript } from "../../../util/Scripting"; import { ScriptField } from "../../../../new_fields/ScriptField"; import { OverlayView, OverlayElementOptions } from "../../OverlayView"; -import { emptyFunction } from "../../../../Utils"; +import { emptyFunction, aggregateBounds } from "../../../../Utils"; import React = require("react"); import { ObservableMap, runInAction } from "mobx"; import { Id, ToString } from "../../../../new_fields/FieldSymbols"; @@ -42,7 +42,13 @@ function toLabel(target: FieldResult<Field>) { return String(target); } -export function computePivotLayout(poolData: ObservableMap<string, any>, pivotDoc: Doc, childDocs: Doc[], childPairs: { layout: Doc, data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: any) => ViewDefResult[]) { +export function computePivotLayout( + poolData: ObservableMap<string, any>, + pivotDoc: Doc, + pwidth: number, pheight: number, + childDocs: Doc[], + childPairs: { layout: Doc, data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: any) => ViewDefResult[] +) { const pivotAxisWidth = NumCast(pivotDoc.pivotWidth, 200); const pivotColumnGroups = new Map<FieldResult<Field>, Doc[]>(); @@ -99,21 +105,37 @@ export function computePivotLayout(poolData: ObservableMap<string, any>, pivotDo x += pivotAxisWidth * (numCols * expander + gap); }); + const grpEles = groupNames.map(gn => { return { x: gn.x, y: gn.y, width: gn.width, height: gn.height }; }); + const docEles = childPairs.map(pair => { + const newPos = docMap.get(pair.layout) || { x: NumCast(pair.layout.x), y: NumCast(pair.layout.y) }; // new pos is computed pos, or pos written to the document's fields + return { + x: newPos.x, + y: newPos.y, + width: NumCast(pair.layout._width), + height: NumCast(pair.layout._height) + }; + } + ); + const aggBounds = aggregateBounds(docEles.concat(grpEles), 0, 0); + + const scale = Math.min(pheight / (aggBounds.b - aggBounds.y), pwidth / (aggBounds.r - aggBounds.x)); + childPairs.map(pair => { - const defaultPosition = { + const fallbackPos = { x: NumCast(pair.layout.x), y: NumCast(pair.layout.y), z: NumCast(pair.layout.z), width: NumCast(pair.layout._width), height: NumCast(pair.layout._height) }; - const pos = docMap.get(pair.layout) || defaultPosition; - const data = poolData.get(pair.layout[Id]); - if (!data || pos.x !== data.x || pos.y !== data.y || pos.z !== data.z || pos.width !== data.width || pos.height !== data.height) { - runInAction(() => poolData.set(pair.layout[Id], { transition: "transform 1s", ...pos })); + const newPosRaw = docMap.get(pair.layout) || fallbackPos; // new pos is computed pos, or pos written to the document's fields + const newPos = { x: newPosRaw.x * scale, y: newPosRaw.y * scale, z: newPosRaw.z, width: newPosRaw.width * scale, height: newPosRaw.height * scale }; + const lastPos = poolData.get(pair.layout[Id]); // last computed pos + if (!lastPos || newPos.x !== lastPos.x || newPos.y !== lastPos.y || newPos.z !== lastPos.z || newPos.width !== lastPos.width || newPos.height !== lastPos.height) { + runInAction(() => poolData.set(pair.layout[Id], { transition: "transform 1s", ...newPos })); } }); - return { elements: viewDefsToJSX(groupNames) }; + return { elements: viewDefsToJSX(groupNames.map(gname => { return { type: gname.type, text: gname.text, x: gname.x * scale, y: gname.y * scale, width: gname.width * scale, height: gname.height, fontSize: gname.fontSize } })) }; } export function AddCustomFreeFormLayout(doc: Doc, dataKey: string): () => void { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 20d20f1f6..90bed2899 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -371,6 +371,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this._lastX = pt.pageX; this._lastY = pt.pageY; e.preventDefault(); + e.stopPropagation(); } else { e.preventDefault(); @@ -386,7 +387,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { case GestureUtils.Gestures.Stroke: const points = ge.points; const B = this.getTransform().transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height); - const inkDoc = Docs.Create.InkDocument(InkingControl.Instance.selectedColor, InkingControl.Instance.selectedTool, parseInt(InkingControl.Instance.selectedWidth), points, { x: B.x, y: B.y, _width: B.width, _height: B.height }); + const inkDoc = Docs.Create.InkDocument(InkingControl.Instance.selectedColor, InkingControl.Instance.selectedTool, parseInt(InkingControl.Instance.selectedWidth), points, { title: "ink stroke", x: B.x, y: B.y, _width: B.width, _height: B.height }); this.addDocument(inkDoc); e.stopPropagation(); break; @@ -408,7 +409,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } return pass; }); - this.addDocument(Docs.Create.FreeformDocument(sel, { x: bounds.x, y: bounds.y, _width: bWidth, _height: bHeight, _panX: 0, _panY: 0 })); + this.addDocument(Docs.Create.FreeformDocument(sel, { title: "nested collection", x: bounds.x, y: bounds.y, _width: bWidth, _height: bHeight, _panX: 0, _panY: 0 })); sel.forEach(d => this.props.removeDocument(d)); break; @@ -775,7 +776,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }.bind(this)); doPivotLayout(poolData: ObservableMap<string, any>) { - return computePivotLayout(poolData, this.props.Document, this.childDocs, + return computePivotLayout(poolData, this.props.Document, this.props.PanelWidth(), this.props.PanelHeight(), this.childDocs, this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)), [this.props.PanelWidth(), this.props.PanelHeight()], this.viewDefsToJSX); } @@ -833,23 +834,23 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { layoutDocsInGrid = () => { UndoManager.RunInBatch(() => { - const docs = DocListCast(this.Document[this.props.fieldKey]); + const docs = this.childLayoutPairs; const startX = this.Document._panX || 0; let x = startX; let y = this.Document._panY || 0; let i = 0; - const width = Math.max(...docs.map(doc => NumCast(doc._width))); - const height = Math.max(...docs.map(doc => NumCast(doc._height))); - for (const doc of docs) { - doc.x = x; - doc.y = y; + const width = Math.max(...docs.map(doc => NumCast(doc.layout._width))); + const height = Math.max(...docs.map(doc => NumCast(doc.layout._height))); + docs.forEach(pair => { + pair.layout.x = x; + pair.layout.y = y; x += width + 20; if (++i === 6) { i = 0; x = startX; y += height + 20; } - } + }); }, "arrange contents"); } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 6a1590b8e..ef2fc2ad1 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -299,7 +299,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque this.hideMarquee(); } - getCollection = (selected: Doc[]) => { + getCollection = (selected: Doc[], asTemplate: boolean) => { const bounds = this.Bounds; const defaultPalette = ["rgb(114,229,239)", "rgb(255,246,209)", "rgb(255,188,156)", "rgb(247,220,96)", "rgb(122,176,238)", "rgb(209,150,226)", "rgb(127,235,144)", "rgb(252,188,189)", "rgb(247,175,81)",]; @@ -321,7 +321,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque const usedSequnce = Array.from(usedPaletted.keys()).sort((a, b) => usedPaletted.get(a)! < usedPaletted.get(b)! ? -1 : usedPaletted.get(a)! > usedPaletted.get(b)! ? 1 : 0); const chosenColor = (usedPaletted.size === 0) ? "white" : palette.length ? palette[0] : usedSequnce[0]; // const inkData = this.ink ? this.ink.inkData : undefined; - const newCollection = Docs.Create.FreeformDocument(selected, { + const creator = asTemplate ? Docs.Create.StackingDocument : Docs.Create.FreeformDocument; + const newCollection = creator(selected, { x: bounds.left, y: bounds.top, _panX: 0, @@ -353,7 +354,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque return d; }); } - const newCollection = this.getCollection(selected); + const newCollection = this.getCollection(selected, e.key === "t"); this.props.addDocument(newCollection); this.props.selectDocuments([newCollection], []); MarqueeOptionsMenu.Instance.fadeOut(true); @@ -406,12 +407,12 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque this.delete(); e.stopPropagation(); } - if (e.key === "c" || e.key === "s" || e.key === "S") { + if (e.key === "c" || e.key === "t" || e.key === "s" || e.key === "S") { this._commandExecuted = true; e.stopPropagation(); e.preventDefault(); (e as any).propagationIsStopped = true; - if (e.key === "c") { + if (e.key === "c" || e.key === "t") { this.collection(e); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 264311a7a..82382c536 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -314,22 +314,25 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu handle1PointerDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>) => { if (this.Document.onPointerDown) return; - if (!e.nativeEvent.cancelBubble) { - const touch = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true)[0]; + const touch = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true)[0]; + console.log("down"); + if (touch) { this._downX = touch.clientX; this._downY = touch.clientY; - this._hitTemplateDrag = false; - for (let element = (e.target as any); element && !this._hitTemplateDrag; element = element.parentElement) { - if (element.className && element.className.toString() === "collectionViewBaseChrome-collapse") { - this._hitTemplateDrag = true; + if (!e.nativeEvent.cancelBubble) { + this._hitTemplateDrag = false; + for (let element = (e.target as any); element && !this._hitTemplateDrag; element = element.parentElement) { + if (element.className && element.className.toString() === "collectionViewBaseChrome-collapse") { + this._hitTemplateDrag = true; + } } + if ((this.active || this.Document.onDragStart || this.Document.onClick) && !e.ctrlKey && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); + this.removeMoveListeners(); + this.addMoveListeners(); + this.removeEndListeners(); + this.addEndListeners(); + e.stopPropagation(); } - if ((this.active || this.Document.onDragStart || this.Document.onClick) && !e.ctrlKey && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); - this.removeMoveListeners(); - this.addMoveListeners(); - this.removeEndListeners(); - this.addEndListeners(); - e.stopPropagation(); } } @@ -710,6 +713,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu subitems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "inTab"), icon: "folder" }); subitems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "onRight"), icon: "caret-square-right" }); subitems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), undefined, "onRight"), icon: "layer-group" }); + subitems.push({ description: "Open Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" }); @@ -761,8 +765,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu moreItems.push({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" }); moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" }); } - moreItems.push({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin" }); //I think this should work... and it does! A miracle! - moreItems.push({ description: "Add Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); moreItems.push({ description: "Download document", icon: "download", event: async () => console.log(JSON.parse(await rp.get(Utils.CorsProxy("http://localhost:8983/solr/dash/select"), { @@ -820,6 +822,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } }); const path = this.props.LibraryPath.reduce((p: string, d: Doc) => p + "/" + (Doc.AreProtosEqual(d, (Doc.UserDoc().LibraryBtn as Doc).sourcePanel as Doc) ? "" : d.title), ""); + cm.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin" }); cm.addItem({ description: `path: ${path}`, event: () => { this.props.LibraryPath.map(lp => Doc.GetProto(lp).treeViewOpen = lp.treeViewOpen = true); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 0d97c3029..fe9b8e0ff 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -379,7 +379,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & specificContextMenu = (e: React.MouseEvent): void => { const funcs: ContextMenuProps[] = []; - funcs.push({ description: "Toggle Sidebar", event: () => { e.stopPropagation(); this.toggleSidebar(); }, icon: "expand-arrows-alt" }); + funcs.push({ description: "Toggle Sidebar", event: () => { e.stopPropagation(); this.props.Document._showSidebar = !this.props.Document._showSidebar }, icon: "expand-arrows-alt" }); funcs.push({ description: "Record Bullet", event: () => { e.stopPropagation(); this.recordBullet(); }, icon: "expand-arrows-alt" }); ["My Text", "Text from Others", "Todo Items", "Important Items", "Ignore Items", "Disagree Items", "By Recent Minute", "By Recent Hour"].forEach(option => funcs.push({ @@ -1062,15 +1062,15 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } @computed get sidebarWidthPercent() { return StrCast(this.props.Document.sidebarWidthPercent, "0%"); } - @computed get sidebarWidth() { return Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth(); } + sidebarWidth = () => { return Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth(); } + sidebarScreenToLocal = () => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth()), 0); @computed get sidebarColor() { return StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "transparent")); } render() { TraceMobx(); const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; const interactive = InkingControl.Instance.selectedTool || this.layoutDoc.isBackground; if (this.props.isSelected()) { - // TODO: ftong --> update from dash in richtextmenu - RichTextMenu.Instance.updateFromDash(this._editorView!, undefined, this.props); + this._editorView && RichTextMenu.Instance.updateFromDash(this._editorView, undefined, this.props); } else if (FormattedTextBoxComment.textBox === this) { FormattedTextBoxComment.Hide(); } @@ -1101,13 +1101,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & <div className={`formattedTextBox-outer`} style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, }} ref={this._scrollRef}> <div className={`formattedTextBox-inner${rounded}`} style={{ whiteSpace: "pre-wrap", pointerEvents: ((this.Document.isButton || this.props.onClick) && !this.props.isSelected()) ? "none" : undefined }} ref={this.createDropTarget} /> </div> - {this.props.Document._hideSidebar ? (null) : this.sidebarWidthPercent === "0%" ? + {this.props.Document._showSidebar ? (null) : this.sidebarWidthPercent === "0%" ? <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} onClick={e => this.toggleSidebar()} /> : <div className={"formattedTextBox-sidebar" + (InkingControl.Instance.selectedTool !== InkTool.None ? "-inking" : "")} style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}> <CollectionFreeFormView {...this.props} PanelHeight={this.props.PanelHeight} - PanelWidth={() => this.sidebarWidth} + PanelWidth={this.sidebarWidth} annotationsKey={this.annotationKey} isAnnotationOverlay={false} focus={this.props.focus} @@ -1118,9 +1118,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & whenActiveChanged={this.whenActiveChanged} removeDocument={this.removeDocument} moveDocument={this.moveDocument} - addDocument={(doc: Doc) => { doc._hideSidebar = true; return this.addDocument(doc); }} + addDocument={this.addDocument} CollectionView={undefined} - ScreenToLocalTransform={() => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth), 0)} + ScreenToLocalTransform={this.sidebarScreenToLocal} renderDepth={this.props.renderDepth + 1} ContainingCollectionDoc={this.props.ContainingCollectionDoc} chromeCollapsed={true}> diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index e5a79ab11..01e7f4834 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -6,7 +6,7 @@ top: 0; bottom: 0; width: 100%; - min-width: 200px; + min-width: 100px; height: 100%; min-height: 50px; letter-spacing: 2px; @@ -16,8 +16,6 @@ .presBox-listCont { position: relative; - padding-left: 10px; - padding-right: 10px; } .presBox-buttons { diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 428e9aa7b..8d53f45a6 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -42,7 +42,7 @@ export class PresBox extends React.Component<FieldViewProps> { if (value) { value.forEach((item, i) => { if (item instanceof Doc && item.type !== DocumentType.PRESELEMENT) { - const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent" }); + const pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5 }); Doc.GetProto(pinDoc).presentationTargetDoc = item; Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('this.presentationTargetDoc?.title?.toString()'); value.splice(i, 1, pinDoc); @@ -337,7 +337,7 @@ export class PresBox extends React.Component<FieldViewProps> { @action initializeScaleViews = (docList: Doc[], viewtype: number) => { this.props.Document._chromeStatus = "disabled"; - const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 72; + const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 42; docList.forEach((doc: Doc) => { doc.presBox = this.props.Document; doc.presBoxKey = this.props.fieldKey; @@ -357,7 +357,7 @@ export class PresBox extends React.Component<FieldViewProps> { } getTransform = () => { - return this.props.ScreenToLocalTransform().translate(-10, -50);// listBox padding-left and pres-box-cont minHeight + return this.props.ScreenToLocalTransform().translate(0, -50);// listBox padding-left and pres-box-cont minHeight } render() { this.initializeScaleViews(this.childDocs, NumCast(this.props.Document._viewType)); diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index 34c170be2..b74b07224 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -6,14 +6,17 @@ width: 100%; outline-color: maroon; outline-style: dashed; - border-radius: 12px; + border-radius: 6px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; - transition: all .1s; + transition: all .1s; + padding: 0px; + padding-left: 5px; + padding-bottom: 3px; .documentView-node { position: absolute; @@ -32,34 +35,43 @@ .presElementBox-item:hover { transition: all .1s; background: #AAAAAA; - border-radius: 12px; + border-radius: 6px; } .presElementBox-selected { background: gray; color: black; - border-radius: 12px; + border-radius: 6px; box-shadow: black 2px 2px 5px; } .presElementBox-closeIcon { - float: right; border-radius: 20px; transform:scale(0.7); + position: absolute; + right: 0; + top: 0; + padding: 8px; } .presElementBox-interaction { color: gray; float: left; + padding: 0px; + width: 20px; + height: 20px; } .presElementBox-interaction-selected { color: white; float: left; + padding: 0px; + width: 22px; + height: 22px; } .presElementBox-name { - font-size: 15px; + font-size: 12px; position: absolute; display: inline-block; width: calc(100% - 45px); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 5f454e930..5f78636a9 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -611,7 +611,7 @@ export namespace Doc { Cast(templateField.data, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc)); (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateField.data)); } - if (templateField.data instanceof RichTextField && templateField.data.Data) { + if (templateField.data instanceof RichTextField && templateField.data.Text) { templateField._textTemplate = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name }); } diff --git a/src/pen-gestures/ndollar.ts b/src/pen-gestures/ndollar.ts index ef5ca38c6..9e15ada2d 100644 --- a/src/pen-gestures/ndollar.ts +++ b/src/pen-gestures/ndollar.ts @@ -168,7 +168,12 @@ export class NDollarRecognizer { // this.Multistrokes = new Array(NumMultistrokes); this.Multistrokes[0] = new Multistroke(GestureUtils.Gestures.Box, useBoundedRotationInvariance, new Array( - new Array(new Point(30, 146), new Point(30, 222), new Point(106, 225), new Point(106, 146), new Point(30, 146)) + new Array( + new Point(30, 146), //new Point(29, 160), new Point(30, 180), new Point(31, 200), + new Point(30, 222), //new Point(50, 219), new Point(70, 225), new Point(90, 230), + new Point(106, 225), //new Point(100, 200), new Point(106, 180), new Point(110, 160), + new Point(106, 146), //new Point(80, 150), new Point(50, 146), + new Point(30, 143)) )); this.Multistrokes[1] = new Multistroke(GestureUtils.Gestures.Line, useBoundedRotationInvariance, new Array( new Array(new Point(12, 347), new Point(119, 347)) diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 35b266608..6bfc729de 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -55,7 +55,7 @@ export class CurrentUserUtils { { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' }, { title: "record", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` }, { title: "clickable button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, title: "Button" })' }, - { title: "presentation", icon: "tv", ignoreClick: true, drag: `Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List<Doc>(), { _width: 200, _height: 500, _viewType: ${CollectionViewType.Stacking}, title: "a presentation trail" })` }, + { title: "presentation", icon: "tv", ignoreClick: true, drag: `Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List<Doc>(), { _width: 200, _height: 500, _xMargin:5, _viewType: ${CollectionViewType.Stacking}, title: "a presentation trail" })` }, { title: "import folder", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, { title: "mobile view", icon: "phone", ignoreClick: true, drag: 'Doc.UserDoc().activeMobile' }, { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, @@ -116,7 +116,8 @@ export class CurrentUserUtils { { title: "use pen", icon: "pen-nib", pointerUp: "resetPen()", pointerDown: 'setPen(2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, { title: "use highlighter", icon: "highlighter", pointerUp: "resetPen()", pointerDown: 'setPen(20, this.backgroundColor)', backgroundColor: "yellow", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, { title: "notepad", icon: "clipboard", pointerUp: "GestureOverlay.Instance.closeFloatingDoc()", pointerDown: 'GestureOverlay.Instance.openFloatingDoc(this.clipboard)', clipboard: Docs.Create.FreeformDocument([], { _width: 300, _height: 300 }), backgroundColor: "orange", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, - { title: "interpret text", icon: "font", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('inktotext')", clipboard: Docs.Create.FreeformDocument([], { _width: 300, _height: 300 }), backgroundColor: "orange", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, + { title: "interpret text", icon: "font", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('inktotext')", backgroundColor: "orange", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, + { title: "ignore gestures", icon: "signature", pointerUp: "setToolglass('none')", pointerDown: "setToolglass('ignoregesture')", backgroundColor: "green", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc }, ]; return docProtoData.map(data => Docs.Create.FontIconDocument({ _nativeWidth: 10, _nativeHeight: 10, _width: 10, _height: 10, _dropAction: data.pointerDown ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, |