1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.java.swing.plaf.motif;
  27 
  28 import javax.swing.*;
  29 import javax.swing.filechooser.*;
  30 import javax.swing.event.*;
  31 import javax.swing.plaf.*;
  32 import javax.swing.plaf.basic.*;
  33 import java.awt.*;
  34 import java.awt.event.MouseAdapter;
  35 import java.awt.event.MouseEvent;
  36 import java.beans.*;
  37 import java.io.File;
  38 import java.io.IOException;
  39 import java.util.*;
  40 import sun.awt.shell.ShellFolder;
  41 import sun.swing.SwingUtilities2;
  42 
  43 /**
  44  * Motif FileChooserUI.
  45  *
  46  * @author Jeff Dinkins
  47  */
  48 public class MotifFileChooserUI extends BasicFileChooserUI {
  49 
  50     private FilterComboBoxModel filterComboBoxModel;
  51 
  52     protected JList<File> directoryList = null;
  53     protected JList<File> fileList = null;
  54 
  55     protected JTextField pathField = null;
  56     protected JComboBox<FileFilter> filterComboBox = null;
  57     protected JTextField filenameTextField = null;
  58 
  59     private static final Dimension hstrut10 = new Dimension(10, 1);
  60     private static final Dimension vstrut10 = new Dimension(1, 10);
  61 
  62     private static final Insets insets = new Insets(10, 10, 10, 10);
  63 
  64     private static Dimension prefListSize = new Dimension(75, 150);
  65 
  66     private static Dimension WITH_ACCELERATOR_PREF_SIZE = new Dimension(650, 450);
  67     private static Dimension PREF_SIZE = new Dimension(350, 450);
  68     private static Dimension MIN_SIZE = new Dimension(200, 300);
  69 
  70     private static Dimension PREF_ACC_SIZE = new Dimension(10, 10);
  71     private static Dimension ZERO_ACC_SIZE = new Dimension(1, 1);
  72 
  73     private static Dimension MAX_SIZE = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
  74 
  75     private static final Insets buttonMargin = new Insets(3, 3, 3, 3);
  76 
  77     private JPanel bottomPanel;
  78 
  79     protected JButton approveButton;
  80 
  81     private String enterFolderNameLabelText = null;
  82     private int enterFolderNameLabelMnemonic = 0;
  83     private String enterFileNameLabelText = null;
  84     private int enterFileNameLabelMnemonic = 0;
  85 
  86     private String filesLabelText = null;
  87     private int filesLabelMnemonic = 0;
  88 
  89     private String foldersLabelText = null;
  90     private int foldersLabelMnemonic = 0;
  91 
  92     private String pathLabelText = null;
  93     private int pathLabelMnemonic = 0;
  94 
  95     private String filterLabelText = null;
  96     private int filterLabelMnemonic = 0;
  97 
  98     private JLabel fileNameLabel;
  99 
 100     private void populateFileNameLabel() {
 101         if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) {
 102             fileNameLabel.setText(enterFolderNameLabelText);
 103             fileNameLabel.setDisplayedMnemonic(enterFolderNameLabelMnemonic);
 104         } else {
 105             fileNameLabel.setText(enterFileNameLabelText);
 106             fileNameLabel.setDisplayedMnemonic(enterFileNameLabelMnemonic);
 107         }
 108     }
 109 
 110     private String fileNameString(File file) {
 111         if (file == null) {
 112             return null;
 113         } else {
 114             JFileChooser fc = getFileChooser();
 115             if (fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) {
 116                 return file.getPath();
 117             } else {
 118                 return file.getName();
 119             }
 120         }
 121     }
 122 
 123     private String fileNameString(File[] files) {
 124         StringBuilder sb = new StringBuilder();
 125         for (int i = 0; files != null && i < files.length; i++) {
 126             if (i > 0) {
 127                 sb.append(" ");
 128             }
 129             if (files.length > 1) {
 130                 sb.append("\"");
 131             }
 132             sb.append(fileNameString(files[i]));
 133             if (files.length > 1) {
 134                 sb.append("\"");
 135             }
 136         }
 137         return sb.toString();
 138     }
 139 
 140     public MotifFileChooserUI(JFileChooser filechooser) {
 141         super(filechooser);
 142     }
 143 
 144     public String getFileName() {
 145         if(filenameTextField != null) {
 146             return filenameTextField.getText();
 147         } else {
 148             return null;
 149         }
 150     }
 151 
 152     public void setFileName(String filename) {
 153         if(filenameTextField != null) {
 154             filenameTextField.setText(filename);
 155         }
 156     }
 157 
 158     public String getDirectoryName() {
 159         return pathField.getText();
 160     }
 161 
 162     public void setDirectoryName(String dirname) {
 163         pathField.setText(dirname);
 164     }
 165 
 166     public void ensureFileIsVisible(JFileChooser fc, File f) {
 167         // PENDING(jeff)
 168     }
 169 
 170     public void rescanCurrentDirectory(JFileChooser fc) {
 171         getModel().validateFileCache();
 172     }
 173 
 174     public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) {
 175         return new PropertyChangeListener() {
 176             public void propertyChange(PropertyChangeEvent e) {
 177                 String prop = e.getPropertyName();
 178                 if(prop.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
 179                     File f = (File) e.getNewValue();
 180                     if(f != null) {
 181                         setFileName(getFileChooser().getName(f));
 182                     }
 183                 } else if (prop.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) {
 184                     File[] files = (File[]) e.getNewValue();
 185                     JFileChooser fc = getFileChooser();
 186                     if (files != null && files.length > 0 && (files.length > 1 || fc.isDirectorySelectionEnabled()
 187                             || !files[0].isDirectory())) {
 188                         setFileName(fileNameString(files));
 189                     }
 190                 } else if (prop.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) {
 191                     fileList.clearSelection();
 192                 } else if(prop.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) {
 193                     directoryList.clearSelection();
 194                     ListSelectionModel sm = directoryList.getSelectionModel();
 195                     if (sm instanceof DefaultListSelectionModel) {
 196                         ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0);
 197                         sm.setAnchorSelectionIndex(0);
 198                     }
 199                     fileList.clearSelection();
 200                     sm = fileList.getSelectionModel();
 201                     if (sm instanceof DefaultListSelectionModel) {
 202                         ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0);
 203                         sm.setAnchorSelectionIndex(0);
 204                     }
 205                     File currentDirectory = getFileChooser().getCurrentDirectory();
 206                     if(currentDirectory != null) {
 207                         try {
 208                             setDirectoryName(ShellFolder.getNormalizedFile((File)e.getNewValue()).getPath());
 209                         } catch (IOException ioe) {
 210                             setDirectoryName(((File)e.getNewValue()).getAbsolutePath());
 211                         }
 212                         if ((getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) && !getFileChooser().isMultiSelectionEnabled()) {
 213                             setFileName(getDirectoryName());
 214                         }
 215                     }
 216                 } else if(prop.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) {
 217                     if (fileNameLabel != null) {
 218                         populateFileNameLabel();
 219                     }
 220                     directoryList.clearSelection();
 221                 } else if (prop.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) {
 222                     if(getFileChooser().isMultiSelectionEnabled()) {
 223                         fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
 224                     } else {
 225                         fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 226                         fileList.clearSelection();
 227                         getFileChooser().setSelectedFiles(null);
 228                     }
 229                 } else if (prop.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) {
 230                     if(getAccessoryPanel() != null) {
 231                         if(e.getOldValue() != null) {
 232                             getAccessoryPanel().remove((JComponent) e.getOldValue());
 233                         }
 234                         JComponent accessory = (JComponent) e.getNewValue();
 235                         if(accessory != null) {
 236                             getAccessoryPanel().add(accessory, BorderLayout.CENTER);
 237                             getAccessoryPanel().setPreferredSize(PREF_ACC_SIZE);
 238                             getAccessoryPanel().setMaximumSize(MAX_SIZE);
 239                         } else {
 240                             getAccessoryPanel().setPreferredSize(ZERO_ACC_SIZE);
 241                             getAccessoryPanel().setMaximumSize(ZERO_ACC_SIZE);
 242                         }
 243                     }
 244                 } else if (prop.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) ||
 245                         prop.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY) ||
 246                         prop.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) {
 247                     approveButton.setText(getApproveButtonText(getFileChooser()));
 248                     approveButton.setToolTipText(getApproveButtonToolTipText(getFileChooser()));
 249                 } else if (prop.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) {
 250                     doControlButtonsChanged(e);
 251                 } else if (prop.equals("componentOrientation")) {
 252                     ComponentOrientation o = (ComponentOrientation)e.getNewValue();
 253                     JFileChooser cc = (JFileChooser)e.getSource();
 254                     if (o != (ComponentOrientation)e.getOldValue()) {
 255                         cc.applyComponentOrientation(o);
 256                     }
 257                 }
 258             }
 259         };
 260     }
 261 
 262     //
 263     // ComponentUI Interface Implementation methods
 264     //
 265     public static ComponentUI createUI(JComponent c) {
 266         return new MotifFileChooserUI((JFileChooser)c);
 267     }
 268 
 269     public void installUI(JComponent c) {
 270         super.installUI(c);
 271     }
 272 
 273     public void uninstallUI(JComponent c) {
 274         c.removePropertyChangeListener(filterComboBoxModel);
 275         approveButton.removeActionListener(getApproveSelectionAction());
 276         filenameTextField.removeActionListener(getApproveSelectionAction());
 277         super.uninstallUI(c);
 278     }
 279 
 280     public void installComponents(JFileChooser fc) {
 281         fc.setLayout(new BorderLayout(10, 10));
 282         fc.setAlignmentX(JComponent.CENTER_ALIGNMENT);
 283 
 284         @SuppressWarnings("serial") // anonymous class
 285         JPanel interior = new JPanel() {
 286             public Insets getInsets() {
 287                 return insets;
 288             }
 289         };
 290         interior.setInheritsPopupMenu(true);
 291         align(interior);
 292         interior.setLayout(new BoxLayout(interior, BoxLayout.PAGE_AXIS));
 293 
 294         fc.add(interior, BorderLayout.CENTER);
 295 
 296         // PENDING(jeff) - I18N
 297         JLabel l = new JLabel(pathLabelText);
 298         l.setDisplayedMnemonic(pathLabelMnemonic);
 299         align(l);
 300         interior.add(l);
 301 
 302         File currentDirectory = fc.getCurrentDirectory();
 303         String curDirName = null;
 304         if(currentDirectory != null) {
 305             curDirName = currentDirectory.getPath();
 306         }
 307 
 308         @SuppressWarnings("serial") // anonymous class
 309         JTextField tmp1 = new JTextField(curDirName) {
 310             public Dimension getMaximumSize() {
 311                 Dimension d = super.getMaximumSize();
 312                 d.height = getPreferredSize().height;
 313                 return d;
 314             }
 315         };
 316         pathField = tmp1;
 317         pathField.setInheritsPopupMenu(true);
 318         l.setLabelFor(pathField);
 319         align(pathField);
 320 
 321         // Change to folder on return
 322         pathField.addActionListener(getUpdateAction());
 323         interior.add(pathField);
 324 
 325         interior.add(Box.createRigidArea(vstrut10));
 326 
 327 
 328         // CENTER: left, right accessory
 329         JPanel centerPanel = new JPanel();
 330         centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.LINE_AXIS));
 331         align(centerPanel);
 332 
 333         // left panel - Filter & folderList
 334         JPanel leftPanel = new JPanel();
 335         leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
 336         align(leftPanel);
 337 
 338         // add the filter PENDING(jeff) - I18N
 339         l = new JLabel(filterLabelText);
 340         l.setDisplayedMnemonic(filterLabelMnemonic);
 341         align(l);
 342         leftPanel.add(l);
 343 
 344         @SuppressWarnings("serial") // anonymous class
 345         JComboBox tmp2 = new JComboBox<FileFilter>() {
 346             public Dimension getMaximumSize() {
 347                 Dimension d = super.getMaximumSize();
 348                 d.height = getPreferredSize().height;
 349                 return d;
 350             }
 351         };
 352         filterComboBox = tmp2;
 353         filterComboBox.setInheritsPopupMenu(true);
 354         l.setLabelFor(filterComboBox);
 355         filterComboBoxModel = createFilterComboBoxModel();
 356         filterComboBox.setModel(filterComboBoxModel);
 357         filterComboBox.setRenderer(createFilterComboBoxRenderer());
 358         fc.addPropertyChangeListener(filterComboBoxModel);
 359         align(filterComboBox);
 360         leftPanel.add(filterComboBox);
 361 
 362         // leftPanel.add(Box.createRigidArea(vstrut10));
 363 
 364         // Add the Folder List PENDING(jeff) - I18N
 365         l = new JLabel(foldersLabelText);
 366         l.setDisplayedMnemonic(foldersLabelMnemonic);
 367         align(l);
 368         leftPanel.add(l);
 369         JScrollPane sp = createDirectoryList();
 370         sp.getVerticalScrollBar().setFocusable(false);
 371         sp.getHorizontalScrollBar().setFocusable(false);
 372         sp.setInheritsPopupMenu(true);
 373         l.setLabelFor(sp.getViewport().getView());
 374         leftPanel.add(sp);
 375         leftPanel.setInheritsPopupMenu(true);
 376 
 377 
 378         // create files list
 379         JPanel rightPanel = new JPanel();
 380         align(rightPanel);
 381         rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.PAGE_AXIS));
 382         rightPanel.setInheritsPopupMenu(true);
 383 
 384         l = new JLabel(filesLabelText);
 385         l.setDisplayedMnemonic(filesLabelMnemonic);
 386         align(l);
 387         rightPanel.add(l);
 388         sp = createFilesList();
 389         l.setLabelFor(sp.getViewport().getView());
 390         rightPanel.add(sp);
 391         sp.setInheritsPopupMenu(true);
 392 
 393         centerPanel.add(leftPanel);
 394         centerPanel.add(Box.createRigidArea(hstrut10));
 395         centerPanel.add(rightPanel);
 396         centerPanel.setInheritsPopupMenu(true);
 397 
 398         JComponent accessoryPanel = getAccessoryPanel();
 399         JComponent accessory = fc.getAccessory();
 400         if(accessoryPanel != null) {
 401             if(accessory == null) {
 402                 accessoryPanel.setPreferredSize(ZERO_ACC_SIZE);
 403                 accessoryPanel.setMaximumSize(ZERO_ACC_SIZE);
 404             } else {
 405                 getAccessoryPanel().add(accessory, BorderLayout.CENTER);
 406                 accessoryPanel.setPreferredSize(PREF_ACC_SIZE);
 407                 accessoryPanel.setMaximumSize(MAX_SIZE);
 408             }
 409             align(accessoryPanel);
 410             centerPanel.add(accessoryPanel);
 411             accessoryPanel.setInheritsPopupMenu(true);
 412         }
 413         interior.add(centerPanel);
 414         interior.add(Box.createRigidArea(vstrut10));
 415 
 416         // add the filename field PENDING(jeff) - I18N
 417         fileNameLabel = new JLabel();
 418         populateFileNameLabel();
 419         align(fileNameLabel);
 420         interior.add(fileNameLabel);
 421 
 422         @SuppressWarnings("serial") // anonymous class
 423         JTextField tmp3 = new JTextField() {
 424             public Dimension getMaximumSize() {
 425                 Dimension d = super.getMaximumSize();
 426                 d.height = getPreferredSize().height;
 427                 return d;
 428             }
 429         };
 430         filenameTextField = tmp3;
 431         filenameTextField.setInheritsPopupMenu(true);
 432         fileNameLabel.setLabelFor(filenameTextField);
 433         filenameTextField.addActionListener(getApproveSelectionAction());
 434         align(filenameTextField);
 435         filenameTextField.setAlignmentX(JComponent.LEFT_ALIGNMENT);
 436         interior.add(filenameTextField);
 437 
 438         bottomPanel = getBottomPanel();
 439         bottomPanel.add(new JSeparator(), BorderLayout.NORTH);
 440 
 441         // Add buttons
 442         JPanel buttonPanel = new JPanel();
 443         align(buttonPanel);
 444         buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
 445         buttonPanel.add(Box.createGlue());
 446 
 447         @SuppressWarnings("serial") // anonymous class
 448         JButton tmp4 = new JButton(getApproveButtonText(fc)) {
 449             public Dimension getMaximumSize() {
 450                 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height);
 451             }
 452         };
 453         approveButton = tmp4;
 454         approveButton.setMnemonic(getApproveButtonMnemonic(fc));
 455         approveButton.setToolTipText(getApproveButtonToolTipText(fc));
 456         approveButton.setInheritsPopupMenu(true);
 457         align(approveButton);
 458         approveButton.setMargin(buttonMargin);
 459         approveButton.addActionListener(getApproveSelectionAction());
 460         buttonPanel.add(approveButton);
 461         buttonPanel.add(Box.createGlue());
 462 
 463         @SuppressWarnings("serial") // anonymous class
 464         JButton updateButton = new JButton(updateButtonText) {
 465             public Dimension getMaximumSize() {
 466                 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height);
 467             }
 468         };
 469         updateButton.setMnemonic(updateButtonMnemonic);
 470         updateButton.setToolTipText(updateButtonToolTipText);
 471         updateButton.setInheritsPopupMenu(true);
 472         align(updateButton);
 473         updateButton.setMargin(buttonMargin);
 474         updateButton.addActionListener(getUpdateAction());
 475         buttonPanel.add(updateButton);
 476         buttonPanel.add(Box.createGlue());
 477 
 478         @SuppressWarnings("serial") // anonymous class
 479         JButton cancelButton = new JButton(cancelButtonText) {
 480             public Dimension getMaximumSize() {
 481                 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height);
 482             }
 483         };
 484         cancelButton.setMnemonic(cancelButtonMnemonic);
 485         cancelButton.setToolTipText(cancelButtonToolTipText);
 486         cancelButton.setInheritsPopupMenu(true);
 487         align(cancelButton);
 488         cancelButton.setMargin(buttonMargin);
 489         cancelButton.addActionListener(getCancelSelectionAction());
 490         buttonPanel.add(cancelButton);
 491         buttonPanel.add(Box.createGlue());
 492 
 493         @SuppressWarnings("serial") // anonymous class
 494         JButton helpButton = new JButton(helpButtonText) {
 495             public Dimension getMaximumSize() {
 496                 return new Dimension(MAX_SIZE.width, this.getPreferredSize().height);
 497             }
 498         };
 499         helpButton.setMnemonic(helpButtonMnemonic);
 500         helpButton.setToolTipText(helpButtonToolTipText);
 501         align(helpButton);
 502         helpButton.setMargin(buttonMargin);
 503         helpButton.setEnabled(false);
 504         helpButton.setInheritsPopupMenu(true);
 505         buttonPanel.add(helpButton);
 506         buttonPanel.add(Box.createGlue());
 507         buttonPanel.setInheritsPopupMenu(true);
 508 
 509         bottomPanel.add(buttonPanel, BorderLayout.SOUTH);
 510         bottomPanel.setInheritsPopupMenu(true);
 511         if (fc.getControlButtonsAreShown()) {
 512            fc.add(bottomPanel, BorderLayout.SOUTH);
 513         }
 514     }
 515 
 516     protected JPanel getBottomPanel() {
 517         if (bottomPanel == null) {
 518             bottomPanel = new JPanel(new BorderLayout(0, 4));
 519         }
 520         return bottomPanel;
 521     }
 522 
 523     private void doControlButtonsChanged(PropertyChangeEvent e) {
 524         if (getFileChooser().getControlButtonsAreShown()) {
 525             getFileChooser().add(bottomPanel,BorderLayout.SOUTH);
 526         } else {
 527             getFileChooser().remove(getBottomPanel());
 528         }
 529     }
 530 
 531     public void uninstallComponents(JFileChooser fc) {
 532         fc.removeAll();
 533         bottomPanel = null;
 534         if (filterComboBoxModel != null) {
 535             fc.removePropertyChangeListener(filterComboBoxModel);
 536         }
 537     }
 538 
 539     protected void installStrings(JFileChooser fc) {
 540         super.installStrings(fc);
 541 
 542         Locale l = fc.getLocale();
 543 
 544         enterFolderNameLabelText = UIManager.getString("FileChooser.enterFolderNameLabelText",l);
 545         enterFolderNameLabelMnemonic = getMnemonic("FileChooser.enterFolderNameLabelMnemonic", l);
 546         enterFileNameLabelText = UIManager.getString("FileChooser.enterFileNameLabelText",l);
 547         enterFileNameLabelMnemonic = getMnemonic("FileChooser.enterFileNameLabelMnemonic", l);
 548 
 549         filesLabelText = UIManager.getString("FileChooser.filesLabelText",l);
 550         filesLabelMnemonic = getMnemonic("FileChooser.filesLabelMnemonic", l);
 551 
 552         foldersLabelText = UIManager.getString("FileChooser.foldersLabelText",l);
 553         foldersLabelMnemonic = getMnemonic("FileChooser.foldersLabelMnemonic", l);
 554 
 555         pathLabelText = UIManager.getString("FileChooser.pathLabelText",l);
 556         pathLabelMnemonic = getMnemonic("FileChooser.pathLabelMnemonic", l);
 557 
 558         filterLabelText = UIManager.getString("FileChooser.filterLabelText",l);
 559         filterLabelMnemonic = getMnemonic("FileChooser.filterLabelMnemonic", l);
 560     }
 561 
 562     private Integer getMnemonic(String key, Locale l) {
 563         return SwingUtilities2.getUIDefaultsInt(key, l);
 564     }
 565 
 566     protected void installIcons(JFileChooser fc) {
 567         // Since motif doesn't have button icons, leave this empty
 568         // which overrides the supertype icon loading
 569     }
 570 
 571     protected void uninstallIcons(JFileChooser fc) {
 572         // Since motif doesn't have button icons, leave this empty
 573         // which overrides the supertype icon loading
 574     }
 575 
 576     protected JScrollPane createFilesList() {
 577         fileList = new JList<File>();
 578 
 579         if(getFileChooser().isMultiSelectionEnabled()) {
 580             fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
 581         } else {
 582             fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 583         }
 584 
 585         fileList.setModel(new MotifFileListModel());
 586         fileList.getSelectionModel().removeSelectionInterval(0, 0);
 587         fileList.setCellRenderer(new FileCellRenderer());
 588         fileList.addListSelectionListener(createListSelectionListener(getFileChooser()));
 589         fileList.addMouseListener(createDoubleClickListener(getFileChooser(), fileList));
 590         fileList.addMouseListener(new MouseAdapter() {
 591             public void mouseClicked(MouseEvent e) {
 592                 JFileChooser chooser = getFileChooser();
 593                 if (SwingUtilities.isLeftMouseButton(e) && !chooser.isMultiSelectionEnabled()) {
 594                     int index = SwingUtilities2.loc2IndexFileList(fileList, e.getPoint());
 595                     if (index >= 0) {
 596                         File file = fileList.getModel().getElementAt(index);
 597                         setFileName(chooser.getName(file));
 598                     }
 599                 }
 600             }
 601         });
 602         align(fileList);
 603         JScrollPane scrollpane = new JScrollPane(fileList);
 604         scrollpane.setPreferredSize(prefListSize);
 605         scrollpane.setMaximumSize(MAX_SIZE);
 606         align(scrollpane);
 607         fileList.setInheritsPopupMenu(true);
 608         scrollpane.setInheritsPopupMenu(true);
 609         return scrollpane;
 610     }
 611 
 612     protected JScrollPane createDirectoryList() {
 613         directoryList = new JList<File>();
 614         align(directoryList);
 615 
 616         directoryList.setCellRenderer(new DirectoryCellRenderer());
 617         directoryList.setModel(new MotifDirectoryListModel());
 618         directoryList.getSelectionModel().removeSelectionInterval(0, 0);
 619         directoryList.addMouseListener(createDoubleClickListener(getFileChooser(), directoryList));
 620         directoryList.addListSelectionListener(createListSelectionListener(getFileChooser()));
 621         directoryList.setInheritsPopupMenu(true);
 622 
 623         JScrollPane scrollpane = new JScrollPane(directoryList);
 624         scrollpane.setMaximumSize(MAX_SIZE);
 625         scrollpane.setPreferredSize(prefListSize);
 626         scrollpane.setInheritsPopupMenu(true);
 627         align(scrollpane);
 628         return scrollpane;
 629     }
 630 
 631     public Dimension getPreferredSize(JComponent c) {
 632         Dimension prefSize =
 633             (getFileChooser().getAccessory() != null) ? WITH_ACCELERATOR_PREF_SIZE : PREF_SIZE;
 634         Dimension d = c.getLayout().preferredLayoutSize(c);
 635         if (d != null) {
 636             return new Dimension(d.width < prefSize.width ? prefSize.width : d.width,
 637                                  d.height < prefSize.height ? prefSize.height : d.height);
 638         } else {
 639             return prefSize;
 640         }
 641     }
 642 
 643     public Dimension getMinimumSize(JComponent x)  {
 644         return MIN_SIZE;
 645     }
 646 
 647     public Dimension getMaximumSize(JComponent x) {
 648         return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
 649     }
 650 
 651     protected void align(JComponent c) {
 652         c.setAlignmentX(JComponent.LEFT_ALIGNMENT);
 653         c.setAlignmentY(JComponent.TOP_ALIGNMENT);
 654     }
 655 
 656     @SuppressWarnings("serial") // Superclass is not serializable across versions
 657     protected class FileCellRenderer extends DefaultListCellRenderer  {
 658         public Component getListCellRendererComponent(JList list, Object value, int index,
 659                                                       boolean isSelected, boolean cellHasFocus) {
 660 
 661             super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
 662             setText(getFileChooser().getName((File) value));
 663             setInheritsPopupMenu(true);
 664             return this;
 665         }
 666     }
 667 
 668     @SuppressWarnings("serial") // Superclass is not serializable across versions
 669     protected class DirectoryCellRenderer extends DefaultListCellRenderer  {
 670         public Component getListCellRendererComponent(JList list, Object value, int index,
 671                                                       boolean isSelected, boolean cellHasFocus) {
 672 
 673             super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
 674             setText(getFileChooser().getName((File) value));
 675             setInheritsPopupMenu(true);
 676             return this;
 677         }
 678     }
 679 
 680     @SuppressWarnings("serial") // Superclass is not serializable across versions
 681     protected class MotifDirectoryListModel extends AbstractListModel<File> implements ListDataListener {
 682         public MotifDirectoryListModel() {
 683             getModel().addListDataListener(this);
 684         }
 685 
 686         public int getSize() {
 687             return getModel().getDirectories().size();
 688         }
 689 
 690         public File getElementAt(int index) {
 691             return getModel().getDirectories().elementAt(index);
 692         }
 693 
 694         public void intervalAdded(ListDataEvent e) {
 695             fireIntervalAdded(this, e.getIndex0(), e.getIndex1());
 696         }
 697 
 698         public void intervalRemoved(ListDataEvent e) {
 699             fireIntervalRemoved(this, e.getIndex0(), e.getIndex1());
 700         }
 701 
 702         // PENDING(jeff) - this is inefficient - should sent out
 703         // incremental adjustment values instead of saying that the
 704         // whole list has changed.
 705         public void fireContentsChanged() {
 706             fireContentsChanged(this, 0, getModel().getDirectories().size()-1);
 707         }
 708 
 709         // PENDING(jeff) - fire the correct interval changed - currently sending
 710         // out that everything has changed
 711         public void contentsChanged(ListDataEvent e) {
 712             fireContentsChanged();
 713         }
 714 
 715     }
 716 
 717     @SuppressWarnings("serial") // Superclass is not serializable across versions
 718     protected class MotifFileListModel extends AbstractListModel<File> implements ListDataListener {
 719         public MotifFileListModel() {
 720             getModel().addListDataListener(this);
 721         }
 722 
 723         public int getSize() {
 724             return getModel().getFiles().size();
 725         }
 726 
 727         public boolean contains(Object o) {
 728             return getModel().getFiles().contains(o);
 729         }
 730 
 731         public int indexOf(Object o) {
 732             return getModel().getFiles().indexOf(o);
 733         }
 734 
 735         public File getElementAt(int index) {
 736             return getModel().getFiles().elementAt(index);
 737         }
 738 
 739         public void intervalAdded(ListDataEvent e) {
 740             fireIntervalAdded(this, e.getIndex0(), e.getIndex1());
 741         }
 742 
 743         public void intervalRemoved(ListDataEvent e) {
 744             fireIntervalRemoved(this, e.getIndex0(), e.getIndex1());
 745         }
 746 
 747         // PENDING(jeff) - this is inefficient - should sent out
 748         // incremental adjustment values instead of saying that the
 749         // whole list has changed.
 750         public void fireContentsChanged() {
 751             fireContentsChanged(this, 0, getModel().getFiles().size()-1);
 752         }
 753 
 754         // PENDING(jeff) - fire the interval changed
 755         public void contentsChanged(ListDataEvent e) {
 756             fireContentsChanged();
 757         }
 758 
 759     }
 760 
 761     //
 762     // DataModel for Types Comboxbox
 763     //
 764     protected FilterComboBoxModel createFilterComboBoxModel() {
 765         return new FilterComboBoxModel();
 766     }
 767 
 768     //
 769     // Renderer for Types ComboBox
 770     //
 771     protected FilterComboBoxRenderer createFilterComboBoxRenderer() {
 772         return new FilterComboBoxRenderer();
 773     }
 774 
 775 
 776     /**
 777      * Render different type sizes and styles.
 778      */
 779     @SuppressWarnings("serial") // Superclass is not serializable across versions
 780     public class FilterComboBoxRenderer extends DefaultListCellRenderer {
 781         public Component getListCellRendererComponent(JList list,
 782             Object value, int index, boolean isSelected,
 783             boolean cellHasFocus) {
 784 
 785             super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
 786 
 787             if (value != null && value instanceof FileFilter) {
 788                 setText(((FileFilter)value).getDescription());
 789             }
 790 
 791             return this;
 792         }
 793     }
 794 
 795     /**
 796      * Data model for a type-face selection combo-box.
 797      */
 798     @SuppressWarnings("serial") // Superclass is not serializable across versions
 799     protected class FilterComboBoxModel extends AbstractListModel<FileFilter> implements ComboBoxModel<FileFilter>,
 800             PropertyChangeListener {
 801         protected FileFilter[] filters;
 802         protected FilterComboBoxModel() {
 803             super();
 804             filters = getFileChooser().getChoosableFileFilters();
 805         }
 806 
 807         public void propertyChange(PropertyChangeEvent e) {
 808             String prop = e.getPropertyName();
 809             if(prop.equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)) {
 810                 filters = (FileFilter[]) e.getNewValue();
 811                 fireContentsChanged(this, -1, -1);
 812             } else if (prop.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) {
 813                 fireContentsChanged(this, -1, -1);
 814             }
 815         }
 816 
 817         public void setSelectedItem(Object filter) {
 818             if(filter != null) {
 819                 getFileChooser().setFileFilter((FileFilter) filter);
 820                 fireContentsChanged(this, -1, -1);
 821             }
 822         }
 823 
 824         public Object getSelectedItem() {
 825             // Ensure that the current filter is in the list.
 826             // NOTE: we shouldnt' have to do this, since JFileChooser adds
 827             // the filter to the choosable filters list when the filter
 828             // is set. Lets be paranoid just in case someone overrides
 829             // setFileFilter in JFileChooser.
 830             FileFilter currentFilter = getFileChooser().getFileFilter();
 831             boolean found = false;
 832             if(currentFilter != null) {
 833                 for (FileFilter filter : filters) {
 834                     if (filter == currentFilter) {
 835                         found = true;
 836                     }
 837                 }
 838                 if (!found) {
 839                     getFileChooser().addChoosableFileFilter(currentFilter);
 840                 }
 841             }
 842             return getFileChooser().getFileFilter();
 843         }
 844 
 845         public int getSize() {
 846             if(filters != null) {
 847                 return filters.length;
 848             } else {
 849                 return 0;
 850             }
 851         }
 852 
 853         public FileFilter getElementAt(int index) {
 854             if(index > getSize() - 1) {
 855                 // This shouldn't happen. Try to recover gracefully.
 856                 return getFileChooser().getFileFilter();
 857             }
 858             if(filters != null) {
 859                 return filters[index];
 860             } else {
 861                 return null;
 862             }
 863         }
 864     }
 865 
 866     protected JButton getApproveButton(JFileChooser fc) {
 867         return approveButton;
 868     }
 869 
 870 }