UNPKG

@visactor/vtable-gantt

Version:

canvas table width high performance

432 lines (424 loc) 25.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.TaskBar = exports.TASKBAR_HOVER_ICON_WIDTH = void 0; const vrender_1 = require("@visactor/vtable/es/vrender"), util_1 = require("../tools/util"), vutils_1 = require("@visactor/vutils"), gantt_helper_1 = require("../gantt-helper"), gantt_node_1 = require("./gantt-node"), ts_types_1 = require("../ts-types"), 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>'; exports.TASKBAR_HOVER_ICON_WIDTH = 10; class TaskBar { formatMilestoneText(text, record) { if (!text) return ""; const matches = text.match(/{([^}]+)}/g); return matches && matches.forEach((match => { const fieldName = match.substring(1, match.length - 1), fieldValue = record[fieldName]; void 0 !== fieldValue && (text = text.replace(match, String(fieldValue))); })), text; } calculateMilestoneTextPosition(position, milestoneWidth, padding = 4) { const paddingVal = "number" == typeof padding ? padding : 4; let textX = 0, textY = 0, textAlignValue = "left", textBaselineValue = "middle"; const center = milestoneWidth / 2; switch (position) { case "left": textX = -paddingVal, textY = center, textAlignValue = "end", textBaselineValue = "middle"; break; case "right": default: textX = milestoneWidth + paddingVal, textY = center, textAlignValue = "start", textBaselineValue = "middle"; break; case "top": textX = center, textY = -paddingVal, textAlignValue = "center", textBaselineValue = "bottom"; break; case "bottom": textX = center, textY = milestoneWidth + paddingVal, textAlignValue = "center", textBaselineValue = "top"; } return { textX: textX, textY: textY, textAlignValue: textAlignValue, textBaselineValue: textBaselineValue }; } constructor(scene) { this.selectedBorders = [], this._scene = scene, this.width = scene._gantt.tableNoFrameWidth, this.height = scene._gantt.gridHeight, this.group = new vrender_1.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, _c; this.barContainer = new vrender_1.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 !== ts_types_1.TasksShowMode.Sub_Tasks_Inline && this._scene._gantt.parsedOptions.tasksShowMode !== ts_types_1.TasksShowMode.Sub_Tasks_Separate && this._scene._gantt.parsedOptions.tasksShowMode !== ts_types_1.TasksShowMode.Sub_Tasks_Arrange && this._scene._gantt.parsedOptions.tasksShowMode !== ts_types_1.TasksShowMode.Sub_Tasks_Compact) if (this._scene._gantt.parsedOptions.tasksShowMode !== ts_types_1.TasksShowMode.Project_Sub_Tasks_Inline) { const barGroup = this.initBar(i); barGroup && this.barContainer.appendChild(barGroup); } else { const record = this._scene._gantt.getRecordByIndex(i), isExpanded = "expand" === record.hierarchyState; if (record.type === ts_types_1.TaskType.PROJECT && (null === (_c = record.children) || void 0 === _c ? void 0 : _c.length) > 0 && !isExpanded) { const recordIndex = this._scene._gantt.getRecordIndexByTaskShowIndex(i), sub_task_indexs = Array.isArray(recordIndex) ? [ ...recordIndex ] : [ recordIndex ], callInitBar = (record, sub_task_indexs) => { var _a, _b; 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 child_record = record.children[j]; if (child_record.type !== ts_types_1.TaskType.PROJECT) { const barGroup = this.initBar(i, [ ...sub_task_indexs, j ], record.children.length); barGroup && this.barContainer.appendChild(barGroup); } else callInitBar(child_record, [ ...sub_task_indexs, j ]); } }; callInitBar(record, sub_task_indexs); } else { 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, _d, _e; const taskBarCustomLayout = this._scene._gantt.parsedOptions.taskBarCustomLayout, {startDate: startDate, endDate: endDate, taskDays: taskDays, progress: progress, taskRecord: taskRecord} = this._scene._gantt.getTaskInfoByTaskListIndex(index, childIndex), isMilestone = taskRecord.type === ts_types_1.TaskType.MILESTONE; 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]; let taskBarSize = (0, util_1.computeCountToTimeScale)(endDate, startDate, unit, step, 1) * this._scene._gantt.parsedOptions.timelineColWidth; const taskBarStyle = this._scene._gantt.getTaskBarStyle(index, childIndex), taskbarHeight = taskBarStyle.width; (0, vutils_1.isValid)(taskBarStyle.minSize) && (taskBarSize = Math.max(taskBarSize, taskBarStyle.minSize)); const oneTaskHeigth = this._scene._gantt.parsedOptions.rowHeight, milestoneTaskBarHeight = this._scene._gantt.parsedOptions.taskBarMilestoneStyle.width, x = (0, util_1.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 === ts_types_1.TasksShowMode.Sub_Tasks_Separate ? (null !== (_a = childIndex) && void 0 !== _a ? _a : 0) * oneTaskHeigth : this._scene._gantt.parsedOptions.tasksShowMode === ts_types_1.TasksShowMode.Sub_Tasks_Arrange || this._scene._gantt.parsedOptions.tasksShowMode === ts_types_1.TasksShowMode.Sub_Tasks_Compact ? taskRecord.vtable_gantt_showIndex * oneTaskHeigth : 0) + (oneTaskHeigth - (isMilestone ? milestoneTaskBarHeight : taskbarHeight)) / 2, barGroupBox = new gantt_node_1.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 !== (_b = taskBarStyle.borderLineWidth) && void 0 !== _b ? _b : 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 vrender_1.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 !== (_c = customLayoutObj.renderDefaultBar) && void 0 !== _c && _c, renderDefaultText = null !== (_d = customLayoutObj.renderDefaultText) && void 0 !== _d && _d, rootContainer && (rootContainer.name = "task-bar-custom-render")); } if (renderDefaultBar) { const rect = (0, vrender_1.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, taskRecord.type !== ts_types_1.TaskType.MILESTONE) { const progress_rect = (0, vrender_1.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 && taskRecord.type !== ts_types_1.TaskType.MILESTONE) { const {textAlign: textAlign, textBaseline: textBaseline, fontSize: fontSize, fontFamily: fontFamily, textOverflow: textOverflow, color: color, padding: padding} = this._scene._gantt.parsedOptions.taskBarLabelStyle, position = (0, gantt_helper_1.getTextPos)((0, util_1.toBoxArray)(padding), textAlign, textBaseline, taskBarSize, taskbarHeight), label = (0, vrender_1.createText)({ x: position.x, y: position.y, fontSize: fontSize, fill: color, fontFamily: fontFamily, text: (0, util_1.parseStringTemplate)(this._scene._gantt.parsedOptions.taskBarLabelText, taskRecord), maxLineWidth: taskBarSize - exports.TASKBAR_HOVER_ICON_WIDTH, textBaseline: textBaseline, textAlign: textAlign, ellipsis: "clip" === textOverflow ? "" : "ellipsis" === textOverflow ? "..." : (0, vutils_1.isValid)(textOverflow) ? textOverflow : void 0, poptip: { position: "bottom" } }); barGroup.appendChild(label), barGroupBox.textLabel = label, barGroupBox.labelStyle = this._scene._gantt.parsedOptions.taskBarLabelStyle, barGroupBox.updateTextPosition(); } if (renderDefaultText && "milestone" === taskRecord.type && this._scene._gantt.parsedOptions.taskBarMilestoneStyle.labelText) { const milestoneStyle = this._scene._gantt.parsedOptions.taskBarMilestoneStyle, textStyle = milestoneStyle.labelTextStyle || {}, pos = this.calculateMilestoneTextPosition(milestoneStyle.textOrient || "right", milestoneStyle.width, null !== (_e = textStyle.padding) && void 0 !== _e ? _e : 4), textContainer = new vrender_1.Group({ x: x, y: y, width: milestoneStyle.width, height: milestoneStyle.width, angle: 0, pickable: !1 }), milestoneLabel = (0, vrender_1.createText)({ x: pos.textX, y: pos.textY, fontSize: textStyle.fontSize || 16, fontFamily: textStyle.fontFamily || "Arial", fill: textStyle.color || "#ff0000", textBaseline: textStyle.textBaseline || pos.textBaselineValue, textAlign: textStyle.textAlign || pos.textAlignValue, text: this.formatMilestoneText(milestoneStyle.labelText, taskRecord), pickable: !1 }); textContainer.appendChild(milestoneLabel), this.barContainer.appendChild(textContainer), barGroupBox.milestoneTextLabel = milestoneLabel, barGroupBox.milestoneTextContainer = textContainer; } 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), barGroup.updateTextPosition()); } initHoverBarIcons() { var _a, _b; const hoverBarGroup = new vrender_1.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 : gantt_helper_1.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 vrender_1.Image({ x: 0, y: 0, width: exports.TASKBAR_HOVER_ICON_WIDTH, 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 vrender_1.Image({ x: 0, y: 0, width: exports.TASKBAR_HOVER_ICON_WIDTH, 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 (taskRecord.type === ts_types_1.TaskType.MILESTONE) 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 (taskRecord.type === ts_types_1.TaskType.MILESTONE) 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", exports.TASKBAR_HOVER_ICON_WIDTH), this.hoverBarLeftIcon.setAttribute("height", height - 2 * Math.ceil(height / 10)), this.hoverBarRightIcon.setAttribute("x", width - exports.TASKBAR_HOVER_ICON_WIDTH), this.hoverBarRightIcon.setAttribute("y", Math.ceil(height / 10)), this.hoverBarRightIcon.setAttribute("width", exports.TASKBAR_HOVER_ICON_WIDTH), 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 vrender_1.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 vrender_1.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 = record.type === ts_types_1.TaskType.MILESTONE ? 15 : 10, linkPointContainer = new vrender_1.Group({ x: -linePointPadding, y: 0, width: 10, height: height, pickable: !0 }), linkPoint = new vrender_1.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 vrender_1.Group({ x: width + (linePointPadding - 10), y: 0, width: 10, height: height, pickable: !0 }), linkPoint1 = new vrender_1.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 vrender_1.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 && (!(0, vutils_1.isValid)(sub_task_index) || (0, vutils_1.isValid)(sub_task_index) && c.sub_task_index === sub_task_index)) return c; c = c._next; } return null; } } exports.TaskBar = TaskBar; //# sourceMappingURL=task-bar.js.map