import { select as d3_select } from '../d3.mjs';
import { gStyle, isStr } from '../core.mjs';
import { getColor, findColor } from './colors.mjs';
const root_line_styles = [
'', '', '3, 3', '1, 2',
'3, 4, 1, 4', '5, 3, 1, 3', '5, 3, 1, 3, 1, 3, 1, 3', '5, 5',
'5, 3, 1, 3, 1, 3', '20, 5', '20, 10, 1, 10', '1, 3'];
/**
* @summary Handle for line attributes
* @private
*/
class TAttLineHandler {
/** @summary constructor
* @param {object} attr - attributes, see {@link TAttLineHandler#setArgs} */
constructor(args) {
this.func = this.apply.bind(this);
this.used = true;
if (args._typename && (args.fLineStyle !== undefined)) args = { attr: args };
this.setArgs(args);
}
/** @summary Set line attributes.
* @param {object} args - specify attributes by different ways
* @param {object} args.attr - TAttLine object with appropriate data members or
* @param {string} args.color - color in html like rgb(255,0,0) or 'red' or '#ff0000'
* @param {number} args.style - line style number
* @param {number} args.width - line width */
setArgs(args) {
if (args.attr) {
this.color_index = args.attr.fLineColor;
args.color = args.color0 || (args.painter?.getColor(this.color_index) ?? getColor(this.color_index));
if (args.width === undefined) args.width = args.attr.fLineWidth;
if (args.style === undefined) args.style = args.attr.fLineStyle;
} else if (isStr(args.color)) {
if ((args.color !== 'none') && !args.width) args.width = 1;
} else if (typeof args.color === 'number') {
this.color_index = args.color;
args.color = args.painter?.getColor(args.color) ?? getColor(args.color);
}
if (args.width === undefined)
args.width = (args.color && args.color !== 'none') ? 1 : 0;
this.color = (args.width === 0) ? 'none' : args.color;
this.width = args.width;
this.style = args.style;
this.pattern = args.pattern || root_line_styles[this.style] || null;
if (args.can_excl) {
this.excl_side = this.excl_width = 0;
if (Math.abs(this.width) > 99) {
// exclusion graph
this.excl_side = (this.width < 0) ? -1 : 1;
this.excl_width = Math.floor(this.width / 100) * 5;
this.width = Math.abs(this.width % 100); // line width
}
}
// if custom color number used, use lightgrey color to show lines
if (!this.color && (this.width > 0))
this.color = 'lightgrey';
}
/** @summary Change exclusion attributes */
changeExcl(side, width) {
if (width !== undefined)
this.excl_width = width;
if (side !== undefined) {
this.excl_side = side;
if ((this.excl_width === 0) && (this.excl_side !== 0)) this.excl_width = 20;
}
this.changed = true;
}
/** @summary returns true if line attribute is empty and will not be applied. */
empty() { return this.color === 'none'; }
/** @summary Set usage flag of attribute */
setUsed(flag) {
this.used = flag;
}
/** @summary set border parameters, used for rect drawing */
setBorder(rx, ry) {
this.rx = rx;
this.ry = ry;
this.func = this.applyBorder.bind(this);
}
/** @summary Applies line attribute to selection.
* @param {object} selection - d3.js selection */
apply(selection) {
this.used = true;
if (this.empty()) {
selection.style('stroke', null)
.style('stroke-width', null)
.style('stroke-dasharray', null);
} else {
selection.style('stroke', this.color)
.style('stroke-width', this.width)
.style('stroke-dasharray', this.pattern);
}
}
/** @summary Applies line and border attribute to selection.
* @param {object} selection - d3.js selection */
applyBorder(selection) {
this.used = true;
if (this.empty()) {
selection.attr('rx', null)
.attr('ry', null)
.style('stroke', null)
.style('stroke-width', null)
.style('stroke-dasharray', null);
} else {
selection.attr('rx', this.rx || null)
.attr('ry', this.ry || null)
.style('stroke', this.color)
.style('stroke-width', this.width)
.style('stroke-dasharray', this.pattern);
}
}
/** @summary Change line attributes */
change(color, width, style) {
if (color !== undefined) {
if (this.color !== color)
delete this.color_index;
this.color = color;
}
if (width !== undefined)
this.width = width;
if (style !== undefined) {
this.style = style;
this.pattern = root_line_styles[this.style] || null;
}
this.changed = true;
}
/** @summary Method used when color or pattern were changed with OpenUi5 widgets.
* @private */
verifyDirectChange(/* painter */) {
this.change(this.color, parseInt(this.width), parseInt(this.style));
}
/** @summary Create sample element inside primitive SVG - used in context menu */
createSample(svg, width, height, plain) {
if (plain) svg = d3_select(svg);
svg.append('path')
.attr('d', `M0,${height/2}h${width}`)
.call(this.func);
}
/** @summary Save attributes values to gStyle */
saveToStyle(name_color, name_width, name_style) {
if (name_color) {
const indx = (this.color_index !== undefined) ? this.color_index : findColor(this.color);
if (indx >= 0)
gStyle[name_color] = indx;
}
if (name_width)
gStyle[name_width] = this.width;
if (name_style)
gStyle[name_style] = this.style;
}
} // class TAttLineHandler
/** @summary Get svg string for specified line style
* @private */
function getSvgLineStyle(indx) {
if ((indx < 0) || (indx >= root_line_styles.length)) indx = 11;
return root_line_styles[indx];
}
export { TAttLineHandler, getSvgLineStyle, root_line_styles };