📄 tableresizepolicy.js
字号:
/*
* Isomorphic SmartClient
* Version 6.5 (2008-04-30)
* Copyright(c) 1998-2007 Isomorphic Software, Inc. All rights reserved.
* "SmartClient" is a trademark of Isomorphic Software, Inc.
*
* licensing@smartclient.com
*
* http://smartclient.com/license
*/
isc.Canvas.addClassMethods({//> @method Canvas.applyTableResizePolicy() (A)// Given a set of items to be shown in a table, this method determines the sizing / positioning// to be applied to each item.//// We factor the placing of titles next to elements into the table here to have them// automatically take up columns in the output.//// Sets up _rowHeights and _colWidths on the items array// Sets up _size property (2 element array for width,height) and _titleWidth on each item.//// @group drawing//<// Note:// The "_rowTable" property stored on the passed-in items can be reused IFF no new items are// visible that were not visible before. It is up to the calling function to clear out an old// _rowHeights if necessary.////applyTableResizePolicy : function (items, totalWidth, totalHeight, numCols, colWidths, rowHeights, overflowedAsFixed) { var logDebug = this.logIsDebugEnabled("tablePolicy"), logInfo = this.logIsInfoEnabled("tablePolicy"), logPlacement = this.logIsDebugEnabled("tablePlacement"); // determine row and column start and end coordinates for each item based on rowSpan, // colSpan, startRow and endrow properties var rowTable = items._rowTable; // If we've previously run the resizePolicy and it is still valid, don't do the // work again. if (!this._tableResizePolicyIsValid(items)) { // determine row and column start and end coordinates for each item based on rowSpan, // colSpan, startRow and endrow properties rowTable = items._rowTable = []; var currentRow = 0, currentCol = 0 ; // iterate through the items, // placing them in a rowTable according to their rowSpan and colSpan entries for (var itemNum = 0; itemNum < items.length; itemNum++) { // get a pointer to the item var item = items[itemNum]; // if the item is not visible, skip it // NOTE: an algorithm BEFORE this one might want to mark items as invisible // based on a showIf property or something like that if (!item.alwaysTakeSpace && !item.visible) continue; var itemCols = item.getColSpan(), itemRows = item.getRowSpan(); // if the item has rowSpan == 0 or colSpan == 0, skip it // this lets us ignore items that should be output (and thus are visible) // but don't factor into the table if (itemRows == 0 || itemCols == 0) continue; if (itemCols == null) itemCols = 1; if (itemRows == null) itemRows = 1; var requiredCols = itemCols; if (itemCols == "*") requiredCols = 1; // add another column for a separate cell for left/right oriented titles // NOTE: extra cells not added for top or bottom-oriented titles var orientation = item.getTitleOrientation(); if (item.showTitle && (orientation == isc.Canvas.LEFT || orientation == isc.Canvas.RIGHT)) { // NOTE: we assume colSpan * and showTitle:true means at least two columns requiredCols += 1; if (itemCols != "*") itemCols += 1; } var startRow = (item.isStartRow ? item.isStartRow() : item.startRow), endRow = (item.isEndRow ? item.isEndRow() : item.endRow); if (logPlacement) { this.logDebug("at: " + ["row" + currentRow, "col" + currentCol] + ", item: " + (item.name || item.Class) + // report colSpan "*" separately since the actual number of // columns we'll take up isn't computed til later, requiredCols // just represents the number of columns the item *must* have (itemCols == "*" ? ", colSpan:'*'" : "") + ", required cols:" + requiredCols + (itemRows > 1 ? ", rowSpan:" + itemRows : "") + (startRow ? ", startRow:true" : "") + (endRow ? ", endRow:true" : ""), "tablePlacement"); } var placeRow = null, placeCol = null; if (currentCol >= numCols || (startRow && currentCol != 0)) { currentRow++; currentCol = 0; item._startRow = true; //this.logWarn("advanced to row: " + currentRow); } else { item._startRow = false; } // if we're within the table, see if we can place the item in an existing row // NOTE: rowSpanning items in this and previous rows means there may be several // partially filled rows to look through for sufficient open space for this item. if (currentRow < rowTable.length) { //this.logWarn("looking in existing rows starting at: " + currentRow); // find the next row with available space for (; currentRow < rowTable.length; currentRow++) { var rowSlots = rowTable[currentRow]; //this.logWarn("trying row: " + currentRow); // no row created yet if (rowSlots == null) break; // look for an open slot for (; currentCol < numCols; currentCol++) { if (rowSlots[currentCol] != null) continue; // check that there are enough open slots in a row to accomodate the // colSpan of this item. This covers the case of cells reserved by // rowSpanning items in previous rows. for (var j = currentCol; j < numCols; j++) { //this.logWarn("checking at open spot in column: " + currentCol); // ran into an occupied slot before we found a spot if (rowSlots[j] != null) break; if ((j - currentCol) + 1 >= requiredCols) { // there's enough room to accomodate this item starting at // column i on this row. // Note that we don't have to check for cells reserved in rows // beneath us. Only items from rows above us could possibly // have reserved cells beneath us, and they'd have to reserve // the intervening cells. placeRow = currentRow; placeCol = currentCol; break; } } if (placeCol != null) break; } if (placeCol != null) break; // moving on to new row, go back to first column //this.logWarn("no spot in row: " + currentRow + ", advancing"); currentCol = 0; item._startRow = true; } //if (placeCol != null) this.logWarn("found spot in row: " + currentRow); } // no spots in existing rows, create a new row if (placeCol == null) { //this.logWarn("created new row: " + currentRow); placeRow = currentRow; placeCol = 0; item._startRow = true; // NOTE: an item with an invalid colSpan which is > numCols will never be // placed on an existing row, hence hits this case and ends up at column 0 of a // new row. } currentCol = placeCol; // if colSpan is variable, now that we've picked a row we can resolve it if (itemCols == "*") itemCols = numCols - currentCol; // NOTE: rowSpan of "*" not supported! // this is because we don't know how many rows there will be, so we don't // have a good way to assign the item to each row going down (?) if (!isc.isA.Number(itemRows)) itemRows = 1; // note the shape of this item in the rowTable (fill in the grid) // for each row to output for (var r = currentRow; r < currentRow + itemRows; r++) { // if there's not a column array in that row, create one if (!rowTable[r]) rowTable[r] = []; // for each column to output for (var c = currentCol; c < currentCol + itemCols; c++) { // stick the number of this item in the row rowTable[r][c] = itemNum; } } // have the item remember how many rows and columns it's actually taking up // as an array of numbers: [startCol, startRow, endCol, endRow] // NOTE: endCol and endRow are NOT inclusive item._tablePlacement = [placeCol, placeRow, placeCol + itemCols, placeRow + itemRows]; // advance currentCol by the number of columns taken up currentCol += itemCols; // if the item is configured to end its row, advance past the last column in the // row, so the next iteration of the loop will start the new row if (endRow) currentCol = numCols; if (logPlacement) { this.logDebug("item: " + (item.name || item.Class) + " placed at: " + ["row" + placeRow, "col" + placeCol] + (item._startRow ? ", marked startRow " : "") + ", rowTable: " + this.echoAll(rowTable), "tablePlacement"); } } // at this point, we know the row and column coordinate where each item will be placed var emptyRows = 0; for (var r = 0; r < rowTable.length; r++) { var row = rowTable[r]; if (row == null) break; var emptyCells = 0, lastItem = null; for (var c = 0; c < row.length; c++) { // empty cell if (row[c] == null) { emptyCells++; continue; } // cell spanned by item in previous row if (r > 0 && rowTable[r-1] != null && row[c] == rowTable[r-1][c]) continue; // occupied cell var itemNum = row[c], item = items[itemNum]; // if we're still in the same colSpanning item, continue if (item == lastItem || item == null) continue; // mark this item with the number of empty cells and rows that precede it item._emptyRows = emptyRows; item._emptyCells = emptyCells; if (logPlacement && (emptyCells > 0 || emptyRows > 0)) { this.logDebug("itemNum:" + itemNum + " (" + (item.name || item.Class) + ") at: " + ["row" + placeRow, "col" + placeCol] + " preceded by " + (emptyCells > 0 ? emptyCells + " empty cells" : "") + (emptyRows > 0 ? " " + emptyRows + " empty rows" : ""), "tablePlacement"); } // reset the counter emptyCells = emptyRows = 0; lastItem = item; } // if we didn't encounter any items on this row, we need to skip a row if (lastItem == null) { emptyRows++; emptyCells = 0; } } } // if column widths were not specified, calculate them from the rowTable if (!colWidths || !isc.isAn.Array(colWidths)) { // && !items.colWidths) { //>DEBUG if (!isc.isAn.Array(colWidths)) { this.logWarn(" 'colWidths' not an array - Ignoring.", "tableResizePolicy"); } //<DEBUG colWidths = []; } // transform any "*" or "%" items in the colWidths to things the stretchResizeList can deal // with. NOTE: don't modify the passed-in Array colWidths = colWidths.duplicate(); for (var c = 0; c < colWidths.length; c++) { // colWidths[c] = [colMinWidth, rowMaxWidth, colMaxPercent, colStarCount]; var width = colWidths[c]; if (isc.isA.String(width)) { if (width == "*") colWidths[c] = [0, 1000, 0, 1]; else if (width.contains("*")) colWidths[c] = [0, 1000, 0, parseInt(width)]; else if (width.contains("%")) colWidths[c] = [0,1000, parseInt(width), 0]; } } // remember the colWidths in the items items.colWidths = colWidths; // look through all the items in each row and gather: // [ min pixel height, // max pixel height, // largest "*" size, // largest percent size ] if (!rowHeights) {// && !items.rowHeights) { rowHeights = []; // for each row in the rowTable for (var r = 0; r < rowTable.length; r++) { var row = rowTable[r], rowMinHeight = null, rowMaxHeight = 100000, rowMaxPercent = 0, rowStarCount = 0 ; if (!row) continue; // for each column in that row for (var c = 0; c < row.length; c++) { // get the item and its preferred height var item = items[row[c]]; if (!item) continue; var itemHeight = item.getCellHeight(overflowedAsFixed); // if the item takes up more than one row, split evenly amongst its rows ??? var itemRows = (item._tablePlacement[3] - item._tablePlacement[1]); if (logDebug) this.logWarn("item at: " + [r,c] + " has height: " + itemHeight + ", item is: " + item); item._isVariableHeight = false; // if the itemHeight is a number if (isc.isA.Number(itemHeight)) { // NOTE: if the item takes up more than one row, split it evenly across its // rows itemHeight = Math.floor(itemHeight / itemRows); if (logDebug) this.logWarn("item: " + item + " has pixel size: " + itemHeight);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -