1/* 2 * Copyright (c) 1997, 2015, 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 26package com.sun.java.swing.plaf.motif; 27 28import javax.swing.*; 29import javax.swing.filechooser.*; 30import javax.swing.event.*; 31import javax.swing.plaf.*; 32import javax.swing.plaf.basic.*; 33import java.awt.*; 34import java.awt.event.MouseAdapter; 35import java.awt.event.MouseEvent; 36import java.beans.*; 37import java.io.File; 38import java.io.IOException; 39import java.util.*; 40import sun.awt.shell.ShellFolder; 41import sun.swing.SwingUtilities2; 42 43/** 44 * Motif FileChooserUI. 45 * 46 * @author Jeff Dinkins 47 */ 48public 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 final int MIN_WIDTH = 200; 69 private static final int MIN_HEIGHT = 300; 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 StringBuilder sb = new StringBuilder(); 125 for (int i = 0; files != null && i < files.length; i++) { 126 if (i > 0) { 127 sb.append(" "); 128 } 129 if (files.length > 1) { 130 sb.append("\""); 131 } 132 sb.append(fileNameString(files[i])); 133 if (files.length > 1) { 134 sb.append("\""); 135 } 136 } 137 return sb.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 @SuppressWarnings("serial") // anonymous class 285 JPanel interior = new JPanel() { 286 public Insets getInsets() { 287 return insets; 288 } 289 }; 290 interior.setInheritsPopupMenu(true); 291 align(interior); 292 interior.setLayout(new BoxLayout(interior, BoxLayout.PAGE_AXIS)); 293 294 fc.add(interior, BorderLayout.CENTER); 295 296 // PENDING(jeff) - I18N 297 JLabel l = new JLabel(pathLabelText); 298 l.setDisplayedMnemonic(pathLabelMnemonic); 299 align(l); 300 interior.add(l); 301 302 File currentDirectory = fc.getCurrentDirectory(); 303 String curDirName = null; 304 if(currentDirectory != null) { 305 curDirName = currentDirectory.getPath(); 306 } 307 308 @SuppressWarnings("serial") // anonymous class 309 JTextField tmp1 = new JTextField(curDirName, 35) { 310 public Dimension getMaximumSize() { 311 Dimension d = super.getMaximumSize(); 312 d.height = getPreferredSize().height; 313 return d; 314 } 315 }; 316 pathField = tmp1; 317 pathField.setInheritsPopupMenu(true); 318 l.setLabelFor(pathField); 319 align(pathField); 320 321 // Change to folder on return 322 pathField.addActionListener(getUpdateAction()); 323 interior.add(pathField); 324 325 interior.add(Box.createRigidArea(vstrut10)); 326 327 328 // CENTER: left, right accessory 329 JPanel centerPanel = new JPanel(); 330 centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.LINE_AXIS)); 331 align(centerPanel); 332 333 // left panel - Filter & folderList 334 JPanel leftPanel = new JPanel(); 335 leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS)); 336 align(leftPanel); 337 338 // add the filter PENDING(jeff) - I18N 339 l = new JLabel(filterLabelText); 340 l.setDisplayedMnemonic(filterLabelMnemonic); 341 align(l); 342 leftPanel.add(l); 343 344 @SuppressWarnings("serial") // anonymous class 345 JComboBox<FileFilter> tmp2 = new JComboBox<FileFilter>() { 346 public Dimension getMaximumSize() { 347 Dimension d = super.getMaximumSize(); 348 d.height = getPreferredSize().height; 349 return d; 350 } 351 }; 352 filterComboBox = tmp2; 353 filterComboBox.setInheritsPopupMenu(true); 354 l.setLabelFor(filterComboBox); 355 filterComboBoxModel = createFilterComboBoxModel(); 356 filterComboBox.setModel(filterComboBoxModel); 357 filterComboBox.setRenderer(createFilterComboBoxRenderer()); 358 fc.addPropertyChangeListener(filterComboBoxModel); 359 align(filterComboBox); 360 leftPanel.add(filterComboBox); 361 362 // leftPanel.add(Box.createRigidArea(vstrut10)); 363 364 // Add the Folder List PENDING(jeff) - I18N 365 l = new JLabel(foldersLabelText); 366 l.setDisplayedMnemonic(foldersLabelMnemonic); 367 align(l); 368 leftPanel.add(l); 369 JScrollPane sp = createDirectoryList(); 370 sp.getVerticalScrollBar().setFocusable(false); 371 sp.getHorizontalScrollBar().setFocusable(false); 372 sp.setInheritsPopupMenu(true); 373 l.setLabelFor(sp.getViewport().getView()); 374 leftPanel.add(sp); 375 leftPanel.setInheritsPopupMenu(true); 376 377 378 // create files list 379 JPanel rightPanel = new JPanel(); 380 align(rightPanel); 381 rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS)); 382 rightPanel.setInheritsPopupMenu(true); 383 384 l = new JLabel(filesLabelText); 385 l.setDisplayedMnemonic(filesLabelMnemonic); 386 align(l); 387 rightPanel.add(l); 388 sp = createFilesList(); 389 l.setLabelFor(sp.getViewport().getView()); 390 rightPanel.add(sp); 391 sp.setInheritsPopupMenu(true); 392 393 centerPanel.add(leftPanel); 394 centerPanel.add(Box.createRigidArea(hstrut10)); 395 centerPanel.add(rightPanel); 396 centerPanel.setInheritsPopupMenu(true); 397 398 JComponent accessoryPanel = getAccessoryPanel(); 399 JComponent accessory = fc.getAccessory(); 400 if(accessoryPanel != null) { 401 if(accessory == null) { 402 accessoryPanel.setPreferredSize(ZERO_ACC_SIZE); 403 accessoryPanel.setMaximumSize(ZERO_ACC_SIZE); 404 } else { 405 getAccessoryPanel().add(accessory, BorderLayout.CENTER); 406 accessoryPanel.setPreferredSize(PREF_ACC_SIZE); 407 accessoryPanel.setMaximumSize(MAX_SIZE); 408 } 409 align(accessoryPanel); 410 centerPanel.add(accessoryPanel); 411 accessoryPanel.setInheritsPopupMenu(true); 412 } 413 interior.add(centerPanel); 414 interior.add(Box.createRigidArea(vstrut10)); 415 416 // add the filename field PENDING(jeff) - I18N 417 fileNameLabel = new JLabel(); 418 populateFileNameLabel(); 419 align(fileNameLabel); 420 interior.add(fileNameLabel); 421 422 @SuppressWarnings("serial") // anonymous class 423 JTextField tmp3 = new JTextField(35) { 424 public Dimension getMaximumSize() { 425 Dimension d = super.getMaximumSize(); 426 d.height = getPreferredSize().height; 427 return d; 428 } 429 }; 430 filenameTextField = tmp3; 431 filenameTextField.setInheritsPopupMenu(true); 432 fileNameLabel.setLabelFor(filenameTextField); 433 filenameTextField.addActionListener(getApproveSelectionAction()); 434 align(filenameTextField); 435 filenameTextField.setAlignmentX(JComponent.LEFT_ALIGNMENT); 436 interior.add(filenameTextField); 437 438 bottomPanel = getBottomPanel(); 439 bottomPanel.add(new JSeparator(), BorderLayout.NORTH); 440 441 // Add buttons 442 JPanel buttonPanel = new JPanel(); 443 align(buttonPanel); 444 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS)); 445 buttonPanel.add(Box.createGlue()); 446 447 @SuppressWarnings("serial") // anonymous class 448 JButton tmp4 = new JButton(getApproveButtonText(fc)) { 449 public Dimension getMaximumSize() { 450 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); 451 } 452 }; 453 approveButton = tmp4; 454 approveButton.setMnemonic(getApproveButtonMnemonic(fc)); 455 approveButton.setToolTipText(getApproveButtonToolTipText(fc)); 456 approveButton.setInheritsPopupMenu(true); 457 align(approveButton); 458 approveButton.setMargin(buttonMargin); 459 approveButton.addActionListener(getApproveSelectionAction()); 460 buttonPanel.add(approveButton); 461 buttonPanel.add(Box.createGlue()); 462 463 @SuppressWarnings("serial") // anonymous class 464 JButton updateButton = new JButton(updateButtonText) { 465 public Dimension getMaximumSize() { 466 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); 467 } 468 }; 469 updateButton.setMnemonic(updateButtonMnemonic); 470 updateButton.setToolTipText(updateButtonToolTipText); 471 updateButton.setInheritsPopupMenu(true); 472 align(updateButton); 473 updateButton.setMargin(buttonMargin); 474 updateButton.addActionListener(getUpdateAction()); 475 buttonPanel.add(updateButton); 476 buttonPanel.add(Box.createGlue()); 477 478 @SuppressWarnings("serial") // anonymous class 479 JButton cancelButton = new JButton(cancelButtonText) { 480 public Dimension getMaximumSize() { 481 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); 482 } 483 }; 484 cancelButton.setMnemonic(cancelButtonMnemonic); 485 cancelButton.setToolTipText(cancelButtonToolTipText); 486 cancelButton.setInheritsPopupMenu(true); 487 align(cancelButton); 488 cancelButton.setMargin(buttonMargin); 489 cancelButton.addActionListener(getCancelSelectionAction()); 490 buttonPanel.add(cancelButton); 491 buttonPanel.add(Box.createGlue()); 492 493 @SuppressWarnings("serial") // anonymous class 494 JButton helpButton = new JButton(helpButtonText) { 495 public Dimension getMaximumSize() { 496 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height); 497 } 498 }; 499 helpButton.setMnemonic(helpButtonMnemonic); 500 helpButton.setToolTipText(helpButtonToolTipText); 501 align(helpButton); 502 helpButton.setMargin(buttonMargin); 503 helpButton.setEnabled(false); 504 helpButton.setInheritsPopupMenu(true); 505 buttonPanel.add(helpButton); 506 buttonPanel.add(Box.createGlue()); 507 buttonPanel.setInheritsPopupMenu(true); 508 509 bottomPanel.add(buttonPanel, BorderLayout.SOUTH); 510 bottomPanel.setInheritsPopupMenu(true); 511 if (fc.getControlButtonsAreShown()) { 512 fc.add(bottomPanel, BorderLayout.SOUTH); 513 } 514 } 515 516 protected JPanel getBottomPanel() { 517 if (bottomPanel == null) { 518 bottomPanel = new JPanel(new BorderLayout(0, 4)); 519 } 520 return bottomPanel; 521 } 522 523 private void doControlButtonsChanged(PropertyChangeEvent e) { 524 if (getFileChooser().getControlButtonsAreShown()) { 525 getFileChooser().add(bottomPanel,BorderLayout.SOUTH); 526 } else { 527 getFileChooser().remove(getBottomPanel()); 528 } 529 } 530 531 public void uninstallComponents(JFileChooser fc) { 532 fc.removeAll(); 533 bottomPanel = null; 534 if (filterComboBoxModel != null) { 535 fc.removePropertyChangeListener(filterComboBoxModel); 536 } 537 } 538 539 protected void installStrings(JFileChooser fc) { 540 super.installStrings(fc); 541 542 Locale l = fc.getLocale(); 543 544 enterFolderNameLabelText = UIManager.getString("FileChooser.enterFolderNameLabelText",l); 545 enterFolderNameLabelMnemonic = getMnemonic("FileChooser.enterFolderNameLabelMnemonic", l); 546 enterFileNameLabelText = UIManager.getString("FileChooser.enterFileNameLabelText",l); 547 enterFileNameLabelMnemonic = getMnemonic("FileChooser.enterFileNameLabelMnemonic", l); 548 549 filesLabelText = UIManager.getString("FileChooser.filesLabelText",l); 550 filesLabelMnemonic = getMnemonic("FileChooser.filesLabelMnemonic", l); 551 552 foldersLabelText = UIManager.getString("FileChooser.foldersLabelText",l); 553 foldersLabelMnemonic = getMnemonic("FileChooser.foldersLabelMnemonic", l); 554 555 pathLabelText = UIManager.getString("FileChooser.pathLabelText",l); 556 pathLabelMnemonic = getMnemonic("FileChooser.pathLabelMnemonic", l); 557 558 filterLabelText = UIManager.getString("FileChooser.filterLabelText",l); 559 filterLabelMnemonic = getMnemonic("FileChooser.filterLabelMnemonic", l); 560 } 561 562 private Integer getMnemonic(String key, Locale l) { 563 return SwingUtilities2.getUIDefaultsInt(key, l); 564 } 565 566 protected void installIcons(JFileChooser fc) { 567 // Since motif doesn't have button icons, leave this empty 568 // which overrides the supertype icon loading 569 } 570 571 protected void uninstallIcons(JFileChooser fc) { 572 // Since motif doesn't have button icons, leave this empty 573 // which overrides the supertype icon loading 574 } 575 576 protected JScrollPane createFilesList() { 577 fileList = new JList<File>(); 578 579 if(getFileChooser().isMultiSelectionEnabled()) { 580 fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 581 } else { 582 fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 583 } 584 585 fileList.setModel(new MotifFileListModel()); 586 fileList.getSelectionModel().removeSelectionInterval(0, 0); 587 fileList.setCellRenderer(new FileCellRenderer()); 588 fileList.addListSelectionListener(createListSelectionListener(getFileChooser())); 589 fileList.addMouseListener(createDoubleClickListener(getFileChooser(), fileList)); 590 fileList.addMouseListener(new MouseAdapter() { 591 public void mouseClicked(MouseEvent e) { 592 JFileChooser chooser = getFileChooser(); 593 if (SwingUtilities.isLeftMouseButton(e) && !chooser.isMultiSelectionEnabled()) { 594 int index = SwingUtilities2.loc2IndexFileList(fileList, e.getPoint()); 595 if (index >= 0) { 596 File file = fileList.getModel().getElementAt(index); 597 setFileName(chooser.getName(file)); 598 } 599 } 600 } 601 }); 602 align(fileList); 603 JScrollPane scrollpane = new JScrollPane(fileList); 604 scrollpane.setPreferredSize(prefListSize); 605 scrollpane.setMaximumSize(MAX_SIZE); 606 align(scrollpane); 607 fileList.setInheritsPopupMenu(true); 608 scrollpane.setInheritsPopupMenu(true); 609 return scrollpane; 610 } 611 612 protected JScrollPane createDirectoryList() { 613 directoryList = new JList<File>(); 614 align(directoryList); 615 616 directoryList.setCellRenderer(new DirectoryCellRenderer()); 617 directoryList.setModel(new MotifDirectoryListModel()); 618 directoryList.getSelectionModel().removeSelectionInterval(0, 0); 619 directoryList.addMouseListener(createDoubleClickListener(getFileChooser(), directoryList)); 620 directoryList.addListSelectionListener(createListSelectionListener(getFileChooser())); 621 directoryList.setInheritsPopupMenu(true); 622 623 JScrollPane scrollpane = new JScrollPane(directoryList); 624 scrollpane.setMaximumSize(MAX_SIZE); 625 scrollpane.setPreferredSize(prefListSize); 626 scrollpane.setInheritsPopupMenu(true); 627 align(scrollpane); 628 return scrollpane; 629 } 630 631 @Override 632 public Dimension getPreferredSize(JComponent c) { 633 Dimension prefSize = 634 (getFileChooser().getAccessory() != null) ? WITH_ACCELERATOR_PREF_SIZE : PREF_SIZE; 635 Dimension d = c.getLayout().preferredLayoutSize(c); 636 if (d != null) { 637 return new Dimension(d.width < prefSize.width ? prefSize.width : d.width, 638 d.height < prefSize.height ? prefSize.height : d.height); 639 } else { 640 return prefSize; 641 } 642 } 643 644 @Override 645 public Dimension getMinimumSize(JComponent x) { 646 return new Dimension(MIN_WIDTH, MIN_HEIGHT); 647 } 648 649 @Override 650 public Dimension getMaximumSize(JComponent x) { 651 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 652 } 653 654 protected void align(JComponent c) { 655 c.setAlignmentX(JComponent.LEFT_ALIGNMENT); 656 c.setAlignmentY(JComponent.TOP_ALIGNMENT); 657 } 658 659 @SuppressWarnings("serial") // Superclass is not serializable across versions 660 protected class FileCellRenderer extends DefaultListCellRenderer { 661 public Component getListCellRendererComponent(JList<?> list, Object value, int index, 662 boolean isSelected, boolean cellHasFocus) { 663 664 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 665 setText(getFileChooser().getName((File) value)); 666 setInheritsPopupMenu(true); 667 return this; 668 } 669 } 670 671 @SuppressWarnings("serial") // Superclass is not serializable across versions 672 protected class DirectoryCellRenderer extends DefaultListCellRenderer { 673 public Component getListCellRendererComponent(JList<?> list, Object value, int index, 674 boolean isSelected, boolean cellHasFocus) { 675 676 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 677 setText(getFileChooser().getName((File) value)); 678 setInheritsPopupMenu(true); 679 return this; 680 } 681 } 682 683 @SuppressWarnings("serial") // Superclass is not serializable across versions 684 protected class MotifDirectoryListModel extends AbstractListModel<File> implements ListDataListener { 685 public MotifDirectoryListModel() { 686 getModel().addListDataListener(this); 687 } 688 689 public int getSize() { 690 return getModel().getDirectories().size(); 691 } 692 693 public File getElementAt(int index) { 694 return getModel().getDirectories().elementAt(index); 695 } 696 697 public void intervalAdded(ListDataEvent e) { 698 fireIntervalAdded(this, e.getIndex0(), e.getIndex1()); 699 } 700 701 public void intervalRemoved(ListDataEvent e) { 702 fireIntervalRemoved(this, e.getIndex0(), e.getIndex1()); 703 } 704 705 // PENDING(jeff) - this is inefficient - should sent out 706 // incremental adjustment values instead of saying that the 707 // whole list has changed. 708 public void fireContentsChanged() { 709 fireContentsChanged(this, 0, getModel().getDirectories().size()-1); 710 } 711 712 // PENDING(jeff) - fire the correct interval changed - currently sending 713 // out that everything has changed 714 public void contentsChanged(ListDataEvent e) { 715 fireContentsChanged(); 716 } 717 718 } 719 720 @SuppressWarnings("serial") // Superclass is not serializable across versions 721 protected class MotifFileListModel extends AbstractListModel<File> implements ListDataListener { 722 public MotifFileListModel() { 723 getModel().addListDataListener(this); 724 } 725 726 public int getSize() { 727 return getModel().getFiles().size(); 728 } 729 730 public boolean contains(Object o) { 731 return getModel().getFiles().contains(o); 732 } 733 734 public int indexOf(Object o) { 735 return getModel().getFiles().indexOf(o); 736 } 737 738 public File getElementAt(int index) { 739 return getModel().getFiles().elementAt(index); 740 } 741 742 public void intervalAdded(ListDataEvent e) { 743 fireIntervalAdded(this, e.getIndex0(), e.getIndex1()); 744 } 745 746 public void intervalRemoved(ListDataEvent e) { 747 fireIntervalRemoved(this, e.getIndex0(), e.getIndex1()); 748 } 749 750 // PENDING(jeff) - this is inefficient - should sent out 751 // incremental adjustment values instead of saying that the 752 // whole list has changed. 753 public void fireContentsChanged() { 754 fireContentsChanged(this, 0, getModel().getFiles().size()-1); 755 } 756 757 // PENDING(jeff) - fire the interval changed 758 public void contentsChanged(ListDataEvent e) { 759 fireContentsChanged(); 760 } 761 762 } 763 764 // 765 // DataModel for Types Comboxbox 766 // 767 protected FilterComboBoxModel createFilterComboBoxModel() { 768 return new FilterComboBoxModel(); 769 } 770 771 // 772 // Renderer for Types ComboBox 773 // 774 protected FilterComboBoxRenderer createFilterComboBoxRenderer() { 775 return new FilterComboBoxRenderer(); 776 } 777 778 779 /** 780 * Render different type sizes and styles. 781 */ 782 @SuppressWarnings("serial") // Superclass is not serializable across versions 783 public class FilterComboBoxRenderer extends DefaultListCellRenderer { 784 public Component getListCellRendererComponent(JList<?> list, 785 Object value, int index, boolean isSelected, 786 boolean cellHasFocus) { 787 788 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 789 790 if (value != null && value instanceof FileFilter) { 791 setText(((FileFilter)value).getDescription()); 792 } 793 794 return this; 795 } 796 } 797 798 /** 799 * Data model for a type-face selection combo-box. 800 */ 801 @SuppressWarnings("serial") // Superclass is not serializable across versions 802 protected class FilterComboBoxModel extends AbstractListModel<FileFilter> implements ComboBoxModel<FileFilter>, 803 PropertyChangeListener { 804 protected FileFilter[] filters; 805 protected FilterComboBoxModel() { 806 super(); 807 filters = getFileChooser().getChoosableFileFilters(); 808 } 809 810 public void propertyChange(PropertyChangeEvent e) { 811 String prop = e.getPropertyName(); 812 if(prop.equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)) { 813 filters = (FileFilter[]) e.getNewValue(); 814 fireContentsChanged(this, -1, -1); 815 } else if (prop.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) { 816 fireContentsChanged(this, -1, -1); 817 } 818 } 819 820 public void setSelectedItem(Object filter) { 821 if(filter != null) { 822 getFileChooser().setFileFilter((FileFilter) filter); 823 fireContentsChanged(this, -1, -1); 824 } 825 } 826 827 public Object getSelectedItem() { 828 // Ensure that the current filter is in the list. 829 // NOTE: we shouldnt' have to do this, since JFileChooser adds 830 // the filter to the choosable filters list when the filter 831 // is set. Lets be paranoid just in case someone overrides 832 // setFileFilter in JFileChooser. 833 FileFilter currentFilter = getFileChooser().getFileFilter(); 834 boolean found = false; 835 if(currentFilter != null) { 836 for (FileFilter filter : filters) { 837 if (filter == currentFilter) { 838 found = true; 839 } 840 } 841 if (!found) { 842 getFileChooser().addChoosableFileFilter(currentFilter); 843 } 844 } 845 return getFileChooser().getFileFilter(); 846 } 847 848 public int getSize() { 849 if(filters != null) { 850 return filters.length; 851 } else { 852 return 0; 853 } 854 } 855 856 public FileFilter getElementAt(int index) { 857 if(index > getSize() - 1) { 858 // This shouldn't happen. Try to recover gracefully. 859 return getFileChooser().getFileFilter(); 860 } 861 if(filters != null) { 862 return filters[index]; 863 } else { 864 return null; 865 } 866 } 867 } 868 869 protected JButton getApproveButton(JFileChooser fc) { 870 return approveButton; 871 } 872 873} 874