KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > ide > dialogs > CreateLinkedResourceGroup


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

11
12 package org.eclipse.ui.internal.ide.dialogs;
13
14 import java.net.URI JavaDoc;
15 import java.net.URISyntaxException JavaDoc;
16 import org.eclipse.core.filesystem.EFS;
17 import org.eclipse.core.filesystem.IFileInfo;
18 import org.eclipse.core.filesystem.IFileStore;
19 import org.eclipse.core.filesystem.URIUtil;
20 import org.eclipse.core.resources.IPathVariableManager;
21 import org.eclipse.core.resources.IResource;
22 import org.eclipse.core.resources.IWorkspace;
23 import org.eclipse.core.resources.ResourcesPlugin;
24 import org.eclipse.core.runtime.IPath;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.Path;
27 import org.eclipse.core.runtime.Status;
28 import org.eclipse.jface.dialogs.Dialog;
29 import org.eclipse.jface.dialogs.IDialogConstants;
30 import org.eclipse.swt.SWT;
31 import org.eclipse.swt.events.ModifyEvent;
32 import org.eclipse.swt.events.ModifyListener;
33 import org.eclipse.swt.events.SelectionAdapter;
34 import org.eclipse.swt.events.SelectionEvent;
35 import org.eclipse.swt.events.SelectionListener;
36 import org.eclipse.swt.graphics.Font;
37 import org.eclipse.swt.graphics.FontMetrics;
38 import org.eclipse.swt.graphics.GC;
39 import org.eclipse.swt.layout.GridData;
40 import org.eclipse.swt.layout.GridLayout;
41 import org.eclipse.swt.widgets.Button;
42 import org.eclipse.swt.widgets.Composite;
43 import org.eclipse.swt.widgets.Control;
44 import org.eclipse.swt.widgets.DirectoryDialog;
45 import org.eclipse.swt.widgets.Event;
46 import org.eclipse.swt.widgets.FileDialog;
47 import org.eclipse.swt.widgets.Label;
48 import org.eclipse.swt.widgets.Listener;
49 import org.eclipse.swt.widgets.Text;
50 import org.eclipse.ui.ide.dialogs.PathVariableSelectionDialog;
51 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
52 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
53 import org.eclipse.ui.internal.ide.filesystem.FileSystemConfiguration;
54 import org.eclipse.ui.internal.ide.filesystem.FileSystemSupportRegistry;
55
56 /**
57  * Widget group for specifying a linked file or folder target.
58  *
59  * @since 2.1
60  */

