(0);
- colWidthCache.ensureCapacity(nvRows);
- for (int i = 0; i < nvRows; i++) {
- colWidthCache.add(-1);
- }
- widthCache.put(column, colWidthCache);
- }
- }
-
- int width = 0;
-
- for (int vRow = 0; vRow < nvRows; vRow++) {
- int mRow = convertRowIndexToModel(vRow);
- int cellWidth = 0;
- try {
- cellWidth = colWidthCache == null ?
- -1 : colWidthCache.get(mRow);
- } catch (IndexOutOfBoundsException ignore) {
- // This method has probably been called (perhaps by the
- // RowSorter) before insertWidthCache could react to a
- // tableChange in the TableModel. That same change will
- // ultimately make its way to our own modelListener, and
- // this method will be called again (after
- // insertWidthCache has been run) so we can abort now.
- return;
- }
-
- if (cellWidth == -1) {
- Object value = getValueAt(vRow, vCol);
-
- Component comp = renderer.getTableCellRendererComponent(
- this, value, true, true, vRow, vCol);
-
- cellWidth = comp.getPreferredSize().width;
-
- if (colWidthCache != null) {
- colWidthCache.set(mRow, cellWidth);
- }
- }
-
- width = Math.max(width, cellWidth);
- }
-
- // Account for header
- renderer = column.getHeaderRenderer();
- if (renderer == null) {
- JTableHeader header = getTableHeader();
- if (header != null) {
- renderer = header.getDefaultRenderer();
- }
- }
-
- if (renderer != null) {
- Object value = column.getHeaderValue();
-
- Component comp = renderer.getTableCellRendererComponent(
- this, value, true, true, -1, vCol);
-
- int cellWidth = comp.getPreferredSize().width;
- width = Math.max(width, cellWidth);
- }
-
- width += cMargin;
-
- maxColWidth = Math.max(maxColWidth, width);
- setPreferredWidth(column, width);
- }
-
- if (colWidthPolicy == ColumnWidthPolicy.EQUAL) {
- for (int vCol = 0; vCol < n; vCol++) {
- int mCol = convertColumnIndexToModel(vCol);
- TableColumn column = cModel.getColumn(vCol);
- setPreferredWidth(column, maxColWidth);
- }
- }
- }
- }
-
- /**
- * Indicates whether {@link #fitColumns} is called automatically whenever
- * the table is changed in a significant way.
- *
- * @return how to automatically fit columns, or {@code null} to not
- * automatically call {@link #fitColumns}
- */
- public ColumnWidthPolicy getAutoFitColumns() {
- return colWidthPolicy;
- }
-
- /**
- * Gets the number of rows in the cache of cell values. A higher value may
- * speed up rendering of the table if the table model must do expensive
- * calculations to determine the value in each cell.
- *
- * The default value is 0, effectively disabling the cache.
- */
- public int getCacheSize() {
- return valueCacheSize;
- }
-
- public Color getStripeColor() {
- return stripeColor;
- }
-
- /**
- * Gets the number of rows used to calculate the preferred size of an
- * enclosing viewport.
- *
- * @return the number of rows to show in an enclosing viewport, or -1
- * to rely on the default calculation for preferred viewport
- * size
- */
- public int getVisibleRowCount() {
- return visibleRowCount;
- }
-
- /**
- * Indicates whether this table has a non-{@code null} {@link
- * #getStripeColor stripe color}.
- */
- public boolean isStriped() {
- return getStripeColor() != null;
- }
-
- /**
- * Sets whether {@link #fitColumns} is called automatically whenever the
- * table is changed in a significant way.
- *
- * @param colWidthPolicy
- * how to automatically fit columns, or {@code null} to not
- * automatically call {@link #fitColumns}
- */
- public void setAutoFitColumns(ColumnWidthPolicy colWidthPolicy) {
- if (this.colWidthPolicy != colWidthPolicy) {
- this.colWidthPolicy = colWidthPolicy;
- fitColumnsIfRequested();
- }
- }
-
- /**
- * Sets the number of rows in the cache of cell values. See {@link
- * #getCacheSize}.
- */
- public void setCacheSize(int valueCacheSize) {
- if (this.valueCacheSize != valueCacheSize) {
- if (this.valueCacheSize > valueCacheSize) {
- try {
- // Trim if necessary
- ListIterator> rowIter =
- valueCache.listIterator(valueCacheSize);
-
- while (rowIter.hasNext()) {
- rowIter.next();
- rowIter.remove();
- }
- } catch (IndexOutOfBoundsException ignore) {
- }
- }
-
- this.valueCacheSize = valueCacheSize;
- }
- }
-
- public void setStripeColor(Color stripeColor) {
- if (this.stripeColor != stripeColor) {
- this.stripeColor = stripeColor;
- repaint();
- }
- }
-
- /**
- * Sets the number of rows used to calculate the preferred size of an
- * enclosing viewport.
- *
- * @param visibleRowCount
- * the number of rows to show in an enclosing viewport, or -1
- * to rely on the default calculation for preferred viewport
- * size
- */
- public void setVisibleRowCount(int visibleRowCount) {
- this.visibleRowCount = visibleRowCount;
- }
-
- //
- // Private methods
- //
-
- private void init() {
- setTableHeader(new ExtTableHeader(getColumnModel()));
- setFillsViewportHeight(true);
-
- addMouseListener(
- new MouseAdapter() {
- @Override
- public void mousePressed(MouseEvent e) {
- int vRow = rowAtPoint(e.getPoint());
- if (vRow == -1) {
- clearSelection();
- }
- }
- });
-
- setShowHorizontalLines(false);
- setShowVerticalLines(true);
-
- // Accommodate a 16-pixel icon + a 1-pixel focus border
- setRowHeight(18);
- }
-
- private void clearWidthCache() {
- if (widthCache != null) {
- synchronized (widthCache) {
- widthCache.clear();
- }
- }
- }
-
- private void deleteUnusedColumnsFromWidthCache() {
- TableColumnModel cModel = getColumnModel();
- synchronized (widthCache) {
- CACHED: for (Iterator i =
- widthCache.keySet().iterator(); i.hasNext();) {
-
- TableColumn column = i.next();
- for (int j = 0, n = cModel.getColumnCount(); j < n; j++) {
- if (cModel.getColumn(j) == column) {
- continue CACHED;
- }
- }
- i.remove();
- }
- }
- }
-
- private void deleteWidthCache(int fmRow, int lmRow) {
- synchronized (widthCache) {
- for (TableColumn column : widthCache.keySet()) {
- ArrayList colWidthCache = widthCache.get(column);
- for (int mRow = lmRow; mRow >= fmRow; mRow--) {
- colWidthCache.remove(mRow);
- }
- }
- }
- }
-
- private void fitColumnsIfRequested() {
- if (colWidthPolicy != null) {
- fitColumns(colWidthPolicy, true);
- }
- }
-
- private void insertWidthCache(int fmRow, int lmRow) {
- synchronized (widthCache) {
- for (TableColumn column : widthCache.keySet()) {
- ArrayList colWidthCache = widthCache.get(column);
- for (int mRow = fmRow; mRow <= lmRow; mRow++) {
- colWidthCache.add(mRow, -1);
- }
- }
- }
- }
-
- private void resetWidthCache(int fmRow, int lmRow, int fmCol, int lmCol) {
- synchronized (widthCache) {
- TableColumnModel cModel = getColumnModel();
-
- for (int mCol = fmCol; mCol <= lmCol; mCol++) {
- int vCol = convertColumnIndexToView(mCol);
- TableColumn column = cModel.getColumn(vCol);
-
- ArrayList colWidthCache = widthCache.get(column);
- if (colWidthCache != null) {
- for (int mRow = fmRow; mRow <= lmRow; mRow++) {
- try {
- colWidthCache.set(mRow, -1);
- } catch (IndexOutOfBoundsException ignore) {
- }
- }
- }
- }
- }
- }
-
- private void setPreferredWidth(TableColumn column, int width) {
- column.setPreferredWidth(width);
- column.setMinWidth(Math.min(column.getMinWidth(), width));
- }
-
- private void updateWidthCache(TableModelEvent e) {
- synchronized (widthCache) {
- int fmRow = e.getFirstRow();
- int lmRow = e.getLastRow();
-
- int nRows = getModel().getRowCount();
- if (lmRow >= nRows) {
- lmRow = nRows - 1;
- }
-
- switch (e.getType()) {
- case TableModelEvent.UPDATE:
- int fmCol = e.getColumn();
- int lmCol = fmCol;
-
- if (fmCol == TableModelEvent.ALL_COLUMNS) {
- fmCol = 0;
- lmCol = getColumnModel().getColumnCount() - 1;
- }
-
- resetWidthCache(fmRow, lmRow, fmCol, lmCol);
- break;
-
-
- case TableModelEvent.DELETE:
- deleteWidthCache(fmRow, lmRow);
- break;
-
- case TableModelEvent.INSERT:
- insertWidthCache(fmRow, lmRow);
- break;
- }
-
- fitColumnsIfRequested();
- }
- }
-
- //
- // Static methods
- //
-
- // XXX Unit test -- remove
- public static void main(String[] args) {
- JFrame f = new JFrame();
-
- JPanel c = (JPanel)f.getContentPane();
- c.setLayout(new BorderLayout());
- c.setBorder(GUIUtil.getEmptyBorder());
-
- Object[][] data = {
- new Object[] {"0 zero", "0 zero", "blah"},
- new Object[] {"1 one", "1 one", "blah"},
- new Object[] {"2 two", "2 two", "blah"},
- new Object[] {"3 three", "3 three", "blah"},
- new Object[] {"4 four", "4 four", "blah"},
- new Object[] {"5 five", "5 five", "blah"},
- };
-
- final DefaultTableModel model = new DefaultTableModel(
- data, new String[] {"Column 0", "Column 1", "Column 2"});
-
- final ExtTable t = new ExtTable(model);
- t.setAutoFitColumns(ColumnWidthPolicy.PREFERRED);
-// t.setOpaque(false);
-// t.setBackground(Color.green);
-// t.setStripeColor(null);
-// t.setShowGrid(true);
-
- t.addMouseListener(
- new MouseAdapter() {
- @Override
- public void mouseClicked(MouseEvent e) {
- if (e.getButton() == 3) {
- Point p = e.getPoint();
- int vCol = t.columnAtPoint(p);
- int mCol = t.convertColumnIndexToModel(vCol);
-
- Object[] row = {"new", "new", "new"};
- row[mCol] = "loooooooooooooooooooooooooong";
- model.addRow(row);
- } else
-
- if (e.getButton() == 2) {
- Point p = e.getPoint();
- int vRow = t.rowAtPoint(p);
- int mRow = t.convertRowIndexToModel(vRow);
- model.removeRow(mRow);
- }
- }
- });
-
- JScrollPane scroll = new ExtScrollPane(t);
- c.add(scroll, BorderLayout.CENTER);
-
- JButton b = new JButton("Remove column");
- b.addActionListener(
- new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- TableColumn column = t.getColumnModel().getColumn(1);
- System.out.printf("Removing column: %s\n",
- column.getIdentifier());
- t.removeColumn(column);
- }
- });
- c.add(b, BorderLayout.SOUTH);
-
- f.pack();
- f.setVisible(true);
- }
-}