From a2eb8ba283ce4a8fb7f423a9198e2a5778eba886 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 4 May 2020 12:18:11 +0530 Subject: updating from master --- src/client/views/nodes/ContentFittingDocumentView.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 641797cac..814f8fd9c 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -43,6 +43,7 @@ interface ContentFittingDocumentViewProps { pinToPres: (document: Doc) => void; dontRegisterView?: boolean; rootSelected: (outsideReaction?: boolean) => boolean; + Display?: string; } @observer @@ -77,7 +78,8 @@ export class ContentFittingDocumentView extends React.Component 0.001 ? "auto" : this.props.PanelWidth(), - height: Math.abs(this.centeringOffset) > 0.0001 ? "auto" : this.props.PanelHeight() + height: Math.abs(this.centeringOffset) > 0.0001 ? "auto" : this.props.PanelHeight(), + display: this.props.Display /* just added for grid */ }}> {!this.props.Document || !this.props.PanelWidth ? (null) : (
Date: Sun, 24 May 2020 10:36:31 +0530 Subject: Added chrome to grid view and modified grid mechanism --- src/client/views/collections/CollectionView.tsx | 1 + .../views/collections/CollectionViewChromes.scss | 30 ++- .../views/collections/CollectionViewChromes.tsx | 57 ++++- .../collectionGrid/CollectionGridView.tsx | 248 ++++++++++++--------- .../views/collections/collectionGrid/Grid.tsx | 8 + .../views/nodes/ContentFittingDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 1 + 7 files changed, 225 insertions(+), 122 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5b344813d..311e8d3a1 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -227,6 +227,7 @@ export class CollectionView extends Touchable func(CollectionViewType.Carousel), icon: "columns" }); subItems.push({ description: "Pivot/Time", event: () => func(CollectionViewType.Time), icon: "columns" }); subItems.push({ description: "Map", event: () => func(CollectionViewType.Map), icon: "globe-americas" }); + subItems.push({ description: "Grid", event: () => func(CollectionViewType.Grid), icon: "border-all" }); if (addExtras && this.props.Document._viewType === CollectionViewType.Freeform) { subItems.push({ description: "Custom", icon: "fingerprint", event: AddCustomFreeFormLayout(this.props.Document, this.props.fieldKey) }); } diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index e4581eb46..9795a3a22 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -3,7 +3,7 @@ .collectionViewChrome-cont { position: absolute; - width:100%; + width: 100%; opacity: 0.9; z-index: 9001; transition: top .5s; @@ -33,7 +33,7 @@ outline-color: black; } - .collectionViewBaseChrome-button{ + .collectionViewBaseChrome-button { font-size: 75%; text-transform: uppercase; letter-spacing: 2px; @@ -44,6 +44,7 @@ padding: 12px 10px 11px 10px; margin-left: 10px; } + .collectionViewBaseChrome-cmdPicker { margin-left: 3px; margin-right: 0px; @@ -51,14 +52,16 @@ border: none; color: grey; } + .commandEntry-outerDiv { pointer-events: all; background-color: gray; display: flex; flex-direction: row; + .commandEntry-drop { - color:white; - width:25px; + color: white; + width: 25px; margin-top: auto; margin-bottom: auto; } @@ -72,15 +75,17 @@ pointer-events: all; // margin-top: 10px; } + .collectionViewBaseChrome-template, .collectionViewBaseChrome-viewModes { display: grid; background: rgb(238, 238, 238); - color:grey; - margin-top:auto; - margin-bottom:auto; + color: grey; + margin-top: auto; + margin-bottom: auto; margin-left: 5px; } + .collectionViewBaseChrome-viewModes { margin-left: 25px; } @@ -88,7 +93,7 @@ .collectionViewBaseChrome-viewSpecs { margin-left: 5px; display: grid; - + .collectionViewBaseChrome-filterIcon { position: relative; display: flex; @@ -202,7 +207,7 @@ .collectionStackingViewChrome-pivotField, .collectionTreeViewChrome-pivotField { color: white; - width:100%; + width: 100%; min-width: 100px; text-align: center; background: rgb(238, 238, 238); @@ -232,6 +237,10 @@ .collectionTreeViewChrome-pivotField:hover { cursor: text; } + + .collectionGridViewChrome-entryBox { + width: 50%; + } } } @@ -292,8 +301,9 @@ flex-direction: column; height: 40px; } + .commandEntry-inputArea { - display:flex; + display: flex; flex-direction: row; width: 150px; margin: auto auto auto auto; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 5dc0b09ac..def20ae9b 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -2,7 +2,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; -import { Doc, DocListCast } from "../../../fields/Doc"; +import { Doc, DocListCast, HeightSym } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; import { listSpec } from "../../../fields/Schema"; @@ -15,6 +15,8 @@ import { COLLECTION_BORDER_WIDTH } from "../globalCssVariables.scss"; import { CollectionViewType } from "./CollectionView"; import { CollectionView } from "./CollectionView"; import "./CollectionViewChromes.scss"; +import { CollectionGridView } from "./collectionGrid/CollectionGridView"; +import HeightLabel from "./collectionMulticolumn/MultirowHeightLabel"; const datepicker = require('js-datepicker'); interface CollectionViewChromeProps { @@ -205,6 +207,7 @@ export class CollectionViewBaseChrome extends React.Component); case CollectionViewType.Tree: return (); case CollectionViewType.Masonry: return (); + case CollectionViewType.Grid: return (); default: return null; } } @@ -504,3 +507,55 @@ export class CollectionTreeViewChrome extends React.Component { + + /** + * Sets the value of `numCols` on the grid's Document to the value entered. + */ + @action + onNumColsEnter = (e: React.KeyboardEvent) => { + if (e.key === "Enter" || e.key === "Tab") { + if (this.props.CollectionView.props.Document.numCols as number !== e.currentTarget.valueAsNumber) { + this.props.CollectionView.props.Document.numCols = e.currentTarget.valueAsNumber; + //this.props.CollectionView.forceUpdate(); // to be used if CollectionGridView is not an observer + } + + } + } + + /** + * Sets the value of `rowHeight` on the grid's Document to the value entered. + */ + @action + onRowHeightEnter = (e: React.KeyboardEvent) => { + if (e.key === "Enter" || e.key === "Tab") { + if (this.props.CollectionView.props.Document.rowHeight as number !== e.currentTarget.valueAsNumber) { + this.props.CollectionView.props.Document.rowHeight = e.currentTarget.valueAsNumber; + //this.props.CollectionView.forceUpdate(); + } + } + } + + render() { + return ( +
+ + + + + + + + + + + + +
+ ); + } +} \ No newline at end of file diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index cd1e0f7f0..ebb710af6 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -1,39 +1,58 @@ -import { action, computed, observable } from 'mobx'; -import { observer } from 'mobx-react'; +import { computed, observable, action } from 'mobx'; import * as React from "react"; -import { Doc, DataSym, DocListCast } from '../../../../new_fields/Doc'; -import { documentSchema } from '../../../../new_fields/documentSchemas'; -import { makeInterface } from '../../../../new_fields/Schema'; -import { BoolCast, NumCast, ScriptCast, StrCast, Cast } from '../../../../new_fields/Types'; +import { Doc, DocListCast } from '../../../../fields/Doc'; +import { documentSchema } from '../../../../fields/documentSchemas'; +import { makeInterface, createSchema } from '../../../../fields/Schema'; +import { BoolCast, NumCast, ScriptCast, StrCast, Cast } from '../../../../fields/Types'; import { DragManager } from '../../../util/DragManager'; import { Transform } from '../../../util/Transform'; import { undoBatch } from '../../../util/UndoManager'; import { ContentFittingDocumentView } from '../../nodes/ContentFittingDocumentView'; import { CollectionSubView } from '../CollectionSubView'; -import { List } from '../../../../new_fields/List'; +import { SubCollectionViewProps } from '../CollectionSubView'; +import { List } from '../../../../fields/List'; import { returnZero } from '../../../../Utils'; -import Grid from "./Grid"; -import { Layout } from "./Grid"; +import Grid, { Layout } from "./Grid"; +import { Id } from '../../../../fields/FieldSymbols'; +import { observer } from 'mobx-react'; type GridSchema = makeInterface<[typeof documentSchema]>; const GridSchema = makeInterface(documentSchema); +@observer export class CollectionGridView extends CollectionSubView(GridSchema) { - private layouts: Layout[] = []; - private layoutDocs: Doc[] = []; - @observable private numCols: number = 10; - @observable private rowHeight: number = 100; - @observable private isMounted: boolean = false; + constructor(props: Readonly) { + super(props); - componentDidMount() { - this.isMounted = true; + this.props.Document.numCols = this.props.Document.numCols ? this.props.Document.numCols : 10; + this.props.Document.rowHeight = this.props.Document.rowHeight ? this.props.Document.rowHeight : 100; } - componentWillUnmount() { - this.isMounted = false; - console.log("hola"); + componentDidMount() { + if (!(this.props.Document.gridLayouts as List)?.length) { + + console.log("no layouts stored on doc"); + + this.props.Document.gridLayouts = new List(); + + for (let i = 0; i < this.childLayoutPairs.length; i++) { + + const layoutDoc: Doc = new Doc(); + layoutDoc.i = layoutDoc[Id]; + layoutDoc.x = 2 * (i % 5); + layoutDoc.y = 2 * Math.floor(i / 5); + layoutDoc.w = 2; + layoutDoc.h = 2; + + (this.props.Document.gridLayouts as List).push(layoutDoc); + + // use childlayoutpairs length instead + } + + } + } /** @@ -42,18 +61,26 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { * the sum of all the resolved column widths of the * documents before the target. */ - private lookupIndividualTransform = (layout: Layout) => { + private lookupIndividualTransform = (doc: Doc) => { - const yTranslation = this.rowHeight * layout.y;// + 15 * (layout.y - 1); - console.log(yTranslation); - return this.props.ScreenToLocalTransform().translate(-this.props.PanelWidth() / this.numCols * layout.x, -yTranslation); + const yTranslation = (this.props.Document.rowHeight as number) * (doc.y as number) + 10 * (doc.y as number); + return this.props.ScreenToLocalTransform().translate(-this.props.PanelWidth() / (this.props.Document.numCols as number) * (doc.x as number), -yTranslation); } @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); } - @observable private width = (layout: Layout) => layout.w * this.props.PanelWidth() / this.numCols; - @observable private height = (layout: Layout) => layout.h * this.rowHeight; + /** + * Sets the width of the decorating box. + * @param Doc doc + */ + @observable private width = (doc: Doc) => doc.w as number * this.props.PanelWidth() / (this.props.Document.numCols as number); + + /** + * Sets the height of the decorating box. + * @param doc `Doc` + */ + @observable private height = (doc: Doc) => doc.h as number * (this.props.Document.rowHeight as number); addDocTab = (doc: Doc, where: string) => { if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { @@ -81,15 +108,23 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { onClick={this.onChildClickHandler} renderDepth={this.props.renderDepth + 1} parentActive={this.props.active} - //Display={"contents"} + display={"contents"} />; } - //@action + /** + * Saves the layouts received from the Grid to the Document. + * @param layouts `Layout[]` + */ set layout(layouts: Layout[]) { - this.layouts = layouts; - this.props.Document.gridLayouts = new List(); + + console.log("setting layout in CollectionGridView"); + console.log(layouts?.[0].w); + //this.props.Document.gridLayouts = new List(); + + const docList: Doc[] = []; + for (const layout of layouts) { const layoutDoc = new Doc(); layoutDoc.i = layout.i; @@ -98,126 +133,119 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { layoutDoc.w = layout.w; layoutDoc.h = layout.h; - (this.props.Document.gridLayouts as List).push(layoutDoc); - console.log("gazoinks"); - + docList.push(layoutDoc); } - this.forceUpdate(); // better way to do this? + + this.props.Document.gridLayouts = new List(docList); } - get layout() { - //console.log(this.layouts.length === 0); - if (this.layouts.length === 0) { - if (this.props.Document.gridLayouts) { - //console.log(this.props.Document.gridLayouts); - // for (const layout of (this.props.Document.gridLayouts as List)) { - // if (layout instanceof Doc) { - // this.layouts.push( - // { i: layout.i as string, x: layout.x as number, y: layout.y as number, w: layout.w as number, h: layout.h as number } - // ); - // } - // else { - // layout.then((layout: Doc) => { - // this.layouts.push( - // { i: layout.i as string, x: layout.x as number, y: layout.y as number, w: layout.w as number, h: layout.h as number } - // ); - // console.log(layout.i); - // }); - // } - // } - // } - for (const layout of DocListCast(this.props.Document.gridLayouts)) { - this.layouts.push( - { i: layout.i as string, x: layout.x as number, y: layout.y as number, w: layout.w as number, h: layout.h as number } - ); - } - } - else { - for (let i = 0; i < this.childLayoutPairs.length; i++) { - this.layouts.push( - { i: 'wrapper' + i, x: 2 * (i % 5), y: 2 * Math.floor(i / 5), w: 2, h: 2 } - ); - - const layoutDoc: Doc = new Doc(); - layoutDoc.i = "wrapper" + i; - layoutDoc.x = 2 * (i % 5); - layoutDoc.y = 2 * Math.floor(i / 5); - layoutDoc.w = 2; - layoutDoc.h = 2; - - this.layoutDocs.push(layoutDoc); - this.props.Document.highest = i; - } - this.props.Document.gridLayouts = new List(this.layoutDocs); - } - } + // _.reject() on item removal? - return this.layouts; - } + /** + * @returns a list of `ContentFittingDocumentView`s inside wrapper divs. + * The key of the wrapper div must be the same as the `i` value of the corresponding layout. + */ @computed - private get contents(): [JSX.Element[], Layout[]] { + private get contents(): JSX.Element[] { const { childLayoutPairs } = this; const collector: JSX.Element[] = []; - const layoutArray: Layout[] = []; + //const layoutArray: Layout[] = []; + const docList: Doc[] = DocListCast(this.props.Document.gridLayouts); - const previousLength = this.layout.length; - layoutArray.push(...this.layout); + const previousLength = docList.length; + // layoutArray.push(...this.layout); - if (!layoutArray.length) { - return [[], []]; - } - - if (this.childLayoutPairs.length > previousLength) { - layoutArray.push( - { i: 'wrapper' + previousLength, x: 2 * (previousLength % 5), y: 2 * Math.floor(previousLength / 5), w: 2, h: 2 } - // add values to document - ); - // this.layout.push( - // { i: 'wrapper' + previousLength, x: 2 * (previousLength % 5), y: 2 * Math.floor(previousLength / 5), w: 2, h: 2 } - // ); + if (!previousLength) { + // console.log("early return"); + return []; } for (let i = 0; i < childLayoutPairs.length; i++) { const { layout } = childLayoutPairs[i]; - const dxf = () => this.lookupIndividualTransform(layoutArray[i]);//.translate(-NumCast(Document._xMargin), -NumCast(Document._yMargin)); - const width = () => this.width(layoutArray[i]); //this.lookupPixels(layout); - const height = () => this.height(layoutArray[i]);//PanelHeight() - 2 * NumCast(Document._yMargin) - (BoolCast(Document.showWidthLabels) ? 20 : 0); + const dxf = () => this.lookupIndividualTransform(docList?.[i]); + const width = () => this.width(docList?.[i]); + const height = () => this.height(docList?.[i]); collector.push(
{this.getDisplayDoc(layout, dxf, width, height)}
); } - return [collector, layoutArray]; + return collector; + } + + /** + * @returns a list of Layouts from a list of Docs + * @param docLayoutList `Doc[]` + */ + toLayoutList(docLayoutList: Doc[]): Layout[] { + + const layouts: Layout[] = []; + for (const layout of docLayoutList) { + layouts.push( + { i: layout.i as string, x: layout.x as number, y: layout.y as number, w: layout.w as number, h: layout.h as number } + ); + } + return layouts; + } + + /** + * Checks whether a new node has been added to the grid and updates the Document accordingly. + */ + checkUpdate() { + const previousLength = (this.props.Document.gridLayouts as List)?.length; + if (this.childLayoutPairs.length > previousLength) { + console.log("adding doc"); + const layoutDoc: Doc = new Doc(); + layoutDoc.i = layoutDoc[Id]; + layoutDoc.x = 2 * (previousLength % 5); + layoutDoc.y = 2 * Math.floor(previousLength / 5); + layoutDoc.w = 2; + layoutDoc.h = 2; + + (this.props.Document.gridLayouts as List).push(layoutDoc); + } } render(): JSX.Element { - const contents: JSX.Element[] = this.contents?.[0]; - const layout: Layout[] = this.contents?.[1]; - // if (this.isMounted) { + this.checkUpdate(); + + const contents: JSX.Element[] = this.contents; + const layout: Layout[] = this.toLayoutList(DocListCast(this.props.Document.gridLayouts)); + + if (layout.length === 0) { + console.log("layouts not loaded"); + } + else { + console.log("rendering with this"); + console.log(layout[0].w); + } + + return (
- + }} + ref={this.createDashEventsTarget} + onPointerDown={(e: React.PointerEvent) => e.stopPropagation()} + >
); - // } } } diff --git a/src/client/views/collections/collectionGrid/Grid.tsx b/src/client/views/collections/collectionGrid/Grid.tsx index ce0173e94..d400f2810 100644 --- a/src/client/views/collections/collectionGrid/Grid.tsx +++ b/src/client/views/collections/collectionGrid/Grid.tsx @@ -20,9 +20,16 @@ interface GridProps { rowHeight: number; } +/** + * Wrapper around the actual GridLayout of `react-grid-layout`. + */ @observer export default class Grid extends React.Component { + /** + * If there has been a change in layout, calls a method in CollectionGridView to set the layouts on the Document. + * @param layout `Layout[]` + */ onLayoutChange(layout: Layout[]) { this.props.gridView.layout = layout; } @@ -36,6 +43,7 @@ export default class Grid extends React.Component this.onLayoutChange(layout)} > {this.props.nodeList} diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 39097865a..77555061f 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -83,7 +83,7 @@ export class ContentFittingDocumentView extends React.Component 0.001 ? "auto" : this.props.PanelWidth(), height: Math.abs(this.centeringOffset) > 0.0001 ? "auto" : this.props.PanelHeight(), - display: this.props.Display /* just added for grid */ + display: this.props.display /* just added for grid */ }}> {!this.props.Document || !this.props.PanelWidth ? (null) : (
Date: Wed, 27 May 2020 13:53:18 -0400 Subject: fixed ineracting with documents selected in GridView --- src/client/views/collections/collectionGrid/CollectionGridView.tsx | 3 ++- src/client/views/collections/collectionGrid/Grid.tsx | 3 +++ src/client/views/nodes/DocumentView.tsx | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index bc554e2c2..a55d5a8ac 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -240,7 +240,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { style={{ marginLeft: NumCast(this.props.Document._xMargin), marginRight: NumCast(this.props.Document._xMargin), marginTop: NumCast(this.props.Document._yMargin), marginBottom: NumCast(this.props.Document._yMargin), - pointerEvents: !this.props.isSelected() && !this.props.ContainingCollectionView?._isChildActive && !SnappingManager.GetIsDragging() ? "none" : undefined + pointerEvents: !this.props.isSelected() && this.props.renderDepth !== 0 && !this.props.ContainingCollectionView?._isChildActive && !SnappingManager.GetIsDragging() ? "none" : undefined }} ref={this.createDashEventsTarget} onPointerDown={e => e.stopPropagation()} @@ -249,6 +249,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { width={this.props.PanelWidth()} nodeList={contents} layout={layout} + transformScale={this.props.ScreenToLocalTransform().Scale} numCols={this.props.Document.numCols as number} rowHeight={this.props.Document.rowHeight as number} setLayout={(layout: Layout[]) => this.setLayout(layout)} diff --git a/src/client/views/collections/collectionGrid/Grid.tsx b/src/client/views/collections/collectionGrid/Grid.tsx index a5f5c724a..9c66d1e33 100644 --- a/src/client/views/collections/collectionGrid/Grid.tsx +++ b/src/client/views/collections/collectionGrid/Grid.tsx @@ -18,6 +18,7 @@ interface GridProps { numCols: number; rowHeight: number; setLayout: Function; + transformScale: number; } /** @@ -35,6 +36,7 @@ export default class Grid extends React.Component { this.props.setLayout(layout); } + Scale = 2 render() { console.log("In grid layout prop received value= " + this.props.layout?.[0]?.w); return ( @@ -45,6 +47,7 @@ export default class Grid extends React.Component { width={this.props.width} compactType={null} isDroppable={true} + useCSSTransforms={true} margin={[10, 10]} onLayoutChange={layout => this.onLayoutChange(layout)} > diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b5de0af12..79b560118 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -517,6 +517,7 @@ export class DocumentView extends DocComponent(Docu if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || InkingControl.Instance.selectedTool === InkTool.Highlighter || InkingControl.Instance.selectedTool === InkTool.Pen)) { if (!InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { e.stopPropagation(); + e.preventDefault(); // TODO: check here for panning/inking } return; @@ -531,7 +532,7 @@ export class DocumentView extends DocComponent(Docu (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) && !this.Document.inOverlay) { e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag); - + e.preventDefault(); } document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); -- cgit v1.2.3-70-g09d2 From efaa44cacf9cf8506209c9bf1437e36828132eea Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 27 May 2020 15:17:01 -0400 Subject: fixed layout and interactions of grid view --- .../collectionGrid/CollectionGridView.scss | 13 ++++---- .../collectionGrid/CollectionGridView.tsx | 37 ++++++++++------------ src/client/views/nodes/DocumentView.tsx | 6 ++-- 3 files changed, 26 insertions(+), 30 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.scss b/src/client/views/collections/collectionGrid/CollectionGridView.scss index 8f12c1a24..c0a2cbc22 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.scss +++ b/src/client/views/collections/collectionGrid/CollectionGridView.scss @@ -4,11 +4,10 @@ width: 100%; height: 100%; flex-direction: column; - - .document-wrapper { - display: flex; - flex-direction: column; - width: 100%; - height: 100%; - } +} +.collectionGridView_contents .document-wrapper { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; } \ No newline at end of file diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index a55d5a8ac..03ba9d004 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -94,25 +94,22 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { } getDisplayDoc(layout: Doc, dxf: () => Transform, width: () => number, height: () => number) { - return
- -
; + return ; } @@ -243,7 +240,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { pointerEvents: !this.props.isSelected() && this.props.renderDepth !== 0 && !this.props.ContainingCollectionView?._isChildActive && !SnappingManager.GetIsDragging() ? "none" : undefined }} ref={this.createDashEventsTarget} - onPointerDown={e => e.stopPropagation()} + onPointerDown={e => { ((e.target as any)?.className.includes("react-resizable-handle")) && e.stopPropagation(); }} > (Docu if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || InkingControl.Instance.selectedTool === InkTool.Highlighter || InkingControl.Instance.selectedTool === InkTool.Pen)) { if (!InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { e.stopPropagation(); - e.preventDefault(); + if (SelectionManager.IsSelected(this, true) && this.props.Document._viewType !== CollectionViewType.Docking) e.preventDefault(); // goldenlayout needs to be able to move its tabs, so can't preventDefault for it // TODO: check here for panning/inking } return; @@ -531,8 +531,8 @@ export class DocumentView extends DocComponent(Docu !e.ctrlKey && (e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) && !this.Document.inOverlay) { - e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag); - e.preventDefault(); + e.stopPropagation(); + if (SelectionManager.IsSelected(this, true) && this.props.Document._viewType !== CollectionViewType.Docking) e.preventDefault(); // goldenlayout needs to be able to move its tabs, so can't preventDefault for it } document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); -- cgit v1.2.3-70-g09d2 From fbc767726b368c089f0e596368cb694859e93914 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Thu, 11 Jun 2020 00:10:31 +0530 Subject: added customisability for default W, H, margin + added context menu display option + added lock in position functionality --- .../collectionGrid/CollectionGridView.tsx | 131 +++++++++++---------- .../views/collections/collectionGrid/Grid.tsx | 2 + .../views/nodes/ContentFittingDocumentView.tsx | 4 +- 3 files changed, 73 insertions(+), 64 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 01ad44a2d..d68277d32 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -1,4 +1,4 @@ -import { computed, observable, Lambda, action, autorun } from 'mobx'; +import { computed, observable, Lambda, action, reaction } from 'mobx'; import * as React from "react"; import { Doc, Opt } from '../../../../fields/Doc'; import { documentSchema } from '../../../../fields/documentSchemas'; @@ -9,7 +9,7 @@ import { undoBatch } from '../../../util/UndoManager'; import { ContentFittingDocumentView } from '../../nodes/ContentFittingDocumentView'; import { CollectionSubView } from '../CollectionSubView'; import { SubCollectionViewProps } from '../CollectionSubView'; -import { returnZero, returnFalse } from '../../../../Utils'; +import { returnZero } from '../../../../Utils'; import Grid, { Layout } from "./Grid"; import { Id } from '../../../../fields/FieldSymbols'; import { observer } from 'mobx-react'; @@ -18,7 +18,8 @@ import { Docs } from '../../../documents/Documents'; import { EditableView, EditableProps } from '../../EditableView'; import "./CollectionGridView.scss"; import { ContextMenu } from '../../ContextMenu'; -import { ScriptField } from '../../../../fields/ScriptField'; +import { List } from '../../../../fields/List'; +import { ContextMenuProps } from '../../ContextMenuItem'; type GridSchema = makeInterface<[typeof documentSchema]>; @@ -48,8 +49,16 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { // determines whether nodes should move out of the way (i.e. collide) when other nodes are dragged over them this.props.Document.preventCollision = BoolCast(this.props.Document.preventCollision, false); + this.props.Document.defaultW = NumCast(this.props.Document.defaultW, 2); + this.props.Document.defaultH = NumCast(this.props.Document.defaultH, 2); + + this.props.Document.margin = NumCast(this.props.Document.margin, 10); + + this.props.Document.display = StrCast(this.props.Document.display, "contents"); + this.setLayout = this.setLayout.bind(this); this.onSliderChange = this.onSliderChange.bind(this); + this.onContextMenu = this.onContextMenu.bind(this); this.containerRef = React.createRef(); } @@ -65,6 +74,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { // if grid view has been opened and then exited and a document has been deleted // this deletes the layout of that document from the layouts list + if (!oldValue && newValue.length) { layouts.forEach(({ i }, index) => { const targetId = i; @@ -76,16 +86,15 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { if (!oldValue || newValue.length > oldValue.length) { // for each document that was added, add a corresponding grid layout object - newValue.forEach(({ layout }, i) => { const targetId = layout[Id]; if (!layouts.find((gridLayout: Layout) => gridLayout.i === targetId)) { layouts.push({ i: targetId, - w: 2, - h: 2, - x: 2 * (i % Math.floor(NumCast(this.props.Document.numCols) / 2)), - y: 2 * Math.floor(i / Math.floor(NumCast(this.props.Document.numCols) / 2)), + w: this.defaultW, + h: this.defaultH, + x: this.defaultW * (i % Math.floor(NumCast(this.props.Document.numCols) / this.defaultW)), + y: this.defaultH * Math.floor(i / Math.floor(NumCast(this.props.Document.numCols) / this.defaultH)), static: !this.props.Document.flexGrid }); } @@ -104,24 +113,19 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { }, true); // updates the layouts if the reset button has been clicked - this.resetListenerDisposer = autorun(() => { - if (this.props.Document.resetLayout) { - if (this.props.Document.flexGrid) { - console.log("Resetting layout"); - const layouts: Layout[] = this.parsedLayoutList; - - this.setLayout( - layouts.map(({ i }, index) => ({ - i: i, - x: 2 * (index % Math.floor(NumCast(this.props.Document.numCols) / 2)), - y: 2 * Math.floor(index / Math.floor(NumCast(this.props.Document.numCols) / 2)), - w: 2, - h: 2, - }))); - } - - this.props.Document.resetLayout = false; + this.resetListenerDisposer = reaction(() => this.props.Document.resetLayout, () => { + if (this.props.Document.flexGrid) { + const layouts: Layout[] = this.parsedLayoutList; + this.setLayout( + layouts.map(({ i }, index) => ({ + i: i, + x: this.defaultW * (index % Math.floor(NumCast(this.props.Document.numCols) / this.defaultW)), + y: this.defaultH * Math.floor(index / Math.floor(NumCast(this.props.Document.numCols) / this.defaultH)), + w: this.defaultW, + h: this.defaultH, + }))); } + this.props.Document.resetLayout = false; }); } @@ -142,16 +146,28 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { const index = this.childLayoutPairs.findIndex(({ layout: layoutDoc }) => layoutDoc[Id] === layout.i); // translations depend on whether the grid is flexible or static - const yTranslation = (this.props.Document.flexGrid ? NumCast(layout.y) : 2 * Math.floor(index / Math.floor(NumCast(this.props.Document.numCols) / 2))) * this.rowHeightPlusGap + 10 - this._scroll + 30; // 30 is the height of the add text doc bar - const xTranslation = (this.props.Document.flexGrid ? NumCast(layout.x) : 2 * (index % Math.floor(NumCast(this.props.Document.numCols) / 2))) * this.colWidthPlusGap + 10; + const xTranslation = (this.props.Document.flexGrid ? NumCast(layout.x) : this.defaultW * (index % Math.floor(NumCast(this.props.Document.numCols) / this.defaultW))) * this.colWidthPlusGap + this.margin; + const yTranslation = (this.props.Document.flexGrid ? NumCast(layout.y) : this.defaultH * Math.floor(index / Math.floor(NumCast(this.props.Document.numCols) / this.defaultH))) * this.rowHeightPlusGap + this.margin - this._scroll + 30; // 30 is the height of the add text doc bar return this.props.ScreenToLocalTransform().translate(-xTranslation, -yTranslation); } - // is this needed? it seems to never be called + @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); } - @computed get colWidthPlusGap() { return (this.props.PanelWidth() - 10) / NumCast(this.props.Document.numCols); } - @computed get rowHeightPlusGap() { return NumCast(this.props.Document.rowHeight) + 10; } + addDocTab = (doc: Doc, where: string) => { + if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { + this.dataDoc[this.props.fieldKey] = new List([doc]); + return true; + } + return this.props.addDocTab(doc, where); + } + + @computed get colWidthPlusGap() { return (this.props.PanelWidth() - this.margin) / NumCast(this.props.Document.numCols); } + @computed get rowHeightPlusGap() { return NumCast(this.props.Document.rowHeight) + this.margin; } + + @computed get margin() { return NumCast(this.props.Document.margin); } + @computed get defaultW() { return NumCast(this.props.Document.defaultW); } + @computed get defaultH() { return NumCast(this.props.Document.defaultH); } /** * @returns the layout list converted from JSON @@ -169,9 +185,10 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { // sometimes there are issues with rendering when you switch from a different view // where the nodes are all squeezed together on the left hand side of the screen // until you click on the screen or close the chrome or interact with it in some way + // the component doesn't rerender when the component mounts // this seems to fix that though it isn't very elegant - console.log("setting unstringified") + console.log("setting unstringified"); this.mounted && (this.props.Document.gridLayoutString = ""); this.props.Document.gridLayoutString = JSON.stringify(layouts); this.mounted = false; @@ -182,31 +199,13 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { * Sets the width of the decorating box. * @param layout */ - @observable private width = (layout: Layout) => (this.props.Document.flexGrid ? layout.w : 2) * this.colWidthPlusGap - 10; + @observable private width = (layout: Layout) => (this.props.Document.flexGrid ? layout.w : this.defaultW) * this.colWidthPlusGap - this.margin; /** * Sets the height of the decorating box. * @param layout */ - @observable private height = (layout: Layout) => (this.props.Document.flexGrid ? layout.h : 2) * this.rowHeightPlusGap - 10; - - contextMenuItems = (layoutDoc: Doc) => { - const layouts: Layout[] = this.parsedLayoutList; - const freezeScript = ScriptField.MakeFunction( - // "layouts.find(({ i }) => i === layoutDoc[Id]).static=true;" + - // "this.unStringifiedLayoutList = layouts;" + - "console.log(doc)", { doc: Doc.name } - ); - - // const layouts: Layout[] = this.parsedLayoutList; - - // const layoutToChange = layouts.find(({ i }) => i === layoutDoc[Id]); - // layoutToChange!.static = !layoutToChange!.static; - - // this.unStringifiedLayoutList = layouts; - - return [{ script: freezeScript!, label: "testing" }]; - } + @observable private height = (layout: Layout) => (this.props.Document.flexGrid ? layout.h : this.defaultH) * this.rowHeightPlusGap - this.margin; /** * @@ -223,7 +222,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { DataDoc={layout.resolvedDataDoc as Doc} NativeHeight={returnZero} NativeWidth={returnZero} - addDocTab={returnFalse} + addDocTab={this.addDocTab} backgroundColor={this.props.backgroundColor} ContainingCollectionDoc={this.props.Document} PanelWidth={width} @@ -232,8 +231,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { onClick={this.onChildClickHandler} renderDepth={this.props.renderDepth + 1} parentActive={this.props.active} - display={"contents"} - contextMenuItems={() => this.contextMenuItems(layout)} + display={StrCast(this.props.Document.display)} />; } @@ -292,7 +290,6 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { collector.push(
ContextMenu.Instance.addItem({ description: "test", event: () => console.log("test"), icon: "rainbow" })} > {this.getDisplayDoc(layout, dxf, width, height)}
@@ -310,21 +307,22 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { console.log("getting layoutlist"); const layouts: Layout[] = this.parsedLayoutList; + return this.props.Document.flexGrid ? - layouts.map(({ i, x, y, w, h, static: staticVal }) => ({ + layouts.map(({ i, x, y, w, h }) => ({ i: i, x: x + w > NumCast(this.props.Document.numCols) ? 0 : x, // handles wrapping around of nodes when numCols decreases y: y, w: w > NumCast(this.props.Document.numCols) ? NumCast(this.props.Document.numCols) : w, // reduces width if greater than numCols h: h, - static: staticVal // only needed if we implement freeze in place + static: BoolCast(this.childLayoutPairs.find(({ layout }) => layout[Id] === i)?.layout.lockedPosition, false) // checks if the lock position item has been selected in the context menu })) : layouts.map(({ i }, index) => ({ i: i, - x: 2 * (index % Math.floor(NumCast(this.props.Document.numCols) / 2)), - y: 2 * Math.floor(index / Math.floor(NumCast(this.props.Document.numCols) / 2)), - w: 2, - h: 2, + x: this.defaultW * (index % Math.floor(NumCast(this.props.Document.numCols) / this.defaultW)), + y: this.defaultH * Math.floor(index / Math.floor(NumCast(this.props.Document.numCols) / this.defaultH)), + w: this.defaultW, + h: this.defaultH, static: true })); } @@ -357,6 +355,14 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { */ @undoBatch @action addTextDocument = (value: string) => this.props.addDocument(Docs.Create.TextDocument(value, { title: value })); + onContextMenu = () => { + const displayOptionsMenu: ContextMenuProps[] = []; + displayOptionsMenu.push({ description: "Contents", event: () => this.props.Document.display = "contents", icon: "copy" }); + displayOptionsMenu.push({ description: "Undefined", event: () => this.props.Document.display = undefined, icon: "exclamation" }); + + ContextMenu.Instance.addItem({ description: "Display", subitems: displayOptionsMenu, icon: "tv" }); + } + render() { console.log("and render"); @@ -376,7 +382,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { style={{ pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined }} - // onContextMenu={() => ContextMenu.Instance.addItem({ description: "test", event: () => console.log("test"), icon: "rainbow" })} + onContextMenu={this.onContextMenu} ref={this.createDashEventsTarget} onPointerDown={e => { if (this.props.active(true)) { @@ -417,6 +423,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { transformScale={this.props.ScreenToLocalTransform().Scale} compactType={StrCast(this.props.Document.compactType)} preventCollision={BoolCast(this.props.Document.preventCollision)} + margin={this.margin} />
diff --git a/src/client/views/collections/collectionGrid/Grid.tsx b/src/client/views/collections/collectionGrid/Grid.tsx index 9192a38d7..529e7762f 100644 --- a/src/client/views/collections/collectionGrid/Grid.tsx +++ b/src/client/views/collections/collectionGrid/Grid.tsx @@ -21,6 +21,7 @@ interface GridProps { childrenDraggable: boolean; preventCollision: boolean; compactType: string; + margin: number; } /** @@ -47,6 +48,7 @@ export default class Grid extends React.Component { preventCollision={this.props.preventCollision} transformScale={1 / this.props.transformScale} // still doesn't work :( style={{ zIndex: 5 }} + margin={[this.props.margin, this.props.margin]} > {this.props.nodeList} diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 77555061f..d9e7d072f 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -73,8 +73,8 @@ export class ContentFittingDocumentView extends React.Component this.props.ScreenToLocalTransform().translate(-this.centeringOffset, -this.centeringYOffset).scale(1 / this.contentScaling()); - private get centeringOffset() { return this.nativeWidth() && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth() * this.contentScaling()) / 2 : 0; } - private get centeringYOffset() { return Math.abs(this.centeringOffset) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight() * this.contentScaling()) / 2 : 0; } + private get centeringOffset() { return this.nativeWidth() && !this.props.Document._fitWidth && this.props.display !== "contents" ? (this.props.PanelWidth() - this.nativeWidth() * this.contentScaling()) / 2 : 0; } + private get centeringYOffset() { return Math.abs(this.centeringOffset) < 0.001 && this.props.display !== "contents" ? (this.props.PanelHeight() - this.nativeHeight() * this.contentScaling()) / 2 : 0; } @computed get borderRounding() { return StrCast(this.props.Document?.borderRounding); } -- cgit v1.2.3-70-g09d2