Skip to content

Commit

Permalink
work on level dependend spacing
Browse files Browse the repository at this point in the history
  • Loading branch information
sgratzl committed Dec 27, 2018
1 parent b219071 commit 68c4637
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 119 deletions.
7 changes: 1 addition & 6 deletions src/model/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,18 +162,13 @@ export interface IGroupParent extends IGroup {
subGroups: (Readonly<IGroupParent> | Readonly<IGroup>)[];
}

export declare type IGroupMeta = 'first' | 'last' | 'first last' | 'inner' | 'first top' | null;

export interface IGroupItem {
readonly dataIndex: number;
readonly group: Readonly<IOrderedGroup>;
readonly relativeIndex: number;
readonly meta: IGroupMeta;
}

export interface IGroupData extends Readonly<IOrderedGroup> {
readonly meta: IGroupMeta;
}
export declare type IGroupData = Readonly<IOrderedGroup>;

export function isGroup(item: IGroupData | IGroupItem): item is IGroupData {
return item && (<IGroupItem>item).group == null; // use .group as separator
Expand Down
77 changes: 76 additions & 1 deletion src/model/internal.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {schemeCategory10, schemeSet3} from 'd3-scale-chromatic';
import Column, {defaultGroup, IGroup, IGroupParent, IndicesArray, IOrderedGroup, ECompareValueType} from '.';
import {OrderedSet} from '../internal';
import {DEFAULT_COLOR} from './interfaces';
import {DEFAULT_COLOR, IGroupData, IGroupItem, isGroup} from './interfaces';


/** @internal */
Expand Down Expand Up @@ -101,6 +101,81 @@ export function isOrderedGroup(g: IOrderedGroup | Readonly<IGroupParent>): g is
return (<IOrderedGroup>g).order != null;
}

declare type IGroupMeta = 'first' | 'last' | 'first last' | null;

function toItemMeta(item: IGroupItem): IGroupMeta {
if (item.relativeIndex === 0) {
return item.group.order.length === 1 ? 'first last' : 'first';
}
if (item.relativeIndex === item.group.order.length - 1) {
return 'last';
}
return null;
}

function groupParents(group: IGroup, meta: IGroupMeta) {
const parents: {group: IGroup, meta: IGroupMeta}[] = [{group, meta}];

let prev = group;
let parent: IGroupParent | undefined | null = group.parent;

while (parent) {
if (parent.subGroups.length === 1) {
meta = 'first last';
} else if (parent.subGroups[0] === prev) {
meta = 'first';
} else if (parent.subGroups[parent.subGroups.length - 1] === prev) {
meta = 'last';
} else {
meta = null;
}
parents.unshift({group: parent, meta});

prev = parent;
parent = parent.parent;
}
return parents;
}

/**
* number of group levels this items ends
*/
export function groupEndLevel(item: IGroupData | IGroupItem) {
const last = isGroup(item) ? 'first last' : toItemMeta(item);
if (last !== 'last' && last !== 'first last') {
return 0;
}

const group: IGroup = isGroup(item) ? item : item.group;
let prev = group;
let parent: IGroupParent | undefined | null = group.parent;
let i = 1;

while(parent) {
if (!(parent.subGroups.length === 1 || (parent.subGroups[parent.subGroups.length - 1] === prev))) {
// not last of group - end
return i;
}
++i;
prev = parent;
parent = parent.parent;
}

return i;
}

export function toRowMeta(item: IGroupData | IGroupItem): string | null {
const last = isGroup(item) ? 'first last' : toItemMeta(item);
if (last == null) {
return null;
}
const level = groupEndLevel(item);
if (level === 0) {
return null;
}
return `last${level === 1 ? '' : level - 1}`;
}

// based on https://github.com/d3/d3-scale-chromatic#d3-scale-chromatic
const colors = schemeCategory10.concat(schemeSet3);

Expand Down
13 changes: 5 additions & 8 deletions src/renderer/AAggregatedGroupRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import {Column, IDataRow, IGroupMeta, IOrderedGroup} from '../model';
import {
IRenderContext, ERenderMode, ICellRenderer, ICellRendererFactory, IGroupCellRenderer,
IImposer
} from './interfaces';
import {noRenderer} from './utils';
import {ISequence} from '../internal';
import {Column, IDataRow, IOrderedGroup} from '../model';
import {ERenderMode, ICellRenderer, ICellRendererFactory, IGroupCellRenderer, IImposer, IRenderContext} from './interfaces';
import {noRenderer} from './utils';

