Source for javax.swing.plaf.basic.BasicTableUI

   1: /* BasicTableUI.java --
   2:    Copyright (C) 2004 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.plaf.basic;
  40: 
  41: import java.awt.Color;
  42: import java.awt.Component;
  43: import java.awt.Dimension;
  44: import java.awt.Graphics;
  45: import java.awt.Point;
  46: import java.awt.Rectangle;
  47: import java.awt.event.FocusEvent;
  48: import java.awt.event.FocusListener;
  49: import java.awt.event.KeyEvent;
  50: import java.awt.event.KeyListener;
  51: import java.awt.event.MouseEvent;
  52: 
  53: import javax.swing.BorderFactory;
  54: import javax.swing.CellRendererPane;
  55: import javax.swing.JComponent;
  56: import javax.swing.JTable;
  57: import javax.swing.ListSelectionModel;
  58: import javax.swing.UIDefaults;
  59: import javax.swing.UIManager;
  60: import javax.swing.border.Border;
  61: import javax.swing.event.MouseInputListener;
  62: import javax.swing.plaf.ComponentUI;
  63: import javax.swing.plaf.TableUI;
  64: import javax.swing.table.TableCellRenderer;
  65: import javax.swing.table.TableColumn;
  66: import javax.swing.table.TableColumnModel;
  67: 
  68: public class BasicTableUI
  69:   extends TableUI
  70: {
  71:   public static ComponentUI createUI(JComponent comp) 
  72:   {
  73:     return new BasicTableUI();
  74:   }
  75: 
  76:   protected FocusListener focusListener;  
  77:   protected KeyListener keyListener;   
  78:   protected MouseInputListener    mouseInputListener;   
  79:   protected CellRendererPane rendererPane;   
  80:   protected JTable table;
  81: 
  82:   /** The normal cell border. */
  83:   Border cellBorder;
  84: 
  85:   /** The cell border for selected/highlighted cells. */
  86:   Border highlightCellBorder;
  87: 
  88:   class FocusHandler implements FocusListener
  89:   {
  90:     public void focusGained(FocusEvent e) 
  91:     {
  92:     }
  93:     public void focusLost(FocusEvent e) 
  94:     {
  95:     }
  96:   }
  97: 
  98:   class KeyHandler implements KeyListener
  99:   {
 100:     public void keyPressed(KeyEvent e) 
 101:     {
 102:     }
 103:     public void keyReleased(KeyEvent e) 
 104:     {
 105:     }
 106:     public void keyTyped(KeyEvent e) 
 107:     {
 108:     }
 109:   }
 110: 
 111:   class MouseInputHandler implements MouseInputListener
 112:   {
 113:     Point begin, curr;
 114: 
 115:     private void updateSelection(boolean controlPressed)
 116:     {
 117:       if (table.getRowSelectionAllowed())
 118:         {
 119:           int lo_row = table.rowAtPoint(begin);
 120:           int hi_row  = table.rowAtPoint(curr);
 121:           ListSelectionModel rowModel = table.getSelectionModel();
 122:           if (lo_row != -1 && hi_row != -1)
 123:             {
 124:               if (controlPressed && rowModel.getSelectionMode() 
 125:                   != ListSelectionModel.SINGLE_SELECTION)
 126:                 rowModel.addSelectionInterval(lo_row, hi_row);
 127:               else
 128:                 rowModel.setSelectionInterval(lo_row, hi_row);
 129:             }
 130:         }
 131: 
 132:       if (table.getColumnSelectionAllowed())
 133:         {
 134:           int lo_col = table.columnAtPoint(begin);
 135:           int hi_col = table.columnAtPoint(curr);
 136:           ListSelectionModel colModel = table.getColumnModel().
 137:             getSelectionModel();
 138:           if (lo_col != -1 && hi_col != -1)
 139:             {
 140:               if (controlPressed && colModel.getSelectionMode() != 
 141:                   ListSelectionModel.SINGLE_SELECTION)
 142:                 colModel.addSelectionInterval(lo_col, hi_col);
 143:               else
 144:                 colModel.setSelectionInterval(lo_col, hi_col);
 145:             }
 146:         }
 147:     }
 148: 
 149:     public void mouseClicked(MouseEvent e) 
 150:     {
 151:     }
 152:     public void mouseDragged(MouseEvent e) 
 153:     {
 154:       curr = new Point(e.getX(), e.getY());
 155:       updateSelection(e.isControlDown());      
 156:     }
 157:     public void mouseEntered(MouseEvent e) 
 158:     {
 159:     }
 160:     public void mouseExited(MouseEvent e) 
 161:     {
 162:     }
 163:     public void mouseMoved(MouseEvent e) 
 164:     {
 165:     }
 166:     public void mousePressed(MouseEvent e) 
 167:     {
 168:       begin = new Point(e.getX(), e.getY());
 169:       curr = new Point(e.getX(), e.getY());
 170:       //if control is pressed and the cell is already selected, deselect it
 171:       if (e.isControlDown() && table.
 172:           isCellSelected(table.rowAtPoint(begin),table.columnAtPoint(begin)))
 173:         {                                       
 174:           table.getSelectionModel().
 175:             removeSelectionInterval(table.rowAtPoint(begin), 
 176:                                     table.rowAtPoint(begin));
 177:           table.getColumnModel().getSelectionModel().
 178:             removeSelectionInterval(table.columnAtPoint(begin), 
 179:                                     table.columnAtPoint(begin));
 180:         }
 181:       else
 182:         updateSelection(e.isControlDown());
 183:       
 184:     }
 185:     public void mouseReleased(MouseEvent e) 
 186:     {
 187:       begin = null;
 188:       curr = null;
 189:     }
 190:   }
 191: 
 192:   protected FocusListener createFocusListener() 
 193:   {
 194:     return new FocusHandler();
 195:   }
 196:   protected KeyListener createKeyListener() 
 197:   {
 198:     return new KeyHandler();
 199:   }
 200:   protected MouseInputListener createMouseInputListener() 
 201:   {
 202:     return new MouseInputHandler();
 203:   }
 204: 
 205:   public Dimension getMaximumSize(JComponent comp) 
 206:   {
 207:     return getPreferredSize(comp);
 208:   }
 209: 
 210:   public Dimension getMinimumSize(JComponent comp) 
 211:   {
 212:     return getPreferredSize(comp);
 213:   }
 214: 
 215:   public Dimension getPreferredSize(JComponent comp) 
 216:   {
 217:     int width = table.getColumnModel().getTotalColumnWidth();
 218:     int height = table.getRowCount() * table.getRowHeight();
 219:     return new Dimension(width, height);
 220:   }
 221: 
 222:   protected void installDefaults() 
 223:   {
 224:     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
 225:     table.setFont(defaults.getFont("Table.font"));
 226:     table.setGridColor(defaults.getColor("Table.gridColor"));
 227:     table.setForeground(defaults.getColor("Table.foreground"));
 228:     table.setBackground(defaults.getColor("Table.background"));
 229:     table.setSelectionForeground(defaults.getColor("Table.selectionForeground"));
 230:     table.setSelectionBackground(defaults.getColor("Table.selectionBackground"));
 231:     table.setOpaque(true);
 232: 
 233:     highlightCellBorder = defaults.getBorder("Table.focusCellHighlightBorder");
 234:     cellBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1);
 235:   }
 236:   protected void installKeyboardActions() 
 237:   {
 238:   }
 239: 
 240:   protected void installListeners() 
 241:   {
 242:     table.addFocusListener(focusListener);  
 243:     table.addKeyListener(keyListener);
 244:     table.addMouseListener(mouseInputListener);    
 245:     table.addMouseMotionListener(mouseInputListener);
 246:   }
 247: 
 248:   protected void uninstallDefaults() 
 249:   {
 250:     // TODO: this method used to do the following which is not
 251:     // quite right (at least it breaks apps that run fine with the
 252:     // JDK):
 253:     //
 254:     // table.setFont(null);
 255:     // table.setGridColor(null);
 256:     // table.setForeground(null);
 257:     // table.setBackground(null);
 258:     // table.setSelectionForeground(null);
 259:     // table.setSelectionBackground(null);
 260:     //
 261:     // This would leave the component in a corrupt state, which is
 262:     // not acceptable. A possible solution would be to have component
 263:     // level defaults installed, that get overridden by the UI defaults
 264:     // and get restored in this method. I am not quite sure about this
 265:     // though. / Roman Kennke
 266:   }
 267: 
 268:   protected void uninstallKeyboardActions() 
 269:   {
 270:   }
 271: 
 272:   protected void uninstallListeners() 
 273:   {
 274:     table.removeFocusListener(focusListener);  
 275:     table.removeKeyListener(keyListener);
 276:     table.removeMouseListener(mouseInputListener);    
 277:     table.removeMouseMotionListener(mouseInputListener);
 278:   }
 279: 
 280:   public void installUI(JComponent comp) 
 281:   {
 282:     table = (JTable)comp;
 283:     focusListener = createFocusListener();  
 284:     keyListener = createKeyListener();
 285:     mouseInputListener = createMouseInputListener();
 286:     installDefaults();
 287:     installKeyboardActions();
 288:     installListeners();
 289:   }
 290: 
 291:   public void uninstallUI(JComponent c) 
 292:   {
 293:     uninstallListeners();
 294:     uninstallKeyboardActions();
 295:     uninstallDefaults();    
 296:   }
 297: 
 298:   public void paint(Graphics gfx, JComponent ignored) 
 299:   {
 300:     int ncols = table.getColumnCount();
 301:     int nrows = table.getRowCount();
 302:     if (nrows == 0 || ncols == 0)
 303:       return;
 304: 
 305:     Rectangle clip = gfx.getClipBounds();
 306:     TableColumnModel cols = table.getColumnModel();
 307: 
 308:     int height = table.getRowHeight();
 309:     int x0 = 0, y0 = 0;
 310:     int x = x0;
 311:     int y = y0;
 312: 
 313:     Dimension gap = table.getIntercellSpacing();
 314:     int ymax = clip.y + clip.height;
 315:     int xmax = clip.x + clip.width;
 316: 
 317:     // paint the cell contents
 318:     for (int c = 0; c < ncols && x < xmax; ++c)
 319:       {
 320:         y = y0;
 321:         TableColumn col = cols.getColumn(c);
 322:         int width = col.getWidth();
 323:         int modelCol = col.getModelIndex();
 324: 
 325:         for (int r = 0; r < nrows && y < ymax; ++r)
 326:           {
 327:             Rectangle bounds = new Rectangle(x, y, width, height);
 328:               if (bounds.intersects(clip))
 329:               {
 330:                 TableCellRenderer rend = table.getCellRenderer(r, c);
 331:                 Component comp = table.prepareRenderer(rend, r, c);
 332:                 gfx.translate(x, y);
 333:                 comp.setBounds(new Rectangle(0, 0, width, height));
 334:                 // Set correct border on cell renderer.
 335:                 if (comp instanceof JComponent)
 336:                   {
 337:                     if (table.isCellSelected(r, c))
 338:                       ((JComponent) comp).setBorder(highlightCellBorder);
 339:                     else
 340:                       ((JComponent) comp).setBorder(cellBorder);
 341:                   }
 342:                 comp.paint(gfx);
 343:                 gfx.translate(-x, -y);
 344:               }
 345:               y += height;
 346:               if (gap != null)
 347:                 y += gap.height;
 348:           }
 349:         x += width;
 350:         if (gap != null)
 351:           x += gap.width;
 352:       }
 353: 
 354:     // tighten up the x and y max bounds
 355:     ymax = y;
 356:     xmax = x;
 357: 
 358:     Color grid = table.getGridColor();    
 359: 
 360:     // paint vertical grid lines    
 361:     if (grid != null && table.getShowVerticalLines())
 362:       {    
 363:         x = x0;
 364:         Color save = gfx.getColor();
 365:         gfx.setColor(grid);
 366:         boolean paintedLine = false;
 367:         for (int c = 0; c < ncols && x < xmax; ++c)
 368:           {
 369:             x += cols.getColumn(c).getWidth();;
 370:             if (gap != null)
 371:               x += gap.width;
 372:             gfx.drawLine(x, y0, x, ymax);
 373:             paintedLine = true;
 374:           }
 375:         gfx.setColor(save);
 376:       }
 377: 
 378:     // paint horizontal grid lines    
 379:     if (grid != null && table.getShowHorizontalLines())
 380:       {    
 381:         y = y0;
 382:         Color save = gfx.getColor();
 383:         gfx.setColor(grid);
 384:         boolean paintedLine = false;
 385:         for (int r = 0; r < nrows && y < ymax; ++r)
 386:           {
 387:             y += height;
 388:             if (gap != null)
 389:               y += gap.height;
 390:             gfx.drawLine(x0, y, xmax, y);
 391:             paintedLine = true;
 392:           }
 393:         gfx.setColor(save);
 394:       }
 395: 
 396:   }
 397: 
 398: }