KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > schlichtherle > io > swing > FileComboBoxBrowser


1 /*
2  * FileComboBoxBrowser.java
3  *
4  * Created on 2. August 2006, 23:45
5  */

6 /*
7  * Copyright 2006 Schlichtherle IT Services
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */

21
22 package de.schlichtherle.io.swing;
23
24 import de.schlichtherle.io.ArchiveDetector;
25 import de.schlichtherle.io.File;
26 import de.schlichtherle.key.PromptingKeyManager;
27 import de.schlichtherle.swing.AbstractComboBoxBrowser;
28
29 import java.io.FilenameFilter JavaDoc;
30 import java.text.Collator JavaDoc;
31 import java.util.Arrays JavaDoc;
32
33 import javax.swing.DefaultComboBoxModel JavaDoc;
34 import javax.swing.JComboBox JavaDoc;
35
36 /**
37  * An implementation of {@link AbstractComboBoxBrowser} which completes
38  * relative and absolute path names of files.
39  * This class uses instances of TrueZIP's custom {@link File} class in
40  * order to support the browsing of archive files for auto completion.
41  * <p>
42  * To use it, do something like this:
43  * <pre>
44     JComboBox box = new JComboBox();
45     new FileComboBoxBrowser(box);
46     box.setEditable(true);
47  * </pre>
48  *
49  * @author Christian Schlichtherle
50  * @since TrueZIP 6.2
51  * @version @version@
52  */

