scichart
Version:
Fast WebGL JavaScript Charting Library and Framework
312 lines (311 loc) • 13.9 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompositeAnnotation = void 0;
var Rect_1 = require("../../../Core/Rect");
var ObservableArray_1 = require("../../../Core/ObservableArray");
var AnnotationBase_1 = require("./AnnotationBase");
var BoxAnnotation_1 = require("./BoxAnnotation");
var IAnnotation_1 = require("./IAnnotation");
var constants_1 = require("./constants");
/**
* Parent annotation that groups other annotations and keeps child positions
* relative to the parent box.
*
* `CompositeAnnotation` is intentionally much simpler than
* {@link MultiPointAnnotationBase}. It does not define its own multi-point
* geometry, snapping, label anchors, segment labels or drag-grip model. Instead,
* it acts as a lightweight container: child annotations are attached to the same
* surface, assigned this annotation as their parent and repositioned when the
* composite box moves or resizes.
*
* Use this when several existing annotations should behave like one grouped
* object. Use {@link MultiPointAnnotationBase} derived annotations when the
* annotation itself is defined by multiple points and needs labels, snapping or
* specialized editing handles.
*/
var CompositeAnnotation = /** @class */ (function (_super) {
__extends(CompositeAnnotation, _super);
/**
* Creates a new {@link CompositeAnnotation}
* @param options Configuration options. See {@link ICompositeAnnotationOptions} for details.
*/
function CompositeAnnotation(options) {
var _this = _super.call(this, options) || this;
/** @inheritdoc */
// @ts-ignore
_this.type = IAnnotation_1.EAnnotationType.CompositeAnnotation;
_this.children = new ObservableArray_1.ObservableArray();
_this.relativePositions = new WeakMap();
_this.isUpdatingChildren = false;
if (options === null || options === void 0 ? void 0 : options.annotations) {
_this.add.apply(_this, options.annotations);
}
return _this;
}
Object.defineProperty(CompositeAnnotation.prototype, "annotations", {
/**
* Gets the child annotations contained within this composite.
* This array should be treated as read-only.
*/
get: function () {
return this.children.asArray();
},
/**
* Replaces all child annotations in the composite.
* Existing children will be removed before adding the new ones.
*/
set: function (value) {
this.clear();
if (value) {
this.add.apply(this, value);
}
this.notifyPropertyChanged(constants_1.PROPERTY.CHILD_ANNOTATIONS);
},
enumerable: false,
configurable: true
});
/**
* Adds one or more annotations to the composite.
* Duplicate or invalid annotations are ignored.
* @param items Child annotation(s) to add
*/
CompositeAnnotation.prototype.add = function () {
var _this = this;
var items = [];
for (var _i = 0; _i < arguments.length; _i++) {
items[_i] = arguments[_i];
}
var validItems = [];
for (var _a = 0, items_1 = items; _a < items_1.length; _a++) {
var annotation = items_1[_a];
if (annotation instanceof AnnotationBase_1.AnnotationBase &&
!this.children.contains(annotation)) {
this.children.add(annotation);
this.captureInitialPosition(annotation);
validItems.push(annotation);
}
}
if (this.parentSurface && validItems.length > 0) {
validItems.forEach(function (a) { return _this.attachChild(a); });
}
};
/**
* Removes a child annotation from the composite.
* @param annotation The child annotation to remove
* @param callDeleteOnChildren When `true`, calls delete() on the removed child
*/
CompositeAnnotation.prototype.remove = function (annotation, callDeleteOnChildren) {
if (!(annotation instanceof AnnotationBase_1.AnnotationBase))
return;
if (!this.children.contains(annotation))
return;
this.children.remove(annotation, callDeleteOnChildren);
this.relativePositions.delete(annotation);
if (this.parentSurface) {
this.parentSurface.annotations.remove(annotation, callDeleteOnChildren);
}
};
/**
* Removes all child annotations from the composite.
* @param callDeleteOnChildren When true, it also deletes the child annotations, which removes the memory claimed by the child annotations.
*
* Default `true`
*/
CompositeAnnotation.prototype.clear = function (callDeleteOnChildren) {
var _this = this;
if (this.parentSurface) {
this.children.asArray().forEach(function (c) {
return _this.parentSurface.annotations.remove(c, callDeleteOnChildren);
});
}
this.children.clear(callDeleteOnChildren);
};
/**
* Sets a normalized relative position for a child annotation.
* Coordinates are expressed in the range [0..1] relative to the parent bounds.
* @param child The child annotation
* @param x1 Normalized X1 position
* @param y1 Normalized Y1 position
* @param x2 Optional normalized X2 position
* @param y2 Optional normalized Y2 position
*/
CompositeAnnotation.prototype.setChildRelativePosition = function (child, x1, y1, x2, y2) {
if (!(child instanceof AnnotationBase_1.AnnotationBase))
return;
if (!this.children.contains(child))
return;
this.relativePositions.set(child, { x1: x1, y1: y1, x2: x2, y2: y2, isNormalized: true });
};
/** @inheritdoc */
CompositeAnnotation.prototype.onAttach = function (surface) {
var _this = this;
_super.prototype.onAttach.call(this, surface);
this.children.asArray().forEach(function (child) { return _this.attachChild(child); });
this.syncPropertiesToChildren();
};
/** @inheritdoc */
CompositeAnnotation.prototype.onDetach = function () {
var _this = this;
if (this.parentSurface) {
this.children.asArray().forEach(function (child) {
return _this.parentSurface.annotations.remove(child);
});
}
_super.prototype.onDetach.call(this);
};
/** @inheritdoc */
CompositeAnnotation.prototype.drawWithContext = function (renderContext, xCalc, yCalc, seriesViewRect, surfaceViewRect, chartViewRect) {
_super.prototype.drawWithContext.call(this, renderContext, xCalc, yCalc, seriesViewRect, surfaceViewRect, chartViewRect);
this.updateAllChildren(xCalc, yCalc);
};
/** @inheritdoc */
CompositeAnnotation.prototype.calcDragDistance = function (xyValues) {
var _a, _b;
_super.prototype.calcDragDistance.call(this, xyValues);
var xCalc = (_a = this.xAxis) === null || _a === void 0 ? void 0 : _a.getCurrentCoordinateCalculator();
var yCalc = (_b = this.yAxis) === null || _b === void 0 ? void 0 : _b.getCurrentCoordinateCalculator();
if (xCalc && yCalc) {
this.updateAllChildren(xCalc, yCalc);
}
};
//internal methods
CompositeAnnotation.prototype.attachChild = function (child) {
var surface = this.parentSurface;
if (surface.annotations.contains(child)) {
surface.annotations.remove(child);
}
child.parentAnnotationId = this.id;
child.xAxisId = this.xAxisId;
child.yAxisId = this.yAxisId;
child.isHidden = this.isHidden;
surface.annotations.add(child);
};
CompositeAnnotation.prototype.captureInitialPosition = function (child) {
if (this.relativePositions.has(child))
return;
this.relativePositions.set(child, {
x1: Number(child.x1),
y1: Number(child.y1),
x2: child.x2 != null ? Number(child.x2) : undefined,
y2: child.y2 != null ? Number(child.y2) : undefined,
isNormalized: false
});
};
CompositeAnnotation.prototype.updateAllChildren = function (xCalc, yCalc) {
if (this.isUpdatingChildren || this.children.size() === 0)
return;
this.isUpdatingChildren = true;
try {
var px1 = this.getX1Coordinate(xCalc, yCalc);
var py1 = this.getY1Coordinate(xCalc, yCalc);
var px2 = this.getX2Coordinate(xCalc, yCalc);
var py2 = this.getY2Coordinate(xCalc, yCalc);
var bounds = new Rect_1.Rect(Math.min(px1, px2), Math.min(py1, py2), Math.abs(px2 - px1), Math.abs(py2 - py1));
if (bounds.width <= 0 || bounds.height <= 0)
return;
for (var _i = 0, _a = this.children.asArray(); _i < _a.length; _i++) {
var child = _a[_i];
this.updateChildPosition(child, xCalc, yCalc, bounds);
}
}
finally {
this.isUpdatingChildren = false;
}
};
CompositeAnnotation.prototype.ensureNormalized = function (child, xCalc, yCalc, bounds) {
var stored = this.relativePositions.get(child);
if (!stored)
return null;
if (stored.x1 >= 0 && stored.x1 <= 1 &&
stored.y1 >= 0 && stored.y1 <= 1) {
return stored;
}
if (bounds.width <= 1 || bounds.height <= 1)
return null;
var cx1 = xCalc.getCoordinate(stored.x1);
var cy1 = yCalc.getCoordinate(stored.y1);
var normalized = {
x1: (cx1 - bounds.x) / bounds.width,
y1: (cy1 - bounds.y) / bounds.height
};
if (stored.x2 != null && stored.y2 != null) {
var cx2 = xCalc.getCoordinate(stored.x2);
var cy2 = yCalc.getCoordinate(stored.y2);
normalized.x2 = (cx2 - bounds.x) / bounds.width;
normalized.y2 = (cy2 - bounds.y) / bounds.height;
}
this.relativePositions.set(child, normalized);
return normalized;
};
CompositeAnnotation.prototype.updateChildPosition = function (child, xCalc, yCalc, parentBounds) {
if (!xCalc || !yCalc)
return;
if (!parentBounds) {
var px1 = this.getX1Coordinate(xCalc, yCalc);
var py1 = this.getY1Coordinate(xCalc, yCalc);
var px2 = this.getX2Coordinate(xCalc, yCalc);
var py2 = this.getY2Coordinate(xCalc, yCalc);
parentBounds = new Rect_1.Rect(Math.min(px1, px2), Math.min(py1, py2), Math.abs(px2 - px1), Math.abs(py2 - py1));
}
var rel = this.ensureNormalized(child, xCalc, yCalc, parentBounds);
if (!rel)
return;
child.x1 = xCalc.getDataValue(parentBounds.x + rel.x1 * parentBounds.width);
child.y1 = yCalc.getDataValue(parentBounds.y + rel.y1 * parentBounds.height);
if (rel.x2 != null && rel.y2 != null) {
child.x2 = xCalc.getDataValue(parentBounds.x + rel.x2 * parentBounds.width);
child.y2 = yCalc.getDataValue(parentBounds.y + rel.y2 * parentBounds.height);
}
};
CompositeAnnotation.prototype.syncPropertiesToChildren = function () {
for (var _i = 0, _a = this.children.asArray(); _i < _a.length; _i++) {
var child = _a[_i];
if (child.xAxisId !== this.xAxisId)
child.xAxisId = this.xAxisId;
if (child.yAxisId !== this.yAxisId)
child.yAxisId = this.yAxisId;
if (child.isHidden !== this.isHidden)
child.isHidden = this.isHidden;
}
};
/** @inheritdoc */
CompositeAnnotation.prototype.notifyPropertyChanged = function (propertyName) {
_super.prototype.notifyPropertyChanged.call(this, propertyName);
if (propertyName === constants_1.PROPERTY.XAXIS_ID ||
propertyName === constants_1.PROPERTY.YAXIS_ID ||
propertyName === constants_1.PROPERTY.IS_HIDDEN) {
this.syncPropertiesToChildren();
}
};
/** @inheritdoc */
CompositeAnnotation.prototype.toJSON = function () {
var json = _super.prototype.toJSON.call(this);
var options = {
annotations: this.children.asArray()
};
Object.assign(json.options, options);
return json;
};
/** @inheritdoc */
CompositeAnnotation.prototype.delete = function () {
this.clear();
_super.prototype.delete.call(this);
};
return CompositeAnnotation;
}(BoxAnnotation_1.BoxAnnotation));
exports.CompositeAnnotation = CompositeAnnotation;