mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-02 20:20:14 +00:00
936 lines
31 KiB
Java
936 lines
31 KiB
Java
/*
|
|
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.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.security.AccessController;
|
|
import java.security.PrivilegedAction;
|
|
import sun.util.logging.PlatformLogger;
|
|
import sun.awt.AWTAccessor;
|
|
|
|
class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListener, ItemListener, KeyEventDispatcher, XChoicePeerListener {
|
|
private static final PlatformLogger log = PlatformLogger.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();
|
|
|
|
boolean isMultipleMode =
|
|
AWTAccessor.getFileDialogAccessor().isMultipleMode(target);
|
|
fileList.setMultipleMode(isMultipleMode);
|
|
|
|
// 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(java.io.File.separatorChar);
|
|
|
|
if (index == -1) {
|
|
savedDir = this.dir;
|
|
savedFile = file;
|
|
} else {
|
|
savedDir = file.substring(0, index+1);
|
|
savedFile = file.substring(index+1);
|
|
}
|
|
|
|
String[] fileNames = fileList.getSelectedItems();
|
|
int filesNumber = (fileNames != null) ? fileNames.length : 0;
|
|
File[] files = new File[filesNumber];
|
|
for (int i = 0; i < filesNumber; i++) {
|
|
files[i] = new File(savedDir, fileNames[i]);
|
|
}
|
|
|
|
AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
|
|
|
|
fileDialogAccessor.setDirectory(target, savedDir);
|
|
fileDialogAccessor.setFile(target, savedFile);
|
|
fileDialogAccessor.setFiles(target, files);
|
|
}
|
|
|
|
/**
|
|
* handle the cancel event
|
|
*/
|
|
void handleCancel() {
|
|
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
|
.removeKeyEventDispatcher(this);
|
|
|
|
setSelectionField(null);
|
|
setFilterField(null);
|
|
directoryList.clear();
|
|
fileList.clear();
|
|
|
|
AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
|
|
|
|
fileDialogAccessor.setDirectory(target, null);
|
|
fileDialogAccessor.setFile(target, null);
|
|
fileDialogAccessor.setFiles(target, 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 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){
|
|
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.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);
|
|
}
|
|
|
|
selectionField.requestFocusInWindow();
|
|
}
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
}
|