KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > ide > misc > ResourceAndContainerGroup


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.ide.misc;
12
13 import org.eclipse.core.resources.IContainer;
14 import org.eclipse.core.resources.IResource;
15 import org.eclipse.core.resources.IWorkspace;
16 import org.eclipse.core.resources.IWorkspaceRoot;
17 import org.eclipse.core.resources.ResourcesPlugin;
18 import org.eclipse.core.runtime.IPath;
19 import org.eclipse.core.runtime.IStatus;
20 import org.eclipse.core.runtime.Path;
21 import org.eclipse.osgi.util.NLS;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.events.FocusAdapter;
24 import org.eclipse.swt.events.FocusEvent;
25 import org.eclipse.swt.graphics.Font;
26 import org.eclipse.swt.layout.GridData;
27 import org.eclipse.swt.layout.GridLayout;
28 import org.eclipse.swt.widgets.Composite;
29 import org.eclipse.swt.widgets.Event;
30 import org.eclipse.swt.widgets.Label;
31 import org.eclipse.swt.widgets.Listener;
32 import org.eclipse.swt.widgets.Text;
33 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
34
35 /**
36  * Workbench-level composite for resource and container specification by the user.
37  * Services such as field validation are performed by the group.
38  * The group can be configured to accept existing resources, or only
39  * new resources.
40  */