61 public class CreateLinkedResourceGroup {
62     private Listener listener;
63
64     private String JavaDoc linkTarget = ""; //$NON-NLS-1$
65

66     private int type;
67
68     private boolean createLink = false;
69
70     // used to compute layout sizes
71
private FontMetrics fontMetrics;
72
73     // widgets
74
private Composite groupComposite;
75
76     private Text linkTargetField;
77
78     private Button browseButton;
79
80     private Button variablesButton;
81
82     private Label resolvedPathLabelText;
83
84     private Label resolvedPathLabelData;
85
86     private final IStringValue updatableResourceName;
87
88     /**
89      * Helper interface intended for updating a string value based on the
90      * currently selected link target.
91      *
92      * @since 3.2
93      */

94     public static interface IStringValue {
95         /**
96          * Sets the String value.
97          *
98          * @param string
99          * a non-null String
100          */

101         void setValue(String JavaDoc string);
102
103         /**
104          * Gets the String value.
105          *
106          * @return the current value, or <code>null</code>
107          */

108         String JavaDoc getValue();
109     }
110
111     private String JavaDoc lastUpdatedValue;
112
113     private FileSystemSelectionArea fileSystemSelectionArea;
114
115     /**
116      * Creates a link target group
117      *
118      * @param type
119      * specifies the type of resource to link to.
120      * <code>IResource.FILE</code> or <code>IResource.FOLDER</code>
121      * @param listener
122      * listener to notify when one of the widgets' value is changed.
123      * @param updatableResourceName
124      * an updatable string value that will be updated to reflect the
125      * link target's last segment, or <code>null</code>. Updating
126      * will only happen if the current value of that string is null
127      * or the empty string, or if it has not been changed since the
128      * last time it was updated.
129      */

130     public CreateLinkedResourceGroup(int type, Listener listener,
131             IStringValue updatableResourceName) {
132         this.type = type;
133         this.listener = listener;
134         this.updatableResourceName = updatableResourceName;
135         if (updatableResourceName != null) {
136             lastUpdatedValue = updatableResourceName.getValue();
137         }
138     }
139
140     /**
141      * Creates the widgets
142      *
143      * @param parent
144      * parent composite of the widget group
145      * @return the widget group
146      */

147     public Composite createContents(Composite parent) {
148         Font font = parent.getFont();
149         initializeDialogUnits(parent);
150         // top level group
151
groupComposite = new Composite(parent, SWT.NONE);
152         GridLayout layout = new GridLayout();
153         groupComposite.setLayout(layout);
154         groupComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL
155                 | GridData.FILL_HORIZONTAL));
156         groupComposite.setFont(font);
157
158         final Button createLinkButton = new Button(groupComposite, SWT.CHECK);
159         if (type == IResource.FILE) {
160             createLinkButton
161                     .setText(IDEWorkbenchMessages.CreateLinkedResourceGroup_linkFileButton);
162         } else {
163             createLinkButton
164                     .setText(IDEWorkbenchMessages.CreateLinkedResourceGroup_linkFolderButton);
165         }
166         createLinkButton.setSelection(createLink);
167         createLinkButton.setFont(font);
168         SelectionListener selectionListener = new SelectionAdapter() {
169             public void widgetSelected(SelectionEvent e) {
170                 createLink = createLinkButton.getSelection();
171                 browseButton.setEnabled(createLink);
172                 variablesButton.setEnabled(createLink);
173                 // Set the required field color if the field is enabled
174
linkTargetField.setEnabled(createLink);
175                 if (fileSystemSelectionArea != null)
176                     fileSystemSelectionArea.setEnabled(createLink);
177
178                 if (listener != null) {
179                     listener.handleEvent(new Event());
180                 }
181             }
182         };
183         createLinkButton.addSelectionListener(selectionListener);
184
185         createLinkLocationGroup(groupComposite, createLink);
186         return groupComposite;
187     }
188
189     /**
190      * Creates the link target location widgets.
191      *
192      * @param locationGroup
193      * the parent composite
194      * @param enabled
195      * sets the initial enabled state of the widgets
196      */

197     private void createLinkLocationGroup(Composite locationGroup,
198             boolean enabled) {
199         Button button = new Button(locationGroup, SWT.CHECK);
200         int indent = button.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
201
202         button.dispose();
203
204         // linkTargetGroup is necessary to decouple layout from
205
// resolvedPathGroup layout
206
Composite linkTargetGroup = new Composite(locationGroup, SWT.NONE);
207         GridLayout layout = new GridLayout();
208         layout.numColumns = 4;
209         layout.marginHeight = 0;
210         layout.marginWidth = 0;
211         linkTargetGroup.setLayout(layout);
212         GridData data = new GridData(GridData.FILL_HORIZONTAL);
213         data.horizontalIndent = indent;
214         linkTargetGroup.setLayoutData(data);
215
216         // link target location entry field
217
linkTargetField = new Text(linkTargetGroup, SWT.BORDER);
218         data = new GridData(GridData.FILL_HORIZONTAL);
219         data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
220         data.horizontalSpan = 2;
221         linkTargetField.setLayoutData(data);
222         linkTargetField.setEnabled(enabled);
223         linkTargetField.addModifyListener(new ModifyListener() {
224             public void modifyText(ModifyEvent e) {
225                 linkTarget = linkTargetField.getText();
226                 resolveVariable();
227                 if (updatableResourceName != null) {
228                     String JavaDoc value = updatableResourceName.getValue();
229                     if (value == null
230                             || value.equals("") || value.equals(lastUpdatedValue)) { //$NON-NLS-1$
231
IPath linkTargetPath = new Path(linkTarget);
232                         String JavaDoc lastSegment = linkTargetPath.lastSegment();
233                         if (lastSegment != null) {
234                             lastUpdatedValue = lastSegment;
235                             updatableResourceName.setValue(lastSegment);
236                         }
237                     }
238                 }
239                 if (listener != null) {
240                     listener.handleEvent(new Event());
241                 }
242             }
243         });
244
245         // browse button
246
browseButton = new Button(linkTargetGroup, SWT.PUSH);
247         browseButton
248                 .setText(IDEWorkbenchMessages.CreateLinkedResourceGroup_browseButton);
249         browseButton.addSelectionListener(new SelectionAdapter() {
250             public void widgetSelected(SelectionEvent event) {
251                 handleLinkTargetBrowseButtonPressed();
252             }
253         });
254         browseButton.setEnabled(enabled);
255         setButtonLayoutData(browseButton);
256
257         // variables button
258
variablesButton = new Button(linkTargetGroup, SWT.PUSH);
259         variablesButton
260                 .setText(IDEWorkbenchMessages.CreateLinkedResourceGroup_variablesButton);
261         variablesButton.addSelectionListener(new SelectionAdapter() {
262             public void widgetSelected(SelectionEvent event) {
263                 handleVariablesButtonPressed();
264             }
265         });
266         variablesButton.setEnabled(enabled);
267         setButtonLayoutData(variablesButton);
268
269         createFileSystemSelection(linkTargetGroup, enabled);
270
271         createResolvedPathGroup(locationGroup, indent);
272
273         if (linkTarget != null) {
274             linkTargetField.setText(linkTarget);
275         }
276     }
277
278     /**
279      * Create the file system selection area.
280      *
281      * @param composite
282      * @param enabled
283      * the initial enablement state.
284      */

