diff options
| author | ab <abdullah_ahmed@brown.edu> | 2019-07-14 23:39:56 -0400 |
|---|---|---|
| committer | ab <abdullah_ahmed@brown.edu> | 2019-07-14 23:39:56 -0400 |
| commit | b7dd805549c5cdb6b583312e5e9637f9f3e0ee93 (patch) | |
| tree | 24217f91f213e57c503d226bae1475acb84c6a1d /src/client/views/DocumentDecorations.tsx | |
| parent | baf446a5d65f8e0203eb3c7fb2f43d62a6997daa (diff) | |
| parent | d7c6f0da00d4ed56d28f679d6f7de1002684864a (diff) | |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web
Diffstat (limited to 'src/client/views/DocumentDecorations.tsx')
| -rw-r--r-- | src/client/views/DocumentDecorations.tsx | 96 |
1 files changed, 63 insertions, 33 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 76c2d71e8..2cb3de50f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faLink } from '@fortawesome/free-solid-svg-icons'; +import { faLink, faTag } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; @@ -12,7 +12,7 @@ import { Docs } from "../documents/Documents"; import { DocumentManager } from "../util/DocumentManager"; import { DragLinksAsDocuments, DragManager } from "../util/DragManager"; import { SelectionManager } from "../util/SelectionManager"; -import { undoBatch } from "../util/UndoManager"; +import { undoBatch, UndoManager } from "../util/UndoManager"; import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss"; import { CollectionView } from "./collections/CollectionView"; import './DocumentDecorations.scss'; @@ -27,11 +27,13 @@ import React = require("react"); import { RichTextField } from '../../new_fields/RichTextField'; import { LinkManager } from '../util/LinkManager'; import { ObjectField } from '../../new_fields/ObjectField'; +import { MetadataEntryMenu } from './MetadataEntryMenu'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; library.add(faLink); +library.add(faTag); @observer export class DocumentDecorations extends React.Component<{}, { value: string }> { @@ -50,6 +52,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> private _downX = 0; private _downY = 0; private _iconDoc?: Doc = undefined; + private _resizeUndo?: UndoManager.Batch; @observable private _minimizedX = 0; @observable private _minimizedY = 0; @observable private _title: string = ""; @@ -83,26 +86,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let fieldTemplate = fieldTemplateView.props.Document; let docTemplate = fieldTemplateView.props.ContainingCollectionView!.props.Document; let metaKey = text.slice(1, text.length); - - // move data doc fields to layout doc as needed (nativeWidth/nativeHeight, data, ??) - let backgroundLayout = StrCast(fieldTemplate.backgroundLayout); - let layout = StrCast(fieldTemplate.layout).replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`); - if (backgroundLayout) { - layout = StrCast(fieldTemplate.layout).replace(/fieldKey={"annotations"}/, `fieldKey={"${metaKey}"} fieldExt={"annotations"}`); - backgroundLayout = backgroundLayout.replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`); - } - let nw = Cast(fieldTemplate.nativeWidth, "number"); - let nh = Cast(fieldTemplate.nativeHeight, "number"); - - fieldTemplate.title = metaKey; - fieldTemplate.layout = layout; - fieldTemplate.backgroundLayout = backgroundLayout; - fieldTemplate.nativeWidth = nw; - fieldTemplate.nativeHeight = nh; - fieldTemplate.embed = true; - fieldTemplate.isTemplate = true; - fieldTemplate.templates = new List<string>([Templates.TitleBar(metaKey)]); - fieldTemplate.proto = Doc.GetProto(docTemplate); + Doc.MakeTemplate(fieldTemplate, metaKey, Doc.GetProto(docTemplate)); } else { if (SelectionManager.SelectedDocuments().length > 0) { @@ -171,7 +155,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> document.addEventListener("pointermove", this.onBackgroundMove); document.addEventListener("pointerup", this.onBackgroundUp); e.stopPropagation(); - e.preventDefault(); } @action @@ -305,7 +288,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @undoBatch @action createIcon = (selected: DocumentView[], layoutString: string): Doc => { let doc = selected[0].props.Document; - let iconDoc = Docs.IconDocument(layoutString); + let iconDoc = Docs.Create.IconDocument(layoutString); iconDoc.isButton = true; iconDoc.proto!.title = selected.length > 1 ? "-multiple-.icon" : StrCast(doc.title) + ".icon"; iconDoc.labelField = selected.length > 1 ? undefined : this._fieldKey; @@ -340,6 +323,37 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> iconDoc.y = where[1] + NumCast(selView.props.Document.y); } + _radiusDown = [0, 0]; + @action + onRadiusDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + if (e.button === 0) { + this._radiusDown = [e.clientX, e.clientY]; + this._isPointerDown = true; + this._resizeUndo = UndoManager.StartBatch("DocDecs set radius"); + document.removeEventListener("pointermove", this.onRadiusMove); + document.removeEventListener("pointerup", this.onRadiusUp); + document.addEventListener("pointermove", this.onRadiusMove); + document.addEventListener("pointerup", this.onRadiusUp); + } + } + + onRadiusMove = (e: PointerEvent): void => { + let dist = Math.sqrt((e.clientX - this._radiusDown[0]) * (e.clientX - this._radiusDown[0]) + (e.clientY - this._radiusDown[1]) * (e.clientY - this._radiusDown[1])); + SelectionManager.SelectedDocuments().map(dv => dv.props.Document.borderRounding = Doc.GetProto(dv.props.Document).borderRounding = `${Math.min(100, dist)}%`); + e.stopPropagation(); + e.preventDefault(); + } + + onRadiusUp = (e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); + this._isPointerDown = false; + this._resizeUndo && this._resizeUndo.end(); + document.removeEventListener("pointermove", this.onRadiusMove); + document.removeEventListener("pointerup", this.onRadiusUp); + } + @action onPointerDown = (e: React.PointerEvent): void => { e.stopPropagation(); @@ -347,6 +361,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> this._isPointerDown = true; this._resizing = e.currentTarget.id; this.Interacting = true; + this._resizeUndo = UndoManager.StartBatch("DocDecs resize"); document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -500,7 +515,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let nheight = doc.nativeHeight || 0; let width = (doc.width || 0); let height = (doc.height || (nheight / nwidth * width)); - let scale = element.props.ScreenToLocalTransform().Scale; + let scale = element.props.ScreenToLocalTransform().Scale * element.props.ContentScaling(); let actualdW = Math.max(width + (dW * scale), 20); let actualdH = Math.max(height + (dH * scale), 20); doc.x = (doc.x || 0) + dX * (actualdW - width); @@ -548,6 +563,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (e.button === 0) { e.preventDefault(); this._isPointerDown = false; + this._resizeUndo && this._resizeUndo.end(); document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); } @@ -582,8 +598,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (!canEmbed) return (null); return ( <div className="linkButtonWrapper"> - <div style={{ paddingTop: 3, marginLeft: 30 }} title="Drag Embed" className="linkButton-linker" ref={this._embedButton} onPointerDown={this.onEmbedButtonDown}> - <FontAwesomeIcon className="fa-image" icon="image" size="sm" /> + <div title="Drag Embed" className="linkButton-linker" ref={this._embedButton} onPointerDown={this.onEmbedButtonDown}> + <FontAwesomeIcon className="documentdecorations-icon" icon="image" size="sm" /> </div> </div> ); @@ -596,10 +612,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> this._textDoc = thisDoc; return ( <div className="tooltipwrapper"> - <div style={{ paddingTop: 3, marginLeft: 30 }} title="Hide Tooltip" className="linkButton-linker" ref={this._tooltipoff} onPointerDown={this.onTooltipOff}> + <div title="Hide Tooltip" className="linkButton-linker" ref={this._tooltipoff} onPointerDown={this.onTooltipOff}> {/* <FontAwesomeIcon className="fa-image" icon="image" size="sm" /> */} - T - </div> + </div> </div> ); @@ -620,6 +635,17 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } } + get metadataMenu() { + return ( + <div className="linkButtonWrapper"> + <Flyout anchorPoint={anchorPoints.TOP_LEFT} + content={<MetadataEntryMenu docs={() => SelectionManager.SelectedDocuments().map(dv => dv.props.Document)} suggestWithFunction />}>{/* tfs: @bcz This might need to be the data document? */} + <div className="docDecs-tagButton" title="Add fields"><FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" /></div> + </Flyout> + </div> + ); + } + render() { var bounds = this.Bounds; let seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; @@ -692,7 +718,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> {this._edtingTitle ? <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this._title} onBlur={this.titleBlur} onChange={this.titleChanged} onKeyPress={this.titleEntered} /> : <div className="title" onPointerDown={this.onTitleDown} ><span>{`${this.selectionTitle}`}</span></div>} - <div className="documentDecorations-closeButton" onPointerDown={this.onCloseDown}>X</div> + <div className="documentDecorations-closeButton" title="Close Document" onPointerDown={this.onCloseDown}>X</div> <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> @@ -702,16 +728,20 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> <div id="documentDecorations-bottomLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> + <div id="documentDecorations-borderRadius" className="documentDecorations-radius" onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}><span className="borderRadiusTooltip" title="Drag Corner Radius"></span></div> <div className="link-button-container"> <div className="linkButtonWrapper"> <div title="View Links" className="linkFlyout" ref={this._linkButton}> {linkButton} </div> </div> <div className="linkButtonWrapper"> <div title="Drag Link" className="linkButton-linker" ref={this._linkerButton} onPointerDown={this.onLinkerButtonDown}> - <FontAwesomeIcon className="fa-icon-link" icon="link" size="sm" /> + <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> </div> </div> - <TemplateMenu docs={SelectionManager.ViewsSortedVertically()} templates={templates} /> + <div className="linkButtonWrapper"> + <TemplateMenu docs={SelectionManager.ViewsSortedVertically()} templates={templates} /> + </div> + {this.metadataMenu} {this.considerEmbed()} {/* {this.considerTooltip()} */} </div> |