41 public class ResourceAndContainerGroup implements Listener {
42     // problem identifiers
43
public static final int PROBLEM_NONE = 0;
44
45     public static final int PROBLEM_RESOURCE_EMPTY = 1;
46
47     public static final int PROBLEM_RESOURCE_EXIST = 2;
48
49     public static final int PROBLEM_PATH_INVALID = 4;
50
51     public static final int PROBLEM_CONTAINER_EMPTY = 5;
52
53     public static final int PROBLEM_PROJECT_DOES_NOT_EXIST = 6;
54
55     public static final int PROBLEM_NAME_INVALID = 7;
56
57     public static final int PROBLEM_PATH_OCCUPIED = 8;
58
59     // the client to notify of changes
60
private Listener client;
61
62     // whether to allow existing resources
63
private boolean allowExistingResources = false;
64
65     // resource type (file, folder, project)
66
private String JavaDoc resourceType = IDEWorkbenchMessages.ResourceGroup_resource;
67
68     // show closed projects in the tree, by default
69
private boolean showClosedProjects = true;
70
71     // problem indicator
72
private String JavaDoc problemMessage = "";//$NON-NLS-1$
73

74     private int problemType = PROBLEM_NONE;
75
76     // widgets
77
private ContainerSelectionGroup containerGroup;
78
79     private Text resourceNameField;
80     
81     /**
82      * The resource extension for the resource name field.
83      * @see ResourceAndContainerGroup#setResourceExtension(String)
84      * @since 3.3
85      */

86     private String JavaDoc resourceExtension;
87
88     // constants
89
private static final int SIZING_TEXT_FIELD_WIDTH = 250;
90
91     /**
92      * Create an instance of the group to allow the user
93      * to enter/select a container and specify a resource
94      * name.
95      *
96      * @param parent composite widget to parent the group
97      * @param client object interested in changes to the group's fields value
98      * @param resourceFieldLabel label to use in front of the resource name field
99      * @param resourceType one word, in lowercase, to describe the resource to the user (file, folder, project)
100      */

101     public ResourceAndContainerGroup(Composite parent, Listener client,
102             String JavaDoc resourceFieldLabel, String JavaDoc resourceType) {
103         this(parent, client, resourceFieldLabel, resourceType, true);
104     }
105
106     /**
107      * Create an instance of the group to allow the user
108      * to enter/select a container and specify a resource
109      * name.
110      *
111      * @param parent composite widget to parent the group
112      * @param client object interested in changes to the group's fields value
113      * @param resourceFieldLabel label to use in front of the resource name field
114      * @param resourceType one word, in lowercase, to describe the resource to the user (file, folder, project)
115      * @param showClosedProjects whether or not to show closed projects
116      */

117     public ResourceAndContainerGroup(Composite parent, Listener client,
118             String JavaDoc resourceFieldLabel, String JavaDoc resourceType,
119             boolean showClosedProjects) {
120         this(parent, client, resourceFieldLabel, resourceType,
121                 showClosedProjects, SWT.DEFAULT);
122     }
123
124     /**
125      * Create an instance of the group to allow the user
126      * to enter/select a container and specify a resource
127      * name.
128      *
129      * @param parent composite widget to parent the group
130      * @param client object interested in changes to the group's fields value
131      * @param resourceFieldLabel label to use in front of the resource name field
132      * @param resourceType one word, in lowercase, to describe the resource to the user (file, folder, project)
133      * @param showClosedProjects whether or not to show closed projects
134      * @param heightHint height hint for the container selection widget group
135      */

136     public ResourceAndContainerGroup(Composite parent, Listener client,
137             String JavaDoc resourceFieldLabel, String JavaDoc resourceType,
138             boolean showClosedProjects, int heightHint) {
139         super();
140         this.resourceType = resourceType;
141         this.showClosedProjects = showClosedProjects;
142         createContents(parent, resourceFieldLabel, heightHint);
143         this.client = client;
144     }
145
146     /**
147      * Returns a boolean indicating whether all controls in this group
148      * contain valid values.
149      *
150      * @return boolean
151      */

152     public boolean areAllValuesValid() {
153         return problemType == PROBLEM_NONE;
154     }
155
156     /**
157      * Creates this object's visual components.
158      *
159      * @param parent org.eclipse.swt.widgets.Composite
160      * @param heightHint height hint for the container selection widget group
161      */

162     protected void createContents(Composite parent, String JavaDoc resourceLabelString,
163             int heightHint) {
164
165         Font font = parent.getFont();
166         // server name group
167
Composite composite = new Composite(parent, SWT.NONE);
168         GridLayout layout = new GridLayout();
169         layout.marginWidth = 0;
170         layout.marginHeight = 0;
171         composite.setLayout(layout);
172         composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
173         composite.setFont(font);
174
175         // container group
176
if (heightHint == SWT.DEFAULT) {
177             containerGroup = new ContainerSelectionGroup(composite, this, true,
178                     null, showClosedProjects);
179         } else {
180             containerGroup = new ContainerSelectionGroup(composite, this, true,
181                     null, showClosedProjects, heightHint, SIZING_TEXT_FIELD_WIDTH);
182         }
183
184         // resource name group
185
Composite nameGroup = new Composite(composite, SWT.NONE);
186         layout = new GridLayout();
187         layout.numColumns = 2;
188         layout.marginWidth = 0;
189         nameGroup.setLayout(layout);
190         nameGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
191                 | GridData.GRAB_HORIZONTAL));
192         nameGroup.setFont(font);
193
194         Label label = new Label(nameGroup, SWT.NONE);
195         label.setText(resourceLabelString);
196         label.setFont(font);
197
198         // resource name entry field
199
resourceNameField = new Text(nameGroup, SWT.BORDER);
200         resourceNameField.addListener(SWT.Modify, this);
201         resourceNameField.addFocusListener(new FocusAdapter() {
202             public void focusLost(FocusEvent e) {
203                 handleResourceNameFocusLostEvent();
204             }
205         });
206         GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
207                 | GridData.GRAB_HORIZONTAL);
208         data.widthHint = SIZING_TEXT_FIELD_WIDTH;
209         resourceNameField.setLayoutData(data);
210         resourceNameField.setFont(font);
211         validateControls();
212     }
213
214     /**
215      * Returns the path of the currently selected container
216      * or null if no container has been selected. Note that
217      * the container may not exist yet if the user entered
218      * a new container name in the field.
219      * @return The path of the container, or <code>null</code>
220      */

221     public IPath getContainerFullPath() {
222         return containerGroup.getContainerFullPath();
223     }
224
225     /**
226      * Returns an error message indicating the current problem with the value
227      * of a control in the group, or an empty message if all controls in the
228      * group contain valid values.
229      *
230      * @return java.lang.String
231      */

232     public String JavaDoc getProblemMessage() {
233         return problemMessage;
234     }
235
236     /**
237      * Returns the type of problem with the value of a control
238      * in the group.
239      *
240      * @return one of the PROBLEM_* constants
241      */

242     public int getProblemType() {
243         return problemType;
244     }
245
246     /**
247      * Returns a string that is the name of the chosen resource, or an
248      * empty string if no resource has been entered.
249      * <br><br>
250      * The name will include the resource extension if the
251      * preconditions are met.
252      * @see ResourceAndContainerGroup#setResourceExtension(String)
253      *
254      * @return The resource name
255      * @since 3.3
256      */

