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 */
25package sun.swing.plaf.synth;
26
27import java.awt.*;
28import java.awt.event.*;
29import java.beans.*;
30import java.io.*;
31import java.util.*;
32import java.security.AccessController;
33import java.security.PrivilegedAction;
34
35import javax.swing.*;
36import javax.swing.event.*;
37import javax.swing.filechooser.*;
38import javax.swing.filechooser.FileFilter;
39import javax.swing.plaf.basic.*;
40import javax.swing.plaf.synth.*;
41import javax.swing.plaf.ActionMapUIResource;
42
43import sun.awt.shell.ShellFolder;
44import 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 */
61public 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}