--- /dev/null 2010-05-25 23:44:47.841006844 +0400 +++ new/src/solaris/classes/sun/awt/X11/XDirectoryDialogPeer.java 2010-05-26 11:58:02.000000000 +0400 @@ -0,0 +1,468 @@ +/* + * Copyright 2010 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 sun.util.logging.PlatformLogger; +import sun.awt.AWTAccessor; + +/** + * DirectoryDialogPeer for X-Windows. + * + * @author Costantino Cerbo (c.cerbo@gmail.com) + */ +class XDirectoryDialogPeer extends XDialogPeer implements DirectoryDialogPeer, + ActionListener, ItemListener, KeyEventDispatcher, XChoicePeerListener { + + private static final PlatformLogger log = PlatformLogger + .getLogger("sun.awt.X11.XFileDialogPeer"); + private static final int PATH_CHOICE_WIDTH = 20; + + private DirectoryDialog directoryDialog; + + // ************** Components in the fileDialogWindow *************** + private List directoryList; + private Choice pathChoice; + private TextField pathField; + private String dir; + + XDirectoryDialogPeer(DirectoryDialog directoryDialog) { + super((Dialog) directoryDialog); + this.directoryDialog = directoryDialog; + if (directoryDialog.getDirectory() == null) { + AWTAccessor.getDirectoryDialogAccessor().setDirectory( + directoryDialog, System.getProperty("user.dir")); + } + this.dir = directoryDialog.getDirectory(); + + Locale l = directoryDialog.getLocale(); + UIDefaults uid = XToolkit.getUIDefaults(); + + GridBagLayout gbl = new GridBagLayout(); + GridBagLayout gblButtons = new GridBagLayout(); + GridBagConstraints gbc = new GridBagConstraints(); + directoryDialog.setLayout(gbl); + directoryDialog.setMinimumSize(new Dimension(400, 400)); + + // create components + Panel buttons = new Panel(); + buttons.setLayout(gblButtons); + Button openButton = new Button(uid.getString( + "FileChooser.openButtonText", l)); + openButton.setActionCommand("openButton"); + + Button cancelButton = new Button(uid.getString( + "FileChooser.cancelButtonText", l)); + cancelButton.setActionCommand("cancelButton"); + + directoryList = new List(); + + // the insets used by the components in the dialog + 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 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(uid.getString("FileChooser.pathLabelText", l)); + label.setFont(f); + addComponent(label, gbl, gbc, 0, 0, 1, GridBagConstraints.WEST, + (Container) directoryDialog, 1, 0, GridBagConstraints.NONE, + labelInset); + + pathField = new TextField(dir); + listFolders(dir); + + pathChoice = new Choice() { + + @Override + public Dimension getPreferredSize() { + return new Dimension(PATH_CHOICE_WIDTH, pathField + .getPreferredSize().height); + } + }; + Panel pathPanel = new Panel(); + pathPanel.setLayout(new BorderLayout()); + + pathPanel.add(pathField, BorderLayout.CENTER); + pathPanel.add(pathChoice, BorderLayout.EAST); + addComponent(pathPanel, gbl, gbc, 0, 1, 2, GridBagConstraints.WEST, + (Container) directoryDialog, 1, 0, + GridBagConstraints.HORIZONTAL, textFieldInset); + + label = new Label(uid.getString("FileChooser.foldersLabelText", l)); + + label.setFont(f); + addComponent(label, gbl, gbc, 0, 4, 1, GridBagConstraints.WEST, + (Container) directoryDialog, 1, 0, GridBagConstraints.NONE, + labelInset); + addComponent(directoryList, gbl, gbc, 0, 5, 1, GridBagConstraints.WEST, + (Container) directoryDialog, 1, 1, GridBagConstraints.BOTH, + leftListInset); + + // Separator + addComponent(new Separator(directoryDialog.getSize().width, 2, + Separator.HORIZONTAL), gbl, gbc, 0, 8, 15, + GridBagConstraints.WEST, (Container) directoryDialog, 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(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) directoryDialog, 1, 0, + GridBagConstraints.HORIZONTAL, buttonsInset); + + directoryList.addActionListener(this); + openButton.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 + directoryDialog.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + handleCancel(); + } + }); + } + + @Override + 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 + */ + private 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); + } + + /** + * handle the selection event + */ + private void handleSelection() { + String newDir = pathField.getText() + File.separator; + if (directoryList.getSelectedItem() != null) { + if (!newDir.endsWith(File.separator)) { + newDir += File.separator; + } + newDir += directoryList.getSelectedItem(); + } + + if (newDir.equals(dir)) { + return; + } + + listFolders(newDir); + setDirectory(newDir); + } + + @Override + 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; + } else { + this.dir = dir + "/"; + } + + AWTAccessor.getDirectoryDialogAccessor().setDirectory(directoryDialog, + this.dir); + } + + private void listFolders(String folder) { + File[] files = new File(folder).listFiles(); + java.util.Arrays.sort(files); + directoryList.clear(); + directoryList.addItem(".."); + for (File file : files) { + if (file.isDirectory()) { + directoryList.addItem(file.getName() + "/"); + } + } + } + + /** + * handle the cancel event + */ + private void handleCancel() { + KeyboardFocusManager.getCurrentKeyboardFocusManager() + .removeKeyEventDispatcher(this); + + directoryList.clear(); + + AWTAccessor.getDirectoryDialogAccessor().setDirectory(directoryDialog, + null); + + handleQuitButton(); + } + + /** + * handle the quit event + */ + private void handleQuitButton() { + dir = null; + directoryDialog.setVisible(false); + } + + private 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; + } + + /** + * + * @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 selectedDir = pathChoice.getSelectedItem(); + pathField.setText(selectedDir); + handleSelection(); + } + } + + public void actionPerformed(ActionEvent actionEvent) { + String actionCommand = actionEvent.getActionCommand(); + Object source = actionEvent.getSource(); + + if (actionCommand.equals("openButton")) { + handleQuitButton(); + } else if (actionCommand.equals("cancelButton")) { + handleCancel(); + } else if (source == pathField || source == directoryList) { + handleSelection(); + } + } + + public boolean dispatchKeyEvent(KeyEvent keyEvent) { + int id = keyEvent.getID(); + int keyCode = keyEvent.getKeyCode(); + + if (id == KeyEvent.KEY_PRESSED && keyCode == KeyEvent.VK_ESCAPE) { + synchronized (directoryDialog.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; + } + + @Override + public void dispose() { + if (directoryDialog != null) { + directoryDialog.removeAll(); + } + if (target != null) { + ((Dialog) target).removeAll(); + } + super.dispose(); + } + + // 03/02/2005 b5097243 Pressing 'ESC' on a file dlg does not dispose the dlg + // on Xtoolkit + @Override + public void setVisible(boolean b) { + super.setVisible(b); + if (b == true) { + // See 6240074 for more information + XChoicePeer choicePeer = (XChoicePeer) pathChoice.getPeer(); + choicePeer.setDrawSelectedItem(false); + choicePeer.setAlignUnder(pathField); + 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 selectedDir = pathChoice.getSelectedItem(); + directoryDialog.setDirectory(selectedDir); + } +}