KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ant > internal > ui > preferences > AddCustomDialog


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.ant.internal.ui.preferences;
12
13 import com.ibm.icu.text.MessageFormat;
14
15 import java.io.File JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.StringTokenizer JavaDoc;
20 import java.util.zip.ZipEntry JavaDoc;
21 import java.util.zip.ZipException JavaDoc;
22 import java.util.zip.ZipFile JavaDoc;
23
24 import org.eclipse.ant.core.IAntClasspathEntry;
25 import org.eclipse.ant.internal.ui.AntUIPlugin;
26 import org.eclipse.core.runtime.CoreException;
27 import org.eclipse.core.runtime.IPath;
28 import org.eclipse.core.runtime.Path;
29 import org.eclipse.core.variables.VariablesPlugin;
30 import org.eclipse.jface.dialogs.IDialogConstants;
31 import org.eclipse.jface.dialogs.StatusDialog;
32 import org.eclipse.jface.viewers.DoubleClickEvent;
33 import org.eclipse.jface.viewers.IDoubleClickListener;
34 import org.eclipse.jface.viewers.ISelectionChangedListener;
35 import org.eclipse.jface.viewers.IStructuredSelection;
36 import org.eclipse.jface.viewers.ITreeContentProvider;
37 import org.eclipse.jface.viewers.SelectionChangedEvent;
38 import org.eclipse.swt.SWT;
39 import org.eclipse.swt.custom.BusyIndicator;
40 import org.eclipse.swt.events.FocusAdapter;
41 import org.eclipse.swt.events.FocusEvent;
42 import org.eclipse.swt.events.KeyAdapter;
43 import org.eclipse.swt.events.KeyEvent;
44 import org.eclipse.swt.events.ModifyEvent;
45 import org.eclipse.swt.events.ModifyListener;
46 import org.eclipse.swt.events.SelectionAdapter;
47 import org.eclipse.swt.events.SelectionEvent;
48 import org.eclipse.swt.layout.GridData;
49 import org.eclipse.swt.layout.GridLayout;
50 import org.eclipse.swt.widgets.Combo;
51 import org.eclipse.swt.widgets.Composite;
52 import org.eclipse.swt.widgets.Control;
53 import org.eclipse.swt.widgets.Label;
54 import org.eclipse.swt.widgets.Shell;
55 import org.eclipse.swt.widgets.Text;
56 import org.eclipse.ui.PlatformUI;
57 import org.eclipse.ui.dialogs.FileSystemElement;
58 import org.eclipse.ui.externaltools.internal.ui.TreeAndListGroup;
59 import org.eclipse.ui.model.WorkbenchContentProvider;
60 import org.eclipse.ui.model.WorkbenchLabelProvider;
61 import org.eclipse.ui.model.WorkbenchViewerComparator;
62 import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
63 import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
64 import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
65
66 public class AddCustomDialog extends StatusDialog {
67     
68     private ZipFileStructureProvider providerCache;
69     private IImportStructureProvider currentProvider;
70     
71     //A boolean to indicate if the user has typed anything
72
private boolean entryChanged = false;
73
74     private Combo sourceNameField;
75     private List JavaDoc libraryEntries;
76     private List JavaDoc existingNames;
77     
78     private String JavaDoc noNameErrorMsg;
79     private String JavaDoc alreadyExistsErrorMsg;
80     
81     private TreeAndListGroup selectionGroup;
82     
83     private Text nameField;
84     
85     private String JavaDoc name=""; //$NON-NLS-1$
86
private IAntClasspathEntry library= null;
87     private String JavaDoc className=""; //$NON-NLS-1$
88

89     private boolean editing= false;
90     
91     private String JavaDoc helpContext;
92
93     /**
94      * Creates a new dialog with the given shell and title.
95      */

96     public AddCustomDialog(Shell parent, List JavaDoc libraryEntries, List JavaDoc existingNames, String JavaDoc helpContext) {
97         super(parent);
98         this.libraryEntries = libraryEntries;
99         this.existingNames= existingNames;
100         this.helpContext= helpContext;
101         setShellStyle(getShellStyle() | SWT.RESIZE);
102     }
103     
104     /* (non-Javadoc)
105      * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
106      */

107     protected Control createDialogArea(Composite parent) {
108         Composite topComposite= (Composite) super.createDialogArea(parent);
109         topComposite.setSize(topComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
110
111         Composite topGroup = new Composite(topComposite, SWT.NONE);
112         GridLayout layout = new GridLayout();
113         layout.numColumns = 2;
114         layout.marginHeight= 0;
115         layout.marginWidth= 0;
116         topGroup.setLayout(layout);
117         topGroup.setFont(topComposite.getFont());
118         topGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
119         
120         createNameGroup(topGroup);
121         createRootDirectoryGroup(topGroup);
122         createFileSelectionGroup(topComposite);
123         
124         if (library != null) {
125             setSourceName(library.getLabel());
126         }
127         return topComposite;
128     }
129     
130     private void createNameGroup(Composite topComposite) {
131         Label label = new Label(topComposite, SWT.NONE);
132         label.setFont(topComposite.getFont());
133         label.setText(AntPreferencesMessages.AddCustomDialog__Name__3);
134         
135         nameField = new Text(topComposite, SWT.BORDER);
136         GridData data = new GridData(GridData.FILL_HORIZONTAL);
137         data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
138     
139         nameField.setLayoutData(data);
140         nameField.setFont(topComposite.getFont());
141         nameField.setText(name);
142         nameField.addModifyListener(new ModifyListener() {
143             public void modifyText(ModifyEvent e) {
144                 updateStatus();
145             }
146         });
147     }
148
149     /* (non-Javadoc)
150      * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
151      */

152     protected void configureShell(Shell newShell) {
153         super.configureShell(newShell);
154         PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, helpContext);
155     }
156     
157     /**
158      * Clears the cached structure provider after first finalizing
159      * it properly.
160      */

161     private void clearProviderCache() {
162         if (providerCache != null) {
163             closeZipFile(providerCache.getZipFile());
164             providerCache = null;
165         }
166     }
167     
168     /**
169      * Attempts to close the passed zip file, and answers a boolean indicating success.
170      */

171     private boolean closeZipFile(ZipFile JavaDoc file) {
172         try {
173             file.close();
174         } catch (IOException JavaDoc e) {
175             AntUIPlugin.log(MessageFormat.format(AntPreferencesMessages.AddCustomDialog_Could_not_close_zip_file__0__4, new String JavaDoc[]{file.getName()}), e);
176             return false;
177         }
178
179         return true;
180     }
181
182     /**
183      * Create the group for creating the root directory
184      */

185     private void createRootDirectoryGroup(Composite parent) {
186         Label groupLabel = new Label(parent, SWT.NONE);
187         groupLabel.setText(AntPreferencesMessages.AddCustomDialog__Location);
188         groupLabel.setFont(parent.getFont());
189
190         // source name entry field
191
sourceNameField = new Combo(parent, SWT.BORDER | SWT.READ_ONLY);
192         GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
193         data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
194         sourceNameField.setLayoutData(data);
195         sourceNameField.setFont(parent.getFont());
196         
197         sourceNameField.addSelectionListener(new SelectionAdapter() {
198             public void widgetSelected(SelectionEvent e) {
199                 updateFromSourceField();
200             }
201         });
202
203         Iterator JavaDoc libraries= libraryEntries.iterator();
204         while (libraries.hasNext()) {
205             ClasspathEntry entry = (ClasspathEntry) libraries.next();
206             sourceNameField.add(entry.getLabel());
207         }
208         
209         sourceNameField.addKeyListener(new KeyAdapter() {
210             /*
211              * @see KeyListener.keyPressed
212              */

213             public void keyPressed(KeyEvent e) {
214                 //If there has been a key pressed then mark as dirty
215
entryChanged = true;
216             }
217         });
218
219         sourceNameField.addFocusListener(new FocusAdapter() {
220             /*
221              * @see FocusListener.focusLost(FocusEvent)
222              */

223             public void focusLost(FocusEvent e) {
224                 //Clear the flag to prevent constant update
225
if (entryChanged) {
226                     entryChanged = false;
227                     updateFromSourceField();
228                 }
229             }
230         });
231     }
232     
233     /**
234      * Update the receiver from the source name field.
235      */

236     private void updateFromSourceField(){
237         setSourceName(sourceNameField.getText());
238         updateStatus();
239     }
240     
241     
242     /**
243      * Check the field values and display a message in the status if needed.
244      */

245     private void updateStatus() {
246         StatusInfo status= new StatusInfo();
247         String JavaDoc customName= nameField.getText().trim();
248         if (customName.length() == 0) {
249             status.setError(noNameErrorMsg);
250         } else if (!editing){
251             Iterator JavaDoc names= existingNames.iterator();
252             while (names.hasNext()) {
253                 String JavaDoc aName = (String JavaDoc) names.next();
254                 if(aName.equals(customName)) {
255                     status.setError(MessageFormat.format(alreadyExistsErrorMsg, new String JavaDoc[]{customName}));
256                     updateStatus(status);
257                     return;
258                 }
259             }
260         }
261         if (selectionGroup.getListTableSelection().isEmpty()) {
262             status.setError(AntPreferencesMessages.AddCustomDialog_mustSelect);
263         }
264         updateStatus(status);
265     }
266
267     
268     /**
269      * Sets the source name of the import to be the supplied path.
270      * Adds the name of the path to the list of items in the
271      * source combo and selects it.
272      *
273      * @param path the path to be added
274      */

275     private void setSourceName(String JavaDoc path) {
276
277         if (path.length() > 0) {
278
279             String JavaDoc[] currentItems = this.sourceNameField.getItems();
280             int selectionIndex = -1;
281             for (int i = 0; i < currentItems.length; i++) {
282                 if (currentItems[i].equals(path)) {
283                     selectionIndex = i;
284                     break;
285                 }
286             }
287             if (selectionIndex < 0) {
288                 int oldLength = currentItems.length;
289                 String JavaDoc[] newItems = new String JavaDoc[oldLength + 1];
290                 System.arraycopy(currentItems, 0, newItems, 0, oldLength);
291                 newItems[oldLength] = path;
292                 this.sourceNameField.setItems(newItems);
293                 selectionIndex = oldLength;
294             }
295             this.sourceNameField.select(selectionIndex);
296
297             resetSelection();
298         }
299     }
300
301     /*
302     * Create the file selection widget
303     */

304     private void createFileSelectionGroup(Composite parent) {
305         //Just create with a dummy root.
306
FileSystemElement dummyRoot= new FileSystemElement("Dummy", null, true); //$NON-NLS-1$
307
this.selectionGroup = new TreeAndListGroup(parent, dummyRoot,
308                 getFolderProvider(), new WorkbenchLabelProvider(), getFileProvider(),
309                 new WorkbenchLabelProvider(), SWT.NONE, 400, 150, false);
310
311         ISelectionChangedListener listener = new ISelectionChangedListener() {
312             public void selectionChanged(SelectionChangedEvent event) {
313                 updateStatus();
314             }
315         };
316
317         WorkbenchViewerComparator comparator = new WorkbenchViewerComparator();
318         this.selectionGroup.setTreeComparator(comparator);
319         this.selectionGroup.setListSorter(comparator);
320         this.selectionGroup.addSelectionChangedListener(listener);
321         selectionGroup.addDoubleClickListener(new IDoubleClickListener() {
322             public void doubleClick(DoubleClickEvent event) {
323                 if (getButton(IDialogConstants.OK_ID).isEnabled()) {
324                     buttonPressed(IDialogConstants.OK_ID);
325                 }
326             }
327         });
328     }
329     
330     /**
331      * Returns whether the specified source currently exists
332      * and is valid (ie.- proper format)
333      */

334     protected boolean ensureSourceIsValid() {
335         ZipFile JavaDoc specifiedFile = getSpecifiedSourceFile();
336
337         if (specifiedFile == null){
338             return false;
339         }
340
341         return closeZipFile(specifiedFile);
342     }
343     /**
344     * Answer the root FileSystemElement that represents the contents of the
345     * currently-specified .zip file. If this FileSystemElement is not
346     * currently defined then create and return it.
347     */

348     private MinimizedFileSystemElement getFileSystemTree() {
349         IImportStructureProvider provider= null;
350         MinimizedFileSystemElement element= null;
351         ZipFile JavaDoc sourceFile = getSpecifiedSourceFile();
352         if (sourceFile == null) {
353             File JavaDoc file= new File JavaDoc(sourceNameField.getText());
354             if (file.exists()) {
355                 provider = FileSystemStructureProvider.INSTANCE;
356                 element= selectFiles(file, provider);
357             }
358         } else {
359             //zip file set as location
360
provider = getStructureProvider(sourceFile);
361             element= selectFiles(((ZipFileStructureProvider)provider).getRoot(), provider);
362         }
363         this.currentProvider = provider;
364         return element;
365     }
366     
367     /**
368      * Invokes a file selection operation using the specified file system and
369      * structure provider. If the user specifies files then this selection is
370      * cached for later retrieval and is returned.
371      */

372     private MinimizedFileSystemElement selectFiles(final Object JavaDoc rootFileSystemObject, final IImportStructureProvider structureProvider) {
373
374         final MinimizedFileSystemElement[] results = new MinimizedFileSystemElement[1];
375
376         BusyIndicator.showWhile(getShell().getDisplay(), new Runnable JavaDoc() {
377             public void run() {
378                 //Create the root element from the supplied file system object
379
results[0] = createRootElement(rootFileSystemObject, structureProvider);
380             }
381         });
382
383         return results[0];
384     }
385     
386     /**
387      * Creates and returns a <code>MinimizedFileSystemElement</code> if the specified
388      * file system object merits one.
389      */

390     private MinimizedFileSystemElement createRootElement(Object JavaDoc fileSystemObject, IImportStructureProvider provider) {
391         boolean isContainer = provider.isFolder(fileSystemObject);
392         String JavaDoc elementLabel = provider.getLabel(fileSystemObject);
393
394         // Use an empty label so that display of the element's full name
395
// doesn't include a confusing label
396
MinimizedFileSystemElement dummyParent =
397             new MinimizedFileSystemElement("", null, true);//$NON-NLS-1$
398
dummyParent.setPopulated();
399         MinimizedFileSystemElement result =
400             new MinimizedFileSystemElement(elementLabel, dummyParent, isContainer);
401         result.setFileSystemObject(fileSystemObject);
402
403         //Get the files for the element so as to build the first level
404
result.getFiles(provider);
405
406         return dummyParent;
407     }
408     
409     /**
410      * Answer a handle to the zip file currently specified as being the source.
411      * Return <code>null</code> if this file does not exist or is not of valid format.
412      */

413     private ZipFile JavaDoc getSpecifiedSourceFile() {
414         try {
415             String JavaDoc expanded = sourceNameField.getText();
416             expanded= VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(expanded);
417             return new ZipFile JavaDoc(expanded);
418         } catch (ZipException JavaDoc e) {
419             StatusInfo status= new StatusInfo();
420             status.setError(AntPreferencesMessages.AddCustomDialog_Bad_Format);
421             updateStatus(status);
422         } catch (IOException JavaDoc e) {
423             StatusInfo status= new StatusInfo();
424             status.setError(AntPreferencesMessages.AddCustomDialog_Unreadable);
425             updateStatus(status);
426         } catch (CoreException e) {
427             StatusInfo status= new StatusInfo();
428             status.setError(AntPreferencesMessages.AddCustomDialog_13);
429             updateStatus(status);
430         }
431
432         sourceNameField.setFocus();
433         return null;
434     }
435     /**
436      * Returns a structure provider for the specified zip file.
437      */

438     private ZipFileStructureProvider getStructureProvider(ZipFile JavaDoc targetZip) {
439         if (providerCache == null) {
440             providerCache = new ZipFileStructureProvider(targetZip);
441         } else if (!providerCache.getZipFile().getName().equals(targetZip.getName())) {
442             clearProviderCache();
443             // ie.- new value, so finalize & remove old value
444
providerCache = new ZipFileStructureProvider(targetZip);
445         } else if (!providerCache.getZipFile().equals(targetZip)) {
446             closeZipFile(targetZip); // ie.- duplicate handle to same .zip
447
}
448
449         return providerCache;
450     }
451
452     /**
453      * Repopulate the view based on the currently entered directory.
454      */

455     private void resetSelection() {
456         MinimizedFileSystemElement currentRoot = getFileSystemTree();
457         selectionGroup.setRoot(currentRoot);
458         
459         if (className.length() != 0) {
460             StringTokenizer JavaDoc tokenizer= new StringTokenizer JavaDoc(className, "."); //$NON-NLS-1$
461
selectClass(currentRoot, tokenizer);
462         }
463     }
464     
465     private void selectClass(MinimizedFileSystemElement currentParent, StringTokenizer JavaDoc tokenizer) {
466         if (!tokenizer.hasMoreTokens()) {
467             return;
468         }
469         List JavaDoc folders= currentParent.getFolders(currentProvider);
470         if (folders.size() == 1) {
471             MinimizedFileSystemElement element = (MinimizedFileSystemElement)folders.get(0);
472             if (element.getLabel(null).equals("/")) { //$NON-NLS-1$
473
selectionGroup.selectAndRevealFolder(element);
474                 selectClass(element, tokenizer);
475                 return;
476             }
477         }
478         String JavaDoc currentName= tokenizer.nextToken();
479         if (tokenizer.hasMoreTokens()) {
480             Iterator JavaDoc allFolders= folders.iterator();
481             while (allFolders.hasNext()) {
482                 MinimizedFileSystemElement folder = (MinimizedFileSystemElement) allFolders.next();
483                 if (folder.getLabel(null).equals(currentName)) {
484                     selectionGroup.selectAndRevealFolder(folder);
485                     selectClass(folder, tokenizer);
486                     return;
487                 }
488             }
489         } else {
490             List JavaDoc files= currentParent.getFiles(currentProvider);
491             Iterator JavaDoc iter= files.iterator();
492             while (iter.hasNext()) {
493                 MinimizedFileSystemElement file = (MinimizedFileSystemElement) iter.next();
494                 if (file.getLabel(null).equals(currentName + ".class")) { //$NON-NLS-1$
495
selectionGroup.selectAndRevealFile(file);
496                     return;
497                 }
498             }
499         }
500     }
501
502     /**
503      * Returns a content provider for <code>MinimizedFileSystemElement</code>s that returns
504      * only files as children.
505      */

506     private ITreeContentProvider getFileProvider() {
507         return new WorkbenchContentProvider() {
508             public Object JavaDoc[] getChildren(Object JavaDoc o) {
509                 if (o instanceof MinimizedFileSystemElement) {
510                     MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
511                     return element.getFiles(currentProvider).toArray();
512                 }
513                 return new Object JavaDoc[0];
514             }
515         };
516     }
517
518     /**
519      * Returns a content provider for <code>MinimizedFileSystemElement</code>s that returns
520      * only folders as children.
521      */

522     private ITreeContentProvider getFolderProvider() {
523         return new WorkbenchContentProvider() {
524             public Object JavaDoc[] getChildren(Object JavaDoc o) {
525                 if (o instanceof MinimizedFileSystemElement) {
526                     MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
527                     return element.getFolders(currentProvider).toArray();
528                 }
529                 return new Object JavaDoc[0];
530             }
531             public boolean hasChildren(Object JavaDoc o) {
532                 if (o instanceof MinimizedFileSystemElement) {
533                     MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
534                     if (element.isPopulated()) {
535                         return getChildren(element).length > 0;
536                     }
537                     
538                     //If we have not populated then wait until asked
539
return true;
540                 }
541                 return false;
542             }
543         };
544     }
545
546     /* (non-Javadoc)
547      * @see org.eclipse.jface.dialogs.Dialog#cancelPressed()
548      */

549     protected void cancelPressed() {
550         clearProviderCache();
551         super.cancelPressed();
552     }
553
554     /* (non-Javadoc)
555      * @see org.eclipse.jface.dialogs.Dialog#okPressed()
556      */

557     protected void okPressed() {
558         clearProviderCache();
559         name= nameField.getText().trim();
560         library= (ClasspathEntry)libraryEntries.get(sourceNameField.getSelectionIndex());
561         IStructuredSelection selection= this.selectionGroup.getListTableSelection();
562         MinimizedFileSystemElement element= (MinimizedFileSystemElement)selection.getFirstElement();
563         if (element == null) {
564             super.okPressed();
565             return;
566         }
567         Object JavaDoc file= element.getFileSystemObject();
568         if (file instanceof ZipEntry JavaDoc) {
569             className= ((ZipEntry JavaDoc)file).getName();
570         } else {
571             className= ((File JavaDoc)file).getAbsolutePath();
572             IPath classPath= new Path(className);
573             IPath libraryPath= new Path(library.getEntryURL().getPath());
574             int matching= classPath.matchingFirstSegments(libraryPath);
575             classPath= classPath.removeFirstSegments(matching);
576             classPath= classPath.setDevice(null);
577             className= classPath.toString();
578         }
579         int index= className.lastIndexOf('.');
580         className= className.substring(0, index);
581         className= className.replace('/', '.');
582         super.okPressed();
583     }
584     
585     protected String JavaDoc getName() {
586         return name;
587     }
588     
589     protected void setName(String JavaDoc name) {
590         this.name= name;
591     }
592     
593     protected void setLibraryEntry(IAntClasspathEntry library) {
594         this.library= library;
595         editing= true;
596     }
597     
598     protected IAntClasspathEntry getLibraryEntry() {
599         return this.library;
600     }
601     
602     protected String JavaDoc getClassName() {
603         return className;
604     }
605     
606     protected void setClassName(String JavaDoc className) {
607         this.className= className;
608     }
609     
610     /* (non-Javadoc)
611      * @see org.eclipse.jface.window.Window#create()
612      */

613     public void create() {
614         super.create();
615         getButton(IDialogConstants.OK_ID).setEnabled(!(library == null));
616     }
617     
618     protected void setAlreadyExistsErrorMsg(String JavaDoc alreadyExistsErrorMsg) {
619         this.alreadyExistsErrorMsg = alreadyExistsErrorMsg;
620     }
621
622     protected void setNoNameErrorMsg(String JavaDoc noNameErrorMsg) {
623         this.noNameErrorMsg = noNameErrorMsg;
624     }
625 }
626
Popular Tags