OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [plaf/] [basic/] [BasicTableUI.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* 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.ComponentOrientation;
44
import java.awt.Dimension;
45
import java.awt.Graphics;
46
import java.awt.Point;
47
import java.awt.Rectangle;
48
import java.awt.event.ActionEvent;
49
import java.awt.event.FocusEvent;
50
import java.awt.event.FocusListener;
51
import java.awt.event.KeyEvent;
52
import java.awt.event.KeyListener;
53
import java.awt.event.MouseEvent;
54
import java.beans.PropertyChangeEvent;
55
import java.beans.PropertyChangeListener;
56
 
57
import javax.swing.AbstractAction;
58
import javax.swing.Action;
59
import javax.swing.ActionMap;
60
import javax.swing.CellRendererPane;
61
import javax.swing.DefaultCellEditor;
62
import javax.swing.DefaultListSelectionModel;
63
import javax.swing.InputMap;
64
import javax.swing.JComponent;
65
import javax.swing.JTable;
66
import javax.swing.ListSelectionModel;
67
import javax.swing.LookAndFeel;
68
import javax.swing.SwingUtilities;
69
import javax.swing.TransferHandler;
70
import javax.swing.UIManager;
71
import javax.swing.border.Border;
72
import javax.swing.event.ChangeEvent;
73
import javax.swing.event.MouseInputListener;
74
import javax.swing.plaf.ActionMapUIResource;
75
import javax.swing.plaf.ComponentUI;
76
import javax.swing.plaf.TableUI;
77
import javax.swing.table.TableCellEditor;
78
import javax.swing.table.TableCellRenderer;
79
import javax.swing.table.TableColumn;
80
import javax.swing.table.TableColumnModel;
81
import javax.swing.table.TableModel;
82
 
83
public class BasicTableUI extends TableUI
84
{
85
  public static ComponentUI createUI(JComponent comp)
86
  {
87
    return new BasicTableUI();
88
  }
89
 
90
  protected FocusListener focusListener;
91
  protected KeyListener keyListener;
92
  protected MouseInputListener  mouseInputListener;
93
  protected CellRendererPane rendererPane;
94
  protected JTable table;
95
 
96
  /** The normal cell border. */
97
  Border cellBorder;
98
 
99
  /** The action bound to KeyStrokes. */
100
  TableAction action;
101
 
102
  /**
103
   * Listens for changes to the tables properties.
104
   */
105
  private PropertyChangeListener propertyChangeListener;
106
 
107
  /**
108
   * Handles key events for the JTable. Key events should be handled through
109
   * the InputMap/ActionMap mechanism since JDK1.3. This class is only there
110
   * for backwards compatibility.
111
   *
112
   * @author Roman Kennke (kennke@aicas.com)
113
   */
114
  public class KeyHandler implements KeyListener
115
  {
116
 
117
    /**
118
     * Receives notification that a key has been pressed and released.
119
     * Activates the editing session for the focused cell by pressing the
120
     * character keys.
121
     *
122
     * @param event the key event
123
     */
124
    public void keyTyped(KeyEvent event)
125
    {
126
      // Key events should be handled through the InputMap/ActionMap mechanism
127
      // since JDK1.3. This class is only there for backwards compatibility.
128
 
129
      // Editor activation is a specific kind of response to ''any''
130
      // character key. Hence it is handled here.
131
      if (!table.isEditing() && table.isEnabled())
132
        {
133
          int r = table.getSelectedRow();
134
          int c = table.getSelectedColumn();
135
          if (table.isCellEditable(r, c))
136
            table.editCellAt(r, c);
137
        }
138
    }
139
 
140
    /**
141
     * Receives notification that a key has been pressed.
142
     *
143
     * @param event the key event
144
     */
145
    public void keyPressed(KeyEvent event)
146
    {
147
      // Key events should be handled through the InputMap/ActionMap mechanism
148
      // since JDK1.3. This class is only there for backwards compatibility.
149
    }
150
 
151
    /**
152
     * Receives notification that a key has been released.
153
     *
154
     * @param event the key event
155
     */
156
    public void keyReleased(KeyEvent event)
157
    {
158
      // Key events should be handled through the InputMap/ActionMap mechanism
159
      // since JDK1.3. This class is only there for backwards compatibility.
160
    }
161
  }
162
 
163
  public class FocusHandler implements FocusListener
164
  {
165
    public void focusGained(FocusEvent e)
166
    {
167
      // The only thing that is affected by a focus change seems to be
168
      // how the lead cell is painted. So we repaint this cell.
169
      repaintLeadCell();
170
    }
171
 
172
    public void focusLost(FocusEvent e)
173
    {
174
      // The only thing that is affected by a focus change seems to be
175
      // how the lead cell is painted. So we repaint this cell.
176
      repaintLeadCell();
177
    }
178
 
179
    /**
180
     * Repaints the lead cell in response to a focus change, to refresh
181
     * the display of the focus indicator.
182
     */
183
    private void repaintLeadCell()
184
    {
185
      int rowCount = table.getRowCount();
186
      int columnCount = table.getColumnCount();
187
      int rowLead = table.getSelectionModel().getLeadSelectionIndex();
188
      int columnLead = table.getColumnModel().getSelectionModel().
189
                                                       getLeadSelectionIndex();
190
      if (rowLead >= 0 && rowLead < rowCount && columnLead >= 0
191
          && columnLead < columnCount)
192
        {
193
          Rectangle dirtyRect = table.getCellRect(rowLead, columnLead, false);
194
          table.repaint(dirtyRect);
195
        }
196
    }
197
  }
198
 
199
  public class MouseInputHandler implements MouseInputListener
200
  {
201
    Point begin, curr;
202
 
203
    private void updateSelection(boolean controlPressed)
204
    {
205
      // Update the rows
206
      int lo_row = table.rowAtPoint(begin);
207
      int hi_row  = table.rowAtPoint(curr);
208
      ListSelectionModel rowModel = table.getSelectionModel();
209
      if (lo_row != -1 && hi_row != -1)
210
        {
211
          if (controlPressed && rowModel.getSelectionMode()
212
              != ListSelectionModel.SINGLE_SELECTION)
213
            rowModel.addSelectionInterval(lo_row, hi_row);
214
          else
215
            rowModel.setSelectionInterval(lo_row, hi_row);
216
        }
217
 
218
      // Update the columns
219
      int lo_col = table.columnAtPoint(begin);
220
      int hi_col = table.columnAtPoint(curr);
221
      ListSelectionModel colModel = table.getColumnModel().
222
        getSelectionModel();
223
      if (lo_col != -1 && hi_col != -1)
224
        {
225
          if (controlPressed && colModel.getSelectionMode() !=
226
              ListSelectionModel.SINGLE_SELECTION)
227
            colModel.addSelectionInterval(lo_col, hi_col);
228
          else
229
            colModel.setSelectionInterval(lo_col, hi_col);
230
        }
231
    }
232
 
233
    /**
234
     * For the double click, start the cell editor.
235
     */
236
    public void mouseClicked(MouseEvent e)
237
    {
238
      Point p = e.getPoint();
239
      int row = table.rowAtPoint(p);
240
      int col = table.columnAtPoint(p);
241
      if (table.isCellEditable(row, col))
242
        {
243
          // If the cell editor is the default editor, we request the
244
          // number of the required clicks from it. Otherwise,
245
          // require two clicks (double click).
246
          TableCellEditor editor = table.getCellEditor(row, col);
247
          if (editor instanceof DefaultCellEditor)
248
            {
249
              DefaultCellEditor ce = (DefaultCellEditor) editor;
250
              if (e.getClickCount() < ce.getClickCountToStart())
251
                return;
252
            }
253
          table.editCellAt(row, col);
254
        }
255
    }
256
 
257
    public void mouseDragged(MouseEvent e)
258
    {
259
      if (table.isEnabled())
260
        {
261
          curr = new Point(e.getX(), e.getY());
262
          updateSelection(e.isControlDown());
263
        }
264
    }
265
 
266
    public void mouseEntered(MouseEvent e)
267
    {
268
      // Nothing to do here.
269
    }
270
 
271
    public void mouseExited(MouseEvent e)
272
    {
273
      // Nothing to do here.
274
    }
275
 
276
    public void mouseMoved(MouseEvent e)
277
    {
278
      // Nothing to do here.
279
    }
280
 
281
    public void mousePressed(MouseEvent e)
282
    {
283
      if (table.isEnabled())
284
        {
285
          ListSelectionModel rowModel = table.getSelectionModel();
286
          ListSelectionModel colModel = table.getColumnModel().getSelectionModel();
287
          int rowLead = rowModel.getLeadSelectionIndex();
288
          int colLead = colModel.getLeadSelectionIndex();
289
 
290
          begin = new Point(e.getX(), e.getY());
291
          curr = new Point(e.getX(), e.getY());
292
          //if control is pressed and the cell is already selected, deselect it
293
          if (e.isControlDown() && table.isCellSelected(
294
              table.rowAtPoint(begin), table.columnAtPoint(begin)))
295
            {
296
              table.getSelectionModel().
297
              removeSelectionInterval(table.rowAtPoint(begin),
298
                                      table.rowAtPoint(begin));
299
              table.getColumnModel().getSelectionModel().
300
              removeSelectionInterval(table.columnAtPoint(begin),
301
                                      table.columnAtPoint(begin));
302
            }
303
          else
304
            updateSelection(e.isControlDown());
305
 
306
          // If we were editing, but the moved to another cell, stop editing
307
          if (rowLead != rowModel.getLeadSelectionIndex() ||
308
              colLead != colModel.getLeadSelectionIndex())
309
            if (table.isEditing())
310
              table.editingStopped(new ChangeEvent(e));
311
 
312
          // Must request focus explicitly.
313
          table.requestFocusInWindow();
314
        }
315
    }
316
 
317
    public void mouseReleased(MouseEvent e)
318
    {
319
      if (table.isEnabled())
320
        {
321
          begin = null;
322
          curr = null;
323
        }
324
    }
325
  }
326
 
327
  /**
328
   * Listens for changes to the model property of the JTable and adjusts some
329
   * settings.
330
   *
331
   * @author Roman Kennke (kennke@aicas.com)
332
   */
333
  private class PropertyChangeHandler implements PropertyChangeListener
334
  {
335
    /**
336
     * Receives notification if one of the JTable's properties changes.
337
     *
338
     * @param ev the property change event
339
     */
340
    public void propertyChange(PropertyChangeEvent ev)
341
    {
342
      String propName = ev.getPropertyName();
343
      if (propName.equals("model"))
344
        {
345
          ListSelectionModel rowSel = table.getSelectionModel();
346
          rowSel.clearSelection();
347
          ListSelectionModel colSel = table.getColumnModel().getSelectionModel();
348
          colSel.clearSelection();
349
          TableModel model = table.getModel();
350
 
351
          // Adjust lead and anchor selection indices of the row and column
352
          // selection models.
353
          if (model.getRowCount() > 0)
354
            {
355
              rowSel.setAnchorSelectionIndex(0);
356
              rowSel.setLeadSelectionIndex(0);
357
            }
358
          else
359
            {
360
              rowSel.setAnchorSelectionIndex(-1);
361
              rowSel.setLeadSelectionIndex(-1);
362
            }
363
          if (model.getColumnCount() > 0)
364
            {
365
              colSel.setAnchorSelectionIndex(0);
366
              colSel.setLeadSelectionIndex(0);
367
            }
368
          else
369
            {
370
              colSel.setAnchorSelectionIndex(-1);
371
              colSel.setLeadSelectionIndex(-1);
372
            }
373
        }
374
    }
375
  }
376
 
377
  protected FocusListener createFocusListener()
378
  {
379
    return new FocusHandler();
380
  }
381
 
382
  protected MouseInputListener createMouseInputListener()
383
  {
384
    return new MouseInputHandler();
385
  }
386
 
387
 
388
  /**
389
   * Creates and returns a key listener for the JTable.
390
   *
391
   * @return a key listener for the JTable
392
   */
393
  protected KeyListener createKeyListener()
394
  {
395
    return new KeyHandler();
396
  }
397
 
398
  /**
399
   * Return the maximum size of the table. The maximum height is the row
400
    * height times the number of rows. The maximum width is the sum of
401
    * the maximum widths of each column.
402
    *
403
    *  @param comp the component whose maximum size is being queried,
404
    *  this is ignored.
405
    *  @return a Dimension object representing the maximum size of the table,
406
    *  or null if the table has no elements.
407
   */
408
  public Dimension getMaximumSize(JComponent comp)
409
  {
410
    int maxTotalColumnWidth = 0;
411
    for (int i = 0; i < table.getColumnCount(); i++)
412
      maxTotalColumnWidth += table.getColumnModel().getColumn(i).getMaxWidth();
413
 
414
    return new Dimension(maxTotalColumnWidth, getHeight());
415
  }
416
 
417
  /**
418
   * Return the minimum size of the table. The minimum height is the row
419
    * height times the number of rows. The minimum width is the sum of
420
    * the minimum widths of each column.
421
    *
422
    *  @param comp the component whose minimum size is being queried,
423
    *  this is ignored.
424
    *  @return a Dimension object representing the minimum size of the table,
425
    *  or null if the table has no elements.
426
   */
427
  public Dimension getMinimumSize(JComponent comp)
428
  {
429
    int minTotalColumnWidth = 0;
430
    for (int i = 0; i < table.getColumnCount(); i++)
431
      minTotalColumnWidth += table.getColumnModel().getColumn(i).getMinWidth();
432
 
433
    return new Dimension(minTotalColumnWidth, getHeight());
434
  }
435
 
436
  /**
437
   * Returns the preferred size for the table of that UI.
438
   *
439
   * @param comp ignored, the <code>table</code> field is used instead
440
   *
441
   * @return the preferred size for the table of that UI
442
   */
443
  public Dimension getPreferredSize(JComponent comp)
444
  {
445
    int prefTotalColumnWidth = 0;
446
    TableColumnModel tcm = table.getColumnModel();
447
 
448
    for (int i = 0; i < tcm.getColumnCount(); i++)
449
      {
450
        TableColumn col = tcm.getColumn(i);
451
        prefTotalColumnWidth += col.getPreferredWidth();
452
      }
453
 
454
    return new Dimension(prefTotalColumnWidth, getHeight());
455
  }
456
 
457
  /**
458
   * Returns the table height. This helper method is used by
459
   * {@link #getMinimumSize(JComponent)}, {@link #getPreferredSize(JComponent)}
460
   * and {@link #getMaximumSize(JComponent)} to determine the table height.
461
   *
462
   * @return the table height
463
   */
464
  private int getHeight()
465
  {
466
    int height = 0;
467
    int rowCount = table.getRowCount();
468
    if (rowCount > 0 && table.getColumnCount() > 0)
469
      {
470
        Rectangle r = table.getCellRect(rowCount - 1, 0, true);
471
        height = r.y + r.height;
472
      }
473
    return height;
474
  }
475
 
476
  protected void installDefaults()
477
  {
478
    LookAndFeel.installColorsAndFont(table, "Table.background",
479
                                     "Table.foreground", "Table.font");
480
    table.setGridColor(UIManager.getColor("Table.gridColor"));
481
    table.setSelectionForeground(UIManager.getColor("Table.selectionForeground"));
482
    table.setSelectionBackground(UIManager.getColor("Table.selectionBackground"));
483
    table.setOpaque(true);
484
  }
485
 
486
  /**
487
   * Installs keyboard actions on the table.
488
   */
489
  protected void installKeyboardActions()
490
  {
491
    // Install the input map.
492
    InputMap inputMap =
493
      (InputMap) SharedUIDefaults.get("Table.ancestorInputMap");
494
    SwingUtilities.replaceUIInputMap(table,
495
                                 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
496
                                 inputMap);
497
 
498
    // FIXME: The JDK uses a LazyActionMap for parentActionMap
499
    SwingUtilities.replaceUIActionMap(table, getActionMap());
500
 
501
  }
502
 
503
  /**
504
   * Fetches the action map from  the UI defaults, or create a new one
505
   * if the action map hasn't been initialized.
506
   *
507
   * @return the action map
508
   */
509
  private ActionMap getActionMap()
510
  {
511
    ActionMap am = (ActionMap) UIManager.get("Table.actionMap");
512
    if (am == null)
513
      {
514
        am = createDefaultActions();
515
        UIManager.getLookAndFeelDefaults().put("Table.actionMap", am);
516
      }
517
    return am;
518
  }
519
 
520
  private ActionMap createDefaultActions()
521
  {
522
    ActionMapUIResource am = new ActionMapUIResource();
523
    Action action = new TableAction();
524
 
525
    am.put("cut", TransferHandler.getCutAction());
526
    am.put("copy", TransferHandler.getCopyAction());
527
    am.put("paste", TransferHandler.getPasteAction());
528
 
529
    am.put("cancel", action);
530
    am.put("selectAll", action);
531
    am.put("clearSelection", action);
532
    am.put("startEditing", action);
533
 
534
    am.put("selectNextRow", action);
535
    am.put("selectNextRowCell", action);
536
    am.put("selectNextRowExtendSelection", action);
537
    am.put("selectNextRowChangeLead", action);
538
 
539
    am.put("selectPreviousRow", action);
540
    am.put("selectPreviousRowCell", action);
541
    am.put("selectPreviousRowExtendSelection", action);
542
    am.put("selectPreviousRowChangeLead", action);
543
 
544
    am.put("selectNextColumn", action);
545
    am.put("selectNextColumnCell", action);
546
    am.put("selectNextColumnExtendSelection", action);
547
    am.put("selectNextColumnChangeLead", action);
548
 
549
    am.put("selectPreviousColumn", action);
550
    am.put("selectPreviousColumnCell", action);
551
    am.put("selectPreviousColumnExtendSelection", action);
552
    am.put("selectPreviousColumnChangeLead", action);
553
 
554
    am.put("scrollLeftChangeSelection", action);
555
    am.put("scrollLeftExtendSelection", action);
556
    am.put("scrollRightChangeSelection", action);
557
    am.put("scrollRightExtendSelection", action);
558
 
559
    am.put("scrollUpChangeSelection", action);
560
    am.put("scrollUpExtendSelection", action);
561
    am.put("scrollDownChangeSelection", action);
562
    am.put("scrolldownExtendSelection", action);
563
 
564
    am.put("selectFirstColumn", action);
565
    am.put("selectFirstColumnExtendSelection", action);
566
    am.put("selectLastColumn", action);
567
    am.put("selectLastColumnExtendSelection", action);
568
 
569
    am.put("selectFirstRow", action);
570
    am.put("selectFirstRowExtendSelection", action);
571
    am.put("selectLastRow", action);
572
    am.put("selectLastRowExtendSelection", action);
573
 
574
    am.put("addToSelection", action);
575
    am.put("toggleAndAnchor", action);
576
    am.put("extendTo", action);
577
    am.put("moveSelectionTo", action);
578
 
579
    return am;
580
  }
581
 
582
  /**
583
   * This class implements the actions that we want to happen
584
   * when specific keys are pressed for the JTable.  The actionPerformed
585
   * method is called when a key that has been registered for the JTable
586
   * is received.
587
   */
588
  private static class TableAction
589
    extends AbstractAction
590
  {
591
    /**
592
     * What to do when this action is called.
593
     *
594
     * @param e the ActionEvent that caused this action.
595
     */
596
    public void actionPerformed(ActionEvent e)
597
    {
598
      JTable table = (JTable) e.getSource();
599
 
600
      DefaultListSelectionModel rowModel
601
          = (DefaultListSelectionModel) table.getSelectionModel();
602
      DefaultListSelectionModel colModel
603
          = (DefaultListSelectionModel) table.getColumnModel().getSelectionModel();
604
 
605
      int rowLead = rowModel.getLeadSelectionIndex();
606
      int rowMax = table.getModel().getRowCount() - 1;
607
 
608
      int colLead = colModel.getLeadSelectionIndex();
609
      int colMax = table.getModel().getColumnCount() - 1;
610
 
611
      // The command with which the action has been called is stored
612
      // in this undocumented action value. This allows us to have only
613
      // one Action instance to serve all keyboard input for JTable.
614
      String command = (String) getValue("__command__");
615
      if (command.equals("selectPreviousRowExtendSelection"))
616
        {
617
          rowModel.setLeadSelectionIndex(Math.max(rowLead - 1, 0));
618
        }
619
      else if (command.equals("selectLastColumn"))
620
        {
621
          colModel.setSelectionInterval(colMax, colMax);
622
        }
623
      else if (command.equals("startEditing"))
624
        {
625
          if (table.isCellEditable(rowLead, colLead))
626
            table.editCellAt(rowLead, colLead);
627
        }
628
      else if (command.equals("selectFirstRowExtendSelection"))
629
        {
630
          rowModel.setLeadSelectionIndex(0);
631
        }
632
      else if (command.equals("selectFirstColumn"))
633
        {
634
          colModel.setSelectionInterval(0, 0);
635
        }
636
      else if (command.equals("selectFirstColumnExtendSelection"))
637
        {
638
          colModel.setLeadSelectionIndex(0);
639
        }
640
      else if (command.equals("selectLastRow"))
641
        {
642
          rowModel.setSelectionInterval(rowMax, rowMax);
643
        }
644
      else if (command.equals("selectNextRowExtendSelection"))
645
        {
646
          rowModel.setLeadSelectionIndex(Math.min(rowLead + 1, rowMax));
647
        }
648
      else if (command.equals("selectFirstRow"))
649
        {
650
          rowModel.setSelectionInterval(0, 0);
651
        }
652
      else if (command.equals("selectNextColumnExtendSelection"))
653
        {
654
          colModel.setLeadSelectionIndex(Math.min(colLead + 1, colMax));
655
        }
656
      else if (command.equals("selectLastColumnExtendSelection"))
657
        {
658
          colModel.setLeadSelectionIndex(colMax);
659
        }
660
      else if (command.equals("selectPreviousColumnExtendSelection"))
661
        {
662
          colModel.setLeadSelectionIndex(Math.max(colLead - 1, 0));
663
        }
664
      else if (command.equals("selectNextRow"))
665
        {
666
          rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax),
667
                                        Math.min(rowLead + 1, rowMax));
668
        }
669
      else if (command.equals("scrollUpExtendSelection"))
670
        {
671
          int target;
672
          if (rowLead == getFirstVisibleRowIndex(table))
673
            target = Math.max(0, rowLead - (getLastVisibleRowIndex(table)
674
                - getFirstVisibleRowIndex(table) + 1));
675
          else
676
            target = getFirstVisibleRowIndex(table);
677
 
678
          rowModel.setLeadSelectionIndex(target);
679
          colModel.setLeadSelectionIndex(colLead);
680
        }
681
      else if (command.equals("selectPreviousRow"))
682
        {
683
          rowModel.setSelectionInterval(Math.max(rowLead - 1, 0),
684
                                        Math.max(rowLead - 1, 0));
685
        }
686
      else if (command.equals("scrollRightChangeSelection"))
687
        {
688
          int target;
689
          if (colLead == getLastVisibleColumnIndex(table))
690
            target = Math.min(colMax, colLead
691
                              + (getLastVisibleColumnIndex(table)
692
                              - getFirstVisibleColumnIndex(table) + 1));
693
          else
694
            target = getLastVisibleColumnIndex(table);
695
 
696
          colModel.setSelectionInterval(target, target);
697
          rowModel.setSelectionInterval(rowLead, rowLead);
698
        }
699
      else if (command.equals("selectPreviousColumn"))
700
        {
701
          colModel.setSelectionInterval(Math.max(colLead - 1, 0),
702
                                        Math.max(colLead - 1, 0));
703
        }
704
      else if (command.equals("scrollLeftChangeSelection"))
705
        {
706
          int target;
707
          if (colLead == getFirstVisibleColumnIndex(table))
708
            target = Math.max(0, colLead - (getLastVisibleColumnIndex(table)
709
                                 - getFirstVisibleColumnIndex(table) + 1));
710
          else
711
            target = getFirstVisibleColumnIndex(table);
712
 
713
          colModel.setSelectionInterval(target, target);
714
          rowModel.setSelectionInterval(rowLead, rowLead);
715
        }
716
      else if (command.equals("clearSelection"))
717
        {
718
          table.clearSelection();
719
        }
720
      else if (command.equals("cancel"))
721
        {
722
          // FIXME: implement other parts of "cancel" like undo-ing last
723
          // selection.  Right now it just calls editingCancelled if
724
          // we're currently editing.
725
          if (table.isEditing())
726
            table.editingCanceled(new ChangeEvent("cancel"));
727
        }
728
      else if (command.equals("selectNextRowCell")
729
               || command.equals("selectPreviousRowCell")
730
               || command.equals("selectNextColumnCell")
731
               || command.equals("selectPreviousColumnCell"))
732
        {
733
          // If nothing is selected, select the first cell in the table
734
          if (table.getSelectedRowCount() == 0 &&
735
              table.getSelectedColumnCount() == 0)
736
            {
737
              rowModel.setSelectionInterval(0, 0);
738
              colModel.setSelectionInterval(0, 0);
739
              return;
740
            }
741
 
742
          // If the lead selection index isn't selected (ie a remove operation
743
          // happened, then set the lead to the first selected cell in the
744
          // table
745
          if (!table.isCellSelected(rowLead, colLead))
746
            {
747
              rowModel.addSelectionInterval(rowModel.getMinSelectionIndex(),
748
                                            rowModel.getMinSelectionIndex());
749
              colModel.addSelectionInterval(colModel.getMinSelectionIndex(),
750
                                            colModel.getMinSelectionIndex());
751
              return;
752
            }
753
 
754
          // multRowsSelected and multColsSelected tell us if multiple rows or
755
          // columns are selected, respectively
756
          boolean multRowsSelected, multColsSelected;
757
          multRowsSelected = table.getSelectedRowCount() > 1 &&
758
            table.getRowSelectionAllowed();
759
 
760
          multColsSelected = table.getSelectedColumnCount() > 1 &&
761
            table.getColumnSelectionAllowed();
762
 
763
          // If there is just one selection, select the next cell, and wrap
764
          // when you get to the edges of the table.
765
          if (!multColsSelected && !multRowsSelected)
766
            {
767
              if (command.indexOf("Column") != -1)
768
                advanceSingleSelection(colModel, colMax, rowModel, rowMax,
769
                    command.equals("selectPreviousColumnCell"));
770
              else
771
                advanceSingleSelection(rowModel, rowMax, colModel, colMax,
772
                    command.equals("selectPreviousRowCell"));
773
              return;
774
            }
775
 
776
 
777
          // rowMinSelected and rowMaxSelected are the minimum and maximum
778
          // values respectively of selected cells in the row selection model
779
          // Similarly for colMinSelected and colMaxSelected.
780
          int rowMaxSelected = table.getRowSelectionAllowed() ?
781
            rowModel.getMaxSelectionIndex() : table.getModel().getRowCount() - 1;
782
          int rowMinSelected = table.getRowSelectionAllowed() ?
783
            rowModel.getMinSelectionIndex() : 0;
784
          int colMaxSelected = table.getColumnSelectionAllowed() ?
785
            colModel.getMaxSelectionIndex() :
786
            table.getModel().getColumnCount() - 1;
787
          int colMinSelected = table.getColumnSelectionAllowed() ?
788
            colModel.getMinSelectionIndex() : 0;
789
 
790
          // If there are multiple rows and columns selected, select the next
791
          // cell and wrap at the edges of the selection.
792
          if (command.indexOf("Column") != -1)
793
            advanceMultipleSelection(table, colModel, colMinSelected,
794
                                     colMaxSelected, rowModel, rowMinSelected,
795
                                     rowMaxSelected,
796
                                    command.equals("selectPreviousColumnCell"),
797
                                    true);
798
 
799
          else
800
            advanceMultipleSelection(table, rowModel, rowMinSelected,
801
                                     rowMaxSelected, colModel, colMinSelected,
802
                                     colMaxSelected,
803
                                     command.equals("selectPreviousRowCell"),
804
                                     false);
805
        }
806
      else if (command.equals("selectNextColumn"))
807
        {
808
          colModel.setSelectionInterval(Math.min(colLead + 1, colMax),
809
                                        Math.min(colLead + 1, colMax));
810
        }
811
      else if (command.equals("scrollLeftExtendSelection"))
812
        {
813
          int target;
814
          if (colLead == getFirstVisibleColumnIndex(table))
815
            target = Math.max(0, colLead - (getLastVisibleColumnIndex(table)
816
                                 - getFirstVisibleColumnIndex(table) + 1));
817
          else
818
            target = getFirstVisibleColumnIndex(table);
819
 
820
          colModel.setLeadSelectionIndex(target);
821
          rowModel.setLeadSelectionIndex(rowLead);
822
        }
823
      else if (command.equals("scrollDownChangeSelection"))
824
        {
825
          int target;
826
          if (rowLead == getLastVisibleRowIndex(table))
827
            target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex(table)
828
                                      - getFirstVisibleRowIndex(table) + 1));
829
          else
830
            target = getLastVisibleRowIndex(table);
831
 
832
          rowModel.setSelectionInterval(target, target);
833
          colModel.setSelectionInterval(colLead, colLead);
834
        }
835
      else if (command.equals("scrollRightExtendSelection"))
836
        {
837
          int target;
838
          if (colLead == getLastVisibleColumnIndex(table))
839
            target = Math.min(colMax, colLead + (getLastVisibleColumnIndex(table)
840
                - getFirstVisibleColumnIndex(table) + 1));
841
          else
842
            target = getLastVisibleColumnIndex(table);
843
 
844
          colModel.setLeadSelectionIndex(target);
845
          rowModel.setLeadSelectionIndex(rowLead);
846
        }
847
      else if (command.equals("selectAll"))
848
        {
849
          table.selectAll();
850
        }
851
      else if (command.equals("selectLastRowExtendSelection"))
852
        {
853
          rowModel.setLeadSelectionIndex(rowMax);
854
          colModel.setLeadSelectionIndex(colLead);
855
        }
856
      else if (command.equals("scrollDownExtendSelection"))
857
        {
858
          int target;
859
          if (rowLead == getLastVisibleRowIndex(table))
860
            target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex(table)
861
                - getFirstVisibleRowIndex(table) + 1));
862
          else
863
            target = getLastVisibleRowIndex(table);
864
 
865
          rowModel.setLeadSelectionIndex(target);
866
          colModel.setLeadSelectionIndex(colLead);
867
        }
