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