diff options
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss (renamed from src/client/views/collections/CollectionMulticolumnView.scss) | 2 | ||||
-rw-r--r-- | src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx (renamed from src/client/views/collections/CollectionMulticolumnView.tsx) | 154 | ||||
-rw-r--r-- | src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx | 115 | ||||
-rw-r--r-- | src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx | 28 |
5 files changed, 159 insertions, 142 deletions
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index db4da30d1..a665b678b 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -27,7 +27,7 @@ import { CollectionDockingView } from "./CollectionDockingView"; import { AddCustomFreeFormLayout } from './collectionFreeForm/CollectionFreeFormLayoutEngines'; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; import { CollectionLinearView } from './CollectionLinearView'; -import { CollectionMulticolumnView } from './CollectionMulticolumnView'; +import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView'; import { CollectionPivotView } from './CollectionPivotView'; import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionStackingView } from './CollectionStackingView'; diff --git a/src/client/views/collections/CollectionMulticolumnView.scss b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss index 5fbc35df6..062b8ac11 100644 --- a/src/client/views/collections/CollectionMulticolumnView.scss +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss @@ -16,7 +16,6 @@ } .resizer { - background: black; cursor: ew-resize; transition: 0.5s opacity ease; display: flex; @@ -25,6 +24,7 @@ .internal { width: 100%; height: 100%; + transition: 0.5s background-color ease; } } diff --git a/src/client/views/collections/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index ef15b29eb..e57e5eb26 100644 --- a/src/client/views/collections/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -1,15 +1,17 @@ import { observer } from 'mobx-react'; -import { makeInterface } from '../../../new_fields/Schema'; -import { documentSchema } from '../../../new_fields/documentSchemas'; -import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; +import { makeInterface } from '../../../../new_fields/Schema'; +import { documentSchema } from '../../../../new_fields/documentSchemas'; +import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView'; import * as React from "react"; -import { Doc } from '../../../new_fields/Doc'; -import { NumCast, StrCast, BoolCast } from '../../../new_fields/Types'; -import { ContentFittingDocumentView } from './../nodes/ContentFittingDocumentView'; -import { Utils } from '../../../Utils'; +import { Doc } from '../../../../new_fields/Doc'; +import { NumCast, StrCast, BoolCast } from '../../../../new_fields/Types'; +import { ContentFittingDocumentView } from '../../nodes/ContentFittingDocumentView'; +import { Utils } from '../../../../Utils'; import "./collectionMulticolumnView.scss"; import { computed, trace, observable, action } from 'mobx'; -import { Transform } from '../../util/Transform'; +import { Transform } from '../../../util/Transform'; +import WidthLabel from './MulticolumnWidthLabel'; +import ResizeBar from './MulticolumnResizer'; type MulticolumnDocument = makeInterface<[typeof documentSchema]>; const MulticolumnDocument = makeInterface(documentSchema); @@ -29,7 +31,6 @@ interface LayoutData { const resolvedUnits = ["*", "px"]; const resizerWidth = 4; -const resizerOpacity = 1; @observer export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocument) { @@ -154,17 +155,18 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu @computed private get contents(): JSX.Element[] | null { - trace(); const { childLayoutPairs } = this; const { Document, PanelHeight } = this.props; const collector: JSX.Element[] = []; for (let i = 0; i < childLayoutPairs.length; i++) { const { layout } = childLayoutPairs[i]; collector.push( - <div className={"document-wrapper"}> + <div + className={"document-wrapper"} + key={Utils.GenerateGuid()} + > <ContentFittingDocumentView {...this.props} - key={Utils.GenerateGuid()} Document={layout} DataDocument={layout.resolvedDataDoc as Doc} PanelWidth={() => this.lookupPixels(layout)} @@ -200,132 +202,4 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu ); } -} - -interface ResizerProps { - width: number; - columnUnitLength(): number | undefined; - toLeft?: Doc; - toRight?: Doc; -} - -enum ResizeMode { - Global, - Pinned, - Undefined -} - -@observer -class ResizeBar extends React.Component<ResizerProps> { - @observable private isHoverActive = false; - @observable private isResizingActive = false; - private resizeMode = ResizeMode.Undefined; - - private registerResizing = (e: React.PointerEvent<HTMLDivElement>, mode: ResizeMode) => { - e.stopPropagation(); - e.preventDefault(); - this.resizeMode = mode; - window.removeEventListener("pointermove", this.onPointerMove); - window.removeEventListener("pointerup", this.onPointerUp); - window.addEventListener("pointermove", this.onPointerMove); - window.addEventListener("pointerup", this.onPointerUp); - this.isResizingActive = true; - } - - private onPointerMove = ({ movementX }: PointerEvent) => { - const { toLeft, toRight, columnUnitLength } = this.props; - const movingRight = movementX > 0; - const toNarrow = movingRight ? toRight : toLeft; - const toWiden = movingRight ? toLeft : toRight; - const unitLength = columnUnitLength(); - if (unitLength) { - if (toNarrow) { - const { widthUnit, widthMagnitude } = toNarrow; - const scale = widthUnit === "*" ? unitLength : 1; - toNarrow.widthMagnitude = NumCast(widthMagnitude) - Math.abs(movementX) / scale; - } - if (this.resizeMode === ResizeMode.Pinned && toWiden) { - const { widthUnit, widthMagnitude } = toWiden; - const scale = widthUnit === "*" ? unitLength : 1; - toWiden.widthMagnitude = NumCast(widthMagnitude) + Math.abs(movementX) / scale; - } - } - } - - private get isActivated() { - const { toLeft, toRight } = this.props; - if (toLeft && toRight) { - if (StrCast(toLeft.widthUnit) === "px" && StrCast(toRight.widthUnit) === "px") { - return false; - } - return true; - } else if (toLeft) { - if (StrCast(toLeft.widthUnit) === "px") { - return false; - } - return true; - } else if (toRight) { - if (StrCast(toRight.widthUnit) === "px") { - return false; - } - return true; - } - return false; - } - - @action - private onPointerUp = () => { - this.resizeMode = ResizeMode.Undefined; - this.isResizingActive = false; - this.isHoverActive = false; - window.removeEventListener("pointermove", this.onPointerMove); - window.removeEventListener("pointerup", this.onPointerUp); - } - - render() { - return ( - <div - className={"resizer"} - style={{ - width: this.props.width, - opacity: this.isActivated && this.isHoverActive ? resizerOpacity : 0 - }} - onPointerEnter={action(() => this.isHoverActive = true)} - onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))} - > - <div - className={"internal"} - onPointerDown={e => this.registerResizing(e, ResizeMode.Pinned)} - /> - <div - className={"internal"} - onPointerDown={e => this.registerResizing(e, ResizeMode.Global)} - /> - </div> - ); - } - -} - -interface WidthLabelProps { - layout: Doc; - collectionDoc: Doc; - decimals?: number; -} - -@observer -class WidthLabel extends React.Component<WidthLabelProps> { - - @computed - private get contents() { - const { layout, decimals } = this.props; - const magnitude = NumCast(layout.widthMagnitude).toFixed(decimals ?? 3); - const unit = StrCast(layout.widthUnit); - return <span className={"display"}>{magnitude} {unit}</span>; - } - - render() { - return BoolCast(this.props.collectionDoc.showWidthLabels) ? this.contents : (null); - } - }
\ No newline at end of file diff --git a/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx new file mode 100644 index 000000000..aab98ecfd --- /dev/null +++ b/src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx @@ -0,0 +1,115 @@ +import * as React from "react"; +import { observer } from "mobx-react"; +import { observable, action } from "mobx"; +import { Doc } from "../../../../new_fields/Doc"; +import { NumCast, StrCast } from "../../../../new_fields/Types"; + +interface ResizerProps { + width: number; + columnUnitLength(): number | undefined; + toLeft?: Doc; + toRight?: Doc; +} + +enum ResizeMode { + Global = "blue", + Pinned = "red", + Undefined = "black" +} + +const resizerOpacity = 1; + +@observer +export default class ResizeBar extends React.Component<ResizerProps> { + @observable private isHoverActive = false; + @observable private isResizingActive = false; + @observable private resizeMode = ResizeMode.Undefined; + + @action + private registerResizing = (e: React.PointerEvent<HTMLDivElement>, mode: ResizeMode) => { + e.stopPropagation(); + e.preventDefault(); + this.resizeMode = mode; + window.removeEventListener("pointermove", this.onPointerMove); + window.removeEventListener("pointerup", this.onPointerUp); + window.addEventListener("pointermove", this.onPointerMove); + window.addEventListener("pointerup", this.onPointerUp); + this.isResizingActive = true; + } + + private onPointerMove = ({ movementX }: PointerEvent) => { + const { toLeft, toRight, columnUnitLength } = this.props; + const movingRight = movementX > 0; + const toNarrow = movingRight ? toRight : toLeft; + const toWiden = movingRight ? toLeft : toRight; + const unitLength = columnUnitLength(); + if (unitLength) { + if (toNarrow) { + const { widthUnit, widthMagnitude } = toNarrow; + const scale = widthUnit === "*" ? unitLength : 1; + toNarrow.widthMagnitude = NumCast(widthMagnitude) - Math.abs(movementX) / scale; + } + if (this.resizeMode === ResizeMode.Pinned && toWiden) { + const { widthUnit, widthMagnitude } = toWiden; + const scale = widthUnit === "*" ? unitLength : 1; + toWiden.widthMagnitude = NumCast(widthMagnitude) + Math.abs(movementX) / scale; + } + } + } + + private get isActivated() { + const { toLeft, toRight } = this.props; + if (toLeft && toRight) { + if (StrCast(toLeft.widthUnit) === "px" && StrCast(toRight.widthUnit) === "px") { + return false; + } + return true; + } else if (toLeft) { + if (StrCast(toLeft.widthUnit) === "px") { + return false; + } + return true; + } else if (toRight) { + if (StrCast(toRight.widthUnit) === "px") { + return false; + } + return true; + } + return false; + } + + @action + private onPointerUp = () => { + this.resizeMode = ResizeMode.Undefined; + this.isResizingActive = false; + this.isHoverActive = false; + window.removeEventListener("pointermove", this.onPointerMove); + window.removeEventListener("pointerup", this.onPointerUp); + } + + render() { + return ( + <div + className={"resizer"} + style={{ + width: this.props.width, + opacity: this.isActivated && this.isHoverActive ? resizerOpacity : 0 + }} + onPointerEnter={action(() => this.isHoverActive = true)} + onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))} + > + <div + className={"internal"} + onPointerDown={e => this.registerResizing(e, ResizeMode.Pinned)} + style={{ backgroundColor: this.resizeMode }} + /> + <div + className={"internal"} + onPointerDown={e => this.registerResizing(e, ResizeMode.Global)} + style={{ backgroundColor: this.resizeMode }} + /> + </div> + ); + } + +}
\ No newline at end of file diff --git a/src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx b/src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx new file mode 100644 index 000000000..e33d4c169 --- /dev/null +++ b/src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx @@ -0,0 +1,28 @@ +import * as React from "react"; +import { observer } from "mobx-react"; +import { computed } from "mobx"; +import { Doc } from "../../../../new_fields/Doc"; +import { NumCast, StrCast, BoolCast } from "../../../../new_fields/Types"; + +interface WidthLabelProps { + layout: Doc; + collectionDoc: Doc; + decimals?: number; +} + +@observer +export default class WidthLabel extends React.Component<WidthLabelProps> { + + @computed + private get contents() { + const { layout, decimals } = this.props; + const magnitude = +NumCast(layout.widthMagnitude).toFixed(decimals ?? 3); + const unit = StrCast(layout.widthUnit); + return <span className={"display"}>{magnitude} {unit}</span>; + } + + render() { + return BoolCast(this.props.collectionDoc.showWidthLabels) ? this.contents : (null); + } + +}
\ No newline at end of file |