| /* |
| * Copyright 2003-2008 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 = "^" + filter + "$"; |
| regex = regex.replaceAll("\\.", "\\\\."); |
| regex = regex.replaceAll("\\?", "."); |
| regex = regex.replaceAll("\\*", ".*"); |
| return regex; |
| } |
| } |