I fixed a couple of bugs in JTable and BasicTableUI, and added the variable row height feature.
2006-05-16 Roman Kennke <[EMAIL PROTECTED]> PR 26521 * javax/swing/JTable.java (rowHeights): New field. (initializeLocalVars): Call setRowHeigt instead of rowHeight=, in order to initialize rowHeights correctly. (tableChanged): Nullify rowHeights when model changes. Only create default columns from model when corresponding property is set. Sync table model with rowHeights as appropriate. (valueChanged): Call repaint with the correct rectangle. (rowAtPoint): Handle rowHeights. (getCellRect): Mostly rewritten. Check for boundaries of model and return (0,0,0,0) or (0,0,width,height) when outside. Handle component orientation. Round correctly. (getRowHeight(int)): Implemented for variable row height. (setRowHeight(int,int)): Implemented for variable row height. (setRowHeight(int)): Nullify rowHeights. (setModel): Notify tableChanged(). * javax/swing/plaf/basic/BasicTableUI.java (installDefaults): Create rendererPane in installUI. (installUI): Create and install rendererPane. (uninstallUI): Uninstall rendererPane and nullify rendererPane and table. (paint): Correctly handle rowMargin. /Roman -- “Improvement makes straight roads, but the crooked roads, without Improvement, are roads of Genius.” - William Blake
Index: javax/swing/JTable.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/JTable.java,v retrieving revision 1.104 diff -u -1 -0 -r1.104 JTable.java --- javax/swing/JTable.java 16 May 2006 13:46:45 -0000 1.104 +++ javax/swing/JTable.java 16 May 2006 19:26:30 -0000 @@ -1598,20 +1598,35 @@ /** * Indicates if the rowHeight property has been set by a client program or by * the UI. * * @see #setUIProperty(String, Object) * @see LookAndFeel#installProperty(JComponent, String, Object) */ private boolean clientRowHeightSet = false; /** + * Stores the sizes and positions of each row, when using non-uniform row + * heights. Initially the height of all rows is equal and stored in + * {link #rowHeight}. However, when an application calls + * [EMAIL PROTECTED] #setRowHeight(int,int)}, the table switches to non-uniform + * row height mode which stores the row heights in the SizeSequence + * object instead. + * + * @see #setRowHeight(int) + * @see #getRowHeight() + * @see #getRowHeight(int) + * @see #setRowHeight(int, int) + */ + private SizeSequence rowHeights; + + /** * Creates a new <code>JTable</code> instance. */ public JTable () { this(null, null, null); } /** * Creates a new <code>JTable</code> instance with the given number * of rows and columns. @@ -1737,21 +1752,21 @@ createDefaultColumnsFromModel(); this.columnModel.addColumnModelListener(this); this.defaultRenderersByColumnClass = new Hashtable(); createDefaultRenderers(); this.defaultEditorsByColumnClass = new Hashtable(); createDefaultEditors(); this.autoResizeMode = AUTO_RESIZE_SUBSEQUENT_COLUMNS; - this.rowHeight = 16; + setRowHeight(16); this.rowMargin = 1; this.rowSelectionAllowed = true; // this.accessibleContext = new AccessibleJTable(); this.cellEditor = null; // COMPAT: Both Sun and IBM have drag enabled this.dragEnabled = true; this.preferredViewportSize = new Dimension(450,400); this.showHorizontalLines = true; this.showVerticalLines = true; this.editingColumn = -1; @@ -1968,52 +1983,62 @@ /** * Invoked when the table changes. * <code>null</code> means everything changed. */ public void tableChanged (TableModelEvent event) { // update the column model from the table model if the structure has // changed and the flag autoCreateColumnsFromModel is set if ((event == null || (event.getFirstRow() == TableModelEvent.HEADER_ROW)) && autoCreateColumnsFromModel) - createDefaultColumnsFromModel(); + { + rowHeights = null; + if (getAutoCreateColumnsFromModel()) + createDefaultColumnsFromModel(); + resizeAndRepaint(); + return; + } // If the structure changes, we need to revalidate, since that might // affect the size parameters of the JTable. Otherwise we only need // to perform a repaint to update the view. if (event == null || event.getType() == TableModelEvent.INSERT) { // Sync selection model with data model. if (event != null) { int first = event.getFirstRow(); if (first < 0) first = 0; int last = event.getLastRow(); if (last < 0) last = getRowCount() - 1; selectionModel.insertIndexInterval(first, last - first + 1, true); + if (rowHeights != null) + rowHeights.insertEntries(first, last - first + 1, rowHeight); } revalidate(); } if (event == null || event.getType() == TableModelEvent.DELETE) { // Sync selection model with data model. if (event != null) { int first = event.getFirstRow(); if (first < 0) first = 0; int last = event.getLastRow(); if (last < 0) last = getRowCount() - 1; selectionModel.removeIndexInterval(first, last); + if (rowHeights != null) + rowHeights.removeEntries(first, last - first + 1); } if (dataModel.getRowCount() == 0) clearSelection(); revalidate(); } repaint(); } /** * Invoked when another table row is selected. It is not recommended @@ -2021,21 +2046,21 @@ */ public void valueChanged (ListSelectionEvent event) { // Repaint the changed region. int first = Math.max(0, Math.min(getRowCount() - 1, event.getFirstIndex())); int last = Math.max(0, Math.min(getRowCount() - 1, event.getLastIndex())); Rectangle rect1 = getCellRect(first, 0, false); Rectangle rect2 = getCellRect(last, getColumnCount() - 1, false); SwingUtilities.computeUnion(rect2.x, rect2.y, rect2.width, rect2.height, rect1); - repaint(rect2); + repaint(rect1); } /** * Returns index of the column that contains specified point * or -1 if this table doesn't contain this point. * * @param point point to identify the column * @return index of the column that contains specified point or * -1 if this table doesn't contain this point. */ @@ -2063,24 +2088,30 @@ * * @param point point to identify the row * @return index of the row that contains specified point or -1 if this table * doesn't contain this point. */ public int rowAtPoint(Point point) { if (point != null) { int nrows = getRowCount(); - int height = getRowHeight() + getRowMargin(); + int r; int y = point.y; + if (rowHeights == null) + { + int height = getRowHeight(); + r = y / height; + } + else + r = rowHeights.getIndex(y); - int r = y / height; if (r < 0 || r >= nrows) return -1; else return r; } else return -1; } /** @@ -2096,41 +2127,84 @@ * @param includeSpacing whether or not to include the cell margins in the * resulting cell. If <code>false</code>, the result will only contain the * inner area of the target cell, not including its margins. * * @return a rectangle enclosing the specified cell */ public Rectangle getCellRect(int row, int column, boolean includeSpacing) { - int height = getRowHeight(row); - int width = columnModel.getColumn(column).getWidth(); - int x_gap = columnModel.getColumnMargin(); - int y_gap = rowMargin; - - column = Math.max(0, Math.min(column, getColumnCount() - 1)); - row = Math.max(0, Math.min(row, getRowCount() - 1)); + Rectangle cellRect = new Rectangle(0, 0, 0, 0); - int x = 0; - int y = (height + y_gap) * row; + // Check for valid range vertically. + if (row >= getRowCount()) + { + cellRect.height = getHeight(); + } + else if (row >= 0) + { + cellRect.height = getRowHeight(row); + if (rowHeights == null) + cellRect.y = row * cellRect.height; + else + cellRect.y = rowHeights.getPosition(row); - for (int i = 0; i < column; ++i) - x += columnModel.getColumn(i).getWidth(); - - Rectangle rect = new Rectangle(); + if (! includeSpacing) + { + // The rounding here is important. + int rMargin = getRowMargin(); + cellRect.y += rMargin / 2; + cellRect.height -= rMargin; + } + } + // else row < 0, y = height = 0 - if (includeSpacing) - rect.setBounds(x, y, width, height +y_gap); + // Check for valid range horizontally. + if (column < 0) + { + if (! getComponentOrientation().isLeftToRight()) + { + cellRect.x = getWidth(); + } + } + else if (column >= getColumnCount()) + { + if (getComponentOrientation().isLeftToRight()) + { + cellRect.x = getWidth(); + } + } else - rect.setBounds(x, y, width - x_gap, height); - return rect; + { + TableColumnModel tcm = getColumnModel(); + if (getComponentOrientation().isLeftToRight()) + { + for (int i = 0; i < column; i++) + cellRect.x += tcm.getColumn(i).getWidth(); + } + else + { + for (int i = tcm.getColumnCount() - 1; i > column; i--) + cellRect.x += tcm.getColumn(i).getWidth(); + } + cellRect.width = tcm.getColumn(column).getWidth(); + if (! includeSpacing) + { + // The rounding here is important. + int cMargin = tcm.getColumnMargin(); + cellRect.x += cMargin / 2; + cellRect.width -= cMargin; + } + } + + return cellRect; } public void clearSelection() { selectionModel.clearSelection(); getColumnModel().getSelectionModel().clearSelection(); } /** * Get the value of the selectedRow property by delegation to @@ -2427,23 +2501,24 @@ return rowHeight; } /** * Get the height of the specified row. * * @param row the row whose height to return */ public int getRowHeight(int row) { - // FIXME: return the height of the specified row - // which may be different from the general rowHeight - return rowHeight; + int rh = rowHeight; + if (rowHeights != null) + rh = rowHeights.getSize(row); + return rh; } /** * Get the value of the [EMAIL PROTECTED] #rowMargin} property. * * @return The current value of the property */ public int getRowMargin() { @@ -2789,47 +2864,55 @@ * @param a The new value of the autoResizeMode property */ public void setAutoResizeMode(int a) { autoResizeMode = a; revalidate(); repaint(); } /** - * Set the value of the [EMAIL PROTECTED] #rowHeight} property. + * Sets the height for all rows in the table. If you want to change the + * height of a single row instead, use [EMAIL PROTECTED] #setRowHeight(int, int)}. * - * @param r The new value of the rowHeight property + * @param r the height to set for all rows + * + * @see #getRowHeight() + * @see #setRowHeight(int, int) + * @see #getRowHeight(int) */ public void setRowHeight(int r) { if (r < 1) throw new IllegalArgumentException(); clientRowHeightSet = true; rowHeight = r; + rowHeights = null; revalidate(); repaint(); } /** - * Sets the value of the rowHeight property for the specified - * row. + * Sets the height of a single row in the table. * - * @param rh is the new rowHeight - * @param row is the row to change the rowHeight of + * @param rh the new row height + * @param row the row to change the height of */ public void setRowHeight(int row, int rh) { - setRowHeight(rh); - // FIXME: not implemented + if (rowHeights == null) + { + rowHeights = new SizeSequence(getRowCount(), rowHeight); + } + rowHeights.setSize(row, rh); } /** * Set the value of the [EMAIL PROTECTED] #rowMargin} property. * * @param r The new value of the rowMargin property */ public void setRowMargin(int r) { rowMargin = r; @@ -2887,20 +2970,24 @@ dataModel.removeTableModelListener(this); if (m != null) { // Set property. dataModel = m; // Add table as TableModelListener to new model. dataModel.addTableModelListener(this); + // Notify the tableChanged method. + tableChanged(new TableModelEvent(dataModel, + TableModelEvent.HEADER_ROW)); + // Automatically create columns. if (autoCreateColumnsFromModel) createDefaultColumnsFromModel(); } // This property is bound, so we fire a property change event. firePropertyChange("model", oldModel, dataModel); // Repaint table. revalidate(); @@ -3875,11 +3962,12 @@ { setRowHeight(((Integer) value).intValue()); clientRowHeightSet = false; } } else { super.setUIProperty(propertyName, value); } } + } Index: javax/swing/plaf/basic/BasicTableUI.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicTableUI.java,v retrieving revision 1.50 diff -u -1 -0 -r1.50 BasicTableUI.java --- javax/swing/plaf/basic/BasicTableUI.java 4 May 2006 12:11:50 -0000 1.50 +++ javax/swing/plaf/basic/BasicTableUI.java 16 May 2006 19:26:30 -0000 @@ -421,21 +421,20 @@ } protected void installDefaults() { LookAndFeel.installColorsAndFont(table, "Table.background", "Table.foreground", "Table.font"); table.setGridColor(UIManager.getColor("Table.gridColor")); table.setSelectionForeground(UIManager.getColor("Table.selectionForeground")); table.setSelectionBackground(UIManager.getColor("Table.selectionBackground")); table.setOpaque(true); - rendererPane = new CellRendererPane(); } protected void installKeyboardActions() { InputMap ancestorMap = (InputMap) UIManager.get("Table.ancestorInputMap"); InputMapUIResource parentInputMap = new InputMapUIResource(); // FIXME: The JDK uses a LazyActionMap for parentActionMap ActionMap parentActionMap = new ActionMapUIResource(); action = new TableAction(); Object keys[] = ancestorMap.allKeys(); @@ -1181,30 +1180,37 @@ table.removeKeyListener(keyListener); table.removeMouseListener(mouseInputListener); table.removeMouseMotionListener(mouseInputListener); table.removePropertyChangeListener(propertyChangeListener); propertyChangeListener = null; } public void installUI(JComponent comp) { table = (JTable)comp; + rendererPane = new CellRendererPane(); + table.add(rendererPane); + installDefaults(); installKeyboardActions(); installListeners(); } public void uninstallUI(JComponent c) { uninstallListeners(); uninstallKeyboardActions(); - uninstallDefaults(); + uninstallDefaults(); + + table.remove(rendererPane); + rendererPane = null; + table = null; } /** * Paints a single cell in the table. * * @param g The graphics context to paint in * @param row The row number to paint * @param col The column number to paint * @param bounds The bounds of the cell to paint, assuming a coordinate * system beginning at <code>(0,0)</code> in the upper left corner of the @@ -1250,44 +1256,43 @@ int rowMargin = table.getRowMargin(); TableColumnModel cmodel = table.getColumnModel(); int [] widths = new int[cn+1]; for (int i = c0; i <=cn ; i++) { widths[i] = cmodel.getColumn(i).getWidth() - columnMargin; } Rectangle bounds = table.getCellRect(r0, c0, false); - // The left boundary of the area being repainted. int left = bounds.x; // The top boundary of the area being repainted. int top = bounds.y; // The bottom boundary of the area being repainted. int bottom; // paint the cell contents Color grid = table.getGridColor(); for (int r = r0; r <= rn; ++r) { for (int c = c0; c <= cn; ++c) { bounds.width = widths[c]; paintCell(gfx, r, c, bounds, table.getCellRenderer(r, c)); bounds.x += widths[c] + columnMargin; } bounds.x = left; - bounds.y += table.getRowHeight(r) + rowMargin; + bounds.y += table.getRowHeight(r); // Update row height for tables with custom heights. - bounds.height = table.getRowHeight(r + 1); + bounds.height = table.getRowHeight(r + 1) - rowMargin; } bottom = bounds.y - rowMargin; // paint vertical grid lines if (grid != null && table.getShowVerticalLines()) { Color save = gfx.getColor(); gfx.setColor(grid); int x = left - columnMargin; @@ -1304,17 +1309,17 @@ // paint horizontal grid lines if (grid != null && table.getShowHorizontalLines()) { Color save = gfx.getColor(); gfx.setColor(grid); int y = top - rowMargin; for (int r = r0; r <= rn; ++r) { // The horizontal grid is draw below the cells, so we // add before drawing. - y += table.getRowHeight(r) + rowMargin; + y += table.getRowHeight(r);// + rowMargin; gfx.drawLine(left, y, p2.x, y); } gfx.setColor(save); } } }
signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil