diff options
author | bob <bcz@cs.brown.edu> | 2019-04-29 10:40:05 -0400 |
---|---|---|
committer | bob <bcz@cs.brown.edu> | 2019-04-29 10:40:05 -0400 |
commit | 9e6c6fe35d481a860145359f0df11d89b1c2329b (patch) | |
tree | 1dbd0e914c175b032970d7598cd3292b34dd54f9 | |
parent | a180574f56447d6f24b4e77f87efba3a1287da9c (diff) |
fixed histograms.
4 files changed, 64 insertions, 38 deletions
diff --git a/src/client/northstar/core/filter/ValueComparision.ts b/src/client/northstar/core/filter/ValueComparision.ts index 80b1242a9..65687a82b 100644 --- a/src/client/northstar/core/filter/ValueComparision.ts +++ b/src/client/northstar/core/filter/ValueComparision.ts @@ -62,13 +62,13 @@ export class ValueComparison { var rawName = this.attributeModel.CodeName; switch (this.Predicate) { case Predicate.STARTS_WITH: - ret += rawName + " !== null && " + rawName + ".StartsWith(" + val + ") "; + ret += rawName + " != null && " + rawName + ".StartsWith(" + val + ") "; return ret; case Predicate.ENDS_WITH: - ret += rawName + " !== null && " + rawName + ".EndsWith(" + val + ") "; + ret += rawName + " != null && " + rawName + ".EndsWith(" + val + ") "; return ret; case Predicate.CONTAINS: - ret += rawName + " !== null && " + rawName + ".Contains(" + val + ") "; + ret += rawName + " != null && " + rawName + ".Contains(" + val + ") "; return ret; default: ret += rawName + " " + op + " " + val + " "; diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index e2ecc8c83..ac5f3c8cf 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -1,7 +1,6 @@ import React = require("react"); import { action, computed, observable, reaction, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; -import Measure from "react-measure"; import { FieldWaiting, Opt } from "../../../fields/Field"; import { Document } from "../../../fields/Document"; import { KeyStore } from "../../../fields/KeyStore"; @@ -31,8 +30,6 @@ export class HistogramBox extends React.Component<FieldViewProps> { private _dropXDisposer?: DragManager.DragDropDisposer; private _dropYDisposer?: DragManager.DragDropDisposer; - @observable public PanelWidth: number = 100; - @observable public PanelHeight: number = 100; @observable public HistoOp: HistogramOperation = HistogramOperation.Empty; @observable public VisualBinRanges: VisualBinRange[] = []; @observable public ValueRange: number[] = []; @@ -88,7 +85,7 @@ export class HistogramBox extends React.Component<FieldViewProps> { } reaction(() => CurrentUserUtils.NorthstarDBCatalog, (catalog?: Catalog) => this.activateHistogramOperation(catalog), { fireImmediately: true }); reaction(() => [this.VisualBinRanges && this.VisualBinRanges.slice()], () => this.SizeConverter.SetVisualBinRanges(this.VisualBinRanges)); - reaction(() => [this.PanelHeight, this.PanelWidth], () => this.SizeConverter.SetIsSmall(this.PanelWidth < 40 && this.PanelHeight < 40)); + reaction(() => [this.props.PanelWidth(), this.props.PanelHeight()], (size: number[]) => this.SizeConverter.SetIsSmall(size[0] < 40 && size[1] < 40)); reaction(() => this.HistogramResult ? this.HistogramResult.binRanges : undefined, (binRanges: BinRange[] | undefined) => { if (binRanges) { @@ -134,38 +131,39 @@ export class HistogramBox extends React.Component<FieldViewProps> { })); } } + + @action + private onScrollWheel = (e: React.WheelEvent) => { + this.HistoOp.DrillDown(e.deltaY > 0); + e.stopPropagation(); + } + render() { let labelY = this.HistoOp && this.HistoOp.Y ? this.HistoOp.Y.PresentedName : "<...>"; let labelX = this.HistoOp && this.HistoOp.X ? this.HistoOp.X.PresentedName : "<...>"; - var h = this.props.isTopMost ? this.PanelHeight : this.props.Document.GetNumber(KeyStore.Height, 0); - var w = this.props.isTopMost ? this.PanelWidth : this.props.Document.GetNumber(KeyStore.Width, 0); let loff = this.SizeConverter.LeftOffset; let toff = this.SizeConverter.TopOffset; let roff = this.SizeConverter.RightOffset; let boff = this.SizeConverter.BottomOffset; return ( - <Measure onResize={(r: any) => runInAction(() => { this.PanelWidth = r.entry.width; this.PanelHeight = r.entry.height; })}> - {({ measureRef }) => - <div className="histogrambox-container" ref={measureRef}> - <div className="histogrambox-yaxislabel" onPointerDown={this.yLabelPointerDown} ref={this._dropYRef} > - <span className="histogrambox-yaxislabel-text"> - {labelY} - </span> - </div> - <div className="histogrambox-primitives" style={{ - transform: `translate(${loff + 25}px, ${toff}px)`, - width: `calc(100% - ${loff + roff + 25}px)`, - height: `calc(100% - ${toff + boff}px)`, - }}> - <HistogramLabelPrimitives HistoBox={this} /> - <HistogramBoxPrimitives HistoBox={this} /> - </div> - <div className="histogrambox-xaxislabel" onPointerDown={this.xLabelPointerDown} ref={this._dropXRef} > - {labelX} - </div> - </div> - } - </Measure> + <div className="histogrambox-container" onWheel={this.onScrollWheel}> + <div className="histogrambox-yaxislabel" onPointerDown={this.yLabelPointerDown} ref={this._dropYRef} > + <span className="histogrambox-yaxislabel-text"> + {labelY} + </span> + </div> + <div className="histogrambox-primitives" style={{ + transform: `translate(${loff + 25}px, ${toff}px)`, + width: `calc(100% - ${loff + roff + 25}px)`, + height: `calc(100% - ${toff + boff}px)`, + }}> + <HistogramLabelPrimitives HistoBox={this} /> + <HistogramBoxPrimitives HistoBox={this} /> + </div> + <div className="histogrambox-xaxislabel" onPointerDown={this.xLabelPointerDown} ref={this._dropXRef} > + {labelX} + </div> + </div> ); } } diff --git a/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx index 5785fe838..62aebd3c6 100644 --- a/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx +++ b/src/client/northstar/dash-nodes/HistogramLabelPrimitives.tsx @@ -12,7 +12,7 @@ import { HistogramPrimitivesProps } from "./HistogramBoxPrimitives"; @observer export class HistogramLabelPrimitives extends React.Component<HistogramPrimitivesProps> { componentDidMount() { - reaction(() => [this.props.HistoBox.PanelWidth, this.props.HistoBox.SizeConverter.LeftOffset, this.props.HistoBox.VisualBinRanges.length], + reaction(() => [this.props.HistoBox.props.PanelWidth(), this.props.HistoBox.SizeConverter.LeftOffset, this.props.HistoBox.VisualBinRanges.length], (fields) => HistogramLabelPrimitives.computeLabelAngle(fields[0], fields[1], this.props.HistoBox), { fireImmediately: true }); } @@ -35,7 +35,7 @@ export class HistogramLabelPrimitives extends React.Component<HistogramPrimitive if (!vb.length || !sc.Initialized) { return (null); } - let dim = (axis === 0 ? this.props.HistoBox.PanelWidth : this.props.HistoBox.PanelHeight) / ((axis === 0 && vb[axis] instanceof NominalVisualBinRange) ? + let dim = (axis === 0 ? this.props.HistoBox.props.PanelWidth() : this.props.HistoBox.props.PanelHeight()) / ((axis === 0 && vb[axis] instanceof NominalVisualBinRange) ? (12 + 5) : // (<number>FontStyles.AxisLabel.fontSize + 5))); sc.MaxLabelSizes[axis].coords[axis] + 5); @@ -49,12 +49,12 @@ export class HistogramLabelPrimitives extends React.Component<HistogramPrimitive let yStart = (axis === 1 ? r.yFrom - textHeight / 2 : r.yFrom); if (axis === 0 && vb[axis] instanceof NominalVisualBinRange) { - let space = (r.xTo - r.xFrom) / sc.RenderDimension * this.props.HistoBox.PanelWidth; + let space = (r.xTo - r.xFrom) / sc.RenderDimension * this.props.HistoBox.props.PanelWidth(); xStart += Math.max(textWidth / 2, (1 - textWidth / space) * textWidth / 2) - textHeight / 2; } let xPercent = axis === 1 ? `${xStart}px` : `${xStart / sc.RenderDimension * 100}%`; - let yPercent = axis === 0 ? `${this.props.HistoBox.PanelHeight - sc.BottomOffset - textHeight}px` : `${yStart / sc.RenderDimension * 100}%`; + let yPercent = axis === 0 ? `${this.props.HistoBox.props.PanelHeight() - sc.BottomOffset - textHeight}px` : `${yStart / sc.RenderDimension * 100}%`; prims.push( <div className="histogramLabelPrimitives-placer" key={DashUtils.GenerateGuid()} style={{ transform: `translate(${xPercent}, ${yPercent})` }}> diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts index 760106023..6a8c9d8cf 100644 --- a/src/client/northstar/operations/HistogramOperation.ts +++ b/src/client/northstar/operations/HistogramOperation.ts @@ -23,7 +23,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons @observable public Links: Document[] = []; @observable public BrushLinks: { l: Document, b: Document }[] = []; @observable public BrushColors: number[] = []; - @observable public FilterModels: FilterModel[] = []; + @observable public BarFilterModels: FilterModel[] = []; @observable public Normalization: number = -1; @observable public X: AttributeTransformationModel; @@ -50,17 +50,24 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons throw new Error("Method not implemented."); } + + @computed public get FilterModels() { + return this.BarFilterModels; + } @action public AddFilterModels(filterModels: FilterModel[]): void { - filterModels.filter(f => f !== null).forEach(fm => this.FilterModels.push(fm)); + filterModels.filter(f => f !== null).forEach(fm => this.BarFilterModels.push(fm)); } @action public RemoveFilterModels(filterModels: FilterModel[]): void { - ArrayUtil.RemoveMany(this.FilterModels, filterModels); + ArrayUtil.RemoveMany(this.BarFilterModels, filterModels); } @computed public get FilterString(): string { + if (this.OverridingFilters.length > 0) { + return "(" + this.OverridingFilters.filter(fm => fm != null).map(fm => fm.ToPythonString()).join(" || ") + ")"; + } let filterModels: FilterModel[] = []; return FilterModel.GetFilterModelsRecursive(this, new Set<IBaseFilterProvider>(), filterModels, true); } @@ -79,6 +86,27 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons return brushes; } + _stackedFilters: (FilterModel[])[] = []; + @action + public DrillDown(up: boolean) { + if (!up) { + if (!this.BarFilterModels.length) + return; + this._stackedFilters.push(this.BarFilterModels.map(f => f)); + this.OverridingFilters.length = 0; + this.OverridingFilters.push(...this._stackedFilters[this._stackedFilters.length - 1]); + this.BarFilterModels.map(fm => fm).map(fm => this.RemoveFilterModels([fm])); + //this.updateHistogram(); + } else { + this.OverridingFilters.length = 0; + if (this._stackedFilters.length) { + this.OverridingFilters.push(...this._stackedFilters.pop()!); + } + // else + // this.updateHistogram(); + } + } + private getAggregateParameters(histoX: AttributeTransformationModel, histoY: AttributeTransformationModel, histoValue: AttributeTransformationModel) { let allAttributes = new Array<AttributeTransformationModel>(histoX, histoY, histoValue); allAttributes = ArrayUtil.Distinct(allAttributes.filter(a => a.AggregateFunction !== AggregateFunction.None)); |