285     private void createFileSystemSelection(Composite composite, boolean enabled) {
286
287         // Always use the default if that is all there is.
288
if (FileSystemSupportRegistry.getInstance().hasOneFileSystem()) {
289             return;
290         }
291
292         fileSystemSelectionArea = new FileSystemSelectionArea();
293         fileSystemSelectionArea.createContents(composite);
294         fileSystemSelectionArea.setEnabled(enabled);
295     }
296
297     /**
298      * Create the composite for the resolved path.
299      *
300      * @param locationGroup
301      * @param indent
302      */

303     private void createResolvedPathGroup(Composite locationGroup, int indent) {
304         GridLayout layout;
305         GridData data;
306         Composite resolvedPathGroup = new Composite(locationGroup, SWT.NONE);
307         layout = new GridLayout();
308         layout.numColumns = 2;
309         layout.marginHeight = 0;
310         layout.marginWidth = 0;
311         resolvedPathGroup.setLayout(layout);
312         data = new GridData(GridData.FILL_HORIZONTAL);
313         data.horizontalIndent = indent;
314         resolvedPathGroup.setLayoutData(data);
315
316         resolvedPathLabelText = new Label(resolvedPathGroup, SWT.SINGLE);
317         resolvedPathLabelText
318                 .setText(IDEWorkbenchMessages.CreateLinkedResourceGroup_resolvedPathLabel);
319         resolvedPathLabelText.setVisible(false);
320
321         resolvedPathLabelData = new Label(resolvedPathGroup, SWT.SINGLE);
322         data = new GridData(GridData.FILL_HORIZONTAL);
323         resolvedPathLabelData.setLayoutData(data);
324         resolvedPathLabelData.setVisible(false);
325     }
326
327     /**
328      * Returns a new status object with the given severity and message.
329      *
330      * @return a new status object with the given severity and message.
331      */

332     private IStatus createStatus(int severity, String JavaDoc message) {
333         return new Status(severity, IDEWorkbenchPlugin.getDefault().getBundle()
334                 .getSymbolicName(), severity, message, null);
335     }
336
337     /**
338      * Disposes the group's widgets.
339      */

340     public void dispose() {
341         if (groupComposite != null && groupComposite.isDisposed() == false) {
342             groupComposite.dispose();
343         }
344     }
345
346     /**
347      * Returns the link target location entered by the user.
348      *
349      * @return the link target location entered by the user. null if the user
350      * chose not to create a link.
351      */

352     public URI JavaDoc getLinkTargetURI() {
353         if (!createLink)
354             return null;
355         // resolve path variable if we have a relative path
356
if (!linkTarget.startsWith("/")) { //$NON-NLS-1$
357
IPathVariableManager pathVariableManager = ResourcesPlugin
358                     .getWorkspace().getPathVariableManager();
359             try {
360                 
361                 URI JavaDoc path = new URI JavaDoc(linkTarget.replace(java.io.File.separatorChar, '/'));
362                 URI JavaDoc resolved = pathVariableManager.resolveURI(path);
363                 if (path != resolved) {
364                     // we know this is a path variable, but return unresolved
365
// path so resource will be created with variable intact
366
return path;
367                 }
368             } catch (URISyntaxException JavaDoc e) {
369                 // link target is not a valid URI. Fall through to handle this
370
// below
371
}
372         }
373
374         FileSystemConfiguration configuration = getSelectedConfiguration();
375         if (configuration == null) {
376             return URIUtil.toURI(linkTarget);
377         }
378         // validate non-local file system location
379
return configuration.getContributor().getURI(linkTarget);
380     }
381
382     /**
383      * Opens a file or directory browser depending on the link type.
384      */

