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