1
2
3
4
5
6
7
8
9
10
11
12 package sk.uniba.euromath.editor.widgets;
13 import java.io.File;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Map;
17 import org.apache.commons.lang.StringUtils;
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.events.DisposeEvent;
20 import org.eclipse.swt.events.DisposeListener;
21 import org.eclipse.swt.events.ModifyEvent;
22 import org.eclipse.swt.events.ModifyListener;
23 import org.eclipse.swt.events.SelectionAdapter;
24 import org.eclipse.swt.events.SelectionEvent;
25 import org.eclipse.swt.layout.GridData;
26 import org.eclipse.swt.layout.GridLayout;
27 import org.eclipse.swt.widgets.Button;
28 import org.eclipse.swt.widgets.Composite;
29 import org.eclipse.swt.widgets.DirectoryDialog;
30 import org.eclipse.swt.widgets.FileDialog;
31 import org.eclipse.swt.widgets.Text;
32 import sk.uniba.euromath.editor.lang.Messages;
33 /***
34 * Allows user to select a file.
35 * @author Martin Vysny
36 */
37 public class FileSelector extends AbstractUserInputWidget {
38 /***
39 * Ignored if <code>null</code>. Otherwise, warning is signalised when
40 * file name does not end with this string. The string should start with a
41 * dot.
42 */
43 protected final String preferredExtension;
44 /***
45 * What level of validity to signalise when <code>preferredExtension</code>
46 * condition is broken.
47 */
48 protected final MessageLevelEnum extLevel;
49 /***
50 * maps flags to their message level.
51 */
52 protected Map<FileRequirementsEnum, MessageLevelEnum> flags;
53 /***
54 * A kind of browser that is displayed when the 'browse' button is clicked.
55 */
56 protected final FileBrowserEnum browser;
57 /***
58 * Constructs instance of the widget.
59 * @param parent parent composite.
60 * @param preferredExtension ignored if <code>null</code>. Otherwise,
61 * warning is signalised when file name does not end with this string. The
62 * string should start with a dot.
63 * @param extLevel what kind of validity to signalise when
64 * <code>preferredExtension</code> condition is broken. If
65 * <code>null</code> then no extension check is performed.
66 * @param browser a kind of browser that is displayed when the 'browse'
67 * button is clicked.
68 * @param flags maps flags to their message level.
69 */
70 public FileSelector(final Composite parent,
71 final String preferredExtension, final MessageLevelEnum extLevel,
72 final Map<FileRequirementsEnum, MessageLevelEnum> flags,
73 final FileBrowserEnum browser) {
74 super();
75 if (preferredExtension == null) {
76 this.preferredExtension = null;
77 } else if (preferredExtension.startsWith(".")) {
78 this.preferredExtension = preferredExtension;
79 } else {
80 this.preferredExtension = "." + preferredExtension;
81 }
82 this.extLevel = extLevel;
83 this.flags = flags;
84 this.browser = (browser == null) ? FileBrowserEnum.DIRECTORY : browser;
85 this.composite = new Composite(parent, SWT.NONE);
86 GridLayout layout = new GridLayout(2, false);
87 composite.setLayout(layout);
88 GridData data = new GridData(SWT.FILL, SWT.FILL, false, false);
89 composite.setLayoutData(data);
90
91 fileNameText = new Text(composite, SWT.SINGLE | SWT.BORDER);
92 fileNameText.addModifyListener(new ModifyListener() {
93
94
95
96
97 public void modifyText(ModifyEvent e) {
98 fillData();
99 fireDataModified();
100 }
101 });
102
103 final GridData fileNameData = new GridData(SWT.FILL, SWT.CENTER, false, false);
104 fileNameData.widthHint = 300;
105 fileNameText.setLayoutData(fileNameData);
106
107 browseButton = new Button(composite, SWT.PUSH);
108 if (this.browser == FileBrowserEnum.DIRECTORY) {
109 browseButton.setText(Messages.getString("BROWSE_DIRECTORY"));
110 } else {
111 browseButton.setText(Messages.getString("SELECT_FILE"));
112 }
113 Tools.setButtonGridLayout(browseButton);
114 browseButton.addSelectionListener(new SelectionAdapter() {
115
116
117
118
119 @Override
120 public void widgetSelected(SelectionEvent e) {
121
122 final String result = executeBrowseDialog();
123 if (result == null)
124 return;
125 fileNameText.setText(result);
126 }
127 });
128
129 fileNameText.addDisposeListener(new DisposeListener() {
130
131
132
133
134 public void widgetDisposed(DisposeEvent e) {
135 fillData();
136 }
137 });
138
139 fillData();
140 }
141 /***
142 * Shows the browse dialog, depending on the dialog type.
143 * @return the file/directory that the user selected. If user presses
144 * 'cancel' button then <code>null</code> is returned.
145 */
146 private String executeBrowseDialog() {
147 if (browser == FileBrowserEnum.DIRECTORY) {
148 final DirectoryDialog dd = new DirectoryDialog(composite.getShell());
149 dd.setMessage(Messages.getString("SELECT_DIRECTORY"));
150 dd.setText(Messages.getString("SELECT_DIRECTORY"));
151 return dd.open();
152 }
153 final FileDialog fd = new FileDialog(composite.getShell(),
154 browser == FileBrowserEnum.OPEN_FILE ? SWT.OPEN : SWT.SAVE);
155 fd.setText(Messages.getString("SELECT_FILE"));
156 final List<String> exts = new ArrayList<String>(2);
157 final List<String> extDescs = new ArrayList<String>(2);
158 if (preferredExtension != null) {
159 exts.add("*" + preferredExtension);
160 extDescs.add(Messages.getString("FILE_FILTER_DESC", preferredExtension));
161 }
162 exts.add("*.*");
163 extDescs.add(Messages.getString("ALL_FILES"));
164 fd.setFilterExtensions(exts.toArray(new String[0]));
165 fd.setFilterNames(extDescs.toArray(new String[0]));
166 return fd.open();
167 }
168 /***
169 * Panel where all components are placed.
170 */
171 protected final Composite composite;
172 /***
173 * Textbox where the file name may be entered.
174 */
175 protected final Text fileNameText;
176 /***
177 * Button that allows user to browse for files.
178 */
179 protected final Button browseButton;
180
181
182
183
184 public final Composite getComposite() {
185 return composite;
186 }
187 /***
188 * Returns file name that user entered.
189 * @return the file name.
190 */
191 public String getFileName() {
192 return StringUtils.defaultString(_fileName);
193 }
194 /***
195 * Sets the file name.
196 * @param fileName file name to set.
197 */
198 public void setFileName(String fileName) {
199 fileName = StringUtils.defaultString(fileName);
200 _fileName = fileName;
201 if (!composite.isDisposed()) {
202 fileNameText.setText(_fileName);
203 }
204 }
205 /***
206 * Valid after the component is disposed.
207 */
208 protected String _fileName = null;
209 /***
210 * Checks whether the file exists.
211 * @return <code>true</code> if the file returned by
212 * <code>getFileName()</code> exists.
213 */
214 public boolean existsFile() {
215 File f = new File(getFileName());
216 return f.exists();
217 }
218 /***
219 * Checks whether the directory exists.
220 * @return <code>true</code> if the
221 */
222 public boolean existsDir() {
223 File f = new File(getFileName());
224 File parent = f.getParentFile();
225 if (parent == null)
226 return true;
227 return parent.exists();
228 }
229 /***
230 * Fills the text value and the validity message object.
231 */
232 protected void fillData() {
233 lastMessages = null;
234 _fileName = fileNameText.getText();
235 if (_fileName.length() == 0) {
236 lastMessages = MessageLevelEnum.ERROR.setMessage(lastMessages,
237 Messages.getString("ERROR_EMPTY_FILENAME"));
238 return;
239 }
240
241 if (preferredExtension != null) {
242 if (!_fileName.endsWith(preferredExtension) && (extLevel != null)) {
243 final String errorMsg;
244 switch (extLevel) {
245 case ERROR:
246 errorMsg = Messages.getString(
247 "FILE_WRONG_EXTENSION", preferredExtension);
248 break;
249 case WARNING:
250 errorMsg = Messages
251 .getString(
252 "FILE_WRONG_EXTENSION_WARNING", preferredExtension);
253 break;
254 case INFO:
255 errorMsg = Messages
256 .getString(
257 "FILE_WRONG_EXTENSION_INFO", preferredExtension);
258 break;
259 default:
260 throw new AssertionError();
261 }
262 lastMessages = extLevel.setMessage(lastMessages, errorMsg);
263 }
264 }
265
266 lastMessages = FileRequirementsEnum.check(new File(_fileName),
267 lastMessages, flags);
268 }
269 /***
270 * Validity messages.
271 */
272 protected ValidityMessages lastMessages = null;
273
274
275
276
277 public ValidityMessages getMessages() {
278 return lastMessages;
279 }
280
281
282
283 public String getState() {
284 return getFileName();
285 }
286
287
288
289 public Class< ? > getStateClass() {
290 return String.class;
291 }
292
293
294
295 public void setState(Object state) {
296 setFileName((String)state);
297 }
298
299 }