1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.java.swing.plaf.motif; 27 28 import javax.swing.*; 29 import javax.swing.filechooser.*; 30 import javax.swing.event.*; 31 import javax.swing.plaf.*; 32 import javax.swing.plaf.basic.*; 33 import java.awt.*; 34 import java.awt.event.MouseAdapter; 35 import java.awt.event.MouseEvent; 36 import java.beans.*; 37 import java.io.File; 38 import java.io.IOException; 39 import java.util.*; 40 import sun.awt.shell.ShellFolder; 41 import sun.swing.SwingUtilities2; 42 43 /** 44 * Motif FileChooserUI. 45 * 46 * @author Jeff Dinkins 47 */ 48 public class MotifFileChooserUI extends BasicFileChooserUI { 49 50 private FilterComboBoxModel filterComboBoxModel; 51 52 protected JList<File> directoryList = null; 53 protected JList<File> fileList = null; 54 55 protected JTextField pathField = null; 56 protected JComboBox<FileFilter> filterComboBox = null; 57 protected JTextField filenameTextField = null; 58 59 private static final Dimension hstrut10 = new Dimension(10, 1); 60 private static final Dimension vstrut10 = new Dimension(1, 10); 61 62 private static final Insets insets = new Insets(10, 10, 10, 10); 63 64 private static Dimension prefListSize = new Dimension(75, 150); 65 66 private static Dimension WITH_ACCELERATOR_PREF_SIZE = new Dimension(650, 450); 67 private static Dimension PREF_SIZE = new Dimension(350, 450); 68 private static Dimension MIN_SIZE = new Dimension(200, 300); 69 70 private static Dimension PREF_ACC_SIZE = new Dimension(10, 10); 71 private static Dimension ZERO_ACC_SIZE = new Dimension(1, 1); 72 73 private static Dimension MAX_SIZE = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); 74 75 private static final Insets buttonMargin = new Insets(3, 3, 3, 3); 76 77 private JPanel bottomPanel; 78 79 protected JButton approveButton; 80 81 private String enterFolderNameLabelText = null; 82 private int enterFolderNameLabelMnemonic = 0; 83 private String enterFileNameLabelText = null; 84 private int enterFileNameLabelMnemonic = 0; 85 86 private String filesLabelText = null; 87 private int filesLabelMnemonic = 0; 88 89 private String foldersLabelText = null; 90 private int foldersLabelMnemonic = 0; 91 92 private String pathLabelText = null; 93 private int pathLabelMnemonic = 0; 94 95 private String filterLabelText = null; 96 private int filterLabelMnemonic = 0; 97 98 private JLabel fileNameLabel; 99 100 private void populateFileNameLabel() { 101 if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) { 102 fileNameLabel.setText(enterFolderNameLabelText); 103 fileNameLabel.setDisplayedMnemonic(enterFolderNameLabelMnemonic); 104 } else { 105 fileNameLabel.setText(enterFileNameLabelText); 106 fileNameLabel.setDisplayedMnemonic(enterFileNameLabelMnemonic); 107 } 108 } 109 110 private String fileNameString(File file) { 111 if (file == null) { 112 return null; 113 } else { 114 JFileChooser fc = getFileChooser(); 115 if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) { 116 return file.getPath(); 117 } else { 118 return file.getName(); 119 } 120 } 121 } 122 123 private String fileNameString(File[] files) { 124 StringBuffer buf = new StringBuffer(); 125 for (int i = 0; files != null && i < files.length; i++) { 126 if (i > 0) { 127 buf.append(" "); 128 } 129 if (files.length > 1) { 130 buf.append("\""); 131 } 132 buf.append(fileNameString(files[i])); 133 if (files.length > 1) { 134 buf.append("\""); 135 } 136 } 137 return buf.toString(); 138 } 139 140 public MotifFileChooserUI(JFileChooser filechooser) { 141 super(filechooser); 142 } 143 144 public String getFileName() { 145 if(filenameTextField != null) { 146 return filenameTextField.getText(); 147 } else { 148 return null; 149 } 150 } 151 152 public void setFileName(String filename) { 153 if(filenameTextField != null) { 154 filenameTextField.setText(filename); 155 } 156 } 157 158 public String getDirectoryName() { 159 return pathField.getText(); 160 } 161 162 public void setDirectoryName(String dirname) { 163 pathField.setText(dirname); 164 } 165 166 public void ensureFileIsVisible(JFileChooser fc, File f) { 167 // PENDING(jeff) 168 } 169 170 public void rescanCurrentDirectory(JFileChooser fc) { 171 getModel().validateFileCache(); 172 } 173 174 public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) { 175 return new PropertyChangeListener() { 176 public void propertyChange(PropertyChangeEvent e) { 177 String prop = e.getPropertyName(); 178 if(prop.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) { 179 File f = (File) e.getNewValue(); 180 if(f != null) { 181 setFileName(getFileChooser().getName(f)); 182 } 183 } else if (prop.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) { 184 File[] files = (File[]) e.getNewValue(); 185 JFileChooser fc = getFileChooser(); 186 if (files != null && files.length > 0 && (files.length > 1 || fc.isDirectorySelectionEnabled() 187 || !files[0].isDirectory())) { 188 setFileName(fileNameString(files)); 189 } 190 } else if (prop.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) { 191 fileList.clearSelection(); 192 } else if(prop.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) { 193 directoryList.clearSelection(); 194 ListSelectionModel sm = directoryList.getSelectionModel(); 195 if (sm instanceof DefaultListSelectionModel) { 196 ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0); 197 sm.setAnchorSelectionIndex(0); 198 } 199 fileList.clearSelection(); 200 sm = fileList.getSelectionModel(); 201 if (sm instanceof DefaultListSelectionModel) { 202 ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0); 203 sm.setAnchorSelectionIndex(0); 204 } 205 File currentDirectory = getFileChooser().getCurrentDirectory(); 206 if(currentDirectory != null) { 207 try { 208 setDirectoryName(ShellFolder.getNormalizedFile((File)e.getNewValue()).getPath()); 209 } catch (IOException ioe) { 210 setDirectoryName(((File)e.getNewValue()).getAbsolutePath()); 211 } 212 if ((getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) && !getFileChooser().isMultiSelectionEnabled()) { 213 setFileName(getDirectoryName()); 214 } 215 } 216 } else if(prop.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) { 217 if (fileNameLabel != null) { 218 populateFileNameLabel(); 219 } 220 directoryList.clearSelection(); 221 } else if (prop.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) { 222 if(getFileChooser().isMultiSelectionEnabled()) { 223 fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 224 } else { 225 fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 226 fileList.clearSelection(); 227 getFileChooser().setSelectedFiles(null); 228 } 229 } else if (prop.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) { 230 if(getAccessoryPanel() != null) { 231 if(e.getOldValue() != null) { 232 getAccessoryPanel().remove((JComponent) e.getOldValue()); 233 } 234 JComponent accessory = (JComponent) e.getNewValue(); 235 if(accessory != null) { 236 getAccessoryPanel().add(accessory, BorderLayout.CENTER); 237 getAccessoryPanel().setPreferredSize(PREF_ACC_SIZE); 238 getAccessoryPanel().setMaximumSize(MAX_SIZE); 239 } else { 240 getAccessoryPanel().setPreferredSize(ZERO_ACC_SIZE); 241 getAccessoryPanel().setMaximumSize(ZERO_ACC_SIZE); 242 } 243 } 244 } else if (prop.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) || 245 prop.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY) || 246 prop.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) { 247 approveButton.setText(getApproveButtonText(getFileChooser())); 248 approveButton.setToolTipText(getApproveButtonToolTipText(getFileChooser())); 249 } else if (prop.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) { 250 doControlButtonsChanged(e); 251 } else if (prop.equals("componentOrientation")) { 252 ComponentOrientation o = (ComponentOrientation)e.getNewValue(); 253 JFileChooser cc = (JFileChooser)e.getSource(); 254 if (o != (ComponentOrientation)e.getOldValue()) { 255 cc.applyComponentOrientation(o); 256 } 257 } 258 } 259 }; 260 } 261 262 // 263 // ComponentUI Interface Implementation methods 264 // 265 public static ComponentUI createUI(JComponent c) { 266 return new MotifFileChooserUI((JFileChooser)c); 267 } 268 269 public void installUI(JComponent c) { 270 super.installUI(c); 271 } 272 273 public void uninstallUI(JComponent c) { 274 c.removePropertyChangeListener(filterComboBoxModel); 275 approveButton.removeActionListener(getApproveSelectionAction()); 276 filenameTextField.removeActionListener(getApproveSelectionAction()); 277 super.uninstallUI(c); 278 } 279 280 public void installComponents(JFileChooser fc) { 281 fc.setLayout(new BorderLayout(10, 10)); 282 fc.setAlignmentX(JComponent.CENTER_ALIGNMENT); 283 284 JPanel interior = new JPanel() { 285 public Insets getInsets() { 286 return insets; 287 } 288 }; 289 interior.setInheritsPopupMenu(true); 290 align(interior); 291 interior.setLayout(new BoxLayout(interior, BoxLayout.PAGE_AXIS)); 292 293 fc.add(interior, BorderLayout.CENTER); 294 295 // PENDING(jeff) - I18N 296 JLabel l = new JLabel(pathLabelText); 297 l.setDisplayedMnemonic(pathLabelMnemonic); 298 align(l); 299 interior.add(l); 300 301 File currentDirectory = fc.getCurrentDirectory(); 302 String curDirName = null; 303 if(currentDirectory != null) { 304 curDirName = currentDirectory.getPath(); 305 } 306 pathField = new JTextField(curDirName) { 307 public Dimension getMaximumSize() { 308 Dimension d = super.getMaximumSize(); 309 d.height = getPreferredSize().height; 310 return d; 311 } 312 }; 313 pathField.setInheritsPopupMenu(true); 314 l.setLabelFor(pathField); 315 align(pathField); 316 317 // Change to folder on return 318 pathField.addActionListener(getUpdateAction()); 319 interior.add(pathField); 320 321 interior.add(Box.createRigidArea(vstrut10)); 322 323 324 // CENTER: left, right accessory 325 JPanel centerPanel = new JPanel(); 326 centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.LINE_AXIS)); 327 align(centerPanel); 328 329 // left panel - Filter & folderList 330 JPanel leftPanel = new JPanel(); 331 leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS)); 332 align(leftPanel); 333 334 // add the filter PENDING(jeff) - I18N 335 l = new JLabel(filterLabelText); 336 l.setDisplayedMnemonic(filterLabelMnemonic); 337 align(l); 338 leftPanel.add(l); 339 340 filterComboBox = new JComboBox<FileFilter>() { 341 public Dimension getMaximumSize() { 342 Dimension d = super.getMaximumSize(); 343 d.height = getPreferredSize().height; 344 return d; 345 } 346 }; 347 filterComboBox.setInheritsPopupMenu(true); 348 l.setLabelFor(filterComboBox); 349 filterComboBoxModel = createFilterComboBoxModel(); 350 filterComboBox.setModel(filterComboBoxModel); 351 filterComboBox.setRenderer(createFilterComboBoxRenderer()); 352 fc.addPropertyChangeListener(filterComboBoxModel); 353 align(filterComboBox); 354 leftPanel.add(filterComboBox); 355 356 // leftPanel.add(Box.createRigidArea(vstrut10)); 357 358 // Add the Folder List PENDING(jeff) - I18N 359 l = new JLabel(foldersLabelText); 360 l.setDisplayedMnemonic(foldersLabelMnemonic); 361 align(l); 362 leftPanel.add(l); 363 JScrollPane sp = createDirectoryList(); 364 sp.getVerticalScrollBar().setFocusable(false); 365 sp.getHorizontalScrollBar().setFocusable(false); 366 sp.setInheritsPopupMenu(true); 367 l.setLabelFor(sp.getViewport().getView()); 368 leftPanel.add(sp); 369 leftPanel.setInheritsPopupMenu(true); 370 371 372 // create files list 373 JPanel rightPanel = new JPanel(); 374 align(rightPanel); 375 rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS)); 376 rightPanel.setInheritsPopupMenu(true); 377 378 l = new JLabel(filesLabelText); 379 l.setDisplayedMnemonic(filesLabelMnemonic); 380 align(l); 381 rightPanel.add(l); 382 sp = createFilesList(); 383 l.setLabelFor(sp.getViewport().getView()); 384 rightPanel.add(sp); 385 sp.setInheritsPopupMenu(true); 386 387 centerPanel.add(leftPanel); 388 centerPanel.add(Box.createRigidArea(hstrut10)); 389 centerPanel.add(rightPanel); 390 centerPanel.setInheritsPopupMenu(true); 391 392 JComponent accessoryPanel = getAccessoryPanel(); 393 JComponent accessory = fc.getAccessory(); 394 if(accessoryPanel != null) { 395 if(accessory == null) { 396 accessoryPanel.setPreferredSize(ZERO_ACC_SIZE); 397 accessoryPanel.setMaximumSize(ZERO_ACC_SIZE); 398 } else { 399 getAccessoryPanel().add(accessory, BorderLayout.CENTER); 400 accessoryPanel.setPreferredSize(PREF_ACC_SIZE); 401 accessoryPanel.setMaximumSize(MAX_SIZE); 402 } 403 align(accessoryPanel); 404 centerPanel.add(accessoryPanel); 405 accessoryPanel.setInheritsPopupMenu(true); 406 } 407 interior.add(centerPanel); 408 interior.add(Box.createRigidArea(vstrut10)); 409 410 // add the filename field PENDING(jeff) - I18N 411 fileNameLabel = new JLabel(); 412 populateFileNameLabel(); 413 align(fileNameLabel); 414 interior.add(fileNameLabel); 415 416 filenameTextField = new JTextField() { 417 public Dimension getMaximumSize() { 418 Dimension d = super.getMaximumSize(); 419 d.height = getPreferredSize().height; 420 return d; 421 } 422 }; 423 filenameTextField.setInheritsPopupMenu(true); 424 fileNameLabel.setLabelFor(filenameTextField); 425 filenameTextField.addActionListener(getApproveSelectionAction()); 426 align(filenameTextField); 427 filenameTextField.setAlignmentX(JComponent.LEFT_ALIGNMENT); 428 interior.add(filenameTextField); 429 430 bottomPanel = getBottomPanel(); 431 bottomPanel.add(new JSeparator(), BorderLayout.NORTH); 432 433 // Add buttons 434 JPanel buttonPanel = new JPanel(); 435 align(buttonPanel); 436 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS)); 437 buttonPanel.add(Box.createGlue()); 438 439 approveButton = new JButton(getApproveButtonText(fc)) { 440 public Dimension getMaximumSize() { 441 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); 442 } 443 }; 444 approveButton.setMnemonic(getApproveButtonMnemonic(fc)); 445 approveButton.setToolTipText(getApproveButtonToolTipText(fc)); 446 approveButton.setInheritsPopupMenu(true); 447 align(approveButton); 448 approveButton.setMargin(buttonMargin); 449 approveButton.addActionListener(getApproveSelectionAction()); 450 buttonPanel.add(approveButton); 451 buttonPanel.add(Box.createGlue()); 452 453 JButton updateButton = new JButton(updateButtonText) { 454 public Dimension getMaximumSize() { 455 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); 456 } 457 }; 458 updateButton.setMnemonic(updateButtonMnemonic); 459 updateButton.setToolTipText(updateButtonToolTipText); 460 updateButton.setInheritsPopupMenu(true); 461 align(updateButton); 462 updateButton.setMargin(buttonMargin); 463 updateButton.addActionListener(getUpdateAction()); 464 buttonPanel.add(updateButton); 465 buttonPanel.add(Box.createGlue()); 466 467 JButton cancelButton = new JButton(cancelButtonText) { 468 public Dimension getMaximumSize() { 469 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); 470 } 471 }; 472 cancelButton.setMnemonic(cancelButtonMnemonic); 473 cancelButton.setToolTipText(cancelButtonToolTipText); 474 cancelButton.setInheritsPopupMenu(true); 475 align(cancelButton); 476 cancelButton.setMargin(buttonMargin); 477 cancelButton.addActionListener(getCancelSelectionAction()); 478 buttonPanel.add(cancelButton); 479 buttonPanel.add(Box.createGlue()); 480 481 JButton helpButton = new JButton(helpButtonText) { 482 public Dimension getMaximumSize() { 483 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); 484 } 485 }; 486 helpButton.setMnemonic(helpButtonMnemonic); 487 helpButton.setToolTipText(helpButtonToolTipText); 488 align(helpButton); 489 helpButton.setMargin(buttonMargin); 490 helpButton.setEnabled(false); 491 helpButton.setInheritsPopupMenu(true); 492 buttonPanel.add(helpButton); 493 buttonPanel.add(Box.createGlue()); 494 buttonPanel.setInheritsPopupMenu(true); 495 496 bottomPanel.add(buttonPanel, BorderLayout.SOUTH); 497 bottomPanel.setInheritsPopupMenu(true); 498 if (fc.getControlButtonsAreShown()) { 499 fc.add(bottomPanel, BorderLayout.SOUTH); 500 } 501 } 502 503 protected JPanel getBottomPanel() { 504 if (bottomPanel == null) { 505 bottomPanel = new JPanel(new BorderLayout(0, 4)); 506 } 507 return bottomPanel; 508 } 509 510 private void doControlButtonsChanged(PropertyChangeEvent e) { 511 if (getFileChooser().getControlButtonsAreShown()) { 512 getFileChooser().add(bottomPanel,BorderLayout.SOUTH); 513 } else { 514 getFileChooser().remove(getBottomPanel()); 515 } 516 } 517 518 public void uninstallComponents(JFileChooser fc) { 519 fc.removeAll(); 520 bottomPanel = null; 521 if (filterComboBoxModel != null) { 522 fc.removePropertyChangeListener(filterComboBoxModel); 523 } 524 } 525 526 protected void installStrings(JFileChooser fc) { 527 super.installStrings(fc); 528 529 Locale l = fc.getLocale(); 530 531 enterFolderNameLabelText = UIManager.getString("FileChooser.enterFolderNameLabelText",l); 532 enterFolderNameLabelMnemonic = getMnemonic("FileChooser.enterFolderNameLabelMnemonic", l); 533 enterFileNameLabelText = UIManager.getString("FileChooser.enterFileNameLabelText",l); 534 enterFileNameLabelMnemonic = getMnemonic("FileChooser.enterFileNameLabelMnemonic", l); 535 536 filesLabelText = UIManager.getString("FileChooser.filesLabelText",l); 537 filesLabelMnemonic = getMnemonic("FileChooser.filesLabelMnemonic", l); 538 539 foldersLabelText = UIManager.getString("FileChooser.foldersLabelText",l); 540 foldersLabelMnemonic = getMnemonic("FileChooser.foldersLabelMnemonic", l); 541 542 pathLabelText = UIManager.getString("FileChooser.pathLabelText",l); 543 pathLabelMnemonic = getMnemonic("FileChooser.pathLabelMnemonic", l); 544 545 filterLabelText = UIManager.getString("FileChooser.filterLabelText",l); 546 filterLabelMnemonic = getMnemonic("FileChooser.filterLabelMnemonic", l); 547 } 548 549 private Integer getMnemonic(String key, Locale l) { 550 return SwingUtilities2.getUIDefaultsInt(key, l); 551 } 552 553 protected void installIcons(JFileChooser fc) { 554 // Since motif doesn't have button icons, leave this empty 555 // which overrides the supertype icon loading 556 } 557 558 protected void uninstallIcons(JFileChooser fc) { 559 // Since motif doesn't have button icons, leave this empty 560 // which overrides the supertype icon loading 561 } 562 563 protected JScrollPane createFilesList() { 564 fileList = new JList<File>(); 565 566 if(getFileChooser().isMultiSelectionEnabled()) { 567 fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 568 } else { 569 fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 570 } 571 572 fileList.setModel(new MotifFileListModel()); 573 fileList.getSelectionModel().removeSelectionInterval(0, 0); 574 fileList.setCellRenderer(new FileCellRenderer()); 575 fileList.addListSelectionListener(createListSelectionListener(getFileChooser())); 576 fileList.addMouseListener(createDoubleClickListener(getFileChooser(), fileList)); 577 fileList.addMouseListener(new MouseAdapter() { 578 public void mouseClicked(MouseEvent e) { 579 JFileChooser chooser = getFileChooser(); 580 if (SwingUtilities.isLeftMouseButton(e) && !chooser.isMultiSelectionEnabled()) { 581 int index = SwingUtilities2.loc2IndexFileList(fileList, e.getPoint()); 582 if (index >= 0) { 583 File file = fileList.getModel().getElementAt(index); 584 setFileName(chooser.getName(file)); 585 } 586 } 587 } 588 }); 589 align(fileList); 590 JScrollPane scrollpane = new JScrollPane(fileList); 591 scrollpane.setPreferredSize(prefListSize); 592 scrollpane.setMaximumSize(MAX_SIZE); 593 align(scrollpane); 594 fileList.setInheritsPopupMenu(true); 595 scrollpane.setInheritsPopupMenu(true); 596 return scrollpane; 597 } 598 599 protected JScrollPane createDirectoryList() { 600 directoryList = new JList<File>(); 601 align(directoryList); 602 603 directoryList.setCellRenderer(new DirectoryCellRenderer()); 604 directoryList.setModel(new MotifDirectoryListModel()); 605 directoryList.getSelectionModel().removeSelectionInterval(0, 0); 606 directoryList.addMouseListener(createDoubleClickListener(getFileChooser(), directoryList)); 607 directoryList.addListSelectionListener(createListSelectionListener(getFileChooser())); 608 directoryList.setInheritsPopupMenu(true); 609 610 JScrollPane scrollpane = new JScrollPane(directoryList); 611 scrollpane.setMaximumSize(MAX_SIZE); 612 scrollpane.setPreferredSize(prefListSize); 613 scrollpane.setInheritsPopupMenu(true); 614 align(scrollpane); 615 return scrollpane; 616 } 617 618 public Dimension getPreferredSize(JComponent c) { 619 Dimension prefSize = 620 (getFileChooser().getAccessory() != null) ? WITH_ACCELERATOR_PREF_SIZE : PREF_SIZE; 621 Dimension d = c.getLayout().preferredLayoutSize(c); 622 if (d != null) { 623 return new Dimension(d.width < prefSize.width ? prefSize.width : d.width, 624 d.height < prefSize.height ? prefSize.height : d.height); 625 } else { 626 return prefSize; 627 } 628 } 629 630 public Dimension getMinimumSize(JComponent x) { 631 return MIN_SIZE; 632 } 633 634 public Dimension getMaximumSize(JComponent x) { 635 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 636 } 637 638 protected void align(JComponent c) { 639 c.setAlignmentX(JComponent.LEFT_ALIGNMENT); 640 c.setAlignmentY(JComponent.TOP_ALIGNMENT); 641 } 642 643 protected class FileCellRenderer extends DefaultListCellRenderer { 644 public Component getListCellRendererComponent(JList list, Object value, int index, 645 boolean isSelected, boolean cellHasFocus) { 646 647 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 648 setText(getFileChooser().getName((File) value)); 649 setInheritsPopupMenu(true); 650 return this; 651 } 652 } 653 654 protected class DirectoryCellRenderer extends DefaultListCellRenderer { 655 public Component getListCellRendererComponent(JList list, Object value, int index, 656 boolean isSelected, boolean cellHasFocus) { 657 658 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 659 setText(getFileChooser().getName((File) value)); 660 setInheritsPopupMenu(true); 661 return this; 662 } 663 } 664 665 protected class MotifDirectoryListModel extends AbstractListModel<File> implements ListDataListener { 666 public MotifDirectoryListModel() { 667 getModel().addListDataListener(this); 668 } 669 670 public int getSize() { 671 return getModel().getDirectories().size(); 672 } 673 674 public File getElementAt(int index) { 675 return getModel().getDirectories().elementAt(index); 676 } 677 678 public void intervalAdded(ListDataEvent e) { 679 fireIntervalAdded(this, e.getIndex0(), e.getIndex1()); 680 } 681 682 public void intervalRemoved(ListDataEvent e) { 683 fireIntervalRemoved(this, e.getIndex0(), e.getIndex1()); 684 } 685 686 // PENDING(jeff) - this is inefficient - should sent out 687 // incremental adjustment values instead of saying that the 688 // whole list has changed. 689 public void fireContentsChanged() { 690 fireContentsChanged(this, 0, getModel().getDirectories().size()-1); 691 } 692 693 // PENDING(jeff) - fire the correct interval changed - currently sending 694 // out that everything has changed 695 public void contentsChanged(ListDataEvent e) { 696 fireContentsChanged(); 697 } 698 699 } 700 701 protected class MotifFileListModel extends AbstractListModel<File> implements ListDataListener { 702 public MotifFileListModel() { 703 getModel().addListDataListener(this); 704 } 705 706 public int getSize() { 707 return getModel().getFiles().size(); 708 } 709 710 public boolean contains(Object o) { 711 return getModel().getFiles().contains(o); 712 } 713 714 public int indexOf(Object o) { 715 return getModel().getFiles().indexOf(o); 716 } 717 718 public File getElementAt(int index) { 719 return getModel().getFiles().elementAt(index); 720 } 721 722 public void intervalAdded(ListDataEvent e) { 723 fireIntervalAdded(this, e.getIndex0(), e.getIndex1()); 724 } 725 726 public void intervalRemoved(ListDataEvent e) { 727 fireIntervalRemoved(this, e.getIndex0(), e.getIndex1()); 728 } 729 730 // PENDING(jeff) - this is inefficient - should sent out 731 // incremental adjustment values instead of saying that the 732 // whole list has changed. 733 public void fireContentsChanged() { 734 fireContentsChanged(this, 0, getModel().getFiles().size()-1); 735 } 736 737 // PENDING(jeff) - fire the interval changed 738 public void contentsChanged(ListDataEvent e) { 739 fireContentsChanged(); 740 } 741 742 } 743 744 // 745 // DataModel for Types Comboxbox 746 // 747 protected FilterComboBoxModel createFilterComboBoxModel() { 748 return new FilterComboBoxModel(); 749 } 750 751 // 752 // Renderer for Types ComboBox 753 // 754 protected FilterComboBoxRenderer createFilterComboBoxRenderer() { 755 return new FilterComboBoxRenderer(); 756 } 757 758 759 /** 760 * Render different type sizes and styles. 761 */ 762 public class FilterComboBoxRenderer extends DefaultListCellRenderer { 763 public Component getListCellRendererComponent(JList list, 764 Object value, int index, boolean isSelected, 765 boolean cellHasFocus) { 766 767 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 768 769 if (value != null && value instanceof FileFilter) { 770 setText(((FileFilter)value).getDescription()); 771 } 772 773 return this; 774 } 775 } 776 777 /** 778 * Data model for a type-face selection combo-box. 779 */ 780 protected class FilterComboBoxModel extends AbstractListModel<FileFilter> implements ComboBoxModel<FileFilter>, 781 PropertyChangeListener { 782 protected FileFilter[] filters; 783 protected FilterComboBoxModel() { 784 super(); 785 filters = getFileChooser().getChoosableFileFilters(); 786 } 787 788 public void propertyChange(PropertyChangeEvent e) { 789 String prop = e.getPropertyName(); 790 if(prop.equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)) { 791 filters = (FileFilter[]) e.getNewValue(); 792 fireContentsChanged(this, -1, -1); 793 } else if (prop.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) { 794 fireContentsChanged(this, -1, -1); 795 } 796 } 797 798 public void setSelectedItem(Object filter) { 799 if(filter != null) { 800 getFileChooser().setFileFilter((FileFilter) filter); 801 fireContentsChanged(this, -1, -1); 802 } 803 } 804 805 public Object getSelectedItem() { 806 // Ensure that the current filter is in the list. 807 // NOTE: we shouldnt' have to do this, since JFileChooser adds 808 // the filter to the choosable filters list when the filter 809 // is set. Lets be paranoid just in case someone overrides 810 // setFileFilter in JFileChooser. 811 FileFilter currentFilter = getFileChooser().getFileFilter(); 812 boolean found = false; 813 if(currentFilter != null) { 814 for (FileFilter filter : filters) { 815 if (filter == currentFilter) { 816 found = true; 817 } 818 } 819 if (!found) { 820 getFileChooser().addChoosableFileFilter(currentFilter); 821 } 822 } 823 return getFileChooser().getFileFilter(); 824 } 825 826 public int getSize() { 827 if(filters != null) { 828 return filters.length; 829 } else { 830 return 0; 831 } 832 } 833 834 public FileFilter getElementAt(int index) { 835 if(index > getSize() - 1) { 836 // This shouldn't happen. Try to recover gracefully. 837 return getFileChooser().getFileFilter(); 838 } 839 if(filters != null) { 840 return filters[index]; 841 } else { 842 return null; 843 } 844 } 845 } 846 847 protected JButton getApproveButton(JFileChooser fc) { 848 return approveButton; 849 } 850 851 }