Source Code Cross Referenced for BasicTableUI.java in  » 6.0-JDK-Core » swing » javax » swing » plaf » basic » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing.plaf.basic 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package javax.swing.plaf.basic;
0027
0028        import java.awt.*;
0029        import java.awt.datatransfer.*;
0030        import java.awt.dnd.*;
0031        import java.awt.event.*;
0032        import java.util.Enumeration;
0033        import java.util.EventObject;
0034        import java.util.Hashtable;
0035        import java.util.TooManyListenersException;
0036        import javax.swing.*;
0037        import javax.swing.event.*;
0038        import javax.swing.plaf.*;
0039        import javax.swing.text.*;
0040        import javax.swing.table.*;
0041        import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag;
0042        import sun.swing.SwingUtilities2;
0043
0044        import java.beans.PropertyChangeEvent;
0045        import java.beans.PropertyChangeListener;
0046
0047        import sun.swing.DefaultLookup;
0048        import sun.swing.UIAction;
0049
0050        /**
0051         * BasicTableUI implementation
0052         *
0053         * @version 1.165 05/05/07
0054         * @author Philip Milne
0055         * @author Shannon Hickey (drag and drop)
0056         */
0057        public class BasicTableUI extends TableUI {
0058            private static final StringBuilder BASELINE_COMPONENT_KEY = new StringBuilder(
0059                    "Table.baselineComponent");
0060
0061            //
0062            // Instance Variables
0063            //
0064
0065            // The JTable that is delegating the painting to this UI.
0066            protected JTable table;
0067            protected CellRendererPane rendererPane;
0068
0069            // Listeners that are attached to the JTable
0070            protected KeyListener keyListener;
0071            protected FocusListener focusListener;
0072            protected MouseInputListener mouseInputListener;
0073
0074            private Handler handler;
0075
0076            /**
0077             * Local cache of Table's client property "Table.isFileList"
0078             */
0079            private boolean isFileList = false;
0080
0081            //
0082            //  Helper class for keyboard actions
0083            //
0084
0085            private static class Actions extends UIAction {
0086                private static final String CANCEL_EDITING = "cancel";
0087                private static final String SELECT_ALL = "selectAll";
0088                private static final String CLEAR_SELECTION = "clearSelection";
0089                private static final String START_EDITING = "startEditing";
0090
0091                private static final String NEXT_ROW = "selectNextRow";
0092                private static final String NEXT_ROW_CELL = "selectNextRowCell";
0093                private static final String NEXT_ROW_EXTEND_SELECTION = "selectNextRowExtendSelection";
0094                private static final String NEXT_ROW_CHANGE_LEAD = "selectNextRowChangeLead";
0095                private static final String PREVIOUS_ROW = "selectPreviousRow";
0096                private static final String PREVIOUS_ROW_CELL = "selectPreviousRowCell";
0097                private static final String PREVIOUS_ROW_EXTEND_SELECTION = "selectPreviousRowExtendSelection";
0098                private static final String PREVIOUS_ROW_CHANGE_LEAD = "selectPreviousRowChangeLead";
0099
0100                private static final String NEXT_COLUMN = "selectNextColumn";
0101                private static final String NEXT_COLUMN_CELL = "selectNextColumnCell";
0102                private static final String NEXT_COLUMN_EXTEND_SELECTION = "selectNextColumnExtendSelection";
0103                private static final String NEXT_COLUMN_CHANGE_LEAD = "selectNextColumnChangeLead";
0104                private static final String PREVIOUS_COLUMN = "selectPreviousColumn";
0105                private static final String PREVIOUS_COLUMN_CELL = "selectPreviousColumnCell";
0106                private static final String PREVIOUS_COLUMN_EXTEND_SELECTION = "selectPreviousColumnExtendSelection";
0107                private static final String PREVIOUS_COLUMN_CHANGE_LEAD = "selectPreviousColumnChangeLead";
0108
0109                private static final String SCROLL_LEFT_CHANGE_SELECTION = "scrollLeftChangeSelection";
0110                private static final String SCROLL_LEFT_EXTEND_SELECTION = "scrollLeftExtendSelection";
0111                private static final String SCROLL_RIGHT_CHANGE_SELECTION = "scrollRightChangeSelection";
0112                private static final String SCROLL_RIGHT_EXTEND_SELECTION = "scrollRightExtendSelection";
0113
0114                private static final String SCROLL_UP_CHANGE_SELECTION = "scrollUpChangeSelection";
0115                private static final String SCROLL_UP_EXTEND_SELECTION = "scrollUpExtendSelection";
0116                private static final String SCROLL_DOWN_CHANGE_SELECTION = "scrollDownChangeSelection";
0117                private static final String SCROLL_DOWN_EXTEND_SELECTION = "scrollDownExtendSelection";
0118
0119                private static final String FIRST_COLUMN = "selectFirstColumn";
0120                private static final String FIRST_COLUMN_EXTEND_SELECTION = "selectFirstColumnExtendSelection";
0121                private static final String LAST_COLUMN = "selectLastColumn";
0122                private static final String LAST_COLUMN_EXTEND_SELECTION = "selectLastColumnExtendSelection";
0123
0124                private static final String FIRST_ROW = "selectFirstRow";
0125                private static final String FIRST_ROW_EXTEND_SELECTION = "selectFirstRowExtendSelection";
0126                private static final String LAST_ROW = "selectLastRow";
0127                private static final String LAST_ROW_EXTEND_SELECTION = "selectLastRowExtendSelection";
0128
0129                // add the lead item to the selection without changing lead or anchor
0130                private static final String ADD_TO_SELECTION = "addToSelection";
0131
0132                // toggle the selected state of the lead item and move the anchor to it
0133                private static final String TOGGLE_AND_ANCHOR = "toggleAndAnchor";
0134
0135                // extend the selection to the lead item
0136                private static final String EXTEND_TO = "extendTo";
0137
0138                // move the anchor to the lead and ensure only that item is selected
0139                private static final String MOVE_SELECTION_TO = "moveSelectionTo";
0140
0141                // give focus to the JTableHeader, if one exists
0142                private static final String FOCUS_HEADER = "focusHeader";
0143
0144                protected int dx;
0145                protected int dy;
0146                protected boolean extend;
0147                protected boolean inSelection;
0148
0149                // horizontally, forwards always means right,
0150                // regardless of component orientation
0151                protected boolean forwards;
0152                protected boolean vertically;
0153                protected boolean toLimit;
0154
0155                protected int leadRow;
0156                protected int leadColumn;
0157
0158                Actions(String name) {
0159                    super (name);
0160                }
0161
0162                Actions(String name, int dx, int dy, boolean extend,
0163                        boolean inSelection) {
0164                    super (name);
0165
0166                    // Actions spcifying true for "inSelection" are
0167                    // fairly sensitive to bad parameter values. They require
0168                    // that one of dx and dy be 0 and the other be -1 or 1.
0169                    // Bogus parameter values could cause an infinite loop.
0170                    // To prevent any problems we massage the params here
0171                    // and complain if we get something we can't deal with.
0172                    if (inSelection) {
0173                        this .inSelection = true;
0174
0175                        // look at the sign of dx and dy only
0176                        dx = sign(dx);
0177                        dy = sign(dy);
0178
0179                        // make sure one is zero, but not both
0180                        assert (dx == 0 || dy == 0) && !(dx == 0 && dy == 0);
0181                    }
0182
0183                    this .dx = dx;
0184                    this .dy = dy;
0185                    this .extend = extend;
0186                }
0187
0188                Actions(String name, boolean extend, boolean forwards,
0189                        boolean vertically, boolean toLimit) {
0190                    this (name, 0, 0, extend, false);
0191                    this .forwards = forwards;
0192                    this .vertically = vertically;
0193                    this .toLimit = toLimit;
0194                }
0195
0196                private static int clipToRange(int i, int a, int b) {
0197                    return Math.min(Math.max(i, a), b - 1);
0198                }
0199
0200                private void moveWithinTableRange(JTable table, int dx, int dy) {
0201                    leadRow = clipToRange(leadRow + dy, 0, table.getRowCount());
0202                    leadColumn = clipToRange(leadColumn + dx, 0, table
0203                            .getColumnCount());
0204                }
0205
0206                private static int sign(int num) {
0207                    return (num < 0) ? -1 : ((num == 0) ? 0 : 1);
0208                }
0209
0210                /**
0211                 * Called to move within the selected range of the given JTable.
0212                 * This method uses the table's notion of selection, which is
0213                 * important to allow the user to navigate between items visually
0214                 * selected on screen. This notion may or may not be the same as
0215                 * what could be determined by directly querying the selection models.
0216                 * It depends on certain table properties (such as whether or not
0217                 * row or column selection is allowed). When performing modifications,
0218                 * it is recommended that caution be taken in order to preserve
0219                 * the intent of this method, especially when deciding whether to
0220                 * query the selection models or interact with JTable directly.
0221                 */
0222                private boolean moveWithinSelectedRange(JTable table, int dx,
0223                        int dy, ListSelectionModel rsm, ListSelectionModel csm) {
0224
0225                    // Note: The Actions constructor ensures that only one of
0226                    // dx and dy is 0, and the other is either -1 or 1
0227
0228                    // find out how many items the table is showing as selected
0229                    // and the range of items to navigate through
0230                    int totalCount;
0231                    int minX, maxX, minY, maxY;
0232
0233                    boolean rs = table.getRowSelectionAllowed();
0234                    boolean cs = table.getColumnSelectionAllowed();
0235
0236                    // both column and row selection
0237                    if (rs && cs) {
0238                        totalCount = table.getSelectedRowCount()
0239                                * table.getSelectedColumnCount();
0240                        minX = csm.getMinSelectionIndex();
0241                        maxX = csm.getMaxSelectionIndex();
0242                        minY = rsm.getMinSelectionIndex();
0243                        maxY = rsm.getMaxSelectionIndex();
0244                        // row selection only
0245                    } else if (rs) {
0246                        totalCount = table.getSelectedRowCount();
0247                        minX = 0;
0248                        maxX = table.getColumnCount() - 1;
0249                        minY = rsm.getMinSelectionIndex();
0250                        maxY = rsm.getMaxSelectionIndex();
0251                        // column selection only
0252                    } else if (cs) {
0253                        totalCount = table.getSelectedColumnCount();
0254                        minX = csm.getMinSelectionIndex();
0255                        maxX = csm.getMaxSelectionIndex();
0256                        minY = 0;
0257                        maxY = table.getRowCount() - 1;
0258                        // no selection allowed
0259                    } else {
0260                        totalCount = 0;
0261                        // A bogus assignment to stop javac from complaining
0262                        // about unitialized values. In this case, these
0263                        // won't even be used.
0264                        minX = maxX = minY = maxY = 0;
0265                    }
0266
0267                    // For some cases, there is no point in trying to stay within the
0268                    // selected area. Instead, move outside the selection, wrapping at
0269                    // the table boundaries. The cases are:
0270                    boolean stayInSelection;
0271
0272                    // - nothing selected
0273                    if (totalCount == 0 ||
0274                    // - one item selected, and the lead is already selected
0275                            (totalCount == 1 && table.isCellSelected(leadRow,
0276                                    leadColumn))) {
0277
0278                        stayInSelection = false;
0279
0280                        maxX = table.getColumnCount() - 1;
0281                        maxY = table.getRowCount() - 1;
0282
0283                        // the mins are calculated like this in case the max is -1
0284                        minX = Math.min(0, maxX);
0285                        minY = Math.min(0, maxY);
0286                    } else {
0287                        stayInSelection = true;
0288                    }
0289
0290                    // the algorithm below isn't prepared to deal with -1 lead/anchor
0291                    // so massage appropriately here first
0292                    if (dy == 1 && leadColumn == -1) {
0293                        leadColumn = minX;
0294                        leadRow = -1;
0295                    } else if (dx == 1 && leadRow == -1) {
0296                        leadRow = minY;
0297                        leadColumn = -1;
0298                    } else if (dy == -1 && leadColumn == -1) {
0299                        leadColumn = maxX;
0300                        leadRow = maxY + 1;
0301                    } else if (dx == -1 && leadRow == -1) {
0302                        leadRow = maxY;
0303                        leadColumn = maxX + 1;
0304                    }
0305
0306                    // In cases where the lead is not within the search range,
0307                    // we need to bring it within one cell for the the search
0308                    // to work properly. Check these here.
0309                    leadRow = Math.min(Math.max(leadRow, minY - 1), maxY + 1);
0310                    leadColumn = Math.min(Math.max(leadColumn, minX - 1),
0311                            maxX + 1);
0312
0313                    // find the next position, possibly looping until it is selected
0314                    do {
0315                        calcNextPos(dx, minX, maxX, dy, minY, maxY);
0316                    } while (stayInSelection
0317                            && !table.isCellSelected(leadRow, leadColumn));
0318
0319                    return stayInSelection;
0320                }
0321
0322                /**
0323                 * Find the next lead row and column based on the given
0324                 * dx/dy and max/min values.
0325                 */
0326                private void calcNextPos(int dx, int minX, int maxX, int dy,
0327                        int minY, int maxY) {
0328
0329                    if (dx != 0) {
0330                        leadColumn += dx;
0331                        if (leadColumn > maxX) {
0332                            leadColumn = minX;
0333                            leadRow++;
0334                            if (leadRow > maxY) {
0335                                leadRow = minY;
0336                            }
0337                        } else if (leadColumn < minX) {
0338                            leadColumn = maxX;
0339                            leadRow--;
0340                            if (leadRow < minY) {
0341                                leadRow = maxY;
0342                            }
0343                        }
0344                    } else {
0345                        leadRow += dy;
0346                        if (leadRow > maxY) {
0347                            leadRow = minY;
0348                            leadColumn++;
0349                            if (leadColumn > maxX) {
0350                                leadColumn = minX;
0351                            }
0352                        } else if (leadRow < minY) {
0353                            leadRow = maxY;
0354                            leadColumn--;
0355                            if (leadColumn < minX) {
0356                                leadColumn = maxX;
0357                            }
0358                        }
0359                    }
0360                }
0361
0362                public void actionPerformed(ActionEvent e) {
0363                    String key = getName();
0364                    JTable table = (JTable) e.getSource();
0365
0366                    ListSelectionModel rsm = table.getSelectionModel();
0367                    leadRow = getAdjustedLead(table, true, rsm);
0368
0369                    ListSelectionModel csm = table.getColumnModel()
0370                            .getSelectionModel();
0371                    leadColumn = getAdjustedLead(table, false, csm);
0372
0373                    if (key == SCROLL_LEFT_CHANGE_SELECTION
0374                            || // Paging Actions
0375                            key == SCROLL_LEFT_EXTEND_SELECTION
0376                            || key == SCROLL_RIGHT_CHANGE_SELECTION
0377                            || key == SCROLL_RIGHT_EXTEND_SELECTION
0378                            || key == SCROLL_UP_CHANGE_SELECTION
0379                            || key == SCROLL_UP_EXTEND_SELECTION
0380                            || key == SCROLL_DOWN_CHANGE_SELECTION
0381                            || key == SCROLL_DOWN_EXTEND_SELECTION
0382                            || key == FIRST_COLUMN
0383                            || key == FIRST_COLUMN_EXTEND_SELECTION
0384                            || key == FIRST_ROW
0385                            || key == FIRST_ROW_EXTEND_SELECTION
0386                            || key == LAST_COLUMN
0387                            || key == LAST_COLUMN_EXTEND_SELECTION
0388                            || key == LAST_ROW
0389                            || key == LAST_ROW_EXTEND_SELECTION) {
0390                        if (toLimit) {
0391                            if (vertically) {
0392                                int rowCount = table.getRowCount();
0393                                this .dx = 0;
0394                                this .dy = forwards ? rowCount : -rowCount;
0395                            } else {
0396                                int colCount = table.getColumnCount();
0397                                this .dx = forwards ? colCount : -colCount;
0398                                this .dy = 0;
0399                            }
0400                        } else {
0401                            if (!(table.getParent().getParent() instanceof  JScrollPane)) {
0402                                return;
0403                            }
0404
0405                            Dimension delta = table.getParent().getSize();
0406
0407                            if (vertically) {
0408                                Rectangle r = table.getCellRect(leadRow, 0,
0409                                        true);
0410                                if (forwards) {
0411                                    // scroll by at least one cell
0412                                    r.y += Math.max(delta.height, r.height);
0413                                } else {
0414                                    r.y -= delta.height;
0415                                }
0416
0417                                this .dx = 0;
0418                                int newRow = table.rowAtPoint(r.getLocation());
0419                                if (newRow == -1 && forwards) {
0420                                    newRow = table.getRowCount();
0421                                }
0422                                this .dy = newRow - leadRow;
0423                            } else {
0424                                Rectangle r = table.getCellRect(0, leadColumn,
0425                                        true);
0426
0427                                if (forwards) {
0428                                    // scroll by at least one cell
0429                                    r.x += Math.max(delta.width, r.width);
0430                                } else {
0431                                    r.x -= delta.width;
0432                                }
0433
0434                                int newColumn = table.columnAtPoint(r
0435                                        .getLocation());
0436                                if (newColumn == -1) {
0437                                    boolean ltr = table
0438                                            .getComponentOrientation()
0439                                            .isLeftToRight();
0440
0441                                    newColumn = forwards ? (ltr ? table
0442                                            .getColumnCount() : 0) : (ltr ? 0
0443                                            : table.getColumnCount());
0444
0445                                }
0446                                this .dx = newColumn - leadColumn;
0447                                this .dy = 0;
0448                            }
0449                        }
0450                    }
0451                    if (key == NEXT_ROW
0452                            || // Navigate Actions
0453                            key == NEXT_ROW_CELL
0454                            || key == NEXT_ROW_EXTEND_SELECTION
0455                            || key == NEXT_ROW_CHANGE_LEAD
0456                            || key == NEXT_COLUMN
0457                            || key == NEXT_COLUMN_CELL
0458                            || key == NEXT_COLUMN_EXTEND_SELECTION
0459                            || key == NEXT_COLUMN_CHANGE_LEAD
0460                            || key == PREVIOUS_ROW
0461                            || key == PREVIOUS_ROW_CELL
0462                            || key == PREVIOUS_ROW_EXTEND_SELECTION
0463                            || key == PREVIOUS_ROW_CHANGE_LEAD
0464                            || key == PREVIOUS_COLUMN
0465                            || key == PREVIOUS_COLUMN_CELL
0466                            || key == PREVIOUS_COLUMN_EXTEND_SELECTION
0467                            || key == PREVIOUS_COLUMN_CHANGE_LEAD
0468                            ||
0469                            // Paging Actions.
0470                            key == SCROLL_LEFT_CHANGE_SELECTION
0471                            || key == SCROLL_LEFT_EXTEND_SELECTION
0472                            || key == SCROLL_RIGHT_CHANGE_SELECTION
0473                            || key == SCROLL_RIGHT_EXTEND_SELECTION
0474                            || key == SCROLL_UP_CHANGE_SELECTION
0475                            || key == SCROLL_UP_EXTEND_SELECTION
0476                            || key == SCROLL_DOWN_CHANGE_SELECTION
0477                            || key == SCROLL_DOWN_EXTEND_SELECTION
0478                            || key == FIRST_COLUMN
0479                            || key == FIRST_COLUMN_EXTEND_SELECTION
0480                            || key == FIRST_ROW
0481                            || key == FIRST_ROW_EXTEND_SELECTION
0482                            || key == LAST_COLUMN
0483                            || key == LAST_COLUMN_EXTEND_SELECTION
0484                            || key == LAST_ROW
0485                            || key == LAST_ROW_EXTEND_SELECTION) {
0486
0487                        if (table.isEditing()
0488                                && !table.getCellEditor().stopCellEditing()) {
0489                            return;
0490                        }
0491
0492                        // Unfortunately, this strategy introduces bugs because
0493                        // of the asynchronous nature of requestFocus() call below.
0494                        // Introducing a delay with invokeLater() makes this work
0495                        // in the typical case though race conditions then allow
0496                        // focus to disappear altogether. The right solution appears
0497                        // to be to fix requestFocus() so that it queues a request
0498                        // for the focus regardless of who owns the focus at the
0499                        // time the call to requestFocus() is made. The optimisation
0500                        // to ignore the call to requestFocus() when the component
0501                        // already has focus may ligitimately be made as the
0502                        // request focus event is dequeued, not before.
0503
0504                        // boolean wasEditingWithFocus = table.isEditing() &&
0505                        // table.getEditorComponent().isFocusOwner();
0506
0507                        boolean changeLead = false;
0508                        if (key == NEXT_ROW_CHANGE_LEAD
0509                                || key == PREVIOUS_ROW_CHANGE_LEAD) {
0510                            changeLead = (rsm.getSelectionMode() == ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
0511                        } else if (key == NEXT_COLUMN_CHANGE_LEAD
0512                                || key == PREVIOUS_COLUMN_CHANGE_LEAD) {
0513                            changeLead = (csm.getSelectionMode() == ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
0514                        }
0515
0516                        if (changeLead) {
0517                            moveWithinTableRange(table, dx, dy);
0518                            if (dy != 0) {
0519                                // casting should be safe since the action is only enabled
0520                                // for DefaultListSelectionModel
0521                                ((DefaultListSelectionModel) rsm)
0522                                        .moveLeadSelectionIndex(leadRow);
0523                                if (getAdjustedLead(table, false, csm) == -1
0524                                        && table.getColumnCount() > 0) {
0525
0526                                    ((DefaultListSelectionModel) csm)
0527                                            .moveLeadSelectionIndex(0);
0528                                }
0529                            } else {
0530                                // casting should be safe since the action is only enabled
0531                                // for DefaultListSelectionModel
0532                                ((DefaultListSelectionModel) csm)
0533                                        .moveLeadSelectionIndex(leadColumn);
0534                                if (getAdjustedLead(table, true, rsm) == -1
0535                                        && table.getRowCount() > 0) {
0536
0537                                    ((DefaultListSelectionModel) rsm)
0538                                            .moveLeadSelectionIndex(0);
0539                                }
0540                            }
0541
0542                            Rectangle cellRect = table.getCellRect(leadRow,
0543                                    leadColumn, false);
0544                            if (cellRect != null) {
0545                                table.scrollRectToVisible(cellRect);
0546                            }
0547                        } else if (!inSelection) {
0548                            moveWithinTableRange(table, dx, dy);
0549                            table.changeSelection(leadRow, leadColumn, false,
0550                                    extend);
0551                        } else {
0552                            if (table.getRowCount() <= 0
0553                                    || table.getColumnCount() <= 0) {
0554                                // bail - don't try to move selection on an empty table
0555                                return;
0556                            }
0557
0558                            if (moveWithinSelectedRange(table, dx, dy, rsm, csm)) {
0559                                // this is the only way we have to set both the lead
0560                                // and the anchor without changing the selection
0561                                if (rsm.isSelectedIndex(leadRow)) {
0562                                    rsm.addSelectionInterval(leadRow, leadRow);
0563                                } else {
0564                                    rsm.removeSelectionInterval(leadRow,
0565                                            leadRow);
0566                                }
0567
0568                                if (csm.isSelectedIndex(leadColumn)) {
0569                                    csm.addSelectionInterval(leadColumn,
0570                                            leadColumn);
0571                                } else {
0572                                    csm.removeSelectionInterval(leadColumn,
0573                                            leadColumn);
0574                                }
0575
0576                                Rectangle cellRect = table.getCellRect(leadRow,
0577                                        leadColumn, false);
0578                                if (cellRect != null) {
0579                                    table.scrollRectToVisible(cellRect);
0580                                }
0581                            } else {
0582                                table.changeSelection(leadRow, leadColumn,
0583                                        false, false);
0584                            }
0585                        }
0586
0587                        /*
0588                        if (wasEditingWithFocus) {
0589                            table.editCellAt(leadRow, leadColumn);
0590                            final Component editorComp = table.getEditorComponent();
0591                            if (editorComp != null) {
0592                                SwingUtilities.invokeLater(new Runnable() {
0593                                    public void run() {
0594                                        editorComp.requestFocus();
0595                                    }
0596                                });
0597                            }
0598                        }
0599                         */
0600                    } else if (key == CANCEL_EDITING) {
0601                        table.removeEditor();
0602                    } else if (key == SELECT_ALL) {
0603                        table.selectAll();
0604                    } else if (key == CLEAR_SELECTION) {
0605                        table.clearSelection();
0606                    } else if (key == START_EDITING) {
0607                        if (!table.hasFocus()) {
0608                            CellEditor cellEditor = table.getCellEditor();
0609                            if (cellEditor != null
0610                                    && !cellEditor.stopCellEditing()) {
0611                                return;
0612                            }
0613                            table.requestFocus();
0614                            return;
0615                        }
0616                        table.editCellAt(leadRow, leadColumn, e);
0617                        Component editorComp = table.getEditorComponent();
0618                        if (editorComp != null) {
0619                            editorComp.requestFocus();
0620                        }
0621                    } else if (key == ADD_TO_SELECTION) {
0622                        if (!table.isCellSelected(leadRow, leadColumn)) {
0623                            int oldAnchorRow = rsm.getAnchorSelectionIndex();
0624                            int oldAnchorColumn = csm.getAnchorSelectionIndex();
0625                            rsm.setValueIsAdjusting(true);
0626                            csm.setValueIsAdjusting(true);
0627                            table.changeSelection(leadRow, leadColumn, true,
0628                                    false);
0629                            rsm.setAnchorSelectionIndex(oldAnchorRow);
0630                            csm.setAnchorSelectionIndex(oldAnchorColumn);
0631                            rsm.setValueIsAdjusting(false);
0632                            csm.setValueIsAdjusting(false);
0633                        }
0634                    } else if (key == TOGGLE_AND_ANCHOR) {
0635                        table.changeSelection(leadRow, leadColumn, true, false);
0636                    } else if (key == EXTEND_TO) {
0637                        table.changeSelection(leadRow, leadColumn, false, true);
0638                    } else if (key == MOVE_SELECTION_TO) {
0639                        table
0640                                .changeSelection(leadRow, leadColumn, false,
0641                                        false);
0642                    } else if (key == FOCUS_HEADER) {
0643                        JTableHeader th = table.getTableHeader();
0644                        if (th != null) {
0645                            //Set the header's selected column to match the table.
0646                            int col = table.getSelectedColumn();
0647                            if (col >= 0) {
0648                                TableHeaderUI thUI = th.getUI();
0649                                if (thUI instanceof  BasicTableHeaderUI) {
0650                                    ((BasicTableHeaderUI) thUI)
0651                                            .selectColumn(col);
0652                                }
0653                            }
0654
0655                            //Then give the header the focus.
0656                            th.requestFocusInWindow();
0657                        }
0658                    }
0659                }
0660
0661                public boolean isEnabled(Object sender) {
0662                    String key = getName();
0663
0664                    if (sender instanceof  JTable
0665                            && Boolean.TRUE.equals(((JTable) sender)
0666                                    .getClientProperty("Table.isFileList"))) {
0667                        if (key == NEXT_COLUMN || key == NEXT_COLUMN_CELL
0668                                || key == NEXT_COLUMN_EXTEND_SELECTION
0669                                || key == NEXT_COLUMN_CHANGE_LEAD
0670                                || key == PREVIOUS_COLUMN
0671                                || key == PREVIOUS_COLUMN_CELL
0672                                || key == PREVIOUS_COLUMN_EXTEND_SELECTION
0673                                || key == PREVIOUS_COLUMN_CHANGE_LEAD
0674                                || key == SCROLL_LEFT_CHANGE_SELECTION
0675                                || key == SCROLL_LEFT_EXTEND_SELECTION
0676                                || key == SCROLL_RIGHT_CHANGE_SELECTION
0677                                || key == SCROLL_RIGHT_EXTEND_SELECTION
0678                                || key == FIRST_COLUMN
0679                                || key == FIRST_COLUMN_EXTEND_SELECTION
0680                                || key == LAST_COLUMN
0681                                || key == LAST_COLUMN_EXTEND_SELECTION
0682                                || key == NEXT_ROW_CELL
0683                                || key == PREVIOUS_ROW_CELL) {
0684
0685                            return false;
0686                        }
0687                    }
0688
0689                    if (key == CANCEL_EDITING && sender instanceof  JTable) {
0690                        return ((JTable) sender).isEditing();
0691                    } else if (key == NEXT_ROW_CHANGE_LEAD
0692                            || key == PREVIOUS_ROW_CHANGE_LEAD) {
0693                        // discontinuous selection actions are only enabled for
0694                        // DefaultListSelectionModel
0695                        return sender != null
0696                                && ((JTable) sender).getSelectionModel() instanceof  DefaultListSelectionModel;
0697                    } else if (key == NEXT_COLUMN_CHANGE_LEAD
0698                            || key == PREVIOUS_COLUMN_CHANGE_LEAD) {
0699                        // discontinuous selection actions are only enabled for
0700                        // DefaultListSelectionModel
0701                        return sender != null
0702                                && ((JTable) sender).getColumnModel()
0703                                        .getSelectionModel() instanceof  DefaultListSelectionModel;
0704                    } else if (key == ADD_TO_SELECTION
0705                            && sender instanceof  JTable) {
0706                        // This action is typically bound to SPACE.
0707                        // If the table is already in an editing mode, SPACE should
0708                        // simply enter a space character into the table, and not
0709                        // select a cell. Likewise, if the lead cell is already selected
0710                        // then hitting SPACE should just enter a space character
0711                        // into the cell and begin editing. In both of these cases
0712                        // this action will be disabled.
0713                        JTable table = (JTable) sender;
0714                        int leadRow = getAdjustedLead(table, true);
0715                        int leadCol = getAdjustedLead(table, false);
0716                        return !(table.isEditing() || table.isCellSelected(
0717                                leadRow, leadCol));
0718                    } else if (key == FOCUS_HEADER && sender instanceof  JTable) {
0719                        JTable table = (JTable) sender;
0720                        return table.getTableHeader() != null;
0721                    }
0722
0723                    return true;
0724                }
0725            }
0726
0727            //
0728            //  The Table's Key listener
0729            //
0730
0731            /**
0732             * This inner class is marked &quot;public&quot; due to a compiler bug.
0733             * This class should be treated as a &quot;protected&quot; inner class.
0734             * Instantiate it only within subclasses of BasicTableUI.
0735             * <p>As of Java 2 platform v1.3 this class is no longer used.
0736             * Instead <code>JTable</code>
0737             * overrides <code>processKeyBinding</code> to dispatch the event to
0738             * the current <code>TableCellEditor</code>.
0739             */
0740            public class KeyHandler implements  KeyListener {
0741                // NOTE: This class exists only for backward compatability. All
0742                // its functionality has been moved into Handler. If you need to add
0743                // new functionality add it to the Handler, but make sure this      
0744                // class calls into the Handler.
0745                public void keyPressed(KeyEvent e) {
0746                    getHandler().keyPressed(e);
0747                }
0748
0749                public void keyReleased(KeyEvent e) {
0750                    getHandler().keyReleased(e);
0751                }
0752
0753                public void keyTyped(KeyEvent e) {
0754                    getHandler().keyTyped(e);
0755                }
0756            }
0757
0758            //
0759            //  The Table's focus listener
0760            //
0761
0762            /**
0763             * This inner class is marked &quot;public&quot; due to a compiler bug.
0764             * This class should be treated as a &quot;protected&quot; inner class.
0765             * Instantiate it only within subclasses of BasicTableUI.
0766             */
0767            public class FocusHandler implements  FocusListener {
0768                // NOTE: This class exists only for backward compatability. All
0769                // its functionality has been moved into Handler. If you need to add
0770                // new functionality add it to the Handler, but make sure this      
0771                // class calls into the Handler.
0772                public void focusGained(FocusEvent e) {
0773                    getHandler().focusGained(e);
0774                }
0775
0776                public void focusLost(FocusEvent e) {
0777                    getHandler().focusLost(e);
0778                }
0779            }
0780
0781            //
0782            //  The Table's mouse and mouse motion listeners
0783            //
0784
0785            /**
0786             * This inner class is marked &quot;public&quot; due to a compiler bug.
0787             * This class should be treated as a &quot;protected&quot; inner class.
0788             * Instantiate it only within subclasses of BasicTableUI.
0789             */
0790            public class MouseInputHandler implements  MouseInputListener {
0791                // NOTE: This class exists only for backward compatability. All
0792                // its functionality has been moved into Handler. If you need to add
0793                // new functionality add it to the Handler, but make sure this      
0794                // class calls into the Handler.
0795                public void mouseClicked(MouseEvent e) {
0796                    getHandler().mouseClicked(e);
0797                }
0798
0799                public void mousePressed(MouseEvent e) {
0800                    getHandler().mousePressed(e);
0801                }
0802
0803                public void mouseReleased(MouseEvent e) {
0804                    getHandler().mouseReleased(e);
0805                }
0806
0807                public void mouseEntered(MouseEvent e) {
0808                    getHandler().mouseEntered(e);
0809                }
0810
0811                public void mouseExited(MouseEvent e) {
0812                    getHandler().mouseExited(e);
0813                }
0814
0815                public void mouseMoved(MouseEvent e) {
0816                    getHandler().mouseMoved(e);
0817                }
0818
0819                public void mouseDragged(MouseEvent e) {
0820                    getHandler().mouseDragged(e);
0821                }
0822            }
0823
0824            private class Handler implements  FocusListener, MouseInputListener,
0825                    PropertyChangeListener, ListSelectionListener,
0826                    ActionListener, BeforeDrag {
0827
0828                // FocusListener
0829                private void repaintLeadCell() {
0830                    int lr = getAdjustedLead(table, true);
0831                    int lc = getAdjustedLead(table, false);
0832
0833                    if (lr < 0 || lc < 0) {
0834                        return;
0835                    }
0836
0837                    Rectangle dirtyRect = table.getCellRect(lr, lc, false);
0838                    table.repaint(dirtyRect);
0839                }
0840
0841                public void focusGained(FocusEvent e) {
0842                    repaintLeadCell();
0843                }
0844
0845                public void focusLost(FocusEvent e) {
0846                    repaintLeadCell();
0847                }
0848
0849                // KeyListener
0850                public void keyPressed(KeyEvent e) {
0851                }
0852
0853                public void keyReleased(KeyEvent e) {
0854                }
0855
0856                public void keyTyped(KeyEvent e) {
0857                    KeyStroke keyStroke = KeyStroke.getKeyStroke(
0858                            e.getKeyChar(), e.getModifiers());
0859
0860                    // We register all actions using ANCESTOR_OF_FOCUSED_COMPONENT
0861                    // which means that we might perform the appropriate action
0862                    // in the table and then forward it to the editor if the editor
0863                    // had focus. Make sure this doesn't happen by checking our
0864                    // InputMaps.
0865                    InputMap map = table.getInputMap(JComponent.WHEN_FOCUSED);
0866                    if (map != null && map.get(keyStroke) != null) {
0867                        return;
0868                    }
0869                    map = table
0870                            .getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
0871                    if (map != null && map.get(keyStroke) != null) {
0872                        return;
0873                    }
0874
0875                    keyStroke = KeyStroke.getKeyStrokeForEvent(e);
0876
0877                    // The AWT seems to generate an unconsumed \r event when
0878                    // ENTER (\n) is pressed.
0879                    if (e.getKeyChar() == '\r') {
0880                        return;
0881                    }
0882
0883                    int leadRow = getAdjustedLead(table, true);
0884                    int leadColumn = getAdjustedLead(table, false);
0885                    if (leadRow != -1 && leadColumn != -1 && !table.isEditing()) {
0886                        if (!table.editCellAt(leadRow, leadColumn)) {
0887                            return;
0888                        }
0889                    }
0890
0891                    // Forwarding events this way seems to put the component
0892                    // in a state where it believes it has focus. In reality
0893                    // the table retains focus - though it is difficult for
0894                    // a user to tell, since the caret is visible and flashing.
0895
0896                    // Calling table.requestFocus() here, to get the focus back to
0897                    // the table, seems to have no effect.
0898
0899                    Component editorComp = table.getEditorComponent();
0900                    if (table.isEditing() && editorComp != null) {
0901                        if (editorComp instanceof  JComponent) {
0902                            JComponent component = (JComponent) editorComp;
0903                            map = component
0904                                    .getInputMap(JComponent.WHEN_FOCUSED);
0905                            Object binding = (map != null) ? map.get(keyStroke)
0906                                    : null;
0907                            if (binding == null) {
0908                                map = component
0909                                        .getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
0910                                binding = (map != null) ? map.get(keyStroke)
0911                                        : null;
0912                            }
0913                            if (binding != null) {
0914                                ActionMap am = component.getActionMap();
0915                                Action action = (am != null) ? am.get(binding)
0916                                        : null;
0917                                if (action != null
0918                                        && SwingUtilities.notifyAction(action,
0919                                                keyStroke, e, component, e
0920                                                        .getModifiers())) {
0921                                    e.consume();
0922                                }
0923                            }
0924                        }
0925                    }
0926                }
0927
0928                // MouseInputListener
0929
0930                // Component receiving mouse events during editing.
0931                // May not be editorComponent.
0932                private Component dispatchComponent;
0933
0934                public void mouseClicked(MouseEvent e) {
0935                }
0936
0937                private void setDispatchComponent(MouseEvent e) {
0938                    Component editorComponent = table.getEditorComponent();
0939                    Point p = e.getPoint();
0940                    Point p2 = SwingUtilities.convertPoint(table, p,
0941                            editorComponent);
0942                    dispatchComponent = SwingUtilities.getDeepestComponentAt(
0943                            editorComponent, p2.x, p2.y);
0944                    SwingUtilities2.setSkipClickCount(dispatchComponent, e
0945                            .getClickCount() - 1);
0946                }
0947
0948                private boolean repostEvent(MouseEvent e) {
0949                    // Check for isEditing() in case another event has
0950                    // caused the editor to be removed. See bug #4306499.
0951                    if (dispatchComponent == null || !table.isEditing()) {
0952                        return false;
0953                    }
0954                    MouseEvent e2 = SwingUtilities.convertMouseEvent(table, e,
0955                            dispatchComponent);
0956                    dispatchComponent.dispatchEvent(e2);
0957                    return true;
0958                }
0959
0960                private void setValueIsAdjusting(boolean flag) {
0961                    table.getSelectionModel().setValueIsAdjusting(flag);
0962                    table.getColumnModel().getSelectionModel()
0963                            .setValueIsAdjusting(flag);
0964                }
0965
0966                // The row and column where the press occurred and the
0967                // press event itself
0968                private int pressedRow;
0969                private int pressedCol;
0970                private MouseEvent pressedEvent;
0971
0972                // Whether or not the mouse press (which is being considered as part
0973                // of a drag sequence) also caused the selection change to be fully
0974                // processed.
0975                private boolean dragPressDidSelection;
0976
0977                // Set to true when a drag gesture has been fully recognized and DnD
0978                // begins. Use this to ignore further mouse events which could be
0979                // delivered if DnD is cancelled (via ESCAPE for example)
0980                private boolean dragStarted;
0981
0982                // Whether or not we should start the editing timer on release
0983                private boolean shouldStartTimer;
0984
0985                // To cache the return value of pointOutsidePrefSize since we use
0986                // it multiple times.
0987                private boolean outsidePrefSize;
0988
0989                // Used to delay the start of editing.
0990                private Timer timer = null;
0991
0992                private boolean canStartDrag() {
0993                    if (pressedRow == -1 || pressedCol == -1) {
0994                        return false;
0995                    }
0996
0997                    if (isFileList) {
0998                        return !outsidePrefSize;
0999                    }
1000
1001                    // if this is a single selection table
1002                    if ((table.getSelectionModel().getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)
1003                            && (table.getColumnModel().getSelectionModel()
1004                                    .getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)) {
1005
1006                        return true;
1007                    }
1008
1009                    return table.isCellSelected(pressedRow, pressedCol);
1010                }
1011
1012                public void mousePressed(MouseEvent e) {
1013                    if (SwingUtilities2.shouldIgnore(e, table)) {
1014                        return;
1015                    }
1016
1017                    if (table.isEditing()
1018                            && !table.getCellEditor().stopCellEditing()) {
1019                        Component editorComponent = table.getEditorComponent();
1020                        if (editorComponent != null
1021                                && !editorComponent.hasFocus()) {
1022                            SwingUtilities2
1023                                    .compositeRequestFocus(editorComponent);
1024                        }
1025                        return;
1026                    }
1027
1028                    Point p = e.getPoint();
1029                    pressedRow = table.rowAtPoint(p);
1030                    pressedCol = table.columnAtPoint(p);
1031                    outsidePrefSize = pointOutsidePrefSize(pressedRow,
1032                            pressedCol, p);
1033
1034                    if (isFileList) {
1035                        shouldStartTimer = table.isCellSelected(pressedRow,
1036                                pressedCol)
1037                                && !e.isShiftDown()
1038                                && !e.isControlDown()
1039                                && !outsidePrefSize;
1040                    }
1041
1042                    if (table.getDragEnabled()) {
1043                        mousePressedDND(e);
1044                    } else {
1045                        SwingUtilities2.adjustFocus(table);
1046                        if (!isFileList) {
1047                            setValueIsAdjusting(true);
1048                        }
1049                        adjustSelection(e);
1050                    }
1051                }
1052
1053                private void mousePressedDND(MouseEvent e) {
1054                    pressedEvent = e;
1055                    boolean grabFocus = true;
1056                    dragStarted = false;
1057
1058                    if (canStartDrag()
1059                            && DragRecognitionSupport.mousePressed(e)) {
1060
1061                        dragPressDidSelection = false;
1062
1063                        if (e.isControlDown() && isFileList) {
1064                            // do nothing for control - will be handled on release
1065                            // or when drag starts
1066                            return;
1067                        } else if (!e.isShiftDown()
1068                                && table.isCellSelected(pressedRow, pressedCol)) {
1069                            // clicking on something that's already selected
1070                            // and need to make it the lead now
1071                            table.getSelectionModel().addSelectionInterval(
1072                                    pressedRow, pressedRow);
1073                            table.getColumnModel().getSelectionModel()
1074                                    .addSelectionInterval(pressedCol,
1075                                            pressedCol);
1076
1077                            return;
1078                        }
1079
1080                        dragPressDidSelection = true;
1081
1082                        // could be a drag initiating event - don't grab focus
1083                        grabFocus = false;
1084                    } else if (!isFileList) {
1085                        // When drag can't happen, mouse drags might change the selection in the table
1086                        // so we want the isAdjusting flag to be set
1087                        setValueIsAdjusting(true);
1088                    }
1089
1090                    if (grabFocus) {
1091                        SwingUtilities2.adjustFocus(table);
1092                    }
1093
1094                    adjustSelection(e);
1095                }
1096
1097                private void adjustSelection(MouseEvent e) {
1098                    // Fix for 4835633
1099                    if (outsidePrefSize) {
1100                        // If shift is down in multi-select, we should just return.
1101                        // For single select or non-shift-click, clear the selection
1102                        if (e.getID() == MouseEvent.MOUSE_PRESSED
1103                                && (!e.isShiftDown() || table
1104                                        .getSelectionModel().getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)) {
1105                            table.clearSelection();
1106                            TableCellEditor tce = table.getCellEditor();
1107                            if (tce != null) {
1108                                tce.stopCellEditing();
1109                            }
1110                        }
1111                        return;
1112                    }
1113                    // The autoscroller can generate drag events outside the
1114                    // table's range.
1115                    if ((pressedCol == -1) || (pressedRow == -1)) {
1116                        return;
1117                    }
1118
1119                    boolean dragEnabled = table.getDragEnabled();
1120
1121                    if (!dragEnabled && !isFileList
1122                            && table.editCellAt(pressedRow, pressedCol, e)) {
1123                        setDispatchComponent(e);
1124                        repostEvent(e);
1125                    }
1126
1127                    CellEditor editor = table.getCellEditor();
1128                    if (dragEnabled || editor == null
1129                            || editor.shouldSelectCell(e)) {
1130                        table.changeSelection(pressedRow, pressedCol, e
1131                                .isControlDown(), e.isShiftDown());
1132                    }
1133                }
1134
1135                public void valueChanged(ListSelectionEvent e) {
1136                    if (timer != null) {
1137                        timer.stop();
1138                        timer = null;
1139                    }
1140                }
1141
1142                public void actionPerformed(ActionEvent ae) {
1143                    table.editCellAt(pressedRow, pressedCol, null);
1144                    Component editorComponent = table.getEditorComponent();
1145                    if (editorComponent != null && !editorComponent.hasFocus()) {
1146                        SwingUtilities2.compositeRequestFocus(editorComponent);
1147                    }
1148                    return;
1149                }
1150
1151                private void maybeStartTimer() {
1152                    if (!shouldStartTimer) {
1153                        return;
1154                    }
1155
1156                    if (timer == null) {
1157                        timer = new Timer(1200, this );
1158                        timer.setRepeats(false);
1159                    }
1160
1161                    timer.start();
1162                }
1163
1164                public void mouseReleased(MouseEvent e) {
1165                    if (SwingUtilities2.shouldIgnore(e, table)) {
1166                        return;
1167                    }
1168
1169                    if (table.getDragEnabled()) {
1170                        mouseReleasedDND(e);
1171                    } else {
1172                        if (isFileList) {
1173                            maybeStartTimer();
1174                        }
1175                    }
1176
1177                    pressedEvent = null;
1178                    repostEvent(e);
1179                    dispatchComponent = null;
1180                    setValueIsAdjusting(false);
1181                }
1182
1183                private void mouseReleasedDND(MouseEvent e) {
1184                    MouseEvent me = DragRecognitionSupport.mouseReleased(e);
1185                    if (me != null) {
1186                        SwingUtilities2.adjustFocus(table);
1187                        if (!dragPressDidSelection) {
1188                            adjustSelection(me);
1189                        }
1190                    }
1191
1192                    if (!dragStarted) {
1193                        if (isFileList) {
1194                            maybeStartTimer();
1195                            return;
1196                        }
1197
1198                        Point p = e.getPoint();
1199
1200                        if (pressedEvent != null
1201                                && table.rowAtPoint(p) == pressedRow
1202                                && table.columnAtPoint(p) == pressedCol
1203                                && table.editCellAt(pressedRow, pressedCol,
1204                                        pressedEvent)) {
1205
1206                            setDispatchComponent(pressedEvent);
1207                            repostEvent(pressedEvent);
1208
1209                            // This may appear completely odd, but must be done for backward
1210                            // compatibility reasons. Developers have been known to rely on
1211                            // a call to shouldSelectCell after editing has begun.
1212                            CellEditor ce = table.getCellEditor();
1213                            if (ce != null) {
1214                                ce.shouldSelectCell(pressedEvent);
1215                            }
1216                        }
1217                    }
1218                }
1219
1220                public void mouseEntered(MouseEvent e) {
1221                }
1222
1223                public void mouseExited(MouseEvent e) {
1224                }
1225
1226                public void mouseMoved(MouseEvent e) {
1227                }
1228
1229                public void dragStarting(MouseEvent me) {
1230                    dragStarted = true;
1231
1232                    if (me.isControlDown() && isFileList) {
1233                        table.getSelectionModel().addSelectionInterval(
1234                                pressedRow, pressedRow);
1235                        table.getColumnModel().getSelectionModel()
1236                                .addSelectionInterval(pressedCol, pressedCol);
1237                    }
1238
1239                    pressedEvent = null;
1240                }
1241
1242                public void mouseDragged(MouseEvent e) {
1243                    if (SwingUtilities2.shouldIgnore(e, table)) {
1244                        return;
1245                    }
1246
1247                    if (table.getDragEnabled()
1248                            && (DragRecognitionSupport.mouseDragged(e, this ) || dragStarted)) {
1249
1250                        return;
1251                    }
1252
1253                    repostEvent(e);
1254
1255                    // Check isFileList:
1256                    // Until we support drag-selection, dragging should not change
1257                    // the selection (act like single-select).
1258                    if (isFileList || table.isEditing()) {
1259                        return;
1260                    }
1261
1262                    Point p = e.getPoint();
1263                    int row = table.rowAtPoint(p);
1264                    int column = table.columnAtPoint(p);
1265                    // The autoscroller can generate drag events outside the
1266                    // table's range.
1267                    if ((column == -1) || (row == -1)) {
1268                        return;
1269                    }
1270
1271                    table.changeSelection(row, column, e.isControlDown(), true);
1272                }
1273
1274                // PropertyChangeListener
1275                public void propertyChange(PropertyChangeEvent event) {
1276                    String changeName = event.getPropertyName();
1277
1278                    if ("componentOrientation" == changeName) {
1279                        InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
1280
1281                        SwingUtilities.replaceUIInputMap(table,
1282                                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
1283                                inputMap);
1284
1285                        JTableHeader header = table.getTableHeader();
1286                        if (header != null) {
1287                            header
1288                                    .setComponentOrientation((ComponentOrientation) event
1289                                            .getNewValue());
1290                        }
1291                    } else if ("dropLocation" == changeName) {
1292                        JTable.DropLocation oldValue = (JTable.DropLocation) event
1293                                .getOldValue();
1294                        repaintDropLocation(oldValue);
1295                        repaintDropLocation(table.getDropLocation());
1296                    } else if ("Table.isFileList" == changeName) {
1297                        isFileList = Boolean.TRUE.equals(table
1298                                .getClientProperty("Table.isFileList"));
1299                        table.revalidate();
1300                        table.repaint();
1301                        if (isFileList) {
1302                            table.getSelectionModel().addListSelectionListener(
1303                                    getHandler());
1304                        } else {
1305                            table.getSelectionModel()
1306                                    .removeListSelectionListener(getHandler());
1307                            timer = null;
1308                        }
1309                    } else if ("selectionModel" == changeName) {
1310                        if (isFileList) {
1311                            ListSelectionModel old = (ListSelectionModel) event
1312                                    .getOldValue();
1313                            old.removeListSelectionListener(getHandler());
1314                            table.getSelectionModel().addListSelectionListener(
1315                                    getHandler());
1316                        }
1317                    }
1318                }
1319
1320                private void repaintDropLocation(JTable.DropLocation loc) {
1321                    if (loc == null) {
1322                        return;
1323                    }
1324
1325                    if (!loc.isInsertRow() && !loc.isInsertColumn()) {
1326                        Rectangle rect = table.getCellRect(loc.getRow(), loc
1327                                .getColumn(), false);
1328                        if (rect != null) {
1329                            table.repaint(rect);
1330                        }
1331                        return;
1332                    }
1333
1334                    if (loc.isInsertRow()) {
1335                        Rectangle rect = extendRect(getHDropLineRect(loc), true);
1336                        if (rect != null) {
1337                            table.repaint(rect);
1338                        }
1339                    }
1340
1341                    if (loc.isInsertColumn()) {
1342                        Rectangle rect = extendRect(getVDropLineRect(loc),
1343                                false);
1344                        if (rect != null) {
1345                            table.repaint(rect);
1346                        }
1347                    }
1348                }
1349            }
1350
1351            /*
1352             * Returns true if the given point is outside the preferredSize of the
1353             * item at the given row of the table.  (Column must be 0).
1354             * Returns false if the "Table.isFileList" client property is not set.
1355             */
1356            private boolean pointOutsidePrefSize(int row, int column, Point p) {
1357                if (!isFileList) {
1358                    return false;
1359                }
1360
1361                return SwingUtilities2.pointOutsidePrefSize(table, row, column,
1362                        p);
1363            }
1364
1365            //
1366            //  Factory methods for the Listeners
1367            //
1368
1369            private Handler getHandler() {
1370                if (handler == null) {
1371                    handler = new Handler();
1372                }
1373                return handler;
1374            }
1375
1376            /**
1377             * Creates the key listener for handling keyboard navigation in the JTable.
1378             */
1379            protected KeyListener createKeyListener() {
1380                return null;
1381            }
1382
1383            /**
1384             * Creates the focus listener for handling keyboard navigation in the JTable.
1385             */
1386            protected FocusListener createFocusListener() {
1387                return getHandler();
1388            }
1389
1390            /**
1391             * Creates the mouse listener for the JTable.
1392             */
1393            protected MouseInputListener createMouseInputListener() {
1394                return getHandler();
1395            }
1396
1397            //
1398            //  The installation/uninstall procedures and support
1399            //
1400
1401            public static ComponentUI createUI(JComponent c) {
1402                return new BasicTableUI();
1403            }
1404
1405            //  Installation
1406
1407            public void installUI(JComponent c) {
1408                table = (JTable) c;
1409
1410                rendererPane = new CellRendererPane();
1411                table.add(rendererPane);
1412                installDefaults();
1413                installDefaults2();
1414                installListeners();
1415                installKeyboardActions();
1416            }
1417
1418            /**
1419             * Initialize JTable properties, e.g. font, foreground, and background.
1420             * The font, foreground, and background properties are only set if their
1421             * current value is either null or a UIResource, other properties are set
1422             * if the current value is null.
1423             *
1424             * @see #installUI
1425             */
1426            protected void installDefaults() {
1427                LookAndFeel.installColorsAndFont(table, "Table.background",
1428                        "Table.foreground", "Table.font");
1429                // JTable's original row height is 16.  To correctly display the
1430                // contents on Linux we should have set it to 18, Windows 19 and
1431                // Solaris 20.  As these values vary so much it's too hard to
1432                // be backward compatable and try to update the row height, we're
1433                // therefor NOT going to adjust the row height based on font.  If the
1434                // developer changes the font, it's there responsability to update
1435                // the row height.
1436
1437                LookAndFeel.installProperty(table, "opaque", Boolean.TRUE);
1438
1439                Color sbg = table.getSelectionBackground();
1440                if (sbg == null || sbg instanceof  UIResource) {
1441                    table.setSelectionBackground(UIManager
1442                            .getColor("Table.selectionBackground"));
1443                }
1444
1445                Color sfg = table.getSelectionForeground();
1446                if (sfg == null || sfg instanceof  UIResource) {
1447                    table.setSelectionForeground(UIManager
1448                            .getColor("Table.selectionForeground"));
1449                }
1450
1451                Color gridColor = table.getGridColor();
1452                if (gridColor == null || gridColor instanceof  UIResource) {
1453                    table.setGridColor(UIManager.getColor("Table.gridColor"));
1454                }
1455
1456                // install the scrollpane border
1457                Container parent = table.getParent(); // should be viewport
1458                if (parent != null) {
1459                    parent = parent.getParent(); // should be the scrollpane
1460                    if (parent != null && parent instanceof  JScrollPane) {
1461                        LookAndFeel.installBorder((JScrollPane) parent,
1462                                "Table.scrollPaneBorder");
1463                    }
1464                }
1465
1466                isFileList = Boolean.TRUE.equals(table
1467                        .getClientProperty("Table.isFileList"));
1468            }
1469
1470            private void installDefaults2() {
1471                TransferHandler th = table.getTransferHandler();
1472                if (th == null || th instanceof  UIResource) {
1473                    table.setTransferHandler(defaultTransferHandler);
1474                    // default TransferHandler doesn't support drop
1475                    // so we don't want drop handling
1476                    if (table.getDropTarget() instanceof  UIResource) {
1477                        table.setDropTarget(null);
1478                    }
1479                }
1480            }
1481
1482            /**
1483             * Attaches listeners to the JTable.
1484             */
1485            protected void installListeners() {
1486                focusListener = createFocusListener();
1487                keyListener = createKeyListener();
1488                mouseInputListener = createMouseInputListener();
1489
1490                table.addFocusListener(focusListener);
1491                table.addKeyListener(keyListener);
1492                table.addMouseListener(mouseInputListener);
1493                table.addMouseMotionListener(mouseInputListener);
1494                table.addPropertyChangeListener(getHandler());
1495                if (isFileList) {
1496                    table.getSelectionModel().addListSelectionListener(
1497                            getHandler());
1498                }
1499            }
1500
1501            /**
1502             * Register all keyboard actions on the JTable.
1503             */
1504            protected void installKeyboardActions() {
1505                LazyActionMap.installLazyActionMap(table, BasicTableUI.class,
1506                        "Table.actionMap");
1507
1508                InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
1509                SwingUtilities
1510                        .replaceUIInputMap(table,
1511                                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
1512                                inputMap);
1513            }
1514
1515            InputMap getInputMap(int condition) {
1516                if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
1517                    InputMap keyMap = (InputMap) DefaultLookup.get(table, this ,
1518                            "Table.ancestorInputMap");
1519                    InputMap rtlKeyMap;
1520
1521                    if (table.getComponentOrientation().isLeftToRight()
1522                            || ((rtlKeyMap = (InputMap) DefaultLookup.get(
1523                                    table, this ,
1524                                    "Table.ancestorInputMap.RightToLeft")) == null)) {
1525                        return keyMap;
1526                    } else {
1527                        rtlKeyMap.setParent(keyMap);
1528                        return rtlKeyMap;
1529                    }
1530                }
1531                return null;
1532            }
1533
1534            static void loadActionMap(LazyActionMap map) {
1535                // IMPORTANT: There is a very close coupling between the parameters
1536                // passed to the Actions constructor. Only certain parameter
1537                // combinations are supported. For example, the following Action would
1538                // not work as expected:
1539                //     new Actions(Actions.NEXT_ROW_CELL, 1, 4, false, true)
1540                // Actions which move within the selection only (having a true
1541                // inSelection parameter) require that one of dx or dy be
1542                // zero and the other be -1 or 1. The point of this warning is
1543                // that you should be very careful about making sure a particular
1544                // combination of parameters is supported before changing or
1545                // adding anything here.
1546
1547                map.put(new Actions(Actions.NEXT_COLUMN, 1, 0, false, false));
1548                map.put(new Actions(Actions.NEXT_COLUMN_CHANGE_LEAD, 1, 0,
1549                        false, false));
1550                map.put(new Actions(Actions.PREVIOUS_COLUMN, -1, 0, false,
1551                        false));
1552                map.put(new Actions(Actions.PREVIOUS_COLUMN_CHANGE_LEAD, -1, 0,
1553                        false, false));
1554                map.put(new Actions(Actions.NEXT_ROW, 0, 1, false, false));
1555                map.put(new Actions(Actions.NEXT_ROW_CHANGE_LEAD, 0, 1, false,
1556                        false));
1557                map.put(new Actions(Actions.PREVIOUS_ROW, 0, -1, false, false));
1558                map.put(new Actions(Actions.PREVIOUS_ROW_CHANGE_LEAD, 0, -1,
1559                        false, false));
1560                map.put(new Actions(Actions.NEXT_COLUMN_EXTEND_SELECTION, 1, 0,
1561                        true, false));
1562                map.put(new Actions(Actions.PREVIOUS_COLUMN_EXTEND_SELECTION,
1563                        -1, 0, true, false));
1564                map.put(new Actions(Actions.NEXT_ROW_EXTEND_SELECTION, 0, 1,
1565                        true, false));
1566                map.put(new Actions(Actions.PREVIOUS_ROW_EXTEND_SELECTION, 0,
1567                        -1, true, false));
1568                map.put(new Actions(Actions.SCROLL_UP_CHANGE_SELECTION, false,
1569                        false, true, false));
1570                map.put(new Actions(Actions.SCROLL_DOWN_CHANGE_SELECTION,
1571                        false, true, true, false));
1572                map.put(new Actions(Actions.FIRST_COLUMN, false, false, false,
1573                        true));
1574                map.put(new Actions(Actions.LAST_COLUMN, false, true, false,
1575                        true));
1576
1577                map.put(new Actions(Actions.SCROLL_UP_EXTEND_SELECTION, true,
1578                        false, true, false));
1579                map.put(new Actions(Actions.SCROLL_DOWN_EXTEND_SELECTION, true,
1580                        true, true, false));
1581                map.put(new Actions(Actions.FIRST_COLUMN_EXTEND_SELECTION,
1582                        true, false, false, true));
1583                map.put(new Actions(Actions.LAST_COLUMN_EXTEND_SELECTION, true,
1584                        true, false, true));
1585
1586                map
1587                        .put(new Actions(Actions.FIRST_ROW, false, false, true,
1588                                true));
1589                map.put(new Actions(Actions.LAST_ROW, false, true, true, true));
1590
1591                map.put(new Actions(Actions.FIRST_ROW_EXTEND_SELECTION, true,
1592                        false, true, true));
1593                map.put(new Actions(Actions.LAST_ROW_EXTEND_SELECTION, true,
1594                        true, true, true));
1595
1596                map
1597                        .put(new Actions(Actions.NEXT_COLUMN_CELL, 1, 0, false,
1598                                true));
1599                map.put(new Actions(Actions.PREVIOUS_COLUMN_CELL, -1, 0, false,
1600                        true));
1601                map.put(new Actions(Actions.NEXT_ROW_CELL, 0, 1, false, true));
1602                map.put(new Actions(Actions.PREVIOUS_ROW_CELL, 0, -1, false,
1603                        true));
1604
1605                map.put(new Actions(Actions.SELECT_ALL));
1606                map.put(new Actions(Actions.CLEAR_SELECTION));
1607                map.put(new Actions(Actions.CANCEL_EDITING));
1608                map.put(new Actions(Actions.START_EDITING));
1609
1610                map.put(TransferHandler.getCutAction().getValue(Action.NAME),
1611                        TransferHandler.getCutAction());
1612                map.put(TransferHandler.getCopyAction().getValue(Action.NAME),
1613                        TransferHandler.getCopyAction());
1614                map.put(TransferHandler.getPasteAction().getValue(Action.NAME),
1615                        TransferHandler.getPasteAction());
1616
1617                map.put(new Actions(Actions.SCROLL_LEFT_CHANGE_SELECTION,
1618                        false, false, false, false));
1619                map.put(new Actions(Actions.SCROLL_RIGHT_CHANGE_SELECTION,
1620                        false, true, false, false));
1621                map.put(new Actions(Actions.SCROLL_LEFT_EXTEND_SELECTION, true,
1622                        false, false, false));
1623                map.put(new Actions(Actions.SCROLL_RIGHT_EXTEND_SELECTION,
1624                        true, true, false, false));
1625
1626                map.put(new Actions(Actions.ADD_TO_SELECTION));
1627                map.put(new Actions(Actions.TOGGLE_AND_ANCHOR));
1628                map.put(new Actions(Actions.EXTEND_TO));
1629                map.put(new Actions(Actions.MOVE_SELECTION_TO));
1630                map.put(new Actions(Actions.FOCUS_HEADER));
1631            }
1632
1633            //  Uninstallation
1634
1635            public void uninstallUI(JComponent c) {
1636                uninstallDefaults();
1637                uninstallListeners();
1638                uninstallKeyboardActions();
1639
1640                table.remove(rendererPane);
1641                rendererPane = null;
1642                table = null;
1643            }
1644
1645            protected void uninstallDefaults() {
1646                if (table.getTransferHandler() instanceof  UIResource) {
1647                    table.setTransferHandler(null);
1648                }
1649            }
1650
1651            protected void uninstallListeners() {
1652                table.removeFocusListener(focusListener);
1653                table.removeKeyListener(keyListener);
1654                table.removeMouseListener(mouseInputListener);
1655                table.removeMouseMotionListener(mouseInputListener);
1656                table.removePropertyChangeListener(getHandler());
1657                if (isFileList) {
1658                    table.getSelectionModel().removeListSelectionListener(
1659                            getHandler());
1660                }
1661
1662                focusListener = null;
1663                keyListener = null;
1664                mouseInputListener = null;
1665                handler = null;
1666            }
1667
1668            protected void uninstallKeyboardActions() {
1669                SwingUtilities.replaceUIInputMap(table,
1670                        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
1671                SwingUtilities.replaceUIActionMap(table, null);
1672            }
1673
1674            /**
1675             * Returns the baseline.
1676             *
1677             * @throws NullPointerException {@inheritDoc}
1678             * @throws IllegalArgumentException {@inheritDoc}
1679             * @see javax.swing.JComponent#getBaseline(int, int)
1680             * @since 1.6
1681             */
1682            public int getBaseline(JComponent c, int width, int height) {
1683                super .getBaseline(c, width, height);
1684                UIDefaults lafDefaults = UIManager.getLookAndFeelDefaults();
1685                Component renderer = (Component) lafDefaults
1686                        .get(BASELINE_COMPONENT_KEY);
1687                if (renderer == null) {
1688                    DefaultTableCellRenderer tcr = new DefaultTableCellRenderer();
1689                    renderer = tcr.getTableCellRendererComponent(table, "a",
1690                            false, false, -1, -1);
1691                    lafDefaults.put(BASELINE_COMPONENT_KEY, renderer);
1692                }
1693                renderer.setFont(table.getFont());
1694                int rowMargin = table.getRowMargin();
1695                return renderer.getBaseline(Integer.MAX_VALUE, table
1696                        .getRowHeight()
1697                        - rowMargin)
1698                        + rowMargin / 2;
1699            }
1700
1701            /**
1702             * Returns an enum indicating how the baseline of the component
1703             * changes as the size changes.
1704             *
1705             * @throws NullPointerException {@inheritDoc}
1706             * @see javax.swing.JComponent#getBaseline(int, int)
1707             * @since 1.6
1708             */
1709            public Component.BaselineResizeBehavior getBaselineResizeBehavior(
1710                    JComponent c) {
1711                super .getBaselineResizeBehavior(c);
1712                return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
1713            }
1714
1715            //
1716            // Size Methods
1717            //
1718
1719            private Dimension createTableSize(long width) {
1720                int height = 0;
1721                int rowCount = table.getRowCount();
1722                if (rowCount > 0 && table.getColumnCount() > 0) {
1723                    Rectangle r = table.getCellRect(rowCount - 1, 0, true);
1724                    height = r.y + r.height;
1725                }
1726                // Width is always positive. The call to abs() is a workaround for
1727                // a bug in the 1.1.6 JIT on Windows.
1728                long tmp = Math.abs(width);
1729                if (tmp > Integer.MAX_VALUE) {
1730                    tmp = Integer.MAX_VALUE;
1731                }
1732                return new Dimension((int) tmp, height);
1733            }
1734
1735            /**
1736             * Return the minimum size of the table. The minimum height is the
1737             * row height times the number of rows.
1738             * The minimum width is the sum of the minimum widths of each column.
1739             */
1740            public Dimension getMinimumSize(JComponent c) {
1741                long width = 0;
1742                Enumeration enumeration = table.getColumnModel().getColumns();
1743                while (enumeration.hasMoreElements()) {
1744                    TableColumn aColumn = (TableColumn) enumeration
1745                            .nextElement();
1746                    width = width + aColumn.getMinWidth();
1747                }
1748                return createTableSize(width);
1749            }
1750
1751            /**
1752             * Return the preferred size of the table. The preferred height is the
1753             * row height times the number of rows.
1754             * The preferred width is the sum of the preferred widths of each column.
1755             */
1756            public Dimension getPreferredSize(JComponent c) {
1757                long width = 0;
1758                Enumeration enumeration = table.getColumnModel().getColumns();
1759                while (enumeration.hasMoreElements()) {
1760                    TableColumn aColumn = (TableColumn) enumeration
1761                            .nextElement();
1762                    width = width + aColumn.getPreferredWidth();
1763                }
1764                return createTableSize(width);
1765            }
1766
1767            /**
1768             * Return the maximum size of the table. The maximum height is the
1769             * row heighttimes the number of rows.
1770             * The maximum width is the sum of the maximum widths of each column.
1771             */
1772            public Dimension getMaximumSize(JComponent c) {
1773                long width = 0;
1774                Enumeration enumeration = table.getColumnModel().getColumns();
1775                while (enumeration.hasMoreElements()) {
1776                    TableColumn aColumn = (TableColumn) enumeration
1777                            .nextElement();
1778                    width = width + aColumn.getMaxWidth();
1779                }
1780                return createTableSize(width);
1781            }
1782
1783            //
1784            //  Paint methods and support
1785            //
1786
1787            /** Paint a representation of the <code>table</code> instance
1788             * that was set in installUI().
1789             */
1790            public void paint(Graphics g, JComponent c) {
1791                Rectangle clip = g.getClipBounds();
1792
1793                Rectangle bounds = table.getBounds();
1794                // account for the fact that the graphics has already been translated
1795                // into the table's bounds
1796                bounds.x = bounds.y = 0;
1797
1798                if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
1799                // this check prevents us from painting the entire table
1800                        // when the clip doesn't intersect our bounds at all
1801                        !bounds.intersects(clip)) {
1802
1803                    paintDropLines(g);
1804                    return;
1805                }
1806
1807                boolean ltr = table.getComponentOrientation().isLeftToRight();
1808
1809                Point upperLeft = clip.getLocation();
1810                Point lowerRight = new Point(clip.x + clip.width - 1, clip.y
1811                        + clip.height - 1);
1812
1813                int rMin = table.rowAtPoint(upperLeft);
1814                int rMax = table.rowAtPoint(lowerRight);
1815                // This should never happen (as long as our bounds intersect the clip,
1816                // which is why we bail above if that is the case).
1817                if (rMin == -1) {
1818                    rMin = 0;
1819                }
1820                // If the table does not have enough rows to fill the view we'll get -1.
1821                // (We could also get -1 if our bounds don't intersect the clip,
1822                // which is why we bail above if that is the case).
1823                // Replace this with the index of the last row.
1824                if (rMax == -1) {
1825                    rMax = table.getRowCount() - 1;
1826                }
1827
1828                int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
1829                int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
1830                // This should never happen.
1831                if (cMin == -1) {
1832                    cMin = 0;
1833                }
1834                // If the table does not have enough columns to fill the view we'll get -1.
1835                // Replace this with the index of the last column.
1836                if (cMax == -1) {
1837                    cMax = table.getColumnCount() - 1;
1838                }
1839
1840                // Paint the grid.
1841                paintGrid(g, rMin, rMax, cMin, cMax);
1842
1843                // Paint the cells.
1844                paintCells(g, rMin, rMax, cMin, cMax);
1845
1846                paintDropLines(g);
1847            }
1848
1849            private void paintDropLines(Graphics g) {
1850                JTable.DropLocation loc = table.getDropLocation();
1851                if (loc == null) {
1852                    return;
1853                }
1854
1855                Color color = UIManager.getColor("Table.dropLineColor");
1856                Color shortColor = UIManager
1857                        .getColor("Table.dropLineShortColor");
1858                if (color == null && shortColor == null) {
1859                    return;
1860                }
1861
1862                Rectangle rect;
1863
1864                rect = getHDropLineRect(loc);
1865                if (rect != null) {
1866                    int x = rect.x;
1867                    int w = rect.width;
1868                    if (color != null) {
1869                        extendRect(rect, true);
1870                        g.setColor(color);
1871                        g.fillRect(rect.x, rect.y, rect.width, rect.height);
1872                    }
1873                    if (!loc.isInsertColumn() && shortColor != null) {
1874                        g.setColor(shortColor);
1875                        g.fillRect(x, rect.y, w, rect.height);
1876                    }
1877                }
1878
1879                rect = getVDropLineRect(loc);
1880                if (rect != null) {
1881                    int y = rect.y;
1882                    int h = rect.height;
1883                    if (color != null) {
1884                        extendRect(rect, false);
1885                        g.setColor(color);
1886                        g.fillRect(rect.x, rect.y, rect.width, rect.height);
1887                    }
1888                    if (!loc.isInsertRow() && shortColor != null) {
1889                        g.setColor(shortColor);
1890                        g.fillRect(rect.x, y, rect.width, h);
1891                    }
1892                }
1893            }
1894
1895            private Rectangle getHDropLineRect(JTable.DropLocation loc) {
1896                if (!loc.isInsertRow()) {
1897                    return null;
1898                }
1899
1900                int row = loc.getRow();
1901                int col = loc.getColumn();
1902                if (col >= table.getColumnCount()) {
1903                    col--;
1904                }
1905
1906                Rectangle rect = table.getCellRect(row, col, true);
1907
1908                if (row >= table.getRowCount()) {
1909                    row--;
1910                    Rectangle prevRect = table.getCellRect(row, col, true);
1911                    rect.y = prevRect.y + prevRect.height;
1912                }
1913
1914                if (rect.y == 0) {
1915                    rect.y = -1;
1916                } else {
1917                    rect.y -= 2;
1918                }
1919
1920                rect.height = 3;
1921
1922                return rect;
1923            }
1924
1925            private Rectangle getVDropLineRect(JTable.DropLocation loc) {
1926                if (!loc.isInsertColumn()) {
1927                    return null;
1928                }
1929
1930                boolean ltr = table.getComponentOrientation().isLeftToRight();
1931                int col = loc.getColumn();
1932                Rectangle rect = table.getCellRect(loc.getRow(), col, true);
1933
1934                if (col >= table.getColumnCount()) {
1935                    col--;
1936                    rect = table.getCellRect(loc.getRow(), col, true);
1937                    if (ltr) {
1938                        rect.x = rect.x + rect.width;
1939                    }
1940                } else if (!ltr) {
1941                    rect.x = rect.x + rect.width;
1942                }
1943
1944                if (rect.x == 0) {
1945                    rect.x = -1;
1946                } else {
1947                    rect.x -= 2;
1948                }
1949
1950                rect.width = 3;
1951
1952                return rect;
1953            }
1954
1955            private Rectangle extendRect(Rectangle rect, boolean horizontal) {
1956                if (rect == null) {
1957                    return rect;
1958                }
1959
1960                if (horizontal) {
1961                    rect.x = 0;
1962                    rect.width = table.getWidth();
1963                } else {
1964                    rect.y = 0;
1965
1966                    if (table.getRowCount() != 0) {
1967                        Rectangle lastRect = table.getCellRect(table
1968                                .getRowCount() - 1, 0, true);
1969                        rect.height = lastRect.y + lastRect.height;
1970                    } else {
1971                        rect.height = table.getHeight();
1972                    }
1973                }
1974
1975                return rect;
1976            }
1977
1978            /*
1979             * Paints the grid lines within <I>aRect</I>, using the grid
1980             * color set with <I>setGridColor</I>. Paints vertical lines
1981             * if <code>getShowVerticalLines()</code> returns true and paints
1982             * horizontal lines if <code>getShowHorizontalLines()</code>
1983             * returns true.
1984             */
1985            private void paintGrid(Graphics g, int rMin, int rMax, int cMin,
1986                    int cMax) {
1987                g.setColor(table.getGridColor());
1988
1989                Rectangle minCell = table.getCellRect(rMin, cMin, true);
1990                Rectangle maxCell = table.getCellRect(rMax, cMax, true);
1991                Rectangle damagedArea = minCell.union(maxCell);
1992
1993                if (table.getShowHorizontalLines()) {
1994                    int tableWidth = damagedArea.x + damagedArea.width;
1995                    int y = damagedArea.y;
1996                    for (int row = rMin; row <= rMax; row++) {
1997                        y += table.getRowHeight(row);
1998                        g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);
1999                    }
2000                }
2001                if (table.getShowVerticalLines()) {
2002                    TableColumnModel cm = table.getColumnModel();
2003                    int tableHeight = damagedArea.y + damagedArea.height;
2004                    int x;
2005                    if (table.getComponentOrientation().isLeftToRight()) {
2006                        x = damagedArea.x;
2007                        for (int column = cMin; column <= cMax; column++) {
2008                            int w = cm.getColumn(column).getWidth();
2009                            x += w;
2010                            g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
2011                        }
2012                    } else {
2013                        x = damagedArea.x;
2014                        for (int column = cMax; column >= cMin; column--) {
2015                            int w = cm.getColumn(column).getWidth();
2016                            x += w;
2017                            g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
2018                        }
2019                    }
2020                }
2021            }
2022
2023            private int viewIndexForColumn(TableColumn aColumn) {
2024                TableColumnModel cm = table.getColumnModel();
2025                for (int column = 0; column < cm.getColumnCount(); column++) {
2026                    if (cm.getColumn(column) == aColumn) {
2027                        return column;
2028                    }
2029                }
2030                return -1;
2031            }
2032
2033            private void paintCells(Graphics g, int rMin, int rMax, int cMin,
2034                    int cMax) {
2035                JTableHeader header = table.getTableHeader();
2036                TableColumn draggedColumn = (header == null) ? null : header
2037                        .getDraggedColumn();
2038
2039                TableColumnModel cm = table.getColumnModel();
2040                int columnMargin = cm.getColumnMargin();
2041
2042                Rectangle cellRect;
2043                TableColumn aColumn;
2044                int columnWidth;
2045                if (table.getComponentOrientation().isLeftToRight()) {
2046                    for (int row = rMin; row <= rMax; row++) {
2047                        cellRect = table.getCellRect(row, cMin, false);
2048                        for (int column = cMin; column <= cMax; column++) {
2049                            aColumn = cm.getColumn(column);
2050                            columnWidth = aColumn.getWidth();
2051                            cellRect.width = columnWidth - columnMargin;
2052                            if (aColumn != draggedColumn) {
2053                                paintCell(g, cellRect, row, column);
2054                            }
2055                            cellRect.x += columnWidth;
2056                        }
2057                    }
2058                } else {
2059                    for (int row = rMin; row <= rMax; row++) {
2060                        cellRect = table.getCellRect(row, cMin, false);
2061                        aColumn = cm.getColumn(cMin);
2062                        if (aColumn != draggedColumn) {
2063                            columnWidth = aColumn.getWidth();
2064                            cellRect.width = columnWidth - columnMargin;
2065                            paintCell(g, cellRect, row, cMin);
2066                        }
2067                        for (int column = cMin + 1; column <= cMax; column++) {
2068                            aColumn = cm.getColumn(column);
2069                            columnWidth = aColumn.getWidth();
2070                            cellRect.width = columnWidth - columnMargin;
2071                            cellRect.x -= columnWidth;
2072                            if (aColumn != draggedColumn) {
2073                                paintCell(g, cellRect, row, column);
2074                            }
2075                        }
2076                    }
2077                }
2078
2079                // Paint the dragged column if we are dragging.
2080                if (draggedColumn != null) {
2081                    paintDraggedArea(g, rMin, rMax, draggedColumn, header
2082                            .getDraggedDistance());
2083                }
2084
2085                // Remove any renderers that may be left in the rendererPane.
2086                rendererPane.removeAll();
2087            }
2088
2089            private void paintDraggedArea(Graphics g, int rMin, int rMax,
2090                    TableColumn draggedColumn, int distance) {
2091                int draggedColumnIndex = viewIndexForColumn(draggedColumn);
2092
2093                Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex,
2094                        true);
2095                Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex,
2096                        true);
2097
2098                Rectangle vacatedColumnRect = minCell.union(maxCell);
2099
2100                // Paint a gray well in place of the moving column.
2101                g.setColor(table.getParent().getBackground());
2102                g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
2103                        vacatedColumnRect.width, vacatedColumnRect.height);
2104
2105                // Move to the where the cell has been dragged.
2106                vacatedColumnRect.x += distance;
2107
2108                // Fill the background.
2109                g.setColor(table.getBackground());
2110                g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
2111                        vacatedColumnRect.width, vacatedColumnRect.height);
2112
2113                // Paint the vertical grid lines if necessary.
2114                if (table.getShowVerticalLines()) {
2115                    g.setColor(table.getGridColor());
2116                    int x1 = vacatedColumnRect.x;
2117                    int y1 = vacatedColumnRect.y;
2118                    int x2 = x1 + vacatedColumnRect.width - 1;
2119                    int y2 = y1 + vacatedColumnRect.height - 1;
2120                    // Left
2121                    g.drawLine(x1 - 1, y1, x1 - 1, y2);
2122                    // Right
2123                    g.drawLine(x2, y1, x2, y2);
2124                }
2125
2126                for (int row = rMin; row <= rMax; row++) {
2127                    // Render the cell value
2128                    Rectangle r = table.getCellRect(row, draggedColumnIndex,
2129                            false);
2130                    r.x += distance;
2131                    paintCell(g, r, row, draggedColumnIndex);
2132
2133                    // Paint the (lower) horizontal grid line if necessary.
2134                    if (table.getShowHorizontalLines()) {
2135                        g.setColor(table.getGridColor());
2136                        Rectangle rcr = table.getCellRect(row,
2137                                draggedColumnIndex, true);
2138                        rcr.x += distance;
2139                        int x1 = rcr.x;
2140                        int y1 = rcr.y;
2141                        int x2 = x1 + rcr.width - 1;
2142                        int y2 = y1 + rcr.height - 1;
2143                        g.drawLine(x1, y2, x2, y2);
2144                    }
2145                }
2146            }
2147
2148            private void paintCell(Graphics g, Rectangle cellRect, int row,
2149                    int column) {
2150                if (table.isEditing() && table.getEditingRow() == row
2151                        && table.getEditingColumn() == column) {
2152                    Component component = table.getEditorComponent();
2153                    component.setBounds(cellRect);
2154                    component.validate();
2155                } else {
2156                    TableCellRenderer renderer = table.getCellRenderer(row,
2157                            column);
2158                    Component component = table.prepareRenderer(renderer, row,
2159                            column);
2160                    rendererPane.paintComponent(g, component, table,
2161                            cellRect.x, cellRect.y, cellRect.width,
2162                            cellRect.height, true);
2163                }
2164            }
2165
2166            private static int getAdjustedLead(JTable table, boolean row,
2167                    ListSelectionModel model) {
2168
2169                int index = model.getLeadSelectionIndex();
2170                int compare = row ? table.getRowCount() : table
2171                        .getColumnCount();
2172                return index < compare ? index : -1;
2173            }
2174
2175            private static int getAdjustedLead(JTable table, boolean row) {
2176                return row ? getAdjustedLead(table, row, table
2177                        .getSelectionModel()) : getAdjustedLead(table, row,
2178                        table.getColumnModel().getSelectionModel());
2179            }
2180
2181            private static final TransferHandler defaultTransferHandler = new TableTransferHandler();
2182
2183            static class TableTransferHandler extends TransferHandler implements 
2184                    UIResource {
2185
2186                /**
2187                 * Create a Transferable to use as the source for a data transfer.
2188                 *
2189                 * @param c  The component holding the data to be transfered.  This
2190                 *  argument is provided to enable sharing of TransferHandlers by
2191                 *  multiple components.
2192                 * @return  The representation of the data to be transfered.
2193                 *
2194                 */
2195                protected Transferable createTransferable(JComponent c) {
2196                    if (c instanceof  JTable) {
2197                        JTable table = (JTable) c;
2198                        int[] rows;
2199                        int[] cols;
2200
2201                        if (!table.getRowSelectionAllowed()
2202                                && !table.getColumnSelectionAllowed()) {
2203                            return null;
2204                        }
2205
2206                        if (!table.getRowSelectionAllowed()) {
2207                            int rowCount = table.getRowCount();
2208
2209                            rows = new int[rowCount];
2210                            for (int counter = 0; counter < rowCount; counter++) {
2211                                rows[counter] = counter;
2212                            }
2213                        } else {
2214                            rows = table.getSelectedRows();
2215                        }
2216
2217                        if (!table.getColumnSelectionAllowed()) {
2218                            int colCount = table.getColumnCount();
2219
2220                            cols = new int[colCount];
2221                            for (int counter = 0; counter < colCount; counter++) {
2222                                cols[counter] = counter;
2223                            }
2224                        } else {
2225                            cols = table.getSelectedColumns();
2226                        }
2227
2228                        if (rows == null || cols == null || rows.length == 0
2229                                || cols.length == 0) {
2230                            return null;
2231                        }
2232
2233                        StringBuffer plainBuf = new StringBuffer();
2234                        StringBuffer htmlBuf = new StringBuffer();
2235
2236                        htmlBuf.append("<html>\n<body>\n<table>\n");
2237
2238                        for (int row = 0; row < rows.length; row++) {
2239                            htmlBuf.append("<tr>\n");
2240                            for (int col = 0; col < cols.length; col++) {
2241                                Object obj = table.getValueAt(rows[row],
2242                                        cols[col]);
2243                                String val = ((obj == null) ? "" : obj
2244                                        .toString());
2245                                plainBuf.append(val + "\t");
2246                                htmlBuf.append("  <td>" + val + "</td>\n");
2247                            }
2248                            // we want a newline at the end of each line and not a tab
2249                            plainBuf.deleteCharAt(plainBuf.length() - 1)
2250                                    .append("\n");
2251                            htmlBuf.append("</tr>\n");
2252                        }
2253
2254                        // remove the last newline
2255                        plainBuf.deleteCharAt(plainBuf.length() - 1);
2256                        htmlBuf.append("</table>\n</body>\n</html>");
2257
2258                        return new BasicTransferable(plainBuf.toString(),
2259                                htmlBuf.toString());
2260                    }
2261
2262                    return null;
2263                }
2264
2265                public int getSourceActions(JComponent c) {
2266                    return COPY;
2267                }
2268
2269            }
2270        } // End of Class BasicTableUI
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.