385     private void handleLinkTargetBrowseButtonPressed() {
386         IFileStore store = null;
387         String JavaDoc selection = null;
388         FileSystemConfiguration config = getSelectedConfiguration();
389         boolean isDefault = config == null
390                 || (FileSystemSupportRegistry.getInstance()
391                         .getDefaultConfiguration()).equals(config);
392
393         if (linkTarget.length() > 0) {
394             store = IDEResourceInfoUtils.getFileStore(linkTarget);
395             if (!store.fetchInfo().exists()) {
396                 store = null;
397             }
398         }
399         if (type == IResource.FILE) {
400             if (isDefault) {
401                 FileDialog dialog = new FileDialog(linkTargetField.getShell());
402                 if (store != null) {
403                     if (store.fetchInfo().isDirectory()) {
404                         dialog.setFilterPath(linkTarget);
405                     } else {
406                         dialog.setFileName(linkTarget);
407                     }
408                 }
409                 selection = dialog.open();
410             } else {
411                 URI JavaDoc uri = config.getContributor().browseFileSystem(linkTarget,
412                         linkTargetField.getShell());
413                 if (uri != null)
414                     selection = uri.toString();
415             }
416         } else {
417             String JavaDoc filterPath = null;
418             if (store != null) {
419                 IFileStore path = store;
420                 if (!store.fetchInfo().isDirectory()) {
421                     path = store.getParent();
422                 }
423                 if (path != null) {
424                     filterPath = store.toString();
425                 }
426             }
427
428             if (isDefault) {
429                 DirectoryDialog dialog = new DirectoryDialog(linkTargetField
430                         .getShell());
431                 dialog
432                         .setMessage(IDEWorkbenchMessages.CreateLinkedResourceGroup_targetSelectionLabel);
433                 if (filterPath != null)
434                     dialog.setFilterPath(filterPath);
435                 selection = dialog.open();
436             } else {
437                 String JavaDoc initialPath = IDEResourceInfoUtils.EMPTY_STRING;
438                 if (filterPath != null)
439                     initialPath = filterPath;
440                 URI JavaDoc uri = config.getContributor().browseFileSystem(initialPath,
441                         linkTargetField.getShell());
442                 if (uri != null)
443                     selection = uri.toString();
444             }
445         }
446         if (selection != null) {
447             linkTargetField.setText(selection);
448         }
449     }
450
451     /**
452      * Return the selected configuration or <code>null</code> if there is not
453      * one selected.
454      *
455      * @return FileSystemConfiguration or <code>null</code>
456      */

457     private FileSystemConfiguration getSelectedConfiguration() {
458         if (fileSystemSelectionArea == null)
459             return null;
460         return fileSystemSelectionArea.getSelectedConfiguration();
461     }
462
463     /**
464      * Opens a path variable selection dialog
465      */

466     private void handleVariablesButtonPressed() {
467         int variableTypes = IResource.FOLDER;
468
469         // allow selecting file and folder variables when creating a
470
// linked file
471
if (type == IResource.FILE) {
472             variableTypes |= IResource.FILE;
473         }
474
475         PathVariableSelectionDialog dialog = new PathVariableSelectionDialog(
476                 linkTargetField.getShell(), variableTypes);
477         if (dialog.open() == IDialogConstants.OK_ID) {
478             String JavaDoc[] variableNames = (String JavaDoc[]) dialog.getResult();
479             if (variableNames != null && variableNames.length == 1) {
480                 linkTargetField.setText(variableNames[0]);
481             }
482         }
483     }
484
485     /**
486      * Initializes the computation of horizontal and vertical dialog units based
487      * on the size of current font.
488      * <p>
489      * This method must be called before <code>setButtonLayoutData</code> is
490      * called.
491      * </p>
492      *
493      * @param control
494      * a control from which to obtain the current font
495      */

496     protected void initializeDialogUnits(Control control) {
497         // Compute and store a font metric
498
GC gc = new GC(control);
499         gc.setFont(control.getFont());
500         fontMetrics = gc.getFontMetrics();
501         gc.dispose();
502     }
503
504     /**
505      * Tries to resolve the value entered in the link target field as a
506      * variable, if the value is a relative path. Displays the resolved value if
507      * the entered value is a variable.
508      */

