terriajs
Version:
Geospatial data visualization platform.
170 lines (148 loc) • 4.48 kB
text/typescript
import { computed, makeObservable } from "mobx";
import JsonValue from "../Core/Json";
import { NotUndefined } from "../Core/TypeModifiers";
import TableMixin from "../ModelMixins/TableMixin";
import Model from "../Models/Definition/Model";
import {
BinStyleTraits,
EnumStyleTraits,
TableStyleMapSymbolTraits,
TableStyleMapTraits
} from "../Traits/TraitsClasses/Table/StyleMapTraits";
import TableStyleTraits from "../Traits/TraitsClasses/Table/StyleTraits";
type PickProperties<Type, Value> = {
[Key in keyof Type as Type[Key] extends Value ? Key : never]: Type[Key];
};
export interface TableStyleMapModel<T extends TableStyleMapSymbolTraits> {
enabled?: boolean;
mapType: StyleMapType | undefined;
column: string | undefined;
enum: Readonly<(EnumStyle & T)[]>;
bin: Readonly<(BinStyle & T)[]>;
null: T;
}
export interface BinStyle {
maxValue?: number | null;
}
export interface EnumStyle {
value?: string | null;
}
export type StyleMapType = "continuous" | "enum" | "bin" | "constant";
type MapValueToStyle<T> = (value: JsonValue | undefined) => T;
export interface EnumStyleMap<T> {
type: "enum";
mapRowIdToStyle: (rowId: number) => T;
mapValueToStyle: MapValueToStyle<T>;
}
export interface BinStyleMap<T> {
type: "bin";
mapRowIdToStyle: (rowId: number) => T;
mapValueToStyle: MapValueToStyle<T>;
}
export interface ConstantStyleMap<T> {
type: "constant";
style: T;
}
export default class TableStyleMap<T extends TableStyleMapSymbolTraits> {
constructor(
readonly tableModel: TableMixin.Instance,
readonly styleTraits: Model<TableStyleTraits>,
readonly key: NotUndefined<
keyof PickProperties<TableStyleTraits, TableStyleMapModel<T>>
>
) {
makeObservable(this);
}
/** Get traits for TableStyleMapSymbolTraits */
get commonTraits() {
return this.styleTraits[this.key] as Model<
{
enum: EnumStyleTraits[];
bin: BinStyleTraits[];
} & TableStyleMapTraits
>;
}
/** Get all traits (this includes TableStyleMapTraits and specific SymbolTraits) */
get traits() {
return this.styleTraits[this.key];
}
/** Get all trait values for this TableStyleMapModel.
* This is a JSON object
*/
get traitValues() {
return this.styleTraits.traits[this.key].toJson(
this.traits
) as TableStyleMapModel<T>;
}
get column() {
return this.traitValues.column
? this.tableModel.tableColumns.find(
(column) => column.name === this.traitValues.column
)
: undefined;
}
/**
*
*/
get styleMap(): EnumStyleMap<T> | BinStyleMap<T> | ConstantStyleMap<T> {
// If column type is `scalar` and binStyles
if (
(this.traitValues.mapType === "bin" || !this.traitValues.mapType) &&
this.traitValues.bin &&
this.traitValues.bin.length > 0
) {
const mapValueToStyle: MapValueToStyle<T> = (value) => {
if (typeof value !== "number") {
return this.traitValues.null;
}
const binStyles = this.traitValues.bin ?? [];
let i;
for (
i = 0;
i < binStyles.length - 1 &&
value > (binStyles[i].maxValue ?? Infinity);
++i
) {
continue;
}
return {
...this.traitValues.null,
...(this.traitValues.bin?.[i] ?? {})
};
};
return {
type: "bin",
mapRowIdToStyle: (rowId) =>
mapValueToStyle(this.column?.valuesForType[rowId]),
mapValueToStyle
};
} else if (
(this.traitValues.mapType === "enum" || !this.traitValues.mapType) &&
this.traitValues.enum &&
this.traitValues.enum.length > 0
) {
const mapValueToStyle: MapValueToStyle<T> = (value) => {
const style = this.traitValues.enum!.find(
(enumStyle) => enumStyle.value !== null && enumStyle.value === value
);
return { ...this.traitValues.null, ...(style ?? {}) };
};
return {
type: "enum",
mapRowIdToStyle: (rowId) => mapValueToStyle(this.column?.values[rowId]),
mapValueToStyle
};
}
// Return default settings
return {
type: "constant",
style: this.traitValues.null
};
}
}
export function isConstantStyleMap<T>(
map: EnumStyleMap<T> | BinStyleMap<T> | ConstantStyleMap<T>
): map is ConstantStyleMap<T> {
return map.type === "constant";
}