(function() {
/**
* @typedef {Help4.control2.Control.Params} Help4.control2.Line.Params
* @property {Help4.control2.PositionXY} point1 - start point of line
* @property {Help4.control2.PositionXY} point2 - end point of line
* @property {number} [thickness = 2] - thickness of line
* @property {string} [ending1 = 'none'] - start point design
* @property {string} [ending2 = 'none'] - end point design
* @property {number} [endingSize = 6] - size of start & end points
*/
/**
* A control to display a line.
* @augments Help4.control2.Control
* @property {Help4.control2.PositionXY} point1 - start point of line
* @property {Help4.control2.PositionXY} point2 - end point of line
* @property {number} thickness - thickness of line; readonly
* @property {string} ending1 - start point design; readonly
* @property {string} ending2 - end point design; readonly
* @property {number} endingSize - size of start/end points; readonly
*/
Help4.control2.Line = class extends Help4.control2.Control {
/**
* @override
* @param {Help4.control2.Line.Params} [params]
* @param {Help4.jscore.ControlBase.Params} [derived]
*/
constructor(params, derived) {
const T = Help4.jscore.ControlBase.TYPES;
super(params, {
params: {
point1: {type: T.xy, mandatory: true},
point2: {type: T.xy, mandatory: true},
thickness: {type: T.number, init: 2, readonly: true},
ending1: {type: T.string, init: 'none', readonly: true}, // can be round, square or none
ending2: {type: T.string, init: 'none', readonly: true},
endingSize: {type: T.number, init: 6, readonly: true}
},
statics: {
_line: {destroy: false}
},
config: {
css: 'control-line'
},
derived
});
}
/**
* @override
* @param {Help4.jscore.ControlBase.PropertyChangeEvent} event - the change event
*/
_applyPropertyToDom({name, value, oldValue}) {
if ({point1: 1, point2: 1}[name] >= 0) {
_apply.call(this);
} else {
super._applyPropertyToDom({name, value, oldValue});
}
}
/**
* @override
* @param {HTMLElement} dom - control DOM
*/
_onDomCreated(dom) {
const {endingSize, ending1, ending2, thickness} = this;
const endingHalf = endingSize / 2;
const endingTransform = endingHalf + 'px ' + endingHalf + 'px';
dom.style.height = endingSize + 'px';
dom.style.transformOrigin = endingTransform;
// create end points
this._createElement('div', {
css: 'ending left ' + ending1,
style: {
width: endingSize + 'px',
height: endingSize + 'px'
}
});
this._createElement('div', {
css: 'ending right ' + ending2,
style: {
width: endingSize + 'px',
height: endingSize + 'px'
}
});
// create line
const padding = endingSize - thickness;
this._line = this._createElement('div', {
css: 'line',
style: {
left: endingSize / 2 + 'px',
top: padding / 2 + 'px',
height: thickness + 'px'
}
});
_apply.call(this);
}
}
/**
* @memberof Help4.control2.Line#
* @private
*/
function _apply() {
const dom = this.getDom();
const {_line, endingSize} = this;
if (!dom || !_line) return;
const c = _calc.call(this);
const endingRotate = 'rotate(' + c.rot + ')';
const endingHalf = endingSize / 2;
// move and adjust wrapper
const {x, y} = this.point1;
Help4.extendObject(dom.style, {
left: x - endingHalf + 'px',
top: y - endingHalf + 'px',
width: c.w + endingSize + 'px',
transform: endingRotate
});
// correctly align the inner line
_line.style.width = c.w + 'px';
}
/**
* @memberof Help4.control2.Line#
* @returns {{rot: string, w: number}}
* @private
*/
function _calc() {
const {point1: {x: x1, y: y1}, point2: {x: x2, y: y2}, endingSize} = this;
const dx = x2 - x1;
const dy = y2 - y1;
if (dx === 0) {
return {
w: Math.abs(dy) + endingSize / 2,
rot: '270deg'
};
} else {
const pi = dx > 0 ? 0 : Math.PI;
return {
w: Math.sqrt(dx * dx + dy * dy) + endingSize / 2,
rot: Math.atan(dy / dx) + pi + 'rad'
};
}
}
})();