--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,917 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.awt.X11;
+
+import java.awt.*;
+import javax.swing.*;
+import java.awt.event.*;
+import java.awt.peer.*;
+import java.io.*;
+import java.util.Locale;
+import java.util.Arrays;
+import com.sun.java.swing.plaf.motif.*;
+import javax.swing.plaf.ComponentUI;
+import java.util.logging.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListener, ItemListener, KeyEventDispatcher, XChoicePeerListener {
+ private static final Logger log = Logger.getLogger("sun.awt.X11.XFileDialogPeer");
+
+ FileDialog target;
+
+ // This variable holds value exactly the same as value of the 'target.file' variable except:
+ // 1) is changed to null after quit (see handleQuitButton())
+ // 2) keep the same value if 'target.file' is incorrect (see setFile())
+ // It's not clear HOW we used it
+ // We should think about existence of this variable
+ String file;
+
+ String dir;
+
+ String title;
+ int mode;
+ FilenameFilter filter;
+
+ private static final int PATH_CHOICE_WIDTH = 20;
+
+ // Seems that the purpose of this variable is cashing of 'target.file' variable in order to help method show()
+ // We should think about using 'target.file' instead of 'savedFile'
+ // Perhaps, 'target.file' just more correct (see target.setFile())
+ String savedFile;
+
+ // Holds value of the directory which was chosen before
+ // We use it in order to restore previously selected directory
+ // at the time of the next showing of the file dialog
+ String savedDir;
+ // Holds value of the system property 'user.dir'
+ // in order to init current directory
+ String userDir;
+
+ Dialog fileDialog;
+
+ GridBagLayout gbl;
+ GridBagLayout gblButtons;
+ GridBagConstraints gbc;
+
+ // ************** Components in the fileDialogWindow ***************
+
+ TextField filterField;
+
+ // This variable holds the current text of the file which user select through the navigation
+ // It's important that updating of this variable must be correct
+ // since this value is used at the time of the file dialog closing
+ // Namely, we invoke target.setFile() and then user can get this value
+ // We update this field in cases:
+ // - ITEM_STATE_CHANGED was triggered on the file list component: set to the current selected item
+ // - at the time of the 'show': set to savedFile
+ // - at the time of the programmatically setting: set to new value
+ TextField selectionField;
+
+ List directoryList;
+
+ // This is the list component which is used for the showing of the file list of the current directory
+ List fileList;
+
+ Panel buttons;
+ Button openButton;
+ Button filterButton;
+ Button cancelButton;
+ Choice pathChoice;
+ TextField pathField;
+ Panel pathPanel;
+
+ String cancelButtonText = null;
+ String enterFileNameLabelText = null;
+ String filesLabelText= null;
+ String foldersLabelText= null;
+ String pathLabelText= null;
+ String filterLabelText= null;
+ String openButtonText= null;
+ String saveButtonText= null;
+ String actionButtonText= null;
+
+
+ void installStrings() {
+ Locale l = target.getLocale();
+ UIDefaults uid = XToolkit.getUIDefaults();
+ cancelButtonText = uid.getString("FileChooser.cancelButtonText",l);
+ enterFileNameLabelText = uid.getString("FileChooser.enterFileNameLabelText",l);
+ filesLabelText = uid.getString("FileChooser.filesLabelText",l);
+ foldersLabelText = uid.getString("FileChooser.foldersLabelText",l);
+ pathLabelText = uid.getString("FileChooser.pathLabelText",l);
+ filterLabelText = uid.getString("FileChooser.filterLabelText",l);
+ openButtonText = uid.getString("FileChooser.openButtonText",l);
+ saveButtonText = uid.getString("FileChooser.saveButtonText",l);
+
+ }
+
+ XFileDialogPeer(FileDialog target) {
+ super((Dialog)target);
+ this.target = target;
+ }
+
+ private void init(FileDialog target) {
+ fileDialog = target; //new Dialog(target, target.getTitle(), false);
+ this.title = target.getTitle();
+ this.mode = target.getMode();
+ this.target = target;
+ this.filter = target.getFilenameFilter();
+
+ savedFile = target.getFile();
+ savedDir = target.getDirectory();
+ // Shouldn't save 'user.dir' to 'savedDir'
+ // since getDirectory() will be incorrect after handleCancel
+ userDir = (String)AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ return System.getProperty("user.dir");
+ }
+ });
+
+ installStrings();
+ gbl = new GridBagLayout();
+ gblButtons = new GridBagLayout();
+ gbc = new GridBagConstraints();
+ fileDialog.setLayout(gbl);
+
+ // create components
+ buttons = new Panel();
+ buttons.setLayout(gblButtons);
+ actionButtonText = (target.getMode() == FileDialog.SAVE) ? saveButtonText : openButtonText;
+ openButton = new Button(actionButtonText);
+
+ filterButton = new Button(filterLabelText);
+ cancelButton = new Button(cancelButtonText);
+ directoryList = new List();
+ fileList = new List();
+ filterField = new TextField();
+ selectionField = new TextField();
+
+ // the insets used by the components in the fileDialog
+ Insets noInset = new Insets(0, 0, 0, 0);
+ Insets textFieldInset = new Insets(0, 8, 0, 8);
+ Insets leftListInset = new Insets(0, 8, 0, 4);
+ Insets rightListInset = new Insets(0, 4, 0, 8);
+ Insets separatorInset = new Insets(8, 0, 0, 0);
+ Insets labelInset = new Insets(0, 8, 0, 0);
+ Insets buttonsInset = new Insets(10, 8, 10, 8);
+
+ // add components to GridBagLayout "gbl"
+
+ Font f = new Font(Font.DIALOG, Font.PLAIN, 12);
+
+ Label label = new Label(pathLabelText);
+ label.setFont(f);
+ addComponent(label, gbl, gbc, 0, 0, 1,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.NONE, labelInset);
+
+ // Fixed 6260650: FileDialog.getDirectory() does not return null when file dialog is cancelled
+ // After showing we should display 'user.dir' as current directory
+ // if user didn't set directory programatically
+ pathField = new TextField(savedDir != null ? savedDir : userDir);
+
+ pathChoice = new Choice() {
+ public Dimension getPreferredSize() {
+ return new Dimension(PATH_CHOICE_WIDTH, pathField.getPreferredSize().height);
+ }
+ };
+ pathPanel = new Panel();
+ pathPanel.setLayout(new BorderLayout());
+
+ pathPanel.add(pathField,BorderLayout.CENTER);
+ pathPanel.add(pathChoice,BorderLayout.EAST);
+ //addComponent(pathField, gbl, gbc, 0, 1, 2,
+ // GridBagConstraints.WEST, (Container)fileDialog,
+ // 1, 0, GridBagConstraints.HORIZONTAL, textFieldInset);
+ //addComponent(pathChoice, gbl, gbc, 1, 1, GridBagConstraints.RELATIVE,
+ // GridBagConstraints.WEST, (Container)fileDialog,
+ // 1, 0, GridBagConstraints.HORIZONTAL, textFieldInset);
+ addComponent(pathPanel, gbl, gbc, 0, 1, 2,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.HORIZONTAL, textFieldInset);
+
+
+
+ label = new Label(filterLabelText);
+
+ label.setFont(f);
+ addComponent(label, gbl, gbc, 0, 2, 1,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.NONE, labelInset);
+ addComponent(filterField, gbl, gbc, 0, 3, 2,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.HORIZONTAL, textFieldInset);
+
+ label = new Label(foldersLabelText);
+
+ label.setFont(f);
+ addComponent(label, gbl, gbc, 0, 4, 1,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.NONE, labelInset);
+
+ label = new Label(filesLabelText);
+
+ label.setFont(f);
+ addComponent(label, gbl, gbc, 1, 4, 1,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.NONE, labelInset);
+ addComponent(directoryList, gbl, gbc, 0, 5, 1,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 1, GridBagConstraints.BOTH, leftListInset);
+ addComponent(fileList, gbl, gbc, 1, 5, 1,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 1, GridBagConstraints.BOTH, rightListInset);
+
+ label = new Label(enterFileNameLabelText);
+
+ label.setFont(f);
+ addComponent(label, gbl, gbc, 0, 6, 1,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.NONE, labelInset);
+ addComponent(selectionField, gbl, gbc, 0, 7, 2,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.HORIZONTAL, textFieldInset);
+ addComponent(new Separator(fileDialog.size().width, 2, Separator.HORIZONTAL), gbl, gbc, 0, 8, 15,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.HORIZONTAL, separatorInset);
+
+ // add buttons to GridBagLayout Buttons
+ addComponent(openButton, gblButtons, gbc, 0, 0, 1,
+ GridBagConstraints.WEST, (Container)buttons,
+ 1, 0, GridBagConstraints.NONE, noInset);
+ addComponent(filterButton, gblButtons, gbc, 1, 0, 1,
+ GridBagConstraints.CENTER, (Container)buttons,
+ 1, 0, GridBagConstraints.NONE, noInset);
+ addComponent(cancelButton, gblButtons, gbc, 2, 0, 1,
+ GridBagConstraints.EAST, (Container)buttons,
+ 1, 0, GridBagConstraints.NONE, noInset);
+
+ // add ButtonPanel to the GridBagLayout of this class
+ addComponent(buttons, gbl, gbc, 0, 9, 2,
+ GridBagConstraints.WEST, (Container)fileDialog,
+ 1, 0, GridBagConstraints.HORIZONTAL, buttonsInset);
+
+ fileDialog.setSize(400, 400);
+
+ // Update choice's popup width
+ XChoicePeer choicePeer = (XChoicePeer)pathChoice.getPeer();
+ choicePeer.setDrawSelectedItem(false);
+ choicePeer.setAlignUnder(pathField);
+
+ filterField.addActionListener(this);
+ selectionField.addActionListener(this);
+ directoryList.addActionListener(this);
+ directoryList.addItemListener(this);
+ fileList.addItemListener(this);
+ fileList.addActionListener(this);
+ openButton.addActionListener(this);
+ filterButton.addActionListener(this);
+ cancelButton.addActionListener(this);
+ pathChoice.addItemListener(this);
+ pathField.addActionListener(this);
+
+ // b6227750 FileDialog is not disposed when clicking the 'close' (X) button on the top right corner, XToolkit
+ target.addWindowListener(
+ new WindowAdapter(){
+ public void windowClosing(WindowEvent e){
+ handleCancel();
+ }
+ }
+ );
+
+ // 6259434 PIT: Choice in FileDialog is not responding to keyboard interactions, XToolkit
+ pathChoice.addItemListener(this);
+
+ }
+
+ public void updateMinimumSize() {
+ }
+
+ public void updateIconImages() {
+ if (winAttr.icons == null){
+ winAttr.iconsInherited = false;
+ winAttr.icons = getDefaultIconInfo();
+ setIconHints(winAttr.icons);
+ }
+ }
+
+ /**
+ * add Component comp to the container cont.
+ * add the component to the correct GridBagLayout
+ */
+ void addComponent(Component comp, GridBagLayout gb, GridBagConstraints c, int gridx,
+ int gridy, int gridwidth, int anchor, Container cont, int weightx, int weighty,
+ int fill, Insets in) {
+ c.gridx = gridx;
+ c.gridy = gridy;
+ c.gridwidth = gridwidth;
+ c.anchor = anchor;
+ c.weightx = weightx;
+ c.weighty = weighty;
+ c.fill = fill;
+ c.insets = in;
+ gb.setConstraints(comp, c);
+ cont.add(comp);
+ }
+
+ /**
+ * get fileName
+ */
+ String getFileName(String str) {
+ if (str == null) {
+ return "";
+ }
+
+ int index = str.lastIndexOf('/');
+
+ if (index == -1) {
+ return str;
+ } else {
+ return str.substring(index + 1);
+ }
+ }
+
+ /** handleFilter
+ *
+ */
+ void handleFilter(String f) {
+
+ if (f == null) {
+ return;
+ }
+ setFilterEntry(dir,f);
+
+ // Fixed within 6259434: PIT: Choice in FileDialog is not responding to keyboard interactions, XToolkit
+ // Here we restoring Motif behaviour
+ directoryList.select(0);
+ if (fileList.getItemCount() != 0) {
+ fileList.requestFocus();
+ } else {
+ directoryList.requestFocus();
+ }
+ }
+
+ /**
+ * handle the selection event
+ */
+ void handleSelection(String file) {
+ int index = file.lastIndexOf('/');
+
+ if (index == -1) {
+ savedDir = this.dir;
+ savedFile = file;
+ } else {
+ savedDir = file.substring(0, index+1);
+ savedFile = file.substring(index+1);
+ }
+ target.setDirectory(savedDir);
+ target.setFile(savedFile);
+ }
+
+ /**
+ * handle the cancel event
+ */
+ void handleCancel() {
+ KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .removeKeyEventDispatcher(this);
+
+ setSelectionField(null);
+ setFilterField(null);
+ directoryList.clear();
+ fileList.clear();
+ target.setFile(null);
+ target.setDirectory(null);
+ handleQuitButton();
+ }
+
+ /**
+ * handle the quit event
+ */
+ void handleQuitButton() {
+ dir = null;
+ file = null;
+ target.hide();
+ }
+
+ /**
+ * set the entry of the new dir with f
+ */
+ void setFilterEntry(String d, String f) {
+ File fe = new File(d);
+
+ if (fe.isDirectory() && fe.canRead()) {
+ // Fixed 6260659: File Name set programmatically in FileDialog is overridden during navigation, XToolkit
+ // Here we restoring Motif behaviour
+ setSelectionField(target.getFile());
+
+ if (f.equals("")) {
+ f = "*";
+ setFilterField(f);
+ } else {
+ setFilterField(f);
+ }
+ String l[];
+
+ if (f.equals("*")) {
+ l = fe.list();
+ } else {
+ // REMIND: fileDialogFilter is not implemented yet
+ FileDialogFilter ff = new FileDialogFilter(f);
+ l = fe.list(ff);
+ }
+ // Fixed 6358953: handling was added in case of I/O error happens
+ if (l == null) {
+ this.dir = getParentDirectory();
+ return;
+ }
+ directoryList.clear();
+ fileList.clear();
+ directoryList.setVisible(false);
+ fileList.setVisible(false);
+
+ directoryList.addItem("..");
+ Arrays.sort(l);
+ for (int i = 0 ; i < l.length ; i++) {
+ File file = new File(d + l[i]);
+ if (file.isDirectory()) {
+ directoryList.addItem(l[i] + "/");
+ } else {
+ if (filter != null) {
+ if (filter.accept(new File(l[i]),l[i])) fileList.addItem(l[i]);
+ }
+ else fileList.addItem(l[i]);
+ }
+ }
+ this.dir = d;
+
+ pathField.setText(dir);
+
+ // Some code was removed
+ // Now we do updating of the pathChoice at the time of the choice opening
+
+ target.setDirectory(this.dir);
+ directoryList.setVisible(true);
+ fileList.setVisible(true);
+ }
+ }
+
+
+ String[] getDirList(String dir) {
+ if (!dir.endsWith("/"))
+ dir = dir + "/";
+ char[] charr = dir.toCharArray();
+ int numSlashes = 0;
+ for (int i=0;i<charr.length;i++) {
+ if (charr[i] == '/')
+ numSlashes++;
+ }
+ String[] starr = new String[numSlashes];
+ int j=0;
+ for (int i=charr.length-1;i>=0;i--) {
+ if (charr[i] == '/')
+ {
+ starr[j++] = new String(charr,0,i+1);
+ }
+ }
+ return starr;
+ }
+
+ /**
+ * set the text in the selectionField
+ */
+ void setSelectionField(String str) {
+ selectionField.setText(str);
+ }
+
+ /**
+ * set the text in the filterField
+ */
+ void setFilterField(String str) {
+ filterField.setText(str);
+ }
+
+ /**
+ *
+ * @see java.awt.event.ItemEvent
+ * ItemEvent.ITEM_STATE_CHANGED
+ */
+ public void itemStateChanged(ItemEvent itemEvent){
+ if (itemEvent.getID() != ItemEvent.ITEM_STATE_CHANGED ||
+ itemEvent.getStateChange() == ItemEvent.DESELECTED) {
+ return;
+ }
+
+ Object source = itemEvent.getSource();
+
+ if (source == pathChoice) {
+ /*
+ * Update the selection ('folder name' text field) after
+ * the current item changing in the unfurled choice by the arrow keys.
+ * See 6259434, 6240074 for more information
+ */
+ String dir = pathChoice.getSelectedItem();
+ pathField.setText(dir);
+ } else if (directoryList == source) {
+ setFilterField(getFileName(filterField.getText()));
+ } else if (fileList == source) {
+ String file = fileList.getItem((Integer)itemEvent.getItem());
+ setSelectionField(file);
+ }
+ }
+
+ /*
+ * Updates the current directory only if directoryList-specific
+ * action occurred. Returns false if the forward directory is inaccessible
+ */
+ boolean updateDirectoryByUserAction(String str) {
+
+ String dir;
+ if (str.equals("..")) {
+ dir = getParentDirectory();
+ }
+ else {
+ dir = this.dir + str;
+ }
+
+ File fe = new File(dir);
+ if (fe.canRead()) {
+ this.dir = dir;
+ return true;
+ }else {
+ return false;
+ }
+ }
+
+ String getParentDirectory(){
+ String parent = this.dir;
+ if (!this.dir.equals("/")) // If the current directory is "/" leave it alone.
+ {
+ if (dir.endsWith("/"))
+ parent = parent.substring(0,parent.lastIndexOf("/"));
+
+ parent = parent.substring(0,parent.lastIndexOf("/")+1);
+ }
+ return parent;
+ }
+
+ public void actionPerformed( ActionEvent actionEvent ) {
+ String actionCommand = actionEvent.getActionCommand();
+ Object source = actionEvent.getSource();
+
+ if (actionCommand.equals(actionButtonText)) {
+ handleSelection( selectionField.getText() );
+ handleQuitButton();
+ } else if (actionCommand.equals(filterLabelText)) {
+ handleFilter( filterField.getText() );
+ } else if (actionCommand.equals(cancelButtonText)) {
+ handleCancel();
+ } else if ( source instanceof TextField ) {
+ if ( selectionField == ((TextField)source) ) {
+ // Fixed within 6259434: PIT: Choice in FileDialog is not responding to keyboard interactions, XToolkit
+ // We should handle the action based on the selection field
+ // Looks like mistake
+ handleSelection(selectionField.getText());
+ handleQuitButton();
+ } else if (filterField == ((TextField)source)) {
+ handleFilter(filterField.getText());
+ } else if (pathField == ((TextField)source)) {
+ target.setDirectory(pathField.getText());
+ }
+ } else if (source instanceof List) {
+ if (directoryList == ((List)source)) {
+ //handleFilter( actionCommand + getFileName( filterField.getText() ) );
+ if (updateDirectoryByUserAction(actionCommand)){
+ handleFilter( getFileName( filterField.getText() ) );
+ }
+ } else if (fileList == ((List)source)) {
+ handleSelection( actionCommand );
+ handleQuitButton();
+ }
+ }
+ }
+
+ public boolean dispatchKeyEvent(KeyEvent keyEvent) {
+ int id = keyEvent.getID();
+ int keyCode = keyEvent.getKeyCode();
+
+ if (id == KeyEvent.KEY_PRESSED && keyCode == KeyEvent.VK_ESCAPE) {
+ synchronized (target.getTreeLock()) {
+ Component comp = (Component) keyEvent.getSource();
+ while (comp != null) {
+ // Fix for 6240084 Disposing a file dialog when the drop-down is active does not dispose the dropdown menu, on Xtoolkit
+ // See also 6259493
+ if (comp == pathChoice) {
+ XChoicePeer choicePeer = (XChoicePeer)pathChoice.getPeer();
+ if (choicePeer.isUnfurled()){
+ return false;
+ }
+ }
+ if (comp.getPeer() == this) {
+ handleCancel();
+ return true;
+ }
+ comp = comp.getParent();
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * set the file
+ */
+ public void setFile(String file) {
+
+ if (file == null) {
+ this.file = null;
+ return;
+ }
+
+ if (this.dir == null) {
+ String d = "./";
+ File f = new File(d, file);
+
+ if (f.isFile()) {
+ this.file = file;
+ setDirectory(d);
+ }
+ } else {
+ File f = new File(this.dir, file);
+ if (f.isFile()) {
+ this.file = file;
+ }
+ }
+
+ setSelectionField(file);
+ }
+
+ /**
+ * set the directory
+ * FIXME: we should update 'savedDir' after programmatically 'setDirectory'
+ * Otherwise, SavedDir will be not null before second showing
+ * So the current directory of the file dialog will be incorrect after second showing
+ * since 'setDirectory' will be ignored
+ * We cann't update savedDir here now since it used very often
+ */
+ public void setDirectory(String dir) {
+
+ if (dir == null) {
+ this.dir = null;
+ return;
+ }
+
+ if (dir.equals(this.dir)) {
+ return;
+ }
+
+ int i;
+ if ((i=dir.indexOf("~")) != -1) {
+
+ dir = dir.substring(0,i) + System.getProperty("user.home") + dir.substring(i+1,dir.length());
+ }
+
+ File fe = new File(dir).getAbsoluteFile();
+ log.fine("Current directory : " + fe);
+
+ if (!fe.isDirectory()) {
+ dir = "./";
+ fe = new File(dir).getAbsoluteFile();
+
+ if (!fe.isDirectory()) {
+ return;
+ }
+ }
+ try {
+ dir = this.dir = fe.getCanonicalPath();
+ } catch (java.io.IOException ie) {
+ dir = this.dir = fe.getAbsolutePath();
+ }
+ pathField.setText(this.dir);
+
+
+ if (dir.endsWith("/")) {
+ this.dir = dir;
+ handleFilter("");
+ } else {
+ this.dir = dir + "/";
+ handleFilter("");
+ }
+
+ // Some code was removed
+ // Now we do updating of the pathChoice at the time of the choice opening
+ // Fixed problem:
+ // The exception java.awt.IllegalComponentStateException will be thrown
+ // if the user invoke setDirectory after the closing of the file dialog
+ }
+
+ /**
+ * set filenameFilter
+ *
+ */
+ public void setFilenameFilter(FilenameFilter filter) {
+ this.filter = filter;
+ }
+
+ public void show() {
+ if (fileDialog == null) {
+ init((FileDialog)target);
+ }
+
+ if (savedDir != null || userDir != null) {
+ setDirectory(savedDir != null ? savedDir : userDir);
+ }
+
+ if (savedFile != null) {
+ // Actually in Motif implementation lost file value which was saved after prevously showing
+ // Seems we shouldn't restore Motif behaviour in this case
+ setFile(savedFile);
+ }
+
+ super.show();
+ selectionField.requestFocusInWindow();
+ }
+
+ public void dispose() {
+ FileDialog fd = (FileDialog)fileDialog;
+ if (fd != null) {
+ fd.removeAll();
+ }
+ super.dispose();
+ }
+
+ // 03/02/2005 b5097243 Pressing 'ESC' on a file dlg does not dispose the dlg on Xtoolkit
+ public void setVisible(boolean b){
+ super.setVisible(b);
+ if (b == true){
+ // See 6240074 for more information
+ XChoicePeer choicePeer = (XChoicePeer)pathChoice.getPeer();
+ choicePeer.addXChoicePeerListener(this);
+
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
+ }else{
+ // See 6240074 for more information
+ XChoicePeer choicePeer = (XChoicePeer)pathChoice.getPeer();
+ choicePeer.removeXChoicePeerListener();
+
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this);
+ }
+ }
+
+ /*
+ * Adding items to the path choice based on the text string
+ * See 6240074 for more information
+ */
+ public void addItemsToPathChoice(String text){
+ String dirList[] = getDirList(text);
+ for (int i = 0; i < dirList.length; i++) pathChoice.addItem(dirList[i]);
+ }
+
+ /*
+ * Refresh the unfurled choice at the time of the opening choice according to the text of the path field
+ * See 6240074 for more information
+ */
+ public void unfurledChoiceOpening(ListHelper choiceHelper){
+
+ // When the unfurled choice is opening the first time, we need only to add elements, otherwise we've got exception
+ if (choiceHelper.getItemCount() == 0){
+ addItemsToPathChoice(pathField.getText());
+ return;
+ }
+
+ // If the set of the directories the exactly same as the used to be then dummy
+ if (pathChoice.getItem(0).equals(pathField.getText()))
+ return;
+
+ pathChoice.removeAll();
+ addItemsToPathChoice(pathField.getText());
+ }
+
+ /*
+ * Refresh the file dialog at the time of the closing choice according to the selected item of the choice
+ * See 6240074 for more information
+ */
+ public void unfurledChoiceClosing(){
+ // This is the exactly same code as invoking later at the time of the itemStateChanged
+ // Here is we restore Windows behaviour: change current directory if user press 'ESC'
+ String dir = pathChoice.getSelectedItem();
+ target.setDirectory(dir);
+ }
+}
+
+class Separator extends Canvas {
+ public final static int HORIZONTAL = 0;
+ public final static int VERTICAL = 1;
+ int orientation;
+
+ public Separator(int length, int thickness, int orient) {
+ super();
+ orientation = orient;
+ if (orient == HORIZONTAL) {
+ resize(length, thickness);
+ } else {
+ // VERTICAL
+ resize(thickness, length);
+ }
+ }
+
+ public void paint(Graphics g) {
+ int x1, y1, x2, y2;
+ Rectangle bbox = bounds();
+ Color c = getBackground();
+ Color brighter = c.brighter();
+ Color darker = c.darker();
+
+ if (orientation == HORIZONTAL) {
+ x1 = 0;
+ x2 = bbox.width - 1;
+ y1 = y2 = bbox.height/2 - 1;
+
+ } else {
+ // VERTICAL
+ x1 = x2 = bbox.width/2 - 1;
+ y1 = 0;
+ y2 = bbox.height - 1;
+ }
+ g.setColor(darker);
+ g.drawLine(x1, y2, x2, y2);
+ g.setColor(brighter);
+ if (orientation == HORIZONTAL)
+ g.drawLine(x1, y2+1, x2, y2+1);
+ else
+ g.drawLine(x1+1, y2, x2+1, y2);
+ }
+}
+
+/*
+ * Motif file dialogs let the user specify a filter that controls the files that
+ * are displayed in the dialog. This filter is generally specified as a regular
+ * expression. The class is used to implement Motif-like filtering.
+ */
+class FileDialogFilter implements FilenameFilter {
+
+ String filter;
+
+ public FileDialogFilter(String f) {
+ filter = f;
+ }
+
+ /*
+ * Tells whether or not the specified file should be included in a file list
+ */
+ public boolean accept(File dir, String fileName) {
+
+ File f = new File(dir, fileName);
+
+ if (f.isDirectory()) {
+ return true;
+ } else {
+ return matches(fileName, filter);
+ }
+ }
+
+ /*
+ * Tells whether or not the input string matches the given filter
+ */
+ private boolean matches(String input, String filter) {
+ String regex = convert(filter);
+ return input.matches(regex);
+ }
+
+ /*
+ * Converts the filter into the form which is acceptable by Java's regexps
+ */
+ private String convert(String filter) {
+ String regex = new String("^" + filter + "$");
+ regex = regex.replaceAll("\\.", "\\\\.");
+ regex = regex.replaceAll("\\?", ".");
+ regex = regex.replaceAll("\\*", ".*");
+ return regex;
+ }
+}