/*
 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.swing.plaf.basic;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.table.*;

import sun.swing.*;

BasicTableHeaderUI implementation
Author:Alan Chung, Philip Milne
/** * BasicTableHeaderUI implementation * * @author Alan Chung * @author Philip Milne */
public class BasicTableHeaderUI extends TableHeaderUI { private static Cursor resizeCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR); // // Instance Variables //
The JTableHeader that is delegating the painting to this UI.
/** The JTableHeader that is delegating the painting to this UI. */
protected JTableHeader header; protected CellRendererPane rendererPane; // Listeners that are attached to the JTable protected MouseInputListener mouseInputListener; // The column header over which the mouse currently is. private int rolloverColumn = -1; // The column that should be highlighted when the table header has the focus. private int selectedColumnIndex = 0; // Read ONLY via getSelectedColumnIndex! private static FocusListener focusListener = new FocusListener() { public void focusGained(FocusEvent e) { repaintHeader(e.getSource()); } public void focusLost(FocusEvent e) { repaintHeader(e.getSource()); } private void repaintHeader(Object source) { if (source instanceof JTableHeader) { JTableHeader th = (JTableHeader)source; BasicTableHeaderUI ui = (BasicTableHeaderUI)BasicLookAndFeel. getUIOfType(th.getUI(), BasicTableHeaderUI.class); if (ui == null) { return; } th.repaint(th.getHeaderRect(ui.getSelectedColumnIndex())); } } };
This class should be treated as a "protected" inner class. Instantiate it only within subclasses of BasicTableHeaderUI.
/** * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of {@code BasicTableHeaderUI}. */
public class MouseInputHandler implements MouseInputListener { private int mouseXOffset; private Cursor otherCursor = resizeCursor; public void mouseClicked(MouseEvent e) { if (!header.isEnabled()) { return; } if (e.getClickCount() % 2 == 1 && SwingUtilities.isLeftMouseButton(e)) { JTable table = header.getTable(); RowSorter sorter; if (table != null && (sorter = table.getRowSorter()) != null) { int columnIndex = header.columnAtPoint(e.getPoint()); if (columnIndex != -1) { columnIndex = table.convertColumnIndexToModel( columnIndex); sorter.toggleSortOrder(columnIndex); } } } } private TableColumn getResizingColumn(Point p) { return getResizingColumn(p, header.columnAtPoint(p)); } private TableColumn getResizingColumn(Point p, int column) { if (column == -1) { return null; } Rectangle r = header.getHeaderRect(column); r.grow(-3, 0); if (r.contains(p)) { return null; } int midPoint = r.x + r.width/2; int columnIndex; if( header.getComponentOrientation().isLeftToRight() ) { columnIndex = (p.x < midPoint) ? column - 1 : column; } else { columnIndex = (p.x < midPoint) ? column : column - 1; } if (columnIndex == -1) { return null; } return header.getColumnModel().getColumn(columnIndex); } public void mousePressed(MouseEvent e) { if (!header.isEnabled()) { return; } header.setDraggedColumn(null); header.setResizingColumn(null); header.setDraggedDistance(0); Point p = e.getPoint(); // First find which header cell was hit TableColumnModel columnModel = header.getColumnModel(); int index = header.columnAtPoint(p); if (index != -1) { // The last 3 pixels + 3 pixels of next column are for resizing TableColumn resizingColumn = getResizingColumn(p, index); if (canResize(resizingColumn, header)) { header.setResizingColumn(resizingColumn); if( header.getComponentOrientation().isLeftToRight() ) { mouseXOffset = p.x - resizingColumn.getWidth(); } else { mouseXOffset = p.x + resizingColumn.getWidth(); } } else if (header.getReorderingAllowed()) { TableColumn hitColumn = columnModel.getColumn(index); header.setDraggedColumn(hitColumn); mouseXOffset = p.x; } } if (header.getReorderingAllowed()) { int oldRolloverColumn = rolloverColumn; rolloverColumn = -1; rolloverColumnUpdated(oldRolloverColumn, rolloverColumn); } } private void swapCursor() { Cursor tmp = header.getCursor(); header.setCursor(otherCursor); otherCursor = tmp; } public void mouseMoved(MouseEvent e) { if (!header.isEnabled()) { return; } if (canResize(getResizingColumn(e.getPoint()), header) != (header.getCursor() == resizeCursor)) { swapCursor(); } updateRolloverColumn(e); } public void mouseDragged(MouseEvent e) { if (!header.isEnabled()) { return; } int mouseX = e.getX(); TableColumn resizingColumn = header.getResizingColumn(); TableColumn draggedColumn = header.getDraggedColumn(); boolean headerLeftToRight = header.getComponentOrientation().isLeftToRight(); if (resizingColumn != null) { int oldWidth = resizingColumn.getWidth(); int newWidth; if (headerLeftToRight) { newWidth = mouseX - mouseXOffset; } else { newWidth = mouseXOffset - mouseX; } mouseXOffset += changeColumnWidth(resizingColumn, header, oldWidth, newWidth); } else if (draggedColumn != null) { TableColumnModel cm = header.getColumnModel(); int draggedDistance = mouseX - mouseXOffset; int direction = (draggedDistance < 0) ? -1 : 1; int columnIndex = viewIndexForColumn(draggedColumn); int newColumnIndex = columnIndex + (headerLeftToRight ? direction : -direction); if (0 <= newColumnIndex && newColumnIndex < cm.getColumnCount()) { int width = cm.getColumn(newColumnIndex).getWidth(); if (Math.abs(draggedDistance) > (width / 2)) { mouseXOffset = mouseXOffset + direction * width; header.setDraggedDistance(draggedDistance - direction * width); //Cache the selected column. int selectedIndex = SwingUtilities2.convertColumnIndexToModel( header.getColumnModel(), getSelectedColumnIndex()); //Now do the move. cm.moveColumn(columnIndex, newColumnIndex); //Update the selected index. selectColumn( SwingUtilities2.convertColumnIndexToView( header.getColumnModel(), selectedIndex), false); return; } } setDraggedDistance(draggedDistance, columnIndex); } updateRolloverColumn(e); } public void mouseReleased(MouseEvent e) { if (!header.isEnabled()) { return; } setDraggedDistance(0, viewIndexForColumn(header.getDraggedColumn())); header.setResizingColumn(null); header.setDraggedColumn(null); updateRolloverColumn(e); } public void mouseEntered(MouseEvent e) { if (!header.isEnabled()) { return; } updateRolloverColumn(e); } public void mouseExited(MouseEvent e) { if (!header.isEnabled()) { return; } int oldRolloverColumn = rolloverColumn; rolloverColumn = -1; rolloverColumnUpdated(oldRolloverColumn, rolloverColumn); } // // Protected & Private Methods // private void setDraggedDistance(int draggedDistance, int column) { header.setDraggedDistance(draggedDistance); if (column != -1) { header.getColumnModel().moveColumn(column, column); } } } // // Factory methods for the Listeners //
Creates the mouse listener for the JTableHeader.
/** * Creates the mouse listener for the JTableHeader. */
protected MouseInputListener createMouseInputListener() { return new MouseInputHandler(); } // // The installation/uninstall procedures and support // public static ComponentUI createUI(JComponent h) { return new BasicTableHeaderUI(); } // Installation public void installUI(JComponent c) { header = (JTableHeader)c; rendererPane = new CellRendererPane(); header.add(rendererPane); installDefaults(); installListeners(); installKeyboardActions(); }
Initializes JTableHeader properties such as font, foreground, and background. The font, foreground, and background properties are only set if their current value is either null or a UIResource, other properties are set if the current value is null.
See Also:
  • installUI
/** * Initializes JTableHeader properties such as font, foreground, and background. * The font, foreground, and background properties are only set if their * current value is either null or a UIResource, other properties are set * if the current value is null. * * @see #installUI */
protected void installDefaults() { LookAndFeel.installColorsAndFont(header, "TableHeader.background", "TableHeader.foreground", "TableHeader.font"); LookAndFeel.installProperty(header, "opaque", Boolean.TRUE); }
Attaches listeners to the JTableHeader.
/** * Attaches listeners to the JTableHeader. */
protected void installListeners() { mouseInputListener = createMouseInputListener(); header.addMouseListener(mouseInputListener); header.addMouseMotionListener(mouseInputListener); header.addFocusListener(focusListener); }
Register all keyboard actions on the JTableHeader.
/** * Register all keyboard actions on the JTableHeader. */
protected void installKeyboardActions() { InputMap keyMap = (InputMap)DefaultLookup.get(header, this, "TableHeader.ancestorInputMap"); SwingUtilities.replaceUIInputMap(header, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, keyMap); LazyActionMap.installLazyActionMap(header, BasicTableHeaderUI.class, "TableHeader.actionMap"); } // Uninstall methods public void uninstallUI(JComponent c) { uninstallDefaults(); uninstallListeners(); uninstallKeyboardActions(); header.remove(rendererPane); rendererPane = null; header = null; } protected void uninstallDefaults() {} protected void uninstallListeners() { header.removeMouseListener(mouseInputListener); header.removeMouseMotionListener(mouseInputListener); mouseInputListener = null; }
Unregisters default key actions.
/** * Unregisters default key actions. */
protected void uninstallKeyboardActions() { SwingUtilities.replaceUIInputMap(header, JComponent.WHEN_FOCUSED, null); SwingUtilities.replaceUIActionMap(header, null); }
Populates TableHeader's actions.
/** * Populates TableHeader's actions. */
static void loadActionMap(LazyActionMap map) { map.put(new Actions(Actions.TOGGLE_SORT_ORDER)); map.put(new Actions(Actions.SELECT_COLUMN_TO_LEFT)); map.put(new Actions(Actions.SELECT_COLUMN_TO_RIGHT)); map.put(new Actions(Actions.MOVE_COLUMN_LEFT)); map.put(new Actions(Actions.MOVE_COLUMN_RIGHT)); map.put(new Actions(Actions.RESIZE_LEFT)); map.put(new Actions(Actions.RESIZE_RIGHT)); map.put(new Actions(Actions.FOCUS_TABLE)); } // // Support for mouse rollover //
Returns the index of the column header over which the mouse currently is. When the mouse is not over the table header, -1 is returned.
See Also:
  • rolloverColumnUpdated(int, int)
Returns:the index of the current rollover column
Since:1.6
/** * Returns the index of the column header over which the mouse * currently is. When the mouse is not over the table header, * -1 is returned. * * @see #rolloverColumnUpdated(int, int) * @return the index of the current rollover column * @since 1.6 */
protected int getRolloverColumn() { return rolloverColumn; }
This method gets called every time when a rollover column in the table header is updated. Every look and feel that supports a rollover effect in a table header should override this method and repaint the header.
Params:
  • oldColumn – the index of the previous rollover column or -1 if the mouse was not over a column
  • newColumn – the index of the new rollover column or -1 if the mouse is not over a column
See Also:
Since:1.6
/** * This method gets called every time when a rollover column in the table * header is updated. Every look and feel that supports a rollover effect * in a table header should override this method and repaint the header. * * @param oldColumn the index of the previous rollover column or -1 if the * mouse was not over a column * @param newColumn the index of the new rollover column or -1 if the mouse * is not over a column * @see #getRolloverColumn() * @see JTableHeader#getHeaderRect(int) * @since 1.6 */
protected void rolloverColumnUpdated(int oldColumn, int newColumn) { } private void updateRolloverColumn(MouseEvent e) { if (header.getDraggedColumn() == null && header.contains(e.getPoint())) { int col = header.columnAtPoint(e.getPoint()); if (col != rolloverColumn) { int oldRolloverColumn = rolloverColumn; rolloverColumn = col; rolloverColumnUpdated(oldRolloverColumn, rolloverColumn); } } } // // Support for keyboard and mouse access // private int selectNextColumn(boolean doIt) { int newIndex = getSelectedColumnIndex(); if (newIndex < header.getColumnModel().getColumnCount() - 1) { newIndex++; if (doIt) { selectColumn(newIndex); } } return newIndex; } private int selectPreviousColumn(boolean doIt) { int newIndex = getSelectedColumnIndex(); if (newIndex > 0) { newIndex--; if (doIt) { selectColumn(newIndex); } } return newIndex; }
Selects the specified column in the table header. Repaints the affected header cells and makes sure the newly selected one is visible.
/** * Selects the specified column in the table header. Repaints the * affected header cells and makes sure the newly selected one is visible. */
void selectColumn(int newColIndex) { selectColumn(newColIndex, true); } void selectColumn(int newColIndex, boolean doScroll) { Rectangle repaintRect = header.getHeaderRect(selectedColumnIndex); header.repaint(repaintRect); selectedColumnIndex = newColIndex; repaintRect = header.getHeaderRect(newColIndex); header.repaint(repaintRect); if (doScroll) { scrollToColumn(newColIndex); } return; }
Used by selectColumn to scroll horizontally, if necessary, to ensure that the newly selected column is visible.
/** * Used by selectColumn to scroll horizontally, if necessary, * to ensure that the newly selected column is visible. */
private void scrollToColumn(int col) { Container container; JTable table; //Test whether the header is in a scroll pane and has a table. if ((header.getParent() == null) || ((container = header.getParent().getParent()) == null) || !(container instanceof JScrollPane) || ((table = header.getTable()) == null)) { return; } //Now scroll, if necessary. Rectangle vis = table.getVisibleRect(); Rectangle cellBounds = table.getCellRect(0, col, true); vis.x = cellBounds.x; vis.width = cellBounds.width; table.scrollRectToVisible(vis); } private int getSelectedColumnIndex() { int numCols = header.getColumnModel().getColumnCount(); if (selectedColumnIndex >= numCols && numCols > 0) { selectedColumnIndex = numCols - 1; } return selectedColumnIndex; } private static boolean canResize(TableColumn column, JTableHeader header) { return (column != null) && header.getResizingAllowed() && column.getResizable(); } private int changeColumnWidth(TableColumn resizingColumn, JTableHeader th, int oldWidth, int newWidth) { resizingColumn.setWidth(newWidth); Container container; JTable table; if ((th.getParent() == null) || ((container = th.getParent().getParent()) == null) || !(container instanceof JScrollPane) || ((table = th.getTable()) == null)) { return 0; } if (!container.getComponentOrientation().isLeftToRight() && !th.getComponentOrientation().isLeftToRight()) { JViewport viewport = ((JScrollPane)container).getViewport(); int viewportWidth = viewport.getWidth(); int diff = newWidth - oldWidth; int newHeaderWidth = table.getWidth() + diff; /* Resize a table */ Dimension tableSize = table.getSize(); tableSize.width += diff; table.setSize(tableSize); /* If this table is in AUTO_RESIZE_OFF mode and * has a horizontal scrollbar, we need to update * a view's position. */ if ((newHeaderWidth >= viewportWidth) && (table.getAutoResizeMode() == JTable.AUTO_RESIZE_OFF)) { Point p = viewport.getViewPosition(); p.x = Math.max(0, Math.min(newHeaderWidth - viewportWidth, p.x + diff)); viewport.setViewPosition(p); return diff; } } return 0; } // // Baseline //
Returns the baseline.
Throws:
See Also:
Since:1.6
/** * Returns the baseline. * * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @see javax.swing.JComponent#getBaseline(int, int) * @since 1.6 */
public int getBaseline(JComponent c, int width, int height) { super.getBaseline(c, width, height); int baseline = -1; TableColumnModel columnModel = header.getColumnModel(); for(int column = 0; column < columnModel.getColumnCount(); column++) { TableColumn aColumn = columnModel.getColumn(column); Component comp = getHeaderRenderer(column); Dimension pref = comp.getPreferredSize(); int columnBaseline = comp.getBaseline(pref.width, height); if (columnBaseline >= 0) { if (baseline == -1) { baseline = columnBaseline; } else if (baseline != columnBaseline) { baseline = -1; break; } } } return baseline; } // // Paint Methods and support // public void paint(Graphics g, JComponent c) { if (header.getColumnModel().getColumnCount() <= 0) { return; } boolean ltr = header.getComponentOrientation().isLeftToRight(); Rectangle clip = g.getClipBounds(); Point left = clip.getLocation(); Point right = new Point( clip.x + clip.width - 1, clip.y ); TableColumnModel cm = header.getColumnModel(); int cMin = header.columnAtPoint( ltr ? left : right ); int cMax = header.columnAtPoint( ltr ? right : left ); // This should never happen. if (cMin == -1) { cMin = 0; } // If the table does not have enough columns to fill the view we'll get -1. // Replace this with the index of the last column. if (cMax == -1) { cMax = cm.getColumnCount()-1; } TableColumn draggedColumn = header.getDraggedColumn(); int columnWidth; Rectangle cellRect = header.getHeaderRect(ltr ? cMin : cMax); TableColumn aColumn; if (ltr) { for(int column = cMin; column <= cMax ; column++) { aColumn = cm.getColumn(column); columnWidth = aColumn.getWidth(); cellRect.width = columnWidth; if (aColumn != draggedColumn) { paintCell(g, cellRect, column); } cellRect.x += columnWidth; } } else { for(int column = cMax; column >= cMin; column--) { aColumn = cm.getColumn(column); columnWidth = aColumn.getWidth(); cellRect.width = columnWidth; if (aColumn != draggedColumn) { paintCell(g, cellRect, column); } cellRect.x += columnWidth; } } // Paint the dragged column if we are dragging. if (draggedColumn != null) { int draggedColumnIndex = viewIndexForColumn(draggedColumn); Rectangle draggedCellRect = header.getHeaderRect(draggedColumnIndex); // Draw a gray well in place of the moving column. g.setColor(header.getParent().getBackground()); g.fillRect(draggedCellRect.x, draggedCellRect.y, draggedCellRect.width, draggedCellRect.height); draggedCellRect.x += header.getDraggedDistance(); // Fill the background. g.setColor(header.getBackground()); g.fillRect(draggedCellRect.x, draggedCellRect.y, draggedCellRect.width, draggedCellRect.height); paintCell(g, draggedCellRect, draggedColumnIndex); } // Remove all components in the rendererPane. rendererPane.removeAll(); } private Component getHeaderRenderer(int columnIndex) { TableColumn aColumn = header.getColumnModel().getColumn(columnIndex); TableCellRenderer renderer = aColumn.getHeaderRenderer(); if (renderer == null) { renderer = header.getDefaultRenderer(); } boolean hasFocus = !header.isPaintingForPrint() && (columnIndex == getSelectedColumnIndex()) && header.hasFocus(); return renderer.getTableCellRendererComponent(header.getTable(), aColumn.getHeaderValue(), false, hasFocus, -1, columnIndex); } private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) { Component component = getHeaderRenderer(columnIndex); rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y, cellRect.width, cellRect.height, true); } private int viewIndexForColumn(TableColumn aColumn) { TableColumnModel cm = header.getColumnModel(); for (int column = 0; column < cm.getColumnCount(); column++) { if (cm.getColumn(column) == aColumn) { return column; } } return -1; } // // Size Methods // private int getHeaderHeight() { int height = 0; boolean accomodatedDefault = false; TableColumnModel columnModel = header.getColumnModel(); for(int column = 0; column < columnModel.getColumnCount(); column++) { TableColumn aColumn = columnModel.getColumn(column); boolean isDefault = (aColumn.getHeaderRenderer() == null); if (!isDefault || !accomodatedDefault) { Component comp = getHeaderRenderer(column); int rendererHeight = comp.getPreferredSize().height; height = Math.max(height, rendererHeight); // Configuring the header renderer to calculate its preferred size // is expensive. Optimise this by assuming the default renderer // always has the same height as the first non-zero height that // it returns for a non-null/non-empty value. if (isDefault && rendererHeight > 0) { Object headerValue = aColumn.getHeaderValue(); if (headerValue != null) { headerValue = headerValue.toString(); if (headerValue != null && !headerValue.equals("")) { accomodatedDefault = true; } } } } } return height; } private Dimension createHeaderSize(long width) { // None of the callers include the intercell spacing, do it here. if (width > Integer.MAX_VALUE) { width = Integer.MAX_VALUE; } return new Dimension((int)width, getHeaderHeight()); }
Return the minimum size of the header. The minimum width is the sum of the minimum widths of each column (plus inter-cell spacing).
/** * Return the minimum size of the header. The minimum width is the sum * of the minimum widths of each column (plus inter-cell spacing). */
public Dimension getMinimumSize(JComponent c) { long width = 0; Enumeration enumeration = header.getColumnModel().getColumns(); while (enumeration.hasMoreElements()) { TableColumn aColumn = (TableColumn)enumeration.nextElement(); width = width + aColumn.getMinWidth(); } return createHeaderSize(width); }
Return the preferred size of the header. The preferred height is the maximum of the preferred heights of all of the components provided by the header renderers. The preferred width is the sum of the preferred widths of each column (plus inter-cell spacing).
/** * Return the preferred size of the header. The preferred height is the * maximum of the preferred heights of all of the components provided * by the header renderers. The preferred width is the sum of the * preferred widths of each column (plus inter-cell spacing). */
public Dimension getPreferredSize(JComponent c) { long width = 0; Enumeration enumeration = header.getColumnModel().getColumns(); while (enumeration.hasMoreElements()) { TableColumn aColumn = (TableColumn)enumeration.nextElement(); width = width + aColumn.getPreferredWidth(); } return createHeaderSize(width); }
Return the maximum size of the header. The maximum width is the sum of the maximum widths of each column (plus inter-cell spacing).
/** * Return the maximum size of the header. The maximum width is the sum * of the maximum widths of each column (plus inter-cell spacing). */
public Dimension getMaximumSize(JComponent c) { long width = 0; Enumeration enumeration = header.getColumnModel().getColumns(); while (enumeration.hasMoreElements()) { TableColumn aColumn = (TableColumn)enumeration.nextElement(); width = width + aColumn.getMaxWidth(); } return createHeaderSize(width); } private static class Actions extends UIAction { public static final String TOGGLE_SORT_ORDER = "toggleSortOrder"; public static final String SELECT_COLUMN_TO_LEFT = "selectColumnToLeft"; public static final String SELECT_COLUMN_TO_RIGHT = "selectColumnToRight"; public static final String MOVE_COLUMN_LEFT = "moveColumnLeft"; public static final String MOVE_COLUMN_RIGHT = "moveColumnRight"; public static final String RESIZE_LEFT = "resizeLeft"; public static final String RESIZE_RIGHT = "resizeRight"; public static final String FOCUS_TABLE = "focusTable"; public Actions(String name) { super(name); } public boolean isEnabled(Object sender) { if (sender instanceof JTableHeader) { JTableHeader th = (JTableHeader)sender; TableColumnModel cm = th.getColumnModel(); if (cm.getColumnCount() <= 0) { return false; } String key = getName(); BasicTableHeaderUI ui = (BasicTableHeaderUI)BasicLookAndFeel.getUIOfType(th.getUI(), BasicTableHeaderUI.class); if (ui != null) { if (key == MOVE_COLUMN_LEFT) { return th.getReorderingAllowed() && maybeMoveColumn(true, th, ui, false); } else if (key == MOVE_COLUMN_RIGHT) { return th.getReorderingAllowed() && maybeMoveColumn(false, th, ui, false); } else if (key == RESIZE_LEFT || key == RESIZE_RIGHT) { return canResize(cm.getColumn(ui.getSelectedColumnIndex()), th); } else if (key == FOCUS_TABLE) { return (th.getTable() != null); } } } return true; } public void actionPerformed(ActionEvent e) { JTableHeader th = (JTableHeader)e.getSource(); BasicTableHeaderUI ui = (BasicTableHeaderUI)BasicLookAndFeel. getUIOfType(th.getUI(), BasicTableHeaderUI.class); if (ui == null) { return; } String name = getName(); if (TOGGLE_SORT_ORDER == name) { JTable table = th.getTable(); RowSorter sorter = table == null ? null : table.getRowSorter(); if (sorter != null) { int columnIndex = ui.getSelectedColumnIndex(); columnIndex = table.convertColumnIndexToModel( columnIndex); sorter.toggleSortOrder(columnIndex); } } else if (SELECT_COLUMN_TO_LEFT == name) { if (th.getComponentOrientation().isLeftToRight()) { ui.selectPreviousColumn(true); } else { ui.selectNextColumn(true); } } else if (SELECT_COLUMN_TO_RIGHT == name) { if (th.getComponentOrientation().isLeftToRight()) { ui.selectNextColumn(true); } else { ui.selectPreviousColumn(true); } } else if (MOVE_COLUMN_LEFT == name) { moveColumn(true, th, ui); } else if (MOVE_COLUMN_RIGHT == name) { moveColumn(false, th, ui); } else if (RESIZE_LEFT == name) { resize(true, th, ui); } else if (RESIZE_RIGHT == name) { resize(false, th, ui); } else if (FOCUS_TABLE == name) { JTable table = th.getTable(); if (table != null) { table.requestFocusInWindow(); } } } private void moveColumn(boolean leftArrow, JTableHeader th, BasicTableHeaderUI ui) { maybeMoveColumn(leftArrow, th, ui, true); } private boolean maybeMoveColumn(boolean leftArrow, JTableHeader th, BasicTableHeaderUI ui, boolean doIt) { int oldIndex = ui.getSelectedColumnIndex(); int newIndex; if (th.getComponentOrientation().isLeftToRight()) { newIndex = leftArrow ? ui.selectPreviousColumn(doIt) : ui.selectNextColumn(doIt); } else { newIndex = leftArrow ? ui.selectNextColumn(doIt) : ui.selectPreviousColumn(doIt); } if (newIndex != oldIndex) { if (doIt) { th.getColumnModel().moveColumn(oldIndex, newIndex); } else { return true; // we'd do the move if asked } } return false; } private void resize(boolean leftArrow, JTableHeader th, BasicTableHeaderUI ui) { int columnIndex = ui.getSelectedColumnIndex(); TableColumn resizingColumn = th.getColumnModel().getColumn(columnIndex); th.setResizingColumn(resizingColumn); int oldWidth = resizingColumn.getWidth(); int newWidth = oldWidth; if (th.getComponentOrientation().isLeftToRight()) { newWidth = newWidth + (leftArrow ? -1 : 1); } else { newWidth = newWidth + (leftArrow ? 1 : -1); } ui.changeColumnWidth(resizingColumn, th, oldWidth, newWidth); } } } // End of Class BasicTableHeaderUI