1 7 8 package javax.swing.plaf.basic; 9 10 import sun.swing.DefaultLookup; 11 import sun.swing.UIAction; 12 13 import javax.swing.*; 14 import javax.swing.event.*; 15 import javax.swing.plaf.*; 16 import javax.swing.text.Position ; 17 18 import java.awt.*; 19 import java.awt.event.*; 20 import java.awt.datatransfer.Transferable ; 21 import java.awt.dnd.*; 22 23 import java.util.ArrayList ; 24 import java.util.TooManyListenersException ; 25 26 import java.beans.PropertyChangeListener ; 27 import java.beans.PropertyChangeEvent ; 28 29 import com.sun.java.swing.SwingUtilities2; 30 import static com.sun.java.swing.SwingUtilities2.DRAG_FIX; 31 import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag ; 32 33 42 public class BasicListUI extends ListUI 43 { 44 protected JList list = null; 45 protected CellRendererPane rendererPane; 46 47 protected FocusListener focusListener; 49 protected MouseInputListener mouseInputListener; 50 protected ListSelectionListener listSelectionListener; 51 protected ListDataListener listDataListener; 52 protected PropertyChangeListener propertyChangeListener; 53 private Handler handler; 54 55 protected int[] cellHeights = null; 56 protected int cellHeight = -1; 57 protected int cellWidth = -1; 58 protected int updateLayoutStateNeeded = modelChanged; 59 63 private int listHeight; 64 65 69 private int listWidth; 70 71 74 private int layoutOrientation; 75 76 78 81 private int columnCount; 82 86 private int preferredHeight; 87 91 private int rowsPerColumn; 92 93 97 private long timeFactor = 1000L; 98 99 102 private boolean isFileList = false; 103 104 107 private boolean isLeftToRight = true; 108 109 115 116 protected final static int modelChanged = 1 << 0; 117 protected final static int selectionModelChanged = 1 << 1; 118 protected final static int fontChanged = 1 << 2; 119 protected final static int fixedCellWidthChanged = 1 << 3; 120 protected final static int fixedCellHeightChanged = 1 << 4; 121 protected final static int prototypeCellValueChanged = 1 << 5; 122 protected final static int cellRendererChanged = 1 << 6; 123 private final static int layoutOrientationChanged = 1 << 7; 124 private final static int heightChanged = 1 << 8; 125 private final static int widthChanged = 1 << 9; 126 private final static int componentOrientationChanged = 1 << 10; 127 128 129 static void loadActionMap(LazyActionMap map) { 130 map.put(new Actions(Actions.SELECT_PREVIOUS_COLUMN)); 131 map.put(new Actions(Actions.SELECT_PREVIOUS_COLUMN_EXTEND)); 132 map.put(new Actions(Actions.SELECT_PREVIOUS_COLUMN_CHANGE_LEAD)); 133 map.put(new Actions(Actions.SELECT_NEXT_COLUMN)); 134 map.put(new Actions(Actions.SELECT_NEXT_COLUMN_EXTEND)); 135 map.put(new Actions(Actions.SELECT_NEXT_COLUMN_CHANGE_LEAD)); 136 map.put(new Actions(Actions.SELECT_PREVIOUS_ROW)); 137 map.put(new Actions(Actions.SELECT_PREVIOUS_ROW_EXTEND)); 138 map.put(new Actions(Actions.SELECT_PREVIOUS_ROW_CHANGE_LEAD)); 139 map.put(new Actions(Actions.SELECT_NEXT_ROW)); 140 map.put(new Actions(Actions.SELECT_NEXT_ROW_EXTEND)); 141 map.put(new Actions(Actions.SELECT_NEXT_ROW_CHANGE_LEAD)); 142 map.put(new Actions(Actions.SELECT_FIRST_ROW)); 143 map.put(new Actions(Actions.SELECT_FIRST_ROW_EXTEND)); 144 map.put(new Actions(Actions.SELECT_FIRST_ROW_CHANGE_LEAD)); 145 map.put(new Actions(Actions.SELECT_LAST_ROW)); 146 map.put(new Actions(Actions.SELECT_LAST_ROW_EXTEND)); 147 map.put(new Actions(Actions.SELECT_LAST_ROW_CHANGE_LEAD)); 148 map.put(new Actions(Actions.SCROLL_UP)); 149 map.put(new Actions(Actions.SCROLL_UP_EXTEND)); 150 map.put(new Actions(Actions.SCROLL_UP_CHANGE_LEAD)); 151 map.put(new Actions(Actions.SCROLL_DOWN)); 152 map.put(new Actions(Actions.SCROLL_DOWN_EXTEND)); 153 map.put(new Actions(Actions.SCROLL_DOWN_CHANGE_LEAD)); 154 map.put(new Actions(Actions.SELECT_ALL)); 155 map.put(new Actions(Actions.CLEAR_SELECTION)); 156 map.put(new Actions(Actions.ADD_TO_SELECTION)); 157 map.put(new Actions(Actions.TOGGLE_AND_ANCHOR)); 158 map.put(new Actions(Actions.EXTEND_TO)); 159 map.put(new Actions(Actions.MOVE_SELECTION_TO)); 160 161 map.put(TransferHandler.getCutAction().getValue(Action.NAME), 162 TransferHandler.getCutAction()); 163 map.put(TransferHandler.getCopyAction().getValue(Action.NAME), 164 TransferHandler.getCopyAction()); 165 map.put(TransferHandler.getPasteAction().getValue(Action.NAME), 166 TransferHandler.getPasteAction()); 167 } 168 169 176 protected void paintCell( 177 Graphics g, 178 int row, 179 Rectangle rowBounds, 180 ListCellRenderer cellRenderer, 181 ListModel dataModel, 182 ListSelectionModel selModel, 183 int leadIndex) 184 { 185 Object value = dataModel.getElementAt(row); 186 boolean cellHasFocus = list.hasFocus() && (row == leadIndex); 187 boolean isSelected = selModel.isSelectedIndex(row); 188 189 Component rendererComponent = 190 cellRenderer.getListCellRendererComponent(list, value, row, isSelected, cellHasFocus); 191 192 int cx = rowBounds.x; 193 int cy = rowBounds.y; 194 int cw = rowBounds.width; 195 int ch = rowBounds.height; 196 197 if (isFileList) { 198 int w = Math.min(cw, rendererComponent.getPreferredSize().width + 4); 202 if (!isLeftToRight) { 203 cx += (cw - w); 204 } 205 cw = w; 206 } 207 208 rendererPane.paintComponent(g, rendererComponent, list, cx, cy, cw, ch, true); 209 } 210 211 212 219 public void paint(Graphics g, JComponent c) 220 { 221 switch (layoutOrientation) { 222 case JList.VERTICAL_WRAP: 223 if (list.getHeight() != listHeight) { 224 updateLayoutStateNeeded |= heightChanged; 225 redrawList(); 226 } 227 break; 228 case JList.HORIZONTAL_WRAP: 229 if (list.getWidth() != listWidth) { 230 updateLayoutStateNeeded |= widthChanged; 231 redrawList(); 232 } 233 break; 234 default: 235 break; 236 } 237 maybeUpdateLayoutState(); 238 239 ListCellRenderer renderer = list.getCellRenderer(); 240 ListModel dataModel = list.getModel(); 241 ListSelectionModel selModel = list.getSelectionModel(); 242 int size; 243 244 if ((renderer == null) || (size = dataModel.getSize()) == 0) { 245 return; 246 } 247 248 Rectangle paintBounds = g.getClipBounds(); 250 251 int startColumn, endColumn; 252 if (c.getComponentOrientation().isLeftToRight()) { 253 startColumn = convertLocationToColumn(paintBounds.x, 254 paintBounds.y); 255 endColumn = convertLocationToColumn(paintBounds.x + 256 paintBounds.width, 257 paintBounds.y); 258 } else { 259 startColumn = convertLocationToColumn(paintBounds.x + 260 paintBounds.width, 261 paintBounds.y); 262 endColumn = convertLocationToColumn(paintBounds.x, 263 paintBounds.y); 264 } 265 int maxY = paintBounds.y + paintBounds.height; 266 int leadIndex = list.getLeadSelectionIndex(); 267 int rowIncrement = (layoutOrientation == JList.HORIZONTAL_WRAP) ? 268 columnCount : 1; 269 270 271 for (int colCounter = startColumn; colCounter <= endColumn; 272 colCounter++) { 273 int row = convertLocationToRowInColumn(paintBounds.y, colCounter); 275 int rowCount = getRowCount(colCounter); 276 int index = getModelIndex(colCounter, row); 277 Rectangle rowBounds = getCellBounds(list, index, index); 278 279 if (rowBounds == null) { 280 return; 282 } 283 while (row < rowCount && rowBounds.y < maxY && 284 index < size) { 285 rowBounds.height = getHeight(colCounter, row); 286 g.setClip(rowBounds.x, rowBounds.y, rowBounds.width, 287 rowBounds.height); 288 g.clipRect(paintBounds.x, paintBounds.y, paintBounds.width, 289 paintBounds.height); 290 paintCell(g, index, rowBounds, renderer, dataModel, selModel, 291 leadIndex); 292 rowBounds.y += rowBounds.height; 293 index += rowIncrement; 294 row++; 295 } 296 } 297 } 298 299 300 355 public Dimension getPreferredSize(JComponent c) { 356 maybeUpdateLayoutState(); 357 358 int lastRow = list.getModel().getSize() - 1; 359 if (lastRow < 0) { 360 return new Dimension(0, 0); 361 } 362 363 Insets insets = list.getInsets(); 364 int width = cellWidth * columnCount + insets.left + insets.right; 365 int height; 366 367 if (layoutOrientation != JList.VERTICAL) { 368 height = preferredHeight; 369 } 370 else { 371 Rectangle bounds = getCellBounds(list, lastRow); 372 373 if (bounds != null) { 374 height = bounds.y + bounds.height + insets.bottom; 375 } 376 else { 377 height = 0; 378 } 379 } 380 return new Dimension(width, height); 381 } 382 383 384 389 protected void selectPreviousIndex() { 390 int s = list.getSelectedIndex(); 391 if(s > 0) { 392 s -= 1; 393 list.setSelectedIndex(s); 394 list.ensureIndexIsVisible(s); 395 } 396 } 397 398 399 404 protected void selectNextIndex() 405 { 406 int s = list.getSelectedIndex(); 407 if((s + 1) < list.getModel().getSize()) { 408 s += 1; 409 list.setSelectedIndex(s); 410 list.ensureIndexIsVisible(s); 411 } 412 } 413 414 415 422 protected void installKeyboardActions() { 423 InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); 424 425 SwingUtilities.replaceUIInputMap(list, JComponent.WHEN_FOCUSED, 426 inputMap); 427 428 LazyActionMap.installLazyActionMap(list, BasicListUI .class, 429 "List.actionMap"); 430 } 431 432 InputMap getInputMap(int condition) { 433 if (condition == JComponent.WHEN_FOCUSED) { 434 InputMap keyMap = (InputMap)DefaultLookup.get( 435 list, this, "List.focusInputMap"); 436 InputMap rtlKeyMap; 437 438 if (isLeftToRight || 439 ((rtlKeyMap = (InputMap)DefaultLookup.get(list, this, 440 "List.focusInputMap.RightToLeft")) == null)) { 441 return keyMap; 442 } else { 443 rtlKeyMap.setParent(keyMap); 444 return rtlKeyMap; 445 } 446 } 447 return null; 448 } 449 450 459 protected void uninstallKeyboardActions() { 460 SwingUtilities.replaceUIActionMap(list, null); 461 SwingUtilities.replaceUIInputMap(list, JComponent.WHEN_FOCUSED, null); 462 } 463 464 465 472 protected void installListeners() 473 { 474 TransferHandler th = list.getTransferHandler(); 475 if (th == null || th instanceof UIResource) { 476 list.setTransferHandler(defaultTransferHandler); 477 } 478 DropTarget dropTarget = list.getDropTarget(); 479 if (dropTarget instanceof UIResource) { 480 try { 481 dropTarget.addDropTargetListener(new ListDropTargetListener()); 482 } catch (TooManyListenersException tmle) { 483 } 485 } 486 487 focusListener = createFocusListener(); 488 mouseInputListener = createMouseInputListener(); 489 propertyChangeListener = createPropertyChangeListener(); 490 listSelectionListener = createListSelectionListener(); 491 listDataListener = createListDataListener(); 492 493 list.addFocusListener(focusListener); 494 if (!DRAG_FIX) { 495 list.addMouseListener(defaultDragRecognizer); 496 list.addMouseMotionListener(defaultDragRecognizer); 497 } 498 list.addMouseListener(mouseInputListener); 499 list.addMouseMotionListener(mouseInputListener); 500 list.addPropertyChangeListener(propertyChangeListener); 501 list.addKeyListener(getHandler()); 502 503 ListModel model = list.getModel(); 504 if (model != null) { 505 model.addListDataListener(listDataListener); 506 } 507 508 ListSelectionModel selectionModel = list.getSelectionModel(); 509 if (selectionModel != null) { 510 selectionModel.addListSelectionListener(listSelectionListener); 511 } 512 } 513 514 515 524 protected void uninstallListeners() 525 { 526 list.removeFocusListener(focusListener); 527 if (!DRAG_FIX) { 528 list.removeMouseListener(defaultDragRecognizer); 529 list.removeMouseMotionListener(defaultDragRecognizer); 530 } 531 list.removeMouseListener(mouseInputListener); 532 list.removeMouseMotionListener(mouseInputListener); 533 list.removePropertyChangeListener(propertyChangeListener); 534 list.removeKeyListener(getHandler()); 535 536 ListModel model = list.getModel(); 537 if (model != null) { 538 model.removeListDataListener(listDataListener); 539 } 540 541 ListSelectionModel selectionModel = list.getSelectionModel(); 542 if (selectionModel != null) { 543 selectionModel.removeListSelectionListener(listSelectionListener); 544 } 545 546 focusListener = null; 547 mouseInputListener = null; 548 listSelectionListener = null; 549 listDataListener = null; 550 propertyChangeListener = null; 551 handler = null; 552 } 553 554 555 566 protected void installDefaults() 567 { 568 list.setLayout(null); 569 570 LookAndFeel.installBorder(list, "List.border"); 571 572 LookAndFeel.installColorsAndFont(list, "List.background", "List.foreground", "List.font"); 573 574 LookAndFeel.installProperty(list, "opaque", Boolean.TRUE); 575 576 if (list.getCellRenderer() == null) { 577 list.setCellRenderer((ListCellRenderer)(UIManager.get("List.cellRenderer"))); 578 } 579 580 Color sbg = list.getSelectionBackground(); 581 if (sbg == null || sbg instanceof UIResource) { 582 list.setSelectionBackground(UIManager.getColor("List.selectionBackground")); 583 } 584 585 Color sfg = list.getSelectionForeground(); 586 if (sfg == null || sfg instanceof UIResource) { 587 list.setSelectionForeground(UIManager.getColor("List.selectionForeground")); 588 } 589 590 Long l = (Long )UIManager.get("List.timeFactor"); 591 timeFactor = (l!=null) ? l.longValue() : 1000L; 592 593 updateIsFileList(); 594 isLeftToRight = list.getComponentOrientation().isLeftToRight(); 595 } 596 597 private void updateIsFileList() { 598 boolean b = Boolean.TRUE.equals(list.getClientProperty("List.isFileList")); 599 if (b != isFileList) { 600 isFileList = b; 601 Font oldFont = list.getFont(); 602 if (oldFont == null || oldFont instanceof UIResource) { 603 Font newFont = UIManager.getFont(b ? "FileChooser.listFont" : "List.font"); 604 if (newFont != null && newFont != oldFont) { 605 list.setFont(newFont); 606 } 607 } 608 } 609 } 610 611 612 621 protected void uninstallDefaults() 622 { 623 LookAndFeel.uninstallBorder(list); 624 if (list.getFont() instanceof UIResource) { 625 list.setFont(null); 626 } 627 if (list.getForeground() instanceof UIResource) { 628 list.setForeground(null); 629 } 630 if (list.getBackground() instanceof UIResource) { 631 list.setBackground(null); 632 } 633 if (list.getSelectionBackground() instanceof UIResource) { 634 list.setSelectionBackground(null); 635 } 636 if (list.getSelectionForeground() instanceof UIResource) { 637 list.setSelectionForeground(null); 638 } 639 if (list.getCellRenderer() instanceof UIResource) { 640 list.setCellRenderer(null); 641 } 642 if (list.getTransferHandler() instanceof UIResource) { 643 list.setTransferHandler(null); 644 } 645 } 646 647 648 657 public void installUI(JComponent c) 658 { 659 list = (JList)c; 660 661 layoutOrientation = list.getLayoutOrientation(); 662 663 rendererPane = new CellRendererPane(); 664 list.add(rendererPane); 665 666 columnCount = 1; 667 668 installDefaults(); 669 installListeners(); 670 installKeyboardActions(); 671 } 672 673 674 683 public void uninstallUI(JComponent c) 684 { 685 uninstallListeners(); 686 uninstallDefaults(); 687 uninstallKeyboardActions(); 688 689 cellWidth = cellHeight = -1; 690 cellHeights = null; 691 692 listWidth = listHeight = -1; 693 694 list.remove(rendererPane); 695 rendererPane = null; 696 list = null; 697 } 698 699 700 706 public static ComponentUI createUI(JComponent list) { 707 return new BasicListUI (); 708 } 709 710 711 720 public int locationToIndex(JList list, Point location) { 721 maybeUpdateLayoutState(); 722 return convertLocationToModel(location.x, location.y); 723 } 724 725 726 730 public Point indexToLocation(JList list, int index) { 731 maybeUpdateLayoutState(); 732 Rectangle rect = getCellBounds(list, index, index); 733 734 if (rect != null) { 735 return new Point(rect.x, rect.y); 736 } 737 return null; 738 } 739 740 741 745 public Rectangle getCellBounds(JList list, int index1, int index2) { 746 maybeUpdateLayoutState(); 747 748 int minIndex = Math.min(index1, index2); 749 int maxIndex = Math.max(index1, index2); 750 751 if (minIndex >= list.getModel().getSize()) { 752 return null; 753 } 754 755 Rectangle minBounds = getCellBounds(list, minIndex); 756 757 if (minBounds == null) { 758 return null; 759 } 760 if (minIndex == maxIndex) { 761 return minBounds; 762 } 763 Rectangle maxBounds = getCellBounds(list, maxIndex); 764 765 if (maxBounds != null) { 766 if (layoutOrientation == JList.HORIZONTAL_WRAP) { 767 int minRow = convertModelToRow(minIndex); 768 int maxRow = convertModelToRow(maxIndex); 769 770 if (minRow != maxRow) { 771 minBounds.x = 0; 772 minBounds.width = list.getWidth(); 773 } 774 } 775 else if (minBounds.x != maxBounds.x) { 776 minBounds.y = 0; 778 minBounds.height = list.getHeight(); 779 } 780 minBounds.add(maxBounds); 781 } 782 return minBounds; 783 } 784 785 789 private Rectangle getCellBounds(JList list, int index) { 790 maybeUpdateLayoutState(); 791 792 int row = convertModelToRow(index); 793 int column = convertModelToColumn(index); 794 795 if (row == -1 || column == -1) { 796 return null; 797 } 798 799 Insets insets = list.getInsets(); 800 int x; 801 int w = cellWidth; 802 int y = insets.top; 803 int h; 804 switch (layoutOrientation) { 805 case JList.VERTICAL_WRAP: 806 case JList.HORIZONTAL_WRAP: 807 if (isLeftToRight) { 808 x = insets.left + column * cellWidth; 809 } else { 810 x = list.getWidth() - insets.right - (column+1) * cellWidth; 811 } 812 y += cellHeight * row; 813 h = cellHeight; 814 break; 815 default: 816 x = insets.left; 817 if (cellHeights == null) { 818 y += (cellHeight * row); 819 } 820 else if (row >= cellHeights.length) { 821 y = 0; 822 } 823 else { 824 for(int i = 0; i < row; i++) { 825 y += cellHeights[i]; 826 } 827 } 828 w = list.getWidth() - (insets.left + insets.right); 829 h = getRowHeight(index); 830 break; 831 } 832 return new Rectangle(x, y, w, h); 833 } 834 835 843 protected int getRowHeight(int row) 844 { 845 return getHeight(0, row); 846 } 847 848 849 858 protected int convertYToRow(int y0) 859 { 860 return convertLocationToRow(0, y0, false); 861 } 862 863 864 872 protected int convertRowToY(int row) 873 { 874 if (row >= getRowCount(0) || row < 0) { 875 return -1; 876 } 877 Rectangle bounds = getCellBounds(list, row, row); 878 return bounds.y; 879 } 880 881 884 private int getHeight(int column, int row) { 885 if (column < 0 || column > columnCount || row < 0) { 886 return -1; 887 } 888 if (layoutOrientation != JList.VERTICAL) { 889 return cellHeight; 890 } 891 if (row >= list.getModel().getSize()) { 892 return -1; 893 } 894 return (cellHeights == null) ? cellHeight : 895 ((row < cellHeights.length) ? cellHeights[row] : -1); 896 } 897 898 904 private int convertLocationToRow(int x, int y0, boolean closest) { 905 int size = list.getModel().getSize(); 906 907 if (size <= 0) { 908 return -1; 909 } 910 Insets insets = list.getInsets(); 911 if (cellHeights == null) { 912 int row = (cellHeight == 0) ? 0 : 913 ((y0 - insets.top) / cellHeight); 914 if (closest) { 915 if (row < 0) { 916 row = 0; 917 } 918 else if (row >= size) { 919 row = size - 1; 920 } 921 } 922 return row; 923 } 924 else if (size > cellHeights.length) { 925 return -1; 926 } 927 else { 928 int y = insets.top; 929 int row = 0; 930 931 if (closest && y0 < y) { 932 return 0; 933 } 934 int i; 935 for (i = 0; i < size; i++) { 936 if ((y0 >= y) && (y0 < y + cellHeights[i])) { 937 return row; 938 } 939 y += cellHeights[i]; 940 row += 1; 941 } 942 return i - 1; 943 } 944 } 945 946 950 private int convertLocationToRowInColumn(int y, int column) { 951 int x = 0; 952 953 if (layoutOrientation != JList.VERTICAL) { 954 if (isLeftToRight) { 955 x = column * cellWidth; 956 } else { 957 x = list.getWidth() - (column+1)*cellWidth - list.getInsets().right; 958 } 959 } 960 return convertLocationToRow(x, y, true); 961 } 962 963 967 private int convertLocationToModel(int x, int y) { 968 int row = convertLocationToRow(x, y, true); 969 int column = convertLocationToColumn(x, y); 970 971 if (row >= 0 && column >= 0) { 972 return getModelIndex(column, row); 973 } 974 return -1; 975 } 976 977 980 private int getRowCount(int column) { 981 if (column < 0 || column >= columnCount) { 982 return -1; 983 } 984 if (layoutOrientation == JList.VERTICAL || 985 (column == 0 && columnCount == 1)) { 986 return list.getModel().getSize(); 987 } 988 if (column >= columnCount) { 989 return -1; 990 } 991 if (layoutOrientation == JList.VERTICAL_WRAP) { 992 if (column < (columnCount - 1)) { 993 return rowsPerColumn; 994 } 995 return list.getModel().getSize() - (columnCount - 1) * 996 rowsPerColumn; 997 } 998 int diff = columnCount - (columnCount * rowsPerColumn - 1000 list.getModel().getSize()); 1001 1002 if (column >= diff) { 1003 return Math.max(0, rowsPerColumn - 1); 1004 } 1005 return rowsPerColumn; 1006 } 1007 1008 1013 private int getModelIndex(int column, int row) { 1014 switch (layoutOrientation) { 1015 case JList.VERTICAL_WRAP: 1016 return Math.min(list.getModel().getSize() - 1, rowsPerColumn * 1017 column + Math.min(row, rowsPerColumn-1)); 1018 case JList.HORIZONTAL_WRAP: 1019 return Math.min(list.getModel().getSize() - 1, row * columnCount + 1020 column); 1021 default: 1022 return row; 1023 } 1024 } 1025 1026 1029 private int convertLocationToColumn(int x, int y) { 1030 if (cellWidth > 0) { 1031 if (layoutOrientation == JList.VERTICAL) { 1032 return 0; 1033 } 1034 Insets insets = list.getInsets(); 1035 int col; 1036 if (isLeftToRight) { 1037 col = (x - insets.left) / cellWidth; 1038 } else { 1039 col = (list.getWidth() - x - insets.right - 1) / cellWidth; 1040 } 1041 if (col < 0) { 1042 return 0; 1043 } 1044 else if (col >= columnCount) { 1045 return columnCount - 1; 1046 } 1047 return col; 1048 } 1049 return 0; 1050 } 1051 1052 1056 private int convertModelToRow(int index) { 1057 int size = list.getModel().getSize(); 1058 1059 if ((index < 0) || (index >= size)) { 1060 return -1; 1061 } 1062 1063 if (layoutOrientation != JList.VERTICAL && columnCount > 1 && 1064 rowsPerColumn > 0) { 1065 if (layoutOrientation == JList.VERTICAL_WRAP) { 1066 return index % rowsPerColumn; 1067 } 1068 return index / columnCount; 1069 } 1070 return index; 1071 } 1072 1073 1077 private int convertModelToColumn(int index) { 1078 int size = list.getModel().getSize(); 1079 1080 if ((index < 0) || (index >= size)) { 1081 return -1; 1082 } 1083 1084 if (layoutOrientation != JList.VERTICAL && rowsPerColumn > 0 && 1085 columnCount > 1) { 1086 if (layoutOrientation == JList.VERTICAL_WRAP) { 1087 return index / rowsPerColumn; 1088 } 1089 return index % columnCount; 1090 } 1091 return 0; 1092 } 1093 1094 1102 protected void maybeUpdateLayoutState() 1103 { 1104 if (updateLayoutStateNeeded != 0) { 1105 updateLayoutState(); 1106 updateLayoutStateNeeded = 0; 1107 } 1108 } 1109 1110 1111 1118 protected void updateLayoutState() 1119 { 1120 1124 1125 int fixedCellHeight = list.getFixedCellHeight(); 1126 int fixedCellWidth = list.getFixedCellWidth(); 1127 1128 cellWidth = (fixedCellWidth != -1) ? fixedCellWidth : -1; 1129 1130 if (fixedCellHeight != -1) { 1131 cellHeight = fixedCellHeight; 1132 cellHeights = null; 1133 } 1134 else { 1135 cellHeight = -1; 1136 cellHeights = new int[list.getModel().getSize()]; 1137 } 1138 1139 1145 1146 if ((fixedCellWidth == -1) || (fixedCellHeight == -1)) { 1147 1148 ListModel dataModel = list.getModel(); 1149 int dataModelSize = dataModel.getSize(); 1150 ListCellRenderer renderer = list.getCellRenderer(); 1151 1152 if (renderer != null) { 1153 for(int index = 0; index < dataModelSize; index++) { 1154 Object value = dataModel.getElementAt(index); 1155 Component c = renderer.getListCellRendererComponent(list, value, index, false, false); 1156 rendererPane.add(c); 1157 Dimension cellSize = c.getPreferredSize(); 1158 if (fixedCellWidth == -1) { 1159 cellWidth = Math.max(cellSize.width, cellWidth); 1160 } 1161 if (fixedCellHeight == -1) { 1162 cellHeights[index] = cellSize.height; 1163 } 1164 } 1165 } 1166 else { 1167 if (cellWidth == -1) { 1168 cellWidth = 0; 1169 } 1170 if (cellHeights == null) { 1171 cellHeights = new int[dataModelSize]; 1172 } 1173 for(int index = 0; index < dataModelSize; index++) { 1174 cellHeights[index] = 0; 1175 } 1176 } 1177 } 1178 1179 columnCount = 1; 1180 if (layoutOrientation != JList.VERTICAL) { 1181 updateHorizontalLayoutState(fixedCellWidth, fixedCellHeight); 1182 } 1183 } 1184 1185 1193 private void updateHorizontalLayoutState(int fixedCellWidth, 1194 int fixedCellHeight) { 1195 int visRows = list.getVisibleRowCount(); 1196 int dataModelSize = list.getModel().getSize(); 1197 Insets insets = list.getInsets(); 1198 1199 listHeight = list.getHeight(); 1200 listWidth = list.getWidth(); 1201 1202 if (dataModelSize == 0) { 1203 rowsPerColumn = columnCount = 0; 1204 preferredHeight = insets.top + insets.bottom; 1205 return; 1206 } 1207 1208 int height; 1209 1210 if (fixedCellHeight != -1) { 1211 height = fixedCellHeight; 1212 } 1213 else { 1214 int maxHeight = 0; 1216 if (cellHeights.length > 0) { 1217 maxHeight = cellHeights[cellHeights.length - 1]; 1218 for (int counter = cellHeights.length - 2; 1219 counter >= 0; counter--) { 1220 maxHeight = Math.max(maxHeight, cellHeights[counter]); 1221 } 1222 } 1223 height = cellHeight = maxHeight; 1224 cellHeights = null; 1225 } 1226 rowsPerColumn = dataModelSize; 1229 if (visRows > 0) { 1230 rowsPerColumn = visRows; 1231 columnCount = Math.max(1, dataModelSize / rowsPerColumn); 1232 if (dataModelSize > 0 && dataModelSize > rowsPerColumn && 1233 dataModelSize % rowsPerColumn != 0) { 1234 columnCount++; 1235 } 1236 if (layoutOrientation == JList.HORIZONTAL_WRAP) { 1237 rowsPerColumn = (dataModelSize / columnCount); 1240 if (dataModelSize % columnCount > 0) { 1241 rowsPerColumn++; 1242 } 1243 } 1244 } 1245 else if (layoutOrientation == JList.VERTICAL_WRAP && height != 0) { 1246 rowsPerColumn = Math.max(1, (listHeight - insets.top - 1247 insets.bottom) / height); 1248 columnCount = Math.max(1, dataModelSize / rowsPerColumn); 1249 if (dataModelSize > 0 && dataModelSize > rowsPerColumn && 1250 dataModelSize % rowsPerColumn != 0) { 1251 columnCount++; 1252 } 1253 } 1254 else if (layoutOrientation == JList.HORIZONTAL_WRAP && cellWidth > 0 && 1255 listWidth > 0) { 1256 columnCount = Math.max(1, (listWidth - insets.left - 1257 insets.right) / cellWidth); 1258 rowsPerColumn = dataModelSize / columnCount; 1259 if (dataModelSize % columnCount > 0) { 1260 rowsPerColumn++; 1261 } 1262 } 1263 preferredHeight = rowsPerColumn * cellHeight + insets.top + 1264 insets.bottom; 1265 } 1266 1267 private Handler getHandler() { 1268 if (handler == null) { 1269 handler = DRAG_FIX ? new DragFixHandler() : new Handler(); 1270 } 1271 return handler; 1272 } 1273 1274 1293 public class MouseInputHandler implements MouseInputListener 1294 { 1295 public void mouseClicked(MouseEvent e) { 1296 getHandler().mouseClicked(e); 1297 } 1298 1299 public void mouseEntered(MouseEvent e) { 1300 getHandler().mouseEntered(e); 1301 } 1302 1303 public void mouseExited(MouseEvent e) { 1304 getHandler().mouseExited(e); 1305 } 1306 1307 public void mousePressed(MouseEvent e) { 1308 getHandler().mousePressed(e); 1309 } 1310 1311 public void mouseDragged(MouseEvent e) { 1312 getHandler().mouseDragged(e); 1313 } 1314 1315 public void mouseMoved(MouseEvent e) { 1316 getHandler().mouseMoved(e); 1317 } 1318 1319 public void mouseReleased(MouseEvent e) { 1320 getHandler().mouseReleased(e); 1321 } 1322 } 1323 1324 1325 1347 protected MouseInputListener createMouseInputListener() { 1348 return getHandler(); 1349 } 1350 1351 1356 public class FocusHandler implements FocusListener 1357 { 1358 protected void repaintCellFocus() 1359 { 1360 getHandler().repaintCellFocus(); 1361 } 1362 1363 1366 1367 public void focusGained(FocusEvent e) { 1368 getHandler().focusGained(e); 1369 } 1370 1371 public void focusLost(FocusEvent e) { 1372 getHandler().focusLost(e); 1373 } 1374 } 1375 1376 protected FocusListener createFocusListener() { 1377 return getHandler(); 1378 } 1379 1380 1398 public class ListSelectionHandler implements ListSelectionListener 1399 { 1400 public void valueChanged(ListSelectionEvent e) 1401 { 1402 getHandler().valueChanged(e); 1403 } 1404 } 1405 1406 1407 1428 protected ListSelectionListener createListSelectionListener() { 1429 return getHandler(); 1430 } 1431 1432 1433 private void redrawList() { 1434 list.revalidate(); 1435 list.repaint(); 1436 } 1437 1438 1439 1457 public class ListDataHandler implements ListDataListener 1458 { 1459 public void intervalAdded(ListDataEvent e) { 1460 getHandler().intervalAdded(e); 1461 } 1462 1463 1464 public void intervalRemoved(ListDataEvent e) 1465 { 1466 getHandler().intervalRemoved(e); 1467 } 1468 1469 1470 public void contentsChanged(ListDataEvent e) { 1471 getHandler().contentsChanged(e); 1472 } 1473 } 1474 1475 1476 1498 protected ListDataListener createListDataListener() { 1499 return getHandler(); 1500 } 1501 1502 1503 1523 public class PropertyChangeHandler implements PropertyChangeListener 1524 { 1525 public void propertyChange(PropertyChangeEvent e) 1526 { 1527 getHandler().propertyChange(e); 1528 } 1529 } 1530 1531 1532 1555 protected PropertyChangeListener createPropertyChangeListener() { 1556 return getHandler(); 1557 } 1558 1559 1561 private static final int CHANGE_LEAD = 0; 1562 1564 private static final int CHANGE_SELECTION = 1; 1565 1567 private static final int EXTEND_SELECTION = 2; 1568 1569 1570 private static class Actions extends UIAction { 1571 private static final String SELECT_PREVIOUS_COLUMN = 1572 "selectPreviousColumn"; 1573 private static final String SELECT_PREVIOUS_COLUMN_EXTEND = 1574 "selectPreviousColumnExtendSelection"; 1575 private static final String SELECT_PREVIOUS_COLUMN_CHANGE_LEAD = 1576 "selectPreviousColumnChangeLead"; 1577 private static final String SELECT_NEXT_COLUMN = "selectNextColumn"; 1578 private static final String SELECT_NEXT_COLUMN_EXTEND = 1579 "selectNextColumnExtendSelection"; 1580 private static final String SELECT_NEXT_COLUMN_CHANGE_LEAD = 1581 "selectNextColumnChangeLead"; 1582 private static final String SELECT_PREVIOUS_ROW = "selectPreviousRow"; 1583 private static final String SELECT_PREVIOUS_ROW_EXTEND = 1584 "selectPreviousRowExtendSelection"; 1585 private static final String SELECT_PREVIOUS_ROW_CHANGE_LEAD = 1586 "selectPreviousRowChangeLead"; 1587 private static final String SELECT_NEXT_ROW = "selectNextRow"; 1588 private static final String SELECT_NEXT_ROW_EXTEND = 1589 "selectNextRowExtendSelection"; 1590 private static final String SELECT_NEXT_ROW_CHANGE_LEAD = 1591 "selectNextRowChangeLead"; 1592 private static final String SELECT_FIRST_ROW = "selectFirstRow"; 1593 private static final String SELECT_FIRST_ROW_EXTEND = 1594 "selectFirstRowExtendSelection"; 1595 private static final String SELECT_FIRST_ROW_CHANGE_LEAD = 1596 "selectFirstRowChangeLead"; 1597 private static final String SELECT_LAST_ROW = "selectLastRow"; 1598 private static final String SELECT_LAST_ROW_EXTEND = 1599 "selectLastRowExtendSelection"; 1600 private static final String SELECT_LAST_ROW_CHANGE_LEAD = 1601 "selectLastRowChangeLead"; 1602 private static final String SCROLL_UP = "scrollUp"; 1603 private static final String SCROLL_UP_EXTEND = 1604 "scrollUpExtendSelection"; 1605 private static final String SCROLL_UP_CHANGE_LEAD = 1606 "scrollUpChangeLead"; 1607 private static final String SCROLL_DOWN = "scrollDown"; 1608 private static final String SCROLL_DOWN_EXTEND = 1609 "scrollDownExtendSelection"; 1610 private static final String SCROLL_DOWN_CHANGE_LEAD = 1611 "scrollDownChangeLead"; 1612 private static final String SELECT_ALL = "selectAll"; 1613 private static final String CLEAR_SELECTION = "clearSelection"; 1614 1615 private static final String ADD_TO_SELECTION = "addToSelection"; 1617 1618 private static final String TOGGLE_AND_ANCHOR = "toggleAndAnchor"; 1620 1621 private static final String EXTEND_TO = "extendTo"; 1623 1624 private static final String MOVE_SELECTION_TO = "moveSelectionTo"; 1626 1627 Actions(String name) { 1628 super(name); 1629 } 1630 public void actionPerformed(ActionEvent e) { 1631 String name = getName(); 1632 JList list = (JList)e.getSource(); 1633 BasicListUI ui = (BasicListUI )BasicLookAndFeel.getUIOfType( 1634 list.getUI(), BasicListUI .class); 1635 1636 if (name == SELECT_PREVIOUS_COLUMN) { 1637 changeSelection(list, CHANGE_SELECTION, 1638 getNextColumnIndex(list, ui, -1), true); 1639 } 1640 else if (name == SELECT_PREVIOUS_COLUMN_EXTEND) { 1641 changeSelection(list, EXTEND_SELECTION, 1642 getNextColumnIndex(list, ui, -1), true); 1643 } 1644 else if (name == SELECT_PREVIOUS_COLUMN_CHANGE_LEAD) { 1645 changeSelection(list, CHANGE_LEAD, 1646 getNextColumnIndex(list, ui, -1), true); 1647 } 1648 else if (name == SELECT_NEXT_COLUMN) { 1649 changeSelection(list, CHANGE_SELECTION, 1650 getNextColumnIndex(list, ui, 1), true); 1651 } 1652 else if (name == SELECT_NEXT_COLUMN_EXTEND) { 1653 changeSelection(list, EXTEND_SELECTION, 1654 getNextColumnIndex(list, ui, 1), true); 1655 } 1656 else if (name == SELECT_NEXT_COLUMN_CHANGE_LEAD) { 1657 changeSelection(list, CHANGE_LEAD, 1658 getNextColumnIndex(list, ui, 1), true); 1659 } 1660 else if (name == SELECT_PREVIOUS_ROW) { 1661 changeSelection(list, CHANGE_SELECTION, 1662 getNextIndex(list, ui, -1), true); 1663 } 1664 else if (name == SELECT_PREVIOUS_ROW_EXTEND) { 1665 changeSelection(list, EXTEND_SELECTION, 1666 getNextIndex(list, ui, -1), true); 1667 } 1668 else if (name == SELECT_PREVIOUS_ROW_CHANGE_LEAD) { 1669 changeSelection(list, CHANGE_LEAD, 1670 getNextIndex(list, ui, -1), true); 1671 } 1672 else if (name == SELECT_NEXT_ROW) { 1673 changeSelection(list, CHANGE_SELECTION, 1674 getNextIndex(list, ui, 1), true); 1675 } 1676 else if (name == SELECT_NEXT_ROW_EXTEND) { 1677 changeSelection(list, EXTEND_SELECTION, 1678 getNextIndex(list, ui, 1), true); 1679 } 1680 else if (name == SELECT_NEXT_ROW_CHANGE_LEAD) { 1681 changeSelection(list, CHANGE_LEAD, 1682 getNextIndex(list, ui, 1), true); 1683 } 1684 else if (name == SELECT_FIRST_ROW) { 1685 changeSelection(list, CHANGE_SELECTION, 0, true); 1686 } 1687 else if (name == SELECT_FIRST_ROW_EXTEND) { 1688 changeSelection(list, EXTEND_SELECTION, 0, true); 1689 } 1690 else if (name == SELECT_FIRST_ROW_CHANGE_LEAD) { 1691 changeSelection(list, CHANGE_LEAD, 0, true); 1692 } 1693 else if (name == SELECT_LAST_ROW) { 1694 changeSelection(list, CHANGE_SELECTION, 1695 list.getModel().getSize() - 1, true); 1696 } 1697 else if (name == SELECT_LAST_ROW_EXTEND) { 1698 changeSelection(list, EXTEND_SELECTION, 1699 list.getModel().getSize() - 1, true); 1700 } 1701 else if (name == SELECT_LAST_ROW_CHANGE_LEAD) { 1702 changeSelection(list, CHANGE_LEAD, 1703 list.getModel().getSize() - 1, true); 1704 } 1705 else if (name == SCROLL_UP) { 1706 scroll(list, CHANGE_SELECTION, true); 1707 } 1708 else if (name == SCROLL_UP_EXTEND) { 1709 scroll(list, EXTEND_SELECTION, true); 1710 } 1711 else if (name == SCROLL_UP_CHANGE_LEAD) { 1712 scroll(list, CHANGE_LEAD, true); 1713 } 1714 else if (name == SCROLL_DOWN) { 1715 scroll(list, CHANGE_SELECTION, false); 1716 } 1717 else if (name == SCROLL_DOWN_EXTEND) { 1718 scroll(list, EXTEND_SELECTION, false); 1719 } 1720 else if (name == SCROLL_DOWN_CHANGE_LEAD) { 1721 scroll(list, CHANGE_LEAD, false); 1722 } 1723 else if (name == SELECT_ALL) { 1724 selectAll(list); 1725 } 1726 else if (name == CLEAR_SELECTION) { 1727 clearSelection(list); 1728 } 1729 else if (name == ADD_TO_SELECTION) { 1730 int index = list.getSelectionModel().getLeadSelectionIndex(); 1731 if (!list.isSelectedIndex(index)) { 1732 int oldAnchor = list.getSelectionModel().getAnchorSelectionIndex(); 1733 list.setValueIsAdjusting(true); 1734 list.addSelectionInterval(index, index); 1735 list.getSelectionModel().setAnchorSelectionIndex(oldAnchor); 1736 list.setValueIsAdjusting(false); 1737 } 1738 } 1739 else if (name == TOGGLE_AND_ANCHOR) { 1740 int index = list.getSelectionModel().getLeadSelectionIndex(); 1741 if (list.isSelectedIndex(index)) { 1742 list.removeSelectionInterval(index, index); 1743 } else { 1744 list.addSelectionInterval(index, index); 1745 } 1746 } 1747 else if (name == EXTEND_TO) { 1748 changeSelection(list, EXTEND_SELECTION, 1749 list.getSelectionModel().getLeadSelectionIndex(), 1750 false); 1751 } 1752 else if (name == MOVE_SELECTION_TO) { 1753 changeSelection(list, CHANGE_SELECTION, 1754 list.getSelectionModel().getLeadSelectionIndex(), 1755 false); 1756 } 1757 } 1758 1759 public boolean isEnabled(Object c) { 1760 Object name = getName(); 1761 if (name == SELECT_PREVIOUS_COLUMN_CHANGE_LEAD || 1762 name == SELECT_NEXT_COLUMN_CHANGE_LEAD || 1763 name == SELECT_PREVIOUS_ROW_CHANGE_LEAD || 1764 name == SELECT_NEXT_ROW_CHANGE_LEAD || 1765 name == SELECT_FIRST_ROW_CHANGE_LEAD || 1766 name == SELECT_LAST_ROW_CHANGE_LEAD || 1767 name == SCROLL_UP_CHANGE_LEAD || 1768 name == SCROLL_DOWN_CHANGE_LEAD) { 1769 1770 return c != null && ((JList)c).getSelectionModel() 1773 instanceof DefaultListSelectionModel; 1774 } 1775 1776 return true; 1777 } 1778 1779 private void clearSelection(JList list) { 1780 list.clearSelection(); 1781 } 1782 1783 private void selectAll(JList list) { 1784 int size = list.getModel().getSize(); 1785 if (size > 0) { 1786 ListSelectionModel lsm = list.getSelectionModel(); 1787 if (lsm.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION) { 1788 int leadIndex = list.getLeadSelectionIndex(); 1789 if (leadIndex != -1) { 1790 list.setSelectionInterval(leadIndex, leadIndex); 1791 } else if (list.getMinSelectionIndex() == -1) { 1792 list.setSelectionInterval(0, 0); 1793 list.ensureIndexIsVisible(0); 1794 } 1795 } else { 1796 list.setValueIsAdjusting(true); 1797 1798 int anchor = lsm.getAnchorSelectionIndex(); 1799 int lead = lsm.getLeadSelectionIndex(); 1800 list.setSelectionInterval(0, size - 1); 1801 1802 list.addSelectionInterval(anchor, lead); 1804 1805 list.setValueIsAdjusting(false); 1806 } 1807 } 1808 } 1809 1810 private void scroll(JList list, int type, 1811 boolean up) { 1812 int index = getNextPageIndex(list, up); 1813 1814 if (index != -1) { 1815 changeSelection(list, type, index, false); 1816 1817 Rectangle visRect = list.getVisibleRect(); 1819 Rectangle cellBounds = list.getCellBounds(index, index); 1820 1821 if (!up) { 1822 cellBounds.y = Math.max(0, cellBounds.y + 1823 cellBounds.height -visRect.height); 1824 cellBounds.height = visRect.height; 1825 } 1826 else { 1827 cellBounds.height = visRect.height; 1828 } 1829 list.scrollRectToVisible(cellBounds); 1830 } 1831 } 1832 1833 private int getNextPageIndex(JList list, boolean up) { 1834 if (up) { 1835 int index = list.getFirstVisibleIndex(); 1836 ListSelectionModel lsm = list.getSelectionModel(); 1837 1838 if (lsm.getLeadSelectionIndex() == index) { 1839 Rectangle visRect = list.getVisibleRect(); 1840 visRect.y = Math.max(0, visRect.y - visRect.height); 1841 index = list.locationToIndex(visRect.getLocation()); 1842 } 1843 return index; 1844 } 1845 int index = list.getLastVisibleIndex(); 1847 ListSelectionModel lsm = list.getSelectionModel(); 1848 1849 if (index == -1) { 1850 index = list.getModel().getSize() - 1; 1852 } 1853 if (lsm.getLeadSelectionIndex() == index) { 1854 Rectangle visRect = list.getVisibleRect(); 1855 visRect.y += visRect.height + visRect.height - 1; 1856 index = list.locationToIndex(visRect.getLocation()); 1857 if (index == -1) { 1858 index = list.getModel().getSize() - 1; 1859 } 1860 } 1861 return index; 1862 } 1863 1864 private void changeSelection(JList list, int type, 1865 int index, boolean scroll) { 1866 if (index >= 0 && index < list.getModel().getSize()) { 1867 ListSelectionModel lsm = list.getSelectionModel(); 1868 1869 if (type == CHANGE_LEAD && 1871 list.getSelectionMode() 1872 != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) { 1873 1874 type = CHANGE_SELECTION; 1875 } 1876 1877 if (type == EXTEND_SELECTION) { 1878 int anchor = lsm.getAnchorSelectionIndex(); 1879 if (anchor == -1) { 1880 anchor = index; 1881 } 1882 1883 list.setSelectionInterval(anchor, index); 1884 } 1885 else if (type == CHANGE_SELECTION) { 1886 list.setSelectedIndex(index); 1887 } 1888 else { 1889 ((DefaultListSelectionModel)lsm).moveLeadSelectionIndex(index); 1892 } 1893 if (scroll) { 1894 list.ensureIndexIsVisible(index); 1895 } 1896 } 1897 } 1898 1899 private int getNextColumnIndex(JList list, BasicListUI ui, 1900 int amount) { 1901 if (list.getLayoutOrientation() != JList.VERTICAL) { 1902 int index = list.getLeadSelectionIndex(); 1903 int size = list.getModel().getSize(); 1904 1905 if (index == -1) { 1906 return 0; 1907 } else if (size == 1) { 1908 return 0; 1910 } else if (ui == null || ui.columnCount <= 1) { 1911 return -1; 1912 } 1913 1914 int column = ui.convertModelToColumn(index); 1915 int row = ui.convertModelToRow(index); 1916 1917 column += amount; 1918 if (column >= ui.columnCount || column < 0) { 1919 return -1; 1921 } 1922 int maxRowCount = ui.getRowCount(column); 1923 if (row >= maxRowCount) { 1924 row = maxRowCount - 1; 1925 } 1926 return ui.getModelIndex(column, row); 1927 } 1928 return -1; 1930 } 1931 1932 private int getNextIndex(JList list, BasicListUI ui, int amount) { 1933 int index = list.getLeadSelectionIndex(); 1934 int size = list.getModel().getSize(); 1935 1936 if (index == -1) { 1937 if (size > 0) { 1938 if (amount > 0) { 1939 index = 0; 1940 } 1941 else { 1942 index = size - 1; 1943 } 1944 } 1945 } else if (size == 1) { 1946 index = 0; 1948 } else if (list.getLayoutOrientation() == JList.HORIZONTAL_WRAP) { 1949 if (ui != null) { 1950 index += ui.columnCount * amount; 1951 } 1952 } else { 1953 index += amount; 1954 } 1955 1956 return index; 1957 } 1958 } 1959 1960 1961 private class Handler implements FocusListener, KeyListener, 1962 ListDataListener, ListSelectionListener, 1963 MouseInputListener, PropertyChangeListener { 1964 private String prefix = ""; 1968 private String typedString = ""; 1969 private long lastTime = 0L; 1970 1971 1982 public void keyTyped(KeyEvent e) { 1983 JList src = (JList)e.getSource(); 1984 ListModel model = src.getModel(); 1985 1986 if (model.getSize() == 0 || e.isAltDown() || e.isControlDown() || e.isMetaDown() || 1987 isNavigationKey(e)) { 1988 return; 1990 } 1991 boolean startingFromSelection = true; 1992 1993 char c = e.getKeyChar(); 1994 1995 long time = e.getWhen(); 1996 int startIndex = src.getLeadSelectionIndex(); 1997 if (time - lastTime < timeFactor) { 1998 typedString += c; 1999 if((prefix.length() == 1) && (c == prefix.charAt(0))) { 2000 startIndex++; 2003 } else { 2004 prefix = typedString; 2005 } 2006 } else { 2007 startIndex++; 2008 typedString = "" + c; 2009 prefix = typedString; 2010 } 2011 lastTime = time; 2012 2013 if (startIndex < 0 || startIndex >= model.getSize()) { 2014 startingFromSelection = false; 2015 startIndex = 0; 2016 } 2017 int index = src.getNextMatch(prefix, startIndex, 2018 Position.Bias.Forward); 2019 if (index >= 0) { 2020 src.setSelectedIndex(index); 2021 src.ensureIndexIsVisible(index); 2022 } else if (startingFromSelection) { index = src.getNextMatch(prefix, 0, 2024 Position.Bias.Forward); 2025 if (index >= 0) { 2026 src.setSelectedIndex(index); 2027 src.ensureIndexIsVisible(index); 2028 } 2029 } 2030 } 2031 2032 2038 public void keyPressed(KeyEvent e) { 2039 if ( isNavigationKey(e) ) { 2040 prefix = ""; 2041 typedString = ""; 2042 lastTime = 0L; 2043 } 2044 } 2045 2046 2051 public void keyReleased(KeyEvent e) { 2052 } 2053 2054 2059 private boolean isNavigationKey(KeyEvent event) { 2060 InputMap inputMap = list.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 2061 KeyStroke key = KeyStroke.getKeyStrokeForEvent(event); 2062 2063 if (inputMap != null && inputMap.get(key) != null) { 2064 return true; 2065 } 2066 return false; 2067 } 2068 2069 public void propertyChange(PropertyChangeEvent e) { 2073 String propertyName = e.getPropertyName(); 2074 2075 2078 if (propertyName == "model") { 2079 ListModel oldModel = (ListModel)e.getOldValue(); 2080 ListModel newModel = (ListModel)e.getNewValue(); 2081 if (oldModel != null) { 2082 oldModel.removeListDataListener(listDataListener); 2083 } 2084 if (newModel != null) { 2085 newModel.addListDataListener(listDataListener); 2086 } 2087 updateLayoutStateNeeded |= modelChanged; 2088 redrawList(); 2089 } 2090 2091 2094 else if (propertyName == "selectionModel") { 2095 ListSelectionModel oldModel = (ListSelectionModel)e.getOldValue(); 2096 ListSelectionModel newModel = (ListSelectionModel)e.getNewValue(); 2097 if (oldModel != null) { 2098 oldModel.removeListSelectionListener(listSelectionListener); 2099 } 2100 if (newModel != null) { 2101 newModel.addListSelectionListener(listSelectionListener); 2102 } 2103 updateLayoutStateNeeded |= modelChanged; 2104 redrawList(); 2105 } 2106 else if (propertyName == "cellRenderer") { 2107 updateLayoutStateNeeded |= cellRendererChanged; 2108 redrawList(); 2109 } 2110 else if (propertyName == "font") { 2111 updateLayoutStateNeeded |= fontChanged; 2112 redrawList(); 2113 } 2114 else if (propertyName == "prototypeCellValue") { 2115 updateLayoutStateNeeded |= prototypeCellValueChanged; 2116 redrawList(); 2117 } 2118 else if (propertyName == "fixedCellHeight") { 2119 updateLayoutStateNeeded |= fixedCellHeightChanged; 2120 redrawList(); 2121 } 2122 else if (propertyName == "fixedCellWidth") { 2123 updateLayoutStateNeeded |= fixedCellWidthChanged; 2124 redrawList(); 2125 } 2126 else if (propertyName == "cellRenderer") { 2127 updateLayoutStateNeeded |= cellRendererChanged; 2128 redrawList(); 2129 } 2130 else if (propertyName == "selectionForeground") { 2131 list.repaint(); 2132 } 2133 else if (propertyName == "selectionBackground") { 2134 list.repaint(); 2135 } 2136 else if ("layoutOrientation" == propertyName) { 2137 updateLayoutStateNeeded |= layoutOrientationChanged; 2138 layoutOrientation = list.getLayoutOrientation(); 2139 redrawList(); 2140 } 2141 else if ("visibleRowCount" == propertyName) { 2142 if (layoutOrientation != JList.VERTICAL) { 2143 updateLayoutStateNeeded |= layoutOrientationChanged; 2144 redrawList(); 2145 } 2146 } 2147 else if ("componentOrientation" == propertyName) { 2148 isLeftToRight = list.getComponentOrientation().isLeftToRight(); 2149 updateLayoutStateNeeded |= componentOrientationChanged; 2150 redrawList(); 2151 2152 InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); 2153 SwingUtilities.replaceUIInputMap(list, JComponent.WHEN_FOCUSED, 2154 inputMap); 2155 } else if ("List.isFileList" == propertyName) { 2156 updateIsFileList(); 2157 redrawList(); 2158 } else if ("transferHandler" == propertyName) { 2159 DropTarget dropTarget = list.getDropTarget(); 2160 if (dropTarget instanceof UIResource) { 2161 try { 2162 dropTarget.addDropTargetListener(new ListDropTargetListener()); 2163 } catch (TooManyListenersException tmle) { 2164 } 2166 } 2167 } 2168 } 2169 2170 public void intervalAdded(ListDataEvent e) { 2174 updateLayoutStateNeeded = modelChanged; 2175 2176 int minIndex = Math.min(e.getIndex0(), e.getIndex1()); 2177 int maxIndex = Math.max(e.getIndex0(), e.getIndex1()); 2178 2179 2181 2182 ListSelectionModel sm = list.getSelectionModel(); 2183 if (sm != null) { 2184 sm.insertIndexInterval(minIndex, maxIndex - minIndex+1, true); 2185 } 2186 2187 2191 redrawList(); 2192 } 2193 2194 2195 public void intervalRemoved(ListDataEvent e) 2196 { 2197 updateLayoutStateNeeded = modelChanged; 2198 2199 2201 2202 ListSelectionModel sm = list.getSelectionModel(); 2203 if (sm != null) { 2204 sm.removeIndexInterval(e.getIndex0(), e.getIndex1()); 2205 } 2206 2207 2211 2212 redrawList(); 2213 } 2214 2215 2216 public void contentsChanged(ListDataEvent e) { 2217 updateLayoutStateNeeded = modelChanged; 2218 redrawList(); 2219 } 2220 2221 2222 public void valueChanged(ListSelectionEvent e) { 2226 maybeUpdateLayoutState(); 2227 2228 Rectangle bounds = getCellBounds(list, e.getFirstIndex(), 2229 e.getLastIndex()); 2230 2231 if (bounds != null) { 2232 list.repaint(bounds.x, bounds.y, bounds.width, bounds.height); 2233 } 2234 } 2235 2236 private boolean selectedOnPress; 2240 2241 public void mouseClicked(MouseEvent e) { 2242 } 2243 2244 public void mouseEntered(MouseEvent e) { 2245 } 2246 2247 public void mouseExited(MouseEvent e) { 2248 } 2249 2250 public void mousePressed(MouseEvent e) { 2251 if (e.isConsumed()) { 2252 selectedOnPress = false; 2253 return; 2254 } 2255 selectedOnPress = true; 2256 adjustFocusAndSelection(e); 2257 } 2258 2259 private void adjustFocusAndSelection(MouseEvent e) { 2260 if (!SwingUtilities.isLeftMouseButton(e)) { 2261 return; 2262 } 2263 2264 if (!list.isEnabled()) { 2265 return; 2266 } 2267 2268 2273 SwingUtilities2.adjustFocus(list); 2274 2275 adjustSelection(e); 2276 } 2277 2278 protected void adjustSelection(MouseEvent e) { 2279 int row = SwingUtilities2.loc2IndexFileList(list, e.getPoint()); 2280 if (row < 0) { 2281 if (isFileList && 2284 e.getID() == MouseEvent.MOUSE_PRESSED && 2285 (!e.isShiftDown() || 2286 list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)) { 2287 list.clearSelection(); 2288 } 2289 } 2290 else { 2291 if (!DRAG_FIX) { 2292 boolean adjusting = (e.getID() == MouseEvent.MOUSE_PRESSED) ? true : false; 2293 list.setValueIsAdjusting(adjusting); 2294 } 2295 int anchorIndex = list.getAnchorSelectionIndex(); 2296 if (e.isControlDown()) { 2297 if (e.isShiftDown() && anchorIndex != -1) { 2298 if (list.isSelectedIndex(anchorIndex)) { 2299 list.addSelectionInterval(anchorIndex, row); 2300 } else { 2301 list.removeSelectionInterval(anchorIndex, row); 2302 list.addSelectionInterval(row, row); 2303 list.getSelectionModel().setAnchorSelectionIndex(anchorIndex); 2304 } 2305 } else if (list.isSelectedIndex(row)) { 2306 list.removeSelectionInterval(row, row); 2307 } 2308 else { 2309 list.addSelectionInterval(row, row); 2310 } 2311 } 2312 else if (e.isShiftDown() && (anchorIndex != -1)) { 2313 list.setSelectionInterval(anchorIndex, row); 2314 } 2315 else { 2316 list.setSelectionInterval(row, row); 2317 } 2318 } 2319 } 2320 2321 public void mouseDragged(MouseEvent e) { 2322 if (e.isConsumed()) { 2323 return; 2324 } 2325 if (!SwingUtilities.isLeftMouseButton(e)) { 2326 return; 2327 } 2328 if (!list.isEnabled()) { 2329 return; 2330 } 2331 2332 mouseDraggedImpl(e); 2333 } 2334 2335 protected void mouseDraggedImpl(MouseEvent e) { 2336 if (e.isShiftDown() || e.isControlDown()) { 2337 return; 2338 } 2339 2340 int row = locationToIndex(list, e.getPoint()); 2341 if (row != -1) { 2342 if (isFileList) { 2344 return; 2345 } 2346 Rectangle cellBounds = getCellBounds(list, row, row); 2347 if (cellBounds != null) { 2348 list.scrollRectToVisible(cellBounds); 2349 list.setSelectionInterval(row, row); 2350 } 2351 } 2352 } 2353 2354 public void mouseMoved(MouseEvent e) { 2355 } 2356 2357 public void mouseReleased(MouseEvent e) { 2358 if (selectedOnPress) { 2359 if (!SwingUtilities.isLeftMouseButton(e)) { 2360 return; 2361 } 2362 2363 list.setValueIsAdjusting(false); 2364 } else { 2365 adjustFocusAndSelection(e); 2366 } 2367 } 2368 2369 protected void repaintCellFocus() 2373 { 2374 int leadIndex = list.getLeadSelectionIndex(); 2375 if (leadIndex != -1) { 2376 Rectangle r = getCellBounds(list, leadIndex, leadIndex); 2377 if (r != null) { 2378 list.repaint(r.x, r.y, r.width, r.height); 2379 } 2380 } 2381 } 2382 2383 2386 2387 public void focusGained(FocusEvent e) { 2388 repaintCellFocus(); 2389 } 2390 2391 public void focusLost(FocusEvent e) { 2392 repaintCellFocus(); 2393 } 2394 } 2395 2396 2397 private class DragFixHandler extends Handler implements BeforeDrag { 2398 2399 private boolean dragPressDidSelection; 2403 2404 public void mousePressed(MouseEvent e) { 2405 if (SwingUtilities2.shouldIgnore(e, list)) { 2406 return; 2407 } 2408 2409 boolean dragEnabled = list.getDragEnabled(); 2410 boolean grabFocus = true; 2411 2412 if (dragEnabled) { 2414 int row = SwingUtilities2.loc2IndexFileList(list, e.getPoint()); 2415 if (row != -1 && DragRecognitionSupport.mousePressed(e)) { 2417 dragPressDidSelection = false; 2418 2419 if (e.isControlDown()) { 2420 return; 2423 } else if (!e.isShiftDown() && list.isSelectedIndex(row)) { 2424 list.addSelectionInterval(row, row); 2427 return; 2428 } 2429 2430 grabFocus = false; 2432 2433 dragPressDidSelection = true; 2434 } 2435 } else { 2436 list.setValueIsAdjusting(true); 2440 } 2441 2442 if (grabFocus) { 2443 SwingUtilities2.adjustFocus(list); 2444 } 2445 2446 adjustSelection(e); 2447 } 2448 2449 public void dragStarting(MouseEvent me) { 2450 if (me.isControlDown()) { 2451 int row = SwingUtilities2.loc2IndexFileList(list, me.getPoint()); 2452 list.addSelectionInterval(row, row); 2453 } 2454 } 2455 2456 public void mouseDragged(MouseEvent e) { 2457 if (SwingUtilities2.shouldIgnore(e, list)) { 2458 return; 2459 } 2460 2461 if (list.getDragEnabled()) { 2462 DragRecognitionSupport.mouseDragged(e, this); 2463 return; 2464 } 2465 2466 mouseDraggedImpl(e); 2467 } 2468 2469 public void mouseReleased(MouseEvent e) { 2470 if (SwingUtilities2.shouldIgnore(e, list)) { 2471 return; 2472 } 2473 2474 if (list.getDragEnabled()) { 2475 MouseEvent me = DragRecognitionSupport.mouseReleased(e); 2476 if (me != null) { 2477 SwingUtilities2.adjustFocus(list); 2478 if (!dragPressDidSelection) { 2479 adjustSelection(me); 2480 } 2481 } 2482 } else { 2483 list.setValueIsAdjusting(false); 2484 } 2485 } 2486 } 2487 2488 2489 private static final ListDragGestureRecognizer defaultDragRecognizer = 2490 DRAG_FIX ? null : new ListDragGestureRecognizer(); 2491 2492 2495 static class ListDragGestureRecognizer extends BasicDragGestureRecognizer { 2496 2497 2509 protected boolean isDragPossible(MouseEvent e) { 2510 if (super.isDragPossible(e)) { 2511 JList list = (JList) this.getComponent(e); 2512 if (list.getDragEnabled()) { 2513 ListUI ui = list.getUI(); 2514 int row = SwingUtilities2.loc2IndexFileList(list, 2515 e.getPoint()); 2516 if ((row != -1) && list.isSelectedIndex(row)) { 2517 return true; 2518 } 2519 } 2520 } 2521 return false; 2522 } 2523 } 2524 2525 2530 class ListDropTargetListener extends BasicDropTargetListener { 2531 2535 protected void saveComponentState(JComponent comp) { 2536 JList list = (JList) comp; 2537 selectedIndices = list.getSelectedIndices(); 2538 } 2539 2540 2544 protected void restoreComponentState(JComponent comp) { 2545 JList list = (JList) comp; 2546 list.setSelectedIndices(selectedIndices); 2547 } 2548 2549 2553 protected void updateInsertionLocation(JComponent comp, Point p) { 2554 JList list = (JList) comp; 2555 int index = locationToIndex(list, p); 2556 if (index != -1) { 2557 list.setSelectionInterval(index, index); 2558 } 2559 } 2560 2561 private int[] selectedIndices; 2562 } 2563 2564 private static final TransferHandler defaultTransferHandler = new ListTransferHandler(); 2565 2566 static class ListTransferHandler extends TransferHandler implements UIResource { 2567 2568 2577 protected Transferable createTransferable(JComponent c) { 2578 if (c instanceof JList) { 2579 JList list = (JList) c; 2580 Object [] values = list.getSelectedValues(); 2581 2582 if (values == null || values.length == 0) { 2583 return null; 2584 } 2585 2586 StringBuffer plainBuf = new StringBuffer (); 2587 StringBuffer htmlBuf = new StringBuffer (); 2588 2589 htmlBuf.append("<html>\n<body>\n<ul>\n"); 2590 2591 for (int i = 0; i < values.length; i++) { 2592 Object obj = values[i]; 2593 String val = ((obj == null) ? "" : obj.toString()); 2594 plainBuf.append(val + "\n"); 2595 htmlBuf.append(" <li>" + val + "\n"); 2596 } 2597 2598 plainBuf.deleteCharAt(plainBuf.length() - 1); 2600 htmlBuf.append("</ul>\n</body>\n</html>"); 2601 2602 return new BasicTransferable (plainBuf.toString(), htmlBuf.toString()); 2603 } 2604 2605 return null; 2606 } 2607 2608 public int getSourceActions(JComponent c) { 2609 return COPY; 2610 } 2611 2612 } 2613} 2614 | Popular Tags |