View Javadoc

1   /*
2    * Created on Mar 8, 2005. Copyright 1999-2006 Faculty of Mathematics, Physics
3    * and Informatics, Comenius University, Bratislava. This file is protected by
4    * the Mozilla Public License version 1.1 (the "License"); you may not use this
5    * file except in compliance with the License. You may obtain a copy of the
6    * License at http://euromath2.sourceforge.net/license.html Unless required by
7    * applicable law or agreed to in writing, software distributed under the
8    * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
9    * OF ANY KIND, either express or implied. See the License for the specific
10   * language governing permissions and limitations under the License.
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(".")) { //$NON-NLS-1$
78  			this.preferredExtension = preferredExtension;
79  		} else {
80  			this.preferredExtension = "." + preferredExtension; //$NON-NLS-1$
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  		// create the file name text control.
91  		fileNameText = new Text(composite, SWT.SINGLE | SWT.BORDER);
92  		fileNameText.addModifyListener(new ModifyListener() {
93  			/*
94  			 * (non-Javadoc)
95  			 * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
96  			 */
97  			public void modifyText(ModifyEvent e) {
98  				fillData();
99  				fireDataModified();
100 			}
101 		});
102 		// set ideal size to 300 pixels
103 		final GridData fileNameData = new GridData(SWT.FILL, SWT.CENTER, false, false);
104 		fileNameData.widthHint = 300;
105 		fileNameText.setLayoutData(fileNameData);
106 		// create the browse button control.
107 		browseButton = new Button(composite, SWT.PUSH);
108 		if (this.browser == FileBrowserEnum.DIRECTORY) {
109 			browseButton.setText(Messages.getString("BROWSE_DIRECTORY")); //$NON-NLS-1$
110 		} else {
111 			browseButton.setText(Messages.getString("SELECT_FILE")); //$NON-NLS-1$
112 		}
113 		Tools.setButtonGridLayout(browseButton);
114 		browseButton.addSelectionListener(new SelectionAdapter() {
115 			/*
116 			 * (non-Javadoc)
117 			 * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
118 			 */
119 			@Override
120 			public void widgetSelected(SelectionEvent e) {
121 				// browse for XML files
122 				final String result = executeBrowseDialog();
123 				if (result == null)
124 					return;
125 				fileNameText.setText(result);
126 			}
127 		});
128 		// store file name to a string object when disposed.
129 		fileNameText.addDisposeListener(new DisposeListener() {
130 			/*
131 			 * (non-Javadoc)
132 			 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
133 			 */
134 			public void widgetDisposed(DisposeEvent e) {
135 				fillData();
136 			}
137 		});
138 		// refresh messages
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")); //$NON-NLS-1$
150 			dd.setText(Messages.getString("SELECT_DIRECTORY")); //$NON-NLS-1$
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")); //$NON-NLS-1$
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);//$NON-NLS-1$
160 			extDescs.add(Messages.getString("FILE_FILTER_DESC", preferredExtension)); //$NON-NLS-1$
161 		}
162 		exts.add("*.*"); //$NON-NLS-1$
163 		extDescs.add(Messages.getString("ALL_FILES"));//$NON-NLS-1$
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 	 * (non-Javadoc)
182 	 * @see sk.uniba.euromath.editor.widgets.IUserInputWidget#getComposite()
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")); //$NON-NLS-1$
238 			return;
239 		}
240 		// check extension
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); //$NON-NLS-1$
248 						break;
249 					case WARNING:
250 						errorMsg = Messages
251 								.getString(
252 										"FILE_WRONG_EXTENSION_WARNING", preferredExtension); //$NON-NLS-1$
253 						break;
254 					case INFO:
255 						errorMsg = Messages
256 								.getString(
257 										"FILE_WRONG_EXTENSION_INFO", preferredExtension); //$NON-NLS-1$
258 						break;
259 					default:
260 						throw new AssertionError();
261 				}
262 				lastMessages = extLevel.setMessage(lastMessages, errorMsg);
263 			}
264 		}
265 		// check other flags
266 		lastMessages = FileRequirementsEnum.check(new File(_fileName),
267 				lastMessages, flags);
268 	}
269 	/***
270 	 * Validity messages.
271 	 */
272 	protected ValidityMessages lastMessages = null;
273 	/*
274 	 * (non-Javadoc)
275 	 * @see sk.uniba.euromath.editor.widgets.IUserInputWidget#getLastError()
276 	 */
277 	public ValidityMessages getMessages() {
278 		return lastMessages;
279 	}
280 	/* (non-Javadoc)
281 	 * @see sk.uniba.euromath.editor.widgets.IUserInputWidget#getState()
282 	 */
283 	public String getState() {
284 		return getFileName();
285 	}
286 	/* (non-Javadoc)
287 	 * @see sk.uniba.euromath.editor.widgets.IUserInputWidget#getStateClass()
288 	 */
289 	public Class< ? > getStateClass() {
290 		return String.class;
291 	}
292 	/* (non-Javadoc)
293 	 * @see sk.uniba.euromath.editor.widgets.IUserInputWidget#setState(java.lang.Object)
294 	 */
295 	public void setState(Object state) {
296 		setFileName((String)state);
297 	}
298 	
299 }