/**
* helper class that renders a group renderer as a selected (e.g. median) single item
Expand All @@ -23,10 +20,10 @@ export abstract class AAggregatedGroupRenderer<T extends Column> implements ICel
const single = this.create(col, context, imposer);
return {
template: `<div>${single.template}</div>`,
update: (node: HTMLElement, group: IOrderedGroup, groupMeta: IGroupMeta) => {
update: (node: HTMLElement, group: IOrderedGroup) => {
return context.tasks.groupRows(col, group, 'aagreated', (rows) => this.aggregatedIndex(rows, col)).then((data) => {
if (typeof data !== 'symbol') {
single.update(<HTMLElement>node.firstElementChild!, data.row, data.index, group, groupMeta);
single.update(<HTMLElement>node.firstElementChild!, data.row, data.index, group);
}
});
}
Expand Down
40 changes: 7 additions & 33 deletions src/renderer/AggregateGroupRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {IDataRow, IGroup, IGroupMeta, Column, AggregateGroupColumn, EAggregationState, IGroupParent} from '../model';
import {IDataRow, IGroup, Column, AggregateGroupColumn, EAggregationState, IGroupParent, IOrderedGroup} from '../model';
import {AGGREGATE, CANVAS_HEIGHT, cssClass} from '../styles';
import {IRenderContext, ICellRendererFactory} from './interfaces';

Expand All @@ -7,32 +7,6 @@ function preventDefault(event: Event) {
event.stopPropagation();
}

function groupParents(group: IGroup, meta: IGroupMeta) {
const parents: {group: IGroup, meta: IGroupMeta}[] = [{group, meta}];

let prev = group;
let prevMeta = meta;
let parent: IGroupParent | undefined | null = group.parent;

while (parent) {
if (parent.subGroups.length === 1 && prevMeta === 'first last') {
meta = 'first last';
} else if (parent.subGroups[0] === prev && (prevMeta === 'first' || prevMeta === 'first last')) {
meta = 'first';
} else if (parent.subGroups[parent.subGroups.length - 1] === prev && (prevMeta === 'last' || prevMeta === 'first last')) {
meta = 'last';
} else {
meta = null;
}
parents.unshift({group: parent, meta});

prevMeta = meta;
prev = parent;
parent = parent.parent;
}
return parents;
}

function matchNodes(node: HTMLElement, group: IGroup, meta: IGroupMeta, col: AggregateGroupColumn) {
const parents = groupParents(group, meta);
const doc = node.ownerDocument!;
Expand Down Expand Up @@ -84,13 +58,13 @@ export default class AggregateGroupRenderer implements ICellRendererFactory {
const width = context.colWidth(col);
return {
template: `<div><div class="${cssClass('agg-level')}"></div></div>`,
update(node: HTMLElement, _row: IDataRow, _i: number, group: IGroup, meta: IGroupMeta) {
matchNodes(node, group, meta, col);
update(node: HTMLElement, _row: IDataRow, _i: number, group: IOrderedGroup) {
// matchNodes(node, group, meta, col);
},
render(ctx: CanvasRenderingContext2D, _row: IDataRow, _i: number, _group: IGroup, meta: IGroupMeta) {
render(ctx: CanvasRenderingContext2D, _row: IDataRow, _i: number, _group: IGroup) {
ctx.fillStyle = AGGREGATE.color;
ctx.fillRect(width - AGGREGATE.width, 0, AGGREGATE.strokeWidth, CANVAS_HEIGHT);
return Boolean(meta);
return Boolean(false);
}
};
}
Expand All @@ -99,8 +73,8 @@ export default class AggregateGroupRenderer implements ICellRendererFactory {
const _showMore = context.provider.getShowTopN() > 0;
return {
template: `<div><div class="${cssClass('agg-level')}"></div></div>`,
update(node: HTMLElement, group: IGroup, meta: IGroupMeta) {
matchNodes(node, group, meta, col);
update(node: HTMLElement, group: IOrderedGroup) {
// matchNodes(node, group, meta, col);

// const children = <HTMLElement[]>Array.from(node.children);

Expand Down
14 changes: 7 additions & 7 deletions src/renderer/InterleavingCellRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {INumberBin, IStatistics} from '../internal';
import {Column, CompositeNumberColumn, IDataRow, IGroupMeta, IOrderedGroup, INumberColumn} from '../model';
import {Column, CompositeNumberColumn, IDataRow, IOrderedGroup, INumberColumn} from '../model';
import {CANVAS_HEIGHT, cssClass} from '../styles';
import {getHistDOMRenderer} from './HistogramCellRenderer';
import {IRenderContext, ERenderMode, ICellRendererFactory} from './interfaces';
Expand All @@ -22,17 +22,17 @@ export default class InterleavingCellRenderer implements ICellRendererFactory {
const width = context.colWidth(col);
return {
template: `<div>${cols.map((r) => r.template).join('')}</div>`,
update: (n: HTMLDivElement, d: IDataRow, i: number, group: IOrderedGroup, meta: IGroupMeta) => {
update: (n: HTMLDivElement, d: IDataRow, i: number, group: IOrderedGroup) => {
const missing = renderMissingDOM(n, col, d);
if (missing) {
return;
}
matchColumns(n, cols, context);
forEachChild(n, (ni: HTMLElement, j) => {
cols[j].renderer!.update(ni, d, i, group, meta);
cols[j].renderer!.update(ni, d, i, group);
});
},
render: (ctx: CanvasRenderingContext2D, d: IDataRow, _i: number, group: IOrderedGroup, meta: IGroupMeta) => {
render: (ctx: CanvasRenderingContext2D, d: IDataRow, _i: number, group: IOrderedGroup) => {
if (renderMissingCanvas(ctx, col, d, width)) {
return;
}
Expand All @@ -42,7 +42,7 @@ export default class InterleavingCellRenderer implements ICellRendererFactory {
cols.forEach((r, i) => {
const rr = r.renderer!;
if (rr.render) {
rr.render(ctx, d, i, group, meta);
rr.render(ctx, d, i, group);
}
ctx.translate(0, CANVAS_HEIGHT);
});
Expand All @@ -55,10 +55,10 @@ export default class InterleavingCellRenderer implements ICellRendererFactory {
const {cols} = createData(col, context, false, ERenderMode.GROUP);
return {
template: `<div>${cols.map((r) => r.template).join('')}</div>`,
update: (n: HTMLElement, group: IOrderedGroup, meta: IGroupMeta) => {
update: (n: HTMLElement, group: IOrderedGroup) => {
matchColumns(n, cols, context);
forEachChild(n, (ni: HTMLElement, j) => {
cols[j].groupRenderer!.update(ni, group, meta);
cols[j].groupRenderer!.update(ni, group);
});
}
};
Expand Down
14 changes: 7 additions & 7 deletions src/renderer/MultiLevelCellRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ISequence, round} from '../internal';
import {Column, IDataRow, INumberColumn, isNumberColumn, IMultiLevelColumn, isMultiLevelColumn, IGroupMeta, IOrderedGroup} from '../model';
import {Column, IDataRow, INumberColumn, isNumberColumn, IMultiLevelColumn, isMultiLevelColumn, IOrderedGroup} from '../model';
import {medianIndex} from '../model/internalNumber';
import {COLUMN_PADDING} from '../styles';
import {AAggregatedGroupRenderer} from './AAggregatedGroupRenderer';
Expand Down Expand Up @@ -80,7 +80,7 @@ export default class MultiLevelCellRenderer extends AAggregatedGroupRenderer<IMu
const width = context.colWidth(col);
return {
template: `<div class='${multiLevelGridCSSClass(context.idPrefix, col)} ${!stacked ? cssClass('grid-space') : ''}'>${cols.map((d) => d.template).join('')}</div>`,
update: (n: HTMLDivElement, d: IDataRow, i: number, group: IOrderedGroup, meta: IGroupMeta) => {
update: (n: HTMLDivElement, d: IDataRow, i: number, group: IOrderedGroup) => {
if (renderMissingDOM(n, col, d)) {
return null;
}
Expand All @@ -97,7 +97,7 @@ export default class MultiLevelCellRenderer extends AAggregatedGroupRenderer<IMu
cnode.dataset.group = 'd';
cnode.style.transform = stacked ? `translate(-${round((missingWeight / weight) * 100, 4)}%,0)` : null;
cnode.style.gridColumnStart = (ci + 1).toString();
const r = col.renderer!.update(cnode, d, i, group, meta);
const r = col.renderer!.update(cnode, d, i, group);
if (stacked) {
missingWeight += (1 - (<INumberColumn>col.column).getNumber(d)) * weight;
}
Expand All @@ -111,7 +111,7 @@ export default class MultiLevelCellRenderer extends AAggregatedGroupRenderer<IMu
}
return null;
},
render: (ctx: CanvasRenderingContext2D, d: IDataRow, i: number, group: IOrderedGroup, meta: IGroupMeta) => {
render: (ctx: CanvasRenderingContext2D, d: IDataRow, i: number, group: IOrderedGroup) => {
if (renderMissingCanvas(ctx, col, d, width)) {
return null;
}
Expand All @@ -122,7 +122,7 @@ export default class MultiLevelCellRenderer extends AAggregatedGroupRenderer<IMu
if (cr.render) {
const shift = col.shift - stackShift;
ctx.translate(shift, 0);
const r = cr.render(ctx, d, i, group, meta);
const r = cr.render(ctx, d, i, group);
if (typeof r !== 'boolean' && r) {
toWait.push({shift, r});
}
Expand Down Expand Up @@ -167,7 +167,7 @@ export default class MultiLevelCellRenderer extends AAggregatedGroupRenderer<IMu
const {cols} = createData(col, context, false, ERenderMode.GROUP, imposer);
return {
template: `<div class='${multiLevelGridCSSClass(context.idPrefix, col)} ${cssClass('grid-space')}'>${cols.map((d) => d.template).join('')}</div>`,
update: (n: HTMLElement, group: IOrderedGroup, meta: IGroupMeta) => {
update: (n: HTMLElement, group: IOrderedGroup) => {
matchColumns(n, cols, context);

const toWait: IAbortAblePromise<void>[] = [];
Expand All @@ -177,7 +177,7 @@ export default class MultiLevelCellRenderer extends AAggregatedGroupRenderer<IMu
cnode.classList.add(cssClass('stack-sub'), cssClass('group'));
cnode.dataset.group = 'g';
cnode.style.gridColumnStart = (ci + 1).toString();
const r = col.groupRenderer!.update(cnode, group, meta);
const r = col.groupRenderer!.update(cnode, group);
if (r) {
toWait.push(r);
}
Expand Down
8 changes: 4 additions & 4 deletions src/renderer/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {IAbortAblePromise} from 'lineupengine';
import {Column, IDataRow, IGroupMeta, IOrderedGroup, INumberColumn, ICategoricalLikeColumn, IDateColumn} from '../model';
import {Column, IDataRow, IOrderedGroup, INumberColumn, ICategoricalLikeColumn, IDateColumn} from '../model';
import {IDataProvider} from '../provider';
import DialogManager from '../ui/dialogs/DialogManager';
import {ISequence, IDateStatistics, ICategoricalStatistics, IAdvancedBoxPlotData, IStatistics} from '../internal';
Expand Down Expand Up @@ -27,13 +27,13 @@ export interface ICellRenderer {
* @param i the order relative index
* @param group the group this row is part of
*/
update(node: HTMLElement, d: IDataRow, i: number, group: IOrderedGroup, meta: IGroupMeta): void | IAbortAblePromise<void> | null;
update(node: HTMLElement, d: IDataRow, i: number, group: IOrderedGroup): void | IAbortAblePromise<void> | null;

/**
* render a low detail canvas row
* @return true if a dom element is needed
*/
render?(ctx: CanvasRenderingContext2D, d: IDataRow, i: number, group: IOrderedGroup, meta: IGroupMeta): void | IAbortAblePromise<IRenderCallback> | boolean | null;
render?(ctx: CanvasRenderingContext2D, d: IDataRow, i: number, group: IOrderedGroup): void | IAbortAblePromise<IRenderCallback> | boolean | null;
}

/**
Expand All @@ -50,7 +50,7 @@ export interface IGroupCellRenderer {
* @param node the node to update
* @param group the group to render
*/
update(node: HTMLElement, group: IOrderedGroup, meta: IGroupMeta): void | IAbortAblePromise<void> | null;
update(node: HTMLElement, group: IOrderedGroup): void | IAbortAblePromise<void> | null;
}

export interface ISummaryRenderer {
Expand Down
Loading

0 comments on commit 68c4637

Please sign in to comment.