Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ function DataBarExample(): JSX.Element {
[
12,
[
{ column: 13, color: 'white' },
{ column: 14, color: 'gray' },
{ value: 13, color: 'white' },
{ value: 14, color: 'gray' },
],
],
]);
Expand Down
31 changes: 14 additions & 17 deletions packages/grid/src/DataBarCellRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class DataBarCellRenderer extends CellRenderer {
markers,
direction,
value,
} = model.dataBarOptionsForCell(modelColumn, modelRow);
} = model.dataBarOptionsForCell(modelColumn, modelRow, theme);

const hasGradient = Array.isArray(dataBarColor);
if (columnMin == null || columnMax == null) {
Expand Down Expand Up @@ -343,7 +343,7 @@ class DataBarCellRenderer extends CellRenderer {
markers,
direction,
value,
} = model.dataBarOptionsForCell(modelColumn, modelRow);
} = model.dataBarOptionsForCell(modelColumn, modelRow, theme);
const longestValueWidth = this.getCachedWidestValueForColumn(
context,
visibleRows,
Expand Down Expand Up @@ -398,11 +398,9 @@ class DataBarCellRenderer extends CellRenderer {
? zeroPosition
: zeroPosition - (Math.abs(value) / totalValueRange) * maxWidth;
let markerXs = markers.map(marker => {
const { column: markerColumn } = marker;
const markerValue = Number(model.textForCell(markerColumn, modelRow));
return markerValue >= 0
? zeroPosition + (Math.abs(markerValue) / totalValueRange) * maxWidth
: zeroPosition - (Math.abs(markerValue) / totalValueRange) * maxWidth;
const { value: markerValue } = marker;
const offset = (Math.abs(markerValue) / totalValueRange) * maxWidth;
return markerValue >= 0 ? zeroPosition + offset : zeroPosition - offset;
});
let leftmostPosition =
valuePlacement === 'beside' && textAlign === 'left'
Expand All @@ -424,8 +422,7 @@ class DataBarCellRenderer extends CellRenderer {
? zeroPosition - (value / totalValueRange) * maxWidth
: zeroPosition;
markerXs = markers.map(marker => {
const { column: markerColumn } = marker;
const markerValue = Number(model.textForCell(markerColumn, modelRow));
const { value: markerValue } = marker;
return markerValue >= 0
? zeroPosition - (Math.abs(markerValue) / totalValueRange) * maxWidth
: zeroPosition + (Math.abs(markerValue) / totalValueRange) * maxWidth;
Expand All @@ -441,8 +438,8 @@ class DataBarCellRenderer extends CellRenderer {
? zeroPosition
: zeroPosition - (Math.abs(value) / columnLongest) * (maxWidth / 2);
markerXs = markers.map(marker => {
const { column: markerColumn } = marker;
const markerValue = Number(model.textForCell(markerColumn, modelRow));
const { value: markerValue } = marker;

return markerValue >= 0
? zeroPosition +
(Math.abs(markerValue) / columnLongest) * (maxWidth / 2)
Expand All @@ -456,8 +453,8 @@ class DataBarCellRenderer extends CellRenderer {
? zeroPosition
: zeroPosition - (Math.abs(value) / columnLongest) * (maxWidth / 2);
markerXs = markers.map(marker => {
const { column: markerColumn } = marker;
const markerValue = Number(model.textForCell(markerColumn, modelRow));
const { value: markerValue } = marker;

return markerValue <= 0
? zeroPosition +
(Math.abs(markerValue) / columnLongest) * (maxWidth / 2)
Expand All @@ -471,8 +468,8 @@ class DataBarCellRenderer extends CellRenderer {
zeroPosition = 0;
dataBarX = zeroPosition;
markerXs = markers.map(marker => {
const { column: markerColumn } = marker;
const markerValue = Number(model.textForCell(markerColumn, modelRow));
const { value: markerValue } = marker;

return (
zeroPosition + (Math.abs(markerValue) / columnLongest) * maxWidth
);
Expand All @@ -482,8 +479,8 @@ class DataBarCellRenderer extends CellRenderer {
zeroPosition = columnWidth;
dataBarX = zeroPosition - (Math.abs(value) / columnLongest) * maxWidth;
markerXs = markers.map(marker => {
const { column: markerColumn } = marker;
const markerValue = Number(model.textForCell(markerColumn, modelRow));
const { value: markerValue } = marker;

return (
zeroPosition - (Math.abs(markerValue) / columnLongest) * maxWidth
);
Expand Down
9 changes: 7 additions & 2 deletions packages/grid/src/DataBarGridModel.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { GridThemeType } from '.';
import { ModelIndex } from './GridMetrics';
import GridModel from './GridModel';
import { GridColor } from './GridTheme';

export type Marker = { column: ModelIndex; color: string };
export type Marker = { value: number; color: string };
export type AxisOption = 'proportional' | 'middle' | 'directional';
export type ValuePlacementOption = 'beside' | 'overlap' | 'hide';
export type DirectionOption = 'LTR' | 'RTL';
Expand Down Expand Up @@ -49,5 +50,9 @@ export function isDataBarGridModel(
}

export interface DataBarGridModel extends GridModel {
dataBarOptionsForCell(column: ModelIndex, row: ModelIndex): DataBarOptions;
dataBarOptionsForCell(
column: ModelIndex,
row: ModelIndex,
theme: GridThemeType
): DataBarOptions;
}
2 changes: 2 additions & 0 deletions packages/grid/src/GridTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export type GridTheme = {
zeroLineColor: GridColor;
positiveBarColor: GridColor;
negativeBarColor: GridColor;
markerBarColor: GridColor;

dataBarHorizontalPadding: number;
};
Expand Down Expand Up @@ -232,6 +233,7 @@ const defaultTheme: GridTheme = Object.freeze({
zeroLineColor: '#888888',
positiveBarColor: '#00ff00',
negativeBarColor: '#ff0000',
markerBarColor: '#ffffff',

dataBarHorizontalPadding: 90,
});
Expand Down
1 change: 1 addition & 0 deletions packages/grid/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ export { default as TextCellRenderer } from './TextCellRenderer';
export { default as DataBarCellRenderer } from './DataBarCellRenderer';
export * from './TokenBoxCellRenderer';
export * from './GridRendererTypes';
export * from './DataBarGridModel';
26 changes: 20 additions & 6 deletions packages/iris-grid/src/IrisGridModel.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable class-methods-use-this */
import type { Event, EventTarget } from 'event-target-shim';
import {
DataBarGridModel,
DataBarOptions,
GridModel,
GridRange,
ModelIndex,
Expand Down Expand Up @@ -29,6 +31,7 @@ import {
PendingDataErrorMap,
} from './CommonTypes';
import ColumnHeaderGroup from './ColumnHeaderGroup';
import { IrisGridThemeType } from './IrisGridTheme';

type IrisGridModelEventNames =
(typeof IrisGridModel.EVENT)[keyof typeof IrisGridModel.EVENT];
Expand All @@ -47,12 +50,15 @@ const EMPTY_ARRAY: never[] = [];
* those out as well, so there's no dependency on IrisAPI at all, but it's a lot of work for no real gain at this time.
*/
abstract class IrisGridModel<
TEventMap extends Record<string, Event<string>> = Record<
string,
Event<string>
>,
TMode extends 'standard' | 'strict' = 'standard',
> extends GridModel<TEventMap & IrisGridModelEventMap, TMode> {
TEventMap extends Record<string, Event<string>> = Record<
string,
Event<string>
>,
TMode extends 'standard' | 'strict' = 'standard',
>
extends GridModel<TEventMap & IrisGridModelEventMap, TMode>
implements DataBarGridModel
{
static EVENT = Object.freeze({
UPDATED: 'UPDATED',
FORMATTER_UPDATED: 'FORMATTER_UPDATED',
Expand Down Expand Up @@ -532,6 +538,14 @@ abstract class IrisGridModel<
modelIndex: ModelIndex,
depth: number
): ColumnHeaderGroup | undefined;

dataBarOptionsForCell(
column: number,
row: number,
theme: IrisGridThemeType
): DataBarOptions {
throw new Error('Method not implemented.');
}
}

export default IrisGridModel;
6 changes: 6 additions & 0 deletions packages/iris-grid/src/IrisGridProxyModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,12 @@ class IrisGridProxyModel extends IrisGridModel {
valueForCell: IrisGridModel['valueForCell'] = (...args) =>
this.model.valueForCell(...args);

renderTypeForCell: IrisGridModel['renderTypeForCell'] = (...args) =>
this.model.renderTypeForCell(...args);

dataBarOptionsForCell: IrisGridModel['dataBarOptionsForCell'] = (...args) =>
this.model.dataBarOptionsForCell(...args);

get filter(): readonly FilterCondition[] {
return this.model.filter;
}
Expand Down
56 changes: 56 additions & 0 deletions packages/iris-grid/src/IrisGridTableModelTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import memoize from 'memoize-one';
import throttle from 'lodash.throttle';
import {
CellRenderType,
EditOperation,
GridRange,
GridUtils,
Expand Down Expand Up @@ -38,6 +39,13 @@ import {
assertNotNull,
} from '@deephaven/utils';
import { TableUtils, Formatter, FormatterUtils } from '@deephaven/jsapi-utils';
import {
AxisOption,
DataBarOptions,
DirectionOption,
Marker,
ValuePlacementOption,
} from 'packages/grid/src/DataBarGridModel';
import IrisGridModel from './IrisGridModel';
import AggregationOperation from './sidebar/aggregations/AggregationOperation';
import IrisGridUtils from './IrisGridUtils';
Expand Down Expand Up @@ -635,6 +643,54 @@ class IrisGridTableModelTemplate<
return 'left';
}

dataBarOptionsForCell(
column: ModelIndex,
row: ModelIndex,
theme: IrisGridThemeType
): DataBarOptions {
const format = this.formatForCell(column, row);
assertNotNull(format);
const { axis, direction, max, min, valuePlacement, value, marker } =
format.formatDataBar;
let { positiveColor, negativeColor, markerColor, opacity } =
format.formatDataBar;

positiveColor = positiveColor ?? theme.positiveBarColor;
negativeColor = negativeColor ?? theme.negativeBarColor;
let databarColor: string | string[] =
format.color ?? (value >= 0 ? positiveColor : negativeColor);
if (databarColor.includes(',')) {
databarColor = databarColor.split(',');
}
markerColor = markerColor ?? theme.markerBarColor;

opacity = valuePlacement.toLowerCase() === 'overlap' ? 0.5 : opacity;

const databarOptions = {
axis: axis.toLowerCase() as AxisOption,
direction: direction.toUpperCase() as DirectionOption,
columnMax: max,
columnMin: min,
opacity,
color: databarColor,
valuePlacement: valuePlacement.toLowerCase() as ValuePlacementOption,
value,
markers: [
{
value: marker,
color: markerColor,
},
] as Marker[],
};

return databarOptions;
}

renderTypeForCell(column: ModelIndex, row: ModelIndex): CellRenderType {
const format = this.formatForCell(column, row);
return format?.formatDataBar != null ? 'dataBar' : 'text';
}

textForColumnHeader(x: ModelIndex, depth = 0): string | undefined {
const header = this.columnAtDepth(x, depth);
if (isColumnHeaderGroup(header)) {
Expand Down
1 change: 1 addition & 0 deletions packages/iris-grid/src/IrisGridTheme.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,5 @@ $header-height: 30px;
zero-line-color: $gray-500;
positive-bar-color: $green;
negative-bar-color: $red;
marker-bar-color: $white;
}
1 change: 1 addition & 0 deletions packages/iris-grid/src/IrisGridTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ const theme: Partial<IrisGridThemeType> = Object.freeze({
zeroLineColor: IrisGridTheme['zero-line-color'],
positiveBarColor: IrisGridTheme['positive-bar-color'],
negativeBarColor: IrisGridTheme['negative-bar-color'],
markerBarColor: IrisGridTheme['marker-bar-color'],
});

export default theme;
15 changes: 15 additions & 0 deletions packages/jsapi-types/src/dh.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,21 @@ export interface Format {
readonly color: string;
readonly backgroundColor: string;
readonly formatString: string;
readonly formatDataBar: DatabarFormat;
}

export interface DatabarFormat {
axis: string;
direction: string;
max: number;
min: number;
negativeColor: string | string[];
opacity: number;
positiveColor: string | string[];
valuePlacement: string;
value: number;
marker: number;
markerColor: string | string[];
}

export interface ColumnStatistics {
Expand Down