📄 tableview.java
字号:
/* * @(#)TableView.java 1.41 06/05/12 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package javax.swing.text.html;import java.awt.*;import java.util.BitSet;import java.util.Vector;import java.util.Arrays;import javax.swing.SizeRequirements;import javax.swing.event.DocumentEvent;import javax.swing.text.*;/** * HTML table view. * * @author Timothy Prinzing * @version 1.41 05/12/06 * @see View *//*public*/ class TableView extends BoxView implements ViewFactory { /** * Constructs a TableView for the given element. * * @param elem the element that this view is responsible for */ public TableView(Element elem) { super(elem, View.Y_AXIS); rows = new Vector(); gridValid = false; captionIndex = -1; totalColumnRequirements = new SizeRequirements(); } /** * Creates a new table row. * * @param elem an element * @return the row */ protected RowView createTableRow(Element elem) { // PENDING(prinz) need to add support for some of the other // elements, but for now just ignore anything that is not // a TR. Object o = elem.getAttributes().getAttribute(StyleConstants.NameAttribute); if (o == HTML.Tag.TR) { return new RowView(elem); } return null; } /** * The number of columns in the table. */ public int getColumnCount() { return columnSpans.length; } /** * Fetches the span (width) of the given column. * This is used by the nested cells to query the * sizes of grid locations outside of themselves. */ public int getColumnSpan(int col) { if (col < columnSpans.length) { return columnSpans[col]; } return 0; } /** * The number of rows in the table. */ public int getRowCount() { return rows.size(); } /** * Fetch the span of multiple rows. This includes * the border area. */ public int getMultiRowSpan(int row0, int row1) { RowView rv0 = getRow(row0); RowView rv1 = getRow(row1); if ((rv0 != null) && (rv1 != null)) { int index0 = rv0.viewIndex; int index1 = rv1.viewIndex; int span = getOffset(Y_AXIS, index1) - getOffset(Y_AXIS, index0) + getSpan(Y_AXIS, index1); return span; } return 0; } /** * Fetches the span (height) of the given row. */ public int getRowSpan(int row) { RowView rv = getRow(row); if (rv != null) { return getSpan(Y_AXIS, rv.viewIndex); } return 0; } RowView getRow(int row) { if (row < rows.size()) { return (RowView) rows.elementAt(row); } return null; } protected View getViewAtPoint(int x, int y, Rectangle alloc) { int n = getViewCount(); View v = null; Rectangle allocation = new Rectangle(); for (int i = 0; i < n; i++) { allocation.setBounds(alloc); childAllocation(i, allocation); v = getView(i); if (v instanceof RowView) { v = ((RowView)v).findViewAtPoint(x, y, allocation); if (v != null) { alloc.setBounds(allocation); return v; } } } return super.getViewAtPoint(x, y, alloc); } /** * Determines the number of columns occupied by * the table cell represented by given element. */ protected int getColumnsOccupied(View v) { AttributeSet a = v.getElement().getAttributes(); if (a.isDefined(HTML.Attribute.COLSPAN)) { String s = (String) a.getAttribute(HTML.Attribute.COLSPAN); if (s != null) { try { return Integer.parseInt(s); } catch (NumberFormatException nfe) { // fall through to one column } } } return 1; } /** * Determines the number of rows occupied by * the table cell represented by given element. */ protected int getRowsOccupied(View v) { AttributeSet a = v.getElement().getAttributes(); if (a.isDefined(HTML.Attribute.ROWSPAN)) { String s = (String) a.getAttribute(HTML.Attribute.ROWSPAN); if (s != null) { try { return Integer.parseInt(s); } catch (NumberFormatException nfe) { // fall through to one row } } } return 1; } protected void invalidateGrid() { gridValid = false; } protected StyleSheet getStyleSheet() { HTMLDocument doc = (HTMLDocument) getDocument(); return doc.getStyleSheet(); } /** * Update the insets, which contain the caption if there * is a caption. */ void updateInsets() { short top = (short) painter.getInset(TOP, this); short bottom = (short) painter.getInset(BOTTOM, this); if (captionIndex != -1) { View caption = getView(captionIndex); short h = (short) caption.getPreferredSpan(Y_AXIS); AttributeSet a = caption.getAttributes(); Object align = a.getAttribute(CSS.Attribute.CAPTION_SIDE); if ((align != null) && (align.equals("bottom"))) { bottom += h; } else { top += h; } } setInsets(top, (short) painter.getInset(LEFT, this), bottom, (short) painter.getInset(RIGHT, this)); } /** * Update any cached values that come from attributes. */ protected void setPropertiesFromAttributes() { StyleSheet sheet = getStyleSheet(); attr = sheet.getViewAttributes(this); painter = sheet.getBoxPainter(attr); if (attr != null) { setInsets((short) painter.getInset(TOP, this), (short) painter.getInset(LEFT, this), (short) painter.getInset(BOTTOM, this), (short) painter.getInset(RIGHT, this)); CSS.LengthValue lv = (CSS.LengthValue) attr.getAttribute(CSS.Attribute.BORDER_SPACING); if (lv != null) { cellSpacing = (int) lv.getValue(); } else { cellSpacing = 0; } lv = (CSS.LengthValue) attr.getAttribute(CSS.Attribute.BORDER_TOP_WIDTH); if (lv != null) { borderWidth = (int) lv.getValue(); } else { borderWidth = 0; } } } /** * Fill in the grid locations that are placeholders * for multi-column, multi-row, and missing grid * locations. */ void updateGrid() { if (! gridValid) { relativeCells = false; multiRowCells = false; // determine which views are table rows and clear out // grid points marked filled. captionIndex = -1; rows.removeAllElements(); int n = getViewCount(); for (int i = 0; i < n; i++) { View v = getView(i); if (v instanceof RowView) { rows.addElement(v); RowView rv = (RowView) v; rv.clearFilledColumns(); rv.rowIndex = rows.size() - 1; rv.viewIndex = i; } else { Object o = v.getElement().getAttributes().getAttribute(StyleConstants.NameAttribute); if (o instanceof HTML.Tag) { HTML.Tag kind = (HTML.Tag) o; if (kind == HTML.Tag.CAPTION) { captionIndex = i; } } } } int maxColumns = 0; int nrows = rows.size(); for (int row = 0; row < nrows; row++) { RowView rv = getRow(row); int col = 0; for (int cell = 0; cell < rv.getViewCount(); cell++, col++) { View cv = rv.getView(cell); if (! relativeCells) { AttributeSet a = cv.getAttributes(); CSS.LengthValue lv = (CSS.LengthValue) a.getAttribute(CSS.Attribute.WIDTH); if ((lv != null) && (lv.isPercentage())) { relativeCells = true; } } // advance to a free column for (; rv.isFilled(col); col++); int rowSpan = getRowsOccupied(cv); if (rowSpan > 1) { multiRowCells = true; } int colSpan = getColumnsOccupied(cv); if ((colSpan > 1) || (rowSpan > 1)) { // fill in the overflow entries for this cell int rowLimit = row + rowSpan; int colLimit = col + colSpan; for (int i = row; i < rowLimit; i++) { for (int j = col; j < colLimit; j++) { if (i != row || j != col) { addFill(i, j); } } } if (colSpan > 1) { col += colSpan - 1; } } } maxColumns = Math.max(maxColumns, col); } // setup the column layout/requirements columnSpans = new int[maxColumns]; columnOffsets = new int[maxColumns]; columnRequirements = new SizeRequirements[maxColumns]; for (int i = 0; i < maxColumns; i++) { columnRequirements[i] = new SizeRequirements(); columnRequirements[i].maximum = Integer.MAX_VALUE; } gridValid = true; } } /** * Mark a grid location as filled in for a cells overflow. */ void addFill(int row, int col) { RowView rv = getRow(row); if (rv != null) { rv.fillColumn(col); } } /** * Layout the columns to fit within the given target span. * * @param targetSpan the given span for total of all the table * columns * @param reqs the requirements desired for each column. This * is the column maximum of the cells minimum, preferred, and * maximum requested span * @param spans the return value of how much to allocated to * each column * @param offsets the return value of the offset from the * origin for each column * @return the offset from the origin and the span for each column * in the offsets and spans parameters */ protected void layoutColumns(int targetSpan, int[] offsets, int[] spans, SizeRequirements[] reqs) { //clean offsets and spans Arrays.fill(offsets, 0); Arrays.fill(spans, 0); colIterator.setLayoutArrays(offsets, spans, targetSpan); CSS.calculateTiledLayout(colIterator, targetSpan); } /** * Calculate the requirements for each column. The calculation * is done as two passes over the table. The table cells that * occupy a single column are scanned first to determine the * maximum of minimum, preferred, and maximum spans along the * give axis. Table cells that span multiple columns are excluded * from the first pass. A second pass is made to determine if * the cells that span multiple columns are satisfied. If the * column requirements are not satisified, the needs of the * multi-column cell is mixed into the existing column requirements. * The calculation of the multi-column distribution is based upon * the proportions of the existing column requirements and taking * into consideration any constraining maximums. */ void calculateColumnRequirements(int axis) { // clean columnRequirements for (SizeRequirements req : columnRequirements) { req.minimum = 0; req.preferred = 0; req.maximum = Integer.MAX_VALUE; } Container host = getContainer(); if (host != null) { if (host instanceof JTextComponent) { skipComments = !((JTextComponent)host).isEditable(); } else { skipComments = true; } } // pass 1 - single column cells boolean hasMultiColumn = false; int nrows = getRowCount(); for (int i = 0; i < nrows; i++) { RowView row = getRow(i); int col = 0; int ncells = row.getViewCount(); for (int cell = 0; cell < ncells; cell++) { View cv = row.getView(cell); if (skipComments && !(cv instanceof CellView)) { continue; } for (; row.isFilled(col); col++); // advance to a free column int rowSpan = getRowsOccupied(cv); int colSpan = getColumnsOccupied(cv); if (colSpan == 1) { checkSingleColumnCell(axis, col, cv); } else { hasMultiColumn = true; col += colSpan - 1; } col++; } } // pass 2 - multi-column cells if (hasMultiColumn) { for (int i = 0; i < nrows; i++) { RowView row = getRow(i); int col = 0; int ncells = row.getViewCount(); for (int cell = 0; cell < ncells; cell++) { View cv = row.getView(cell); if (skipComments && !(cv instanceof CellView)) { continue; } for (; row.isFilled(col); col++); // advance to a free column int colSpan = getColumnsOccupied(cv); if (colSpan > 1) { checkMultiColumnCell(axis, col, colSpan, cv); col += colSpan - 1; } col++; } } } } /** * check the requirements of a table cell that spans a single column. */ void checkSingleColumnCell(int axis, int col, View v) { SizeRequirements req = columnRequirements[col]; req.minimum = Math.max((int) v.getMinimumSpan(axis), req.minimum); req.preferred = Math.max((int) v.getPreferredSpan(axis), req.preferred); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -