diff options
| author | bobzel <zzzman@gmail.com> | 2023-11-29 10:02:34 -0500 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2023-11-29 10:02:34 -0500 |
| commit | ba3b3f6f261074bd3f35012bde8730f5d4a36905 (patch) | |
| tree | 6f6c7b141f8bc5881113378801d4b2940cfde36a /src/client/views/collections/CollectionMenu.tsx | |
| parent | ac360607bee82f0fef769eada99dc0b3f85ae70a (diff) | |
numerous changes to fix bugs and to fix/remove old or hacky code. fixed doc dec resizing. moving this.rootDoc => this.Document . fixing template artifacts.
Diffstat (limited to 'src/client/views/collections/CollectionMenu.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionMenu.tsx | 824 |
1 files changed, 16 insertions, 808 deletions
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index b190eb23d..3c555e731 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -1,43 +1,26 @@ import React = require('react'); -import { IconProp } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon, FontAwesomeIconProps } from '@fortawesome/react-fontawesome'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import { Toggle, ToggleType, Type } from 'browndash-components'; import { action, computed, Lambda, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import { ColorState } from 'react-color'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; -import { Document } from '../../../fields/documentSchemas'; -import { Id } from '../../../fields/FieldSymbols'; -import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { RichTextField } from '../../../fields/RichTextField'; -import { listSpec } from '../../../fields/Schema'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { GestureUtils } from '../../../pen-gestures/GestureUtils'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../../Utils'; -import { Docs } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; -import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; import { SettingsManager } from '../../util/SettingsManager'; import { Transform } from '../../util/Transform'; import { undoBatch } from '../../util/UndoManager'; import { AntimodeMenu } from '../AntimodeMenu'; import { EditableView } from '../EditableView'; -import { GestureOverlay } from '../GestureOverlay'; -import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart, SetActiveBezierApprox, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from '../InkingStroke'; -import { LightboxView } from '../LightboxView'; import { MainView } from '../MainView'; -import { media_state } from '../nodes/AudioBox'; -import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; -import { DocumentView, DocumentViewInternal, OpenWhereMod } from '../nodes/DocumentView'; -import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; +import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView'; import { DefaultStyleProvider } from '../StyleProvider'; -import { CollectionDockingView } from './CollectionDockingView'; -import { CollectionFreeFormView } from './collectionFreeForm'; import { CollectionLinearView } from './collectionLinear'; import './CollectionMenu.scss'; @@ -66,7 +49,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> { componentDidMount() { reaction( - () => SelectionManager.Views().length && SelectionManager.Views()[0], + () => SelectionManager.Views().lastElement(), view => view && this.SetSelection(view) ); } @@ -174,7 +157,6 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> { </div> ); - // NEW BUTTONS //dash col linear view buttons const contMenuButtons = ( <div @@ -189,21 +171,6 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> { ); return contMenuButtons; - - // const button = <Tooltip title={<div className="dash-tooltip">Pin Menu</div>} key="pin menu" placement="bottom"> - // <button className="antimodeMenu-button" onClick={this.toggleMenuPin} style={{ backgroundColor: "#121721" }}> - // <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} /> - // </button> - // </Tooltip>; - - // //OLD BUTTONS - // return this.getElement(!this.SelectedCollection ? [/*button*/] : - // [<CollectionViewBaseChrome key="chrome" - // docView={this.SelectedCollection} - // fieldKey={this.SelectedCollection.LayoutFieldKey} - // type={StrCast(this.SelectedCollection?.props.Document._type_collection, CollectionViewType.Invalid) as CollectionViewType} />, - // prop, - // /*button*/]); } } @@ -228,7 +195,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu _templateCommand = { params: ['target', 'source'], title: 'item view', - script: 'self.target.childLayoutTemplate = getDocTemplate(self.source?.[0])', + script: 'this.target.childLayoutTemplate = getDocTemplate(this.source?.[0])', immediate: undoBatch((source: Doc[]) => { let formatStr = source.length && Cast(source[0].text, RichTextField, null)?.Text; try { @@ -250,24 +217,24 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu _narrativeCommand = { params: ['target', 'source'], title: 'child click view', - script: 'self.target.childClickedOpenTemplateView = getDocTemplate(self.source?.[0])', + script: 'this.target.childClickedOpenTemplateView = getDocTemplate(this.source?.[0])', immediate: undoBatch((source: Doc[]) => source.length && (this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]))), initialize: emptyFunction, }; _contentCommand = { params: ['target', 'source'], title: 'set content', - script: 'getProto(self.target).data = copyField(self.source);', + script: 'getProto(this.target).data = copyField(this.source);', immediate: undoBatch((source: Doc[]) => (Doc.GetProto(this.target).data = new List<Doc>(source))), initialize: emptyFunction, }; _onClickCommand = { params: ['target', 'proxy'], title: 'copy onClick', - script: `{ if (self.proxy?.[0]) { - getProto(self.proxy[0]).onClick = copyField(self.target.onClick); - getProto(self.proxy[0]).target = self.target.target; - getProto(self.proxy[0]).source = copyField(self.target.source); + script: `{ if (this.proxy?.[0]) { + getProto(this.proxy[0]).onClick = copyField(this.target.onClick); + getProto(this.proxy[0]).target = this.target.target; + getProto(this.proxy[0]).source = copyField(this.target.source); }}`, immediate: undoBatch((source: Doc[]) => {}), initialize: emptyFunction, @@ -275,7 +242,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu _viewCommand = { params: ['target'], title: 'bookmark view', - script: "self.target._freeform_panX = self['target-freeform_panX']; self.target._freeform_panY = self['target-freeform_panY']; self.target._freeform_scale = self['target_freeform_scale']; gotoFrame(self.target, self['target-currentFrame']);", + script: "this.target._freeform_panX = self['target-freeform_panX']; this.target._freeform_panY = this['target-freeform_panY']; this.target._freeform_scale = this['target_freeform_scale']; gotoFrame(this.target, this['target-currentFrame']);", immediate: undoBatch((source: Doc[]) => { this.target._freeform_panX = 0; this.target._freeform_panY = 0; @@ -292,22 +259,22 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu _clusterCommand = { params: ['target'], title: 'fit content', - script: 'self.target._freeform_fitContentsToBox = !self.target._freeform_fitContentsToBox;', + script: 'this.target._freeform_fitContentsToBox = !this.target._freeform_fitContentsToBox;', immediate: undoBatch((source: Doc[]) => (this.target._freeform_fitContentsToBox = !this.target._freeform_fitContentsToBox)), initialize: emptyFunction, }; _fitContentCommand = { params: ['target'], title: 'toggle clusters', - script: 'self.target._freeform_useClusters = !self.target._freeform_useClusters;', + script: 'this.target._freeform_useClusters = !this.target._freeform_useClusters;', immediate: undoBatch((source: Doc[]) => (this.target._freeform_useClusters = !this.target._freeform_useClusters)), initialize: emptyFunction, }; _saveFilterCommand = { params: ['target'], title: 'save filter', - script: `self.target._childFilters = compareLists(self['target-childFilters'],self.target._childFilters) ? undefined : copyField(self['target-childFilters']); - self.target._searchFilterDocs = compareLists(self['target-searchFilterDocs'],self.target._searchFilterDocs) ? undefined: copyField(self['target-searchFilterDocs']);`, + script: `this.target._childFilters = compareLists(this['target-childFilters'],this.target._childFilters) ? undefined : copyField(this['target-childFilters']); + this.target._searchFilterDocs = compareLists(this['target-searchFilterDocs'],this.target._searchFilterDocs) ? undefined: copyField(this['target-searchFilterDocs']);`, immediate: undoBatch((source: Doc[]) => { this.target._childFilters = undefined; this.target._searchFilterDocs = undefined; @@ -390,57 +357,6 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu this.document._facetWidth = 0; }; - @computed get subChrome() { - switch ( - this.props.docView.props.LayoutTemplateString ? CollectionViewType.Freeform : this.props.type // bcz: ARgh! hack to get menu for tree view outline items - ) { - default: - return this.otherSubChrome; - case CollectionViewType.Invalid: - case CollectionViewType.Freeform: - return <CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={this.props.type === CollectionViewType.Invalid} />; - case CollectionViewType.Stacking: - return <CollectionStackingViewChrome key="collchrome" {...this.props} />; - case CollectionViewType.NoteTaking: - return <CollectionNoteTakingViewChrome key="collchrome" {...this.props} />; - case CollectionViewType.Schema: - return <CollectionSchemaViewChrome key="collchrome" {...this.props} />; - case CollectionViewType.Tree: - return <CollectionTreeViewChrome key="collchrome" {...this.props} />; - case CollectionViewType.Masonry: - return <CollectionStackingViewChrome key="collchrome" {...this.props} />; - case CollectionViewType.Carousel: - case CollectionViewType.Carousel3D: - return <Collection3DCarouselViewChrome key="collchrome" {...this.props} />; - case CollectionViewType.Grid: - return <CollectionGridViewChrome key="collchrome" {...this.props} />; - case CollectionViewType.Docking: - return <CollectionDockingChrome key="collchrome" {...this.props} />; - } - } - - @computed get otherSubChrome() { - const docType = this.props.docView.Document.type; - switch (docType) { - default: - return null; - case DocumentType.IMG: - return <CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />; - case DocumentType.PDF: - return <CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />; - case DocumentType.INK: - return <CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />; - case DocumentType.WEB: - return <CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />; - case DocumentType.VID: - return <CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />; - case DocumentType.RTF: - return <CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={this.props.type === CollectionViewType.Invalid} isDoc={true} />; - case DocumentType.MAP: - return <CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={false} isDoc={true} />; - } - } - private dropDisposer?: DragManager.DragDropDisposer; protected createDropTarget = (ele: HTMLDivElement) => { this.dropDisposer?.(); @@ -517,593 +433,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu </div> ); } - - @computed get viewModes() { - const excludedViewTypes = [CollectionViewType.Invalid, CollectionViewType.Docking, CollectionViewType.Pile, CollectionViewType.StackedTimeline, CollectionViewType.Linear]; - const isPres: boolean = this.document && this.document.type === DocumentType.PRES; - return isPres ? null : ( - <div className="collectionViewBaseChrome-viewModes"> - <Tooltip title={<div className="dash-tooltip">drop document to apply or drag to create button</div>} placement="bottom"> - <div className="commandEntry-outerDiv" ref={this._viewRef} onPointerDown={this.dragViewDown}> - <button className={'antimodeMenu-button'}> - <FontAwesomeIcon icon="bullseye" size="lg" /> - </button> - <select className="collectionViewBaseChrome-viewPicker" onPointerDown={stopPropagation} onChange={this.viewChanged} value={StrCast(this.props.type)}> - {Object.values(CollectionViewType) - .filter(type => !excludedViewTypes.includes(type)) - .map(type => ( - <option key={Utils.GenerateGuid()} className="collectionViewBaseChrome-viewOption" onPointerDown={stopPropagation} value={type}> - {type[0].toUpperCase() + type.substring(1)} - </option> - ))} - </select> - </div> - </Tooltip> - </div> - ); - } - - @computed get selectedDocumentView() { - return SelectionManager.Views().lastElement(); - } - @computed get selectedDoc() { - return SelectionManager.Docs().lastElement(); - } - @computed get notACollection() { - if (this.selectedDoc) { - const layoutField = Doc.LayoutField(this.selectedDoc); - return this.props.type === CollectionViewType.Docking || (typeof layoutField === 'string' && !layoutField?.includes('CollectionView')); - } else return false; - } - - @undoBatch - @action - startRecording = () => { - const doc = Docs.Create.ScreenshotDocument({ title: 'screen recording', _layout_fitWidth: true, _width: 400, _height: 200, mediaState: media_state.PendingRecording }); - CollectionDockingView.AddSplit(doc, OpenWhereMod.right); - }; - - @computed - get recordButton() { - const targetDoc = this.selectedDoc; - return ( - <Tooltip key="record" title={<div className="dash-tooltip">{'Capture screen'}</div>} placement="top"> - <button className="antimodeMenu-button" onClick={e => this.startRecording()}> - <div className="recordButtonOutline" style={{}}> - <div className="recordButtonInner" style={{}}></div> - </div> - </button> - </Tooltip> - ); - } - - @undoBatch - onEmbed = () => { - if (this.selectedDoc && this.selectedDocumentView) { - // const copy = Doc.MakeCopy(this.selectedDocumentView.props.Document, true); - // copy.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width); - // copy.y = NumCast(this.selectedDoc.y) + 30; - // this.selectedDocumentView.props.addDocument?.(copy); - const embedding = Doc.MakeEmbedding(this.selectedDoc); - embedding.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width); - embedding.y = NumCast(this.selectedDoc.y) + 30; - this.selectedDocumentView.props.addDocument?.(embedding); - } - }; - onEmbedButtonDown = (e: React.PointerEvent): void => { - setupMoveUpEvents(this, e, this.onEmbedButtonMoved, emptyFunction, emptyFunction); - }; - - @undoBatch - onEmbedButtonMoved = (e: PointerEvent) => { - const contentDiv = this.selectedDocumentView?.ContentDiv; - if (contentDiv && this.selectedDoc) { - const dragData = new DragManager.DocumentDragData([this.selectedDoc]); - const offset = [e.clientX - contentDiv.getBoundingClientRect().x, e.clientY - contentDiv.getBoundingClientRect().y]; - dragData.defaultDropAction = 'embed'; - dragData.canEmbed = true; - DragManager.StartDocumentDrag([contentDiv], dragData, e.clientX, e.clientY, { - offsetX: offset[0], - offsetY: offset[1], - hideSource: false, - }); - return true; - } - return false; - }; - - @computed - get embedButton() { - const targetDoc = this.selectedDoc; - return !targetDoc || targetDoc.type === DocumentType.PRES ? null : ( - <Tooltip title={<div className="dash-tooltip">{'Tap or Drag to create an embedding'}</div>} placement="top"> - <button className="antimodeMenu-button" onPointerDown={this.onEmbedButtonDown} onClick={this.onEmbed} style={{ cursor: 'drag' }}> - <FontAwesomeIcon className="colMenu-icon" icon="copy" size="lg" /> - </button> - </Tooltip> - ); - } - - @computed get lightboxButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? null : ( - <Tooltip title={<div className="dash-tooltip">{'View in Lightbox'}</div>} placement="top"> - <button - className="antimodeMenu-button" - onPointerDown={() => { - const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]); - LightboxView.Instance.SetLightboxDoc(targetDoc, undefined, docs); - }}> - <FontAwesomeIcon className="colMenu-icon" icon="desktop" size="lg" /> - </button> - </Tooltip> - ); - } - - @computed get toggleOverlayButton() { - return ( - <> - <Tooltip title={<div className="dash-tooltip">Toggle Overlay Layer</div>} placement="bottom"> - <button - className={'antimodeMenu-button'} - key="float" - style={{ - backgroundColor: this.props.docView.layoutDoc.z ? '121212' : undefined, - pointerEvents: this.props.docView.props.docViewPath().lastElement()?.rootDoc?._type_collection !== CollectionViewType.Freeform ? 'none' : undefined, - color: this.props.docView.props.docViewPath().lastElement()?.rootDoc?._type_collection !== CollectionViewType.Freeform ? 'dimgrey' : undefined, - }} - onClick={undoBatch(() => this.props.docView.CollectionFreeFormDocumentView?.float())}> - <FontAwesomeIcon icon={['fab', 'buffer']} size={'lg'} /> - </button> - </Tooltip> - </> - ); - } - render() { return ( <div className="collectionMenu-cont"> <div className="collectionMenu"> - <div className="collectionViewBaseChrome"> - {this.notACollection || this.props.type === CollectionViewType.Invalid ? null : this.viewModes} - <div className="collectionMenu-divider" key="divider1"></div> - {this.embedButton} - {/* {this.pinButton} */} - {this.toggleOverlayButton} - <div className="collectionMenu-divider" key="divider2"></div> - {this.subChrome} - <div className="collectionMenu-divider" key="divider3"></div> - {this.lightboxButton} - {this.recordButton} - {!this._buttonizableCommands ? null : this.templateChrome} - </div> - </div> - </div> - ); - } -} - -@observer -export class CollectionDockingChrome extends React.Component<CollectionViewMenuProps> { - render() { - return null; - } -} - -@observer -export class CollectionFreeFormViewChrome extends React.Component<CollectionViewMenuProps & { isOverlay: boolean; isDoc?: boolean }> { - public static Instance: CollectionFreeFormViewChrome; - constructor(props: any) { - super(props); - CollectionFreeFormViewChrome.Instance = this; - } - get document() { - return this.props.docView.props.Document; - } - @computed get dataField() { - return this.document[this.props.docView.LayoutFieldKey + (this.props.isOverlay ? '_annotations' : '')]; - } - @computed get childDocs() { - return DocListCast(this.dataField); - } - @computed get selectedDocumentView() { - return SelectionManager.Views().lastElement(); - } - @computed get selectedDoc() { - return SelectionManager.Docs().lastElement(); - } - @computed get isText() { - return this.selectedDoc?.type === DocumentType.RTF || (RichTextMenu.Instance?.view as any) ? true : false; - } - - public static gotoKeyFrame(doc: Doc, newFrame: number) { - if (doc) { - const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]); - const currentFrame = Cast(doc._currentFrame, 'number', null); - if (currentFrame === undefined) { - doc._currentFrame = 0; - CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0); - } - CollectionFreeFormView.updateKeyframe(undefined, [...childDocs, doc], currentFrame || 0); - doc._currentFrame = newFrame === undefined ? 0 : Math.max(0, newFrame); - } - } - - _keyTimer: NodeJS.Timeout | undefined; - @undoBatch - @action - nextKeyframe = (): void => { - const currentFrame = Cast(this.document._currentFrame, 'number', null); - if (currentFrame === undefined) { - this.document._currentFrame = 0; - CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0); - } - this._keyTimer = CollectionFreeFormView.updateKeyframe(this._keyTimer, [...this.childDocs, this.document], currentFrame || 0); - this.document._currentFrame = Math.max(0, (currentFrame || 0) + 1); - this.document.lastFrame = Math.max(NumCast(this.document._currentFrame), NumCast(this.document.lastFrame)); - }; - @undoBatch - @action - prevKeyframe = (): void => { - const currentFrame = Cast(this.document._currentFrame, 'number', null); - if (currentFrame === undefined) { - this.document._currentFrame = 0; - CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0); - } - this._keyTimer = CollectionFreeFormView.gotoKeyframe(this._keyTimer, [...this.childDocs, this.document], 1000); - this.document._currentFrame = Math.max(0, (currentFrame || 0) - 1); - }; - - private _palette = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '']; - private _width = ['1', '5', '10', '100']; - private _dotsize = [10, 20, 30, 40]; - private _draw = ['∿', '=', '⎯', '→', '↔︎', 'ロ', 'O']; - private _head = ['', '', '', '', 'arrow', '', '']; - private _end = ['', '', '', 'arrow', 'arrow', '', '']; - private _shapePrims = ['', '', 'line', 'line', 'line', 'rectangle', 'circle'] as GestureUtils.Gestures[]; - private _title = ['pen', 'highlighter', 'line', 'line with arrow', 'line with double arrows', 'square', 'circle']; - private _faName = ['pen-fancy', 'highlighter', 'minus', 'long-arrow-alt-right', 'arrows-alt-h', 'square', 'circle']; - @observable _selectedPrimitive = this._shapePrims.length; - @observable _keepPrimitiveMode = false; // for whether primitive selection enters a one-shot or persistent mode - @observable _colorBtn = false; - @observable _widthBtn = false; - @observable _fillBtn = false; - - @action clearKeepPrimitiveMode() { - this._selectedPrimitive = this._shapePrims.length; - } - @action primCreated() { - if (!this._keepPrimitiveMode) { - //get out of ink mode after each stroke= - if (Doc.ActiveTool === InkTool.Highlighter && GestureOverlay.Instance.SavedColor) SetActiveInkColor(GestureOverlay.Instance.SavedColor); - Doc.ActiveTool = InkTool.None; - this._selectedPrimitive = this._shapePrims.length; - SetActiveArrowStart('none'); - SetActiveArrowEnd('none'); - } - } - - @action - changeColor = (color: string, type: string) => { - const col: ColorState = { - hex: color, - hsl: { a: 0, h: 0, s: 0, l: 0, source: '' }, - hsv: { a: 0, h: 0, s: 0, v: 0, source: '' }, - rgb: { a: 0, r: 0, b: 0, g: 0, source: '' }, - oldHue: 0, - source: '', - }; - if (type === 'color') { - SetActiveInkColor(Utils.colorString(col)); - } else if (type === 'fill') { - SetActiveFillColor(Utils.colorString(col)); - } - }; - - @action - editProperties = (value: any, field: string) => { - SelectionManager.Views().forEach( - action((element: DocumentView) => { - const doc = Document(element.rootDoc); - if (doc.type === DocumentType.INK) { - switch (field) { - case 'width': - doc.stroke_width = Number(value); - break; - case 'color': - doc.color = String(value); - break; - case 'fill': - doc.fillColor = String(value); - break; - case 'dash': - doc.stroke_dash = value; - } - } - }) - ); - }; - - @computed get drawButtons() { - const func = action((e: React.MouseEvent | React.PointerEvent, i: number, keep: boolean) => { - this._keepPrimitiveMode = keep; - // these are for shapes - if (this._selectedPrimitive !== i) { - this._selectedPrimitive = i; - if (this._title[i] === 'highlighter') { - Doc.ActiveTool = InkTool.Highlighter; - GestureOverlay.Instance.SavedColor = ActiveInkColor(); - SetActiveInkColor('rgba(245, 230, 95, 0.75)'); - } else { - Doc.ActiveTool = InkTool.Pen; - } - SetActiveArrowStart(this._head[i]); - SetActiveArrowEnd(this._end[i]); - SetActiveBezierApprox('300'); - - if (GestureOverlay.Instance) GestureOverlay.Instance.InkShape = this._shapePrims[i]; - } else { - this._selectedPrimitive = this._shapePrims.length; - Doc.ActiveTool = InkTool.None; - SetActiveArrowStart(''); - SetActiveArrowEnd(''); - if (GestureOverlay.Instance) GestureOverlay.Instance.InkShape = undefined; - SetActiveBezierApprox('0'); - } - e.stopPropagation(); - }); - return ( - <div className="btn-draw" key="draw"> - {this._draw.map((icon, i) => ( - <Tooltip key={icon} title={<div className="dash-tooltip">{this._title[i]}</div>} placement="bottom"> - <button className="antimodeMenu-button" onPointerDown={e => func(e, i, false)} onDoubleClick={e => func(e, i, true)} style={{ backgroundColor: i === this._selectedPrimitive ? '525252' : '', fontSize: '20' }}> - <FontAwesomeIcon icon={this._faName[i] as IconProp} size="sm" /> - </button> - </Tooltip> - ))} - </div> - ); - } - - toggleButton = (key: string, value: boolean, setter: () => {}, icon: FontAwesomeIconProps['icon'], ele: JSX.Element | null) => { - return ( - <Tooltip title={<div className="dash-tooltip">{key}</div>} placement="bottom"> - <button className="antimodeMenu-button" key={key} onPointerDown={action(e => setter())} style={{ backgroundColor: value ? '121212' : '' }}> - <FontAwesomeIcon icon={icon} size="lg" /> - {ele} - </button> - </Tooltip> - ); - }; - - @computed get widthPicker() { - const widthPicker = this.toggleButton('stroke width', this._widthBtn, () => (this._widthBtn = !this._widthBtn), 'bars', null); - return !this._widthBtn ? ( - widthPicker - ) : ( - <div className="btn2-group" key="width"> - {widthPicker} - {this._width.map((wid, i) => ( - <Tooltip title={<div className="dash-tooltip">change width</div>} placement="bottom"> - <button - className="antimodeMenu-button" - key={wid} - onPointerDown={action(() => { - SetActiveInkWidth(wid); - this._widthBtn = false; - this.editProperties(wid, 'width'); - })} - style={{ backgroundColor: this._widthBtn ? '121212' : '', zIndex: 1001, fontSize: this._dotsize[i], padding: 0, textAlign: 'center' }}> - • - </button> - </Tooltip> - ))} - </div> - ); - } - - @computed get colorPicker() { - const colorPicker = this.toggleButton('stroke color', this._colorBtn, () => (this._colorBtn = !this._colorBtn), 'pen-nib', <div className="color-previewI" style={{ backgroundColor: ActiveInkColor() ?? '121212' }} />); - return !this._colorBtn ? ( - colorPicker - ) : ( - <div className="btn-group" key="color"> - {colorPicker} - {this._palette.map(color => ( - <button - className="antimodeMenu-button" - key={color} - onPointerDown={action(() => { - this.changeColor(color, 'color'); - this._colorBtn = false; - this.editProperties(color, 'color'); - })} - style={{ backgroundColor: this._colorBtn ? '121212' : '', zIndex: 1001 }}> - {/* <FontAwesomeIcon icon="pen-nib" size="lg" /> */} - <div className="color-previewII" style={{ backgroundColor: color }}> - {color === '' ? <p style={{ fontSize: 40, color: 'red', marginTop: -10, marginLeft: -5, position: 'fixed' }}>☒</p> : ''} - </div> - </button> - ))} - </div> - ); - } - @computed get fillPicker() { - const fillPicker = this.toggleButton('shape fill color', this._fillBtn, () => (this._fillBtn = !this._fillBtn), 'fill-drip', <div className="color-previewI" style={{ backgroundColor: ActiveFillColor() ?? '121212' }} />); - return !this._fillBtn ? ( - fillPicker - ) : ( - <div className="btn-group" key="fill"> - {fillPicker} - {this._palette.map(color => ( - <button - className="antimodeMenu-button" - key={color} - onPointerDown={action(() => { - this.changeColor(color, 'fill'); - this._fillBtn = false; - this.editProperties(color, 'fill'); - })} - style={{ backgroundColor: this._fillBtn ? '121212' : '', zIndex: 1001 }}> - <div className="color-previewII" style={{ backgroundColor: color }}> - {color === '' ? <p style={{ fontSize: 40, color: 'red', marginTop: -10, marginLeft: -5, position: 'fixed' }}>☒</p> : ''} - </div> - </button> - ))} - </div> - ); - } - - render() { - return !this.props.docView.layoutDoc ? null : ( - <div className="collectionFreeFormMenu-cont"> - <RichTextMenu key="rich" /> - {!this.isText ? ( - <> - {this.drawButtons} - {this.widthPicker} - {this.colorPicker} - {this.fillPicker} - {Doc.noviceMode || this.props.isDoc ? null : ( - <> - <Tooltip key="back" title={<div className="dash-tooltip">Back Frame</div>} placement="bottom"> - <div className="backKeyframe" onClick={this.prevKeyframe}> - <FontAwesomeIcon icon={'caret-left'} size={'lg'} /> - </div> - </Tooltip> - <Tooltip key="num" title={<div className="dash-tooltip">Frame number</div>} placement="bottom"> - <div - className="numKeyframe" - style={{ color: this.props.docView.ComponentView?.getKeyFrameEditing?.() ? 'white' : 'black', backgroundColor: this.props.docView.ComponentView?.getKeyFrameEditing?.() ? '#5B9FDD' : '#AEDDF8' }} - onClick={action(() => this.props.docView.ComponentView?.setKeyFrameEditing?.(!this.props.docView.ComponentView?.getKeyFrameEditing?.()))}> - {NumCast(this.document._currentFrame)} - </div> - </Tooltip> - <Tooltip key="fwd" title={<div className="dash-tooltip">Forward Frame</div>} placement="bottom"> - <div className="fwdKeyframe" onClick={this.nextKeyframe}> - <FontAwesomeIcon icon={'caret-right'} size={'lg'} /> - </div> - </Tooltip> - </> - )} - </> - ) : null} - {!this.selectedDocumentView?.ComponentView?.menuControls ? null : this.selectedDocumentView?.ComponentView?.menuControls?.()} - </div> - ); - } -} -@observer -export class CollectionStackingViewChrome extends React.Component<CollectionViewMenuProps> { - @observable private _currentKey: string = ''; - @observable private suggestions: string[] = []; - - get document() { - return this.props.docView.props.Document; - } - - @computed private get descending() { - return StrCast(this.document._columnsSort) === 'descending'; - } - @computed get pivotField() { - return StrCast(this.document._pivotField); - } - - getKeySuggestions = async (value: string): Promise<string[]> => { - const val = value.toLowerCase(); - const docs = DocListCast(this.document[this.props.fieldKey]); - - if (Doc.noviceMode) { - if (docs instanceof Doc) { - const keys = Object.keys(docs).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('author_date') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_')); - return keys.filter(key => key.toLowerCase().indexOf(val) > -1); - } - const keys = new Set<string>(); - docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); - const noviceKeys = Array.from(keys).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('author_date') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_')); - return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1); - } - - if (docs instanceof Doc) { - return Object.keys(docs).filter(key => key.toLowerCase().indexOf(val) > -1); - } else { - const keys = new Set<string>(); - docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); - return Array.from(keys).filter(key => key.toLowerCase().indexOf(val) > -1); - } - }; - - @action - onKeyChange = (e: React.ChangeEvent, { newValue }: { newValue: string }) => { - this._currentKey = newValue; - }; - - getSuggestionValue = (suggestion: string) => suggestion; - - renderSuggestion = (suggestion: string) => { - return <p>{suggestion}</p>; - }; - - onSuggestionFetch = async ({ value }: { value: string }) => { - const sugg = await this.getKeySuggestions(value); - runInAction(() => { - this.suggestions = sugg; - }); - }; - - @action - onSuggestionClear = () => { - this.suggestions = []; - }; - - @action - setValue = (value: string) => { - this.document._pivotField = value; - return true; - }; - - @action toggleSort = () => { - this.document._columnsSort = this.document._columnsSort === 'descending' ? 'ascending' : this.document._columnsSort === 'ascending' ? undefined : 'descending'; - }; - @action resetValue = () => { - this._currentKey = this.pivotField; - }; - - render() { - const doctype = this.props.docView.Document.type; - const isPres: boolean = doctype === DocumentType.PRES; - return isPres ? null : ( - <div className="collectionStackingViewChrome-cont"> - <div className="collectionStackingViewChrome-pivotField-cont"> - <div className="collectionStackingViewChrome-pivotField-label">GROUP BY:</div> - <div className="collectionStackingViewChrome-sortIcon" onClick={this.toggleSort} style={{ transform: `rotate(${this.descending ? '180' : '0'}deg)` }}> - <FontAwesomeIcon icon="caret-up" size="2x" color="white" /> - </div> - <div className="collectionStackingViewChrome-pivotField"> - <EditableView - GetValue={() => this.pivotField} - autosuggestProps={{ - resetValue: this.resetValue, - value: this._currentKey, - onChange: this.onKeyChange, - autosuggestProps: { - inputProps: { - value: this._currentKey, - onChange: this.onKeyChange, - }, - getSuggestionValue: this.getSuggestionValue, - suggestions: this.suggestions, - alwaysRenderSuggestions: true, - renderSuggestion: this.renderSuggestion, - onSuggestionsFetchRequested: this.onSuggestionFetch, - onSuggestionsClearRequested: this.onSuggestionClear, - }, - }} - oneLine - SetValue={this.setValue} - contents={this.pivotField ? this.pivotField : 'N/A'} - /> - </div> + <div className="collectionViewBaseChrome">{!this._buttonizableCommands ? null : this.templateChrome}</div> </div> </div> ); @@ -1230,123 +564,6 @@ export class CollectionNoteTakingViewChrome extends React.Component<CollectionVi } } -@observer -export class CollectionSchemaViewChrome extends React.Component<CollectionViewMenuProps> { - // private _textwrapAllRows: boolean = Cast(this.document.textwrappedSchemaRows, listSpec("string"), []).length > 0; - get document() { - return this.props.docView.props.Document; - } - - @undoBatch - togglePreview = () => { - const dividerWidth = 4; - const borderWidth = 0; - const panelWidth = this.props.docView.props.PanelWidth(); - const previewWidth = NumCast(this.document.schema_previewWidth); - const tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth; - this.document.schema_previewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0; - }; - - @undoBatch - @action - toggleTextwrap = async () => { - const textwrappedRows = Cast(this.document.textwrappedSchemaRows, listSpec('string'), []); - if (textwrappedRows.length) { - this.document.textwrappedSchemaRows = new List<string>([]); - } else { - const docs = DocListCast(this.document[this.props.fieldKey]); - const allRows = docs instanceof Doc ? [docs[Id]] : docs.map(doc => doc[Id]); - this.document.textwrappedSchemaRows = new List<string>(allRows); - } - }; - - render() { - const previewWidth = NumCast(this.document.schema_previewWidth); - const textWrapped = Cast(this.document.textwrappedSchemaRows, listSpec('string'), []).length > 0; - - return ( - <div className="collectionSchemaViewChrome-cont"> - <div className="collectionSchemaViewChrome-toggle"> - <div className="collectionSchemaViewChrome-label">Show Preview: </div> - <div className="collectionSchemaViewChrome-toggler" onClick={this.togglePreview}> - <div className={'collectionSchemaViewChrome-togglerButton' + (previewWidth !== 0 ? ' on' : ' off')}>{previewWidth !== 0 ? 'on' : 'off'}</div> - </div> - </div> - </div> - ); - } -} - -@observer -export class CollectionTreeViewChrome extends React.Component<CollectionViewMenuProps> { - get document() { - return this.props.docView.props.Document; - } - get sortAscending() { - return this.document[this.props.fieldKey + '-sortAscending']; - } - set sortAscending(value) { - this.document[this.props.fieldKey + '-sortAscending'] = value; - } - @computed private get ascending() { - return Cast(this.sortAscending, 'boolean', null); - } - - @action toggleSort = () => { - if (this.sortAscending) this.sortAscending = undefined; - else if (this.sortAscending === undefined) this.sortAscending = false; - else this.sortAscending = true; - }; - - render() { - return ( - <div className="collectionTreeViewChrome-cont"> - <button className="collectionTreeViewChrome-sort" onClick={this.toggleSort}> - <div className="collectionTreeViewChrome-sortLabel">Sort</div> - <div className="collectionTreeViewChrome-sortIcon" style={{ transform: `rotate(${this.ascending === undefined ? '90' : this.ascending ? '180' : '0'}deg)` }}> - <FontAwesomeIcon icon="caret-up" size="2x" color="white" /> - </div> - </button> - </div> - ); - } -} - -// Enter scroll speed for 3D Carousel -@observer -export class Collection3DCarouselViewChrome extends React.Component<CollectionViewMenuProps> { - get document() { - return this.props.docView.props.Document; - } - @computed get scrollSpeed() { - return this.document._autoScrollSpeed; - } - - @action - setValue = (value: string) => { - const numValue = Number(StrCast(value)); - if (numValue > 0) { - this.document._autoScrollSpeed = numValue; - return true; - } - return false; - }; - - render() { - return ( - <div className="collection3DCarouselViewChrome-cont"> - <div className="collection3DCarouselViewChrome-scrollSpeed-cont"> - {/* {FormattedTextBox.Focused ? <RichTextMenu /> : null} */} - <div className="collectionStackingViewChrome-scrollSpeed-label">AUTOSCROLL SPEED:</div> - <div className="collection3DCarouselViewChrome-scrollSpeed"> - <EditableView GetValue={() => StrCast(this.scrollSpeed)} oneLine SetValue={this.setValue} contents={this.scrollSpeed ? this.scrollSpeed : 1000} /> - </div> - </div> - </div> - ); - } -} - /** * Chrome for grid view. */ @@ -1492,12 +709,6 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewMenu <input className="collectionGridViewChrome-columnButton" onClick={this.onIncrementButtonClick} onMouseEnter={this.incrementValue} onMouseLeave={this.decrementValue} type="button" value="↑" /> <input className="collectionGridViewChrome-columnButton" style={{ marginRight: 5 }} onClick={this.onDecrementButtonClick} onMouseEnter={this.decrementValue} onMouseLeave={this.incrementValue} type="button" value="↓" /> </span> - {/* <span className="grid-control"> - <span className="grid-icon"> - <FontAwesomeIcon icon="text-height" size="1x" /> - </span> - <input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.document.rowHeight as string} onKeyDown={this.onRowHeightEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} /> - </span> */} <span className="grid-control" style={{ width: this.resize ? '12%' : '20%' }}> <input type="checkbox" style={{ marginRight: 5 }} onChange={this.toggleCollisions} checked={!this.document.gridPreventCollision} /> <label className="flexLabel">{this.resize ? 'Coll' : 'Collisions'}</label> @@ -1526,6 +737,3 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewMenu ); } } -ScriptingGlobals.add(function gotoFrame(doc: any, newFrame: any) { - CollectionFreeFormViewChrome.gotoKeyFrame(doc, newFrame); -}); |
