UNPKG

mthb-canvas-table

Version:
1,308 lines 78.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const CanvasTableColum_1 = require("./CanvasTableColum"); const CanvasTableMode_1 = require("./CanvasTableMode"); const CustomCanvasIndex_1 = require("./CustomCanvasIndex"); const defaultConfig = { backgroundColor: "white", font: "arial", fontColor: "black", fontSize: 14, fontStyle: "", groupItemArrowColor: "black", groupItemBackgroundColor: "#F9D3CB", groupItemFontColor: "back", headerBackgroundColor: "#add8e6", headerDrawSortArrow: true, headerDrawSortArrowColor: "purple", headerFont: "arial", headerFontColor: "black", headerFontSize: 14, headerFontStyle: "bold", howerBackgroundColor: "#DCDCDC", lineColor: "black", rowGroupItemArrowColor: "black", rowGroupItemBackgroundColor: "#F9D3CB", rowGroupItemFontColor: "black", selectLineColor: "green", sepraBackgroundColor: "#ECECEC", }; class CustomCanvasTable { constructor(config) { this.r = 1; this.data = []; this.allowEdit = false; this.headerHeight = 18; this.cellHeight = 20; this.dataIndex = undefined; this.config = defaultConfig; this.column = []; this.eventDblClick = []; this.eventClick = []; this.eventClickHeader = []; this.eventReCalcForScrollView = []; this.eventEdit = []; this.needToCalc = true; this.needToCalcFont = true; this.isFocus = false; this.minFontWidth = 1; this.maxFontWidth = 1; this.orgColum = []; this.selectRowValue = null; this.lastCursor = ""; this.canvasHeight = 0; this.canvasWidth = 0; this.editData = {}; this.tableMode = CanvasTableMode_1.CanvasTableMode.ColMode; this.updateConfig(config); } getScrollView() { return this.scrollView; } /** * To customize style of CanvasTable * @param config config */ updateConfig(config) { this.config = Object.assign(Object.assign({}, defaultConfig), config); } /** * Is CanvasTable goging to redraw in next frame */ isPlanToRedraw() { if (!this.requestAnimationFrame) { return false; } return (this.drawconf !== undefined && this.drawconf.fulldraw); } /** * Let CanvasTable redraw * @param config */ askForReDraw(config) { if (config === undefined || (this.drawconf !== undefined && this.drawconf.fulldraw)) { this.drawconf = { fulldraw: true }; } else { if (this.drawconf === undefined) { this.drawconf = Object.assign(Object.assign({}, config), { fulldraw: false }); } else { // this.drawconf = ...this.drawconf, ...config; } } if (this.requestAnimationFrame) { return; } this.requestAnimationFrame = requestAnimationFrame(() => { this.drawCanvas(); }); } /** * Recalc index and then redraw * You need to call this if size of the data was change or columns witch was change is in active groupby or sort */ askForReIndex() { this.calcIndex(); this.askForReDraw(); } setAllowEdit(allowEdit) { this.allowEdit = allowEdit; } setRowColStyle(style) { if (style === null) { style = undefined; } if (this.customRowColStyle !== style) { this.customRowColStyle = style; this.askForReDraw(); } } setFilter(filter) { if (filter === null) { filter = undefined; } if (this.customFilter !== filter) { this.customFilter = filter; this.askForReIndex(); } } setCustomSort(customSort) { if (customSort === null) { customSort = undefined; } this.customSort = customSort; this.sortCol = undefined; this.askForReIndex(); } setSort(sortCol) { this.sortCol = sortCol; this.customSort = undefined; this.askForReIndex(); } /** * Set group by data * @param col */ setGroupBy(col) { if (!col) { col = []; } const list = []; let i; for (i = 0; i < col.length; i++) { const item = col[i]; if (typeof item === "string") { list.push({ field: item }); } else { list.push(item); } } this.groupByCol = list; this.askForReIndex(); } setRowTableGroup(row) { if (typeof row === "string") { this.rowTableGroup = { field: row }; } else { this.rowTableGroup = row; } this.askForReIndex(); } setTableMode(tableMode) { if (tableMode !== this.tableMode) { this.tableMode = tableMode; this.askForReIndex(); } } getTableMode() { return this.tableMode; } /** * Set new Data and then reindex and redraw * @param data new Data */ setData(data) { if (data !== undefined) { this.data = data; } this.askForReIndex(); } /** * Change the visibility of the column * @param col index of colum or the column it self * @param visible show or hide the colum */ setColumnVisible(col, visible) { if (typeof col === "number") { if (col < 0 || col >= this.orgColum.length) { throw new Error("out of range"); } if (visible && this.orgColum[col].visible === true) { return; } if (!visible && !this.orgColum[col].visible) { return; } this.orgColum[col].visible = visible; this.updateColumns(this.orgColum); return; } const v = col.visible === undefined ? true : false; if (v !== visible) { col.visible = v; this.updateColumns(this.orgColum); return; } } updateColumns(col) { this.orgColum = col; this.column = []; let i; for (i = 0; i < col.length; i++) { if (col[i].visible === false) { continue; } const index = this.column.length; this.column[index] = Object.assign({ align: CanvasTableColum_1.Align.left, allowEdit: true, index, leftPos: 0, orginalCol: col[i], rightPos: 0, width: 50, }, col[i]); if (this.column[index].field === "__idxnum__" || this.column[index].field === "__rownum__") { this.column[index].allowEdit = false; } } this.needToCalc = true; this.resize(); this.calcColum(); } /** * Expend All data in tree mode */ expendAll() { const dataIndex = this.dataIndex; if (dataIndex === undefined) { return; } if (dataIndex.mode === CanvasTableMode_1.CanvasTableMode.ColMode) { const index = dataIndex.index; if (index.type === CustomCanvasIndex_1.CanvasTableIndexType.GroupItems) { this.changeChildExpend(index, true); this.reCalcForScrollView(); this.askForReDraw(); return; } } else { this.changeChildExpend(dataIndex.index, true); this.reCalcForScrollView(); this.askForReDraw(); } } /** * Collapse All data in tree mode */ collapseAll() { const dataIndex = this.dataIndex; if (dataIndex === undefined) { return; } if (dataIndex.mode === CanvasTableMode_1.CanvasTableMode.ColMode) { const index = dataIndex.index; if (index.type === CustomCanvasIndex_1.CanvasTableIndexType.GroupItems) { this.changeChildExpend(index, false); this.reCalcForScrollView(); this.askForReDraw(); return; } } else { this.changeChildExpend(dataIndex.index, false); this.reCalcForScrollView(); this.askForReDraw(); } } addEvent(eventName, event) { this.getEvent(eventName).push(event); } removeEvent(eventName, event) { const e = this.getEvent(eventName); const index = e.indexOf(event); if (index !== -1) { e.splice(index, 1); } } setUpdateData(row, field, data) { const oldData = this.getUpdateDataOrData(row, field); if (!this.editData[row]) { this.editData[row] = {}; } this.editData[row][field] = data; this.fireEdit(row, field, data, oldData); } getUpdateData(row, field) { const rowData = this.editData[row]; if (!rowData) { return undefined; } if (rowData.hasOwnProperty(field)) { return { data: rowData[field] }; } return undefined; } getUpdateDataOrData(row, field) { const rowData = this.editData[row]; if (rowData && rowData.hasOwnProperty(field)) { return rowData[field]; } return this.data[row][field]; } getEditData() { return this.editData; } clearEditData() { this.editData = {}; this.askForReIndex(); } logError(value, value2, value3) { // tslint:disable-next-line: no-console console.log(value, value2, value3); } setOverRow(value) { if (value !== this.overRowValue) { const temp = this.overRowValue; this.overRowValue = value; if (value !== undefined && temp !== undefined) { this.askForReDraw({ drawOnly: [temp, value] }); return; } if (value !== undefined) { this.askForReDraw({ drawOnly: [value] }); return; } if (temp !== undefined) { this.askForReDraw({ drawOnly: [temp] }); return; } } } setR(r) { if (this.r === r) { return; } this.r = r; this.needToCalc = true; this.needToCalcFont = true; } getColumnByCanvasTableColumnConf(column) { let i; for (i = 0; i < this.column.length; i++) { if (this.column[i].orginalCol === column) { return this.column[i]; } } return undefined; } setIsFocus(isFocus) { if (this.isFocus !== isFocus) { this.isFocus = isFocus; if (this.allowEdit) { this.askForReDraw(); } } } fireEdit(row, col, newData, oldData) { let i; for (i = 0; i < this.eventEdit.length; i++) { try { this.eventEdit[i](this, row, col, newData, oldData); } catch (_a) { this.logError("eventEdit"); } } } fireDblClick(row, col) { let i; for (i = 0; i < this.eventDblClick.length; i++) { try { this.eventDblClick[i](this, row, col === null ? null : col.orginalCol); } catch (_a) { this.logError("fireDblClick"); } } } fireClick(row, col) { let i; for (i = 0; i < this.eventClick.length; i++) { try { this.eventClick[i](this, row, col === null ? null : col.orginalCol); } catch (_a) { this.logError("fireClick"); } } } fireClickHeader(col) { let i; for (i = 0; i < this.eventClick.length; i++) { try { this.eventClickHeader[i](this, col === null ? null : col.orginalCol); } catch (_a) { this.logError("fireClickHeader"); } } } fireReCalcForScrollView(width, height) { const scrollView = this.scrollView; if (scrollView) { let i; for (i = 0; i < this.eventReCalcForScrollView.length; i++) { try { this.eventReCalcForScrollView[i](this, width, height, scrollView); } catch (_a) { this.logError("fireReCalcForScrollView"); } } } } clickOnHeader(col) { if (col) { if (this.sortCol && this.sortCol.length === 1 && this.sortCol[0].col === col.orginalCol && this.sortCol[0].sort === CanvasTableColum_1.Sort.ascending) { this.setSort([{ col: col.orginalCol, sort: CanvasTableColum_1.Sort.descending }]); } else { this.setSort([{ col: col.orginalCol, sort: CanvasTableColum_1.Sort.ascending }]); } } } wheel(deltaMode, deltaX, deltaY) { if (this.scrollView) { this.scrollView.onScroll(deltaMode, deltaX, deltaY); } } dblClick(x, y) { const col = this.findColByPos(x); if (y <= this.headerHeight) { return; } const row = this.findRowByPos(y); if (this.allowEdit && row && typeof row.select === "number" && col !== null) { if (!col.allowEdit) { return; } this.updateForEdit(col, row.select); } this.fireDblClick(row === null ? null : row.select, col); } mouseDown(x, y) { if (this.dataIndex === undefined) { return; } if (this.scrollView && this.scrollView.onMouseDown(x, y)) { return; } if (this.dataIndex.mode === CanvasTableMode_1.CanvasTableMode.ColMode) { const dataIndex = this.dataIndex.index; const col = this.findColByPos(x); if (y <= this.headerHeight) { const colSplit = this.findColSplit(x); if (colSplit !== null) { this.columnResize = { x, col: this.column[colSplit] }; this.askForExtentedMouseMoveAndMaouseUp(); this.fireClickHeader(col); return; } this.clickOnHeader(col); this.fireClickHeader(col); return; } const row = this.findRowByPos(y); if (row && typeof row.select === "number" && col !== null) { if (this.selectColValue !== col || this.selectRowValue !== row) { this.selectColValue = col; this.selectRowValue = row; this.askForReDraw(); } } else { if (dataIndex.type === CustomCanvasIndex_1.CanvasTableIndexType.GroupItems) { if (row !== null && typeof row.select === "object") { row.select.isExpended = !row.select.isExpended; this.askForReDraw(); this.reCalcForScrollView(); } } } this.fireClick(row === null ? null : row.select, col); } else { const result = this.findColAndRowInRowMode(x, y); if (result === null) { return; } const { row, col } = result; if (col === null) { row.isExpended = !row.isExpended; this.askForReDraw(); this.reCalcForScrollView(); } } } mouseMove(x, y) { if (!this.scrollView) { return; } if (this.resizeColIfNeed(x)) { return; } if (this.scrollView.onMouseMove(x, y)) { this.updateCursor(); this.setOverRow(undefined); return; } if (y < this.headerHeight) { this.setOverRow(undefined); if (this.findColSplit(x) === null) { this.updateCursor(); } else { this.updateCursor("col-resize"); } return; } else { this.updateCursor(); const result = this.findRowByPos(y); if (result && typeof result.select === "number") { this.setOverRow(result.select); return; } this.setOverRow(undefined); } } mouseUp(x, y) { if (this.columnResize) { this.columnResize = undefined; this.askForNormalMouseMoveAndMaouseUp(); } if (this.scrollView && this.scrollView.onMouseUp(x, y)) { return; } } mouseMoveExtended(x, y) { if (this.resizeColIfNeed(x)) { return; } if (this.scrollView && this.scrollView.onExtendedMouseMove(x, y)) { return; } } mouseUpExtended(x, y) { if (this.columnResize) { this.columnResize = undefined; this.askForNormalMouseMoveAndMaouseUp(); } if (this.scrollView && this.scrollView.onExtendedMouseUp(x, y)) { return; } } mouseLeave() { this.setOverRow(undefined); if (this.columnResize === undefined) { this.updateCursor(); } if (this.scrollView) { this.scrollView.onMouseLeave(); } } keydown(keycode) { if (this.scrollView !== undefined && this.selectColValue !== undefined && this.selectRowValue !== null && this.selectRowValue.mode === CanvasTableMode_1.CanvasTableMode.ColMode && typeof this.selectRowValue.select === "number") { const index = this.selectRowValue.path[this.selectRowValue.path.length - 1]; if (index.type === CustomCanvasIndex_1.CanvasTableIndexType.Index) { let y; switch (keycode) { case 40: // Down if (this.selectRowValue.index === index.list.length - 1) { return; } this.selectRowValue.index++; this.selectRowValue.select = index.list[this.selectRowValue.index]; y = this.findTopPosByRow(this.selectRowValue); if (y !== undefined) { y = y - (this.canvasHeight - ((this.headerHeight + (this.scrollView.getHasScrollBarX() ? this.scrollView.getScrollbarSize() : 0)) * this.r)); if (this.scrollView.getPosY() < y) { this.scrollView.setPosY(y); } } this.askForReDraw(); break; case 38: // Up if (this.selectRowValue.index === 0) { return; } this.selectRowValue.index--; this.selectRowValue.select = index.list[this.selectRowValue.index]; y = this.findTopPosByRow(this.selectRowValue); if (y !== undefined) { y = y - this.headerHeight * this.r; if (this.scrollView.getPosY() > y) { this.scrollView.setPosY(y); } } this.askForReDraw(); break; case 37: // Left if (this.selectColValue.index === 0) { return; } this.selectColValue = this.column[this.selectColValue.index - 1]; if (this.selectColValue.leftPos < this.scrollView.getPosX()) { this.scrollView.setPosX(this.selectColValue.leftPos); } this.askForReDraw(); break; case 39: // Right if (this.selectColValue.index === this.column.length - 1) { return; } this.selectColValue = this.column[this.selectColValue.index + 1]; if (this.selectColValue.rightPos > this.scrollView.getPosX() + this.canvasWidth) { this.scrollView.setPosX(this.selectColValue.rightPos - this.canvasWidth); } this.askForReDraw(); break; case 13: // Enter if (this.allowEdit && typeof this.selectRowValue.select === "number") { if (!this.selectColValue.allowEdit) { return; } this.updateForEdit(this.selectColValue, this.selectRowValue.select); } default: // console.log(keycode); break; } } } else { if (this.scrollView && this.scrollView.OnKeydown(keycode)) { this.setOverRow(undefined); } } } TouchStart(e, offsetLeft, offsetTop) { if (this.scrollView && this.scrollView.OnTouchStart(e, offsetLeft, offsetTop)) { return; } if (e.changedTouches.length === 1) { const y = e.changedTouches[0].pageY - offsetTop; const x = e.changedTouches[0].pageX - offsetLeft; this.touchClick = { timeout: setTimeout(() => { if (this.dataIndex === undefined) { return; } if (this.dataIndex.mode === CanvasTableMode_1.CanvasTableMode.ColMode) { const row = this.findRowByPos(y); const col = this.findColByPos(x); if (y > this.headerHeight) { if (row !== null && typeof row.select === "object") { row.select.isExpended = !row.select.isExpended; this.askForReDraw(); this.reCalcForScrollView(); } this.fireClick(row === null ? null : row.select, col); } else { const colSplit = this.findColSplit(x); if (colSplit !== null) { this.columnResize = { x, col: this.column[colSplit] }; return; } this.clickOnHeader(col); this.fireClickHeader(col); } } else { const result = this.findColAndRowInRowMode(x, y); if (result === null) { return; } const { col, row } = result; if (col === null) { row.isExpended = !row.isExpended; this.askForReDraw(); this.reCalcForScrollView(); } } }, 250), x, y }; } else { this.clearTouchClick(); } } TouchMove(e, offsetLeft, offsetTop) { const x = e.changedTouches[0].pageX - offsetLeft; if (this.resizeColIfNeed(x)) { return; } if (this.scrollView) { this.scrollView.OnTouchMove(e, offsetLeft, offsetTop); } if (this.touchClick) { if (e.changedTouches.length !== 1) { this.clearTouchClick(); return; } const y = e.changedTouches[0].pageY - offsetTop; if (Math.abs(x - this.touchClick.x) > 4 || Math.abs(y - this.touchClick.y) > 4) { this.clearTouchClick(); } } } TouchEnd(e, offsetLeft, offsetTop) { this.columnResize = undefined; if (this.scrollView) { this.scrollView.OnTouchEnd(e); } } calcRect(col, row) { if (!this.scrollView) { return; } const topPos = this.findTopPosByRow(row); if (topPos === undefined) { return; } const y = (topPos - this.scrollView.getPosY()) / this.r; const x = -(this.scrollView.getPosX() / this.r) + (col.leftPos / this.r); const top = y; const left = x; let clipTop; const clipRight = undefined; const clipBottom = undefined; let clipLeft; if (y < this.headerHeight) { // rect(<top>, <right>, <bottom>, <left>) if (x < 0) { clipTop = -y + this.headerHeight; clipLeft = -x; } else { clipTop = -y + this.headerHeight; } } else if (x < 0) { clipLeft = -x; } return { cellHeight: this.cellHeight, clipBottom, clipLeft, clipRight, clipTop, left, top, width: col.width, x, y, }; } findColSplit(x) { if (this.scrollView === undefined) { return null; } const posXNeg = -this.scrollView.getPosX(); for (let i = 0; i < this.column.length; i++) { const d = ((posXNeg + this.column[i].rightPos) / this.r) - x; if (-3 <= d && d <= 3) { return i; } } return null; } findColAndRowInRowMode(x, y) { if (this.dataIndex === undefined || this.scrollView === undefined) { return null; } if (this.dataIndex.mode === CanvasTableMode_1.CanvasTableMode.ColMode) { return null; } let pos = -this.scrollView.getPosY() / this.r; const cellHeight = this.cellHeight; const find = (index) => { let i; if (index.type === CustomCanvasIndex_1.CanvasTableIndexType.GroupItems) { for (i = 0; i < index.list.length; i++) { const item = index.list[i]; if (pos < y && y < pos + cellHeight) { return { row: item, col: null }; } pos += cellHeight; if (item.isExpended) { const result = find(item.child); if (result != null) { return result; } } } } else { for (i = 0; i < index.list.length; i++) { const item = index.list[i]; if (pos < y && y < pos + cellHeight) { return { row: item, col: null }; } pos += cellHeight; if (item.isExpended) { let col; for (col = 0; col < this.column.length; col++) { if (pos < y && y < pos + cellHeight) { return { row: item, col: this.column[col] }; } pos += cellHeight; } } } } return null; }; return find(this.dataIndex.index); } findColByPos(x) { if (this.scrollView === undefined) { return null; } const pos = this.scrollView.getPosX() / this.r + x; let w = 0; let i; for (i = 0; i < this.column.length; i++) { w += this.column[i].width; if (w >= pos) { return this.column[i]; } } return null; } findRowByPos(y) { if (this.dataIndex === undefined || this.scrollView === undefined) { return null; } if (this.dataIndex.mode === CanvasTableMode_1.CanvasTableMode.RowMode) { return null; } const mode = this.dataIndex.mode; let pos = -this.scrollView.getPosY() / this.r + this.headerHeight; const cellHeight = this.cellHeight; const find = (items) => { let i; switch (items.type) { case CustomCanvasIndex_1.CanvasTableIndexType.Index: const h = items.list.length * cellHeight; if (y > pos + h) { pos += h; } else { i = Math.trunc((-pos + y) / cellHeight); pos += i * cellHeight; if (i < items.list.length) { return { mode, path: [items], select: items.list[i], index: i }; } return null; } break; case CustomCanvasIndex_1.CanvasTableIndexType.GroupItems: for (i = 0; i < items.list.length; i++) { if (pos < y && y < pos + cellHeight) { return { mode, path: [items], select: items.list[i], index: i }; } pos += cellHeight; if (!items.list[i].isExpended) { continue; } const f = find(items.list[i].child); if (f !== null) { f.path.unshift(items); return f; } } break; } return null; }; return find(this.dataIndex.index); } findTopPosByRow(rowValue) { if (this.dataIndex === undefined || this.scrollView === undefined || rowValue === null) { return undefined; } if (this.dataIndex.mode === CanvasTableMode_1.CanvasTableMode.RowMode) { return undefined; } let row; let rowGroup; if (typeof rowValue === "number") { row = rowValue; } else { if (typeof rowValue.select === "number") { row = rowValue.select; } else { rowGroup = rowValue.select; } } let pos = this.headerHeight * this.r; const cellHeight = this.cellHeight * this.r; const find = (items) => { let i; switch (items.type) { case CustomCanvasIndex_1.CanvasTableIndexType.Index: if (row === undefined) { pos += cellHeight * items.list.length; } else { for (i = 0; i < items.list.length; i++) { if (items.list[i] === row) { return pos; } pos += cellHeight; } } break; case CustomCanvasIndex_1.CanvasTableIndexType.GroupItems: for (i = 0; i < items.list.length; i++) { if (items.list[i] === rowGroup) { return pos; } pos += cellHeight; if (!items.list[i].isExpended) { continue; } const f = find(items.list[i].child); if (f !== undefined) { return f; } } break; } return undefined; }; return find(this.dataIndex.index); } reCalcIndexIfNeed(field) { let i; if (this.customFilter || this.customSort) { this.calcIndex(); return; } if (this.groupByCol) { for (i = 0; i < this.groupByCol.length; i++) { if (this.groupByCol[i].field === field) { this.calcIndex(); return; } } } if (this.sortCol) { for (i = 0; i < this.sortCol.length; i++) { if (this.sortCol[i].col.field === field) { this.calcIndex(); return; } } } } calcIndex() { if (this.data === undefined) { return; } const index = []; let i; if (this.customFilter) { for (i = 0; i < this.data.length; i++) { if (this.customFilter(this.data, this.data[i], this.orgColum, i, this.editData[i] || {})) { index[index.length] = i; } } } else { for (i = 0; i < this.data.length; i++) { index[index.length] = i; } } if (this.customSort) { const customSort = this.customSort; index.sort((a, b) => { return customSort(this.data, this.data[a], this.data[b], a, b); }); } else { const sortCol = this.sortCol; if (sortCol && sortCol.length) { index.sort((a, b) => { let sortColIndex; for (sortColIndex = 0; sortColIndex < sortCol.length; sortColIndex++) { let d; const col = sortCol[sortColIndex]; switch (col.col.field) { case "__rownum__": d = a - b; if (d !== 0) { return d * col.sort; } break; default: const da = this.getUpdateDataOrData(a, col.col.field); const db = this.getUpdateDataOrData(b, col.col.field); if (da === undefined || da === null) { if (db === undefined || db === null) { continue; } return col.sort; } if (db === undefined || db === null) { return -1 * col.sort; } if (typeof da === "string" && typeof db === "string") { if (da === "") { if (db === "") { continue; } return col.sort; } if (db === "") { return -1 * col.sort; } d = da.localeCompare(db); if (d !== 0) { return d * col.sort; } continue; } if (da > db) { return col.sort; } if (da < db) { return -1 * col.sort; } } } return 0; }); } } if (this.rowTableGroup && this.tableMode === CanvasTableMode_1.CanvasTableMode.RowMode) { if (this.groupByCol && this.groupByCol.length > 0) { const groupItems = { type: CustomCanvasIndex_1.CanvasTableIndexType.GroupItems, list: [] }; this.groupRow(groupItems, index, 0, this.groupByCol, this.rowTableGroup, (this.dataIndex !== undefined && this.dataIndex.index.type === CustomCanvasIndex_1.CanvasTableIndexType.GroupItems) ? this.dataIndex.index : undefined); this.dataIndex = { index: groupItems, mode: CanvasTableMode_1.CanvasTableMode.RowMode, }; } else { const groupItems = { type: CustomCanvasIndex_1.CanvasTableIndexType.GroupRows, list: [] }; this.groupRowItem(groupItems, index, this.rowTableGroup, (this.dataIndex !== undefined && this.dataIndex.index.type === CustomCanvasIndex_1.CanvasTableIndexType.GroupRows) ? this.dataIndex.index : undefined); this.dataIndex = { index: groupItems, mode: CanvasTableMode_1.CanvasTableMode.RowMode, }; } } else { if (this.groupByCol && this.groupByCol.length > 0) { const groupByCol = this.groupByCol; const groupItems = { type: CustomCanvasIndex_1.CanvasTableIndexType.GroupItems, list: [] }; let oldIndex; if (this.dataIndex && this.dataIndex.index.type === CustomCanvasIndex_1.CanvasTableIndexType.GroupItems) { oldIndex = this.dataIndex.index; } this.group(groupItems, index, 0, groupByCol, oldIndex); this.dataIndex = { mode: CanvasTableMode_1.CanvasTableMode.ColMode, index: groupItems }; } else { this.dataIndex = { index: { type: CustomCanvasIndex_1.CanvasTableIndexType.Index, list: index }, mode: CanvasTableMode_1.CanvasTableMode.ColMode, }; } } this.reCalcForScrollView(); } reCalcForScrollView() { if (this.dataIndex === undefined) { return; } let w = 1; if (this.dataIndex.mode === CanvasTableMode_1.CanvasTableMode.ColMode) { if (this.column) { let i; for (i = 0; i < this.column.length; i++) { w += this.column[i].width * this.r + 0; } } else { w = undefined; } } let h = 0; const cellHeight = this.cellHeight; const calc = (index) => { let i; switch (index.type) { case CustomCanvasIndex_1.CanvasTableIndexType.Index: h += cellHeight * index.list.length; break; case CustomCanvasIndex_1.CanvasTableIndexType.GroupItems: for (i = 0; i < index.list.length; i++) { h += cellHeight; if (index.list[i].isExpended) { calc(index.list[i].child); } } break; case CustomCanvasIndex_1.CanvasTableIndexType.GroupRows: for (i = 0; i < index.list.length; i++) { h += cellHeight; if (index.list[i].isExpended) { h += cellHeight * this.column.length; } } break; } }; calc(this.dataIndex.index); if (this.scrollView && w !== undefined) { this.scrollView.setSize(this.r, this.canvasWidth, this.canvasHeight, w, h * this.r); this.fireReCalcForScrollView(w / this.r, h + this.headerHeight); } } setCanvasSize(width, height) { this.canvasWidth = width; this.canvasHeight = height; this.reCalcForScrollView(); } doReize(width, height) { this.setCanvasSize(width * this.r, height * this.r); } drawCanvas() { if (!this.scrollView || !this.context || !this.dataIndex) { return; } if (this.needToCalc) { this.calcColum(); } this.context.font = this.config.fontStyle + " " + this.config.fontSize * this.r + "px " + this.config.font; const posX = this.scrollView.getPosX(); if (this.needToCalcFont) { this.minFontWidth = this.context.measureText("i").width; this.maxFontWidth = this.context.measureText("Æ").width; } if (this.drawconf !== undefined && this.drawconf.fulldraw) { this.drawconf = undefined; } const drawConf = this.drawconf; this.drawconf = undefined; this.requestAnimationFrame = undefined; if (this.scrollView.beforeDraw()) { this.askForReDraw(); } const headderHeight = this.headerHeight * this.r; const offsetLeft = 5 * this.r; if (drawConf === undefined) { this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight); } this.context.fillStyle = this.config.fontColor; this.context.strokeStyle = this.config.lineColor; const colStart = 0; const colEnd = this.column.length; const height = this.cellHeight * this.r; const index = this.dataIndex.index; let pos; let i; let maxPos; switch (index.type) { case CustomCanvasIndex_1.CanvasTableIndexType.Index: maxPos = this.canvasHeight + this.cellHeight + 5 * this.r; i = Math.floor(this.scrollView.getPosY() / (height)); pos = (-this.scrollView.getPosY() + (i + 1) * height); pos += 14 * this.r; while (pos < maxPos) { if (i < index.list.length) { this.drawRowItem(this.context, index.list[i], i, pos, posX, height, offsetLeft, colStart, colEnd, drawConf); } else { break; } pos += height; i++; } this.context.beginPath(); const end = pos - height + 4 * this.r; const firstLine = -this.scrollView.getPosX() + this.column[colStart].leftPos; this.context.moveTo(firstLine, headderHeight); this.context.lineTo(firstLine, end); for (let col = colStart; col < colEnd; col++) { const rightPos = -this.scrollView.getPosX() + this.column[col].rightPos; this.context.moveTo(rightPos, headderHeight); this.context.lineTo(rightPos, end); } this.context.stroke(); break; case CustomCanvasIndex_1.CanvasTableIndexType.GroupItems: pos = -this.scrollView.getPosY(); maxPos = this.canvasHeight + this.cellHeight + 5 * this.r; pos += (this.dataIndex.mode === CanvasTableMode_1.CanvasTableMode.ColMode ? 14 : -4) * this.r + height; i = 0; const w = (this.dataIndex.mode === CanvasTableMode_1.CanvasTableMode.ColMode) ? Math.min(-posX + this.column[this.column.length - 1].rightPos, this.canvasWidth) : this.canvasWidth; while (pos < maxPos && index.list.length > i) { const item = index.list[i]; pos = this.drawGroupItem(this.context, 1, item, pos, posX, w, height, maxPos, offsetLeft, colStart, colEnd, drawConf); i++; } break; case CustomCanvasIndex_1.CanvasTableIndexType.GroupRows: pos = -this.scrollView.getPosY() + height - 4 * this.r; this.drawGroupRowsItem(this.context, 1, index, pos, posX, height, offsetLeft, drawConf); break; } if (this.dataIndex.mode === CanvasTableMode_1.CanvasTableMode.ColMode) { // Headder pos = 14 * this.r; this.context.font = this.config.headerFontStyle + " " + (this.config.headerFontSize * this.r) + "px " + this.config.headerFont; this.context.fillStyle = this.config.headerFontColor; this.context.clearRect(0, 0, this.canvasWidth, headderHeight); this.context.beginPath(); this.context.strokeStyle = this.config.lineColor; const leftPos = -this.scrollView.getPosX() + this.column[colStart].leftPos; this.context.moveTo(leftPos, 0); this.context.lineTo(leftPos, headderHeight); for (let col = colStart; col < colEnd; col++) { const rightPos = -this.scrollView.getPosX() + this.column[col].rightPos; this.context.moveTo(rightPos, 0); this.context.lineTo(rightPos, headderHeight); } this.context.stroke(); this.context.textAlign = "left"; for (let col = colStart; col < colEnd; col++) { let needClip; const colItem = this.column[col]; const colWidth = this.column[col].width * this.r - offsetLeft * 2; const data = this.column[col].header; if (colWidth > data.length * this.maxFontWidth) { needClip = false; } else if (colWidth < data.length * this.minFontWidth) { needClip = true; } else { needClip = colWidth < this.context.measureText(data).width; } this.context.fillStyle = this.config.headerBackgroundColor; if (needClip) { this.context.fillRect(-posX + colItem.leftPos + 1, pos - height + 4 * this.r + 1, colItem.width * this.r - 1 * 2, height - 3); this.context.save(); this.context.beginPath(); this.context.rect(-this.scrollView.getPosX() + colItem.leftPos + offsetLeft, pos - height, colItem.width * this.r - offsetLeft * 2, height); this.context.clip(); this.context.fillStyle = this.config.headerFontColor; this.context.fillText(data, -this.scrollView.getPosX() + colItem.leftPos + offsetLeft, pos); this.context.restore(); } else { this.context.fillRect(-posX + colItem.leftPos + 1, pos - height + 4 * this.r + 1, colItem.width * this.r - 1 * 2, height - 3); this.context.fillStyle = this.config.headerFontColor; this.context.fillText(data, -this.scrollView.getPosX() + colItem.leftPos + offsetLeft, pos); } if (this.config.headerDrawSortArrow) { let sort; if (this.sortCol) { let sortIndex; for (sortIndex = 0; sortIndex < this.sortCol.length; sortIndex++) { if (this.sortCol[sortIndex].col === this.column[col].orginalCol) { sort = this