257     public String JavaDoc getResource() {
258         String JavaDoc resource = resourceNameField.getText();
259         if (useResourceExtension()) {
260             return resource + '.' + resourceExtension;
261         }
262         return resource;
263     }
264     
265     /**
266      * Returns the resource extension.
267      *
268      * @return The resource extension or <code>null</code>.
269      * @see ResourceAndContainerGroup#setResourceExtension(String)
270      * @since 3.3
271      */

272     public String JavaDoc getResourceExtension() {
273         return resourceExtension;
274     }
275     
276     /**
277      * Determines whether the resource extension should be added to the
278      * resource name field.
279      * <br><br>
280      * @see ResourceAndContainerGroup#setResourceExtension(String)
281      * @return <code>true</code> if the preconditions are met; otherwise,
282      * <code>false</code>.
283      * @since 3.3
284      */

285     private boolean useResourceExtension() {
286         String JavaDoc resource = resourceNameField.getText();
287         if ((resourceExtension != null) &&
288                 (resourceExtension.length() > 0) &&
289                 (resource.length() > 0) &&
290                 (resource.endsWith('.' + resourceExtension) == false)) {
291             return true;
292         }
293         return false;
294     }
295
296     /**
297      * Handle the focus lost event from the resource name field.
298      * <br>
299      * Adds the resource extension to the resource name field when it
300      * loses focus (if the preconditions are met).
301      * @see ResourceNameFocusListener
302      * @see ResourceAndContainerGroup#setResourceExtension(String)
303      * @since 3.3
304      */

305     private void handleResourceNameFocusLostEvent() {
306         if (useResourceExtension()) {
307             setResource(resourceNameField.getText() + '.' + resourceExtension);
308         }
309     }
310     
311     /**
312      * Handles events for all controls in the group.
313      *
314      * @param e org.eclipse.swt.widgets.Event
315      */

316     public void handleEvent(Event e) {
317         validateControls();
318         if (client != null) {
319             client.handleEvent(e);
320         }
321     }
322
323     /**
324      * Sets the flag indicating whether existing resources are permitted.
325      */

326     public void setAllowExistingResources(boolean value) {
327         allowExistingResources = value;
328     }
329
330     /**
331      * Sets the value of this page's container.
332      *
333      * @param path Full path to the container.
334      */

335     public void setContainerFullPath(IPath path) {
336         IResource initial = ResourcesPlugin.getWorkspace().getRoot()
337                 .findMember(path);
338         if (initial != null) {
339             if (!(initial instanceof IContainer)) {
340                 initial = initial.getParent();
341             }
342             containerGroup.setSelectedContainer((IContainer) initial);
343         }
344         validateControls();
345     }
346
347     /**
348      * Gives focus to the resource name field and selects its contents
349      */

350     public void setFocus() {
351         //select the whole resource name.
352
resourceNameField.setSelection(0, resourceNameField.getText().length());
353         resourceNameField.setFocus();
354     }
355
356     /**
357      * Sets the value of this page's resource name.
358      *
359      * @param value new value
360      */

361     public void setResource(String JavaDoc value) {
362         resourceNameField.setText(value);
363         validateControls();
364     }
365
366     /**
367      * Set the only file extension allowed for the resource name field.
368      * <br><br>
369      * If a resource extension is specified, then it will always be
370      * appended with a '.' to the text from the resource name field for
371      * validation when the following conditions are met:
372      * <br><br>
373      * (1) Resource extension length is greater than 0
374      * <br>
375      * (2) Resource name field text length is greater than 0
376      * <br>
377      * (3) Resource name field text does not already end with a '.' and the
378      * resource extension specified (case sensitive)
379      * <br><br>
380      * The resource extension will not be reflected in the actual
381      * resource name field until the resource name field loses focus.
382      *
383      * @param value
384      * The resource extension without the '.' prefix
385      * (e.g. 'java', 'xml')
386      * @since 3.3
387      */

