diff options
| author | Bob Zeleznik <zzzman@gmail.com> | 2020-04-28 17:32:59 -0400 |
|---|---|---|
| committer | Bob Zeleznik <zzzman@gmail.com> | 2020-04-28 17:32:59 -0400 |
| commit | d020ab540abaf279414aa682c8930a4b280ace55 (patch) | |
| tree | 2cab1b330659a97664af86e34f52d2d1b0ed49e1 /src/client/views/collections/CollectionStackingView.tsx | |
| parent | 4ecf08b5c5cdc4ddb3a997e2f3a2188e921ff430 (diff) | |
| parent | 6b2896756c55727ed397c223187cb03fe8a51a59 (diff) | |
merged with master
Diffstat (limited to 'src/client/views/collections/CollectionStackingView.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionStackingView.tsx | 260 |
1 files changed, 146 insertions, 114 deletions
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index d772ace23..e3720bf01 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -9,60 +9,63 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; -import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from "../../../new_fields/Types"; -import { emptyFunction, Utils } from "../../../Utils"; -import { DragManager } from "../../util/DragManager"; +import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../new_fields/Types"; +import { TraceMobx } from "../../../new_fields/util"; +import { Utils, setupMoveUpEvents, emptyFunction, returnZero, returnOne } from "../../../Utils"; +import { DragManager, dropActionType } from "../../util/DragManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; +import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from "../ContextMenuItem"; import { EditableView } from "../EditableView"; import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView"; +import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow"; import "./CollectionStackingView.scss"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; import { CollectionSubView } from "./CollectionSubView"; -import { ContextMenu } from "../ContextMenu"; -import { ContextMenuProps } from "../ContextMenuItem"; -import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow"; -import { TraceMobx } from "../../../new_fields/util"; import { CollectionViewType } from "./CollectionView"; +import { SelectionManager } from "../../util/SelectionManager"; +const _global = (window /* browser */ || global /* node */) as any; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { _masonryGridRef: HTMLDivElement | null = null; _draggerRef = React.createRef<HTMLDivElement>(); - _heightDisposer?: IReactionDisposer; - _sectionFilterDisposer?: IReactionDisposer; + _pivotFieldDisposer?: IReactionDisposer; _docXfs: any[] = []; _columnStart: number = 0; @observable _heightMap = new Map<string, number>(); @observable _cursor: CursorProperty = "grab"; @observable _scroll = 0; // used to force the document decoration to update when scrolling @computed get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } - @computed get sectionFilter() { return StrCast(this.props.Document.sectionFilter); } - @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.isMinimized).map(pair => pair.layout); } + @computed get pivotField() { return StrCast(this.props.Document._pivotField); } + @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout); } @computed get xMargin() { return NumCast(this.props.Document._xMargin, 2 * Math.min(this.gridGap, .05 * this.props.PanelWidth())); } - @computed get yMargin() { return Math.max(this.props.Document.showTitle && !this.props.Document.showTitleHover ? 30 : 0, NumCast(this.props.Document._yMargin, 0)); } // 2 * this.gridGap)); } + @computed get yMargin() { return Math.max(this.props.Document._showTitle && !this.props.Document._showTitleHover ? 30 : 0, NumCast(this.props.Document._yMargin, 0)); } // 2 * this.gridGap)); } @computed get gridGap() { return NumCast(this.props.Document._gridGap, 10); } @computed get isStackingView() { return BoolCast(this.props.Document.singleColumn, true); } @computed get numGroupColumns() { return this.isStackingView ? Math.max(1, this.Sections.size + (this.showAddAGroup ? 1 : 0)) : 1; } - @computed get showAddAGroup() { return (this.sectionFilter && (this.props.Document._chromeStatus !== 'view-mode' && this.props.Document._chromeStatus !== 'disabled')); } + @computed get showAddAGroup() { return (this.pivotField && (this.props.Document._chromeStatus !== 'view-mode' && this.props.Document._chromeStatus !== 'disabled')); } @computed get columnWidth() { + TraceMobx(); return Math.min(this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin, - this.isStackingView ? Number.MAX_VALUE : NumCast(this.props.Document.columnWidth, 250)); + this.isStackingView ? Number.MAX_VALUE : this.props.Document.columnWidth === -1 ? this.props.PanelWidth() - 2 * this.xMargin : NumCast(this.props.Document.columnWidth, 250)); } @computed get NodeWidth() { return this.props.PanelWidth() - this.gridGap; } children(docs: Doc[], columns?: number) { + TraceMobx(); this._docXfs.length = 0; return docs.map((d, i) => { const height = () => this.getDocHeight(d); - const width = () => this.widthScale * Math.min(d._nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); + const width = () => this.getDocWidth(d); const dref = React.createRef<HTMLDivElement>(); const dxf = () => this.getDocTransform(d, dref.current!); this._docXfs.push({ dxf: dxf, width: width, height: height }); const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); - const style = this.isStackingView ? { width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` }; + const style = this.isStackingView ? { width: width(), marginTop: i ? this.gridGap : 0, height: height() } : { gridRowEnd: `span ${rowSpan}` }; return <div className={`collectionStackingView-${this.isStackingView ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} > - {this.getDisplayDoc(d, Cast(d.resolvedDataDoc, Doc, null) || this.props.DataDoc, dxf, width)} + {this.getDisplayDoc(d, (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc, dxf, width)} </div>; }); } @@ -72,73 +75,70 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } get Sections() { - if (!this.sectionFilter || this.sectionHeaders instanceof Promise) return new Map<SchemaHeaderField, Doc[]>(); + if (!this.pivotField || this.sectionHeaders instanceof Promise) return new Map<SchemaHeaderField, Doc[]>(); if (this.sectionHeaders === undefined) { setTimeout(() => this.props.Document.sectionHeaders = new List<SchemaHeaderField>(), 0); return new Map<SchemaHeaderField, Doc[]>(); } - const sectionHeaders = this.sectionHeaders; + const sectionHeaders: SchemaHeaderField[] = Array.from(this.sectionHeaders); const fields = new Map<SchemaHeaderField, Doc[]>(sectionHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); + let changed = false; this.filteredChildren.map(d => { - const sectionValue = (d[this.sectionFilter] ? d[this.sectionFilter] : `NO ${this.sectionFilter.toUpperCase()} VALUE`) as object; + const sectionValue = (d[this.pivotField] ? d[this.pivotField] : `NO ${this.pivotField.toUpperCase()} VALUE`) as object; // the next five lines ensures that floating point rounding errors don't create more than one section -syip const parsed = parseInt(sectionValue.toString()); const castedSectionValue = !isNaN(parsed) ? parsed : sectionValue; // look for if header exists already - const existingHeader = sectionHeaders.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.sectionFilter.toUpperCase()} VALUE`)); + const existingHeader = sectionHeaders.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`)); if (existingHeader) { fields.get(existingHeader)!.push(d); } else { - const newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.sectionFilter.toUpperCase()} VALUE`); + const newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`); fields.set(newSchemaHeader, [d]); sectionHeaders.push(newSchemaHeader); + changed = true; } }); + // remove all empty columns if hideHeadings is set + if (this.props.Document.hideHeadings) { + Array.from(fields.keys()).filter(key => !fields.get(key)!.length).map(header => { + fields.delete(header); + sectionHeaders.splice(sectionHeaders.indexOf(header), 1); + changed = true; + }); + } + changed && setTimeout(action(() => { if (this.sectionHeaders) { this.sectionHeaders.length = 0; this.sectionHeaders.push(...sectionHeaders); } }), 0); return fields; } + getSimpleDocHeight(d?: Doc) { + if (!d) return 0; + const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); + const nw = NumCast(layoutDoc._nativeWidth); + const nh = NumCast(layoutDoc._nativeHeight); + let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); + if (!layoutDoc._fitWidth && nw && nh) { + const aspect = nw && nh ? nh / nw : 1; + if (!(this.props.Document.fillColumn)) wid = Math.min(layoutDoc[WidthSym](), wid); + return wid * aspect; + } + return layoutDoc._fitWidth ? wid * NumCast(layoutDoc.scrollHeight, nh) / (nw || 1) : layoutDoc[HeightSym](); + } componentDidMount() { super.componentDidMount(); - this._heightDisposer = reaction(() => { - if (this.props.Document._autoHeight) { - const sectionsList = Array.from(this.Sections.size ? this.Sections.values() : [this.filteredChildren]); - if (this.isStackingView) { - const res = this.props.ContentScaling() * sectionsList.reduce((maxHght, s) => { - const r1 = Math.max(maxHght, - (this.Sections.size ? 50 : 0) + s.reduce((height, d, i) => { - const val = height + this.getDocHeight(d) + (i === s.length - 1 ? this.yMargin : this.gridGap); - return val; - }, this.yMargin)); - return r1; - }, 0); - return res; - } else { - const sum = Array.from(this._heightMap.values()).reduce((acc: number, curr: number) => acc += curr, 0); - return this.props.ContentScaling() * (sum + (this.Sections.size ? (this.props.Document.miniHeaders ? 20 : 85) : -15)); - } - } - return -1; - }, - (hgt: number) => { - const doc = hgt === -1 ? undefined : this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; - doc && hgt > 0 && (Doc.Layout(doc)._height = hgt); - }, - { fireImmediately: true } - ); // reset section headers when a new filter is inputted - this._sectionFilterDisposer = reaction( - () => this.sectionFilter, + this._pivotFieldDisposer = reaction( + () => this.pivotField, () => this.props.Document.sectionHeaders = new List() ); } componentWillUnmount() { super.componentWillUnmount(); - this._heightDisposer && this._heightDisposer(); - this._sectionFilterDisposer && this._sectionFilterDisposer(); + this._pivotFieldDisposer?.(); } @action @@ -153,67 +153,75 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); } @computed get onClickHandler() { return ScriptCast(this.Document.onChildClick); } + addDocTab = (doc: Doc, where: string) => { + if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { + this.dataDoc[this.props.fieldKey] = new List<Doc>([doc]); + return true; + } + return this.props.addDocTab(doc, where); + } getDisplayDoc(doc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) { - const layoutDoc = Doc.Layout(doc); + const layoutDoc = Doc.Layout(doc, this.props.childLayoutTemplate?.()); const height = () => this.getDocHeight(doc); return <ContentFittingDocumentView Document={doc} - DataDocument={dataDoc} + DataDocument={dataDoc || (doc[DataSym] !== doc && doc[DataSym])} + backgroundColor={this.props.backgroundColor} + LayoutDoc={this.props.childLayoutTemplate} LibraryPath={this.props.LibraryPath} + FreezeDimensions={this.props.freezeChildDimensions} renderDepth={this.props.renderDepth + 1} - fitToBox={this.props.fitToBox} - onClick={layoutDoc.isTemplateDoc ? this.onClickHandler : this.onChildClickHandler} PanelWidth={width} PanelHeight={height} + NativeHeight={returnZero} + NativeWidth={returnZero} + fitToBox={BoolCast(this.props.Document._freezeChildDimensions)} + rootSelected={this.rootSelected} + dropAction={StrCast(this.props.Document.childDropAction) as dropActionType} + onClick={layoutDoc.isTemplateDoc ? this.onClickHandler : this.onChildClickHandler} getTransform={dxf} focus={this.props.focus} - CollectionDoc={this.props.CollectionView && this.props.CollectionView.props.Document} + CollectionDoc={this.props.CollectionView?.props.Document} CollectionView={this.props.CollectionView} addDocument={this.props.addDocument} moveDocument={this.props.moveDocument} removeDocument={this.props.removeDocument} active={this.props.active} whenActiveChanged={this.props.whenActiveChanged} - addDocTab={this.props.addDocTab} - pinToPres={this.props.pinToPres}> - </ContentFittingDocumentView>; + addDocTab={this.addDocTab} + pinToPres={this.props.pinToPres} + />; + } + + getDocWidth(d?: Doc) { + if (!d) return 0; + const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); + const nw = NumCast(layoutDoc._nativeWidth); + return Math.min(nw && !this.props.Document.fillColumn ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); } getDocHeight(d?: Doc) { if (!d) return 0; - const layoutDoc = Doc.Layout(d); + const layoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); const nw = NumCast(layoutDoc._nativeWidth); const nh = NumCast(layoutDoc._nativeHeight); let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); - if (!layoutDoc.ignoreAspect && !layoutDoc._fitWidth && nw && nh) { + if (!layoutDoc._fitWidth && nw && nh) { const aspect = nw && nh ? nh / nw : 1; - if (!(d._nativeWidth && !layoutDoc.ignoreAspect && this.props.Document.fillColumn)) wid = Math.min(layoutDoc[WidthSym](), wid); + if (!(this.props.Document.fillColumn)) wid = Math.min(layoutDoc[WidthSym](), wid); return wid * aspect; } - return layoutDoc._fitWidth ? !layoutDoc._nativeHeight ? this.props.PanelHeight() - 2 * this.yMargin : - Math.min(wid * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth, 1), this.props.PanelHeight() - 2 * this.yMargin) : layoutDoc[HeightSym](); + return layoutDoc._fitWidth ? !nh ? this.props.PanelHeight() - 2 * this.yMargin : + Math.min(wid * NumCast(layoutDoc.scrollHeight, nh) / (nw || 1), this.props.PanelHeight() - 2 * this.yMargin) : layoutDoc[HeightSym](); } columnDividerDown = (e: React.PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); runInAction(() => this._cursor = "grabbing"); - document.addEventListener("pointermove", this.onDividerMove); - document.addEventListener('pointerup', this.onDividerUp); - this._columnStart = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; + setupMoveUpEvents(this, e, this.onDividerMove, action(() => this._cursor = "grab"), emptyFunction); } @action - onDividerMove = (e: PointerEvent): void => { - const dragPos = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; - const delta = dragPos - this._columnStart; - this._columnStart = dragPos; - this.layoutDoc.columnWidth = Math.max(10, this.columnWidth + delta); - } - - @action - onDividerUp = (e: PointerEvent): void => { - runInAction(() => this._cursor = "grab"); - document.removeEventListener("pointermove", this.onDividerMove); - document.removeEventListener('pointerup', this.onDividerUp); + onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => { + this.layoutDoc.columnWidth = Math.max(10, this.columnWidth + delta[0]); + return false; } @computed get columnDragger() { @@ -225,7 +233,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @undoBatch @action - drop = (e: Event, de: DragManager.DropEvent) => { + onInternalDrop = (e: Event, de: DragManager.DropEvent) => { const where = [de.x, de.y]; let targInd = -1; let plusOne = 0; @@ -239,7 +247,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { plusOne = where[axis] > (pos[axis] + pos1[axis]) / 2 ? 1 : 0; } }); - if (super.drop(e, de)) { + if (super.onInternalDrop(e, de)) { const newDoc = de.complete.docDragData.droppedDocuments[0]; const docs = this.childDocList; if (docs) { @@ -255,7 +263,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } @undoBatch @action - onDrop = async (e: React.DragEvent): Promise<void> => { + onExternalDrop = async (e: React.DragEvent): Promise<void> => { const where = [e.clientX, e.clientY]; let targInd = -1; this._docXfs.map((cd, i) => { @@ -265,7 +273,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { targInd = i; } }); - super.onDrop(e, {}, () => { + super.onExternalDrop(e, {}, () => { if (targInd !== -1) { const newDoc = this.childDocs[this.childDocs.length - 1]; const docs = this.childDocList; @@ -276,9 +284,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } }); } - headings = () => Array.from(this.Sections.keys()); + headings = () => Array.from(this.Sections); + refList: any[] = []; sectionStacking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { - const key = this.sectionFilter; + const key = this.pivotField; let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; const types = docList.length ? docList.map(d => typeof d[key]) : this.filteredChildren.map(d => typeof d[key]); if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { @@ -287,6 +296,19 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const cols = () => this.isStackingView ? 1 : Math.max(1, Math.min(this.filteredChildren.length, Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); return <CollectionStackingViewFieldColumn + unobserveHeight={(ref) => this.refList.splice(this.refList.indexOf(ref), 1)} + observeHeight={(ref) => { + if (ref) { + this.refList.push(ref); + const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; + this.observer = new _global.ResizeObserver(action((entries: any) => { + if (this.props.Document._autoHeight && ref && this.refList.length && !SelectionManager.GetIsDragging()) { + Doc.Layout(doc)._height = Math.min(1200, Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))))); + } + })); + this.observer.observe(ref); + } + }} key={heading ? heading.heading : ""} cols={cols} headings={this.headings} @@ -305,15 +327,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const y = this._scroll; // required for document decorations to update when the text box container is scrolled const { scale, translateX, translateY } = Utils.GetScreenTransform(dref); const outerXf = Utils.GetScreenTransform(this._masonryGridRef!); - const scaling = 1 / Math.min(1, this.props.PanelHeight() / this.layoutDoc[HeightSym]()); const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); - const offsetx = (doc[WidthSym]() - doc[WidthSym]() / scaling) / 2; const offsety = (this.props.ChromeHeight && this.props.ChromeHeight() < 0 ? this.props.ChromeHeight() : 0); - return this.props.ScreenToLocalTransform().translate(offset[0] - offsetx, offset[1] + offsety).scale(scaling); + return this.props.ScreenToLocalTransform().translate(offset[0], offset[1] + offsety); } - sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { - const key = this.sectionFilter; + sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[], first: boolean) => { + const key = this.pivotField; let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; const types = docList.length ? docList.map(d => typeof d[key]) : this.filteredChildren.map(d => typeof d[key]); if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { @@ -322,6 +342,20 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const rows = () => !this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); return <CollectionMasonryViewFieldRow + showHandle={first} + unobserveHeight={(ref) => this.refList.splice(this.refList.indexOf(ref), 1)} + observeHeight={(ref) => { + if (ref) { + this.refList.push(ref); + const doc = this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc; + this.observer = new _global.ResizeObserver(action((entries: any) => { + if (this.props.Document._autoHeight && ref && this.refList.length && !SelectionManager.GetIsDragging()) { + Doc.Layout(doc)._height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0); + } + })); + this.observer.observe(ref); + } + }} key={heading ? heading.heading : ""} rows={rows} headings={this.headings} @@ -339,7 +373,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @action addGroup = (value: string) => { if (value && this.sectionHeaders) { - this.sectionHeaders.push(new SchemaHeaderField(value)); + const schemaHdrField = new SchemaHeaderField(value); + this.sectionHeaders.push(schemaHdrField); + Doc.addFieldEnumerations(undefined, this.pivotField, [{ title: value, _backgroundColor: schemaHdrField.color }]); return true; } return false; @@ -361,31 +397,27 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { if (!e.isPropagationStopped()) { const subItems: ContextMenuProps[] = []; subItems.push({ description: `${this.props.Document.fillColumn ? "Variable Size" : "Autosize"} Column`, event: () => this.props.Document.fillColumn = !this.props.Document.fillColumn, icon: "plus" }); - subItems.push({ description: `${this.props.Document.showTitles ? "Hide Titles" : "Show Titles"}`, event: () => this.props.Document.showTitles = !this.props.Document.showTitles ? "title" : "", icon: "plus" }); - subItems.push({ description: `${this.props.Document.showCaptions ? "Hide Captions" : "Show Captions"}`, event: () => this.props.Document.showCaptions = !this.props.Document.showCaptions ? "caption" : "", icon: "plus" }); - ContextMenu.Instance.addItem({ description: "Stacking Options ...", subitems: subItems, icon: "eye" }); + ContextMenu.Instance.addItem({ description: "Options...", subitems: subItems, icon: "eye" }); } } @computed get renderedSections() { TraceMobx(); let sections = [[undefined, this.filteredChildren] as [SchemaHeaderField | undefined, Doc[]]]; - if (this.sectionFilter) { + if (this.pivotField) { const entries = Array.from(this.Sections.entries()); sections = entries.sort(this.sortFunc); } - return sections.map(section => this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1])); - } - @computed get contentScale() { - const heightExtra = this.heightPercent > 1 ? this.heightPercent : 1; - return Math.min(this.props.Document[WidthSym]() / this.props.PanelWidth(), heightExtra * this.props.Document[HeightSym]() / this.props.PanelHeight()); - } - @computed get widthScale() { - return this.heightPercent < 1 ? Math.max(1, this.contentScale) : 1; - } - @computed get heightPercent() { - return this.props.PanelHeight() / this.layoutDoc[HeightSym](); + return sections.map((section, i) => this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1], i === 0)); } + + + @computed get nativeWidth() { return NumCast(this.layoutDoc._nativeWidth) || this.props.NativeWidth() || 0; } + @computed get nativeHeight() { return NumCast(this.layoutDoc._nativeHeight) || this.props.NativeHeight() || 0; } + + @computed get scaling() { return !this.nativeWidth ? 1 : this.props.PanelHeight() / this.nativeHeight; } + + observer: any; render() { TraceMobx(); const editableViewProps = { @@ -399,13 +431,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { ref={this.createRef} style={{ overflowY: this.props.active() ? "auto" : "hidden", - transform: `scale(${Math.min(1, this.heightPercent)})`, - height: `${100 * Math.max(1, this.contentScale)}%`, - width: `${100 * this.widthScale}%`, + transform: `scale(${this.scaling}`, + height: `${1 / this.scaling * 100}%`, + width: `${1 / this.scaling * 100}%`, transformOrigin: "top left", }} onScroll={action((e: React.UIEvent<HTMLDivElement>) => this._scroll = e.currentTarget.scrollTop)} - onDrop={this.onDrop.bind(this)} + onDrop={this.onExternalDrop.bind(this)} onContextMenu={this.onContextMenu} onWheel={e => this.props.active() && e.stopPropagation()} > {this.renderedSections} @@ -414,7 +446,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { style={{ width: !this.isStackingView ? "100%" : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}> <EditableView {...editableViewProps} /> </div>} - {this.props.Document._chromeStatus !== 'disabled' ? <Switch + {this.props.Document._chromeStatus !== 'disabled' && this.props.isSelected() ? <Switch onChange={this.onToggle} onClick={this.onToggle} defaultChecked={this.props.Document._chromeStatus !== 'view-mode'} |