53 public class FileComboBoxBrowser extends AbstractComboBoxBrowser {
54
55     private java.io.File JavaDoc directory = new File(".");
56
57     /**
58      * Creates a new combo box auto completion browser.
59      * {@link #setComboBox} must be called in order to use this object.
60      */

61     public FileComboBoxBrowser() {
62     }
63
64     /**
65      * Creates a new combo box auto completion browser.
66      *
67      * @param comboBox The combo box to enable browsing for auto completions.
68      * May be <code>null</code>.
69      */

70     public FileComboBoxBrowser(final JComboBox JavaDoc comboBox) {
71         super(comboBox);
72         if (comboBox != null) {
73             final Object JavaDoc item = comboBox.getSelectedItem();
74             if (item == null || item instanceof String JavaDoc)
75                 update( (DefaultComboBoxModel JavaDoc) comboBox.getModel(),
76                         directory, (String JavaDoc) item);
77         }
78     }
79
80     /**
81      * Returns the directory which is used to complete relative path names.
82      * This defaults to the current directory; <code>null</code> is never
83      * returned.
84      */

85     public java.io.File JavaDoc getDirectory() {
86         return directory;
87     }
88
89     /**
90      * Returns the directory which is used to complete relative path names.
91      *
92      * @param directory The directory to use for completion.
93      * If this is <code>null</code>, the directory is reset to the
94      * current directory.
95      */

96     public void setDirectory(final java.io.File JavaDoc directory) {
97         this.directory = directory != null ? directory : new File(".");
98     }
99
100     /**
101      * Interpretes the specified <code>initials</code> as the initial
102      * characters of an absolute or relative path name of a node in the file
103      * system and updates the contents of the combo box model with possible
104      * completions.
105      * The elements in the combo box model are sorted according to their
106      * natural comparison order.
107      *
108      * @param initials The initial characters of a file or directory path name.
109      * May be <code>null</code>.
110      * @return <code>true</code> if and only if the file system contains a
111      * node with <code>initials</code> as its initial characters and
112      * hence the popup window with the completions should be shown.
113      */

114     protected boolean update(final String JavaDoc initials) {
115         return update( (DefaultComboBoxModel JavaDoc) getComboBox().getModel(),
116                         getDirectory(), initials);
117     }
118
119     private static boolean update(
120             final DefaultComboBoxModel JavaDoc model,
121             java.io.File JavaDoc dir,
122             String JavaDoc initials) {
123         // This is actually a pretty ugly piece of code, but I don't know
124
// of any other way to implement this so that a user can use his
125
// platform specific file separator (e.g. '\\' on Windows)
126
// AND the standard Internet file name separator '/' in a file path
127
// name.
128

129         if (initials == null)
130             initials = "";
131
132         // Identify the directory to list, the prefix of the elements we want
133
// to find and the base string which prepends the elements we will find.
134
final String JavaDoc prefix, base;
135         if ("".equals(initials)) {
136             prefix = base = "";
137         } else {
138             final ArchiveDetector detector;
139             if (dir instanceof File)
140                 detector = ((File) dir).getArchiveDetector();
141             else
142                 detector = ArchiveDetector.NULL;
143             File node = new File(initials, detector);
144             if (node.isAbsolute()) {
145                 final boolean dirPath = node.getPath().length() < initials.length();
146                 if (dirPath)
147                     PromptingKeyManager.resetCancelledPrompts();
148                 // The test order is important here because isDirectory() may
149
// actually prompt the user for a key if node is an RAES
150
// encrypted ZIP file!
151
if (dirPath && node.isDirectory()) {
152                     dir = node;
153                     prefix = "";
154                 } else {
155                     dir = (File) node.getParentFile();
156                     if (dir == null) {
157                         dir = node;
158                         prefix = "";
159                     } else {
160                         prefix = node.getName();
161                     }
162                 }
163                 if (dir.getPath().endsWith(File.separator)) {
164                     // dir is the root of a file system.
165
base = initials.substring(0, dir.getPath().length());
166                 } else {
167                     // Otherwise keep the user provided file separator.
168
base = initials.substring(0, dir.getPath().length() + 1);
169                 }
170             } else {
171                 final java.io.File JavaDoc directory = dir;
172                 node = new File(directory, initials); // inherits archive detector from directory
173
final boolean dirPath = node.getPath().length()
174                         < (directory.getPath() + File.separator + initials).length();
175                 if (dirPath)
176                     PromptingKeyManager.resetCancelledPrompts();
177                 // The test order is important here because isDirectory() may
178
// actually prompt the user!
179
if (dirPath && node.isDirectory()) {
180                     dir = node;
181                     prefix = "";
182                 } else {
183                     dir = (File) node.getParentFile();
184                     prefix = node.getName();
185                 }
186                 // Keep the user provided file separator.
187
base = initials.substring(0, dir.getPath().length() - directory.getPath().length());
188             }
189         }
190
191         final FilenameFilter JavaDoc filter;
192         /*if (File.separatorChar != '\\') {
193             // Consider case (Unix).
194             filter = new FilenameFilter() {
195                 public boolean accept(java.io.File d, String child) {
196                     return child.startsWith(prefix);
197                 }
198             };
199         } else {*/

200             // Ignore case (Windows).
201
filter = new FilenameFilter JavaDoc() {
202                 final int pl = prefix.length();
203
204                 public boolean accept(java.io.File JavaDoc d, String JavaDoc child) {
205                     if (child.length() >= pl)
206                         return prefix.equalsIgnoreCase(child.substring(0, pl));
207                     else
208                         return false;
209                 }
210             };
211         //}
212
final String JavaDoc[] children = dir.list(filter);
213
214         // Update combo box model.
215
// Note that the list MUST be cleared and repopulated because its
216
// current content does not need to reflect the status of the edited
217
// initials.
218
try {
219             model.removeAllElements();
220             final int l = children != null ? children.length : 0;
221             if (l > 0) {
222                 Arrays.sort(children, Collator.getInstance()); // get nice sorting order
223
for (int i = 0; i < l; i++)
224                     model.addElement(base + children[i]);
225                 return true; // show popup
226
} else {
227                 // Leave initials als sole content of the list.
228
model.addElement(initials);
229                 return false; // hide popup
230
}
231         } finally {
232             if (!initials.equals(model.getSelectedItem())) // check required!
233
model.setSelectedItem(initials);
234         }
235     }
236 }
237
Popular Tags