509     private void resolveVariable() {
510         IPathVariableManager pathVariableManager = ResourcesPlugin
511                 .getWorkspace().getPathVariableManager();
512         IPath path = new Path(linkTarget);
513         IPath resolvedPath = pathVariableManager.resolvePath(path);
514
515         if (path.equals(resolvedPath)) {
516             resolvedPathLabelText.setVisible(false);
517             resolvedPathLabelData.setVisible(false);
518         } else {
519             resolvedPathLabelText.setVisible(true);
520             resolvedPathLabelData.setVisible(true);
521         }
522         resolvedPathLabelData.setText(resolvedPath.toOSString());
523     }
524
525     /**
526      * Sets the <code>GridData</code> on the specified button to be one that
527      * is spaced for the current dialog page units. The method
528      * <code>initializeDialogUnits</code> must be called once before calling
529      * this method for the first time.
530      *
531      * @param button
532      * the button to set the <code>GridData</code>
533      * @return the <code>GridData</code> set on the specified button
534      */

535     private GridData setButtonLayoutData(Button button) {
536         GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
537         int widthHint = Dialog.convertHorizontalDLUsToPixels(fontMetrics,
538                 IDialogConstants.BUTTON_WIDTH);
539         data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT,
540                 SWT.DEFAULT, true).x);
541         button.setLayoutData(data);
542         return data;
543     }
544
545     /**
546      * Sets the value of the link target field
547      *
548      * @param target
549      * the value of the link target field
550      */

551     public void setLinkTarget(String JavaDoc target) {
552         linkTarget = target;
553         if (linkTargetField != null && linkTargetField.isDisposed() == false) {
554             linkTargetField.setText(target);
555         }
556     }
557
558     /**
559      * Validates the type of the given file against the link type specified in
560      * the constructor.
561      *
562      * @param linkTargetFile
563      * file to validate
564      * @return IStatus indicating the validation result. IStatus.OK if the given
565      * file is valid.
566      */

567     private IStatus validateFileType(IFileInfo linkTargetFile) {
568         if (type == IResource.FILE && linkTargetFile.isDirectory()) {
569             return createStatus(
570                     IStatus.ERROR,
571                     IDEWorkbenchMessages.CreateLinkedResourceGroup_linkTargetNotFile);
572         } else if (type == IResource.FOLDER && !linkTargetFile.isDirectory()) {
573             return createStatus(
574                     IStatus.ERROR,
575                     IDEWorkbenchMessages.CreateLinkedResourceGroup_linkTargetNotFolder);
576         }
577         return Status.OK_STATUS;
578     }
579
580     /**
581      * Validates this page's controls.
582      *
583      * @param linkHandle
584      * The target to check
585      *
586      * @return IStatus indicating the validation result. IStatus.OK if the
587      * specified link target is valid given the linkHandle.
588      */

589     public IStatus validateLinkLocation(IResource linkHandle) {
590         if (linkTargetField == null || linkTargetField.isDisposed()
591                 || !createLink) {
592             return Status.OK_STATUS;
593         }
594         IWorkspace workspace = IDEWorkbenchPlugin.getPluginWorkspace();
595         FileSystemConfiguration configuration = getSelectedConfiguration();
596         if (configuration == null
597                 || EFS.SCHEME_FILE.equals(configuration.getScheme())) {
598             // Special handling for UNC paths. See bug 90825
599
IPath location = new Path(linkTarget);
600             if (location.isUNC()) {
601                 return createStatus(
602                         IStatus.WARNING,
603                         IDEWorkbenchMessages.CreateLinkedResourceGroup_unableToValidateLinkTarget);
604             }
605         }
606         URI JavaDoc locationURI = getLinkTargetURI();
607         IStatus locationStatus = workspace.validateLinkLocationURI(linkHandle,
608                 locationURI);
609         if (locationStatus.getSeverity() == IStatus.ERROR) {
610             return locationStatus;
611         }
612
613         // use the resolved link target name
614
URI JavaDoc resolved = workspace.getPathVariableManager().resolveURI(
615                 locationURI);
616         IFileInfo linkTargetFile = IDEResourceInfoUtils.getFileInfo(resolved);
617         if (linkTargetFile != null && linkTargetFile.exists()) {
618             IStatus fileTypeStatus = validateFileType(linkTargetFile);
619             if (!fileTypeStatus.isOK()) {
620                 return fileTypeStatus;
621             }
622         } else if (locationStatus.isOK()) {
623             // locationStatus takes precedence over missing location warning.
624
return createStatus(
625                     IStatus.WARNING,
626                     IDEWorkbenchMessages.CreateLinkedResourceGroup_linkTargetNonExistent);
627         }
628         return locationStatus;
629     }
630 }
631
Popular Tags