diff options
author | Sam Wilkins <samwilkins333@gmail.com> | 2020-01-17 21:33:55 -0500 |
---|---|---|
committer | Sam Wilkins <samwilkins333@gmail.com> | 2020-01-17 21:33:55 -0500 |
commit | d9e8815ad25b413b825ae72267b85782e787407c (patch) | |
tree | f36f08efde257f71cd99e5162438d2b7382a84a2 /src | |
parent | 6fe419d5545dce871376fa5540665f8ef07f5ae2 (diff) |
created files for mcview subcomponents, removed excess zeros in width labels and added colored feedback for resize mode. Need to implement more useful version of 'global' resize mode
Diffstat (limited to 'src')
-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 |