//////////////////////////////////////////////////////////////////////////////
// Dividers
//////////////////////////////////////////////////////////////////////////////
import Divider from './Divider';
import CGArray from './CGArray';
/**
* Dividers is a container for the track and slot [divider](Divider.html).
* They are accessed from the viewer object (e.g. cgv):
* - cgv.dividers.track - controls spacing/lines between tracks.
* - cgv.dividers.slot - controls spacing/lines betweens slots within a track.
*
* <a name="attributes"></a>
* ### Attributes
*
* Option | Description
* ------------------------------|----------------------------
* [track](#track) | [Divider attributes](Divider.html#attributes) for tracks
* [slot](#slot) | [Divider attributes](Divider.html#attributes) for slots
*/
class Dividers {
/**
* Create the dividers container
* @param {Viewer} viewer - The viewer that contains the dividers
* @param {Object} options - [Attributes](#attributes) used to create the dividers. Passed on slot and track divider.
* @param {Object} [meta] - User-defined [Meta data](../tutorials/details-meta-data.html) to add to the dividers
*/
constructor(viewer, options = {}, meta = {}) {
this.viewer = viewer;
const keys = Object.keys(options);
// Both track and slot data is provided
if (keys.includes('slot') && keys.includes('track')) {
this._slot = new Divider(viewer, 'slot', options.slot);
this._track = new Divider(viewer, 'track', options.track);
} else {
// Only one of track or slot data is provided. Mirro data.
if (keys.includes('slot')) {
this._slot = new Divider(viewer, 'mirrored', options.slot);
this._track = this.slot;
} else if (keys.includes('track')) {
this._track = new Divider(viewer, 'mirrored', options.track);
this._slot = this.track;
} else {
// Neither track or slot data is provided. Create default slot and mirror.
this._slot = new Divider(viewer, 'mirrored');
this._track = this.slot;
}
}
this.clearBbOffsets();
// this.viewer.trigger('settings-update', {attributes: this.toJSON({includeDefaults: true})});
}
/**
* Return the class name as a string.
* @return {String} - 'Dividers'
*/
toString() {
return 'Dividers';
}
/**
* Returns the track divider
*/
get track() {
return this._track;
}
/**
* Returns the slot divider
*/
get slot() {
return this._slot;
}
/**
* Returns true if the slot and track divider are mirrored
*/
get dividersMirrored() {
return this.slot === this.track;
}
/**
* If a dividier is provided, the other divider will be mirroed to the provide one.
* If no divider is provided, the dividers will no longer be mirrored.
* @private
*/
mirrorDivider(divider) {
if (divider) {
// Mirror other divider to the one provided
if (this.slot === divider) {
this._track = this.slot;
} else {
this._slot = this.track;
}
this.slot._name = 'mirrored';
} else {
// Turn off mirroring
this._track = new Divider(this.viewer, 'track', this.slot.toJSON());
this.slot._name = 'slot';
}
}
/**
* @member {Number} - Returns a CGArray where each element is an object with 2 properties: distance, type. The 'distance' is the divider distance from the backbone. The 'type' is the divider type (e.g. 'slot' or 'track').
* @private
*/
get bbOffsets() {
return this._bbOffsets;
}
/**
* @private
*/
clearBbOffsets() {
this._bbOffsets = new CGArray();
}
/**
* @private
*/
addBbOffset(bbOffset, type) {
if (['track', 'slot'].includes(type)) {
this._bbOffsets.push({distance: bbOffset, type: type});
} else {
throw 'Divider bbOffset type must be one of "slot" or "track"';
}
}
/**
* Invert colors of the dividers
*/
invertColors() {
if (this.track.mirror) {
this.track.update({ color: this.track.color.invert().rgbaString });
} else {
this.track.update({ color: this.track.color.invert().rgbaString });
this.slot.update({ color: this.slot.color.invert().rgbaString });
}
}
/**
* Draw the dividers
* @private
*/
draw() {
const canvas = this.viewer.canvas;
const backboneOffset = this.viewer.backbone.adjustedCenterOffset;
// if (!this.visible || this.thickness === 0) { return; }
for (let i = 0, len = this._bbOffsets.length; i < len; i++) {
const bbOffset = this._bbOffsets[i];
if (!this[bbOffset.type].visible) { continue; }
const centerOffset = backboneOffset + bbOffset.distance;
const visibleRange = canvas.visibleRangeForCenterOffset(centerOffset, 100);
if (visibleRange) {
canvas.drawElement('map', visibleRange.start, visibleRange.stop, centerOffset, this[bbOffset.type].color.rgbaString, this[bbOffset.type].adjustedThickness);
}
}
}
/**
* Returns JSON representing the object
*/
toJSON(options = {}) {
if (this.slot === this.track) {
return {
slot: this._slot.toJSON(options),
};
} else {
return {
track: this._track.toJSON(options),
slot: this._slot.toJSON(options),
};
}
}
}
export default Dividers;