aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionStackingView.tsx
diff options
context:
space:
mode:
authorBob Zeleznik <zzzman@gmail.com>2020-04-28 17:32:59 -0400
committerBob Zeleznik <zzzman@gmail.com>2020-04-28 17:32:59 -0400
commitd020ab540abaf279414aa682c8930a4b280ace55 (patch)
tree2cab1b330659a97664af86e34f52d2d1b0ed49e1 /src/client/views/collections/CollectionStackingView.tsx
parent4ecf08b5c5cdc4ddb3a997e2f3a2188e921ff430 (diff)
parent6b2896756c55727ed397c223187cb03fe8a51a59 (diff)
merged with master
Diffstat (limited to 'src/client/views/collections/CollectionStackingView.tsx')
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx260
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'}