diff options
author | kimdahey <claire_kim1@brown.edu> | 2019-11-23 14:30:06 -0500 |
---|---|---|
committer | kimdahey <claire_kim1@brown.edu> | 2019-11-23 14:30:06 -0500 |
commit | 66424255021c7563df93aa9de9c1535bef1d9b50 (patch) | |
tree | 1149b7d16ab9680660aee470a34f456dae960639 /src/client/views/nodes/DocumentView.tsx | |
parent | b4a23b21bbe0a44df1328419c7d94b97a772e54f (diff) | |
parent | 3b37cc31bb09b11238868c34a38a8e99f508479f (diff) |
pulled from master
Diffstat (limited to 'src/client/views/nodes/DocumentView.tsx')
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 152 |
1 files changed, 84 insertions, 68 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 304555c30..467fd4b32 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -11,13 +11,12 @@ import { ScriptField } from '../../../new_fields/ScriptField'; import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { ImageField } from '../../../new_fields/URLField'; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; -import { emptyFunction, returnTransparent, returnTrue, Utils } from "../../../Utils"; +import { emptyFunction, returnTransparent, returnTrue, Utils, returnOne } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { DocServer } from "../../DocServer"; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from '../../documents/DocumentTypes'; import { ClientUtils } from '../../util/ClientUtils'; -import { DictationManager } from '../../util/DictationManager'; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager, dropActionType } from "../../util/DragManager"; import { LinkManager } from '../../util/LinkManager'; @@ -41,6 +40,10 @@ import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import { FormattedTextBox } from './FormattedTextBox'; import React = require("react"); +import { InteractionUtils } from '../../util/InteractionUtils'; +import { InkingControl } from '../InkingControl'; +import { InkTool } from '../../../new_fields/InkField'; +import { TraceMobx } from '../../../new_fields/util'; library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight, fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale, @@ -64,7 +67,7 @@ export interface DocumentViewProps { PanelWidth: () => number; PanelHeight: () => number; focus: (doc: Doc, willZoom: boolean, scale?: number, afterFocus?: () => boolean) => void; - parentActive: () => boolean; + parentActive: (outsideReaction: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; bringToFront: (doc: Doc, sendToBack?: boolean) => void; addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean; @@ -74,6 +77,7 @@ export interface DocumentViewProps { getScale: () => number; animateBetweenIcon?: (maximize: boolean, target: number[]) => void; ChromeHeight?: () => number; + dontRegisterView?: boolean; layoutKey?: string; } @@ -88,8 +92,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu private _mainCont = React.createRef<HTMLDivElement>(); private _dropDisposer?: DragManager.DragDropDisposer; + public get displayName() { return "DocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive public get ContentDiv() { return this._mainCont.current; } - @computed get active() { return SelectionManager.IsSelected(this) || this.props.parentActive(); } + @computed get active() { return SelectionManager.IsSelected(this, true) || this.props.parentActive(true); } @computed get topMost() { return this.props.renderDepth === 0; } @computed get nativeWidth() { return this.layoutDoc.nativeWidth || 0; } @computed get nativeHeight() { return this.layoutDoc.nativeHeight || 0; } @@ -98,7 +103,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu @action componentDidMount() { this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } })); - DocumentManager.Instance.DocumentViews.push(this); + + !this.props.dontRegisterView && DocumentManager.Instance.DocumentViews.push(this); } @action @@ -111,7 +117,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu componentWillUnmount() { this._dropDisposer && this._dropDisposer(); Doc.UnBrushDoc(this.props.Document); - DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1); + !this.props.dontRegisterView && DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1); } startDragging(x: number, y: number, dropAction: dropActionType, applyAsTemplate?: boolean) { @@ -136,7 +142,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { e.stopPropagation(); let preventDefault = true; - if (this._doubleTap && this.props.renderDepth && (!this.onClickHandler || !this.onClickHandler.script)) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click + if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click let fullScreenAlias = Doc.MakeAlias(this.props.Document); if (StrCast(fullScreenAlias.layoutKey) !== "layoutCustom" && fullScreenAlias.layoutCustom !== undefined) { fullScreenAlias.layoutKey = "layoutCustom"; @@ -206,14 +212,15 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu document.addEventListener("pointerup", this.onPointerUp); if ((e.nativeEvent as any).formattedHandled) { e.stopPropagation(); } } + onPointerMove = (e: PointerEvent): void => { if ((e as any).formattedHandled) { e.stopPropagation(); return; } if (e.cancelBubble && this.active) { document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView) } - else if (!e.cancelBubble && (SelectionManager.IsSelected(this) || this.props.parentActive() || this.Document.onDragStart || this.Document.onClick) && !this.Document.lockedPosition && !this.Document.inOverlay) { + else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.Document.onDragStart || this.Document.onClick) && !this.Document.lockedPosition && !this.Document.inOverlay) { if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { - if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.Document.onClick) && e.buttons === 1) { + if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.Document.onClick) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCH))) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); @@ -223,6 +230,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu e.preventDefault(); } } + onPointerUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -350,9 +358,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu @undoBatch @action setCustomView = (custom: boolean): void => { - if (this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.DataDoc) { - Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.DataDoc); - } else { // bcz: not robust -- for now documents with string layout are native documents, and those with Doc layouts are customized + if (this.props.ContainingCollectionView?.props.DataDoc || this.props.ContainingCollectionView?.props.Document.isTemplateDoc) { + Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.Document); + } else { custom ? DocumentView.makeCustomViewClicked(this.props.Document, this.props.DataDoc) : DocumentView.makeNativeViewClicked(this.props.Document); } } @@ -370,15 +378,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu this.Document.lockedPosition = this.Document.lockedPosition ? undefined : true; } - listen = async () => { - Doc.GetProto(this.props.Document).transcript = await DictationManager.Controls.listen({ - continuous: { indefinite: true }, - interimHandler: (results: string) => { - DictationOverlay.Instance.dictationSuccess = true; - DictationOverlay.Instance.dictatedPhrase = results; - DictationOverlay.Instance.isListening = { interim: true }; - } - }); + @undoBatch + @action + toggleLockTransform = (): void => { + this.Document.lockedTransform = this.Document.lockedTransform ? undefined : true; } @action @@ -402,14 +405,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu subitems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group" }); cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" }); - if (Cast(this.props.Document.data, ImageField)) { - cm.addItem({ description: "Export to Google Photos", event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: "caret-square-right" }); - } - if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) { - cm.addItem({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" }); - cm.addItem({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" }); - cm.addItem({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" }); - } let existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; @@ -427,10 +422,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); let funcs: ContextMenuProps[] = []; - funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); - funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) }); - funcs.push({ description: "Drag Document", icon: "edit", event: () => this.Document.onDragStart = undefined }); - ContextMenu.Instance.addItem({ description: "OnDrag...", subitems: funcs, icon: "asterisk" }); + if (this.Document.onDragStart) { + funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); + funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) }); + funcs.push({ description: "Drag Document", icon: "edit", event: () => this.Document.onDragStart = undefined }); + ContextMenu.Instance.addItem({ description: "OnDrag...", subitems: funcs, icon: "asterisk" }); + } let existing = ContextMenu.Instance.findByDescription("Layout..."); let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : []; @@ -442,6 +439,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu layoutItems.push({ description: `${this.Document.autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc.autoHeight = !this.layoutDoc.autoHeight, icon: "plus" }); layoutItems.push({ description: this.Document.ignoreAspect || !this.Document.nativeWidth || !this.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" }); 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" }); layoutItems.push({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" }); layoutItems.push({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" }); if (this.Document.type !== DocumentType.COL && this.Document.type !== DocumentType.TEMPLATE) { @@ -450,18 +448,26 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu layoutItems.push({ description: "Use Native Layout", event: () => DocumentView.makeNativeViewClicked(this.props.Document), icon: "concierge-bell" }); } !existing && cm.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" }); + + let more = ContextMenu.Instance.findByDescription("More..."); + let moreItems: ContextMenuProps[] = more && "subitems" in more ? more.subitems : []; + if (!ClientUtils.RELEASE) { // let copies: ContextMenuProps[] = []; - cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); + moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); // cm.addItem({ description: "Copy...", subitems: copies, icon: "copy" }); } - let existingAnalyze = ContextMenu.Instance.findByDescription("Analyzers..."); - let analyzers: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : []; - analyzers.push({ description: "Transcribe Speech", event: this.listen, icon: "microphone" }); - !existingAnalyze && cm.addItem({ description: "Analyzers...", subitems: analyzers, icon: "hand-point-right" }); - cm.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin" }); //I think this should work... and it does! A miracle! - cm.addItem({ description: "Add Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); - cm.addItem({ + if (Cast(this.props.Document.data, ImageField)) { + moreItems.push({ description: "Export to Google Photos", event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: "caret-square-right" }); + } + if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) { + moreItems.push({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" }); + 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"), { qs: { q: 'world', fq: 'NOT baseProto_b:true AND NOT deleted:true', start: '0', rows: '100', hl: true, 'hl.fl': '*' } @@ -473,8 +479,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu // a.click(); }); - cm.addItem({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, this.Document.title || "", this.props.addDocument, this.props.removeDocument), icon: "file" }); - cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); + moreItems.push({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, this.Document.title || "", this.props.addDocument, this.props.removeDocument), icon: "file" }); + moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" }); + moreItems.push({ description: "Undo Debug Test", event: () => UndoManager.TraceOpenBatches(), icon: "exclamation" }); + !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); runInAction(() => { if (!ClientUtils.RELEASE) { let setWriteMode = (mode: DocServer.WriteMode) => { @@ -497,7 +505,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu aclsMenu.push({ description: "Live Playground (write own/read others)", event: () => setWriteMode(DocServer.WriteMode.LivePlayground), icon: DocServer.AclsMode === DocServer.WriteMode.LivePlayground ? "check" : "exclamation" }); aclsMenu.push({ description: "Live Readonly (no write/read others)", event: () => setWriteMode(DocServer.WriteMode.LiveReadonly), icon: DocServer.AclsMode === DocServer.WriteMode.LiveReadonly ? "check" : "exclamation" }); cm.addItem({ description: "Collaboration ACLs...", subitems: aclsMenu, icon: "share" }); - cm.addItem({ description: "Undo Debug Test", event: () => UndoManager.TraceOpenBatches(), icon: "exclamation" }); } }); runInAction(() => { @@ -512,7 +519,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu e.stopPropagation(); } ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - if (!SelectionManager.IsSelected(this)) { + if (!SelectionManager.IsSelected(this, true)) { SelectionManager.SelectDoc(this, false); } }); @@ -524,7 +531,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu getLayoutPropStr = (prop: string) => StrCast(this.setsLayoutProp(prop) ? this.props.Document[prop] : this.layoutDoc[prop]); getLayoutPropNum = (prop: string) => NumCast(this.setsLayoutProp(prop) ? this.props.Document[prop] : this.layoutDoc[prop]); - isSelected = () => SelectionManager.IsSelected(this); + isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction); select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; chromeHeight = () => { @@ -533,8 +540,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu return (showTitle ? 25 : 0) + 1; } + @computed get finalLayoutKey() { return this.props.layoutKey || "layout"; } childScaling = () => (this.layoutDoc.fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling()); @computed get contents() { + TraceMobx(); return (<DocumentContentsView ContainingCollectionView={this.props.ContainingCollectionView} ContainingCollectionDoc={this.props.ContainingCollectionDoc} Document={this.props.Document} @@ -563,12 +572,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu isSelected={this.isSelected} select={this.select} onClick={this.onClickHandler} - layoutKey={this.props.layoutKey || "layout"} + layoutKey={this.finalLayoutKey} DataDoc={this.props.DataDoc} />); } linkEndpoint = (linkDoc: Doc) => Doc.LinkEndpoint(linkDoc, this.props.Document); - // used to decide whether a link document should be created or not. + // used to decide whether a link document should be created or not. // if it's a tempoarl link (currently just for Audio), then the audioBox will display the anchor and we don't want to display it here. // would be good to generalize this some way. isNonTemporalLink = (linkDoc: Doc) => { @@ -578,16 +587,17 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } @computed get innards() { + TraceMobx(); const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined; const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : this.getLayoutPropStr("showTitle"); const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.getLayoutPropStr("showCaption"); const showTextTitle = showTitle && StrCast(this.Document.layout).indexOf("FormattedTextBox") !== -1 ? showTitle : undefined; const searchHighlight = (!this.Document.searchFields ? (null) : - <div className="documentView-searchHighlight" style={{ width: `${100 * this.props.ContentScaling()}%`, transform: `scale(${1 / this.props.ContentScaling()})` }}> + <div className="documentView-searchHighlight"> {this.Document.searchFields} </div>); const captionView = (!showCaption ? (null) : - <div className="documentView-captionWrapper" style={{ width: `${100 * this.props.ContentScaling()}%`, transform: `scale(${1 / this.props.ContentScaling()})` }}> + <div className="documentView-captionWrapper"> <FormattedTextBox {...this.props} onClick={this.onClickHandler} DataDoc={this.props.DataDoc} active={returnTrue} isSelected={this.isSelected} focus={emptyFunction} select={this.select} @@ -596,7 +606,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu </div>); const titleView = (!showTitle ? (null) : <div className="documentView-titleWrapper" style={{ - width: `${100 * this.props.ContentScaling()}%`, transform: `scale(${1 / this.props.ContentScaling()})`, position: showTextTitle ? "relative" : "absolute", pointerEvents: SelectionManager.GetIsDragging() ? "none" : "all", }}> @@ -608,9 +617,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu /> </div>); return <> - {this.Document.links && DocListCast(this.Document.links).filter((d) => !DocListCast(this.layoutDoc.hiddenLinks).some(hidden => Doc.AreProtosEqual(hidden, d))).filter(this.isNonTemporalLink).map((d, i) => - <div className="documentView-docuLinkWrapper" key={`${d[Id]}`} style={{ transform: `scale(${this.layoutDoc.fitWidth ? 1 : 1 / this.props.ContentScaling()})` }}> - <DocumentView {...this.props} Document={d} layoutKey={this.linkEndpoint(d)} backgroundColor={returnTransparent} removeDocument={undoBatch(doc => Doc.AddDocToList(this.layoutDoc, "hiddenLinks", doc))} /> + {this.Document.links && DocListCast(this.Document.links).filter(d => !d.hidden).filter(this.isNonTemporalLink).map((d, i) => + <div className="documentView-docuLinkWrapper" key={`${d[Id]}`}> + <DocumentView {...this.props} ContentScaling={returnOne} Document={d} layoutKey={this.linkEndpoint(d)} backgroundColor={returnTransparent} removeDocument={undoBatch(doc => doc.hidden = true)} /> </div>)} {!showTitle && !showCaption ? this.Document.searchFields ? @@ -630,45 +639,52 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu {searchHighlight} </div> } - </> + </>; } + @computed get ignorePointerEvents() { + return (this.Document.isBackground && !this.isSelected()) || (this.Document.type === DocumentType.INK && InkingControl.Instance.selectedTool !== InkTool.None); + } + render() { if (!this.props.Document) return (null); - // trace(); - const animDims = this.Document.animateToDimensions ? Array.from(this.Document.animateToDimensions) : undefined; const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined; const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; const colorSet = this.setsLayoutProp("backgroundColor"); const clusterCol = this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.clusterOverridesDefaultBackground; - const backgroundColor = this.Document.isBackground || (clusterCol && !colorSet) ? + const backgroundColor = (clusterCol && !colorSet) ? this.props.backgroundColor(this.Document) || StrCast(this.layoutDoc.backgroundColor) : ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.Document); - const nativeWidth = this.layoutDoc.fitWidth ? this.props.PanelWidth() - 2 : this.nativeWidth > 0 && !this.layoutDoc.ignoreAspect ? `${this.nativeWidth}px` : "100%"; - const nativeHeight = this.layoutDoc.fitWidth ? this.props.PanelHeight() - 2 : this.Document.ignoreAspect ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document); const borderRounding = this.getLayoutPropStr("borderRounding") || ruleRounding; - const localScale = this.props.ScreenToLocalTransform().Scale * fullDegree; + const localScale = fullDegree; - let animheight = animDims ? animDims[1] : nativeHeight; - let animwidth = animDims ? animDims[0] : nativeWidth; + const animDims = this.Document.animateToDimensions ? Array.from(this.Document.animateToDimensions) : undefined; + let animheight = animDims ? animDims[1] : "100%"; + let animwidth = animDims ? animDims[0] : "100%"; const highlightColors = ["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"]; - const highlightStyles = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid", "solid"]; + const highlightStyles = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid"]; let highlighting = fullDegree && this.layoutDoc.type !== DocumentType.FONTICON && this.layoutDoc.viewType !== CollectionViewType.Linear; return <div className={`documentView-node${this.topMost ? "-topmost" : ""}`} ref={this._mainCont} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} - onPointerEnter={() => Doc.BrushDoc(this.props.Document)} onPointerLeave={e => Doc.UnBrushDoc(this.props.Document)} + onPointerEnter={e => { + console.log("Brush" + this.props.Document.title); + Doc.BrushDoc(this.props.Document); + }} onPointerLeave={e => { + console.log("UnBrush" + this.props.Document.title); + Doc.UnBrushDoc(this.props.Document); + + }} style={{ - transition: this.Document.isAnimating !== undefined ? ".5s linear" : StrCast(this.Document.transition), - pointerEvents: this.Document.isBackground && !this.isSelected() ? "none" : "all", + transition: this.Document.isAnimating ? ".5s linear" : StrCast(this.Document.transition), + pointerEvents: this.ignorePointerEvents ? "none" : "all", color: StrCast(this.Document.color), outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", border: highlighting && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, background: this.layoutDoc.type === DocumentType.FONTICON || this.layoutDoc.viewType === CollectionViewType.Linear ? undefined : backgroundColor, width: animwidth, height: animheight, - transform: `scale(${this.layoutDoc.fitWidth ? 1 : this.props.ContentScaling()})`, opacity: this.Document.opacity }} > {this.innards} |