From d9e8815ad25b413b825ae72267b85782e787407c Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 17 Jan 2020 21:33:55 -0500 Subject: 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 --- .../collections/CollectionMulticolumnView.scss | 31 -- .../collections/CollectionMulticolumnView.tsx | 331 --------------------- src/client/views/collections/CollectionView.tsx | 2 +- .../CollectionMulticolumnView.scss | 31 ++ .../CollectionMulticolumnView.tsx | 205 +++++++++++++ .../collectionMulticolumn/MulticolumnResizer.tsx | 115 +++++++ .../MulticolumnWidthLabel.tsx | 28 ++ 7 files changed, 380 insertions(+), 363 deletions(-) delete mode 100644 src/client/views/collections/CollectionMulticolumnView.scss delete mode 100644 src/client/views/collections/CollectionMulticolumnView.tsx create mode 100644 src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss create mode 100644 src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx create mode 100644 src/client/views/collections/collectionMulticolumn/MulticolumnResizer.tsx create mode 100644 src/client/views/collections/collectionMulticolumn/MulticolumnWidthLabel.tsx (limited to 'src') diff --git a/src/client/views/collections/CollectionMulticolumnView.scss b/src/client/views/collections/CollectionMulticolumnView.scss deleted file mode 100644 index 5fbc35df6..000000000 --- a/src/client/views/collections/CollectionMulticolumnView.scss +++ /dev/null @@ -1,31 +0,0 @@ -.collectionMulticolumnView_contents { - display: flex; - width: 100%; - height: 100%; - overflow: hidden; - - .document-wrapper { - display: flex; - flex-direction: column; - - .display { - text-align: center; - height: 20px; - } - - } - - .resizer { - background: black; - cursor: ew-resize; - transition: 0.5s opacity ease; - display: flex; - flex-direction: column; - - .internal { - width: 100%; - height: 100%; - } - } - -} \ No newline at end of file diff --git a/src/client/views/collections/CollectionMulticolumnView.tsx b/src/client/views/collections/CollectionMulticolumnView.tsx deleted file mode 100644 index ef15b29eb..000000000 --- a/src/client/views/collections/CollectionMulticolumnView.tsx +++ /dev/null @@ -1,331 +0,0 @@ -import { observer } from 'mobx-react'; -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 "./collectionMulticolumnView.scss"; -import { computed, trace, observable, action } from 'mobx'; -import { Transform } from '../../util/Transform'; - -type MulticolumnDocument = makeInterface<[typeof documentSchema]>; -const MulticolumnDocument = makeInterface(documentSchema); - -interface Unresolved { - target: Doc; - magnitude: number; - unit: string; -} - -interface LayoutData { - unresolved: Unresolved[]; - numFixed: number; - numRatio: number; - starSum: number; -} - -const resolvedUnits = ["*", "px"]; -const resizerWidth = 4; -const resizerOpacity = 1; - -@observer -export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocument) { - - @computed - private get ratioDefinedDocs() { - return this.childLayoutPairs.map(({ layout }) => layout).filter(({ widthUnit }) => StrCast(widthUnit) === "*"); - } - - @computed - private get resolvedLayoutInformation(): LayoutData { - const unresolved: Unresolved[] = []; - let starSum = 0, numFixed = 0, numRatio = 0; - - for (const { layout } of this.childLayoutPairs) { - const unit = StrCast(layout.widthUnit); - const magnitude = NumCast(layout.widthMagnitude); - if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) { - if (unit === "*") { - starSum += magnitude; - numRatio++; - } else { - numFixed++; - } - unresolved.push({ target: layout, magnitude, unit }); - } - // otherwise, the particular configuration entry is ignored and the remaining - // space is allocated as if the document were absent from the configuration list - } - - - setTimeout(() => { - const { ratioDefinedDocs } = this; - if (ratioDefinedDocs.length > 1) { - const minimum = Math.min(...ratioDefinedDocs.map(({ widthMagnitude }) => NumCast(widthMagnitude))); - ratioDefinedDocs.forEach(layout => layout.widthMagnitude = NumCast(layout.widthMagnitude) / minimum); - } - }); - - return { unresolved, numRatio, numFixed, starSum }; - } - - /** - * This returns the total quantity, in pixels, that this - * view needs to reserve for child documents that have - * (with higher priority) requested a fixed pixel width. - * - * If the underlying resolvedLayoutInformation returns null - * because we're waiting on promises to resolve, this value will be undefined as well. - */ - @computed - private get totalFixedAllocation(): number | undefined { - return this.resolvedLayoutInformation?.unresolved.reduce( - (sum, { magnitude, unit }) => sum + (unit === "px" ? magnitude : 0), 0); - } - - /** - * This returns the total quantity, in pixels, that this - * view needs to reserve for child documents that have - * (with lower priority) requested a certain relative proportion of the - * remaining pixel width not allocated for fixed widths. - * - * If the underlying totalFixedAllocation returns undefined - * because we're waiting indirectly on promises to resolve, this value will be undefined as well. - */ - @computed - private get totalRatioAllocation(): number | undefined { - const layoutInfoLen = this.resolvedLayoutInformation?.unresolved.length; - if (layoutInfoLen > 0 && this.totalFixedAllocation !== undefined) { - return this.props.PanelWidth() - (this.totalFixedAllocation + resizerWidth * (layoutInfoLen - 1)); - } - } - - /** - * This returns the total quantity, in pixels, that - * 1* (relative / star unit) is worth. For example, - * if the configuration has three documents, with, respectively, - * widths of 2*, 2* and 1*, and the panel width returns 1000px, - * this accessor returns 1000 / (2 + 2 + 1), or 200px. - * Elsewhere, this is then multiplied by each relative-width - * document's (potentially decimal) * count to compute its actual width (400px, 400px and 200px). - * - * If the underlying totalRatioAllocation or this.resolveLayoutInformation return undefined - * because we're waiting indirectly on promises to resolve, this value will be undefined as well. - */ - @computed - private get columnUnitLength(): number | undefined { - if (this.resolvedLayoutInformation && this.totalRatioAllocation !== undefined) { - return this.totalRatioAllocation / this.resolvedLayoutInformation.starSum; - } - } - - private getColumnUnitLength = () => this.columnUnitLength; - - private lookupPixels = (layout: Doc): number => { - const columnUnitLength = this.columnUnitLength; - if (columnUnitLength === undefined) { - return 0; // we're still waiting on promises to resolve - } - let width = NumCast(layout.widthMagnitude); - if (StrCast(layout.widthUnit) === "*") { - width *= columnUnitLength; - } - return width; - } - - private lookupIndividualTransform = (layout: Doc) => { - const columnUnitLength = this.columnUnitLength; - if (columnUnitLength === undefined) { - return Transform.Identity(); // we're still waiting on promises to resolve - } - let offset = 0; - for (const { layout: candidate } of this.childLayoutPairs) { - if (candidate === layout) { - const shift = offset; - return this.props.ScreenToLocalTransform().translate(-shift, 0); - } - offset += this.lookupPixels(candidate) + resizerWidth; - } - return Transform.Identity(); // type coersion, this case should never be hit - } - - @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( -
- this.lookupPixels(layout)} - PanelHeight={() => PanelHeight() - (BoolCast(Document.showWidthLabels) ? 20 : 0)} - getTransform={() => this.lookupIndividualTransform(layout)} - /> - -
, - - ); - } - collector.pop(); // removes the final extraneous resize bar - return collector; - } - - render(): JSX.Element { - return ( -
- {this.contents} -
- ); - } - -} - -interface ResizerProps { - width: number; - columnUnitLength(): number | undefined; - toLeft?: Doc; - toRight?: Doc; -} - -enum ResizeMode { - Global, - Pinned, - Undefined -} - -@observer -class ResizeBar extends React.Component { - @observable private isHoverActive = false; - @observable private isResizingActive = false; - private resizeMode = ResizeMode.Undefined; - - private registerResizing = (e: React.PointerEvent, 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 ( -
this.isHoverActive = true)} - onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))} - > -
this.registerResizing(e, ResizeMode.Pinned)} - /> -
this.registerResizing(e, ResizeMode.Global)} - /> -
- ); - } - -} - -interface WidthLabelProps { - layout: Doc; - collectionDoc: Doc; - decimals?: number; -} - -@observer -class WidthLabel extends React.Component { - - @computed - private get contents() { - const { layout, decimals } = this.props; - const magnitude = NumCast(layout.widthMagnitude).toFixed(decimals ?? 3); - const unit = StrCast(layout.widthUnit); - return {magnitude} {unit}; - } - - render() { - return BoolCast(this.props.collectionDoc.showWidthLabels) ? this.contents : (null); - } - -} \ No newline at end of file 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/collectionMulticolumn/CollectionMulticolumnView.scss b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss new file mode 100644 index 000000000..062b8ac11 --- /dev/null +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss @@ -0,0 +1,31 @@ +.collectionMulticolumnView_contents { + display: flex; + width: 100%; + height: 100%; + overflow: hidden; + + .document-wrapper { + display: flex; + flex-direction: column; + + .display { + text-align: center; + height: 20px; + } + + } + + .resizer { + cursor: ew-resize; + transition: 0.5s opacity ease; + display: flex; + flex-direction: column; + + .internal { + width: 100%; + height: 100%; + transition: 0.5s background-color ease; + } + } + +} \ No newline at end of file diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx new file mode 100644 index 000000000..e57e5eb26 --- /dev/null +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -0,0 +1,205 @@ +import { observer } from 'mobx-react'; +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 "./collectionMulticolumnView.scss"; +import { computed, trace, observable, action } from 'mobx'; +import { Transform } from '../../../util/Transform'; +import WidthLabel from './MulticolumnWidthLabel'; +import ResizeBar from './MulticolumnResizer'; + +type MulticolumnDocument = makeInterface<[typeof documentSchema]>; +const MulticolumnDocument = makeInterface(documentSchema); + +interface Unresolved { + target: Doc; + magnitude: number; + unit: string; +} + +interface LayoutData { + unresolved: Unresolved[]; + numFixed: number; + numRatio: number; + starSum: number; +} + +const resolvedUnits = ["*", "px"]; +const resizerWidth = 4; + +@observer +export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocument) { + + @computed + private get ratioDefinedDocs() { + return this.childLayoutPairs.map(({ layout }) => layout).filter(({ widthUnit }) => StrCast(widthUnit) === "*"); + } + + @computed + private get resolvedLayoutInformation(): LayoutData { + const unresolved: Unresolved[] = []; + let starSum = 0, numFixed = 0, numRatio = 0; + + for (const { layout } of this.childLayoutPairs) { + const unit = StrCast(layout.widthUnit); + const magnitude = NumCast(layout.widthMagnitude); + if (unit && magnitude && magnitude > 0 && resolvedUnits.includes(unit)) { + if (unit === "*") { + starSum += magnitude; + numRatio++; + } else { + numFixed++; + } + unresolved.push({ target: layout, magnitude, unit }); + } + // otherwise, the particular configuration entry is ignored and the remaining + // space is allocated as if the document were absent from the configuration list + } + + + setTimeout(() => { + const { ratioDefinedDocs } = this; + if (ratioDefinedDocs.length > 1) { + const minimum = Math.min(...ratioDefinedDocs.map(({ widthMagnitude }) => NumCast(widthMagnitude))); + ratioDefinedDocs.forEach(layout => layout.widthMagnitude = NumCast(layout.widthMagnitude) / minimum); + } + }); + + return { unresolved, numRatio, numFixed, starSum }; + } + + /** + * This returns the total quantity, in pixels, that this + * view needs to reserve for child documents that have + * (with higher priority) requested a fixed pixel width. + * + * If the underlying resolvedLayoutInformation returns null + * because we're waiting on promises to resolve, this value will be undefined as well. + */ + @computed + private get totalFixedAllocation(): number | undefined { + return this.resolvedLayoutInformation?.unresolved.reduce( + (sum, { magnitude, unit }) => sum + (unit === "px" ? magnitude : 0), 0); + } + + /** + * This returns the total quantity, in pixels, that this + * view needs to reserve for child documents that have + * (with lower priority) requested a certain relative proportion of the + * remaining pixel width not allocated for fixed widths. + * + * If the underlying totalFixedAllocation returns undefined + * because we're waiting indirectly on promises to resolve, this value will be undefined as well. + */ + @computed + private get totalRatioAllocation(): number | undefined { + const layoutInfoLen = this.resolvedLayoutInformation?.unresolved.length; + if (layoutInfoLen > 0 && this.totalFixedAllocation !== undefined) { + return this.props.PanelWidth() - (this.totalFixedAllocation + resizerWidth * (layoutInfoLen - 1)); + } + } + + /** + * This returns the total quantity, in pixels, that + * 1* (relative / star unit) is worth. For example, + * if the configuration has three documents, with, respectively, + * widths of 2*, 2* and 1*, and the panel width returns 1000px, + * this accessor returns 1000 / (2 + 2 + 1), or 200px. + * Elsewhere, this is then multiplied by each relative-width + * document's (potentially decimal) * count to compute its actual width (400px, 400px and 200px). + * + * If the underlying totalRatioAllocation or this.resolveLayoutInformation return undefined + * because we're waiting indirectly on promises to resolve, this value will be undefined as well. + */ + @computed + private get columnUnitLength(): number | undefined { + if (this.resolvedLayoutInformation && this.totalRatioAllocation !== undefined) { + return this.totalRatioAllocation / this.resolvedLayoutInformation.starSum; + } + } + + private getColumnUnitLength = () => this.columnUnitLength; + + private lookupPixels = (layout: Doc): number => { + const columnUnitLength = this.columnUnitLength; + if (columnUnitLength === undefined) { + return 0; // we're still waiting on promises to resolve + } + let width = NumCast(layout.widthMagnitude); + if (StrCast(layout.widthUnit) === "*") { + width *= columnUnitLength; + } + return width; + } + + private lookupIndividualTransform = (layout: Doc) => { + const columnUnitLength = this.columnUnitLength; + if (columnUnitLength === undefined) { + return Transform.Identity(); // we're still waiting on promises to resolve + } + let offset = 0; + for (const { layout: candidate } of this.childLayoutPairs) { + if (candidate === layout) { + const shift = offset; + return this.props.ScreenToLocalTransform().translate(-shift, 0); + } + offset += this.lookupPixels(candidate) + resizerWidth; + } + return Transform.Identity(); // type coersion, this case should never be hit + } + + @computed + private get contents(): JSX.Element[] | null { + 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( +
+ this.lookupPixels(layout)} + PanelHeight={() => PanelHeight() - (BoolCast(Document.showWidthLabels) ? 20 : 0)} + getTransform={() => this.lookupIndividualTransform(layout)} + /> + +
, + + ); + } + collector.pop(); // removes the final extraneous resize bar + return collector; + } + + render(): JSX.Element { + return ( +
+ {this.contents} +
+ ); + } + +} \ 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 { + @observable private isHoverActive = false; + @observable private isResizingActive = false; + @observable private resizeMode = ResizeMode.Undefined; + + @action + private registerResizing = (e: React.PointerEvent, 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 ( +
this.isHoverActive = true)} + onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))} + > +
this.registerResizing(e, ResizeMode.Pinned)} + style={{ backgroundColor: this.resizeMode }} + /> +
this.registerResizing(e, ResizeMode.Global)} + style={{ backgroundColor: this.resizeMode }} + /> +
+ ); + } + +} \ 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 { + + @computed + private get contents() { + const { layout, decimals } = this.props; + const magnitude = +NumCast(layout.widthMagnitude).toFixed(decimals ?? 3); + const unit = StrCast(layout.widthUnit); + return {magnitude} {unit}; + } + + render() { + return BoolCast(this.props.collectionDoc.showWidthLabels) ? this.contents : (null); + } + +} \ No newline at end of file -- cgit v1.2.3-70-g09d2