diff options
Diffstat (limited to 'src/client/views/collections/CollectionStackingView.tsx')
-rw-r--r-- | src/client/views/collections/CollectionStackingView.tsx | 90 |
1 files changed, 48 insertions, 42 deletions
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index da7ea50c6..cad7cd50c 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -1,5 +1,5 @@ import React = require("react"); -import { action, computed, IReactionDisposer, reaction } from "mobx"; +import { action, computed, IReactionDisposer, reaction, trace } from "mobx"; import { observer } from "mobx-react"; import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; @@ -11,28 +11,34 @@ import { DocumentView } from "../nodes/DocumentView"; import { CollectionSchemaPreview } from "./CollectionSchemaView"; import "./CollectionStackingView.scss"; import { CollectionSubView } from "./CollectionSubView"; +import { ContextMenu } from "../ContextMenu"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { _masonryGridRef: HTMLDivElement | null = null; _heightDisposer?: IReactionDisposer; - get gridGap() { return 10; } - get gridSize() { return 20; } - get singleColumn() { return BoolCast(this.props.Document.singleColumn, true); } - get columnWidth() { return this.singleColumn ? this.props.PanelWidth() - 4 * this.gridGap : NumCast(this.props.Document.columnWidth, 250); } + _gridSize = 1; + @computed get xMargin() { return NumCast(this.props.Document.xMargin, 2 * this.gridGap); } + @computed get yMargin() { return NumCast(this.props.Document.yMargin, 2 * this.gridGap); } + @computed get gridGap() { return NumCast(this.props.Document.gridGap, 10); } + @computed get singleColumn() { return BoolCast(this.props.Document.singleColumn, true); } + @computed get columnWidth() { return this.singleColumn ? this.props.PanelWidth() - 2 * this.xMargin : Math.min(this.props.PanelWidth() - 2 * this.xMargin, NumCast(this.props.Document.columnWidth, 250)); } + singleColDocHeight(d: Doc) { + let nw = NumCast(d.nativeWidth); + let nh = NumCast(d.nativeHeight); + let aspect = nw && nh ? nh / nw : 1; + let wid = Math.min(d[WidthSym](), this.columnWidth); + return (nw && nh) ? wid * aspect : d[HeightSym](); + } componentDidMount() { - this._heightDisposer = reaction(() => [this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized]), this.columnWidth, this.props.PanelHeight()], + this._heightDisposer = reaction(() => [this.yMargin, this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])], () => { if (this.singleColumn) { - this.props.Document.height = this.childDocs.filter(d => !d.isMinimized).reduce((height, d) => { - let hgt = d[HeightSym](); - let wid = d[WidthSym](); - let nw = NumCast(d.nativeWidth); - let nh = NumCast(d.nativeHeight); - if (nw && nh) hgt = nh / nw * Math.min(this.columnWidth, wid); - return height + hgt + 2 * this.gridGap; - }, this.gridGap * 2); + let children = this.childDocs.filter(d => !d.isMinimized); + this.props.Document.height = children.reduce((height, d, i) => + height + this.singleColDocHeight(d) + (i === children.length - 1 ? this.yMargin : this.gridGap) + , this.yMargin); } }, { fireImmediately: true }); } @@ -73,23 +79,17 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @computed get singleColumnChildren() { - return this.childDocs.filter(d => !d.isMinimized).map((d, i) => { + let children = this.childDocs.filter(d => !d.isMinimized); + return children.map((d, i) => { let dref = React.createRef<HTMLDivElement>(); let script = undefined; let colWidth = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; - let margin = colWidth() < this.columnWidth ? "auto" : undefined; - let rowHeight = () => { - let hgt = d[HeightSym](); - let nw = NumCast(d.nativeWidth); - let nh = NumCast(d.nativeHeight); - if (nw && nh) hgt = nh / nw * colWidth(); - return hgt; - } + let rowHeight = () => this.singleColDocHeight(d); let dxf = () => this.getDocTransform(d, dref.current!).scale(this.columnWidth / d[WidthSym]()); return <div className="collectionStackingView-masonryDoc" key={d[Id]} ref={dref} - style={{ marginTop: `${i ? 2 * this.gridGap : 0}px`, width: colWidth(), height: rowHeight(), marginLeft: margin, marginRight: margin }} > + style={{ width: colWidth(), height: rowHeight(), marginLeft: "auto", marginRight: "auto" }} > <CollectionSchemaPreview Document={d} width={colWidth} @@ -109,11 +109,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } @computed get children() { - return this.childDocs.filter(d => !d.isMinimized).map(d => { + return this.childDocs.filter(d => !d.isMinimized).map((d, i) => { let dref = React.createRef<HTMLDivElement>(); let dxf = () => this.getDocTransform(d, dref.current!); - let colSpan = Math.ceil(Math.min(d[WidthSym](), this.columnWidth + this.gridGap) / (this.gridSize + this.gridGap)); - let rowSpan = Math.ceil((this.columnWidth / d[WidthSym]() * d[HeightSym]() + this.gridGap) / (this.gridSize + this.gridGap)); + let rowSpan = Math.ceil((this.columnWidth / d[WidthSym]() * d[HeightSym]() + this.gridGap) / (this._gridSize + this.gridGap)); let childFocus = (doc: Doc) => { doc.libraryBrush = true; this.props.focus(this.props.Document); // just focus on this collection, not the underlying document because the API doesn't support adding an offset to focus on and we can't pan zoom our contents to be centered. @@ -126,7 +125,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { height: NumCast(d.nativeHeight, d[HeightSym]()), transformOrigin: "top left", gridRowEnd: `span ${rowSpan}`, - gridColumnEnd: `span ${colSpan}`, + gridColumnEnd: `span 1`, transform: `scale(${this.columnWidth / NumCast(d.nativeWidth, d[WidthSym]())}, ${this.columnWidth / NumCast(d.nativeWidth, d[WidthSym]())})` }} > <DocumentView key={d[Id]} Document={d} @@ -150,30 +149,37 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { </div>); }) } + onContextMenu = (e: React.MouseEvent): void => { + if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + ContextMenu.Instance.addItem({ + description: "Toggle multi-column", + event: () => this.props.Document.singleColumn = !BoolCast(this.props.Document.singleColumn, true), icon: "file-pdf" + }); + } + } render() { - let leftMargin = 2 * this.gridGap; - let topMargin = 2 * this.gridGap; - let itemCols = Math.ceil(this.columnWidth / (this.gridSize + this.gridGap)); - let cells = Math.floor((this.props.PanelWidth() - leftMargin) / (itemCols * (this.gridSize + this.gridGap))); + let cols = this.singleColumn ? 1 : Math.max(1, Math.min(this.childDocs.filter(d => !d.isMinimized).length, + Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); + let templatecols = ""; + for (let i = 0; i < cols; i++) templatecols += `${this.columnWidth}px `; return ( - <div className="collectionStackingView" style={{ height: "100%" }} - ref={this.createRef} onWheel={(e: React.WheelEvent) => e.stopPropagation()}> + <div className="collectionStackingView"> <div className={`collectionStackingView-masonry${this.singleColumn ? "Single" : "Grid"}`} + onContextMenu={this.onContextMenu} + ref={this.createRef} onWheel={(e: React.WheelEvent) => e.stopPropagation()} style={{ - padding: `${topMargin}px 0px 0px ${leftMargin}px`, - width: this.singleColumn ? "100%" : `${cells * itemCols * (this.gridSize + this.gridGap) + leftMargin}`, + padding: this.singleColumn ? `${this.yMargin}px ${this.xMargin}px ${this.yMargin}px ${this.xMargin}px` : `${this.yMargin}px ${this.xMargin}px`, + margin: "auto", + width: this.singleColumn ? undefined : `${cols * (this.columnWidth + this.gridGap) + 2 * this.xMargin - this.gridGap}px`, height: "100%", - overflow: "hidden", - marginRight: "auto", position: "relative", gridGap: this.gridGap, - gridTemplateColumns: this.singleColumn ? undefined : `repeat(auto-fill, minmax(${this.gridSize}px,1fr))`, - gridAutoRows: this.singleColumn ? undefined : `${this.gridSize}px` + gridTemplateColumns: this.singleColumn ? undefined : templatecols, + gridAutoRows: this.singleColumn ? undefined : `${this._gridSize}px` }} > {this.singleColumn ? this.singleColumnChildren : this.children} - </div> - </div> + </div></div> ); } }
\ No newline at end of file |