import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, HeightSym, Opt, WidthSym } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnTrue, Utils } from '../../../../Utils'; import { DocUtils } from '../../../documents/Documents'; import { CurrentUserUtils } from '../../../util/CurrentUserUtils'; import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager } from '../../../util/DragManager'; import { Transform } from '../../../util/Transform'; import { Colors, Shadows } from '../../global/globalEnums'; import { AudioBox } from '../../nodes/AudioBox'; import { DocumentLinksButton } from '../../nodes/DocumentLinksButton'; import { DocumentView } from '../../nodes/DocumentView'; import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup'; import { StyleProp } from '../../StyleProvider'; import { CollectionStackedTimeline } from '../CollectionStackedTimeline'; import { CollectionSubView } from '../CollectionSubView'; import { CollectionViewType } from '../CollectionView'; import "./CollectionLinearView.scss"; /** * CollectionLinearView is the class for rendering the horizontal collection * of documents, it useful for horizontal menus. It can either be expandable * or not using the linearViewExpandable field. * It is used in the following locations: * - It is used in the popup menu on the bottom left (see docButtons() in MainView.tsx) * - It is used for the context sensitive toolbar at the top (see contMenuButtons() in CollectionMenu.tsx) */ @observer export class CollectionLinearView extends CollectionSubView() { @observable public addMenuToggle = React.createRef(); @observable private _selectedIndex = -1; private _dropDisposer?: DragManager.DragDropDisposer; private _widthDisposer?: IReactionDisposer; private _selectedDisposer?: IReactionDisposer; componentWillUnmount() { this._dropDisposer?.(); this._widthDisposer?.(); this._selectedDisposer?.(); this.childLayoutPairs.map((pair, ind) => ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log)); } componentDidMount() { this._widthDisposer = reaction(() => 5 + (this.layoutDoc.linearViewIsExpanded ? this.childDocs.length * (this.rootDoc[HeightSym]()) : 10), width => this.childDocs.length && (this.layoutDoc._width = width), { fireImmediately: true } ); this._selectedDisposer = reaction( () => NumCast(this.layoutDoc.selectedIndex), (i) => runInAction(() => { this._selectedIndex = i; let selected: any = undefined; this.childLayoutPairs.map(async (pair, ind) => { const isSelected = this._selectedIndex === ind; if (isSelected) { selected = pair; } else { ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log); } }); if (selected && selected.layout) { ScriptCast(selected.layout.proto?.onPointerDown)?.script.run({ this: selected.layout.proto }, console.log); } }), { fireImmediately: true } ); } protected createDashEventsTarget = (ele: HTMLDivElement | null) => { //used for stacking and masonry view this._dropDisposer && this._dropDisposer(); if (ele) { this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); } } dimension = () => NumCast(this.rootDoc._height); // 2 * the padding getTransform = (ele: Opt) => { if (!ele) return Transform.Identity(); const { scale, translateX, translateY } = Utils.GetScreenTransform(ele); return new Transform(-translateX, -translateY, 1); } @action exitLongLinks = () => { if (DocumentLinksButton.StartLink) { if (DocumentLinksButton.StartLink.Document) { action((e: React.PointerEvent) => { Doc.UnBrushDoc(DocumentLinksButton.StartLink?.Document as Doc); }); } } DocumentLinksButton.StartLink = undefined; DocumentLinksButton.StartLinkView = undefined; } @action changeDescriptionSetting = () => { if (LinkDescriptionPopup.showDescriptions) { if (LinkDescriptionPopup.showDescriptions === "ON") { LinkDescriptionPopup.showDescriptions = "OFF"; LinkDescriptionPopup.descriptionPopup = false; } else { LinkDescriptionPopup.showDescriptions = "ON"; } } else { LinkDescriptionPopup.showDescriptions = "OFF"; LinkDescriptionPopup.descriptionPopup = false; } } myContextMenu = (e: React.MouseEvent) => { e.stopPropagation(); e.preventDefault(); } getDisplayDoc = (doc: Doc, preview: boolean = false) => { const nested = doc._viewType === CollectionViewType.Linear; const hidden = doc.hidden === true; let dref: Opt; const docXf = () => this.getTransform(dref); // const scalable = pair.layout.onClick || pair.layout.onDragStart; return hidden ? (null) :
dref = r || undefined} style={{ pointerEvents: "all", width: nested ? undefined : NumCast(doc._width), height: nested ? undefined : NumCast(doc._height), marginLeft: !nested ? 2.5 : 0, marginRight: !nested ? 2.5 : 0, // width: NumCast(pair.layout._width), // height: NumCast(pair.layout._height), }} >
; } render() { const guid = Utils.GenerateGuid(); // Generate a unique ID to use as the label const flexDir: any = StrCast(this.Document.flexDirection); // Specify direction of linear view content const flexGap: number = NumCast(this.Document.flexGap); // Specify the gap between linear view content const expandable: boolean = BoolCast(this.props.Document.linearViewExpandable); // Specify whether it is expandable or not const floating: boolean = BoolCast(this.props.Document.linearViewFloating); // Specify whether it is expandable or not const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); const icon: string = StrCast(this.props.Document.icon); // Menu opener toggle const menuOpener = ; return
{!expandable ? (null) :
{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close" : "Open"}
} placement="top"> {menuOpener}
} this.props.Document.linearViewIsExpanded = this.addMenuToggle.current!.checked)} />
{this.childLayoutPairs.map(pair => this.getDisplayDoc(pair.layout))}
{!DocumentLinksButton.StartLink || this.layoutDoc !== CurrentUserUtils.MyDockedBtns ? null : e.stopPropagation()} > Creating link from: {DocumentLinksButton.AnnotationId ? "Annotation in " : " "} {StrCast(DocumentLinksButton.StartLink.title).length < 51 ? DocumentLinksButton.StartLink.title : StrCast(DocumentLinksButton.StartLink.title).slice(0, 50) + '...'}
{"Toggle description pop-up"}
} placement="top"> Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
Exit linking mode
} placement="top"> Stop
} {!CollectionStackedTimeline.CurrentlyPlaying || !CollectionStackedTimeline.CurrentlyPlaying.length || this.layoutDoc !== CurrentUserUtils.MyDockedBtns ? (null) : Currently playing: {CollectionStackedTimeline.CurrentlyPlaying.map((clip, i) => DocumentManager.Instance.jumpToDocument(clip, true, undefined, [])}> {clip.title + (i === CollectionStackedTimeline.CurrentlyPlaying.length - 1 ? "" : ",")} )} }
; } }