Save This Page
Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]
    1   /*
    2    * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.swing.plaf.basic;
   27   
   28   import java.awt;
   29   import java.awt.event;
   30   import java.util;
   31   import javax.swing;
   32   import javax.swing.event;
   33   import javax.swing.plaf;
   34   import javax.swing.table;
   35   
   36   import sun.swing;
   37   
   38   /**
   39    * BasicTableHeaderUI implementation
   40    *
   41    * @author Alan Chung
   42    * @author Philip Milne
   43    */
   44   public class BasicTableHeaderUI extends TableHeaderUI {
   45   
   46       private static Cursor resizeCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
   47   
   48   //
   49   // Instance Variables
   50   //
   51   
   52       /** The JTableHeader that is delegating the painting to this UI. */
   53       protected JTableHeader header;
   54       protected CellRendererPane rendererPane;
   55   
   56       // Listeners that are attached to the JTable
   57       protected MouseInputListener mouseInputListener;
   58   
   59       // The column header over which the mouse currently is.
   60       private int rolloverColumn = -1;
   61   
   62       // The column that should be highlighted when the table header has the focus.
   63       private int selectedColumnIndex = 0; // Read ONLY via getSelectedColumnIndex!
   64   
   65       private static FocusListener focusListener = new FocusListener() {
   66           public void focusGained(FocusEvent e) {
   67               repaintHeader(e.getSource());
   68           }
   69   
   70           public void focusLost(FocusEvent e) {
   71               repaintHeader(e.getSource());
   72           }
   73   
   74           private void repaintHeader(Object source) {
   75               if (source instanceof JTableHeader) {
   76                   JTableHeader th = (JTableHeader)source;
   77                   BasicTableHeaderUI ui =
   78                      (BasicTableHeaderUI)BasicLookAndFeel.
   79                                           getUIOfType(th.getUI(),
   80                                               BasicTableHeaderUI.class);
   81                   if (ui == null) {
   82                       return;
   83                   }
   84   
   85                   th.repaint(th.getHeaderRect(ui.getSelectedColumnIndex()));
   86               }
   87           }
   88       };
   89   
   90       /**
   91        * This inner class is marked "public" due to a compiler bug.
   92        * This class should be treated as a "protected" inner class.
   93        * Instantiate it only within subclasses of BasicTableUI.
   94        */
   95       public class MouseInputHandler implements MouseInputListener {
   96   
   97           private int mouseXOffset;
   98           private Cursor otherCursor = resizeCursor;
   99   
  100           public void mouseClicked(MouseEvent e) {
  101               if (e.getClickCount() % 2 == 1 &&
  102                       SwingUtilities.isLeftMouseButton(e)){
  103                   JTable table = header.getTable();
  104                   RowSorter sorter;
  105                   if (table != null && (sorter = table.getRowSorter()) != null) {
  106                       int columnIndex = header.columnAtPoint(e.getPoint());
  107                       if (columnIndex != -1) {
  108                           columnIndex = table.convertColumnIndexToModel(
  109                                               columnIndex);
  110                           sorter.toggleSortOrder(columnIndex);
  111                       }
  112                   }
  113               }
  114           }
  115   
  116           private TableColumn getResizingColumn(Point p) {
  117               return getResizingColumn(p, header.columnAtPoint(p));
  118           }
  119   
  120           private TableColumn getResizingColumn(Point p, int column) {
  121               if (column == -1) {
  122                    return null;
  123               }
  124               Rectangle r = header.getHeaderRect(column);
  125               r.grow(-3, 0);
  126               if (r.contains(p)) {
  127                   return null;
  128               }
  129               int midPoint = r.x + r.width/2;
  130               int columnIndex;
  131               if( header.getComponentOrientation().isLeftToRight() ) {
  132                   columnIndex = (p.x < midPoint) ? column - 1 : column;
  133               } else {
  134                   columnIndex = (p.x < midPoint) ? column : column - 1;
  135               }
  136               if (columnIndex == -1) {
  137                   return null;
  138               }
  139               return header.getColumnModel().getColumn(columnIndex);
  140           }
  141   
  142           public void mousePressed(MouseEvent e) {
  143               header.setDraggedColumn(null);
  144               header.setResizingColumn(null);
  145               header.setDraggedDistance(0);
  146   
  147               Point p = e.getPoint();
  148   
  149               // First find which header cell was hit
  150               TableColumnModel columnModel = header.getColumnModel();
  151               int index = header.columnAtPoint(p);
  152   
  153               if (index != -1) {
  154                   // The last 3 pixels + 3 pixels of next column are for resizing
  155                   TableColumn resizingColumn = getResizingColumn(p, index);
  156                   if (canResize(resizingColumn, header)) {
  157                       header.setResizingColumn(resizingColumn);
  158                       if( header.getComponentOrientation().isLeftToRight() ) {
  159                           mouseXOffset = p.x - resizingColumn.getWidth();
  160                       } else {
  161                           mouseXOffset = p.x + resizingColumn.getWidth();
  162                       }
  163                   }
  164                   else if (header.getReorderingAllowed()) {
  165                       TableColumn hitColumn = columnModel.getColumn(index);
  166                       header.setDraggedColumn(hitColumn);
  167                       mouseXOffset = p.x;
  168                   }
  169               }
  170   
  171               if (header.getReorderingAllowed()) {
  172                   int oldRolloverColumn = rolloverColumn;
  173                   rolloverColumn = -1;
  174                   rolloverColumnUpdated(oldRolloverColumn, rolloverColumn);
  175               }
  176           }
  177   
  178           private void swapCursor() {
  179               Cursor tmp = header.getCursor();
  180               header.setCursor(otherCursor);
  181               otherCursor = tmp;
  182           }
  183   
  184           public void mouseMoved(MouseEvent e) {
  185               if (canResize(getResizingColumn(e.getPoint()), header) !=
  186                   (header.getCursor() == resizeCursor)) {
  187                   swapCursor();
  188               }
  189               updateRolloverColumn(e);
  190          }
  191   
  192           public void mouseDragged(MouseEvent e) {
  193               int mouseX = e.getX();
  194   
  195               TableColumn resizingColumn  = header.getResizingColumn();
  196               TableColumn draggedColumn  = header.getDraggedColumn();
  197   
  198               boolean headerLeftToRight = header.getComponentOrientation().isLeftToRight();
  199   
  200               if (resizingColumn != null) {
  201                   int oldWidth = resizingColumn.getWidth();
  202                   int newWidth;
  203                   if (headerLeftToRight) {
  204                       newWidth = mouseX - mouseXOffset;
  205                   } else  {
  206                       newWidth = mouseXOffset - mouseX;
  207                   }
  208                   mouseXOffset += changeColumnWidth(resizingColumn, header,
  209                                                     oldWidth, newWidth);
  210               }
  211               else if (draggedColumn != null) {
  212                   TableColumnModel cm = header.getColumnModel();
  213                   int draggedDistance = mouseX - mouseXOffset;
  214                   int direction = (draggedDistance < 0) ? -1 : 1;
  215                   int columnIndex = viewIndexForColumn(draggedColumn);
  216                   int newColumnIndex = columnIndex + (headerLeftToRight ? direction : -direction);
  217                   if (0 <= newColumnIndex && newColumnIndex < cm.getColumnCount()) {
  218                       int width = cm.getColumn(newColumnIndex).getWidth();
  219                       if (Math.abs(draggedDistance) > (width / 2)) {
  220                           JTable table = header.getTable();
  221   
  222                           mouseXOffset = mouseXOffset + direction * width;
  223                           header.setDraggedDistance(draggedDistance - direction * width);
  224   
  225                           //Cache the selected column.
  226                           int selectedIndex = table.convertColumnIndexToModel(
  227                                                           getSelectedColumnIndex());
  228   
  229                           //Now do the move.
  230                           cm.moveColumn(columnIndex, newColumnIndex);
  231   
  232                           //Update the selected index.
  233                           selectColumn(
  234                               table.convertColumnIndexToView(selectedIndex),
  235                               false);
  236   
  237                           return;
  238                       }
  239                   }
  240                   setDraggedDistance(draggedDistance, columnIndex);
  241               }
  242   
  243               updateRolloverColumn(e);
  244           }
  245   
  246           public void mouseReleased(MouseEvent e) {
  247               setDraggedDistance(0, viewIndexForColumn(header.getDraggedColumn()));
  248   
  249               header.setResizingColumn(null);
  250               header.setDraggedColumn(null);
  251   
  252               updateRolloverColumn(e);
  253           }
  254   
  255           public void mouseEntered(MouseEvent e) {
  256               updateRolloverColumn(e);
  257           }
  258   
  259           public void mouseExited(MouseEvent e) {
  260               int oldRolloverColumn = rolloverColumn;
  261               rolloverColumn = -1;
  262               rolloverColumnUpdated(oldRolloverColumn, rolloverColumn);
  263           }
  264   //
  265   // Protected & Private Methods
  266   //
  267   
  268           private void setDraggedDistance(int draggedDistance, int column) {
  269               header.setDraggedDistance(draggedDistance);
  270               if (column != -1) {
  271                   header.getColumnModel().moveColumn(column, column);
  272               }
  273           }
  274       }
  275   
  276   //
  277   //  Factory methods for the Listeners
  278   //
  279   
  280       /**
  281        * Creates the mouse listener for the JTableHeader.
  282        */
  283       protected MouseInputListener createMouseInputListener() {
  284           return new MouseInputHandler();
  285       }
  286   
  287   //
  288   //  The installation/uninstall procedures and support
  289   //
  290   
  291       public static ComponentUI createUI(JComponent h) {
  292           return new BasicTableHeaderUI();
  293       }
  294   
  295   //  Installation
  296   
  297       public void installUI(JComponent c) {
  298           header = (JTableHeader)c;
  299   
  300           rendererPane = new CellRendererPane();
  301           header.add(rendererPane);
  302   
  303           installDefaults();
  304           installListeners();
  305           installKeyboardActions();
  306       }
  307   
  308       /**
  309        * Initialize JTableHeader properties, e.g. font, foreground, and background.
  310        * The font, foreground, and background properties are only set if their
  311        * current value is either null or a UIResource, other properties are set
  312        * if the current value is null.
  313        *
  314        * @see #installUI
  315        */
  316       protected void installDefaults() {
  317           LookAndFeel.installColorsAndFont(header, "TableHeader.background",
  318                                            "TableHeader.foreground", "TableHeader.font");
  319           LookAndFeel.installProperty(header, "opaque", Boolean.TRUE);
  320       }
  321   
  322       /**
  323        * Attaches listeners to the JTableHeader.
  324        */
  325       protected void installListeners() {
  326           mouseInputListener = createMouseInputListener();
  327   
  328           header.addMouseListener(mouseInputListener);
  329           header.addMouseMotionListener(mouseInputListener);
  330           header.addFocusListener(focusListener);
  331       }
  332   
  333       /**
  334        * Register all keyboard actions on the JTableHeader.
  335        */
  336       protected void installKeyboardActions() {
  337           InputMap keyMap = (InputMap)DefaultLookup.get(header, this,
  338                   "TableHeader.ancestorInputMap");
  339           SwingUtilities.replaceUIInputMap(header,
  340                                   JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, keyMap);
  341           LazyActionMap.installLazyActionMap(header, BasicTableHeaderUI.class,
  342                   "TableHeader.actionMap");
  343       }
  344   
  345   // Uninstall methods
  346   
  347       public void uninstallUI(JComponent c) {
  348           uninstallDefaults();
  349           uninstallListeners();
  350           uninstallKeyboardActions();
  351   
  352           header.remove(rendererPane);
  353           rendererPane = null;
  354           header = null;
  355       }
  356   
  357       protected void uninstallDefaults() {}
  358   
  359       protected void uninstallListeners() {
  360           header.removeMouseListener(mouseInputListener);
  361           header.removeMouseMotionListener(mouseInputListener);
  362   
  363           mouseInputListener = null;
  364       }
  365   
  366       /**
  367        * Unregisters default key actions.
  368        */
  369       protected void uninstallKeyboardActions() {
  370           SwingUtilities.replaceUIInputMap(header, JComponent.WHEN_FOCUSED, null);
  371           SwingUtilities.replaceUIActionMap(header, null);
  372       }
  373   
  374       /**
  375        * Populates TableHeader's actions.
  376        */
  377       static void loadActionMap(LazyActionMap map) {
  378           map.put(new Actions(Actions.TOGGLE_SORT_ORDER));
  379           map.put(new Actions(Actions.SELECT_COLUMN_TO_LEFT));
  380           map.put(new Actions(Actions.SELECT_COLUMN_TO_RIGHT));
  381           map.put(new Actions(Actions.MOVE_COLUMN_LEFT));
  382           map.put(new Actions(Actions.MOVE_COLUMN_RIGHT));
  383           map.put(new Actions(Actions.RESIZE_LEFT));
  384           map.put(new Actions(Actions.RESIZE_RIGHT));
  385           map.put(new Actions(Actions.FOCUS_TABLE));
  386       }
  387   
  388   //
  389   // Support for mouse rollover
  390   //
  391   
  392       /**
  393        * Returns the index of the column header over which the mouse
  394        * currently is. When the mouse is not over the table header,
  395        * -1 is returned.
  396        *
  397        * @see #rolloverColumnUpdated(int, int)
  398        * @return the index of the current rollover column
  399        * @since 1.6
  400        */
  401       protected int getRolloverColumn() {
  402           return rolloverColumn;
  403       }
  404   
  405       /**
  406        * This method gets called every time the rollover column in the table
  407        * header is updated. Every look and feel supporting rollover effect
  408        * in table header should override this method and repaint the header.
  409        *
  410        * @param oldColumn the index of the previous rollover column or -1 if the
  411        * mouse was not over a column
  412        * @param newColumn the index of the new rollover column or -1 if the mouse
  413        * is not over a column
  414        * @see #getRolloverColumn()
  415        * @see JTableHeader#getHeaderRect(int)
  416        * @since 1.6
  417        */
  418       protected void rolloverColumnUpdated(int oldColumn, int newColumn) {
  419       }
  420   
  421       private void updateRolloverColumn(MouseEvent e) {
  422           if (header.getDraggedColumn() == null &&
  423               header.contains(e.getPoint())) {
  424   
  425               int col = header.columnAtPoint(e.getPoint());
  426               if (col != rolloverColumn) {
  427                   int oldRolloverColumn = rolloverColumn;
  428                   rolloverColumn = col;
  429                   rolloverColumnUpdated(oldRolloverColumn, rolloverColumn);
  430               }
  431           }
  432       }
  433   
  434   //
  435   // Support for keyboard and mouse access
  436   //
  437       private int selectNextColumn(boolean doIt) {
  438           int newIndex = getSelectedColumnIndex();
  439           if (newIndex < header.getColumnModel().getColumnCount() - 1) {
  440               newIndex++;
  441               if (doIt) {
  442                   selectColumn(newIndex);
  443               }
  444           }
  445           return newIndex;
  446       }
  447   
  448       private int selectPreviousColumn(boolean doIt) {
  449           int newIndex = getSelectedColumnIndex();
  450           if (newIndex > 0) {
  451               newIndex--;
  452               if (doIt) {
  453                   selectColumn(newIndex);
  454               }
  455           }
  456           return newIndex;
  457       }
  458   
  459       /**
  460        * Selects the specified column in the table header. Repaints the
  461        * affected header cells and makes sure the newly selected one is visible.
  462        */
  463       void selectColumn(int newColIndex) {
  464           selectColumn(newColIndex, true);
  465       }
  466   
  467       void selectColumn(int newColIndex, boolean doScroll) {
  468           Rectangle repaintRect = header.getHeaderRect(selectedColumnIndex);
  469           header.repaint(repaintRect);
  470           selectedColumnIndex = newColIndex;
  471           repaintRect = header.getHeaderRect(newColIndex);
  472           header.repaint(repaintRect);
  473           if (doScroll) {
  474               scrollToColumn(newColIndex);
  475           }
  476           return;
  477       }
  478       /**
  479        * Used by selectColumn to scroll horizontally, if necessary,
  480        * to ensure that the newly selected column is visible.
  481        */
  482       private void scrollToColumn(int col) {
  483           Container container;
  484           JTable table;
  485   
  486           //Test whether the header is in a scroll pane and has a table.
  487           if ((header.getParent() == null) ||
  488               ((container = header.getParent().getParent()) == null) ||
  489               !(container instanceof JScrollPane) ||
  490               ((table = header.getTable()) == null)) {
  491               return;
  492           }
  493   
  494           //Now scroll, if necessary.
  495           Rectangle vis = table.getVisibleRect();
  496           Rectangle cellBounds = table.getCellRect(0, col, true);
  497           vis.x = cellBounds.x;
  498           vis.width = cellBounds.width;
  499           table.scrollRectToVisible(vis);
  500       }
  501   
  502       private int getSelectedColumnIndex() {
  503           int numCols = header.getColumnModel().getColumnCount();
  504           if (selectedColumnIndex >= numCols && numCols > 0) {
  505               selectedColumnIndex = numCols - 1;
  506           }
  507           return selectedColumnIndex;
  508       }
  509   
  510       private static boolean canResize(TableColumn column,
  511                                        JTableHeader header) {
  512           return (column != null) && header.getResizingAllowed()
  513                                   && column.getResizable();
  514       }
  515   
  516       private int changeColumnWidth(TableColumn resizingColumn,
  517                                     JTableHeader th,
  518                                     int oldWidth, int newWidth) {
  519           resizingColumn.setWidth(newWidth);
  520   
  521           Container container;
  522           JTable table;
  523   
  524           if ((th.getParent() == null) ||
  525               ((container = th.getParent().getParent()) == null) ||
  526               !(container instanceof JScrollPane) ||
  527               ((table = th.getTable()) == null)) {
  528               return 0;
  529           }
  530   
  531           if (!container.getComponentOrientation().isLeftToRight() &&
  532                   !th.getComponentOrientation().isLeftToRight()) {
  533                   JViewport viewport = ((JScrollPane)container).getViewport();
  534                   int viewportWidth = viewport.getWidth();
  535                   int diff = newWidth - oldWidth;
  536                   int newHeaderWidth = table.getWidth() + diff;
  537   
  538                   /* Resize a table */
  539                   Dimension tableSize = table.getSize();
  540                   tableSize.width += diff;
  541                   table.setSize(tableSize);
  542   
  543                   /* If this table is in AUTO_RESIZE_OFF mode and
  544                    * has a horizontal scrollbar, we need to update
  545                    * a view's position.
  546                    */
  547                   if ((newHeaderWidth >= viewportWidth) &&
  548                       (table.getAutoResizeMode() == JTable.AUTO_RESIZE_OFF)) {
  549                       Point p = viewport.getViewPosition();
  550                       p.x = Math.max(0, Math.min(newHeaderWidth - viewportWidth,
  551                                                  p.x + diff));
  552                       viewport.setViewPosition(p);
  553                       return diff;
  554               }
  555           }
  556           return 0;
  557       }
  558   
  559   //
  560   // Baseline
  561   //
  562   
  563       /**
  564        * Returns the baseline.
  565        *
  566        * @throws NullPointerException {@inheritDoc}
  567        * @throws IllegalArgumentException {@inheritDoc}
  568        * @see javax.swing.JComponent#getBaseline(int, int)
  569        * @since 1.6
  570        */
  571       public int getBaseline(JComponent c, int width, int height) {
  572           super.getBaseline(c, width, height);
  573           int baseline = -1;
  574           TableColumnModel columnModel = header.getColumnModel();
  575           for(int column = 0; column < columnModel.getColumnCount();
  576               column++) {
  577               TableColumn aColumn = columnModel.getColumn(column);
  578               Component comp = getHeaderRenderer(column);
  579               Dimension pref = comp.getPreferredSize();
  580               int columnBaseline = comp.getBaseline(pref.width, height);
  581               if (columnBaseline >= 0) {
  582                   if (baseline == -1) {
  583                       baseline = columnBaseline;
  584                   }
  585                   else if (baseline != columnBaseline) {
  586                       baseline = -1;
  587                       break;
  588                   }
  589               }
  590           }
  591           return baseline;
  592       }
  593   
  594   //
  595   // Paint Methods and support
  596   //
  597   
  598       public void paint(Graphics g, JComponent c) {
  599           if (header.getColumnModel().getColumnCount() <= 0) {
  600               return;
  601           }
  602           boolean ltr = header.getComponentOrientation().isLeftToRight();
  603   
  604           Rectangle clip = g.getClipBounds();
  605           Point left = clip.getLocation();
  606           Point right = new Point( clip.x + clip.width - 1, clip.y );
  607           TableColumnModel cm = header.getColumnModel();
  608           int cMin = header.columnAtPoint( ltr ? left : right );
  609           int cMax = header.columnAtPoint( ltr ? right : left );
  610           // This should never happen.
  611           if (cMin == -1) {
  612               cMin =  0;
  613           }
  614           // If the table does not have enough columns to fill the view we'll get -1.
  615           // Replace this with the index of the last column.
  616           if (cMax == -1) {
  617               cMax = cm.getColumnCount()-1;
  618           }
  619   
  620           TableColumn draggedColumn = header.getDraggedColumn();
  621           int columnWidth;
  622           Rectangle cellRect = header.getHeaderRect(ltr ? cMin : cMax);
  623           TableColumn aColumn;
  624           if (ltr) {
  625               for(int column = cMin; column <= cMax ; column++) {
  626                   aColumn = cm.getColumn(column);
  627                   columnWidth = aColumn.getWidth();
  628                   cellRect.width = columnWidth;
  629                   if (aColumn != draggedColumn) {
  630                       paintCell(g, cellRect, column);
  631                   }
  632                   cellRect.x += columnWidth;
  633               }
  634           } else {
  635               for(int column = cMax; column >= cMin; column--) {
  636                   aColumn = cm.getColumn(column);
  637                   columnWidth = aColumn.getWidth();
  638                   cellRect.width = columnWidth;
  639                   if (aColumn != draggedColumn) {
  640                       paintCell(g, cellRect, column);
  641                   }
  642                   cellRect.x += columnWidth;
  643               }
  644           }
  645   
  646           // Paint the dragged column if we are dragging.
  647           if (draggedColumn != null) {
  648               int draggedColumnIndex = viewIndexForColumn(draggedColumn);
  649               Rectangle draggedCellRect = header.getHeaderRect(draggedColumnIndex);
  650   
  651               // Draw a gray well in place of the moving column.
  652               g.setColor(header.getParent().getBackground());
  653               g.fillRect(draggedCellRect.x, draggedCellRect.y,
  654                                  draggedCellRect.width, draggedCellRect.height);
  655   
  656               draggedCellRect.x += header.getDraggedDistance();
  657   
  658               // Fill the background.
  659               g.setColor(header.getBackground());
  660               g.fillRect(draggedCellRect.x, draggedCellRect.y,
  661                          draggedCellRect.width, draggedCellRect.height);
  662   
  663               paintCell(g, draggedCellRect, draggedColumnIndex);
  664           }
  665   
  666           // Remove all components in the rendererPane.
  667           rendererPane.removeAll();
  668       }
  669   
  670       private Component getHeaderRenderer(int columnIndex) {
  671           TableColumn aColumn = header.getColumnModel().getColumn(columnIndex);
  672           TableCellRenderer renderer = aColumn.getHeaderRenderer();
  673           if (renderer == null) {
  674               renderer = header.getDefaultRenderer();
  675           }
  676   
  677           boolean hasFocus = !header.isPaintingForPrint()
  678                              && (columnIndex == getSelectedColumnIndex())
  679                              && header.hasFocus();
  680           return renderer.getTableCellRendererComponent(header.getTable(),
  681                                                   aColumn.getHeaderValue(),
  682                                                   false, hasFocus,
  683                                                   -1, columnIndex);
  684       }
  685   
  686       private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) {
  687           Component component = getHeaderRenderer(columnIndex);
  688           rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
  689                               cellRect.width, cellRect.height, true);
  690       }
  691   
  692       private int viewIndexForColumn(TableColumn aColumn) {
  693           TableColumnModel cm = header.getColumnModel();
  694           for (int column = 0; column < cm.getColumnCount(); column++) {
  695               if (cm.getColumn(column) == aColumn) {
  696                   return column;
  697               }
  698           }
  699           return -1;
  700       }
  701   
  702   //
  703   // Size Methods
  704   //
  705   
  706       private int getHeaderHeight() {
  707           int height = 0;
  708           boolean accomodatedDefault = false;
  709           TableColumnModel columnModel = header.getColumnModel();
  710           for(int column = 0; column < columnModel.getColumnCount(); column++) {
  711               TableColumn aColumn = columnModel.getColumn(column);
  712               boolean isDefault = (aColumn.getHeaderRenderer() == null);
  713   
  714               if (!isDefault || !accomodatedDefault) {
  715                   Component comp = getHeaderRenderer(column);
  716                   int rendererHeight = comp.getPreferredSize().height;
  717                   height = Math.max(height, rendererHeight);
  718   
  719                   // Configuring the header renderer to calculate its preferred size
  720                   // is expensive. Optimise this by assuming the default renderer
  721                   // always has the same height as the first non-zero height that
  722                   // it returns for a non-null/non-empty value.
  723                   if (isDefault && rendererHeight > 0) {
  724                       Object headerValue = aColumn.getHeaderValue();
  725                       if (headerValue != null) {
  726                           headerValue = headerValue.toString();
  727   
  728                           if (headerValue != null && !headerValue.equals("")) {
  729                               accomodatedDefault = true;
  730                           }
  731                       }
  732                   }
  733               }
  734           }
  735           return height;
  736       }
  737   
  738       private Dimension createHeaderSize(long width) {
  739           TableColumnModel columnModel = header.getColumnModel();
  740           // None of the callers include the intercell spacing, do it here.
  741           if (width > Integer.MAX_VALUE) {
  742               width = Integer.MAX_VALUE;
  743           }
  744           return new Dimension((int)width, getHeaderHeight());
  745       }
  746   
  747   
  748       /**
  749        * Return the minimum size of the header. The minimum width is the sum
  750        * of the minimum widths of each column (plus inter-cell spacing).
  751        */
  752       public Dimension getMinimumSize(JComponent c) {
  753           long width = 0;
  754           Enumeration enumeration = header.getColumnModel().getColumns();
  755           while (enumeration.hasMoreElements()) {
  756               TableColumn aColumn = (TableColumn)enumeration.nextElement();
  757               width = width + aColumn.getMinWidth();
  758           }
  759           return createHeaderSize(width);
  760       }
  761   
  762       /**
  763        * Return the preferred size of the header. The preferred height is the
  764        * maximum of the preferred heights of all of the components provided
  765        * by the header renderers. The preferred width is the sum of the
  766        * preferred widths of each column (plus inter-cell spacing).
  767        */
  768       public Dimension getPreferredSize(JComponent c) {
  769           long width = 0;
  770           Enumeration enumeration = header.getColumnModel().getColumns();
  771           while (enumeration.hasMoreElements()) {
  772               TableColumn aColumn = (TableColumn)enumeration.nextElement();
  773               width = width + aColumn.getPreferredWidth();
  774           }
  775           return createHeaderSize(width);
  776       }
  777   
  778       /**
  779        * Return the maximum size of the header. The maximum width is the sum
  780        * of the maximum widths of each column (plus inter-cell spacing).
  781        */
  782       public Dimension getMaximumSize(JComponent c) {
  783           long width = 0;
  784           Enumeration enumeration = header.getColumnModel().getColumns();
  785           while (enumeration.hasMoreElements()) {
  786               TableColumn aColumn = (TableColumn)enumeration.nextElement();
  787               width = width + aColumn.getMaxWidth();
  788           }
  789           return createHeaderSize(width);
  790       }
  791   
  792       private static class Actions extends UIAction {
  793           public static final String TOGGLE_SORT_ORDER =
  794               "toggleSortOrder";
  795           public static final String SELECT_COLUMN_TO_LEFT =
  796               "selectColumnToLeft";
  797           public static final String SELECT_COLUMN_TO_RIGHT =
  798               "selectColumnToRight";
  799           public static final String MOVE_COLUMN_LEFT =
  800               "moveColumnLeft";
  801           public static final String MOVE_COLUMN_RIGHT =
  802               "moveColumnRight";
  803           public static final String RESIZE_LEFT =
  804               "resizeLeft";
  805           public static final String RESIZE_RIGHT =
  806               "resizeRight";
  807           public static final String FOCUS_TABLE =
  808               "focusTable";
  809   
  810           public Actions(String name) {
  811               super(name);
  812           }
  813   
  814           public boolean isEnabled(Object sender) {
  815               if (sender instanceof JTableHeader) {
  816                   JTableHeader th = (JTableHeader)sender;
  817                   TableColumnModel cm = th.getColumnModel();
  818                   if (cm.getColumnCount() <= 0) {
  819                       return false;
  820                   }
  821   
  822                   String key = getName();
  823                   BasicTableHeaderUI ui =
  824                       (BasicTableHeaderUI)BasicLookAndFeel.getUIOfType(th.getUI(),
  825                                                         BasicTableHeaderUI.class);
  826                   if (ui != null) {
  827                       if (key == MOVE_COLUMN_LEFT) {
  828                           return th.getReorderingAllowed()
  829                               && maybeMoveColumn(true, th, ui, false);
  830                       } else if (key == MOVE_COLUMN_RIGHT) {
  831                           return th.getReorderingAllowed()
  832                               && maybeMoveColumn(false, th, ui, false);
  833                       } else if (key == RESIZE_LEFT ||
  834                                  key == RESIZE_RIGHT) {
  835                           return canResize(cm.getColumn(ui.getSelectedColumnIndex()), th);
  836                       } else if (key == FOCUS_TABLE) {
  837                           return (th.getTable() != null);
  838                       }
  839                   }
  840               }
  841               return true;
  842           }
  843   
  844           public void actionPerformed(ActionEvent e) {
  845               JTableHeader th = (JTableHeader)e.getSource();
  846               BasicTableHeaderUI ui =
  847                   (BasicTableHeaderUI)BasicLookAndFeel.
  848                                           getUIOfType(th.getUI(),
  849                                               BasicTableHeaderUI.class);
  850               if (ui == null) {
  851                   return;
  852               }
  853   
  854               String name = getName();
  855               if (TOGGLE_SORT_ORDER == name) {
  856                   JTable table = th.getTable();
  857                   RowSorter sorter = table.getRowSorter();
  858                   if (sorter != null) {
  859                       int columnIndex = ui.getSelectedColumnIndex();
  860                       columnIndex = table.convertColumnIndexToModel(
  861                                                         columnIndex);
  862                       sorter.toggleSortOrder(columnIndex);
  863                   }
  864               } else if (SELECT_COLUMN_TO_LEFT == name) {
  865                   if (th.getComponentOrientation().isLeftToRight()) {
  866                       ui.selectPreviousColumn(true);
  867                   } else {
  868                       ui.selectNextColumn(true);
  869                   }
  870               } else if (SELECT_COLUMN_TO_RIGHT == name) {
  871                   if (th.getComponentOrientation().isLeftToRight()) {
  872                       ui.selectNextColumn(true);
  873                   } else {
  874                       ui.selectPreviousColumn(true);
  875                   }
  876               } else if (MOVE_COLUMN_LEFT == name) {
  877                   moveColumn(true, th, ui);
  878               } else if (MOVE_COLUMN_RIGHT == name) {
  879                   moveColumn(false, th, ui);
  880               } else if (RESIZE_LEFT == name) {
  881                   resize(true, th, ui);
  882               } else if (RESIZE_RIGHT == name) {
  883                   resize(false, th, ui);
  884               } else if (FOCUS_TABLE == name) {
  885                   JTable table = th.getTable();
  886                   if (table != null) {
  887                       table.requestFocusInWindow();
  888                   }
  889               }
  890           }
  891   
  892           private void moveColumn(boolean leftArrow, JTableHeader th,
  893                                   BasicTableHeaderUI ui) {
  894               maybeMoveColumn(leftArrow, th, ui, true);
  895           }
  896   
  897           private boolean maybeMoveColumn(boolean leftArrow, JTableHeader th,
  898                                           BasicTableHeaderUI ui, boolean doIt) {
  899               int oldIndex = ui.getSelectedColumnIndex();
  900               int newIndex;
  901   
  902               if (th.getComponentOrientation().isLeftToRight()) {
  903                   newIndex = leftArrow ? ui.selectPreviousColumn(doIt)
  904                                        : ui.selectNextColumn(doIt);
  905               } else {
  906                   newIndex = leftArrow ? ui.selectNextColumn(doIt)
  907                                        : ui.selectPreviousColumn(doIt);
  908               }
  909   
  910               if (newIndex != oldIndex) {
  911                   if (doIt) {
  912                       th.getColumnModel().moveColumn(oldIndex, newIndex);
  913                   } else {
  914                       return true; // we'd do the move if asked
  915                   }
  916               }
  917   
  918               return false;
  919           }
  920   
  921           private void resize(boolean leftArrow, JTableHeader th,
  922                               BasicTableHeaderUI ui) {
  923               int columnIndex = ui.getSelectedColumnIndex();
  924               TableColumn resizingColumn =
  925                   th.getColumnModel().getColumn(columnIndex);
  926   
  927               th.setResizingColumn(resizingColumn);
  928               int oldWidth = resizingColumn.getWidth();
  929               int newWidth = oldWidth;
  930   
  931               if (th.getComponentOrientation().isLeftToRight()) {
  932                   newWidth = newWidth + (leftArrow ? -1 : 1);
  933               } else {
  934                   newWidth = newWidth + (leftArrow ? 1 : -1);
  935               }
  936   
  937               ui.changeColumnWidth(resizingColumn, th, oldWidth, newWidth);
  938           }
  939       }
  940   }  // End of Class BasicTableHeaderUI

Save This Page
Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]