toway-vtable-gantt
Version:
canvas table width high performance
352 lines (344 loc) • 20.9 kB
JavaScript
import { Group, createText, createRect, Image, Circle, Line } from "@visactor/vtable/es/vrender";
import { computeCountToTimeScale, createDateAtMidnight, parseStringTemplate, toBoxArray } from "../tools/util";
import { isValid } from "@visactor/vutils";
import { computeRowsCountByRecordDate, computeRowsCountByRecordDateForCompact, defaultTaskBarStyle, getTextPos } from "../gantt-helper";
import { GanttTaskBarNode } from "./gantt-node";
import { TasksShowMode } from "../ts-types";
const TASKBAR_HOVER_ICON = '<svg width="100" height="200" xmlns="http://www.w3.org/2000/svg">\n <line x1="30" y1="10" x2="30" y2="190" stroke="black" stroke-width="4"/>\n <line x1="70" y1="10" x2="70" y2="190" stroke="black" stroke-width="4"/>\n</svg>';
export const TASKBAR_HOVER_ICON_WIDTH = 10;
export class TaskBar {
constructor(scene) {
this.selectedBorders = [], this._scene = scene, this.width = scene._gantt.tableNoFrameWidth,
this.height = scene._gantt.gridHeight, this.group = new Group({
x: 0,
y: scene._gantt.getAllHeaderRowsHeight(),
width: this.width,
height: this.height,
pickable: !1,
clip: !0
}), this.group.name = "task-bar-container", scene.ganttGroup.addChild(this.group),
this.initBars(), this.initHoverBarIcons();
}
initBars() {
var _a, _b;
this.barContainer = new Group({
x: 0,
y: 0,
width: this._scene._gantt.getAllDateColsWidth(),
height: this._scene._gantt.getAllTaskBarsHeight(),
pickable: !1,
clip: !0
}), this.group.appendChild(this.barContainer);
for (let i = 0; i < this._scene._gantt.itemCount; i++) if (this._scene._gantt.parsedOptions.tasksShowMode !== TasksShowMode.Sub_Tasks_Inline && this._scene._gantt.parsedOptions.tasksShowMode !== TasksShowMode.Sub_Tasks_Separate && this._scene._gantt.parsedOptions.tasksShowMode !== TasksShowMode.Sub_Tasks_Arrange && this._scene._gantt.parsedOptions.tasksShowMode !== TasksShowMode.Sub_Tasks_Compact) {
const barGroup = this.initBar(i);
barGroup && this.barContainer.appendChild(barGroup);
} else {
const record = this._scene._gantt.getRecordByIndex(i);
if ((null === (_a = record.children) || void 0 === _a ? void 0 : _a.length) > 0) for (let j = 0; j < (null === (_b = record.children) || void 0 === _b ? void 0 : _b.length); j++) {
const barGroup = this.initBar(i, j, record.children.length);
barGroup && this.barContainer.appendChild(barGroup);
} else {
const barGroup = this.initBar(i);
barGroup && this.barContainer.appendChild(barGroup);
}
}
}
initBar(index, childIndex, childrenLength) {
var _a, _b, _c;
const taskBarCustomLayout = this._scene._gantt.parsedOptions.taskBarCustomLayout, {startDate: startDate, endDate: endDate, taskDays: taskDays, progress: progress, taskRecord: taskRecord} = this._scene._gantt.getTaskInfoByTaskListIndex(index, childIndex), isMilestone = "milestone" === taskRecord.type;
if (isMilestone && !startDate || !isMilestone && (taskDays <= 0 || !startDate || !endDate || startDate.getTime() > endDate.getTime())) return null;
const {unit: unit, step: step} = this._scene._gantt.parsedOptions.reverseSortedTimelineScales[0], taskBarSize = computeCountToTimeScale(endDate, startDate, unit, step, 1) * this._scene._gantt.parsedOptions.timelineColWidth, taskBarStyle = this._scene._gantt.getTaskBarStyle(index, childIndex), taskbarHeight = taskBarStyle.width, oneTaskHeigth = (createDateAtMidnight(this._scene._gantt.parsedOptions.minDate),
this._scene._gantt.parsedOptions.tasksShowMode === TasksShowMode.Sub_Tasks_Separate || (this._scene._gantt.parsedOptions.tasksShowMode === TasksShowMode.Sub_Tasks_Arrange ? computeRowsCountByRecordDate(this._scene._gantt, this._scene._gantt.records[index]) : this._scene._gantt.parsedOptions.tasksShowMode === TasksShowMode.Sub_Tasks_Compact && computeRowsCountByRecordDateForCompact(this._scene._gantt, this._scene._gantt.records[index])),
this._scene._gantt.parsedOptions.rowHeight), milestoneTaskBarHeight = this._scene._gantt.parsedOptions.taskBarMilestoneStyle.width, x = computeCountToTimeScale(startDate, this._scene._gantt.parsedOptions.minDate, unit, step) * this._scene._gantt.parsedOptions.timelineColWidth - (isMilestone ? milestoneTaskBarHeight / 2 : 0), y = this._scene._gantt.getRowsHeightByIndex(0, index - 1) + (this._scene._gantt.parsedOptions.tasksShowMode === TasksShowMode.Sub_Tasks_Separate ? (null != childIndex ? childIndex : 0) * oneTaskHeigth : this._scene._gantt.parsedOptions.tasksShowMode === TasksShowMode.Sub_Tasks_Arrange || this._scene._gantt.parsedOptions.tasksShowMode === TasksShowMode.Sub_Tasks_Compact ? taskRecord.vtable_gantt_showIndex * oneTaskHeigth : 0) + (oneTaskHeigth - (isMilestone ? milestoneTaskBarHeight : taskbarHeight)) / 2, barGroupBox = new GanttTaskBarNode({
x: x,
y: y,
width: isMilestone ? milestoneTaskBarHeight : taskBarSize,
height: isMilestone ? milestoneTaskBarHeight : taskbarHeight,
cornerRadius: isMilestone ? this._scene._gantt.parsedOptions.taskBarMilestoneStyle.cornerRadius : taskBarStyle.cornerRadius,
lineWidth: isMilestone ? 2 * this._scene._gantt.parsedOptions.taskBarMilestoneStyle.borderLineWidth : 2 * (null !== (_a = taskBarStyle.borderLineWidth) && void 0 !== _a ? _a : taskBarStyle.borderWidth),
stroke: isMilestone ? this._scene._gantt.parsedOptions.taskBarMilestoneStyle.borderColor : taskBarStyle.borderColor,
angle: isMilestone ? .25 * Math.PI : 0,
anchor: isMilestone ? [ x + milestoneTaskBarHeight / 2, y + milestoneTaskBarHeight / 2 ] : void 0
});
barGroupBox.name = "task-bar", barGroupBox.task_index = index, barGroupBox.sub_task_index = childIndex,
barGroupBox.record = taskRecord;
const barGroup = new Group({
x: 0,
y: 0,
width: barGroupBox.attribute.width,
height: barGroupBox.attribute.height,
cornerRadius: isMilestone ? this._scene._gantt.parsedOptions.taskBarMilestoneStyle.cornerRadius : taskBarStyle.cornerRadius,
clip: !0
});
let rootContainer;
barGroup.name = "task-bar-group", barGroupBox.appendChild(barGroup), barGroupBox.clipGroupBox = barGroup;
let renderDefaultBar = !0, renderDefaultText = !0;
if (taskBarCustomLayout) {
let customLayoutObj;
if ("function" == typeof taskBarCustomLayout) {
customLayoutObj = taskBarCustomLayout({
width: taskBarSize,
height: taskbarHeight,
index: index,
startDate: startDate,
endDate: endDate,
taskDays: taskDays,
progress: progress,
taskRecord: taskRecord,
ganttInstance: this._scene._gantt
});
} else customLayoutObj = taskBarCustomLayout;
customLayoutObj && (rootContainer = customLayoutObj.rootContainer, renderDefaultBar = null !== (_b = customLayoutObj.renderDefaultBar) && void 0 !== _b && _b,
renderDefaultText = null !== (_c = customLayoutObj.renderDefaultText) && void 0 !== _c && _c,
rootContainer && (rootContainer.name = "task-bar-custom-render"));
}
if (renderDefaultBar) {
const rect = createRect({
x: 0,
y: 0,
width: barGroupBox.attribute.width,
height: barGroupBox.attribute.height,
fill: isMilestone ? this._scene._gantt.parsedOptions.taskBarMilestoneStyle.fillColor : taskBarStyle.barColor,
pickable: !1
});
if (rect.name = "task-bar-rect", barGroup.appendChild(rect), barGroupBox.barRect = rect,
"milestone" !== taskRecord.type) {
const progress_rect = createRect({
x: 0,
y: 0,
width: taskBarSize * progress / 100,
height: taskbarHeight,
fill: taskBarStyle.completedBarColor,
pickable: !1
});
progress_rect.name = "task-bar-progress-rect", barGroup.appendChild(progress_rect),
barGroupBox.progressRect = progress_rect;
}
}
if (rootContainer && barGroup.appendChild(rootContainer), renderDefaultText && "milestone" !== taskRecord.type) {
const {textAlign: textAlign, textBaseline: textBaseline, fontSize: fontSize, fontFamily: fontFamily, textOverflow: textOverflow, color: color, padding: padding} = this._scene._gantt.parsedOptions.taskBarLabelStyle, position = getTextPos(toBoxArray(padding), textAlign, textBaseline, taskBarSize, taskbarHeight), label = createText({
x: position.x,
y: position.y,
fontSize: fontSize,
fill: color,
fontFamily: fontFamily,
text: parseStringTemplate(this._scene._gantt.parsedOptions.taskBarLabelText, taskRecord),
maxLineWidth: taskBarSize - 10,
textBaseline: textBaseline,
textAlign: textAlign,
ellipsis: "clip" === textOverflow ? "" : "ellipsis" === textOverflow ? "..." : isValid(textOverflow) ? textOverflow : void 0,
poptip: {
position: "bottom",
dx: (taskBarSize - 10) / 4
}
});
barGroup.appendChild(label), barGroupBox.textLabel = label;
}
return barGroupBox;
}
updateTaskBarNode(index, sub_task_index) {
const taskbarGroup = this.getTaskBarNodeByIndex(index, sub_task_index);
taskbarGroup && this.barContainer.removeChild(taskbarGroup);
const barGroup = this.initBar(index, sub_task_index);
barGroup && this.barContainer.insertInto(barGroup, index);
}
initHoverBarIcons() {
var _a, _b;
const hoverBarGroup = new Group({
x: 0,
y: 0,
width: 100,
height: 100,
clip: !0,
pickable: !1,
cornerRadius: null !== (_b = null !== (_a = this._scene._gantt.parsedOptions.taskBarHoverStyle.cornerRadius) && void 0 !== _a ? _a : defaultTaskBarStyle.cornerRadius) && void 0 !== _b ? _b : 0,
fill: this._scene._gantt.parsedOptions.taskBarHoverStyle.barOverlayColor,
visibleAll: !1
});
if (this.hoverBarGroup = hoverBarGroup, hoverBarGroup.name = "task-bar-hover-shadow",
this._scene._gantt.parsedOptions.taskBarResizable) {
const icon = new Image({
x: 0,
y: 0,
width: 10,
height: 20,
image: TASKBAR_HOVER_ICON,
pickable: !0,
cursor: "col-resize"
});
icon.name = "task-bar-hover-shadow-left-icon", this.hoverBarLeftIcon = icon, hoverBarGroup.appendChild(icon);
const rightIcon = new Image({
x: 0,
y: 0,
width: 10,
height: 20,
image: TASKBAR_HOVER_ICON,
pickable: !0,
cursor: "col-resize"
});
rightIcon.name = "task-bar-hover-shadow-right-icon", this.hoverBarRightIcon = rightIcon,
hoverBarGroup.appendChild(rightIcon);
}
}
setX(x) {
this.barContainer.setAttribute("x", x);
}
setY(y) {
this.barContainer.setAttribute("y", y);
}
refresh() {
this.width = this._scene._gantt.tableNoFrameWidth, this.height = this._scene._gantt.gridHeight,
this.group.setAttributes({
height: this.height,
width: this.width,
y: this._scene._gantt.getAllHeaderRowsHeight()
});
const x = this.barContainer.attribute.x, y = this.barContainer.attribute.y;
this.barContainer.removeAllChild(), this.group.removeChild(this.barContainer), this.initBars(),
this.setX(x), this.setY(y);
}
resize() {
this.width = this._scene._gantt.tableNoFrameWidth, this.height = this._scene._gantt.gridHeight,
this.group.setAttribute("width", this.width), this.group.setAttribute("height", this.height);
}
showHoverBar(x, y, width, height, target) {
var _a, _b, _c, _d;
const {startDate: startDate, endDate: endDate, taskRecord: taskRecord} = this._scene._gantt.getTaskInfoByTaskListIndex(target.task_index, target.sub_task_index);
target && "task-bar" === target.name && target.appendChild(this.hoverBarGroup),
this.hoverBarGroup.setAttribute("x", 0), this.hoverBarGroup.setAttribute("y", 0),
this.hoverBarGroup.setAttribute("width", width), this.hoverBarGroup.setAttribute("height", height),
this.hoverBarGroup.setAttribute("visibleAll", !0);
const taskBarStyle = this._scene._gantt.getTaskBarStyle(target.task_index, target.sub_task_index);
if ("milestone" === taskRecord.type) this.hoverBarGroup.setAttribute("cornerRadius", target.attribute.cornerRadius); else {
const cornerRadius = null !== (_b = null !== (_a = this._scene._gantt.parsedOptions.taskBarHoverStyle.cornerRadius) && void 0 !== _a ? _a : taskBarStyle.cornerRadius) && void 0 !== _b ? _b : 0;
this.hoverBarGroup.setAttribute("cornerRadius", cornerRadius);
}
null === (_c = this.hoverBarLeftIcon) || void 0 === _c || _c.setAttribute("visible", !1),
null === (_d = this.hoverBarRightIcon) || void 0 === _d || _d.setAttribute("visible", !1);
let leftResizable = !0, rightResizable = !0;
if ("milestone" === taskRecord.type) leftResizable = !1, rightResizable = !1; else if ("function" == typeof this._scene._gantt.parsedOptions.taskBarResizable) {
const arg = {
index: target.task_index,
startDate: startDate,
endDate: endDate,
taskRecord: taskRecord,
ganttInstance: this._scene._gantt
}, resizableResult = this._scene._gantt.parsedOptions.taskBarResizable(arg);
Array.isArray(resizableResult) ? [leftResizable, rightResizable] = resizableResult : (leftResizable = resizableResult,
rightResizable = resizableResult);
} else Array.isArray(this._scene._gantt.parsedOptions.taskBarResizable) ? [leftResizable, rightResizable] = this._scene._gantt.parsedOptions.taskBarResizable : (leftResizable = this._scene._gantt.parsedOptions.taskBarResizable,
rightResizable = this._scene._gantt.parsedOptions.taskBarResizable);
leftResizable && this.hoverBarLeftIcon.setAttribute("visible", !0), rightResizable && this.hoverBarRightIcon.setAttribute("visible", !0),
this.hoverBarLeftIcon && (this.hoverBarLeftIcon.setAttribute("x", 0), this.hoverBarLeftIcon.setAttribute("y", Math.ceil(height / 10)),
this.hoverBarLeftIcon.setAttribute("width", 10), this.hoverBarLeftIcon.setAttribute("height", height - 2 * Math.ceil(height / 10)),
this.hoverBarRightIcon.setAttribute("x", width - 10), this.hoverBarRightIcon.setAttribute("y", Math.ceil(height / 10)),
this.hoverBarRightIcon.setAttribute("width", 10), this.hoverBarRightIcon.setAttribute("height", height - 2 * Math.ceil(height / 10)));
}
hideHoverBar() {
this.hoverBarGroup.setAttribute("visibleAll", !1);
}
createSelectedBorder(x, y, width, height, attachedToTaskBarNode, showLinkPoint = !1) {
const record = attachedToTaskBarNode.record, selectedBorder = new Group({
x: x,
y: y,
width: width,
height: height,
pickable: !1,
attachedToTaskBarNode: attachedToTaskBarNode,
zIndex: 1e4
});
selectedBorder.name = "task-bar-select-border", this.barContainer.appendChild(selectedBorder),
this.selectedBorders.push(selectedBorder);
const selectRectBorder = new Group({
x: 0,
y: 0,
width: width,
height: height,
lineWidth: this._scene._gantt.parsedOptions.taskBarSelectedStyle.borderLineWidth,
pickable: !1,
cornerRadius: attachedToTaskBarNode.attribute.cornerRadius,
fill: !1,
stroke: this._scene._gantt.parsedOptions.taskBarSelectedStyle.borderColor,
shadowColor: this._scene._gantt.parsedOptions.taskBarSelectedStyle.shadowColor,
shadowOffsetX: this._scene._gantt.parsedOptions.taskBarSelectedStyle.shadowOffsetX,
shadowOffsetY: this._scene._gantt.parsedOptions.taskBarSelectedStyle.shadowOffsetY,
shadowBlur: this._scene._gantt.parsedOptions.taskBarSelectedStyle.shadowBlur,
angle: attachedToTaskBarNode.attribute.angle,
anchor: [ width / 2, height / 2 ]
});
if (selectedBorder.appendChild(selectRectBorder), showLinkPoint) {
const linePointPadding = "milestone" === record.type ? 15 : 10, linkPointContainer = new Group({
x: -linePointPadding,
y: 0,
width: 10,
height: height,
pickable: !0
}), linkPoint = new Circle({
x: 5,
y: height / 2,
radius: this._scene._gantt.parsedOptions.dependencyLinkLineCreatePointStyle.radius,
fill: this._scene._gantt.parsedOptions.dependencyLinkLineCreatePointStyle.fillColor,
stroke: this._scene._gantt.parsedOptions.dependencyLinkLineCreatePointStyle.strokeColor,
lineWidth: this._scene._gantt.parsedOptions.dependencyLinkLineCreatePointStyle.strokeWidth,
pickable: !1
});
linkPointContainer.appendChild(linkPoint), linkPointContainer.name = "task-bar-link-point-left",
selectedBorder.appendChild(linkPointContainer);
const linkPointContainer1 = new Group({
x: width + (linePointPadding - 10),
y: 0,
width: 10,
height: height,
pickable: !0
}), linkPoint1 = new Circle({
x: 5,
y: height / 2,
radius: this._scene._gantt.parsedOptions.dependencyLinkLineCreatePointStyle.radius,
fill: this._scene._gantt.parsedOptions.dependencyLinkLineCreatePointStyle.fillColor,
stroke: this._scene._gantt.parsedOptions.dependencyLinkLineCreatePointStyle.strokeColor,
lineWidth: this._scene._gantt.parsedOptions.dependencyLinkLineCreatePointStyle.strokeWidth,
pickable: !1,
pickStrokeBuffer: 10
});
linkPointContainer1.appendChild(linkPoint1), linkPointContainer1.name = "task-bar-link-point-right",
selectedBorder.appendChild(linkPointContainer1);
}
}
removeSelectedBorder() {
this.selectedBorders.forEach((border => {
border.delete();
})), this.selectedBorders = [];
}
removeSecondSelectedBorder() {
if (2 === this.selectedBorders.length) {
this.selectedBorders.pop().delete();
}
}
updateCreatingDependencyLine(x1, y1, x2, y2) {
this.creatingDependencyLine && (this.creatingDependencyLine.delete(), this.creatingDependencyLine = void 0);
const line = new Line({
points: [ {
x: x1,
y: y1
}, {
x: x2,
y: y2
} ],
stroke: this._scene._gantt.parsedOptions.dependencyLinkLineCreatingStyle.lineColor,
lineWidth: this._scene._gantt.parsedOptions.dependencyLinkLineCreatingStyle.lineWidth,
lineDash: this._scene._gantt.parsedOptions.dependencyLinkLineCreatingStyle.lineDash,
pickable: !1
});
this.creatingDependencyLine = line, this.selectedBorders[0].appendChild(line);
}
getTaskBarNodeByIndex(index, sub_task_index) {
let c = this.barContainer.firstChild;
if (!c) return null;
for (let i = 0; i < this.barContainer.childrenCount; i++) {
if (c.task_index === index && (!isValid(sub_task_index) || isValid(sub_task_index) && c.sub_task_index === sub_task_index)) return c;
c = c._next;
}
return null;
}
}
//# sourceMappingURL=task-bar.js.map