diff options
Diffstat (limited to 'src/client/views')
| -rw-r--r-- | src/client/views/collections/TabDocView.tsx | 9 | ||||
| -rw-r--r-- | src/client/views/collections/TreeView.tsx | 54 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 3 | ||||
| -rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 13 | ||||
| -rw-r--r-- | src/client/views/nodes/trails/PresElementBox.scss | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/trails/PresElementBox.tsx | 4 | 
6 files changed, 50 insertions, 35 deletions
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index bd3e810c9..136486f47 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -33,6 +33,7 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV  import { CollectionView, CollectionViewType } from './CollectionView';  import "./TabDocView.scss";  import React = require("react"); +import { List } from '../../../fields/List';  const _global = (window /* browser */ || global /* node */) as any;  interface TabDocViewProps { @@ -209,9 +210,17 @@ export class TabDocView extends React.Component<TabDocViewProps> {              const pinDoc = Doc.MakeAlias(doc);              pinDoc.presentationTargetDoc = doc;              pinDoc.title = doc.title + " - Slide"; +            pinDoc.data = new List<Doc>();  // the children of the alias' layout are the presentation slide children.  the alias' data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data              pinDoc.presMovement = PresMovement.Zoom;              pinDoc.groupWithUp = false;              pinDoc.context = curPres; +            // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements.  That way the PresBox could configure all of its children at render time +            pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area +            pinDoc.treeViewHeaderWidth = "100%"; // forces the header to grow to be the same size as its largest sibling. +            pinDoc.treeViewFieldKey = "data"; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field +            pinDoc.treeViewExpandedView = "data";// in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view +            pinDoc.treeViewGrowsHorizontally = true;// the document can expand horizontally when displayed as a tree view header   +            pinDoc.treeViewHideHeader = true;  // this will force the document to render itself as the tree view header              const presArray: Doc[] = PresBox.Instance?.sortArray();              const size: number = PresBox.Instance?._selectedArray.size;              const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index c2d0983da..a35304787 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -112,7 +112,7 @@ export class TreeView extends React.Component<TreeViewProps> {      @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containerCollection.maxEmbedHeight, 200); }      @computed get dataDoc() { return this.doc[DataSym]; }      @computed get layoutDoc() { return Doc.Layout(this.doc); } -    @computed get fieldKey() { return Doc.LayoutFieldKey(this.doc); } +    @computed get fieldKey() { return StrCast(this.doc._treeViewFieldKey, Doc.LayoutFieldKey(this.doc)); }      @computed get childDocs() { return this.childDocList(this.fieldKey); }      @computed get childLinks() { return this.childDocList("links"); }      @computed get childAliases() { return this.childDocList("aliases"); } @@ -156,18 +156,7 @@ export class TreeView extends React.Component<TreeViewProps> {              docView.select(false);          }      } -    @action -    openLevel = (docView: DocumentView) => { -        if (this.props.document.isFolder || Doc.IsSystem(this.props.document)) { -            this.treeViewOpen = !this.treeViewOpen; -        } else { -            // choose an appropriate alias or make one. --- choose the first alias that (1) user owns,  (2) has no context field ... otherwise make a new alias -            // this.props.addDocTab(CurrentUserUtils.ActiveDashboard.isShared ? Doc.MakeAlias(this.props.document) : this.props.document, "add:right"); -            const bestAlias = DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail); -            this.props.addDocTab(bestAlias ?? Doc.MakeAlias(this.props.document), "add:right"); -        } -    }      constructor(props: any) {          super(props);          if (!TreeView._openLevelScript) { @@ -379,8 +368,14 @@ export class TreeView extends React.Component<TreeViewProps> {          return rows;      } -    rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), (this.props.panelWidth() - treeBulletWidth())) / (this.props.treeView.props.scaling?.() || 1); -    rtfHeight = () => this.rtfWidth() <= this.layoutDoc?.[WidthSym]() ? Math.min(this.layoutDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; +    rtfWidth = () => { +        const layout = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ""))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc; +        return Math.min(layout[WidthSym](), (this.props.panelWidth() - treeBulletWidth())) / (this.props.treeView.props.scaling?.() || 1); +    } +    rtfHeight = () => { +        const layout = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document, ""))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc; +        return this.rtfWidth() <= layout[WidthSym]() ? Math.min(layout[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; +    }      rtfOutlineHeight = () => Math.max(this.layoutDoc?.[HeightSym](), treeBulletWidth());      expandPanelHeight = () => {          if (this.layoutDoc._fitWidth) return this.docHeight(); @@ -580,13 +575,20 @@ export class TreeView extends React.Component<TreeViewProps> {      }      onKeyDown = (e: React.KeyboardEvent) => {          if (this.doc.treeViewHideHeader || this.props.treeView.outlineMode) { -            e.stopPropagation(); -            e.preventDefault();              switch (e.key) { -                case "Tab": setTimeout(() => RichTextMenu.Instance.TextView?.EditorView?.focus(), 150); +                case "Tab": +                    e.stopPropagation(); +                    e.preventDefault(); +                    setTimeout(() => RichTextMenu.Instance.TextView?.EditorView?.focus(), 150);                      return UndoManager.RunInBatch(() => e.shiftKey ? this.props.outdentDocument?.(true) : this.props.indentDocument?.(true), "tab"); -                case "Backspace": return !(this.doc.text as RichTextField)?.Text && this.props.removeDoc?.(this.doc); -                case "Enter": return UndoManager.RunInBatch(this.makeTextCollection, "bullet"); +                case "Backspace": +                    e.stopPropagation(); +                    e.preventDefault(); +                    return !(this.doc.text as RichTextField)?.Text && this.props.removeDoc?.(this.doc); +                case "Enter": +                    e.stopPropagation(); +                    e.preventDefault(); +                    return UndoManager.RunInBatch(this.makeTextCollection, "bullet");              }          }      } @@ -691,7 +693,7 @@ export class TreeView extends React.Component<TreeViewProps> {      renderBulletHeader = (contents: JSX.Element, editing: boolean) => {          return <>              <div className={`treeView-header` + (editing ? "-editing" : "")} key="titleheader" -                style={{ width: "max-content" }} +                style={{ width: StrCast(this.doc.treeViewHeaderWidth, "max-content") }}                  ref={this._header}                  onClick={this.ignoreEvent}                  onPointerDown={this.ignoreEvent} @@ -705,8 +707,7 @@ export class TreeView extends React.Component<TreeViewProps> {      renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => { -        const layout = StrCast(Doc.LayoutField(this.layoutDoc)); -        const isExpandable = layout.includes(FormattedTextBox.name) || layout.includes(SliderBox.name); +        const isExpandable = this.doc._treeViewGrowsHorizontally;          const panelWidth = asText || isExpandable ? this.rtfWidth : this.expandPanelWidth;          const panelHeight = asText ? this.rtfOutlineHeight : isExpandable ? this.rtfHeight : this.expandPanelHeight;          return <DocumentView key={this.doc[Id]} ref={action((r: DocumentView | null) => this._dref = r)} @@ -717,6 +718,7 @@ export class TreeView extends React.Component<TreeViewProps> {              NativeWidth={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfWidth : undefined}              NativeHeight={!asText && (this.layoutDoc.type === DocumentType.RTF || this.layoutDoc.type === DocumentType.SLIDER) ? this.rtfHeight : undefined}              LayoutTemplateString={asText ? FormattedTextBox.LayoutString("text") : undefined} +            LayoutTemplate={this.props.treeView.props.childLayoutTemplate}              isContentActive={isActive}              isDocumentActive={isActive}              styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider} @@ -759,10 +761,10 @@ export class TreeView extends React.Component<TreeViewProps> {      }      // renders the document in the header field instead of a text proxy. -    @computed get renderDocumentAsHeader() { +    renderDocumentAsHeader = (asText: boolean) => {          return <>              {this.renderBullet} -            {this.renderEmbeddedDocument(true, this.props.isContentActive)} +            {this.renderEmbeddedDocument(asText, this.props.isContentActive)}          </>;      } @@ -794,9 +796,9 @@ export class TreeView extends React.Component<TreeViewProps> {                  //onPointerDown={e => this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document                  onKeyDown={this.onKeyDown}>                  <li className="collection-child"> -                    {hideTitle && this.doc.type !== DocumentType.RTF ? +                    {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeViewRenderAsBulletHeader ? // should test for prop 'treeViewRenderDocWithBulletAsHeader"                          this.renderEmbeddedDocument(false, returnFalse) : -                        this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader : this.renderTitleAsHeader, this._editTitle)} +                        this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader(!this.doc.treeViewRenderAsBulletHeader) : this.renderTitleAsHeader, this._editTitle)}                  </li>              </div>;      } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1eaff3c1c..bcf00e88d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1308,6 +1308,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {          TraceMobx();          const xshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined);          const yshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined); +        const isPresTreeElement: boolean = this.props.treeViewDoc?.type === DocumentType.PRES;          const isButton: boolean = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear;          return (<div className="contentFittingDocumentView">              {!this.props.Document || !this.props.PanelWidth() ? (null) : ( @@ -1316,7 +1317,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {                          transition: this.props.dataTransition,                          position: this.props.Document.isInkMask ? "absolute" : undefined,                          transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`, -                        width: isButton ? "100%" : xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`, +                        width: isButton || isPresTreeElement ? "100%" : xshift() ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`,                          height: (!this.props.ignoreAutoHeight && this.layoutDoc.autoHeight && this.layoutDoc.type === DocumentType.RTF) || isButton || this.props.forceAutoHeight ? undefined : yshift() ?? (this.fitWidth ? `${this.panelHeight}px` :                              `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`),                      }}> diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 2e312ee51..c9c74eca4 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -122,7 +122,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {          if (Doc.UserDoc().activePresentation = this.rootDoc) runInAction(() => PresBox.Instance = this);          if (!this.presElement) { // create exactly one presElmentBox template to use by any and all presentations.              Doc.UserDoc().presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ -                title: "pres element template", type: DocumentType.PRESELEMENT, _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data" +                title: "pres element template", type: DocumentType.PRESELEMENT, _fitWidth: true, _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data"              }));              // this script will be called by each presElement to get rendering-specific info that the PresBox knows about but which isn't written to the PresElement              // this is a design choice -- we could write this data to the presElements which would require a reaction to keep it up to date, and it would prevent @@ -308,7 +308,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {              }              if (!group) this._selectedArray.clear();              this.childDocs[index] && this._selectedArray.set(this.childDocs[index], undefined); //Update selected array -            if (this.layoutDoc._viewType === "stacking" && !group) this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list +            if ([CollectionViewType.Stacking, CollectionViewType.Tree].includes(this.layoutDoc._viewType as any) && !group) this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list              this.onHideDocument(); //Handles hide after/before          }      }); @@ -620,9 +620,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {          //@ts-ignore          const viewType = e.target.selectedOptions[0].value as CollectionViewType;          // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here -        viewType === CollectionViewType.Stacking && (this.rootDoc._pivotField = undefined); +        [CollectionViewType.Tree || CollectionViewType.Stacking].includes(viewType) && (this.rootDoc._pivotField = undefined);          this.rootDoc._viewType = viewType; -        if (viewType === CollectionViewType.Stacking) this.layoutDoc._gridGap = 0; +        if ([CollectionViewType.Tree || CollectionViewType.Stacking].includes(viewType)) this.layoutDoc._gridGap = 0;      });      /** @@ -696,7 +696,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {          });          return true;      } -    childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement; +    childLayoutTemplate = () => ![CollectionViewType.Stacking, CollectionViewType.Tree].includes(this.rootDoc._viewType as any) ? undefined : this.presElement;      removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc);      getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight      panelHeight = () => this.props.PanelHeight() - 40; @@ -2262,6 +2262,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {                      onChange={this.viewChanged}                      value={mode}>                      <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Stacking}>List</option> +                    <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Tree}>Tree</option>                      <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Carousel3D}>3D Carousel</option>                  </select>}                  <div className="presBox-presentPanel" style={{ opacity: this.childDocs.length ? 1 : 0.3 }}> @@ -2459,7 +2460,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {  }  ScriptingGlobals.add(function lookupPresBoxField(container: Doc, field: string, data: Doc) {      if (field === 'indexInPres') return DocListCast(container[StrCast(container.presentationFieldKey)]).indexOf(data); -    if (field === 'presCollapsedHeight') return container._viewType === CollectionViewType.Stacking ? 35 : 31; +    if (field === 'presCollapsedHeight') return [CollectionViewType.Tree || CollectionViewType.Stacking].includes(container._viewType as any) ? 35 : 31;      if (field === 'presStatus') return container.presStatus;      if (field === '_itemIndex') return container._itemIndex;      if (field === 'presBox') return container; diff --git a/src/client/views/nodes/trails/PresElementBox.scss b/src/client/views/nodes/trails/PresElementBox.scss index 1ad4b820e..a178be910 100644 --- a/src/client/views/nodes/trails/PresElementBox.scss +++ b/src/client/views/nodes/trails/PresElementBox.scss @@ -42,7 +42,7 @@ $slide-active: #5B9FDD;      background-color: #d5dce2;      border-radius: 5px;      height: calc(100% - 7px); -    width: calc(100% - 15px); +    width: 100%;      display: grid;      grid-template-rows: 16px 10px auto;      grid-template-columns: max-content max-content max-content max-content auto; diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index a4ec559f5..5c16d743a 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -23,6 +23,7 @@ import { PresBox } from "./PresBox";  import "./PresElementBox.scss";  import { PresMovement } from "./PresEnums";  import React = require("react"); +import { CollectionViewType } from "../../collections/CollectionView";  /**   * This class models the view a document added to presentation will have in the presentation.   * It involves some functionality for its buttons and options. @@ -87,6 +88,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {                      isContentActive={this.props.isContentActive}                      addDocTab={returnFalse}                      pinToPres={returnFalse} +                    fitContentsToDoc={returnTrue}                      PanelWidth={this.embedWidth}                      PanelHeight={this.embedHeight}                      ScreenToLocalTransform={Transform.Identity} @@ -321,7 +323,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {                          backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),                          boxShadow: presBoxColor && presBoxColor !== "white" && presBoxColor !== "transparent" ? isSelected ? "0 0 0px 1.5px" + presBoxColor : undefined : undefined                      }}> -                    <div className="presItem-name" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105, cursor: isSelected ? 'text' : 'grab' }}> +                    <div className="presItem-name" style={{ maxWidth: showMore ? (toolbarWidth - (this.presBox._viewType === CollectionViewType.Stacking ? 195 : 220)) : toolbarWidth - (this.presBox._viewType === CollectionViewType.Stacking ? 105 : 145), cursor: isSelected ? 'text' : 'grab' }}>                          <EditableView                              ref={this._titleRef}                              editing={!isSelected ? false : undefined}  | 
