1 /* 2 * Copyright (c) 1997, 2006, 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.windows; 27 28 import javax.swing.*; 29 import javax.swing.border.*; 30 import javax.swing.filechooser.*; 31 import javax.swing.event.*; 32 import javax.swing.plaf.*; 33 import javax.swing.plaf.basic.*; 34 import java.awt.*; 35 import java.awt.event.*; 36 import java.awt.image.BufferedImage; 37 import java.beans.*; 38 import java.io.File; 39 import java.io.FileNotFoundException; 40 import java.io.IOException; 41 import java.util.*; 42 import java.security.AccessController; 43 import java.security.PrivilegedAction; 44 45 import sun.awt.shell.ShellFolder; 46 import sun.awt.OSInfo; 47 import sun.swing.*; 48 49 import javax.accessibility.*; 50 51 /** 52 * Windows L&F implementation of a FileChooser. 53 * 54 * @author Jeff Dinkins 55 */ 56 public class WindowsFileChooserUI extends BasicFileChooserUI { 57 58 // The following are private because the implementation of the 59 // Windows FileChooser L&F is not complete yet. 60 61 private static final OSInfo.WindowsVersion OS_VERSION = OSInfo.getWindowsVersion(); 62 63 private JPanel centerPanel; 64 65 private JLabel lookInLabel; 66 private JComboBox directoryComboBox; 67 private DirectoryComboBoxModel directoryComboBoxModel; 68 private ActionListener directoryComboBoxAction = new DirectoryComboBoxAction(); 69 70 private FilterComboBoxModel filterComboBoxModel; 71 72 private JTextField filenameTextField; 73 private FilePane filePane; 74 private WindowsPlacesBar placesBar; 75 private boolean useShellFolder; 76 77 private JButton approveButton; 78 private JButton cancelButton; 79 80 private JPanel buttonPanel; 81 private JPanel bottomPanel; 82 83 private JComboBox filterComboBox; 84 85 private static final Dimension hstrut10 = new Dimension(10, 1); 86 87 private static final Dimension vstrut4 = new Dimension(1, 4); 88 private static final Dimension vstrut6 = new Dimension(1, 6); 89 private static final Dimension vstrut8 = new Dimension(1, 8); 90 91 private static final Insets shrinkwrap = new Insets(0,0,0,0); 92 93 // Preferred and Minimum sizes for the dialog box 94 private static int PREF_WIDTH = 425; 95 private static int PREF_HEIGHT = 245; 96 private static Dimension PREF_SIZE = new Dimension(PREF_WIDTH, PREF_HEIGHT); 97 98 private static int MIN_WIDTH = 425; 99 private static int MIN_HEIGHT = 245; 100 private static Dimension MIN_SIZE = new Dimension(MIN_WIDTH, MIN_HEIGHT); 101 102 private static int LIST_PREF_WIDTH = 444; 103 private static int LIST_PREF_HEIGHT = 138; 104 private static Dimension LIST_PREF_SIZE = new Dimension(LIST_PREF_WIDTH, LIST_PREF_HEIGHT); 105 106 // Labels, mnemonics, and tooltips (oh my!) 107 private int lookInLabelMnemonic = 0; 108 private String lookInLabelText = null; 109 private String saveInLabelText = null; 110 111 private int fileNameLabelMnemonic = 0; 112 private String fileNameLabelText = null; 113 private int folderNameLabelMnemonic = 0; 114 private String folderNameLabelText = null; 115 116 private int filesOfTypeLabelMnemonic = 0; 117 private String filesOfTypeLabelText = null; 118 119 private String upFolderToolTipText = null; 120 private String upFolderAccessibleName = null; 121 122 private String homeFolderToolTipText = null; 123 private String homeFolderAccessibleName = null; 124 125 private String newFolderToolTipText = null; 126 private String newFolderAccessibleName = null; 127 128 private String listViewButtonToolTipText = null; 129 private String listViewButtonAccessibleName = null; 130 131 private String detailsViewButtonToolTipText = null; 132 private String detailsViewButtonAccessibleName = null; 133 134 private String viewMenuButtonToolTipText = null; 135 private String viewMenuButtonAccessibleName = null; 136 137 private BasicFileView fileView = new WindowsFileView(); 138 139 private JLabel fileNameLabel; 140 141 private Icon viewMenuIcon = null; 142 143 private void populateFileNameLabel() { 144 if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) { 145 fileNameLabel.setText(folderNameLabelText); 146 fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic); 147 } else { 148 fileNameLabel.setText(fileNameLabelText); 149 fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic); 150 } 151 } 152 153 // 154 // ComponentUI Interface Implementation methods 155 // 156 public static ComponentUI createUI(JComponent c) { 157 return new WindowsFileChooserUI((JFileChooser) c); 158 } 159 160 public WindowsFileChooserUI(JFileChooser filechooser) { 161 super(filechooser); 162 } 163 164 public void installUI(JComponent c) { 165 super.installUI(c); 166 } 167 168 public void uninstallComponents(JFileChooser fc) { 169 fc.removeAll(); 170 } 171 172 private class WindowsFileChooserUIAccessor implements FilePane.FileChooserUIAccessor { 173 public JFileChooser getFileChooser() { 174 return WindowsFileChooserUI.this.getFileChooser(); 175 } 176 177 public BasicDirectoryModel getModel() { 178 return WindowsFileChooserUI.this.getModel(); 179 } 180 181 public JPanel createList() { 182 return WindowsFileChooserUI.this.createList(getFileChooser()); 183 } 184 185 public JPanel createDetailsView() { 186 return WindowsFileChooserUI.this.createDetailsView(getFileChooser()); 187 } 188 189 public boolean isDirectorySelected() { 190 return WindowsFileChooserUI.this.isDirectorySelected(); 191 } 192 193 public File getDirectory() { 194 return WindowsFileChooserUI.this.getDirectory(); 195 } 196 197 public Action getChangeToParentDirectoryAction() { 198 return WindowsFileChooserUI.this.getChangeToParentDirectoryAction(); 199 } 200 201 public Action getApproveSelectionAction() { 202 return WindowsFileChooserUI.this.getApproveSelectionAction(); 203 } 204 205 public Action getNewFolderAction() { 206 return WindowsFileChooserUI.this.getNewFolderAction(); 207 } 208 209 public MouseListener createDoubleClickListener(JList list) { 210 return WindowsFileChooserUI.this.createDoubleClickListener(getFileChooser(), 211 list); 212 } 213 214 public ListSelectionListener createListSelectionListener() { 215 return WindowsFileChooserUI.this.createListSelectionListener(getFileChooser()); 216 } 217 218 public boolean usesShellFolder() { 219 return useShellFolder; 220 } 221 } 222 223 public void installComponents(JFileChooser fc) { 224 filePane = new FilePane(new WindowsFileChooserUIAccessor()); 225 fc.addPropertyChangeListener(filePane); 226 227 FileSystemView fsv = fc.getFileSystemView(); 228 229 fc.setBorder(new EmptyBorder(4, 10, 10, 10)); 230 fc.setLayout(new BorderLayout(8, 8)); 231 232 updateUseShellFolder(); 233 234 // ********************************* // 235 // **** Construct the top panel **** // 236 // ********************************* // 237 238 // Directory manipulation buttons 239 JToolBar topPanel = new JToolBar(); 240 topPanel.setFloatable(false); 241 if (OS_VERSION.compareTo(OSInfo.WINDOWS_ME) >= 0) { 242 topPanel.putClientProperty("JToolBar.isRollover", Boolean.TRUE); 243 } 244 245 // Add the top panel to the fileChooser 246 fc.add(topPanel, BorderLayout.NORTH); 247 248 // ComboBox Label 249 lookInLabel = new JLabel(lookInLabelText, JLabel.TRAILING) { 250 public Dimension getPreferredSize() { 251 return getMinimumSize(); 252 } 253 254 public Dimension getMinimumSize() { 255 Dimension d = super.getPreferredSize(); 256 if (placesBar != null) { 257 d.width = Math.max(d.width, placesBar.getWidth()); 258 } 259 return d; 260 } 261 }; 262 lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic); 263 lookInLabel.setAlignmentX(JComponent.LEFT_ALIGNMENT); 264 lookInLabel.setAlignmentY(JComponent.CENTER_ALIGNMENT); 265 topPanel.add(lookInLabel); 266 topPanel.add(Box.createRigidArea(new Dimension(8,0))); 267 268 // CurrentDir ComboBox 269 directoryComboBox = new JComboBox() { 270 public Dimension getMinimumSize() { 271 Dimension d = super.getMinimumSize(); 272 d.width = 60; 273 return d; 274 } 275 276 public Dimension getPreferredSize() { 277 Dimension d = super.getPreferredSize(); 278 // Must be small enough to not affect total width. 279 d.width = 150; 280 return d; 281 } 282 }; 283 directoryComboBox.putClientProperty( "JComboBox.lightweightKeyboardNavigation", "Lightweight" ); 284 lookInLabel.setLabelFor(directoryComboBox); 285 directoryComboBoxModel = createDirectoryComboBoxModel(fc); 286 directoryComboBox.setModel(directoryComboBoxModel); 287 directoryComboBox.addActionListener(directoryComboBoxAction); 288 directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc)); 289 directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT); 290 directoryComboBox.setAlignmentY(JComponent.CENTER_ALIGNMENT); 291 directoryComboBox.setMaximumRowCount(8); 292 293 topPanel.add(directoryComboBox); 294 topPanel.add(Box.createRigidArea(hstrut10)); 295 296 // Up Button 297 JButton upFolderButton = new JButton(getChangeToParentDirectoryAction()); 298 upFolderButton.setText(null); 299 upFolderButton.setIcon(upFolderIcon); 300 upFolderButton.setToolTipText(upFolderToolTipText); 301 upFolderButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, 302 upFolderAccessibleName); 303 upFolderButton.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, 304 Boolean.TRUE); 305 upFolderButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); 306 upFolderButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); 307 upFolderButton.setMargin(shrinkwrap); 308 upFolderButton.setFocusPainted(false); 309 topPanel.add(upFolderButton); 310 if (OS_VERSION.compareTo(OSInfo.WINDOWS_ME) < 0) { 311 topPanel.add(Box.createRigidArea(hstrut10)); 312 } 313 314 JButton b; 315 316 if (OS_VERSION == OSInfo.WINDOWS_98) { 317 // Desktop Button 318 File homeDir = fsv.getHomeDirectory(); 319 String toolTipText = homeFolderToolTipText; 320 if (fsv.isRoot(homeDir)) { 321 toolTipText = getFileView(fc).getName(homeDir); // Probably "Desktop". 322 } 323 b = new JButton(getFileView(fc).getIcon(homeDir)); 324 b.setToolTipText(toolTipText); 325 b.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, 326 toolTipText); 327 b.setAlignmentX(JComponent.LEFT_ALIGNMENT); 328 b.setAlignmentY(JComponent.CENTER_ALIGNMENT); 329 b.setMargin(shrinkwrap); 330 b.setFocusPainted(false); 331 b.addActionListener(getGoHomeAction()); 332 topPanel.add(b); 333 topPanel.add(Box.createRigidArea(hstrut10)); 334 } 335 336 // New Directory Button 337 if (!UIManager.getBoolean("FileChooser.readOnly")) { 338 b = new JButton(filePane.getNewFolderAction()); 339 b.setText(null); 340 b.setIcon(newFolderIcon); 341 b.setToolTipText(newFolderToolTipText); 342 b.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, 343 newFolderAccessibleName); 344 b.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, 345 Boolean.TRUE); 346 b.setAlignmentX(JComponent.LEFT_ALIGNMENT); 347 b.setAlignmentY(JComponent.CENTER_ALIGNMENT); 348 b.setMargin(shrinkwrap); 349 b.setFocusPainted(false); 350 topPanel.add(b); 351 } 352 if (OS_VERSION.compareTo(OSInfo.WINDOWS_ME) < 0) { 353 topPanel.add(Box.createRigidArea(hstrut10)); 354 355 // View button group 356 ButtonGroup viewButtonGroup = new ButtonGroup(); 357 358 // List Button 359 final JToggleButton listViewButton = new JToggleButton(listViewIcon); 360 listViewButton.setToolTipText(listViewButtonToolTipText); 361 listViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, 362 listViewButtonAccessibleName); 363 listViewButton.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, 364 Boolean.TRUE); 365 listViewButton.setFocusPainted(false); 366 listViewButton.setSelected(true); 367 listViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); 368 listViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); 369 listViewButton.setMargin(shrinkwrap); 370 listViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST)); 371 topPanel.add(listViewButton); 372 viewButtonGroup.add(listViewButton); 373 374 // Details Button 375 final JToggleButton detailsViewButton = new JToggleButton(detailsViewIcon); 376 detailsViewButton.setToolTipText(detailsViewButtonToolTipText); 377 detailsViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, 378 detailsViewButtonAccessibleName); 379 detailsViewButton.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, 380 Boolean.TRUE); 381 detailsViewButton.setFocusPainted(false); 382 detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); 383 detailsViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); 384 detailsViewButton.setMargin(shrinkwrap); 385 detailsViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS)); 386 topPanel.add(detailsViewButton); 387 viewButtonGroup.add(detailsViewButton); 388 389 topPanel.add(Box.createRigidArea(new Dimension(60, 0))); 390 391 filePane.addPropertyChangeListener(new PropertyChangeListener() { 392 public void propertyChange(PropertyChangeEvent e) { 393 if ("viewType".equals(e.getPropertyName())) { 394 int viewType = filePane.getViewType(); 395 396 switch (viewType) { 397 case FilePane.VIEWTYPE_LIST: 398 listViewButton.setSelected(true); 399 break; 400 401 case FilePane.VIEWTYPE_DETAILS: 402 detailsViewButton.setSelected(true); 403 break; 404 } 405 } 406 } 407 }); 408 } else { // After Windows Me 409 // View button group 410 ButtonGroup viewButtonGroup = new ButtonGroup(); 411 412 // Popup Menu 413 final JPopupMenu viewTypePopupMenu = new JPopupMenu(); 414 415 final JRadioButtonMenuItem listViewMenuItem = new JRadioButtonMenuItem( 416 filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST)); 417 listViewMenuItem.setSelected(filePane.getViewType() == FilePane.VIEWTYPE_LIST); 418 viewTypePopupMenu.add(listViewMenuItem); 419 viewButtonGroup.add(listViewMenuItem); 420 421 final JRadioButtonMenuItem detailsViewMenuItem = new JRadioButtonMenuItem( 422 filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS)); 423 detailsViewMenuItem.setSelected(filePane.getViewType() == FilePane.VIEWTYPE_DETAILS); 424 viewTypePopupMenu.add(detailsViewMenuItem); 425 viewButtonGroup.add(detailsViewMenuItem); 426 427 // Create icon for viewMenuButton 428 BufferedImage image = new BufferedImage(viewMenuIcon.getIconWidth() + 7, viewMenuIcon.getIconHeight(), 429 BufferedImage.TYPE_INT_ARGB); 430 Graphics graphics = image.getGraphics(); 431 viewMenuIcon.paintIcon(filePane, graphics, 0, 0); 432 int x = image.getWidth() - 5; 433 int y = image.getHeight() / 2 - 1; 434 graphics.setColor(Color.BLACK); 435 graphics.fillPolygon(new int[]{x, x + 5, x + 2}, new int[]{y, y, y + 3}, 3); 436 437 // Details Button 438 final JButton viewMenuButton = new JButton(new ImageIcon(image)); 439 viewMenuButton.setToolTipText(viewMenuButtonToolTipText); 440 viewMenuButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, viewMenuButtonAccessibleName); 441 viewMenuButton.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, Boolean.TRUE); 442 viewMenuButton.setFocusable(false); 443 viewMenuButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); 444 viewMenuButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); 445 viewMenuButton.setMargin(shrinkwrap); 446 viewMenuButton.setModel(new DefaultButtonModel() { 447 public void setPressed(boolean b) { 448 } 449 450 public void setArmed(boolean b) { 451 } 452 453 public void setSelected(boolean b) { 454 super.setSelected(b); 455 456 if (b) { 457 stateMask |= PRESSED | ARMED; 458 } else { 459 stateMask &= ~(PRESSED | ARMED); 460 } 461 } 462 }); 463 viewMenuButton.addMouseListener(new MouseAdapter() { 464 public void mousePressed(MouseEvent e) { 465 if (SwingUtilities.isLeftMouseButton(e)) { 466 viewMenuButton.setSelected(!viewMenuButton.isSelected()); 467 468 if (viewMenuButton.isSelected()) { 469 viewTypePopupMenu.show(viewMenuButton, 0, viewMenuButton.getHeight()); 470 } 471 } 472 } 473 }); 474 viewTypePopupMenu.addPopupMenuListener(new PopupMenuListener() { 475 public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 476 } 477 478 public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 479 SwingUtilities.invokeLater(new Runnable() { 480 public void run() { 481 viewMenuButton.setSelected(false); 482 } 483 }); 484 } 485 486 public void popupMenuCanceled(PopupMenuEvent e) { 487 } 488 }); 489 topPanel.add(viewMenuButton); 490 491 topPanel.add(Box.createRigidArea(new Dimension(80, 0))); 492 493 filePane.addPropertyChangeListener(new PropertyChangeListener() { 494 public void propertyChange(PropertyChangeEvent e) { 495 if ("viewType".equals(e.getPropertyName())) { 496 switch (filePane.getViewType()) { 497 case FilePane.VIEWTYPE_LIST: 498 listViewMenuItem.setSelected(true); 499 break; 500 501 case FilePane.VIEWTYPE_DETAILS: 502 detailsViewMenuItem.setSelected(true); 503 break; 504 } 505 } 506 } 507 }); 508 } 509 510 // ************************************** // 511 // ******* Add the directory pane ******* // 512 // ************************************** // 513 centerPanel = new JPanel(new BorderLayout()); 514 centerPanel.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS); 515 JComponent accessory = fc.getAccessory(); 516 if(accessory != null) { 517 getAccessoryPanel().add(accessory); 518 } 519 filePane.setPreferredSize(LIST_PREF_SIZE); 520 centerPanel.add(filePane, BorderLayout.CENTER); 521 fc.add(centerPanel, BorderLayout.CENTER); 522 523 // ********************************** // 524 // **** Construct the bottom panel ** // 525 // ********************************** // 526 getBottomPanel().setLayout(new BoxLayout(getBottomPanel(), BoxLayout.LINE_AXIS)); 527 528 // Add the bottom panel to file chooser 529 centerPanel.add(getBottomPanel(), BorderLayout.SOUTH); 530 531 // labels 532 JPanel labelPanel = new JPanel(); 533 labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.PAGE_AXIS)); 534 labelPanel.add(Box.createRigidArea(vstrut4)); 535 536 fileNameLabel = new JLabel(); 537 populateFileNameLabel(); 538 fileNameLabel.setAlignmentY(0); 539 labelPanel.add(fileNameLabel); 540 541 labelPanel.add(Box.createRigidArea(new Dimension(1,12))); 542 543 JLabel ftl = new JLabel(filesOfTypeLabelText); 544 ftl.setDisplayedMnemonic(filesOfTypeLabelMnemonic); 545 labelPanel.add(ftl); 546 547 getBottomPanel().add(labelPanel); 548 getBottomPanel().add(Box.createRigidArea(new Dimension(15, 0))); 549 550 // file entry and filters 551 JPanel fileAndFilterPanel = new JPanel(); 552 fileAndFilterPanel.add(Box.createRigidArea(vstrut8)); 553 fileAndFilterPanel.setLayout(new BoxLayout(fileAndFilterPanel, BoxLayout.Y_AXIS)); 554 555 556 filenameTextField = new JTextField(35) { 557 public Dimension getMaximumSize() { 558 return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height); 559 } 560 }; 561 562 fileNameLabel.setLabelFor(filenameTextField); 563 filenameTextField.addFocusListener( 564 new FocusAdapter() { 565 public void focusGained(FocusEvent e) { 566 if (!getFileChooser().isMultiSelectionEnabled()) { 567 filePane.clearSelection(); 568 } 569 } 570 } 571 ); 572 573 if (fc.isMultiSelectionEnabled()) { 574 setFileName(fileNameString(fc.getSelectedFiles())); 575 } else { 576 setFileName(fileNameString(fc.getSelectedFile())); 577 } 578 579 fileAndFilterPanel.add(filenameTextField); 580 fileAndFilterPanel.add(Box.createRigidArea(vstrut8)); 581 582 filterComboBoxModel = createFilterComboBoxModel(); 583 fc.addPropertyChangeListener(filterComboBoxModel); 584 filterComboBox = new JComboBox(filterComboBoxModel); 585 ftl.setLabelFor(filterComboBox); 586 filterComboBox.setRenderer(createFilterComboBoxRenderer()); 587 fileAndFilterPanel.add(filterComboBox); 588 589 getBottomPanel().add(fileAndFilterPanel); 590 getBottomPanel().add(Box.createRigidArea(new Dimension(30, 0))); 591 592 // buttons 593 getButtonPanel().setLayout(new BoxLayout(getButtonPanel(), BoxLayout.Y_AXIS)); 594 595 approveButton = new JButton(getApproveButtonText(fc)) { 596 public Dimension getMaximumSize() { 597 return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ? 598 approveButton.getPreferredSize() : cancelButton.getPreferredSize(); 599 } 600 }; 601 Insets buttonMargin = approveButton.getMargin(); 602 buttonMargin = new InsetsUIResource(buttonMargin.top, buttonMargin.left + 5, 603 buttonMargin.bottom, buttonMargin.right + 5); 604 approveButton.setMargin(buttonMargin); 605 approveButton.setMnemonic(getApproveButtonMnemonic(fc)); 606 approveButton.addActionListener(getApproveSelectionAction()); 607 approveButton.setToolTipText(getApproveButtonToolTipText(fc)); 608 getButtonPanel().add(Box.createRigidArea(vstrut6)); 609 getButtonPanel().add(approveButton); 610 getButtonPanel().add(Box.createRigidArea(vstrut4)); 611 612 cancelButton = new JButton(cancelButtonText) { 613 public Dimension getMaximumSize() { 614 return approveButton.getPreferredSize().width > cancelButton.getPreferredSize().width ? 615 approveButton.getPreferredSize() : cancelButton.getPreferredSize(); 616 } 617 }; 618 cancelButton.setMargin(buttonMargin); 619 cancelButton.setToolTipText(cancelButtonToolTipText); 620 cancelButton.addActionListener(getCancelSelectionAction()); 621 getButtonPanel().add(cancelButton); 622 623 if(fc.getControlButtonsAreShown()) { 624 addControlButtons(); 625 } 626 } 627 628 private void updateUseShellFolder() { 629 // Decide whether to use the ShellFolder class to populate shortcut 630 // panel and combobox. 631 JFileChooser fc = getFileChooser(); 632 Boolean prop = 633 (Boolean)fc.getClientProperty("FileChooser.useShellFolder"); 634 if (prop != null) { 635 useShellFolder = prop.booleanValue(); 636 } else { 637 useShellFolder = fc.getFileSystemView().equals(FileSystemView.getFileSystemView()); 638 } 639 if (OS_VERSION.compareTo(OSInfo.WINDOWS_ME) >= 0) { 640 if (useShellFolder) { 641 if (placesBar == null && !UIManager.getBoolean("FileChooser.noPlacesBar")) { 642 placesBar = new WindowsPlacesBar(fc, XPStyle.getXP() != null); 643 fc.add(placesBar, BorderLayout.BEFORE_LINE_BEGINS); 644 fc.addPropertyChangeListener(placesBar); 645 } 646 } else { 647 if (placesBar != null) { 648 fc.remove(placesBar); 649 fc.removePropertyChangeListener(placesBar); 650 placesBar = null; 651 } 652 } 653 } 654 } 655 656 protected JPanel getButtonPanel() { 657 if(buttonPanel == null) { 658 buttonPanel = new JPanel(); 659 } 660 return buttonPanel; 661 } 662 663 protected JPanel getBottomPanel() { 664 if(bottomPanel == null) { 665 bottomPanel = new JPanel(); 666 } 667 return bottomPanel; 668 } 669 670 protected void installIcons(JFileChooser fc) { 671 super.installIcons(fc); 672 viewMenuIcon = UIManager.getIcon("FileChooser.viewMenuIcon"); 673 } 674 675 protected void uninstallIcons(JFileChooser fc) { 676 super.uninstallIcons(fc); 677 viewMenuIcon = null; 678 } 679 680 protected void installStrings(JFileChooser fc) { 681 super.installStrings(fc); 682 683 Locale l = fc.getLocale(); 684 685 lookInLabelMnemonic = getMnemonic("FileChooser.lookInLabelMnemonic", l); 686 lookInLabelText = UIManager.getString("FileChooser.lookInLabelText",l); 687 saveInLabelText = UIManager.getString("FileChooser.saveInLabelText",l); 688 689 fileNameLabelMnemonic = getMnemonic("FileChooser.fileNameLabelMnemonic", l); 690 fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText",l); 691 folderNameLabelMnemonic = getMnemonic("FileChooser.folderNameLabelMnemonic", l); 692 folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText",l); 693 694 filesOfTypeLabelMnemonic = getMnemonic("FileChooser.filesOfTypeLabelMnemonic", l); 695 filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText",l); 696 697 upFolderToolTipText = UIManager.getString("FileChooser.upFolderToolTipText",l); 698 upFolderAccessibleName = UIManager.getString("FileChooser.upFolderAccessibleName",l); 699 700 homeFolderToolTipText = UIManager.getString("FileChooser.homeFolderToolTipText",l); 701 homeFolderAccessibleName = UIManager.getString("FileChooser.homeFolderAccessibleName",l); 702 703 newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText",l); 704 newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName",l); 705 706 listViewButtonToolTipText = UIManager.getString("FileChooser.listViewButtonToolTipText",l); 707 listViewButtonAccessibleName = UIManager.getString("FileChooser.listViewButtonAccessibleName",l); 708 709 detailsViewButtonToolTipText = UIManager.getString("FileChooser.detailsViewButtonToolTipText",l); 710 detailsViewButtonAccessibleName = UIManager.getString("FileChooser.detailsViewButtonAccessibleName",l); 711 712 viewMenuButtonToolTipText = UIManager.getString("FileChooser.viewMenuButtonToolTipText",l); 713 viewMenuButtonAccessibleName = UIManager.getString("FileChooser.viewMenuButtonAccessibleName",l); 714 } 715 716 private Integer getMnemonic(String key, Locale l) { 717 return SwingUtilities2.getUIDefaultsInt(key, l); 718 } 719 720 protected void installListeners(JFileChooser fc) { 721 super.installListeners(fc); 722 ActionMap actionMap = getActionMap(); 723 SwingUtilities.replaceUIActionMap(fc, actionMap); 724 } 725 726 protected ActionMap getActionMap() { 727 return createActionMap(); 728 } 729 730 protected ActionMap createActionMap() { 731 ActionMap map = new ActionMapUIResource(); 732 FilePane.addActionsToMap(map, filePane.getActions()); 733 return map; 734 } 735 736 protected JPanel createList(JFileChooser fc) { 737 return filePane.createList(); 738 } 739 740 protected JPanel createDetailsView(JFileChooser fc) { 741 return filePane.createDetailsView(); 742 } 743 744 /** 745 * Creates a selection listener for the list of files and directories. 746 * 747 * @param fc a <code>JFileChooser</code> 748 * @return a <code>ListSelectionListener</code> 749 */ 750 public ListSelectionListener createListSelectionListener(JFileChooser fc) { 751 return super.createListSelectionListener(fc); 752 } 753 754 // Obsolete class, not used in this version. 755 protected class WindowsNewFolderAction extends NewFolderAction { 756 } 757 758 // Obsolete class, not used in this version. 759 protected class SingleClickListener extends MouseAdapter { 760 } 761 762 // Obsolete class, not used in this version. 763 protected class FileRenderer extends DefaultListCellRenderer { 764 } 765 766 public void uninstallUI(JComponent c) { 767 // Remove listeners 768 c.removePropertyChangeListener(filterComboBoxModel); 769 c.removePropertyChangeListener(filePane); 770 if (placesBar != null) { 771 c.removePropertyChangeListener(placesBar); 772 } 773 cancelButton.removeActionListener(getCancelSelectionAction()); 774 approveButton.removeActionListener(getApproveSelectionAction()); 775 filenameTextField.removeActionListener(getApproveSelectionAction()); 776 777 if (filePane != null) { 778 filePane.uninstallUI(); 779 filePane = null; 780 } 781 782 super.uninstallUI(c); 783 } 784 785 /** 786 * Returns the preferred size of the specified 787 * <code>JFileChooser</code>. 788 * The preferred size is at least as large, 789 * in both height and width, 790 * as the preferred size recommended 791 * by the file chooser's layout manager. 792 * 793 * @param c a <code>JFileChooser</code> 794 * @return a <code>Dimension</code> specifying the preferred 795 * width and height of the file chooser 796 */ 797 public Dimension getPreferredSize(JComponent c) { 798 int prefWidth = PREF_SIZE.width; 799 Dimension d = c.getLayout().preferredLayoutSize(c); 800 if (d != null) { 801 return new Dimension(d.width < prefWidth ? prefWidth : d.width, 802 d.height < PREF_SIZE.height ? PREF_SIZE.height : d.height); 803 } else { 804 return new Dimension(prefWidth, PREF_SIZE.height); 805 } 806 } 807 808 /** 809 * Returns the minimum size of the <code>JFileChooser</code>. 810 * 811 * @param c a <code>JFileChooser</code> 812 * @return a <code>Dimension</code> specifying the minimum 813 * width and height of the file chooser 814 */ 815 public Dimension getMinimumSize(JComponent c) { 816 return MIN_SIZE; 817 } 818 819 /** 820 * Returns the maximum size of the <code>JFileChooser</code>. 821 * 822 * @param c a <code>JFileChooser</code> 823 * @return a <code>Dimension</code> specifying the maximum 824 * width and height of the file chooser 825 */ 826 public Dimension getMaximumSize(JComponent c) { 827 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); 828 } 829 830 private String fileNameString(File file) { 831 if (file == null) { 832 return null; 833 } else { 834 JFileChooser fc = getFileChooser(); 835 if ((fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) || 836 (fc.isDirectorySelectionEnabled() && fc.isFileSelectionEnabled() && fc.getFileSystemView().isFileSystemRoot(file))){ 837 return file.getPath(); 838 } else { 839 return file.getName(); 840 } 841 } 842 } 843 844 private String fileNameString(File[] files) { 845 StringBuffer buf = new StringBuffer(); 846 for (int i = 0; files != null && i < files.length; i++) { 847 if (i > 0) { 848 buf.append(" "); 849 } 850 if (files.length > 1) { 851 buf.append("\""); 852 } 853 buf.append(fileNameString(files[i])); 854 if (files.length > 1) { 855 buf.append("\""); 856 } 857 } 858 return buf.toString(); 859 } 860 861 /* The following methods are used by the PropertyChange Listener */ 862 863 private void doSelectedFileChanged(PropertyChangeEvent e) { 864 File f = (File) e.getNewValue(); 865 JFileChooser fc = getFileChooser(); 866 if (f != null 867 && ((fc.isFileSelectionEnabled() && !f.isDirectory()) 868 || (f.isDirectory() && fc.isDirectorySelectionEnabled()))) { 869 870 setFileName(fileNameString(f)); 871 } 872 } 873 874 private void doSelectedFilesChanged(PropertyChangeEvent e) { 875 File[] files = (File[]) e.getNewValue(); 876 JFileChooser fc = getFileChooser(); 877 if (files != null 878 && files.length > 0 879 && (files.length > 1 || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) { 880 setFileName(fileNameString(files)); 881 } 882 } 883 884 private void doDirectoryChanged(PropertyChangeEvent e) { 885 JFileChooser fc = getFileChooser(); 886 FileSystemView fsv = fc.getFileSystemView(); 887 888 clearIconCache(); 889 File currentDirectory = fc.getCurrentDirectory(); 890 if(currentDirectory != null) { 891 directoryComboBoxModel.addItem(currentDirectory); 892 893 if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) { 894 if (fsv.isFileSystem(currentDirectory)) { 895 setFileName(currentDirectory.getPath()); 896 } else { 897 setFileName(null); 898 } 899 } 900 } 901 } 902 903 private void doFilterChanged(PropertyChangeEvent e) { 904 clearIconCache(); 905 } 906 907 private void doFileSelectionModeChanged(PropertyChangeEvent e) { 908 if (fileNameLabel != null) { 909 populateFileNameLabel(); 910 } 911 clearIconCache(); 912 913 JFileChooser fc = getFileChooser(); 914 File currentDirectory = fc.getCurrentDirectory(); 915 if (currentDirectory != null 916 && fc.isDirectorySelectionEnabled() 917 && !fc.isFileSelectionEnabled() 918 && fc.getFileSystemView().isFileSystem(currentDirectory)) { 919 920 setFileName(currentDirectory.getPath()); 921 } else { 922 setFileName(null); 923 } 924 } 925 926 private void doAccessoryChanged(PropertyChangeEvent e) { 927 if(getAccessoryPanel() != null) { 928 if(e.getOldValue() != null) { 929 getAccessoryPanel().remove((JComponent) e.getOldValue()); 930 } 931 JComponent accessory = (JComponent) e.getNewValue(); 932 if(accessory != null) { 933 getAccessoryPanel().add(accessory, BorderLayout.CENTER); 934 } 935 } 936 } 937 938 private void doApproveButtonTextChanged(PropertyChangeEvent e) { 939 JFileChooser chooser = getFileChooser(); 940 approveButton.setText(getApproveButtonText(chooser)); 941 approveButton.setToolTipText(getApproveButtonToolTipText(chooser)); 942 approveButton.setMnemonic(getApproveButtonMnemonic(chooser)); 943 } 944 945 private void doDialogTypeChanged(PropertyChangeEvent e) { 946 JFileChooser chooser = getFileChooser(); 947 approveButton.setText(getApproveButtonText(chooser)); 948 approveButton.setToolTipText(getApproveButtonToolTipText(chooser)); 949 approveButton.setMnemonic(getApproveButtonMnemonic(chooser)); 950 if (chooser.getDialogType() == JFileChooser.SAVE_DIALOG) { 951 lookInLabel.setText(saveInLabelText); 952 } else { 953 lookInLabel.setText(lookInLabelText); 954 } 955 } 956 957 private void doApproveButtonMnemonicChanged(PropertyChangeEvent e) { 958 approveButton.setMnemonic(getApproveButtonMnemonic(getFileChooser())); 959 } 960 961 private void doControlButtonsChanged(PropertyChangeEvent e) { 962 if(getFileChooser().getControlButtonsAreShown()) { 963 addControlButtons(); 964 } else { 965 removeControlButtons(); 966 } 967 } 968 969 /* 970 * Listen for filechooser property changes, such as 971 * the selected file changing, or the type of the dialog changing. 972 */ 973 public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) { 974 return new PropertyChangeListener() { 975 public void propertyChange(PropertyChangeEvent e) { 976 String s = e.getPropertyName(); 977 if(s.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) { 978 doSelectedFileChanged(e); 979 } else if (s.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) { 980 doSelectedFilesChanged(e); 981 } else if(s.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) { 982 doDirectoryChanged(e); 983 } else if(s.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) { 984 doFilterChanged(e); 985 } else if(s.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) { 986 doFileSelectionModeChanged(e); 987 } else if(s.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) { 988 doAccessoryChanged(e); 989 } else if (s.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) || 990 s.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) { 991 doApproveButtonTextChanged(e); 992 } else if(s.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) { 993 doDialogTypeChanged(e); 994 } else if(s.equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) { 995 doApproveButtonMnemonicChanged(e); 996 } else if(s.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) { 997 doControlButtonsChanged(e); 998 } else if (s == "FileChooser.useShellFolder") { 999 updateUseShellFolder(); 1000 doDirectoryChanged(e); 1001 } else if (s.equals("componentOrientation")) { 1002 ComponentOrientation o = (ComponentOrientation)e.getNewValue(); 1003 JFileChooser cc = (JFileChooser)e.getSource(); 1004 if (o != e.getOldValue()) { 1005 cc.applyComponentOrientation(o); 1006 } 1007 } else if (s.equals("ancestor")) { 1008 if (e.getOldValue() == null && e.getNewValue() != null) { 1009 // Ancestor was added, set initial focus 1010 filenameTextField.selectAll(); 1011 filenameTextField.requestFocus(); 1012 } 1013 } 1014 } 1015 }; 1016 } 1017 1018 1019 protected void removeControlButtons() { 1020 getBottomPanel().remove(getButtonPanel()); 1021 } 1022 1023 protected void addControlButtons() { 1024 getBottomPanel().add(getButtonPanel()); 1025 } 1026 1027 public void ensureFileIsVisible(JFileChooser fc, File f) { 1028 filePane.ensureFileIsVisible(fc, f); 1029 } 1030 1031 public void rescanCurrentDirectory(JFileChooser fc) { 1032 filePane.rescanCurrentDirectory(); 1033 } 1034 1035 public String getFileName() { 1036 if(filenameTextField != null) { 1037 return filenameTextField.getText(); 1038 } else { 1039 return null; 1040 } 1041 } 1042 1043 public void setFileName(String filename) { 1044 if(filenameTextField != null) { 1045 filenameTextField.setText(filename); 1046 } 1047 } 1048 1049 /** 1050 * Property to remember whether a directory is currently selected in the UI. 1051 * This is normally called by the UI on a selection event. 1052 * 1053 * @param directorySelected if a directory is currently selected. 1054 * @since 1.4 1055 */ 1056 protected void setDirectorySelected(boolean directorySelected) { 1057 super.setDirectorySelected(directorySelected); 1058 JFileChooser chooser = getFileChooser(); 1059 if(directorySelected) { 1060 approveButton.setText(directoryOpenButtonText); 1061 approveButton.setToolTipText(directoryOpenButtonToolTipText); 1062 approveButton.setMnemonic(directoryOpenButtonMnemonic); 1063 } else { 1064 approveButton.setText(getApproveButtonText(chooser)); 1065 approveButton.setToolTipText(getApproveButtonToolTipText(chooser)); 1066 approveButton.setMnemonic(getApproveButtonMnemonic(chooser)); 1067 } 1068 } 1069 1070 public String getDirectoryName() { 1071 // PENDING(jeff) - get the name from the directory combobox 1072 return null; 1073 } 1074 1075 public void setDirectoryName(String dirname) { 1076 // PENDING(jeff) - set the name in the directory combobox 1077 } 1078 1079 protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) { 1080 return new DirectoryComboBoxRenderer(); 1081 } 1082 1083 // 1084 // Renderer for DirectoryComboBox 1085 // 1086 class DirectoryComboBoxRenderer extends DefaultListCellRenderer { 1087 IndentIcon ii = new IndentIcon(); 1088 public Component getListCellRendererComponent(JList list, Object value, 1089 int index, boolean isSelected, 1090 boolean cellHasFocus) { 1091 1092 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 1093 1094 if (value == null) { 1095 setText(""); 1096 return this; 1097 } 1098 File directory = (File)value; 1099 setText(getFileChooser().getName(directory)); 1100 Icon icon = getFileChooser().getIcon(directory); 1101 ii.icon = icon; 1102 ii.depth = directoryComboBoxModel.getDepth(index); 1103 setIcon(ii); 1104 1105 return this; 1106 } 1107 } 1108 1109 final static int space = 10; 1110 class IndentIcon implements Icon { 1111 1112 Icon icon = null; 1113 int depth = 0; 1114 1115 public void paintIcon(Component c, Graphics g, int x, int y) { 1116 if (c.getComponentOrientation().isLeftToRight()) { 1117 icon.paintIcon(c, g, x+depth*space, y); 1118 } else { 1119 icon.paintIcon(c, g, x, y); 1120 } 1121 } 1122 1123 public int getIconWidth() { 1124 return icon.getIconWidth() + depth*space; 1125 } 1126 1127 public int getIconHeight() { 1128 return icon.getIconHeight(); 1129 } 1130 1131 } 1132 1133 // 1134 // DataModel for DirectoryComboxbox 1135 // 1136 protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) { 1137 return new DirectoryComboBoxModel(); 1138 } 1139 1140 /** 1141 * Data model for a type-face selection combo-box. 1142 */ 1143 protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { 1144 Vector<File> directories = new Vector<File>(); 1145 int[] depths = null; 1146 File selectedDirectory = null; 1147 JFileChooser chooser = getFileChooser(); 1148 FileSystemView fsv = chooser.getFileSystemView(); 1149 1150 public DirectoryComboBoxModel() { 1151 // Add the current directory to the model, and make it the 1152 // selectedDirectory 1153 File dir = getFileChooser().getCurrentDirectory(); 1154 if(dir != null) { 1155 addItem(dir); 1156 } 1157 } 1158 1159 /** 1160 * Adds the directory to the model and sets it to be selected, 1161 * additionally clears out the previous selected directory and 1162 * the paths leading up to it, if any. 1163 */ 1164 private void addItem(File directory) { 1165 1166 if(directory == null) { 1167 return; 1168 } 1169 1170 directories.clear(); 1171 1172 File[] baseFolders = (useShellFolder) 1173 ? (File[]) ShellFolder.get("fileChooserComboBoxFolders") 1174 : fsv.getRoots(); 1175 directories.addAll(Arrays.asList(baseFolders)); 1176 1177 // Get the canonical (full) path. This has the side 1178 // benefit of removing extraneous chars from the path, 1179 // for example /foo/bar/ becomes /foo/bar 1180 File canonical; 1181 try { 1182 canonical = directory.getCanonicalFile(); 1183 } catch (IOException e) { 1184 // Maybe drive is not ready. Can't abort here. 1185 canonical = directory; 1186 } 1187 1188 // create File instances of each directory leading up to the top 1189 try { 1190 File sf = useShellFolder ? ShellFolder.getShellFolder(canonical) 1191 : canonical; 1192 File f = sf; 1193 Vector<File> path = new Vector<File>(10); 1194 do { 1195 path.addElement(f); 1196 } while ((f = f.getParentFile()) != null); 1197 1198 int pathCount = path.size(); 1199 // Insert chain at appropriate place in vector 1200 for (int i = 0; i < pathCount; i++) { 1201 f = path.get(i); 1202 if (directories.contains(f)) { 1203 int topIndex = directories.indexOf(f); 1204 for (int j = i-1; j >= 0; j--) { 1205 directories.insertElementAt(path.get(j), topIndex+i-j); 1206 } 1207 break; 1208 } 1209 } 1210 calculateDepths(); 1211 setSelectedItem(sf); 1212 } catch (FileNotFoundException ex) { 1213 calculateDepths(); 1214 } 1215 } 1216 1217 private void calculateDepths() { 1218 depths = new int[directories.size()]; 1219 for (int i = 0; i < depths.length; i++) { 1220 File dir = directories.get(i); 1221 File parent = dir.getParentFile(); 1222 depths[i] = 0; 1223 if (parent != null) { 1224 for (int j = i-1; j >= 0; j--) { 1225 if (parent.equals(directories.get(j))) { 1226 depths[i] = depths[j] + 1; 1227 break; 1228 } 1229 } 1230 } 1231 } 1232 } 1233 1234 public int getDepth(int i) { 1235 return (depths != null && i >= 0 && i < depths.length) ? depths[i] : 0; 1236 } 1237 1238 public void setSelectedItem(Object selectedDirectory) { 1239 this.selectedDirectory = (File)selectedDirectory; 1240 fireContentsChanged(this, -1, -1); 1241 } 1242 1243 public Object getSelectedItem() { 1244 return selectedDirectory; 1245 } 1246 1247 public int getSize() { 1248 return directories.size(); 1249 } 1250 1251 public Object getElementAt(int index) { 1252 return directories.elementAt(index); 1253 } 1254 } 1255 1256 // 1257 // Renderer for Types ComboBox 1258 // 1259 protected FilterComboBoxRenderer createFilterComboBoxRenderer() { 1260 return new FilterComboBoxRenderer(); 1261 } 1262 1263 /** 1264 * Render different type sizes and styles. 1265 */ 1266 public class FilterComboBoxRenderer extends DefaultListCellRenderer { 1267 public Component getListCellRendererComponent(JList list, 1268 Object value, int index, boolean isSelected, 1269 boolean cellHasFocus) { 1270 1271 super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 1272 1273 if (value != null && value instanceof FileFilter) { 1274 setText(((FileFilter)value).getDescription()); 1275 } 1276 1277 return this; 1278 } 1279 } 1280 1281 // 1282 // DataModel for Types Comboxbox 1283 // 1284 protected FilterComboBoxModel createFilterComboBoxModel() { 1285 return new FilterComboBoxModel(); 1286 } 1287 1288 /** 1289 * Data model for a type-face selection combo-box. 1290 */ 1291 protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener { 1292 protected FileFilter[] filters; 1293 protected FilterComboBoxModel() { 1294 super(); 1295 filters = getFileChooser().getChoosableFileFilters(); 1296 } 1297 1298 public void propertyChange(PropertyChangeEvent e) { 1299 String prop = e.getPropertyName(); 1300 if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { 1301 filters = (FileFilter[]) e.getNewValue(); 1302 fireContentsChanged(this, -1, -1); 1303 } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) { 1304 fireContentsChanged(this, -1, -1); 1305 } 1306 } 1307 1308 public void setSelectedItem(Object filter) { 1309 if(filter != null) { 1310 getFileChooser().setFileFilter((FileFilter) filter); 1311 fireContentsChanged(this, -1, -1); 1312 } 1313 } 1314 1315 public Object getSelectedItem() { 1316 // Ensure that the current filter is in the list. 1317 // NOTE: we shouldnt' have to do this, since JFileChooser adds 1318 // the filter to the choosable filters list when the filter 1319 // is set. Lets be paranoid just in case someone overrides 1320 // setFileFilter in JFileChooser. 1321 FileFilter currentFilter = getFileChooser().getFileFilter(); 1322 boolean found = false; 1323 if(currentFilter != null) { 1324 for (FileFilter filter : filters) { 1325 if (filter == currentFilter) { 1326 found = true; 1327 } 1328 } 1329 if(found == false) { 1330 getFileChooser().addChoosableFileFilter(currentFilter); 1331 } 1332 } 1333 return getFileChooser().getFileFilter(); 1334 } 1335 1336 public int getSize() { 1337 if(filters != null) { 1338 return filters.length; 1339 } else { 1340 return 0; 1341 } 1342 } 1343 1344 public Object getElementAt(int index) { 1345 if(index > getSize() - 1) { 1346 // This shouldn't happen. Try to recover gracefully. 1347 return getFileChooser().getFileFilter(); 1348 } 1349 if(filters != null) { 1350 return filters[index]; 1351 } else { 1352 return null; 1353 } 1354 } 1355 } 1356 1357 public void valueChanged(ListSelectionEvent e) { 1358 JFileChooser fc = getFileChooser(); 1359 File f = fc.getSelectedFile(); 1360 if (!e.getValueIsAdjusting() && f != null && !getFileChooser().isTraversable(f)) { 1361 setFileName(fileNameString(f)); 1362 } 1363 } 1364 1365 /** 1366 * Acts when DirectoryComboBox has changed the selected item. 1367 */ 1368 protected class DirectoryComboBoxAction implements ActionListener { 1369 1370 1371 1372 1373 public void actionPerformed(ActionEvent e) { 1374 File f = (File)directoryComboBox.getSelectedItem(); 1375 getFileChooser().setCurrentDirectory(f); 1376 } 1377 } 1378 1379 protected JButton getApproveButton(JFileChooser fc) { 1380 return approveButton; 1381 } 1382 1383 public FileView getFileView(JFileChooser fc) { 1384 return fileView; 1385 } 1386 1387 // *********************** 1388 // * FileView operations * 1389 // *********************** 1390 protected class WindowsFileView extends BasicFileView { 1391 /* FileView type descriptions */ 1392 1393 public Icon getIcon(File f) { 1394 Icon icon = getCachedIcon(f); 1395 if (icon != null) { 1396 return icon; 1397 } 1398 if (f != null) { 1399 icon = getFileChooser().getFileSystemView().getSystemIcon(f); 1400 } 1401 if (icon == null) { 1402 icon = super.getIcon(f); 1403 } 1404 cacheIcon(f, icon); 1405 return icon; 1406 } 1407 } 1408 }