388     public void setResourceExtension(String JavaDoc value) {
389         resourceExtension = value;
390         validateControls();
391     }
392
393     /**
394      * Returns a <code>boolean</code> indicating whether a container name represents
395      * a valid container resource in the workbench. An error message is stored for
396      * future reference if the name does not represent a valid container.
397      *
398      * @return <code>boolean</code> indicating validity of the container name
399      */

400     protected boolean validateContainer() {
401         IPath path = containerGroup.getContainerFullPath();
402         if (path == null) {
403             problemType = PROBLEM_CONTAINER_EMPTY;
404             problemMessage = IDEWorkbenchMessages.ResourceGroup_folderEmpty;
405             return false;
406         }
407         IWorkspace workspace = ResourcesPlugin.getWorkspace();
408         String JavaDoc projectName = path.segment(0);
409         if (projectName == null
410                 || !workspace.getRoot().getProject(projectName).exists()) {
411             problemType = PROBLEM_PROJECT_DOES_NOT_EXIST;
412             problemMessage = IDEWorkbenchMessages.ResourceGroup_noProject;
413             return false;
414         }
415         //path is invalid if any prefix is occupied by a file
416
IWorkspaceRoot root = workspace.getRoot();
417         while (path.segmentCount() > 1) {
418             if (root.getFile(path).exists()) {
419                 problemType = PROBLEM_PATH_OCCUPIED;
420                 problemMessage = NLS.bind(IDEWorkbenchMessages.ResourceGroup_pathOccupied, path.makeRelative());
421                 return false;
422             }
423             path = path.removeLastSegments(1);
424         }
425         return true;
426     }
427
428     /**
429      * Validates the values for each of the group's controls. If an invalid
430      * value is found then a descriptive error message is stored for later
431      * reference. Returns a boolean indicating the validity of all of the
432      * controls in the group.
433      */

434     protected boolean validateControls() {
435         // don't attempt to validate controls until they have been created
436
if (containerGroup == null) {
437             return false;
438         }
439         problemType = PROBLEM_NONE;
440         problemMessage = "";//$NON-NLS-1$
441

442         if (!validateContainer() || !validateResourceName()) {
443             return false;
444         }
445
446         IPath path = containerGroup.getContainerFullPath().append(
447                 getResource());
448         return validateFullResourcePath(path);
449     }
450
451     /**
452      * Returns a <code>boolean</code> indicating whether the specified resource
453      * path represents a valid new resource in the workbench. An error message
454      * is stored for future reference if the path does not represent a valid
455      * new resource path.
456      *
457      * @param resourcePath the path to validate
458      * @return <code>boolean</code> indicating validity of the resource path
459      */

460     protected boolean validateFullResourcePath(IPath resourcePath) {
461         IWorkspace workspace = ResourcesPlugin.getWorkspace();
462
463         IStatus result = workspace.validatePath(resourcePath.toString(),
464                 IResource.FOLDER);
465         if (!result.isOK()) {
466             problemType = PROBLEM_PATH_INVALID;
467             problemMessage = result.getMessage();
468             return false;
469         }
470
471         if (!allowExistingResources
472                 && (workspace.getRoot().getFolder(resourcePath).exists() || workspace
473                         .getRoot().getFile(resourcePath).exists())) {
474             problemType = PROBLEM_RESOURCE_EXIST;
475             problemMessage = NLS.bind(IDEWorkbenchMessages.ResourceGroup_nameExists, getResource());
476             return false;
477         }
478         return true;
479     }
480
481     /**
482      * Returns a <code>boolean</code> indicating whether the resource name rep-
483      * resents a valid resource name in the workbench. An error message is stored
484      * for future reference if the name does not represent a valid resource name.
485      *
486      * @return <code>boolean</code> indicating validity of the resource name
487      */

488     protected boolean validateResourceName() {
489         String JavaDoc resourceName = getResource();
490
491         if (resourceName.length() == 0) {
492             problemType = PROBLEM_RESOURCE_EMPTY;
493             problemMessage = NLS.bind(IDEWorkbenchMessages.ResourceGroup_emptyName, resourceType);
494             return false;
495         }
496
497         if (!Path.ROOT.isValidPath(resourceName)) {
498             problemType = PROBLEM_NAME_INVALID;
499             problemMessage = NLS.bind(IDEWorkbenchMessages.ResourceGroup_invalidFilename, resourceName);
500             return false;
501         }
502         return true;
503     }
504
505 }
506
Popular Tags