webglimpse
Version:
Webglimpse is a data visualization library for the web.
1,301 lines • 236 kB
JavaScript
/*
* Copyright (c) 2014, Metron, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { OrderedStringSet, OrderedSet } from '../util/ordered_set';
import { parseCssColor } from '../color';
import { Notification, Notification2 } from '../util/notification';
import { formatTime_ISO8601, hasval, parseTime_PMILLIS } from '../util/util';
import { indexOf } from '../util/sorted_arrays';
import { FillPattern } from './timeline_events_row';
import { Axis1D } from '../plot/axis';
export class TimelineCursorModel {
constructor(cursor) {
this._cursorGuid = cursor.cursorGuid;
this._attrsChanged = new Notification();
this.setAttrs(cursor);
}
get labeledTimeseriesGuids() {
return this._labeledTimeseriesGuids;
}
get cursorGuid() {
return this._cursorGuid;
}
get attrsChanged() {
return this._attrsChanged;
}
get lineColor() {
return this._lineColor;
}
get textColor() {
return this._textColor;
}
get showVerticalLine() {
return this._showVerticalLine;
}
get showHorizontalLine() {
return this._showHorizontalLine;
}
get showCursorText() {
return this._showCursorText;
}
setAttrs(cursor) {
this._labeledTimeseriesGuids = new OrderedStringSet(cursor.labeledTimeseriesGuids || []);
this._lineColor = (hasval(cursor.lineColor) ? parseCssColor(cursor.lineColor) : null);
this._textColor = (hasval(cursor.textColor) ? parseCssColor(cursor.textColor) : null);
this._showVerticalLine = cursor.showVerticalLine;
this._showHorizontalLine = cursor.showHorizontalLine;
this._showCursorText = cursor.showCursorText;
this._attrsChanged.fire();
}
snapshot() {
return {
cursorGuid: this._cursorGuid,
labeledTimeseriesGuids: this._labeledTimeseriesGuids.toArray(),
lineColor: (hasval(this._lineColor) ? this._lineColor.cssString : null),
textColor: (hasval(this._textColor) ? this._textColor.cssString : null),
showVerticalLine: this._showVerticalLine,
showHorizontalLine: this._showHorizontalLine,
showCursorText: this._showCursorText
};
}
}
export class TimelineAnnotationModel {
constructor(annotation) {
this._annotationGuid = annotation.annotationGuid;
this._attrsChanged = new Notification();
this.setAttrs(annotation);
}
get annotationGuid() {
return this._annotationGuid;
}
get attrsChanged() {
return this._attrsChanged;
}
setLocation(time_PMILLIS, y) {
if (time_PMILLIS !== this._time_PMILLIS || y !== this.y) {
this._y = y;
this._time_PMILLIS = time_PMILLIS;
this._attrsChanged.fire();
}
}
get time_PMILLIS() {
return this._time_PMILLIS;
}
set time_PMILLIS(time_PMILLIS) {
if (time_PMILLIS !== this._time_PMILLIS) {
this._time_PMILLIS = time_PMILLIS;
this._attrsChanged.fire();
}
}
get y() {
return this._y;
}
set y(y) {
if (y !== this.y) {
this._y = y;
this._attrsChanged.fire();
}
}
get label() {
return this._label;
}
set label(label) {
if (label !== this.label) {
this._label = label;
this._attrsChanged.fire();
}
}
get styleGuid() {
return this._styleGuid;
}
set styleGuid(styleGuid) {
if (styleGuid !== this.styleGuid) {
this._styleGuid = styleGuid;
this._attrsChanged.fire();
}
}
get pickable() {
return this._pickable;
}
set pickable(pickable) {
if (pickable !== this.pickable) {
this._pickable = pickable;
this._attrsChanged.fire();
}
}
setAttrs(annotation) {
// Don't both checking whether values are going to change -- it's not that important, and it would be obnoxious here
this._time_PMILLIS = hasval(annotation.time_ISO8601) ? parseTime_PMILLIS(annotation.time_ISO8601) : undefined;
this._y = annotation.y;
this._label = annotation.label;
this._styleGuid = annotation.styleGuid;
this._pickable = hasval(annotation.pickable) ? annotation.pickable : true;
this._attrsChanged.fire();
}
snapshot() {
return {
annotationGuid: this._annotationGuid,
label: this._label,
styleGuid: this._styleGuid,
time_ISO8601: formatTime_ISO8601(this._time_PMILLIS),
y: this._y,
pickable: this._pickable,
};
}
}
export class TimelineTimeseriesModel {
constructor(timeseries) {
this._timeseriesGuid = timeseries.timeseriesGuid;
this._attrsChanged = new Notification();
this.setAttrs(timeseries);
this._fragmentGuids = new OrderedStringSet(timeseries.fragmentGuids || []);
}
get timeseriesGuid() {
return this._timeseriesGuid;
}
get attrsChanged() {
return this._attrsChanged;
}
setAttrs(timeseries) {
// Don't both checking whether values are going to change -- it's not that important, and it would be obnoxious here
this._uiHint = timeseries.uiHint;
this._baseline = timeseries.baseline;
this._lineColor = (hasval(timeseries.lineColor) ? parseCssColor(timeseries.lineColor) : null);
this._pointColor = (hasval(timeseries.pointColor) ? parseCssColor(timeseries.pointColor) : null);
this._lineThickness = timeseries.lineThickness;
this._pointSize = timeseries.pointSize;
this._dash = timeseries.dash;
this._fragmentGuids = new OrderedStringSet(timeseries.fragmentGuids || []);
this._attrsChanged.fire();
}
get baseline() {
return this._baseline;
}
set baseline(baseline) {
if (baseline !== this._baseline) {
this._baseline = baseline;
this._attrsChanged.fire();
}
}
get lineColor() {
return this._lineColor;
}
set lineColor(lineColor) {
if (lineColor !== this._lineColor) {
this._lineColor = lineColor;
this._attrsChanged.fire();
}
}
get pointColor() {
return this._pointColor;
}
set pointColor(pointColor) {
if (pointColor !== this._pointColor) {
this._pointColor = pointColor;
this._attrsChanged.fire();
}
}
get lineThickness() {
return this._lineThickness;
}
set lineThickness(lineThickness) {
if (lineThickness !== this._lineThickness) {
this._lineThickness = lineThickness;
this._attrsChanged.fire();
}
}
get pointSize() {
return this._pointSize;
}
set pointSize(pointSize) {
if (pointSize !== this._pointSize) {
this._pointSize = pointSize;
this._attrsChanged.fire();
}
}
get dash() {
return this._dash;
}
set dash(dash) {
if (dash !== this._dash) {
this._dash = dash;
this._attrsChanged.fire();
}
}
get uiHint() {
return this._uiHint;
}
set uiHint(uiHint) {
if (uiHint !== this._uiHint) {
this._uiHint = uiHint;
this._attrsChanged.fire();
}
}
get fragmentGuids() {
return this._fragmentGuids;
}
set fragmentGuids(fragmentGuids) {
if (fragmentGuids !== this._fragmentGuids) {
this._fragmentGuids = fragmentGuids;
this._attrsChanged.fire();
}
}
snapshot() {
return {
timeseriesGuid: this._timeseriesGuid,
uiHint: this._uiHint,
baseline: this._baseline,
lineColor: (hasval(this._lineColor) ? this._lineColor.cssString : null),
pointColor: (hasval(this._pointColor) ? this._pointColor.cssString : null),
lineThickness: this._lineThickness,
pointSize: this._pointSize,
dash: this._dash,
fragmentGuids: this._fragmentGuids.toArray(),
};
}
}
export class TimelineTimeseriesFragmentModel {
constructor(fragment) {
this._fragmentGuid = fragment.fragmentGuid;
this._attrsChanged = new Notification();
this._dataChanged = new Notification2();
this.setAttrs(fragment);
}
get fragmentGuid() {
return this._fragmentGuid;
}
get dataChanged() {
return this._dataChanged;
}
setAttrs(fragment) {
this._userEditMode = fragment.userEditMode;
this._times_PMILLIS = hasval(fragment.times_ISO8601) ? fragment.times_ISO8601.map(parseTime_PMILLIS) : [];
this._data = hasval(fragment.data) ? fragment.data.slice() : [];
this._dataChanged.fire(0, this._data.length);
this._attrsChanged.fire();
}
get data() {
return this._data;
}
set data(data) {
if (data !== this._data) {
this._data = data;
this._dataChanged.fire(0, this._data.length);
}
}
get times_PMILLIS() {
return this._times_PMILLIS;
}
// Time should only be modified in a way which keeps the _times_PMILLIS
// array sorted. This is currently not enforced by the model.
set times_PMILLIS(times_PMILLIS) {
if (times_PMILLIS !== this._times_PMILLIS) {
this._times_PMILLIS = times_PMILLIS;
this._dataChanged.fire(0, this._data.length);
}
}
// Time should only be modified in a way which keeps the _times_PMILLIS
// array sorted. This is currently not enforced by the model.
setAllData(data, times_PMILLIS) {
if (data !== this._data || times_PMILLIS !== this._times_PMILLIS) {
this._data = data;
this._times_PMILLIS = times_PMILLIS;
this._dataChanged.fire(0, this._data.length);
}
}
// Handles adjusting the _times_PMILLIS and _data arrays if the new time
// requires them to be rearranged to stay in time order. Returns the new
// index assigned to the data point.
setData(index, value, time) {
if (this._data[index] !== value || (hasval(time) && this._times_PMILLIS[index] !== time)) {
if (hasval(time)) {
// the new time value would maintain the sorted order of the array
if ((index === 0 || time > this._times_PMILLIS[index - 1]) &&
(index === this._times_PMILLIS.length - 1 || time < this._times_PMILLIS[index + 1])) {
this._times_PMILLIS[index] = time;
this._data[index] = value;
this._dataChanged.fire(index, index + 1);
}
else {
// remove the current point at index
this._times_PMILLIS.splice(index, 1);
this._data.splice(index, 1);
// find the index to reinsert new data at
index = indexOf(this._times_PMILLIS, time);
if (index < 0) {
index = -index - 1;
}
this._times_PMILLIS.splice(index, 0, time);
this._data.splice(index, 0, value);
this._dataChanged.fire(index, index + 1);
}
}
else {
this._data[index] = value;
this._dataChanged.fire(index, index + 1);
}
}
return index;
}
get start_PMILLIS() {
return this._times_PMILLIS[0];
}
get end_PMILLIS() {
return this._times_PMILLIS.slice(-1)[0];
}
get userEditMode() {
return this._userEditMode;
}
set userEditMode(userEditMode) {
if (userEditMode !== this._userEditMode) {
this._userEditMode = userEditMode;
this._attrsChanged.fire();
}
}
snapshot() {
return {
userEditMode: this._userEditMode,
fragmentGuid: this._fragmentGuid,
data: this._data.slice(),
times_ISO8601: this._times_PMILLIS.map(formatTime_ISO8601)
};
}
}
export class TimelineEventModel {
constructor(event) {
this._eventGuid = event.eventGuid;
this._attrsChanged = new Notification();
this.setAttrs(event);
}
get eventGuid() {
return this._eventGuid;
}
get attrsChanged() {
return this._attrsChanged;
}
setAttrs(event) {
// Don't both checking whether values are going to change -- it's not that important, and it would be obnoxious here
this._startLimit_PMILLIS = (hasval(event.startLimit_ISO8601) ? Math.trunc(parseTime_PMILLIS(event.startLimit_ISO8601)) : null);
this._endLimit_PMILLIS = (hasval(event.endLimit_ISO8601) ? Math.trunc(parseTime_PMILLIS(event.endLimit_ISO8601)) : null);
this._start_PMILLIS = Math.trunc(parseTime_PMILLIS(event.start_ISO8601));
this._end_PMILLIS = Math.trunc(parseTime_PMILLIS(event.end_ISO8601));
this._label = event.label;
this._labelIcon = event.labelIcon;
this._userEditable = (hasval(event.userEditable) ? event.userEditable : false);
this._styleGuid = event.styleGuid;
this._order = event.order;
this._topMargin = event.topMargin;
this._bottomMargin = event.bottomMargin;
this._fgColor = (hasval(event.fgColor) ? parseCssColor(event.fgColor) : null);
this._bgColor = (hasval(event.bgColor) ? parseCssColor(event.bgColor) : null);
this._bgSecondaryColor = (hasval(event.bgSecondaryColor) ? parseCssColor(event.bgSecondaryColor) : null);
this._borderColor = (hasval(event.borderColor) ? parseCssColor(event.borderColor) : null);
this._borderSecondaryColor = (hasval(event.borderSecondaryColor) ? parseCssColor(event.borderSecondaryColor) : null);
this._labelTopMargin = event.labelTopMargin;
this._labelBottomMargin = event.labelBottomMargin;
this._labelVAlign = event.labelVAlign;
this._labelVPos = event.labelVPos;
this._labelHAlign = event.labelHAlign;
this._labelHPos = event.labelHPos;
this._isBorderDashed = (hasval(event.isBorderDashed) ? event.isBorderDashed : false);
this._fillPattern = (hasval(event.fillPattern) ? FillPattern[event.fillPattern] : FillPattern.solid);
this._attrsChanged.fire();
}
setInterval(start_PMILLIS, end_PMILLIS) {
if (start_PMILLIS !== this._start_PMILLIS || end_PMILLIS !== this._end_PMILLIS) {
const initial_start_PMILLIS = this._start_PMILLIS;
const initial_end_PMILLIS = this._end_PMILLIS;
const underStartLimit = hasval(this._startLimit_PMILLIS) && start_PMILLIS < this._startLimit_PMILLIS;
const overEndLimit = hasval(this._endLimit_PMILLIS) && end_PMILLIS > this._endLimit_PMILLIS;
const duration_PMILLIS = end_PMILLIS - start_PMILLIS;
const durationLimit_PMILLIS = this._endLimit_PMILLIS - this._startLimit_PMILLIS;
// If both limits are present and the event is larger than the total distance between them
// then shrink the event to fit between the limits.
if (hasval(this._startLimit_PMILLIS) && hasval(this._endLimit_PMILLIS) && durationLimit_PMILLIS < duration_PMILLIS) {
this._start_PMILLIS = Math.trunc(this._startLimit_PMILLIS);
this._end_PMILLIS = Math.trunc(this._endLimit_PMILLIS);
}
// Otherwise shift the event to comply with the limits without adjusting its total duration
else if (underStartLimit) {
this._start_PMILLIS = Math.trunc(this._startLimit_PMILLIS);
this._end_PMILLIS = Math.trunc(this._start_PMILLIS + duration_PMILLIS);
}
else if (overEndLimit) {
this._end_PMILLIS = Math.trunc(this._endLimit_PMILLIS);
this._start_PMILLIS = Math.trunc(this._end_PMILLIS - duration_PMILLIS);
}
else {
this._end_PMILLIS = Math.trunc(end_PMILLIS);
this._start_PMILLIS = Math.trunc(start_PMILLIS);
}
// its possible due to the limits that the values didn't actually change
// only fire attrsChanged if one of the values did actually change
if (initial_start_PMILLIS !== this._start_PMILLIS || initial_end_PMILLIS !== this._end_PMILLIS) {
this._attrsChanged.fire();
}
}
}
limit_start_PMILLIS(start_PMILLIS) {
return hasval(this._startLimit_PMILLIS) ? Math.max(start_PMILLIS, this._startLimit_PMILLIS) : start_PMILLIS;
}
limit_end_PMILLIS(end_PMILLIS) {
return hasval(this._endLimit_PMILLIS) ? Math.min(end_PMILLIS, this._endLimit_PMILLIS) : end_PMILLIS;
}
get start_PMILLIS() {
return this._start_PMILLIS;
}
set start_PMILLIS(start_PMILLIS) {
if (start_PMILLIS !== this._start_PMILLIS) {
this._start_PMILLIS = Math.trunc(this.limit_start_PMILLIS(start_PMILLIS));
this._attrsChanged.fire();
}
}
get end_PMILLIS() {
return this._end_PMILLIS;
}
set end_PMILLIS(end_PMILLIS) {
if (end_PMILLIS !== this._end_PMILLIS) {
this._end_PMILLIS = Math.trunc(this.limit_end_PMILLIS(end_PMILLIS));
this._attrsChanged.fire();
}
}
get startLimit_PMILLIS() {
return this._startLimit_PMILLIS;
}
set startLimit_PMILLIS(startLimit_PMILLIS) {
if (startLimit_PMILLIS !== this._startLimit_PMILLIS) {
this._startLimit_PMILLIS = Math.trunc(startLimit_PMILLIS);
this._start_PMILLIS = Math.trunc(this.limit_start_PMILLIS(this._start_PMILLIS));
this._attrsChanged.fire();
}
}
get endLimit_PMILLIS() {
return this._endLimit_PMILLIS;
}
set endLimit_PMILLIS(endLimit_PMILLIS) {
if (endLimit_PMILLIS !== this._endLimit_PMILLIS) {
this._endLimit_PMILLIS = Math.trunc(endLimit_PMILLIS);
this._end_PMILLIS = Math.trunc(this.limit_end_PMILLIS(this._end_PMILLIS));
this._attrsChanged.fire();
}
}
get label() {
return this._label;
}
set label(label) {
if (label !== this._label) {
this._label = label;
this._attrsChanged.fire();
}
}
get labelIcon() {
return this._labelIcon;
}
set labelIcon(labelIcon) {
if (labelIcon !== this._labelIcon) {
this._labelIcon = labelIcon;
this._attrsChanged.fire();
}
}
get userEditable() {
return this._userEditable;
}
set userEditable(userEditable) {
if (userEditable !== this._userEditable) {
this._userEditable = userEditable;
this._attrsChanged.fire();
}
}
get styleGuid() {
return this._styleGuid;
}
set styleGuid(styleGuid) {
if (styleGuid !== this._styleGuid) {
this._styleGuid = styleGuid;
this._attrsChanged.fire();
}
}
get order() {
return this._order;
}
set order(orderVal) {
if (orderVal !== this._order) {
this._order = orderVal;
this._attrsChanged.fire();
}
}
get topMargin() {
return this._topMargin;
}
set topMargin(topMargin) {
if (topMargin !== this._topMargin) {
this._topMargin = topMargin;
this._attrsChanged.fire();
}
}
get bottomMargin() {
return this._bottomMargin;
}
set bottomMargin(bottomMargin) {
if (bottomMargin !== this._bottomMargin) {
this._bottomMargin = bottomMargin;
this._attrsChanged.fire();
}
}
get fgColor() {
return this._fgColor;
}
set fgColor(fgColor) {
if (fgColor !== this._fgColor) {
this._fgColor = fgColor;
this._attrsChanged.fire();
}
}
get bgColor() {
return this._bgColor;
}
set bgColor(bgColor) {
if (bgColor !== this._bgColor) {
this._bgColor = bgColor;
this._attrsChanged.fire();
}
}
get bgSecondaryColor() {
return this._bgSecondaryColor;
}
set bgSecondaryColor(bgSecondaryColor) {
if (bgSecondaryColor !== this._bgSecondaryColor) {
this._bgSecondaryColor = bgSecondaryColor;
this._attrsChanged.fire();
}
}
get borderColor() {
return this._borderColor;
}
set borderColor(borderColor) {
if (borderColor !== this._borderColor) {
this._borderColor = borderColor;
this._attrsChanged.fire();
}
}
get borderSecondaryColor() {
return this._borderSecondaryColor;
}
set borderSecondaryColor(borderSecondaryColor) {
if (borderSecondaryColor !== this._borderSecondaryColor) {
this._borderSecondaryColor = borderSecondaryColor;
this._attrsChanged.fire();
}
}
get labelTopMargin() {
return this._labelTopMargin;
}
set labelTopMargin(labelTopMargin) {
if (labelTopMargin !== this._labelTopMargin) {
this._labelTopMargin = labelTopMargin;
this._attrsChanged.fire();
}
}
get labelBottomMargin() {
return this._labelBottomMargin;
}
set labelBottomMargin(labelBottomMargin) {
if (labelBottomMargin !== this._labelBottomMargin) {
this._labelBottomMargin = labelBottomMargin;
this._attrsChanged.fire();
}
}
get labelVAlign() {
return this._labelVAlign;
}
set labelVAlign(labelVAlign) {
if (labelVAlign !== this._labelVAlign) {
this._labelVAlign = labelVAlign;
this._attrsChanged.fire();
}
}
get labelVPos() {
return this._labelVPos;
}
set labelVPos(labelVPos) {
if (labelVPos !== this._labelVPos) {
this._labelVPos = labelVPos;
this._attrsChanged.fire();
}
}
get labelHAlign() {
return this._labelHAlign;
}
set labelHAlign(labelHAlign) {
if (labelHAlign !== this._labelHAlign) {
this._labelHAlign = labelHAlign;
this._attrsChanged.fire();
}
}
get labelHPos() {
return this._labelHPos;
}
set labelHPos(labelHPos) {
if (labelHPos !== this._labelHPos) {
this._labelHPos = labelHPos;
this._attrsChanged.fire();
}
}
get isBorderDashed() {
return this._isBorderDashed;
}
set isBorderDashed(isBorderDashed) {
if (isBorderDashed !== this._isBorderDashed) {
this._isBorderDashed = isBorderDashed;
this._attrsChanged.fire();
}
}
get fillPattern() {
return this._fillPattern;
}
set fillPattern(fillPattern) {
if (fillPattern !== this._fillPattern) {
this._fillPattern = fillPattern;
this._attrsChanged.fire();
}
}
snapshot() {
return {
eventGuid: this._eventGuid,
startLimit_ISO8601: (hasval(this._startLimit_PMILLIS) ? formatTime_ISO8601(this._startLimit_PMILLIS) : null),
endLimit_ISO8601: (hasval(this._endLimit_PMILLIS) ? formatTime_ISO8601(this._endLimit_PMILLIS) : null),
start_ISO8601: formatTime_ISO8601(this._start_PMILLIS),
end_ISO8601: formatTime_ISO8601(this._end_PMILLIS),
label: this._label,
labelIcon: this._labelIcon,
userEditable: this._userEditable,
styleGuid: this._styleGuid,
order: this._order,
topMargin: this._topMargin,
bottomMargin: this._bottomMargin,
bgColor: (hasval(this._bgColor) ? this._bgColor.cssString : null),
bgSecondaryColor: (hasval(this._bgSecondaryColor) ? this._bgSecondaryColor.cssString : null),
fgColor: (hasval(this._fgColor) ? this._fgColor.cssString : null),
borderColor: (hasval(this._borderColor) ? this._borderColor.cssString : null),
borderSecondaryColor: (hasval(this._borderSecondaryColor) ? this.borderSecondaryColor.cssString : null),
labelTopMargin: this._labelTopMargin,
labelBottomMargin: this._labelBottomMargin,
labelVAlign: this._labelVAlign,
labelVPos: this._labelVPos,
labelHAlign: this._labelHAlign,
labelHPos: this._labelHPos,
isBorderDashed: this._isBorderDashed,
fillPattern: FillPattern[this._fillPattern]
};
}
}
export class TimelineRowModel {
constructor(row) {
this._rowGuid = row.rowGuid;
this._attrsChanged = new Notification();
const min = hasval(row.yMin) ? row.yMin : 0;
const max = hasval(row.yMax) ? row.yMax : 1;
this._dataAxis = new Axis1D(min, max);
this.setAttrs(row);
this._eventGuids = new OrderedStringSet(row.eventGuids || []);
this._timeseriesGuids = new OrderedStringSet(row.timeseriesGuids || []);
this._annotationGuids = new OrderedStringSet(row.annotationGuids || []);
}
get rowGuid() {
return this._rowGuid;
}
get attrsChanged() {
return this._attrsChanged;
}
setAttrs(row) {
// Don't both checking whether values are going to change -- it's not that important, and it would be obnoxious here
this._label = row.label;
this._truncate = row.truncate;
this._uiHint = row.uiHint;
this._hidden = row.hidden;
this._rowHeight = row.rowHeight;
this._cursorGuid = row.cursorGuid;
this._bgColor = (hasval(row.bgColor) ? parseCssColor(row.bgColor) : null);
this._fgLabelColor = (hasval(row.fgLabelColor) ? parseCssColor(row.fgLabelColor) : null);
this._bgLabelColor = (hasval(row.bgLabelColor) ? parseCssColor(row.bgLabelColor) : null);
this._labelFont = row.labelFont;
this._cursor = row.cursor;
this._highlighted = hasval(row.highlighted) ? row.highlighted : false;
this._highlightColor = hasval(row.highlightColor) ? row.highlightColor : parseCssColor('white');
this._highlightWidth = row.highlightWidth;
this._highlightInsets = row.highlightInsets;
this._attrsChanged.fire();
}
get cursorGuid() {
return this._cursorGuid;
}
set cursorGuid(cursorGuid) {
this._cursorGuid = cursorGuid;
this._attrsChanged.fire();
}
get rowHeight() {
return this._rowHeight;
}
set rowHeight(rowHeight) {
this._rowHeight = rowHeight;
this._attrsChanged.fire();
}
get hidden() {
return this._hidden;
}
set hidden(hidden) {
this._hidden = hidden;
this._attrsChanged.fire();
}
get dataAxis() {
return this._dataAxis;
}
set dataAxis(dataAxis) {
this._dataAxis = dataAxis;
this._attrsChanged.fire();
}
get label() {
return this._label;
}
set label(label) {
if (label !== this._label) {
this._label = label;
this._attrsChanged.fire();
}
}
get truncate() {
return this._truncate;
}
set truncate(truncate) {
if (truncate !== this._truncate) {
this._truncate = truncate;
this._attrsChanged.fire();
}
}
get uiHint() {
return this._uiHint;
}
set uiHint(uiHint) {
if (uiHint !== this._uiHint) {
this._uiHint = uiHint;
this._attrsChanged.fire();
}
}
get bgColor() {
return this._bgColor;
}
set bgColor(bgColor) {
if (bgColor !== this._bgColor) {
this._bgColor = bgColor;
this._attrsChanged.fire();
}
}
get bgLabelColor() {
return this._bgLabelColor;
}
set bgLabelColor(bgLabelColor) {
if (bgLabelColor !== this._bgLabelColor) {
this._bgLabelColor = bgLabelColor;
this._attrsChanged.fire();
}
}
get fgLabelColor() {
return this._fgLabelColor;
}
set fgLabelColor(fgLabelColor) {
if (fgLabelColor !== this._fgLabelColor) {
this._fgLabelColor = fgLabelColor;
this._attrsChanged.fire();
}
}
get labelFont() {
return this._labelFont;
}
set labelFont(labelFont) {
if (labelFont !== this._labelFont) {
this._labelFont = labelFont;
this._attrsChanged.fire();
}
}
get cursor() {
return this._cursor;
}
set cursor(cursor) {
if (cursor !== this._cursor) {
this._cursor = cursor;
this._attrsChanged.fire();
}
}
get highlighted() {
return this._highlighted;
}
set highlighted(highlighted) {
if (highlighted !== this._highlighted) {
this._highlighted = highlighted;
this._attrsChanged.fire();
}
}
get highlightColor() {
return this._highlightColor;
}
set highlightColor(highlightColor) {
if (highlightColor !== this._highlightColor) {
this._highlightColor = highlightColor;
this._attrsChanged.fire();
}
}
get highlightWidth() {
return this._highlightWidth;
}
set highlightWidth(highlightWidth) {
if (highlightWidth !== this._highlightWidth) {
this._highlightWidth = highlightWidth;
this._attrsChanged.fire();
}
}
get highlightInsets() {
return this._highlightInsets;
}
set highlightInsets(highlightInsets) {
if (highlightInsets !== this._highlightInsets) {
this._highlightInsets = highlightInsets;
this._attrsChanged.fire();
}
}
get eventGuids() {
return this._eventGuids;
}
get timeseriesGuids() {
return this._timeseriesGuids;
}
get annotationGuids() {
return this._annotationGuids;
}
snapshot() {
return {
rowGuid: this._rowGuid,
label: this._label,
truncate: this._truncate,
rowHeight: this._rowHeight,
hidden: this._hidden,
uiHint: this._uiHint,
eventGuids: this._eventGuids.toArray(),
timeseriesGuids: this._timeseriesGuids.toArray(),
annotationGuids: this._annotationGuids.toArray(),
cursorGuid: this._cursorGuid,
bgColor: (hasval(this._bgColor) ? this._bgColor.cssString : null),
bgLabelColor: (hasval(this._bgLabelColor) ? this._bgLabelColor.cssString : null),
fgLabelColor: (hasval(this._fgLabelColor) ? this._fgLabelColor.cssString : null),
labelFont: this._labelFont,
cursor: this._cursor,
highlighted: (hasval(this._highlighted) ? this._highlighted : false),
highlightColor: hasval(this.highlightColor) ? this.highlightColor : parseCssColor('white'),
highlightWidth: this._highlightWidth,
highlightInsets: this._highlightInsets
};
}
}
export class TimelineGroupModel {
constructor(group) {
this._groupGuid = group.groupGuid;
this._attrsChanged = new Notification();
this.setAttrs(group);
this._rowGuids = new OrderedStringSet(group.rowGuids);
}
get groupGuid() {
return this._groupGuid;
}
get rollupGuid() {
return this._rollupGuid;
}
set rollupGuid(rollupGuid) {
this._rollupGuid = rollupGuid;
this._attrsChanged.fire();
}
get attrsChanged() {
return this._attrsChanged;
}
setAttrs(group) {
// Don't both checking whether values are going to change -- it's not that important, and it would be obnoxious here
this._rollupGuid = group.rollupGuid;
this._hidden = group.hidden;
this._label = group.label;
this._collapsed = group.collapsed;
this._highlighted = hasval(group.highlighted) ? group.highlighted : false;
this._highlightColor = hasval(group.highlightColor) ? group.highlightColor : parseCssColor('white');
this._dashPattern = hasval(group.dashPattern) ? group.dashPattern : 0xFFFF;
this._dashLength = hasval(group.dashLength) ? group.dashLength : 16;
this._highlightWidth = group.highlightWidth;
this._highlightInsets = group.highlightInsets;
this._labelFont = group.labelFont;
this._cursor = group.cursor;
this._attrsChanged.fire();
}
get hidden() {
return this._hidden;
}
set hidden(hidden) {
this._hidden = hidden;
this._attrsChanged.fire();
}
get label() {
return this._label;
}
set label(label) {
if (label !== this._label) {
this._label = label;
this._attrsChanged.fire();
}
}
get collapsed() {
return this._collapsed;
}
set collapsed(collapsed) {
if (collapsed !== this._collapsed) {
this._collapsed = collapsed;
this._attrsChanged.fire();
}
}
get highlighted() {
return this._highlighted;
}
set highlighted(highlighted) {
if (highlighted !== this._highlighted) {
this._highlighted = highlighted;
this._attrsChanged.fire();
}
}
get highlightColor() {
return this._highlightColor;
}
set highlightColor(highlightColor) {
if (highlightColor !== this._highlightColor) {
this._highlightColor = highlightColor;
this._attrsChanged.fire();
}
}
get highlightWidth() {
return this._highlightWidth;
}
set highlightWidth(highlightWidth) {
if (highlightWidth !== this._highlightWidth) {
this._highlightWidth = highlightWidth;
this._attrsChanged.fire();
}
}
get highlightInsets() {
return this._highlightInsets;
}
set highlightInsets(highlightInsets) {
if (highlightInsets !== this._highlightInsets) {
this._highlightInsets = highlightInsets;
this._attrsChanged.fire();
}
}
get dashPattern() {
return this._dashPattern;
}
set dashPattern(dashPattern) {
if (dashPattern !== this._dashPattern) {
this._dashPattern = dashPattern;
this._attrsChanged.fire();
}
}
get dashLength() {
return this._dashLength;
}
set dashLength(dashLength) {
if (dashLength !== this._dashLength) {
this._dashLength = dashLength;
this._attrsChanged.fire();
}
}
get labelFont() {
return this._labelFont;
}
set labelFont(labelFont) {
if (labelFont !== this._labelFont) {
this._labelFont = labelFont;
this._attrsChanged.fire();
}
}
get cursor() {
return this._cursor;
}
set cursor(cursor) {
if (cursor !== this._cursor) {
this._cursor = cursor;
this._attrsChanged.fire();
}
}
get rowGuids() {
return this._rowGuids;
}
snapshot() {
return {
groupGuid: this._groupGuid,
rollupGuid: this._rollupGuid,
label: this._label,
hidden: this._hidden,
collapsed: (hasval(this._collapsed) ? this._collapsed : false),
highlighted: (hasval(this._highlighted) ? this._highlighted : false),
highlightColor: hasval(this.highlightColor) ? this.highlightColor : parseCssColor('white'),
highlightWidth: this._highlightWidth,
highlightInsets: this._highlightInsets,
dashPattern: hasval(this.dashPattern) ? this.dashPattern : 0xFFFF,
dashLength: hasval(this.dashLength) ? this.dashLength : 16,
labelFont: this._labelFont,
cursor: this._cursor,
rowGuids: this._rowGuids.toArray()
};
}
}
export class TimelineRootModel {
constructor(root) {
this._attrsChanged = new Notification();
this.setAttrs(root);
this._groupGuids = new OrderedStringSet(root.groupGuids);
this._topPinnedRowGuids = new OrderedStringSet(root.topPinnedRowGuids || []);
this._bottomPinnedRowGuids = new OrderedStringSet(root.bottomPinnedRowGuids || []);
this._maximizedRowGuids = new OrderedStringSet(root.maximizedRowGuids || []);
}
get attrsChanged() {
return this._attrsChanged;
}
setAttrs(root) {
// Don't both checking whether values are going to change -- it's not that important, and it would be obnoxious here
// No attrs yet
this._attrsChanged.fire();
}
get groupGuids() {
return this._groupGuids;
}
get topPinnedRowGuids() {
return this._topPinnedRowGuids;
}
get bottomPinnedRowGuids() {
return this._bottomPinnedRowGuids;
}
get maximizedRowGuids() {
return this._maximizedRowGuids;
}
snapshot() {
return {
groupGuids: this._groupGuids.toArray(),
topPinnedRowGuids: this._topPinnedRowGuids.toArray(),
bottomPinnedRowGuids: this._bottomPinnedRowGuids.toArray(),
maximizedRowGuids: this._maximizedRowGuids.toArray()
};
}
}
export class TimelineModel {
constructor(timeline) {
const cursors = (hasval(timeline) && hasval(timeline.cursors) ? timeline.cursors : []);
this._cursors = new OrderedSet([], (g) => g.cursorGuid);
for (let n = 0; n < cursors.length; n++) {
this._cursors.add(new TimelineCursorModel(cursors[n]));
}
const annotations = (hasval(timeline) && hasval(timeline.annotations) ? timeline.annotations : []);
this._annotations = new OrderedSet([], (g) => g.annotationGuid);
for (let n = 0; n < annotations.length; n++) {
this._annotations.add(new TimelineAnnotationModel(annotations[n]));
}
const timeseriesFragments = (hasval(timeline) && hasval(timeline.timeseriesFragments) ? timeline.timeseriesFragments : []);
this._timeseriesFragments = new OrderedSet([], (e) => e.fragmentGuid);
for (let n = 0; n < timeseriesFragments.length; n++) {
this._timeseriesFragments.add(new TimelineTimeseriesFragmentModel(timeseriesFragments[n]));
}
const timeseries = (hasval(timeline) && hasval(timeline.timeseries) ? timeline.timeseries : []);
this._timeseries = new OrderedSet([], (e) => e.timeseriesGuid);
for (let n = 0; n < timeseries.length; n++) {
this._timeseries.add(new TimelineTimeseriesModel(timeseries[n]));
}
const events = (hasval(timeline) && hasval(timeline.events) ? timeline.events : []);
this._events = new OrderedSet([], (e) => e.eventGuid);
for (let n = 0; n < events.length; n++) {
this._events.add(new TimelineEventModel(events[n]));
}
const rows = (hasval(timeline) && hasval(timeline.rows) ? timeline.rows : []);
this._rows = new OrderedSet([], (r) => r.rowGuid);
for (let n = 0; n < rows.length; n++) {
this._rows.add(new TimelineRowModel(rows[n]));
}
const groups = (hasval(timeline) && hasval(timeline.groups) ? timeline.groups : []);
this._groups = new OrderedSet([], (g) => g.groupGuid);
for (let n = 0; n < groups.length; n++) {
this._groups.add(new TimelineGroupModel(groups[n]));
}
const root = (hasval(timeline) && hasval(timeline.root) ? timeline.root : newEmptyTimelineRoot());
this._root = new TimelineRootModel(root);
}
get cursors() { return this._cursors; }
get annotations() { return this._annotations; }
get timeseriesFragments() { return this._timeseriesFragments; }
get timeseriesSets() { return this._timeseries; }
get events() { return this._events; }
get rows() { return this._rows; }
get groups() { return this._groups; }
get root() { return this._root; }
cursor(cursorGuid) { return this._cursors.valueFor(cursorGuid); }
annotation(annotationGuid) { return this._annotations.valueFor(annotationGuid); }
timeseriesFragment(fragmentGuid) { return this._timeseriesFragments.valueFor(fragmentGuid); }
timeseries(timeseriesGuid) { return this._timeseries.valueFor(timeseriesGuid); }
event(eventGuid) { return this._events.valueFor(eventGuid); }
row(rowGuid) { return this._rows.valueFor(rowGuid); }
group(groupGuid) { return this._groups.valueFor(groupGuid); }
replace(newTimeline) {
// Purge removed items
//
const freshRoot = newTimeline.root;
this._root.groupGuids.retainValues(freshRoot.groupGuids);
this._root.topPinnedRowGuids.retainValues(freshRoot.topPinnedRowGuids);
this._root.bottomPinnedRowGuids.retainValues(freshRoot.bottomPinnedRowGuids);
this._root.maximizedRowGuids.retainValues(freshRoot.maximizedRowGuids);
const freshGroups = newTimeline.groups;
const retainedGroupGuids = [];
for (let n = 0; n < freshGroups.length; n++) {
const freshGroup = freshGroups[n];
const groupGuid = freshGroup.groupGuid;
const oldGroup = this._groups.valueFor(groupGuid);
if (hasval(oldGroup)) {
oldGroup.rowGuids.retainValues(freshGroup.rowGuids);
retainedGroupGuids.push(groupGuid);
}
}
this._groups.retainIds(retainedGroupGuids);
const freshRows = newTimeline.rows;
const retainedRowGuids = [];
for (let n = 0; n < freshRows.length; n++) {
const freshRow = freshRows[n];
const rowGuid = freshRow.rowGuid;
const oldRow = this._rows.valueFor(rowGuid);
if (hasval(oldRow)) {
oldRow.eventGuids.retainValues(freshRow.eventGuids || []);
retainedRowGuids.push(rowGuid);
}
}
this._rows.retainIds(retainedRowGuids);
const freshEvents = newTimeline.events;
const retainedEventGuids = [];
for (let n = 0; n < freshEvents.length; n++) {
const freshEvent = freshEvents[n];
const eventGuid = freshEvent.eventGuid;
const oldEvent = this._events.valueFor(eventGuid);
if (hasval(oldEvent)) {
retainedEventGuids.push(eventGuid);
}
}
this._events.retainIds(retainedEventGuids);
const freshTimeseriesSet = newTimeline.timeseries;
const retainedTimeseriesGuids = [];
for (let n = 0; n < freshTimeseriesSet.length; n++) {
const freshTimeseries = freshTimeseriesSet[n];
const timeseriesGuid = freshTimeseries.timeseriesGuid;
const oldTimeseries = this._timeseries.valueFor(timeseriesGuid);
if (hasval(oldTimeseries)) {
retainedTimeseriesGuids.push(timeseriesGuid);
}
}
this._timeseries.retainIds(retainedTimeseriesGuids);
const freshTimeseriesFragments = newTimeline.timeseriesFragments;
const retainedTimeseriesFragmentGuids = [];
for (let n = 0; n < freshTimeseriesFragments.length; n++) {
const freshTimeseriesFragment = freshTimeseriesFragments[n];
const fragmentGuid = freshTimeseriesFragment.fragmentGuid;
const oldTimeseriesFragment = this._timeseriesFragments.valueFor(fragmentGuid);
if (hasval(oldTimeseriesFragment)) {
retainedTimeseriesFragmentGuids.push(fragmentGuid);
}
}
this._timeseriesFragments.retainIds(retainedTimeseriesFragmentGuids);
const freshAnnotations = newTimeline.annotations;
const retainedAnnotationGuids = [];
for (let n = 0; n < freshAnnotations.length; n++) {
const freshAnnotation = freshAnnotations[n];
const annotationGuid = freshAnnotation.annotationGuid;
const oldAnnotation = this._annotations.valueFor(annotationGuid);
if (hasval(oldAnnotation)) {
retainedAnnotationGuids.push(annotationGuid);
}
}
this._annotations.retainIds(retainedAnnotationGuids);
const freshCursors = newTimeline.cursors;
const retainedCursorGuids = [];
for (let n = 0; n < freshCursors.length; n++) {
const freshCursor = freshCursors[n];
const cursorGuid = freshCursor.cursorGuid;
const oldCursor = this._cursors.valueFor(cursorGuid);
if (hasval(oldCursor)) {
retainedCursorGuids.push(cursorGuid);
}
}
this._cursors.retainIds(retainedCursorGuids);
// Add new items
//
for (let n = 0; n < freshCursors.length; n++) {
const freshCursor = freshCursors[n];
const oldCursor = this._cursors.valueFor(freshCursor.cursorGuid);
if (hasval(oldCursor)) {
oldCursor.setAttrs(freshCursor);
}
else {
this._cursors.add(new TimelineCursorModel(freshCursor));
}
}
for (let n = 0; n < freshAnnotations.length; n++) {
const freshAnnotation = freshAnnotations[n];
const oldAnnotation = this._annotations.valueFor(freshAnnotation.annotationGuid);
if (hasval(oldAnnotation)) {
oldAnnotation.setAttrs(freshAnnotation);
}
else {
this._annotations.add(new TimelineAnnotationModel(freshAnnotation));
}
}
for (let n = 0; n < freshTimeseriesFragments.length; n++) {
const freshTimeseriesFragment = freshTimeseriesFragments[n];
const oldTimeseriesFragment = this._timeseriesFragments.valueFor(freshTimeseriesFragment.fragmentGuid);
if (hasval(oldTimeseriesFragment)) {
oldTimeseriesFragment.setAttrs(freshTimeseriesFragment);
}
else {
this._timeseriesFragments.add(new TimelineTimeseriesFragmentModel(freshTimeseriesFragment));
}
}
for (let n = 0; n < freshTimeseriesSet.length; n++) {
const freshTimeseries = freshTimeseriesSet[n];
const oldTimeseries = this._timeseries.valueFor(freshTimeseries.timeseriesGuid);
if (hasval(oldTimeseries)) {
oldTimeseries.setAttrs(freshTimeseries);
}
else {
this._timeseries.add(new TimelineTimeseriesModel(freshTimeseries));
}
}
for (let