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