f21bfb6da792d609ce4c54befcab25c4269b963f
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpdt / ui / wizards / NewContainerWizardPage.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.ui.wizards;
12
13 import net.sourceforge.phpdt.core.IJavaElement;
14 import net.sourceforge.phpdt.core.IJavaProject;
15 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
16 import net.sourceforge.phpdt.core.JavaCore;
17 import net.sourceforge.phpdt.core.JavaModelException;
18 import net.sourceforge.phpdt.externaltools.internal.ui.StatusInfo;
19 import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider;
20 import net.sourceforge.phpdt.internal.ui.wizards.NewWizardMessages;
21 import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.DialogField;
22 import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
23 import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
24 import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.LayoutUtil;
25 import net.sourceforge.phpdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
26 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
27 import net.sourceforge.phpeclipse.ui.WebUI;
28
29 import org.eclipse.core.resources.IProject;
30 import org.eclipse.core.resources.IResource;
31 import org.eclipse.core.resources.IWorkspaceRoot;
32 import org.eclipse.core.resources.ResourcesPlugin;
33 import org.eclipse.core.runtime.IAdaptable;
34 import org.eclipse.core.runtime.IPath;
35 import org.eclipse.core.runtime.IStatus;
36 import org.eclipse.core.runtime.Path;
37 import org.eclipse.jface.viewers.IStructuredSelection;
38 import org.eclipse.swt.widgets.Composite;
39 import org.eclipse.ui.IWorkbenchPart;
40 import org.eclipse.ui.views.contentoutline.ContentOutline;
41
42 /**
43  * Wizard page that acts as a base class for wizard pages that create new Java
44  * elements. The class provides a input field for source folders (called
45  * container in this class) and API to validate the enter source folder name.
46  * 
47  * @since 2.0
48  */
49 public abstract class NewContainerWizardPage extends NewElementWizardPage {
50
51         /** Id of the container field */
52         protected static final String CONTAINER = "NewContainerWizardPage.container"; //$NON-NLS-1$
53
54         /** The status of the last validation. */
55         protected IStatus fContainerStatus;
56
57         private StringButtonDialogField fContainerDialogField;
58
59         /*
60          * package fragment root corresponding to the input type (can be null)
61          */
62         private IPackageFragmentRoot fCurrRoot;
63
64         private IWorkspaceRoot fWorkspaceRoot;
65
66         /**
67          * Create a new <code>NewContainerWizardPage</code>
68          * 
69          * @param name
70          *            the wizard page's name
71          */
72         public NewContainerWizardPage(String name) {
73                 super(name);
74                 fWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
75                 ContainerFieldAdapter adapter = new ContainerFieldAdapter();
76
77                 fContainerDialogField = new StringButtonDialogField(adapter);
78                 fContainerDialogField.setDialogFieldListener(adapter);
79                 fContainerDialogField.setLabelText(NewWizardMessages
80                                 .getString("NewContainerWizardPage.container.label")); //$NON-NLS-1$
81                 fContainerDialogField.setButtonLabel(NewWizardMessages
82                                 .getString("NewContainerWizardPage.container.button")); //$NON-NLS-1$
83
84                 fContainerStatus = new StatusInfo();
85                 fCurrRoot = null;
86         }
87
88         /**
89          * Initializes the source folder field with a valid package fragement root.
90          * The package fragement root is computed from the given Java element.
91          * 
92          * @param elem
93          *            the Java element used to compute the initial package fragment
94          *            root used as the source folder
95          */
96         protected void initContainerPage(IJavaElement elem) {
97                 IPackageFragmentRoot initRoot = null;
98                 // if (elem != null) {
99                 // initRoot= JavaModelUtil.getPackageFragmentRoot(elem);
100                 // if (initRoot == null || initRoot.isArchive()) {
101                 // IJavaProject jproject= elem.getJavaProject();
102                 // if (jproject != null) {
103                 // try {
104                 // initRoot= null;
105                 // if (jproject.exists()) {
106                 // IPackageFragmentRoot[] roots= jproject.getPackageFragmentRoots();
107                 // for (int i= 0; i < roots.length; i++) {
108                 // if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
109                 // initRoot= roots[i];
110                 // break;
111                 // }
112                 // }
113                 // }
114                 // } catch (JavaModelException e) {
115                 // PHPeclipsePlugin.log(e);
116                 // }
117                 // if (initRoot == null) {
118                 // initRoot= jproject.getPackageFragmentRoot(jproject.getResource());
119                 // }
120                 // }
121                 // }
122                 // }
123                 // setPackageFragmentRoot(initRoot, true);
124         }
125
126         /**
127          * Utility method to inspect a selection to find a Java element.
128          * 
129          * @param selection
130          *            the selection to be inspected
131          * @return a Java element to be used as the initial selection, or
132          *         <code>null</code>, if no Java element exists in the given
133          *         selection
134          */
135         protected IJavaElement getInitialJavaElement(IStructuredSelection selection) {
136                 IJavaElement jelem = null;
137                 if (selection != null && !selection.isEmpty()) {
138                         Object selectedElement = selection.getFirstElement();
139                         if (selectedElement instanceof IAdaptable) {
140                                 IAdaptable adaptable = (IAdaptable) selectedElement;
141
142                                 jelem = (IJavaElement) adaptable.getAdapter(IJavaElement.class);
143                                 if (jelem == null) {
144                                         IResource resource = (IResource) adaptable
145                                                         .getAdapter(IResource.class);
146                                         if (resource != null
147                                                         && resource.getType() != IResource.ROOT) {
148                                                 while (jelem == null
149                                                                 && resource.getType() != IResource.PROJECT) {
150                                                         resource = resource.getParent();
151                                                         jelem = (IJavaElement) resource
152                                                                         .getAdapter(IJavaElement.class);
153                                                 }
154                                                 if (jelem == null) {
155                                                         jelem = JavaCore.create(resource); // java project
156                                                 }
157                                         }
158                                 }
159                         }
160                 }
161                 if (jelem == null) {
162                         IWorkbenchPart part = WebUI.getActivePage()
163                                         .getActivePart();
164                         if (part instanceof ContentOutline) {
165                                 part = WebUI.getActivePage().getActiveEditor();
166                         }
167
168                         if (part instanceof IViewPartInputProvider) {
169                                 Object elem = ((IViewPartInputProvider) part)
170                                                 .getViewPartInput();
171                                 if (elem instanceof IJavaElement) {
172                                         jelem = (IJavaElement) elem;
173                                 }
174                         }
175                 }
176
177                 if (jelem == null || jelem.getElementType() == IJavaElement.JAVA_MODEL) {
178                         try {
179                                 IJavaProject[] projects = JavaCore.create(getWorkspaceRoot())
180                                                 .getJavaProjects();
181                                 if (projects.length == 1) {
182                                         jelem = projects[0];
183                                 }
184                         } catch (JavaModelException e) {
185                                 PHPeclipsePlugin.log(e);
186                         }
187                 }
188                 return jelem;
189         }
190
191         /**
192          * Returns the recommended maximum width for text fields (in pixels). This
193          * method requires that createContent has been called before this method is
194          * call. Subclasses may override to change the maximum width for text
195          * fields.
196          * 
197          * @return the recommended maximum width for text fields.
198          */
199         protected int getMaxFieldWidth() {
200                 return convertWidthInCharsToPixels(40);
201         }
202
203         /**
204          * Creates the necessary controls (label, text field and browse button) to
205          * edit the source folder location. The method expects that the parent
206          * composite uses a <code>GridLayout</code> as its layout manager and that
207          * the grid layout has at least 3 columns.
208          * 
209          * @param parent
210          *            the parent composite
211          * @param nColumns
212          *            the number of columns to span. This number must be greater or
213          *            equal three
214          */
215         protected void createContainerControls(Composite parent, int nColumns) {
216                 fContainerDialogField.doFillIntoGrid(parent, nColumns);
217                 LayoutUtil.setWidthHint(fContainerDialogField.getTextControl(null),
218                                 getMaxFieldWidth());
219         }
220
221         /**
222          * Sets the focus to the source folder's text field.
223          */
224         protected void setFocusOnContainer() {
225                 fContainerDialogField.setFocus();
226         }
227
228         // -------- ContainerFieldAdapter --------
229
230         private class ContainerFieldAdapter implements IStringButtonAdapter,
231                         IDialogFieldListener {
232
233                 // -------- IStringButtonAdapter
234                 public void changeControlPressed(DialogField field) {
235                         containerChangeControlPressed(field);
236                 }
237
238                 // -------- IDialogFieldListener
239                 public void dialogFieldChanged(DialogField field) {
240                         containerDialogFieldChanged(field);
241                 }
242         }
243
244         private void containerChangeControlPressed(DialogField field) {
245                 // take the current jproject as init element of the dialog
246                 // IPackageFragmentRoot root= getPackageFragmentRoot();
247                 // root= chooseSourceContainer(root);
248                 // if (root != null) {
249                 // setPackageFragmentRoot(root, true);
250                 // }
251         }
252
253         private void containerDialogFieldChanged(DialogField field) {
254                 if (field == fContainerDialogField) {
255                         fContainerStatus = containerChanged();
256                 }
257                 // tell all others
258                 handleFieldChanged(CONTAINER);
259         }
260
261         // ----------- validation ----------
262
263         /**
264          * This method is a hook which gets called after the source folder's text
265          * input field has changed. This default implementation updates the model
266          * and returns an error status. The underlying model is only valid if the
267          * returned status is OK.
268          * 
269          * @return the model's error status
270          */
271         protected IStatus containerChanged() {
272                 StatusInfo status = new StatusInfo();
273
274                 fCurrRoot = null;
275                 String str = getPackageFragmentRootText();
276                 if (str.length() == 0) {
277                         status
278                                         .setError(NewWizardMessages
279                                                         .getString("NewContainerWizardPage.error.EnterContainerName")); //$NON-NLS-1$
280                         return status;
281                 }
282                 IPath path = new Path(str);
283                 IResource res = fWorkspaceRoot.findMember(path);
284                 if (res != null) {
285                         int resType = res.getType();
286                         if (resType == IResource.PROJECT || resType == IResource.FOLDER) {
287                                 IProject proj = res.getProject();
288                                 if (!proj.isOpen()) {
289                                         status
290                                                         .setError(NewWizardMessages
291                                                                         .getFormattedString(
292                                                                                         "NewContainerWizardPage.error.ProjectClosed", proj.getFullPath().toString())); //$NON-NLS-1$
293                                         return status;
294                                 }
295                                 IJavaProject jproject = JavaCore.create(proj);
296                                 // fCurrRoot= jproject.getPackageFragmentRoot(res);
297                                 // if (res.exists()) {
298                                 // try {
299                                 // if (!proj.hasNature(JavaCore.NATURE_ID)) {
300                                 // if (resType == IResource.PROJECT) {
301                                 // status.setError(NewWizardMessages.getString("NewContainerWizardPage.warning.NotAJavaProject"));
302                                 // //$NON-NLS-1$
303                                 // } else {
304                                 // status.setWarning(NewWizardMessages.getString("NewContainerWizardPage.warning.NotInAJavaProject"));
305                                 // //$NON-NLS-1$
306                                 // }
307                                 // return status;
308                                 // }
309                                 // } catch (CoreException e) {
310                                 // status.setWarning(NewWizardMessages.getString("NewContainerWizardPage.warning.NotAJavaProject"));
311                                 // //$NON-NLS-1$
312                                 // }
313                                 // if (!jproject.isOnClasspath(fCurrRoot)) {
314                                 // status.setWarning(NewWizardMessages.getFormattedString("NewContainerWizardPage.warning.NotOnClassPath",
315                                 // str)); //$NON-NLS-1$
316                                 // }
317                                 // if (fCurrRoot.isArchive()) {
318                                 // status.setError(NewWizardMessages.getFormattedString("NewContainerWizardPage.error.ContainerIsBinary",
319                                 // str)); //$NON-NLS-1$
320                                 // return status;
321                                 // }
322                                 // }
323                                 return status;
324                         } else {
325                                 status.setError(NewWizardMessages.getFormattedString(
326                                                 "NewContainerWizardPage.error.NotAFolder", str)); //$NON-NLS-1$
327                                 return status;
328                         }
329                 } else {
330                         status.setError(NewWizardMessages.getFormattedString(
331                                         "NewContainerWizardPage.error.ContainerDoesNotExist", str)); //$NON-NLS-1$
332                         return status;
333                 }
334         }
335
336         // -------- update message ----------------
337
338         /**
339          * Hook method that gets called when a field on this page has changed. For
340          * this page the method gets called when the source folder field changes.
341          * <p>
342          * Every sub type is responsible to call this method when a field on its
343          * page has changed. Subtypes override (extend) the method to add
344          * verification when a own field has a dependency to an other field. For
345          * example the class name input must be verified again when the package
346          * field changes (check for duplicated class names).
347          * 
348          * @param fieldName
349          *            The name of the field that has changed (field id). For the
350          *            source folder the field id is <code>CONTAINER</code>
351          */
352         protected void handleFieldChanged(String fieldName) {
353         }
354
355         // ---- get ----------------
356
357         /**
358          * Returns the workspace root.
359          * 
360          * @return the workspace root
361          */
362         protected IWorkspaceRoot getWorkspaceRoot() {
363                 return fWorkspaceRoot;
364         }
365
366         /**
367          * Returns the <code>IPackageFragmentRoot</code> that corresponds to the
368          * current value of the source folder field.
369          * 
370          * @return the IPackageFragmentRoot or <code>null</code> if the current
371          *         source folder value is not a valid package fragment root
372          * 
373          */
374         public IPackageFragmentRoot getPackageFragmentRoot() {
375                 return fCurrRoot;
376         }
377
378         /**
379          * Returns the current text of source folder text field.
380          * 
381          * @return the text of the source folder text field
382          */
383         public String getPackageFragmentRootText() {
384                 return fContainerDialogField.getText();
385         }
386
387         /**
388          * Sets the current source folder (model and text field) to the given
389          * package fragment root.
390          * 
391          * @param canBeModified
392          *            if <code>false</code> the source folder field can not be
393          *            changed by the user. If <code>true</code> the field is
394          *            editable
395          */
396         // public void setPackageFragmentRoot(IPackageFragmentRoot root, boolean
397         // canBeModified) {
398         // fCurrRoot= root;
399         // String str= (root == null) ? "" :
400         // root.getPath().makeRelative().toString(); //$NON-NLS-1$
401         // fContainerDialogField.setText(str);
402         // fContainerDialogField.setEnabled(canBeModified);
403         // }
404         // ------------- choose source container dialog
405         // private IPackageFragmentRoot chooseSourceContainer(IJavaElement
406         // initElement) {
407         // Class[] acceptedClasses= new Class[] { IPackageFragmentRoot.class,
408         // IJavaProject.class };
409         // TypedElementSelectionValidator validator= new
410         // TypedElementSelectionValidator(acceptedClasses, false) {
411         // public boolean isSelectedValid(Object element) {
412         // try {
413         // if (element instanceof IJavaProject) {
414         // IJavaProject jproject= (IJavaProject)element;
415         // IPath path= jproject.getProject().getFullPath();
416         // return (jproject.findPackageFragmentRoot(path) != null);
417         // } else if (element instanceof IPackageFragmentRoot) {
418         // return (((IPackageFragmentRoot)element).getKind() ==
419         // IPackageFragmentRoot.K_SOURCE);
420         // }
421         // return true;
422         // } catch (JavaModelException e) {
423         // PHPeclipsePlugin.log(e.getStatus()); // just log, no ui in validation
424         // }
425         // return false;
426         // }
427         // };
428         //              
429         // acceptedClasses= new Class[] { IJavaModel.class,
430         // IPackageFragmentRoot.class, IJavaProject.class };
431         // ViewerFilter filter= new TypedViewerFilter(acceptedClasses) {
432         // public boolean select(Viewer viewer, Object parent, Object element) {
433         // if (element instanceof IPackageFragmentRoot) {
434         // try {
435         // return (((IPackageFragmentRoot)element).getKind() ==
436         // IPackageFragmentRoot.K_SOURCE);
437         // } catch (JavaModelException e) {
438         // PHPeclipsePlugin.log(e.getStatus()); // just log, no ui in validation
439         // return false;
440         // }
441         // }
442         // return super.select(viewer, parent, element);
443         // }
444         // };
445         //
446         // StandardJavaElementContentProvider provider= new
447         // StandardJavaElementContentProvider();
448         // ILabelProvider labelProvider= new
449         // JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
450         // ElementTreeSelectionDialog dialog= new
451         // ElementTreeSelectionDialog(getShell(), labelProvider, provider);
452         // dialog.setValidator(validator);
453         // dialog.setSorter(new JavaElementSorter());
454         // dialog.setTitle(NewWizardMessages.getString("NewContainerWizardPage.ChooseSourceContainerDialog.title"));
455         // //$NON-NLS-1$
456         // dialog.setMessage(NewWizardMessages.getString("NewContainerWizardPage.ChooseSourceContainerDialog.description"));
457         // //$NON-NLS-1$
458         // dialog.addFilter(filter);
459         // dialog.setInput(JavaCore.create(fWorkspaceRoot));
460         // dialog.setInitialSelection(initElement);
461         //              
462         // if (dialog.open() == ElementTreeSelectionDialog.OK) {
463         // Object element= dialog.getFirstResult();
464         // if (element instanceof IJavaProject) {
465         // IJavaProject jproject= (IJavaProject)element;
466         // return jproject.getPackageFragmentRoot(jproject.getProject());
467         // } else if (element instanceof IPackageFragmentRoot) {
468         // return (IPackageFragmentRoot)element;
469         // }
470         // return null;
471         // }
472         // return null;
473         // }
474 }