Files
web/web_timeline/static/src/js/timeline_canvas.js
Murtaza Mithaiwala 4b562effb8 [FIX] Travis
2022-08-02 14:35:04 +02:00

161 lines
5.9 KiB
JavaScript

/* Copyright 2018 Onestein
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
odoo.define("web_timeline.TimelineCanvas", function (require) {
"use strict";
const Widget = require("web.Widget");
/**
* Used to draw stuff on upon the timeline view.
*/
const TimelineCanvas = Widget.extend({
template: "TimelineView.Canvas",
/**
* Clears all drawings (svg elements) from the canvas.
*/
clear: function () {
this.$(" > :not(defs)").remove();
},
/**
* Gets the path from one point to another.
*
* @param {Object} rectFrom
* @param {Object} rectTo
* @param {Number} widthMarker The marker's width of the polyline
* @param {Number} breakAt The space between the line turns
* @returns {Array} Each item represents a coordinate
*/
get_polyline_points: function (rectFrom, rectTo, widthMarker, breakAt) {
let fromX = 0,
toX = 0;
if (rectFrom.x < rectTo.x + rectTo.w) {
fromX = rectFrom.x + rectFrom.w + widthMarker;
toX = rectTo.x;
} else {
fromX = rectFrom.x - widthMarker;
toX = rectTo.x + rectTo.w;
}
let deltaBreak = 0;
if (fromX < toX) {
deltaBreak = fromX + breakAt - (toX - breakAt);
} else {
deltaBreak = fromX - breakAt - (toX + breakAt);
}
const fromHalfHeight = rectFrom.h / 2;
const fromY = rectFrom.y + fromHalfHeight;
const toHalfHeight = rectTo.h / 2;
const toY = rectTo.y + toHalfHeight;
const xDiff = fromX - toX;
const yDiff = fromY - toY;
const threshold = breakAt + widthMarker;
const spaceY = toHalfHeight + 2;
const points = [[fromX, fromY]];
const _addPoints = (space, ePoint, mode) => {
if (mode) {
points.push([fromX + breakAt, fromY]);
points.push([fromX + breakAt, ePoint + space]);
points.push([toX - breakAt, toY + space]);
points.push([toX - breakAt, toY]);
} else {
points.push([fromX - breakAt, fromY]);
points.push([fromX - breakAt, ePoint + space]);
points.push([toX + breakAt, toY + space]);
points.push([toX + breakAt, toY]);
}
};
if (fromY !== toY) {
if (Math.abs(xDiff) < threshold) {
points.push([fromX + breakAt, toY + yDiff]);
points.push([fromX + breakAt, toY]);
} else {
const yDiffSpace = yDiff > 0 ? spaceY : -spaceY;
_addPoints(yDiffSpace, toY, rectFrom.x < rectTo.x + rectTo.w);
}
} else if (Math.abs(deltaBreak) >= threshold) {
_addPoints(spaceY, fromY, fromX < toX);
}
points.push([toX, toY]);
return points;
},
/**
* Draws an arrow.
*
* @param {HTMLElement} from Element to draw the arrow from
* @param {HTMLElement} to Element to draw the arrow to
* @param {String} color Color of the line
* @param {Number} width Width of the line
* @returns {HTMLElement} The created SVG polyline
*/
draw_arrow: function (from, to, color, width) {
return this.draw_line(from, to, color, width, "#arrowhead", 10, 12);
},
/**
* Draws a line.
*
* @param {HTMLElement} from Element to draw the line from
* @param {HTMLElement} to Element to draw the line to
* @param {String} color Color of the line
* @param {Number} width Width of the line
* @param {String} markerStart Start marker of the line
* @param {Number} widthMarker The marker's width of the polyline
* @param {Number} breakLineAt The space between the line turns
* @returns {HTMLElement} The created SVG polyline
*/
draw_line: function (
from,
to,
color,
width,
markerStart,
widthMarker,
breakLineAt
) {
const $from = $(from);
const childPosFrom = $from.offset();
const parentPosFrom = $from.closest(".vis-center").offset();
const rectFrom = {
x: childPosFrom.left - parentPosFrom.left,
y: childPosFrom.top - parentPosFrom.top,
w: $from.width(),
h: $from.height(),
};
const $to = $(to);
const childPosTo = $to.offset();
const parentPosTo = $to.closest(".vis-center").offset();
const rectTo = {
x: childPosTo.left - parentPosTo.left,
y: childPosTo.top - parentPosTo.top,
w: $to.width(),
h: $to.height(),
};
const points = this.get_polyline_points(
rectFrom,
rectTo,
widthMarker,
breakLineAt
);
const line = document.createElementNS(
"http://www.w3.org/2000/svg",
"polyline"
);
line.setAttribute("points", _.flatten(points).join(","));
line.setAttribute("stroke", color || "#000");
line.setAttribute("stroke-width", width || 1);
line.setAttribute("fill", "none");
if (markerStart) {
line.setAttribute("marker-start", "url(" + markerStart + ")");
}
this.$el.append(line);
return line;
},
});
return TimelineCanvas;
});