History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/swing/plaf/synth/SynthFileChooserUIImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/swing/plaf/synth/SynthFileChooserUIImpl.java+1113−0
@@ -0,0 +1,1113 @@
1+/*
2+ * Copyright (c) 2003, 2010, 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+package sun.swing.plaf.synth;
26+
27+import java.awt.*;
28+import java.awt.event.*;
29+import java.beans.*;
30+import java.io.*;
31+import java.util.*;
32+import java.security.AccessController;
33+import java.security.PrivilegedAction;
34+
35+import javax.swing.*;
36+import javax.swing.event.*;
37+import javax.swing.filechooser.*;
38+import javax.swing.filechooser.FileFilter;
39+import javax.swing.plaf.basic.*;
40+import javax.swing.plaf.synth.*;
41+import javax.swing.plaf.ActionMapUIResource;
42+
43+import sun.awt.shell.ShellFolder;
44+import sun.swing.*;
45+
46+/**
47+ * Synth FileChooserUI implementation.
48+ * <p>
49+ * Note that the classes in the com.sun.java.swing.plaf.synth
50+ * package are not
51+ * part of the core Java APIs. They are a part of Sun's JDK and JRE
52+ * distributions. Although other licensees may choose to distribute
53+ * these classes, developers cannot depend on their availability in
54+ * non-Sun implementations. Additionally this API may change in
55+ * incompatible ways between releases. While this class is public, it
56+ * shoud be considered an implementation detail, and subject to change.
57+ *
58+ * @author Leif Samuelsson
59+ * @author Jeff Dinkins
60+ */
61+public class SynthFileChooserUIImpl extends SynthFileChooserUI {
62+ private JLabel lookInLabel;
63+ private JComboBox directoryComboBox;
64+ private DirectoryComboBoxModel directoryComboBoxModel;
65+ private Action directoryComboBoxAction = new DirectoryComboBoxAction();
66+
67+ private FilterComboBoxModel filterComboBoxModel;
68+
69+ private JTextField fileNameTextField;
70+
71+ private FilePane filePane;
72+ private JToggleButton listViewButton;
73+ private JToggleButton detailsViewButton;
74+
75+ private boolean readOnly;
76+
77+ private JPanel buttonPanel;
78+ private JPanel bottomPanel;
79+
80+ private JComboBox filterComboBox;
81+
82+ private static final Dimension hstrut5 = new Dimension(5, 1);
83+ private static final Dimension vstrut5 = new Dimension(1, 5);
84+
85+ private static final Insets shrinkwrap = new Insets(0,0,0,0);
86+
87+ // Preferred and Minimum sizes for the dialog box
88+ private static Dimension LIST_PREF_SIZE = new Dimension(405, 135);
89+
90+ // Labels, mnemonics, and tooltips (oh my!)
91+ private int lookInLabelMnemonic = 0;
92+ private String lookInLabelText = null;
93+ private String saveInLabelText = null;
94+
95+ private int fileNameLabelMnemonic = 0;
96+ private String fileNameLabelText = null;
97+ private int folderNameLabelMnemonic = 0;
98+ private String folderNameLabelText = null;
99+
100+ private int filesOfTypeLabelMnemonic = 0;
101+ private String filesOfTypeLabelText = null;
102+
103+ private String upFolderToolTipText = null;
104+ private String upFolderAccessibleName = null;
105+
106+ private String homeFolderToolTipText = null;
107+ private String homeFolderAccessibleName = null;
108+
109+ private String newFolderToolTipText = null;
110+ private String newFolderAccessibleName = null;
111+
112+ private String listViewButtonToolTipText = null;
113+ private String listViewButtonAccessibleName = null;
114+
115+ private String detailsViewButtonToolTipText = null;
116+ private String detailsViewButtonAccessibleName = null;
117+
118+ private AlignedLabel fileNameLabel;
119+ private final PropertyChangeListener modeListener = new PropertyChangeListener() {
120+ public void propertyChange(PropertyChangeEvent event) {
121+ if (fileNameLabel != null) {
122+ populateFileNameLabel();
123+ }
124+ }
125+ };
126+
127+ private void populateFileNameLabel() {
128+ if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) {
129+ fileNameLabel.setText(folderNameLabelText);
130+ fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic);
131+ } else {
132+ fileNameLabel.setText(fileNameLabelText);
133+ fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic);
134+ }
135+ }
136+
137+ public SynthFileChooserUIImpl(JFileChooser b) {
138+ super(b);
139+ }
140+
141+
142+ private class SynthFileChooserUIAccessor implements FilePane.FileChooserUIAccessor {
143+ public JFileChooser getFileChooser() {
144+ return SynthFileChooserUIImpl.this.getFileChooser();
145+ }
146+
147+ public BasicDirectoryModel getModel() {
148+ return SynthFileChooserUIImpl.this.getModel();
149+ }
150+
151+ public JPanel createList() {
152+ return null;
153+ }
154+
155+ public JPanel createDetailsView() {
156+ return null;
157+ }
158+
159+ public boolean isDirectorySelected() {
160+ return SynthFileChooserUIImpl.this.isDirectorySelected();
161+ }
162+
163+ public File getDirectory() {
164+ return SynthFileChooserUIImpl.this.getDirectory();
165+ }
166+
167+ public Action getChangeToParentDirectoryAction() {
168+ return SynthFileChooserUIImpl.this.getChangeToParentDirectoryAction();
169+ }
170+
171+ public Action getApproveSelectionAction() {
172+ return SynthFileChooserUIImpl.this.getApproveSelectionAction();
173+ }
174+
175+ public Action getNewFolderAction() {
176+ return SynthFileChooserUIImpl.this.getNewFolderAction();
177+ }
178+
179+ public MouseListener createDoubleClickListener(JList list) {
180+ return SynthFileChooserUIImpl.this.createDoubleClickListener(getFileChooser(),
181+ list);
182+ }
183+
184+ public ListSelectionListener createListSelectionListener() {
185+ return SynthFileChooserUIImpl.this.createListSelectionListener(getFileChooser());
186+ }
187+ }
188+
189+ protected void installDefaults(JFileChooser fc) {
190+ super.installDefaults(fc);
191+ readOnly = UIManager.getBoolean("FileChooser.readOnly");
192+ }
193+
194+ public void installComponents(JFileChooser fc) {
195+ super.installComponents(fc);
196+
197+ SynthContext context = getContext(fc, ENABLED);
198+
199+ fc.setLayout(new BorderLayout(0, 11));
200+
201+ // ********************************* //
202+ // **** Construct the top panel **** //
203+ // ********************************* //
204+
205+ // Directory manipulation buttons
206+ JPanel topPanel = new JPanel(new BorderLayout(11, 0));
207+ JPanel topButtonPanel = new JPanel();
208+ topButtonPanel.setLayout(new BoxLayout(topButtonPanel, BoxLayout.LINE_AXIS));
209+ topPanel.add(topButtonPanel, BorderLayout.AFTER_LINE_ENDS);
210+
211+ // Add the top panel to the fileChooser
212+ fc.add(topPanel, BorderLayout.NORTH);
213+
214+ // ComboBox Label
215+ lookInLabel = new JLabel(lookInLabelText);
216+ lookInLabel.setDisplayedMnemonic(lookInLabelMnemonic);
217+ topPanel.add(lookInLabel, BorderLayout.BEFORE_LINE_BEGINS);
218+
219+ // CurrentDir ComboBox
220+ directoryComboBox = new JComboBox();
221+ directoryComboBox.getAccessibleContext().setAccessibleDescription(lookInLabelText);
222+ directoryComboBox.putClientProperty( "JComboBox.isTableCellEditor", Boolean.TRUE );
223+ lookInLabel.setLabelFor(directoryComboBox);
224+ directoryComboBoxModel = createDirectoryComboBoxModel(fc);
225+ directoryComboBox.setModel(directoryComboBoxModel);
226+ directoryComboBox.addActionListener(directoryComboBoxAction);
227+ directoryComboBox.setRenderer(createDirectoryComboBoxRenderer(fc));
228+ directoryComboBox.setAlignmentX(JComponent.LEFT_ALIGNMENT);
229+ directoryComboBox.setAlignmentY(JComponent.TOP_ALIGNMENT);
230+ directoryComboBox.setMaximumRowCount(8);
231+ topPanel.add(directoryComboBox, BorderLayout.CENTER);
232+
233+ filePane = new FilePane(new SynthFileChooserUIAccessor());
234+ fc.addPropertyChangeListener(filePane);
235+
236+ // Add 'Go Up' to context menu, plus 'Go Home' if on Unix
237+ JPopupMenu contextMenu = filePane.getComponentPopupMenu();
238+ if (contextMenu != null) {
239+ contextMenu.insert(getChangeToParentDirectoryAction(), 0);
240+ if (File.separatorChar == '/') {
241+ contextMenu.insert(getGoHomeAction(), 1);
242+ }
243+ }
244+
245+ FileSystemView fsv = fc.getFileSystemView();
246+
247+ // Up Button
248+ JButton upFolderButton = new JButton(getChangeToParentDirectoryAction());
249+ upFolderButton.setText(null);
250+ upFolderButton.setIcon(upFolderIcon);
251+ upFolderButton.setToolTipText(upFolderToolTipText);
252+ upFolderButton.getAccessibleContext().setAccessibleName(upFolderAccessibleName);
253+ upFolderButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
254+ upFolderButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
255+ upFolderButton.setMargin(shrinkwrap);
256+
257+ topButtonPanel.add(upFolderButton);
258+ topButtonPanel.add(Box.createRigidArea(hstrut5));
259+
260+ // Home Button
261+ File homeDir = fsv.getHomeDirectory();
262+ String toolTipText = homeFolderToolTipText;
263+ if (fsv.isRoot(homeDir)) {
264+ toolTipText = getFileView(fc).getName(homeDir); // Probably "Desktop".
265+ }
266+
267+ JButton b = new JButton(homeFolderIcon);
268+ b.setToolTipText(toolTipText);
269+ b.getAccessibleContext().setAccessibleName(homeFolderAccessibleName);
270+ b.setAlignmentX(JComponent.LEFT_ALIGNMENT);
271+ b.setAlignmentY(JComponent.CENTER_ALIGNMENT);
272+ b.setMargin(shrinkwrap);
273+
274+ b.addActionListener(getGoHomeAction());
275+ topButtonPanel.add(b);
276+ topButtonPanel.add(Box.createRigidArea(hstrut5));
277+
278+ // New Directory Button
279+ if (!readOnly) {
280+ b = new JButton(filePane.getNewFolderAction());
281+ b.setText(null);
282+ b.setIcon(newFolderIcon);
283+ b.setToolTipText(newFolderToolTipText);
284+ b.getAccessibleContext().setAccessibleName(newFolderAccessibleName);
285+ b.setAlignmentX(JComponent.LEFT_ALIGNMENT);
286+ b.setAlignmentY(JComponent.CENTER_ALIGNMENT);
287+ b.setMargin(shrinkwrap);
288+ topButtonPanel.add(b);
289+ topButtonPanel.add(Box.createRigidArea(hstrut5));
290+ }
291+
292+ // View button group
293+ ButtonGroup viewButtonGroup = new ButtonGroup();
294+
295+ // List Button
296+ listViewButton = new JToggleButton(listViewIcon);
297+ listViewButton.setToolTipText(listViewButtonToolTipText);
298+ listViewButton.getAccessibleContext().setAccessibleName(listViewButtonAccessibleName);
299+ listViewButton.setSelected(true);
300+ listViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
301+ listViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
302+ listViewButton.setMargin(shrinkwrap);
303+ listViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST));
304+ topButtonPanel.add(listViewButton);
305+ viewButtonGroup.add(listViewButton);
306+
307+ // Details Button
308+ detailsViewButton = new JToggleButton(detailsViewIcon);
309+ detailsViewButton.setToolTipText(detailsViewButtonToolTipText);
310+ detailsViewButton.getAccessibleContext().setAccessibleName(detailsViewButtonAccessibleName);
311+ detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
312+ detailsViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT);
313+ detailsViewButton.setMargin(shrinkwrap);
314+ detailsViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS));
315+ topButtonPanel.add(detailsViewButton);
316+ viewButtonGroup.add(detailsViewButton);
317+
318+ filePane.addPropertyChangeListener(new PropertyChangeListener() {
319+ public void propertyChange(PropertyChangeEvent e) {
320+ if ("viewType".equals(e.getPropertyName())) {
321+ int viewType = filePane.getViewType();
322+ switch (viewType) {
323+ case FilePane.VIEWTYPE_LIST:
324+ listViewButton.setSelected(true);
325+ break;
326+ case FilePane.VIEWTYPE_DETAILS:
327+ detailsViewButton.setSelected(true);
328+ break;
329+ }
330+ }
331+ }
332+ });
333+
334+ // ************************************** //
335+ // ******* Add the directory pane ******* //
336+ // ************************************** //
337+ fc.add(getAccessoryPanel(), BorderLayout.AFTER_LINE_ENDS);
338+ JComponent accessory = fc.getAccessory();
339+ if (accessory != null) {
340+ getAccessoryPanel().add(accessory);
341+ }
342+ filePane.setPreferredSize(LIST_PREF_SIZE);
343+ fc.add(filePane, BorderLayout.CENTER);
344+
345+
346+ // ********************************** //
347+ // **** Construct the bottom panel ** //
348+ // ********************************** //
349+ bottomPanel = new JPanel();
350+ bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));
351+ fc.add(bottomPanel, BorderLayout.SOUTH);
352+
353+ // FileName label and textfield
354+ JPanel fileNamePanel = new JPanel();
355+ fileNamePanel.setLayout(new BoxLayout(fileNamePanel, BoxLayout.LINE_AXIS));
356+ bottomPanel.add(fileNamePanel);
357+ bottomPanel.add(Box.createRigidArea(new Dimension(1, 5)));
358+
359+ fileNameLabel = new AlignedLabel();
360+ populateFileNameLabel();
361+ fileNamePanel.add(fileNameLabel);
362+
363+ fileNameTextField = new JTextField(35) {
364+ public Dimension getMaximumSize() {
365+ return new Dimension(Short.MAX_VALUE, super.getPreferredSize().height);
366+ }
367+ };
368+ fileNamePanel.add(fileNameTextField);
369+ fileNameLabel.setLabelFor(fileNameTextField);
370+ fileNameTextField.addFocusListener(
371+ new FocusAdapter() {
372+ public void focusGained(FocusEvent e) {
373+ if (!getFileChooser().isMultiSelectionEnabled()) {
374+ filePane.clearSelection();
375+ }
376+ }
377+ }
378+ );
379+ if (fc.isMultiSelectionEnabled()) {
380+ setFileName(fileNameString(fc.getSelectedFiles()));
381+ } else {
382+ setFileName(fileNameString(fc.getSelectedFile()));
383+ }
384+
385+
386+ // Filetype label and combobox
387+ JPanel filesOfTypePanel = new JPanel();
388+ filesOfTypePanel.setLayout(new BoxLayout(filesOfTypePanel, BoxLayout.LINE_AXIS));
389+ bottomPanel.add(filesOfTypePanel);
390+
391+ AlignedLabel filesOfTypeLabel = new AlignedLabel(filesOfTypeLabelText);
392+ filesOfTypeLabel.setDisplayedMnemonic(filesOfTypeLabelMnemonic);
393+ filesOfTypePanel.add(filesOfTypeLabel);
394+
395+ filterComboBoxModel = createFilterComboBoxModel();
396+ fc.addPropertyChangeListener(filterComboBoxModel);
397+ filterComboBox = new JComboBox(filterComboBoxModel);
398+ filterComboBox.getAccessibleContext().setAccessibleDescription(filesOfTypeLabelText);
399+ filesOfTypeLabel.setLabelFor(filterComboBox);
400+ filterComboBox.setRenderer(createFilterComboBoxRenderer());
401+ filesOfTypePanel.add(filterComboBox);
402+
403+
404+ // buttons
405+ buttonPanel = new JPanel();
406+ buttonPanel.setLayout(new ButtonAreaLayout());
407+
408+ buttonPanel.add(getApproveButton(fc));
409+ buttonPanel.add(getCancelButton(fc));
410+
411+ if (fc.getControlButtonsAreShown()) {
412+ addControlButtons();
413+ }
414+
415+ groupLabels(new AlignedLabel[] { fileNameLabel, filesOfTypeLabel });
416+ }
417+
418+ protected void installListeners(JFileChooser fc) {
419+ super.installListeners(fc);
420+ fc.addPropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener);
421+ }
422+
423+ protected void uninstallListeners(JFileChooser fc) {
424+ fc.removePropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener);
425+ super.uninstallListeners(fc);
426+ }
427+
428+ private String fileNameString(File file) {
429+ if (file == null) {
430+ return null;
431+ } else {
432+ JFileChooser fc = getFileChooser();
433+ if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
434+ return file.getPath();
435+ } else {
436+ return file.getName();
437+ }
438+ }
439+ }
440+
441+ private String fileNameString(File[] files) {
442+ StringBuffer buf = new StringBuffer();
443+ for (int i = 0; files != null && i < files.length; i++) {
444+ if (i > 0) {
445+ buf.append(" ");
446+ }
447+ if (files.length > 1) {
448+ buf.append("\"");
449+ }
450+ buf.append(fileNameString(files[i]));
451+ if (files.length > 1) {
452+ buf.append("\"");
453+ }
454+ }
455+ return buf.toString();
456+ }
457+
458+ public void uninstallUI(JComponent c) {
459+ // Remove listeners
460+ c.removePropertyChangeListener(filterComboBoxModel);
461+ c.removePropertyChangeListener(filePane);
462+
463+ if (filePane != null) {
464+ filePane.uninstallUI();
465+ filePane = null;
466+ }
467+
468+ super.uninstallUI(c);
469+ }
470+
471+ protected void installStrings(JFileChooser fc) {
472+ super.installStrings(fc);
473+
474+ Locale l = fc.getLocale();
475+
476+ lookInLabelMnemonic = getMnemonic("FileChooser.lookInLabelMnemonic", l);
477+ lookInLabelText = UIManager.getString("FileChooser.lookInLabelText", l);
478+ saveInLabelText = UIManager.getString("FileChooser.saveInLabelText", l);
479+
480+ fileNameLabelMnemonic = getMnemonic("FileChooser.fileNameLabelMnemonic", l);
481+ fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText", l);
482+ folderNameLabelMnemonic = getMnemonic("FileChooser.folderNameLabelMnemonic", l);
483+ folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText", l);
484+
485+ filesOfTypeLabelMnemonic = getMnemonic("FileChooser.filesOfTypeLabelMnemonic", l);
486+ filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText", l);
487+
488+ upFolderToolTipText = UIManager.getString("FileChooser.upFolderToolTipText",l);
489+ upFolderAccessibleName = UIManager.getString("FileChooser.upFolderAccessibleName",l);
490+
491+ homeFolderToolTipText = UIManager.getString("FileChooser.homeFolderToolTipText",l);
492+ homeFolderAccessibleName = UIManager.getString("FileChooser.homeFolderAccessibleName",l);
493+
494+ newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText",l);
495+ newFolderAccessibleName = UIManager.getString("FileChooser.newFolderAccessibleName",l);
496+
497+ listViewButtonToolTipText = UIManager.getString("FileChooser.listViewButtonToolTipText",l);
498+ listViewButtonAccessibleName = UIManager.getString("FileChooser.listViewButtonAccessibleName",l);
499+
500+ detailsViewButtonToolTipText = UIManager.getString("FileChooser.detailsViewButtonToolTipText",l);
501+ detailsViewButtonAccessibleName = UIManager.getString("FileChooser.detailsViewButtonAccessibleName",l);
502+ }
503+
504+ private int getMnemonic(String key, Locale l) {
505+ return SwingUtilities2.getUIDefaultsInt(key, l);
506+ }
507+
508+
509+ public String getFileName() {
510+ if (fileNameTextField != null) {
511+ return fileNameTextField.getText();
512+ } else {
513+ return null;
514+ }
515+ }
516+
517+ public void setFileName(String fileName) {
518+ if (fileNameTextField != null) {
519+ fileNameTextField.setText(fileName);
520+ }
521+ }
522+
523+ @Override public void rescanCurrentDirectory(JFileChooser fc) {
524+ filePane.rescanCurrentDirectory();
525+ }
526+
527+ protected void doSelectedFileChanged(PropertyChangeEvent e) {
528+ super.doSelectedFileChanged(e);
529+
530+ File f = (File) e.getNewValue();
531+ JFileChooser fc = getFileChooser();
532+ if (f != null
533+ && ((fc.isFileSelectionEnabled() && !f.isDirectory())
534+ || (f.isDirectory() && fc.isDirectorySelectionEnabled()))) {
535+
536+ setFileName(fileNameString(f));
537+ }
538+ }
539+
540+ protected void doSelectedFilesChanged(PropertyChangeEvent e) {
541+ super.doSelectedFilesChanged(e);
542+
543+ File[] files = (File[]) e.getNewValue();
544+ JFileChooser fc = getFileChooser();
545+ if (files != null
546+ && files.length > 0
547+ && (files.length > 1 || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) {
548+ setFileName(fileNameString(files));
549+ }
550+ }
551+
552+ protected void doDirectoryChanged(PropertyChangeEvent e) {
553+ super.doDirectoryChanged(e);
554+
555+ JFileChooser fc = getFileChooser();
556+ FileSystemView fsv = fc.getFileSystemView();
557+ File currentDirectory = fc.getCurrentDirectory();
558+
559+ if (!readOnly && currentDirectory != null) {
560+ getNewFolderAction().setEnabled(filePane.canWrite(currentDirectory));
561+ }
562+
563+ if (currentDirectory != null) {
564+ JComponent cb = getDirectoryComboBox();
565+ if (cb instanceof JComboBox) {
566+ ComboBoxModel model = ((JComboBox)cb).getModel();
567+ if (model instanceof DirectoryComboBoxModel) {
568+ ((DirectoryComboBoxModel)model).addItem(currentDirectory);
569+ }
570+ }
571+
572+ if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
573+ if (fsv.isFileSystem(currentDirectory)) {
574+ setFileName(currentDirectory.getPath());
575+ } else {
576+ setFileName(null);
577+ }
578+ }
579+ }
580+ }
581+
582+
583+ protected void doFileSelectionModeChanged(PropertyChangeEvent e) {
584+ super.doFileSelectionModeChanged(e);
585+
586+ JFileChooser fc = getFileChooser();
587+ File currentDirectory = fc.getCurrentDirectory();
588+ if (currentDirectory != null
589+ && fc.isDirectorySelectionEnabled()
590+ && !fc.isFileSelectionEnabled()
591+ && fc.getFileSystemView().isFileSystem(currentDirectory)) {
592+
593+ setFileName(currentDirectory.getPath());
594+ } else {
595+ setFileName(null);
596+ }
597+ }
598+
599+ protected void doAccessoryChanged(PropertyChangeEvent e) {
600+ if (getAccessoryPanel() != null) {
601+ if (e.getOldValue() != null) {
602+ getAccessoryPanel().remove((JComponent)e.getOldValue());
603+ }
604+ JComponent accessory = (JComponent)e.getNewValue();
605+ if (accessory != null) {
606+ getAccessoryPanel().add(accessory, BorderLayout.CENTER);
607+ }
608+ }
609+ }
610+
611+ protected void doControlButtonsChanged(PropertyChangeEvent e) {
612+ super.doControlButtonsChanged(e);
613+
614+ if (getFileChooser().getControlButtonsAreShown()) {
615+ addControlButtons();
616+ } else {
617+ removeControlButtons();
618+ }
619+ }
620+
621+ protected void addControlButtons() {
622+ if (bottomPanel != null) {
623+ bottomPanel.add(buttonPanel);
624+ }
625+ }
626+
627+ protected void removeControlButtons() {
628+ if (bottomPanel != null) {
629+ bottomPanel.remove(buttonPanel);
630+ }
631+ }
632+
633+
634+
635+
636+ // *******************************************************
637+ // ************ FileChooser UI PLAF methods **************
638+ // *******************************************************
639+
640+ protected ActionMap createActionMap() {
641+ ActionMap map = new ActionMapUIResource();
642+ // add standard actions
643+ FilePane.addActionsToMap(map, filePane.getActions());
644+ // add synth only actions
645+ map.put("fileNameCompletion", getFileNameCompletionAction());
646+ return map;
647+ }
648+
649+ // *****************************
650+ // ***** Directory Actions *****
651+ // *****************************
652+
653+ protected JComponent getDirectoryComboBox() {
654+ return directoryComboBox;
655+ }
656+
657+ protected Action getDirectoryComboBoxAction() {
658+ return directoryComboBoxAction;
659+ }
660+
661+ protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
662+ return new DirectoryComboBoxRenderer(directoryComboBox.getRenderer());
663+ }
664+
665+ //
666+ // Renderer for DirectoryComboBox
667+ //
668+ // Synth has some odd behavior with regards to renderers. Renderers are styled
669+ // in a specific manner by the SynthComboBoxUI. If we extend DefaultListCellRenderer
670+ // here, then we get none of those benefits or behaviors, leading to poor
671+ // looking combo boxes.
672+ // So what we do here is delegate most jobs to the "real" or original renderer,
673+ // and simply monkey with the icon and text of the renderer.
674+ private class DirectoryComboBoxRenderer implements ListCellRenderer {
675+ private ListCellRenderer delegate;
676+ IndentIcon ii = new IndentIcon();
677+
678+ private DirectoryComboBoxRenderer(ListCellRenderer delegate) {
679+ this.delegate = delegate;
680+ }
681+
682+ @Override
683+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
684+ Component c = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
685+
686+ assert c instanceof JLabel;
687+ JLabel label = (JLabel)c;
688+ if (value == null) {
689+ label.setText("");
690+ return label;
691+ }
692+ File directory = (File) value;
693+ label.setText(getFileChooser().getName(directory));
694+ Icon icon = getFileChooser().getIcon(directory);
695+ ii.icon = icon;
696+ ii.depth = directoryComboBoxModel.getDepth(index);
697+ label.setIcon(ii);
698+
699+ return label;
700+ }
701+ }
702+
703+ final static int space = 10;
704+ class IndentIcon implements Icon {
705+
706+ Icon icon = null;
707+ int depth = 0;
708+
709+ public void paintIcon(Component c, Graphics g, int x, int y) {
710+ if (icon != null) {
711+ if (c.getComponentOrientation().isLeftToRight()) {
712+ icon.paintIcon(c, g, x+depth*space, y);
713+ } else {
714+ icon.paintIcon(c, g, x, y);
715+ }
716+ }
717+ }
718+
719+ public int getIconWidth() {
720+ return ((icon != null) ? icon.getIconWidth() : 0) + depth*space;
721+ }
722+
723+ public int getIconHeight() {
724+ return (icon != null) ? icon.getIconHeight() : 0;
725+ }
726+
727+ }
728+
729+ //
730+ // DataModel for DirectoryComboxbox
731+ //
732+ protected DirectoryComboBoxModel createDirectoryComboBoxModel(JFileChooser fc) {
733+ return new DirectoryComboBoxModel();
734+ }
735+
736+ /**
737+ * Data model for a type-face selection combo-box.
738+ */
739+ protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel {
740+ Vector<File> directories = new Vector<File>();
741+ int[] depths = null;
742+ File selectedDirectory = null;
743+ JFileChooser chooser = getFileChooser();
744+ FileSystemView fsv = chooser.getFileSystemView();
745+
746+ public DirectoryComboBoxModel() {
747+ // Add the current directory to the model, and make it the
748+ // selectedDirectory
749+ File dir = getFileChooser().getCurrentDirectory();
750+ if (dir != null) {
751+ addItem(dir);
752+ }
753+ }
754+
755+ /**
756+ * Adds the directory to the model and sets it to be selected,
757+ * additionally clears out the previous selected directory and
758+ * the paths leading up to it, if any.
759+ */
760+ public void addItem(File directory) {
761+
762+ if (directory == null) {
763+ return;
764+ }
765+
766+ boolean useShellFolder = FilePane.usesShellFolder(chooser);
767+
768+ int oldSize = directories.size();
769+ directories.clear();
770+ if (oldSize > 0) {
771+ fireIntervalRemoved(this, 0, oldSize);
772+ }
773+
774+ File[] baseFolders;
775+ if (useShellFolder) {
776+ baseFolders = AccessController.doPrivileged(new PrivilegedAction<File[]>() {
777+ public File[] run() {
778+ return (File[]) ShellFolder.get("fileChooserComboBoxFolders");
779+ }
780+ });
781+ } else {
782+ baseFolders = fsv.getRoots();
783+ }
784+ directories.addAll(Arrays.asList(baseFolders));
785+
786+ // Get the canonical (full) path. This has the side
787+ // benefit of removing extraneous chars from the path,
788+ // for example /foo/bar/ becomes /foo/bar
789+ File canonical;
790+ try {
791+ canonical = ShellFolder.getNormalizedFile(directory);
792+ } catch (IOException e) {
793+ // Maybe drive is not ready. Can't abort here.
794+ canonical = directory;
795+ }
796+
797+ // create File instances of each directory leading up to the top
798+ try {
799+ File sf = useShellFolder ? ShellFolder.getShellFolder(canonical)
800+ : canonical;
801+ File f = sf;
802+ Vector<File> path = new Vector<File>(10);
803+ do {
804+ path.addElement(f);
805+ } while ((f = f.getParentFile()) != null);
806+
807+ int pathCount = path.size();
808+ // Insert chain at appropriate place in vector
809+ for (int i = 0; i < pathCount; i++) {
810+ f = path.get(i);
811+ if (directories.contains(f)) {
812+ int topIndex = directories.indexOf(f);
813+ for (int j = i-1; j >= 0; j--) {
814+ directories.insertElementAt(path.get(j), topIndex+i-j);
815+ }
816+ break;
817+ }
818+ }
819+ calculateDepths();
820+ setSelectedItem(sf);
821+ } catch (FileNotFoundException ex) {
822+ calculateDepths();
823+ }
824+ }
825+
826+ private void calculateDepths() {
827+ depths = new int[directories.size()];
828+ for (int i = 0; i < depths.length; i++) {
829+ File dir = directories.get(i);
830+ File parent = dir.getParentFile();
831+ depths[i] = 0;
832+ if (parent != null) {
833+ for (int j = i-1; j >= 0; j--) {
834+ if (parent.equals(directories.get(j))) {
835+ depths[i] = depths[j] + 1;
836+ break;
837+ }
838+ }
839+ }
840+ }
841+ }
842+
843+ public int getDepth(int i) {
844+ return (depths != null && i >= 0 && i < depths.length) ? depths[i] : 0;
845+ }
846+
847+ public void setSelectedItem(Object selectedDirectory) {
848+ this.selectedDirectory = (File)selectedDirectory;
849+ fireContentsChanged(this, -1, -1);
850+ }
851+
852+ public Object getSelectedItem() {
853+ return selectedDirectory;
854+ }
855+
856+ public int getSize() {
857+ return directories.size();
858+ }
859+
860+ public Object getElementAt(int index) {
861+ return directories.elementAt(index);
862+ }
863+ }
864+
865+ /**
866+ * Acts when DirectoryComboBox has changed the selected item.
867+ */
868+ protected class DirectoryComboBoxAction extends AbstractAction {
869+ protected DirectoryComboBoxAction() {
870+ super("DirectoryComboBoxAction");
871+ }
872+
873+ public void actionPerformed(ActionEvent e) {
874+ directoryComboBox.hidePopup();
875+ JComponent cb = getDirectoryComboBox();
876+ if (cb instanceof JComboBox) {
877+ File f = (File)((JComboBox)cb).getSelectedItem();
878+ getFileChooser().setCurrentDirectory(f);
879+ }
880+ }
881+ }
882+
883+ //
884+ // Renderer for Types ComboBox
885+ //
886+ protected FilterComboBoxRenderer createFilterComboBoxRenderer() {
887+ return new FilterComboBoxRenderer(filterComboBox.getRenderer());
888+ }
889+
890+ /**
891+ * Render different type sizes and styles.
892+ */
893+ public class FilterComboBoxRenderer implements ListCellRenderer {
894+ private ListCellRenderer delegate;
895+ private FilterComboBoxRenderer(ListCellRenderer delegate) {
896+ this.delegate = delegate;
897+ }
898+
899+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
900+ Component c = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
901+
902+ String text = null;
903+ if (value != null && value instanceof FileFilter) {
904+ text = ((FileFilter) value).getDescription();
905+ }
906+
907+ //this should always be true, since SynthComboBoxUI's SynthComboBoxRenderer
908+ //extends JLabel
909+ assert c instanceof JLabel;
910+ if (text != null) {
911+ ((JLabel)c).setText(text);
912+ }
913+ return c;
914+ }
915+ }
916+
917+ //
918+ // DataModel for Types Comboxbox
919+ //
920+ protected FilterComboBoxModel createFilterComboBoxModel() {
921+ return new FilterComboBoxModel();
922+ }
923+
924+ /**
925+ * Data model for a type-face selection combo-box.
926+ */
927+ protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener {
928+ protected FileFilter[] filters;
929+ protected FilterComboBoxModel() {
930+ super();
931+ filters = getFileChooser().getChoosableFileFilters();
932+ }
933+
934+ public void propertyChange(PropertyChangeEvent e) {
935+ String prop = e.getPropertyName();
936+ if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) {
937+ filters = (FileFilter[]) e.getNewValue();
938+ fireContentsChanged(this, -1, -1);
939+ } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) {
940+ fireContentsChanged(this, -1, -1);
941+ }
942+ }
943+
944+ public void setSelectedItem(Object filter) {
945+ if(filter != null) {
946+ getFileChooser().setFileFilter((FileFilter) filter);
947+ fireContentsChanged(this, -1, -1);
948+ }
949+ }
950+
951+ public Object getSelectedItem() {
952+ // Ensure that the current filter is in the list.
953+ // NOTE: we shouldnt' have to do this, since JFileChooser adds
954+ // the filter to the choosable filters list when the filter
955+ // is set. Lets be paranoid just in case someone overrides
956+ // setFileFilter in JFileChooser.
957+ FileFilter currentFilter = getFileChooser().getFileFilter();
958+ boolean found = false;
959+ if(currentFilter != null) {
960+ for (FileFilter filter : filters) {
961+ if (filter == currentFilter) {
962+ found = true;
963+ }
964+ }
965+ if(found == false) {
966+ getFileChooser().addChoosableFileFilter(currentFilter);
967+ }
968+ }
969+ return getFileChooser().getFileFilter();
970+ }
971+
972+ public int getSize() {
973+ if(filters != null) {
974+ return filters.length;
975+ } else {
976+ return 0;
977+ }
978+ }
979+
980+ public Object getElementAt(int index) {
981+ if(index > getSize() - 1) {
982+ // This shouldn't happen. Try to recover gracefully.
983+ return getFileChooser().getFileFilter();
984+ }
985+ if(filters != null) {
986+ return filters[index];
987+ } else {
988+ return null;
989+ }
990+ }
991+ }
992+
993+
994+
995+ /**
996+ * <code>ButtonAreaLayout</code> behaves in a similar manner to
997+ * <code>FlowLayout</code>. It lays out all components from left to
998+ * right, flushed right. The widths of all components will be set
999+ * to the largest preferred size width.
1000+ */
1001+ private static class ButtonAreaLayout implements LayoutManager {
1002+ private int hGap = 5;
1003+ private int topMargin = 17;
1004+
1005+ public void addLayoutComponent(String string, Component comp) {
1006+ }
1007+
1008+ public void layoutContainer(Container container) {
1009+ Component[] children = container.getComponents();
1010+
1011+ if (children != null && children.length > 0) {
1012+ int numChildren = children.length;
1013+ Dimension[] sizes = new Dimension[numChildren];
1014+ Insets insets = container.getInsets();
1015+ int yLocation = insets.top + topMargin;
1016+ int maxWidth = 0;
1017+
1018+ for (int counter = 0; counter < numChildren; counter++) {
1019+ sizes[counter] = children[counter].getPreferredSize();
1020+ maxWidth = Math.max(maxWidth, sizes[counter].width);
1021+ }
1022+ int xLocation, xOffset;
1023+ if (container.getComponentOrientation().isLeftToRight()) {
1024+ xLocation = container.getSize().width - insets.left - maxWidth;
1025+ xOffset = hGap + maxWidth;
1026+ } else {
1027+ xLocation = insets.left;
1028+ xOffset = -(hGap + maxWidth);
1029+ }
1030+ for (int counter = numChildren - 1; counter >= 0; counter--) {
1031+ children[counter].setBounds(xLocation, yLocation,
1032+ maxWidth, sizes[counter].height);
1033+ xLocation -= xOffset;
1034+ }
1035+ }
1036+ }
1037+
1038+ public Dimension minimumLayoutSize(Container c) {
1039+ if (c != null) {
1040+ Component[] children = c.getComponents();
1041+
1042+ if (children != null && children.length > 0) {
1043+ int numChildren = children.length;
1044+ int height = 0;
1045+ Insets cInsets = c.getInsets();
1046+ int extraHeight = topMargin + cInsets.top + cInsets.bottom;
1047+ int extraWidth = cInsets.left + cInsets.right;
1048+ int maxWidth = 0;
1049+
1050+ for (int counter = 0; counter < numChildren; counter++) {
1051+ Dimension aSize = children[counter].getPreferredSize();
1052+ height = Math.max(height, aSize.height);
1053+ maxWidth = Math.max(maxWidth, aSize.width);
1054+ }
1055+ return new Dimension(extraWidth + numChildren * maxWidth +
1056+ (numChildren - 1) * hGap,
1057+ extraHeight + height);
1058+ }
1059+ }
1060+ return new Dimension(0, 0);
1061+ }
1062+
1063+ public Dimension preferredLayoutSize(Container c) {
1064+ return minimumLayoutSize(c);
1065+ }
1066+
1067+ public void removeLayoutComponent(Component c) { }
1068+ }
1069+
1070+ private static void groupLabels(AlignedLabel[] group) {
1071+ for (int i = 0; i < group.length; i++) {
1072+ group[i].group = group;
1073+ }
1074+ }
1075+
1076+ private class AlignedLabel extends JLabel {
1077+ private AlignedLabel[] group;
1078+ private int maxWidth = 0;
1079+
1080+ AlignedLabel() {
1081+ super();
1082+ setAlignmentX(JComponent.LEFT_ALIGNMENT);
1083+ }
1084+
1085+ AlignedLabel(String text) {
1086+ super(text);
1087+ setAlignmentX(JComponent.LEFT_ALIGNMENT);
1088+ }
1089+
1090+ public Dimension getPreferredSize() {
1091+ Dimension d = super.getPreferredSize();
1092+ // Align the width with all other labels in group.
1093+ return new Dimension(getMaxWidth() + 11, d.height);
1094+ }
1095+
1096+ private int getMaxWidth() {
1097+ if (maxWidth == 0 && group != null) {
1098+ int max = 0;
1099+ for (int i = 0; i < group.length; i++) {
1100+ max = Math.max(group[i].getSuperPreferredWidth(), max);
1101+ }
1102+ for (int i = 0; i < group.length; i++) {
1103+ group[i].maxWidth = max;
1104+ }
1105+ }
1106+ return maxWidth;
1107+ }
1108+
1109+ private int getSuperPreferredWidth() {
1110+ return super.getPreferredSize().width;
1111+ }
1112+ }
1113+}