868
      else if (command.equals("scrollUpChangeSelection"))
869
        {
870
          int target;
871
          if (rowLead == getFirstVisibleRowIndex(table))
872
            target = Math.max(0, rowLead - (getLastVisibleRowIndex(table)
873
                - getFirstVisibleRowIndex(table) + 1));
874
          else
875
            target = getFirstVisibleRowIndex(table);
876
 
877
          rowModel.setSelectionInterval(target, target);
878
          colModel.setSelectionInterval(colLead, colLead);
879
        }
880
      else if (command.equals("selectNextRowChangeLead"))
881
          {
882
            if (rowModel.getSelectionMode()
883
                != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
884
              {
885
                // just "selectNextRow"
886
                rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax),
887
                                              Math.min(rowLead + 1, rowMax));
888
                colModel.setSelectionInterval(colLead, colLead);
889
              }
890
            else
891
              rowModel.moveLeadSelectionIndex(Math.min(rowLead + 1, rowMax));
892
          }
893
      else if (command.equals("selectPreviousRowChangeLead"))
894
        {
895
          if (rowModel.getSelectionMode()
896
              != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
897
            {
898
              // just selectPreviousRow
899
              rowModel.setSelectionInterval(Math.max(rowLead - 1, 0),
900
                                            Math.min(rowLead - 1, 0));
901
              colModel.setSelectionInterval(colLead, colLead);
902
            }
903
          else
904
            rowModel.moveLeadSelectionIndex(Math.max(rowLead - 1, 0));
905
        }
906
      else if (command.equals("selectNextColumnChangeLead"))
907
        {
908
          if (colModel.getSelectionMode()
909
              != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
910
            {
911
              // just selectNextColumn
912
              rowModel.setSelectionInterval(rowLead, rowLead);
913
              colModel.setSelectionInterval(Math.min(colLead + 1, colMax),
914
                                            Math.min(colLead + 1, colMax));
915
            }
916
          else
917
            colModel.moveLeadSelectionIndex(Math.min(colLead + 1, colMax));
918
        }
919
      else if (command.equals("selectPreviousColumnChangeLead"))
920
        {
921
          if (colModel.getSelectionMode()
922
              != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
923
            {
924
              // just selectPreviousColumn
925
              rowModel.setSelectionInterval(rowLead, rowLead);
926
              colModel.setSelectionInterval(Math.max(colLead - 1, 0),
927
                                            Math.max(colLead - 1, 0));
928
 
929
            }
930
          else
931
            colModel.moveLeadSelectionIndex(Math.max(colLead - 1, 0));
932
        }
933
      else if (command.equals("addToSelection"))
934
          {
935
            if (!table.isEditing())
936
              {
937
                int oldRowAnchor = rowModel.getAnchorSelectionIndex();
938
                int oldColAnchor = colModel.getAnchorSelectionIndex();
939
                rowModel.addSelectionInterval(rowLead, rowLead);
940
                colModel.addSelectionInterval(colLead, colLead);
941
                rowModel.setAnchorSelectionIndex(oldRowAnchor);
942
                colModel.setAnchorSelectionIndex(oldColAnchor);
943
              }
944
          }
945
      else if (command.equals("extendTo"))
946
        {
947
          rowModel.setSelectionInterval(rowModel.getAnchorSelectionIndex(),
948
                                        rowLead);
949
          colModel.setSelectionInterval(colModel.getAnchorSelectionIndex(),
950
                                        colLead);
951
        }
952
      else if (command.equals("toggleAndAnchor"))
953
        {
954
          if (rowModel.isSelectedIndex(rowLead))
955
            rowModel.removeSelectionInterval(rowLead, rowLead);
956
          else
957
            rowModel.addSelectionInterval(rowLead, rowLead);
958
 
959
          if (colModel.isSelectedIndex(colLead))
960
            colModel.removeSelectionInterval(colLead, colLead);
961
          else
962
            colModel.addSelectionInterval(colLead, colLead);
963
 
964
          rowModel.setAnchorSelectionIndex(rowLead);
965
          colModel.setAnchorSelectionIndex(colLead);
966
        }
967
      else if (command.equals("stopEditing"))
968
        {
969
          table.editingStopped(new ChangeEvent(command));
970
        }
971
      else
972
        {
973
          // If we're here that means we bound this TableAction class
974
          // to a keyboard input but we either want to ignore that input
975
          // or we just haven't implemented its action yet.
976
 
977
          // Uncomment the following line to print the names of unused bindings
978
          // when their keys are pressed
979
 
980
          // System.out.println ("not implemented: "+e.getActionCommand());
981
        }
982
 
983
      // Any commands whose keyStrokes should be used by the Editor should not
984
      // cause editing to be stopped: ie, the SPACE sends "addToSelection" but
985
      // if the table is in editing mode, the space should not cause us to stop
986
      // editing because it should be used by the Editor.
987
      if (table.isEditing() && command != "startEditing"
988
          && command != "addToSelection")
989
        table.editingStopped(new ChangeEvent("update"));
990
 
991
      table.scrollRectToVisible(table.getCellRect(
992
          rowModel.getLeadSelectionIndex(), colModel.getLeadSelectionIndex(),
993
          false));
994
    }
995
 
996
    /**
997
     * Returns the column index of the first visible column.
998
     * @return the column index of the first visible column.
999
     */
1000
    int getFirstVisibleColumnIndex(JTable table)
1001
    {
1002
      ComponentOrientation or = table.getComponentOrientation();
1003
      Rectangle r = table.getVisibleRect();
1004
      if (!or.isLeftToRight())
1005
        r.translate((int) r.getWidth() - 1, 0);
1006
      return table.columnAtPoint(r.getLocation());
1007
    }
1008
 
1009
    /**
1010
     * Returns the column index of the last visible column.
1011
     *
1012
     */
1013
    int getLastVisibleColumnIndex(JTable table)
1014
    {
1015
      ComponentOrientation or = table.getComponentOrientation();
1016
      Rectangle r = table.getVisibleRect();
1017
      if (or.isLeftToRight())
1018
        r.translate((int) r.getWidth() - 1, 0);
1019
      return table.columnAtPoint(r.getLocation());
1020
    }
1021
 
1022
    /**
1023
     * Returns the row index of the first visible row.
1024
     *
1025
     */
1026
    int getFirstVisibleRowIndex(JTable table)
1027
    {
1028
      ComponentOrientation or = table.getComponentOrientation();
1029
      Rectangle r = table.getVisibleRect();
1030
      if (!or.isLeftToRight())
1031
        r.translate((int) r.getWidth() - 1, 0);
1032
      return table.rowAtPoint(r.getLocation());
1033
    }
1034
 
1035
    /**
1036
     * Returns the row index of the last visible row.
1037
     *
1038
     */
1039
    int getLastVisibleRowIndex(JTable table)
1040
    {
1041
      ComponentOrientation or = table.getComponentOrientation();
1042
      Rectangle r = table.getVisibleRect();
1043
      r.translate(0, (int) r.getHeight() - 1);
1044
      if (or.isLeftToRight())
1045
        r.translate((int) r.getWidth() - 1, 0);
1046
      // The next if makes sure that we don't return -1 simply because
1047
      // there is white space at the bottom of the table (ie, the display
1048
      // area is larger than the table)
1049
      if (table.rowAtPoint(r.getLocation()) == -1)
1050
        {
1051
          if (getFirstVisibleRowIndex(table) == -1)
1052
            return -1;
1053
          else
1054
            return table.getModel().getRowCount() - 1;
1055
        }
1056
      return table.rowAtPoint(r.getLocation());
1057
    }
1058
 
1059
    /**
1060
     * A helper method for the key bindings.  Used because the actions
1061
     * for TAB, SHIFT-TAB, ENTER, and SHIFT-ENTER are very similar.
1062
     *
1063
     * Selects the next (previous if SHIFT pressed) column for TAB, or row for
1064
     * ENTER from within the currently selected cells.
1065
     *
1066
     * @param firstModel the ListSelectionModel for columns (TAB) or
1067
     * rows (ENTER)
1068
     * @param firstMin the first selected index in firstModel
1069
     * @param firstMax the last selected index in firstModel
1070
     * @param secondModel the ListSelectionModel for rows (TAB) or
1071
     * columns (ENTER)
1072
     * @param secondMin the first selected index in secondModel
1073
     * @param secondMax the last selected index in secondModel
1074
     * @param reverse true if shift was held for the event
1075
     * @param eventIsTab true if TAB was pressed, false if ENTER pressed
1076
     */
1077
    void advanceMultipleSelection(JTable table, ListSelectionModel firstModel,
1078
                                  int firstMin,
1079
                                  int firstMax, ListSelectionModel secondModel,
1080
                                  int secondMin, int secondMax, boolean reverse,
1081
                                  boolean eventIsTab)
1082
    {
1083
      // If eventIsTab, all the "firsts" correspond to columns, otherwise, to
1084
      // rows "seconds" correspond to the opposite
1085
      int firstLead = firstModel.getLeadSelectionIndex();
1086
      int secondLead = secondModel.getLeadSelectionIndex();
1087
      int numFirsts = eventIsTab ?
1088
        table.getModel().getColumnCount() : table.getModel().getRowCount();
1089
      int numSeconds = eventIsTab ?
1090
        table.getModel().getRowCount() : table.getModel().getColumnCount();
1091
 
1092
      // check if we have to wrap the "firsts" around, going to the other side
1093
      if ((firstLead == firstMax && !reverse) ||
1094
          (reverse && firstLead == firstMin))
1095
        {
1096
          firstModel.addSelectionInterval(reverse ? firstMax : firstMin,
1097
                                          reverse ? firstMax : firstMin);
1098
 
1099
          // check if we have to wrap the "seconds"
1100
          if ((secondLead == secondMax && !reverse) ||
1101
              (reverse && secondLead == secondMin))
1102
            secondModel.addSelectionInterval(reverse ? secondMax : secondMin,
1103
                                             reverse ? secondMax : secondMin);
1104
 
1105
          // if we're not wrapping the seconds, we have to find out where we
1106
          // are within the secondModel and advance to the next cell (or
1107
          // go back to the previous cell if reverse == true)
1108
          else
1109
            {
1110
              int[] secondsSelected;
1111
              if (eventIsTab && table.getRowSelectionAllowed() ||
1112
                  !eventIsTab && table.getColumnSelectionAllowed())
1113
                secondsSelected = eventIsTab ?
1114
                  table.getSelectedRows() : table.getSelectedColumns();
1115
              else
1116
                {
1117
                  // if row selection is not allowed, then the entire column gets
1118
                  // selected when you click on it, so consider ALL rows selected
1119
                  secondsSelected = new int[numSeconds];
1120
                  for (int i = 0; i < numSeconds; i++)
1121
                  secondsSelected[i] = i;
1122
                }
1123
 
1124
              // and now find the "next" index within the model
1125
              int secondIndex = reverse ? secondsSelected.length - 1 : 0;
1126
              if (!reverse)
1127
                while (secondsSelected[secondIndex] <= secondLead)
1128
                  secondIndex++;
1129
              else
1130
                while (secondsSelected[secondIndex] >= secondLead)
1131
                  secondIndex--;
1132
 
1133
              // and select it - updating the lead selection index
1134
              secondModel.addSelectionInterval(secondsSelected[secondIndex],
1135
                                               secondsSelected[secondIndex]);
1136
            }
1137
        }
1138
      // We didn't have to wrap the firsts, so just find the "next" first
1139
      // and select it, we don't have to change "seconds"
1140
      else
1141
        {
1142
          int[] firstsSelected;
1143
          if (eventIsTab && table.getColumnSelectionAllowed() ||
1144
              !eventIsTab && table.getRowSelectionAllowed())
1145
            firstsSelected = eventIsTab ?
1146
              table.getSelectedColumns() : table.getSelectedRows();
1147
          else
1148
            {
1149
              // if selection not allowed, consider ALL firsts to be selected
1150
              firstsSelected = new int[numFirsts];
1151
              for (int i = 0; i < numFirsts; i++)
1152
                firstsSelected[i] = i;
1153
            }
1154
          int firstIndex = reverse ? firstsSelected.length - 1 : 0;
1155
          if (!reverse)
1156
            while (firstsSelected[firstIndex] <= firstLead)
1157
              firstIndex++;
1158
          else
1159
            while (firstsSelected[firstIndex] >= firstLead)
1160
              firstIndex--;
1161
          firstModel.addSelectionInterval(firstsSelected[firstIndex],
1162
                                          firstsSelected[firstIndex]);
1163
          secondModel.addSelectionInterval(secondLead, secondLead);
1164
        }
1165
    }
1166
 
1167
    /**
1168
     * A helper method for the key  bindings. Used because the actions
1169
     * for TAB, SHIFT-TAB, ENTER, and SHIFT-ENTER are very similar.
1170
     *
1171
     * Selects the next (previous if SHIFT pressed) column (TAB) or row (ENTER)
1172
     * in the table, changing the current selection.  All cells in the table
1173
     * are eligible, not just the ones that are currently selected.
1174
     * @param firstModel the ListSelectionModel for columns (TAB) or rows
1175
     * (ENTER)
1176
     * @param firstMax the last index in firstModel
1177
     * @param secondModel the ListSelectionModel for rows (TAB) or columns
1178
     * (ENTER)
1179
     * @param secondMax the last index in secondModel
1180
     * @param reverse true if SHIFT was pressed for the event
1181
     */
1182
 
1183
    void advanceSingleSelection(ListSelectionModel firstModel, int firstMax,
1184
                                ListSelectionModel secondModel, int secondMax,
1185
                                boolean reverse)
1186
    {
1187
      // for TABs, "first" corresponds to columns and "seconds" to rows.
1188
      // the opposite is true for ENTERs
1189
      int firstLead = firstModel.getLeadSelectionIndex();
1190
      int secondLead = secondModel.getLeadSelectionIndex();
1191
 
1192
      // if we are going backwards subtract 2 because we later add 1
1193
      // for a net change of -1
1194
      if (reverse && (firstLead == 0))
1195
        {
1196
          // check if we have to wrap around
1197
          if (secondLead == 0)
1198
            secondLead += secondMax + 1;
1199
          secondLead -= 2;
1200
        }
1201
 
1202
      // do we have to wrap the "seconds"?
1203
      if (reverse && (firstLead == 0) || !reverse && (firstLead == firstMax))
1204
        secondModel.setSelectionInterval((secondLead + 1) % (secondMax + 1),
1205
                                         (secondLead + 1) % (secondMax + 1));
1206
      // if not, just reselect the current lead
1207
      else
1208
        secondModel.setSelectionInterval(secondLead, secondLead);
1209
 
1210
      // if we are going backwards, subtract 2  because we add 1 later
1211
      // for net change of -1
1212
      if (reverse)
1213
        {
1214
          // check for wraparound
1215
          if (firstLead == 0)
1216
            firstLead += firstMax + 1;
1217
          firstLead -= 2;
1218
        }
1219
      // select the next "first"
1220
      firstModel.setSelectionInterval((firstLead + 1) % (firstMax + 1),
1221
                                      (firstLead + 1) % (firstMax + 1));
1222
    }
1223
  }
1224
 
1225
  protected void installListeners()
1226
  {
1227
    if (focusListener == null)
1228
      focusListener = createFocusListener();
1229
    table.addFocusListener(focusListener);
1230
    if (keyListener == null)
1231
      keyListener = createKeyListener();
1232
    table.addKeyListener(keyListener);
1233
    if (mouseInputListener == null)
1234
      mouseInputListener = createMouseInputListener();
1235
    table.addMouseListener(mouseInputListener);
1236
    table.addMouseMotionListener(mouseInputListener);
1237
    if (propertyChangeListener == null)
1238
      propertyChangeListener = new PropertyChangeHandler();
1239
    table.addPropertyChangeListener(propertyChangeListener);
1240
  }
1241
 
1242
  /**
1243
   * Uninstalls UI defaults that have been installed by
1244
   * {@link #installDefaults()}.
1245
   */
1246
  protected void uninstallDefaults()
1247
  {
1248
    // Nothing to do here for now.
1249
  }
1250
 
1251
  /**
1252
   * Uninstalls the keyboard actions that have been installed by
1253
   * {@link #installKeyboardActions()}.
1254
   */
1255
  protected void uninstallKeyboardActions()
1256
  {
1257
    SwingUtilities.replaceUIInputMap(table, JComponent.
1258
                                     WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
1259
    SwingUtilities.replaceUIActionMap(table, null);
1260
  }
1261
 
1262
  protected void uninstallListeners()
1263
  {
1264
    table.removeFocusListener(focusListener);
1265
    table.removeKeyListener(keyListener);
1266
    table.removeMouseListener(mouseInputListener);
1267
    table.removeMouseMotionListener(mouseInputListener);
1268
    table.removePropertyChangeListener(propertyChangeListener);
1269
    propertyChangeListener = null;
1270
  }
1271
 
1272
  public void installUI(JComponent comp)
1273
  {
1274
    table = (JTable) comp;
1275
    rendererPane = new CellRendererPane();
1276
    table.add(rendererPane);
1277
 
1278
    installDefaults();
1279
    installKeyboardActions();
1280
    installListeners();
1281
  }
1282
 
1283
  public void uninstallUI(JComponent c)
1284
  {
1285
    uninstallListeners();
1286
    uninstallKeyboardActions();
1287
    uninstallDefaults();
1288
 
1289
    table.remove(rendererPane);
1290
    rendererPane = null;
1291
    table = null;
1292
  }
1293
 
1294
  /**
1295
   * Paints a single cell in the table.
1296
   *
1297
   * @param g The graphics context to paint in
1298
   * @param row The row number to paint
1299
   * @param col The column number to paint
1300
   * @param bounds The bounds of the cell to paint, assuming a coordinate
1301
   * system beginning at <code>(0,0)</code> in the upper left corner of the
1302
   * table
1303
   * @param rend A cell renderer to paint with
1304
   */
1305
  void paintCell(Graphics g, int row, int col, Rectangle bounds,
1306
                 TableCellRenderer rend)
1307
  {
1308
    Component comp = table.prepareRenderer(rend, row, col);
1309
    rendererPane.paintComponent(g, comp, table, bounds);
1310
  }
1311
 
1312
  /**
1313
   * Paint the associated table.
1314
   */
1315
  public void paint(Graphics gfx, JComponent ignored)
1316
  {
1317
    int ncols = table.getColumnCount();
1318
    int nrows = table.getRowCount();
1319
    if (nrows == 0 || ncols == 0)
1320
      return;
1321
 
1322
    Rectangle clip = gfx.getClipBounds();
1323
 
1324
    // Determine the range of cells that are within the clip bounds.
1325
    Point p1 = new Point(clip.x, clip.y);
1326
    int c0 = table.columnAtPoint(p1);
1327
    if (c0 == -1)
1328
      c0 = 0;
1329
    int r0 = table.rowAtPoint(p1);
1330
    if (r0 == -1)
1331
      r0 = 0;
1332
    Point p2 = new Point(clip.x + clip.width, clip.y + clip.height);
1333
    int cn = table.columnAtPoint(p2);
1334
    if (cn == -1)
1335
      cn = table.getColumnCount() - 1;
1336
    int rn = table.rowAtPoint(p2);
1337
    if (rn == -1)
1338
      rn = table.getRowCount() - 1;
1339
 
1340
    int columnMargin = table.getColumnModel().getColumnMargin();
1341
    int rowMargin = table.getRowMargin();
1342
 
1343
    TableColumnModel cmodel = table.getColumnModel();
1344
    int[] widths = new int[cn + 1];
1345
    for (int i = c0; i <= cn; i++)
1346
      {
1347
        widths[i] = cmodel.getColumn(i).getWidth() - columnMargin;
1348
      }
1349
 
1350
    Rectangle bounds = table.getCellRect(r0, c0, false);
1351
    // The left boundary of the area being repainted.
1352
    int left = bounds.x;
1353
 
1354
    // The top boundary of the area being repainted.
1355
    int top = bounds.y;
1356
 
1357
    // The bottom boundary of the area being repainted.
1358
    int bottom;
1359
 
1360
    // paint the cell contents
1361
    Color grid = table.getGridColor();
1362
    for (int r = r0; r <= rn; ++r)
1363
      {
1364
        for (int c = c0; c <= cn; ++c)
1365
          {
1366
            bounds.width = widths[c];
1367
            paintCell(gfx, r, c, bounds, table.getCellRenderer(r, c));
1368
            bounds.x += widths[c] + columnMargin;
1369
          }
1370
        bounds.x = left;
1371
        bounds.y += table.getRowHeight(r);
1372
        // Update row height for tables with custom heights.
1373
        bounds.height = table.getRowHeight(r + 1) - rowMargin;
1374
      }
1375
 
1376
    bottom = bounds.y - rowMargin;
1377
 
1378
    // paint vertical grid lines
1379
    if (grid != null && table.getShowVerticalLines())
1380
      {
1381
        Color save = gfx.getColor();
1382
        gfx.setColor(grid);
1383
        int x = left - columnMargin;
1384
        for (int c = c0; c <= cn; ++c)
1385
          {
1386
            // The vertical grid is draw right from the cells, so we
1387
            // add before drawing.
1388
            x += widths[c] + columnMargin;
1389
            gfx.drawLine(x, top, x, bottom);
1390
          }
1391
        gfx.setColor(save);
1392
      }
1393
 
1394
    // paint horizontal grid lines
1395
    if (grid != null && table.getShowHorizontalLines())
1396
      {
1397
        Color save = gfx.getColor();
1398
        gfx.setColor(grid);
1399
        int y = top - rowMargin;
1400
        for (int r = r0; r <= rn; ++r)
1401
          {
1402
            // The horizontal grid is draw below the cells, so we
1403
            // add before drawing.
1404
            y += table.getRowHeight(r);
1405
            gfx.drawLine(left, y, p2.x, y);
1406
          }
1407
        gfx.setColor(save);
1408
      }
1409
  }
1410
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.