KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > pde > internal > ui > editor > plugin > BundleSourcePage


1 /*******************************************************************************
2  * Copyright (c) 2003, 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 package org.eclipse.pde.internal.ui.editor.plugin;
12 import java.util.ArrayList JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.jface.action.IMenuManager;
18 import org.eclipse.jface.text.BadLocationException;
19 import org.eclipse.jface.text.ITextSelection;
20 import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
21 import org.eclipse.jface.viewers.ILabelProvider;
22 import org.eclipse.jface.viewers.ISelection;
23 import org.eclipse.jface.viewers.ITreeContentProvider;
24 import org.eclipse.jface.viewers.LabelProvider;
25 import org.eclipse.jface.viewers.SelectionChangedEvent;
26 import org.eclipse.osgi.util.NLS;
27 import org.eclipse.pde.core.IBaseModel;
28 import org.eclipse.pde.core.plugin.IPluginLibrary;
29 import org.eclipse.pde.core.plugin.IPluginModelBase;
30 import org.eclipse.pde.internal.core.ibundle.IBundleModel;
31 import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase;
32 import org.eclipse.pde.internal.core.ibundle.IManifestHeader;
33 import org.eclipse.pde.internal.core.plugin.ImportObject;
34 import org.eclipse.pde.internal.core.text.AbstractEditingModel;
35 import org.eclipse.pde.internal.core.text.IDocumentKey;
36 import org.eclipse.pde.internal.core.text.IDocumentRange;
37 import org.eclipse.pde.internal.core.text.IEditingModel;
38 import org.eclipse.pde.internal.core.text.bundle.Bundle;
39 import org.eclipse.pde.internal.core.text.bundle.BundleClasspathHeader;
40 import org.eclipse.pde.internal.core.text.bundle.BundleModel;
41 import org.eclipse.pde.internal.core.text.bundle.BundleSymbolicNameHeader;
42 import org.eclipse.pde.internal.core.text.bundle.CompositeManifestHeader;
43 import org.eclipse.pde.internal.core.text.bundle.ExecutionEnvironment;
44 import org.eclipse.pde.internal.core.text.bundle.ExportPackageHeader;
45 import org.eclipse.pde.internal.core.text.bundle.ExportPackageObject;
46 import org.eclipse.pde.internal.core.text.bundle.ImportPackageHeader;
47 import org.eclipse.pde.internal.core.text.bundle.ImportPackageObject;
48 import org.eclipse.pde.internal.core.text.bundle.ManifestHeader;
49 import org.eclipse.pde.internal.core.text.bundle.PDEManifestElement;
50 import org.eclipse.pde.internal.core.text.bundle.PackageObject;
51 import org.eclipse.pde.internal.core.text.bundle.RequireBundleHeader;
52 import org.eclipse.pde.internal.core.text.bundle.RequireBundleObject;
53 import org.eclipse.pde.internal.core.text.bundle.RequiredExecutionEnvironmentHeader;
54 import org.eclipse.pde.internal.ui.PDELabelProvider;
55 import org.eclipse.pde.internal.ui.PDEPlugin;
56 import org.eclipse.pde.internal.ui.PDEPluginImages;
57 import org.eclipse.pde.internal.ui.PDEUIMessages;
58 import org.eclipse.pde.internal.ui.editor.KeyValueSourcePage;
59 import org.eclipse.pde.internal.ui.editor.PDEFormEditor;
60 import org.eclipse.pde.internal.ui.editor.actions.PDEActionConstants;
61 import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
62 import org.eclipse.pde.internal.ui.refactoring.RenamePluginAction;
63 import org.eclipse.pde.internal.ui.util.SharedLabelProvider;
64 import org.eclipse.swt.custom.StyledText;
65 import org.eclipse.swt.graphics.Image;
66 import org.eclipse.swt.graphics.Point;
67 import org.eclipse.ui.forms.editor.FormEditor;
68 import org.osgi.framework.Constants;
69
70 public class BundleSourcePage extends KeyValueSourcePage {
71
72     /**
73      * Used to set the selection in the outline view with the link with editor
74      * feature is enabled
75      * Cannot use a document range object because manifest header elements
76      * do not have ranges associated with them in the bundle model
77      */

78     private Object JavaDoc fTargetOutlineSelection;
79     
80     /**
81      * Offset used to set the current highlight range.
82      * Used to prevent cyclic event firing when a selection is made in the
83      * outline view with the link with editor feature on. When a selection
84      * is made in the source viewer, an event is fired back to the outline
85      * view to unnecessarily update the selection.
86      */

87     private int fCurrentHighlightRangeOffset;
88     
89     private final int F_NOT_SET = -1;
90     
91     private RenamePluginAction fRenameAction;
92     
93     /**
94      * BundleOutlineContentProvider
95      *
96      */

97     private class BundleOutlineContentProvider extends DefaultContentProvider
98             implements ITreeContentProvider {
99         
100         public Object JavaDoc[] getChildren(Object JavaDoc parent) {
101             // Need an identifying class for label provider
102
if (parent instanceof ImportPackageHeader) {
103                 return ((ImportPackageHeader)parent).getPackages();
104             } else if (parent instanceof ExportPackageHeader) {
105                 return ((ExportPackageHeader)parent).getPackages();
106             } else if (parent instanceof RequiredExecutionEnvironmentHeader) {
107                 return ((RequiredExecutionEnvironmentHeader)parent).getEnvironments();
108             } else if (parent instanceof RequireBundleHeader) {
109                 return ((RequireBundleHeader)parent).getRequiredBundles();
110             } else if (parent instanceof BundleClasspathHeader) {
111                 return getPluginLibraries();
112             }
113             return new Object JavaDoc[0];
114         }
115         
116         private Object JavaDoc[] getPluginLibraries() {
117             IPluginLibrary[] libraries = getBundleClasspathLibraries();
118             if ((libraries == null) ||
119                     (libraries.length == 0)) {
120                 return new Object JavaDoc[0];
121             }
122             return libraries;
123         }
124         
125         public boolean hasChildren(Object JavaDoc parent) {
126             return getChildren(parent).length > 0;
127         }
128         public Object JavaDoc getParent(Object JavaDoc child) {
129             return null;
130         }
131         public Object JavaDoc[] getElements(Object JavaDoc parent) {
132             if (parent instanceof BundleModel) {
133                 BundleModel model = (BundleModel) parent;
134                 Map JavaDoc manifest = ((Bundle)model.getBundle()).getHeaders();
135                 ArrayList JavaDoc keys = new ArrayList JavaDoc();
136                 for (Iterator JavaDoc elements = manifest.keySet().iterator(); elements.hasNext();) {
137                     IDocumentKey key = (IDocumentKey) manifest.get(elements.next());
138                     if (key.getOffset() > -1)
139                         keys.add(key);
140                 }
141                 return keys.toArray();
142             }
143             return new Object JavaDoc[0];
144         }
145     }
146     
147     /**
148      * @return
149      */

150     private IPluginLibrary[] getBundleClasspathLibraries() {
151         // The bundle classpath header has no model data members
152
// Retrieve the plug-in library equivalents from the editor model
153
FormEditor editor = getEditor();
154         if (editor instanceof PDEFormEditor) {
155             PDEFormEditor formEditor = (PDEFormEditor)editor;
156             IBaseModel baseModel = formEditor.getAggregateModel();
157             if (baseModel instanceof IPluginModelBase) {
158                 IPluginLibrary[] libraries =
159                     ((IPluginModelBase)baseModel).getPluginBase().getLibraries();
160                 return libraries;
161             }
162         }
163         return null;
164     }
165     
166     private class BundleLabelProvider extends LabelProvider {
167         // TODO: MP: QO: LOW: Move to PDELabelProvider
168
public String JavaDoc getText(Object JavaDoc obj) {
169             if (obj instanceof PackageObject) {
170                 return ((PackageObject)obj).getName();
171             } else if (obj instanceof ExecutionEnvironment) {
172                 return ((ExecutionEnvironment)obj).getName();
173             } else if (obj instanceof RequireBundleObject) {
174                 return getTextRequireBundle(((RequireBundleObject)obj));
175             } else if (obj instanceof ManifestHeader) {
176                 return ((ManifestHeader) obj).getName();
177             }
178             return super.getText(obj);
179         }
180         
181         private String JavaDoc getTextRequireBundle(RequireBundleObject bundle) {
182             StringBuffer JavaDoc label = new StringBuffer JavaDoc();
183             // Append the ID
184
label.append(bundle.getId());
185             // Get the version
186
String JavaDoc version = bundle.getVersion();
187             // If there is no version, just return what we have
188
if ((version == null) ||
189                     (version.length() == 0)) {
190                 return label.toString();
191             }
192             // Append a space
193
label.append(' ');
194             // If the first character does not have a range indicator,
195
// add a default one. This can happen when there is only one
196
// value specified for either min or max
197
char firstChar = version.charAt(0);
198             if ((firstChar != '(') &&
199                     (firstChar != '[')) {
200                 label.append('(');
201             }
202             // Append the version
203
label.append(version);
204             // If the last character does not have a range indicator,
205
// add a default one. This can happen when there is only one
206
// value specified for either min or max
207
char lastChar = version.charAt(version.length() - 1);
208             if ((lastChar != ')') &&
209                     (lastChar != ']')) {
210                 label.append(')');
211             }
212             // Return what we have
213
return label.toString();
214         }
215         
216         public Image getImage(Object JavaDoc obj) {
217             PDELabelProvider labelProvider =
218                 PDEPlugin.getDefault().getLabelProvider();
219             if (obj instanceof PackageObject) {
220                 return labelProvider.get(
221                         PDEPluginImages.DESC_PACKAGE_OBJ);
222             } else if (obj instanceof ExecutionEnvironment) {
223                 return labelProvider.get(
224                         PDEPluginImages.DESC_JAVA_LIB_OBJ);
225             } else if (obj instanceof RequireBundleObject) {
226                 int flags = SharedLabelProvider.F_EXTERNAL;
227                 if (((RequireBundleObject)obj).isReexported()) {
228                     flags = flags | SharedLabelProvider.F_EXPORT;
229                 }
230                 return labelProvider.get(PDEPluginImages.DESC_REQ_PLUGIN_OBJ, flags);
231             } else if (obj instanceof ManifestHeader) {
232                 return labelProvider.get(
233                         PDEPluginImages.DESC_BUILD_VAR_OBJ);
234             } else if (obj instanceof IPluginLibrary) {
235                 return labelProvider.get(
236                         PDEPluginImages.DESC_JAVA_LIB_OBJ);
237             }
238             return null;
239         }
240     }
241     
242     /**
243      * @param editor
244      * @param id
245      * @param title
246      */

247     public BundleSourcePage(PDEFormEditor editor, String JavaDoc id, String JavaDoc title) {
248         super(editor, id, title);
249         resetTargetOutlineSelection();
250         resetCurrentHighlightRangeOffset();
251     }
252     
253     /**
254      * @param offset
255      */

256     private void setCurrentHighlightRangeOffset(int offset) {
257         fCurrentHighlightRangeOffset = offset;
258     }
259     
260     /**
261      *
262      */

263     private void resetCurrentHighlightRangeOffset() {
264         fCurrentHighlightRangeOffset = F_NOT_SET;
265     }
266     
267     /**
268      * @return
269      */

270     private int getCurrentHighlightRangeOffset() {
271         return fCurrentHighlightRangeOffset;
272     }
273     
274     /* (non-Javadoc)
275      * @see org.eclipse.ui.texteditor.AbstractTextEditor#resetHighlightRange()
276      */

277     public void resetHighlightRange() {
278         resetCurrentHighlightRangeOffset();
279         super.resetHighlightRange();
280     }
281     
282     /**
283      *
284      */

285     private void resetTargetOutlineSelection() {
286         fTargetOutlineSelection = null;
287     }
288     
289     /**
290      * @param object
291      */

292     private void setTargetOutlineSelection(Object JavaDoc object) {
293         fTargetOutlineSelection = object;
294     }
295     
296     /**
297      * @return
298      */

299     private Object JavaDoc getTargetOutlineSelection() {
300         return fTargetOutlineSelection;
301     }
302     
303     public ILabelProvider createOutlineLabelProvider() {
304         return new BundleLabelProvider();
305     }
306     
307     public ITreeContentProvider createOutlineContentProvider() {
308         return new BundleOutlineContentProvider();
309     }
310     
311     /* (non-Javadoc)
312      * @see org.eclipse.pde.internal.ui.editor.PDESourcePage#getRangeElement(int, boolean)
313      */

314     public IDocumentRange getRangeElement(int offset, boolean searchChildren) {
315         IBundleModel model = (IBundleModel) getInputContext().getModel();
316         Map JavaDoc manifest = ((Bundle) model.getBundle()).getHeaders();
317         // Reset
318
resetTargetOutlineSelection();
319         // Search each manifest header
320
for (Iterator JavaDoc elements = manifest.values().iterator(); elements.hasNext();) {
321             IDocumentRange node = (IDocumentRange) elements.next();
322             // Check to see if the parent is within range
323
if (isWithinCurrentRange(offset, node)) {
324                 // Search the children of composite manifest headers first if
325
// specified
326
if (searchChildren &&
327                         (node instanceof CompositeManifestHeader)) {
328                     IDocumentRange child_node = getRangeElementChild(model, offset,
329                             (CompositeManifestHeader)node);
330                     // If the child node is specified return it; otherwise, we
331
// will default to the parent node
332
if (child_node != null) {
333                         return child_node;
334                     }
335                 }
336                 // A manifest header object can be used both for setting the
337
// highlight range and making a selection in the outline view
338
setTargetOutlineSelection(node);
339                 return node;
340             }
341         }
342         return null;
343     }
344     
345     /**
346      * @param offset
347      * @param range
348      * @return true if the offset is within the range; false, otherwise
349      */

350     private boolean isWithinCurrentRange(int offset, IDocumentRange range) {
351         
352         if (range == null) {
353             // Range not set
354
return false;
355         } else if (offset >= range.getOffset()
356                 && (offset <= (range.getOffset() + range.getLength()))) {
357             // Offset within range
358
return true;
359         }
360         // Offset not within range
361
return false;
362     }
363
364     /**
365      * This method is required because the calculated ranges, do NOT include
366      * their parameters (e.g. x-friends, bundle-version)
367      * @param offset
368      * @param current_range
369      * @param previous_range
370      * @return true if the offset falls in between the end of the previous range
371      * and before the current range (e.g. the previous ranges parameters)
372      */

373     private boolean isWithinPreviousRange(int offset,
374             IDocumentRange current_range, IDocumentRange previous_range) {
375         
376         if ((current_range == null) ||
377                 (previous_range == null)) {
378             // Range not set
379
return false;
380         } else if ((offset >= previous_range.getOffset() + previous_range.getLength()) &&
381                 ((offset <= current_range.getOffset()))) {
382             // Offset within range
383
return true;
384         }
385         // Offset not within range
386
return false;
387     }
388
389     /**
390      * @param offset
391      * @param previousRange
392      * @return
393      */

394     private boolean isBeforePreviousRange(int offset,
395             IDocumentRange previousRange) {
396         
397         if (previousRange == null) {
398             return false;
399         } else if (offset < previousRange.getOffset()) {
400             return true;
401         }
402         return false;
403     }
404     
405     /**
406      * @param model
407      * @param offset
408      * @param header
409      * @return
410      */

411     private IDocumentRange getRangeElementChild(IBundleModel model,
412             int offset, CompositeManifestHeader header) {
413         // Ensure the header has associated elements
414
if (header.isEmpty()) {
415             return null;
416         }
417         // Get the header elements
418
PDEManifestElement[] elements = header.getElements();
419         // Get the header elements name (assume that all elements are the same
420
// as the first element)
421
String JavaDoc headerName = getHeaderName(elements[0]);
422         PDEManifestElement previousElement = null;
423         PDEManifestElement currentElement = null;
424         IDocumentRange previousRange = null;
425         IDocumentRange currentRange = null;
426         // Process each element
427
for (int i = 0; i < elements.length; i++) {
428             currentElement = elements[i];
429             // Find the range for the element
430
currentRange = getSpecificRange(
431                     model,
432                     headerName,
433                     currentElement.getValue());
434             // Determine whether the element is within range
435
if (isBeforePreviousRange(offset, previousRange)) {
436                 return null;
437             } else if (isWithinCurrentRange(offset, currentRange)) {
438                 setChildTargetOutlineSelection(headerName, currentElement);
439                 // Use for setting the highlight range
440
return currentRange;
441             } else if (isWithinPreviousRange(offset, currentRange, previousRange)) {
442                 setChildTargetOutlineSelection(headerName, previousElement);
443                 // Use for setting the highlight range
444
return previousRange;
445             }
446             // Update for the next iteration
447
previousRange = currentRange;
448             previousElement = currentElement;
449         }
450         
451         if (isWithinLastElementParamRange(offset, currentRange, header)) {
452             // No element found within range
453
setChildTargetOutlineSelection(headerName, currentElement);
454             // Use for setting the highlight range
455
return currentRange;
456         }
457         return null;
458     }
459
460     
461     /**
462      * @param offset
463      * @param currentRange
464      * @param headerRange
465      * @return
466      */

467     private boolean isWithinLastElementParamRange(int offset,
468             IDocumentRange currentRange, IDocumentRange headerRange) {
469         if (currentRange == null) {
470             return false;
471         } else if ((offset >= currentRange.getOffset() + currentRange.getLength()) &&
472                 (offset <= (headerRange.getOffset() + headerRange.getLength()))) {
473             return true;
474         }
475         return false;
476     }
477     
478     /**
479      * @param headerName
480      * @param element
481      */

482     private void setChildTargetOutlineSelection(String JavaDoc headerName,
483             PDEManifestElement element) {
484         // Use for setting the outline view selection
485
if (headerName.equalsIgnoreCase(Constants.BUNDLE_CLASSPATH)) {
486             setTargetOutlineSelection(
487                     getBundleClasspathOutlineSelection(element));
488         } else {
489             setTargetOutlineSelection(element);
490         }
491     }
492
493     /**
494      * Edge Case: Cannot use the PDEManifestElement directly to select bundle
495      * classpath elements in the outline view. Need to use IPluginLibrary
496      * objects
497      * @param manifestElement
498      * @return
499      */

500     private Object JavaDoc getBundleClasspathOutlineSelection(
501             PDEManifestElement manifestElement) {
502         
503         IPluginLibrary[] libraries = getBundleClasspathLibraries();
504         // Ensure there are libraries
505
if ((libraries == null) ||
506                 (libraries.length == 0)) {
507             return null;
508         }
509         // Linearly search for the equivalent library object
510
for (int i = 0; i < libraries.length; i++) {
511             if (manifestElement.getValue().equals(libraries[i].getName())) {
512                 // Found
513
return libraries[i];
514             }
515         }
516         // None found
517
return null;
518     }
519
520     /**
521      * @param element
522      * @return
523      */

524     private String JavaDoc getHeaderName(PDEManifestElement element) {
525         if (element instanceof ExportPackageObject) {
526             return Constants.EXPORT_PACKAGE;
527         } else if (element instanceof ImportPackageObject) {
528             return Constants.IMPORT_PACKAGE;
529         } else if (element instanceof ExecutionEnvironment) {
530             return Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT;
531         } else if (element instanceof RequireBundleObject) {
532             return Constants.REQUIRE_BUNDLE;
533         } else {
534             // Bundle classpath elements do not have their own model class
535
// They are created as PDEManifestElements directly whose value
536
// is just a String
537
// Assume that if the element is none of the above types it is this
538
// type
539
return Constants.BUNDLE_CLASSPATH;
540         }
541     }
542     
543     protected String JavaDoc[] collectContextMenuPreferencePages() {
544         String JavaDoc[] ids= super.collectContextMenuPreferencePages();
545         String JavaDoc[] more= new String JavaDoc[ids.length + 1];
546         more[0]= "org.eclipse.pde.ui.EditorPreferencePage"; //$NON-NLS-1$
547
System.arraycopy(ids, 0, more, 1, ids.length);
548         return more;
549     }
550     
551     public IDocumentRange findRange() {
552         if (fSelection instanceof ImportObject) {
553             IPluginModelBase base = ((ImportObject)fSelection).getImport().getPluginModel();
554             if (base instanceof IBundlePluginModelBase)
555                 return getSpecificRange(
556                         ((IBundlePluginModelBase)base).getBundleModel(),
557                         Constants.REQUIRE_BUNDLE,
558                         ((ImportObject)fSelection).getId());
559         } else if (fSelection instanceof ImportPackageObject) {
560             return getSpecificRange(
561                     ((ImportPackageObject)fSelection).getModel(),
562                     Constants.IMPORT_PACKAGE,
563                     ((ImportPackageObject)fSelection).getValue());
564         } else if (fSelection instanceof ExportPackageObject) {
565             return getSpecificRange(
566                     ((ExportPackageObject)fSelection).getModel(),
567                     Constants.EXPORT_PACKAGE,
568                     ((ExportPackageObject)fSelection).getValue());
569         } else if (fSelection instanceof IPluginLibrary) {
570             IPluginModelBase base = ((IPluginLibrary)fSelection).getPluginModel();
571             if (base instanceof IBundlePluginModelBase)
572                 return getSpecificRange(
573                         ((IBundlePluginModelBase)base).getBundleModel(),
574                         Constants.BUNDLE_CLASSPATH,
575                         ((IPluginLibrary)fSelection).getName());
576         } else if (fSelection instanceof ExecutionEnvironment) {
577             return getSpecificRange(
578                     ((ExecutionEnvironment)fSelection).getModel(),
579                     Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT,
580                     ((ExecutionEnvironment)fSelection).getValue());
581         } else if (fSelection instanceof RequireBundleObject) {
582             return getSpecificRange(
583                     ((RequireBundleObject)fSelection).getModel(),
584                     Constants.REQUIRE_BUNDLE,
585                     ((RequireBundleObject)fSelection).getId());
586         }
587         return null;
588     }
589     
590     public static IDocumentRange getSpecificRange(IBundleModel model, IManifestHeader header, String JavaDoc element) {
591         if (header == null || !(model instanceof IEditingModel))
592             return null;
593         
594         final int[] range = new int[] { -1, -1 }; // { offset, length }
595
try {
596             int start = header.getOffset() + header.getName().length();
597             int length = header.getLength() - header.getName().length();
598             String JavaDoc headerValue = ((IEditingModel)model).getDocument().get(start, length);
599             
600             int i = headerValue.indexOf(element);
601             int last = headerValue.lastIndexOf(element);
602             if (i > 0 && i != last) {
603                 char[] sChar = element.toCharArray();
604                 char[] headerChar = headerValue.toCharArray();
605                 headLoop: for (; i <= last; i++) {
606                     // check 1st, middle and last chars to speed things up
607
if (headerChar[i] != sChar[0] &&
608                             headerChar[i + sChar.length / 2] != sChar[sChar.length / 2] &&
609                             headerChar[i + sChar.length - 1] != sChar[sChar.length - 1])
610                         continue headLoop;
611                     
612                     for (int j = 1; j < sChar.length - 1; j++)
613                         if (headerChar[i + j] != sChar[j])
614                             continue headLoop;
615
616                     // found match
617
char c = headerChar[i - 1];
618                     if (!Character.isWhitespace(c) && c != ',')
619                         // search string is contained by another
620
continue headLoop;
621                     
622                     int index = i + sChar.length;
623                     if (index >= headerChar.length) {
624                         // Current match is longer than search
625
// Occurs when match is '.' or a single character
626
continue;
627                     }
628                     c = headerChar[index];
629                     if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '.')
630                         // current match is longer than search
631
continue headLoop;
632                     
633                     break;
634                 }
635             }
636             if (i != -1) {
637                 range[0] = start + i;
638                 range[1] = element.length();
639             }
640         } catch (BadLocationException e) {
641         }
642         if (range[0] == -1) { // if un-set offset use header range
643
range[0] = header.getOffset();
644             // Only select the length of the header name; otherwise, the
645
// header value will be included in the selection
646
range[1] = header.getName().length();
647         }
648         return new IDocumentRange() {
649             public int getOffset() { return range[0]; }
650             public int getLength() { return range[1]; }
651         };
652     }
653     
654     public static IDocumentRange getSpecificRange(IBundleModel model, String JavaDoc headerName, String JavaDoc search) {
655         IManifestHeader header = model.getBundle().getManifestHeader(headerName);
656         return getSpecificRange(model, header, search);
657     }
658
659     protected boolean isSelectionListener() {
660         return true;
661     }
662     
663     public Object JavaDoc getAdapter(Class JavaDoc adapter) {
664         if (IHyperlinkDetector.class.equals(adapter))
665             return new BundleHyperlinkDetector(this);
666         return super.getAdapter(adapter);
667     }
668     
669     /* (non-Javadoc)
670      * @see org.eclipse.pde.internal.ui.editor.PDESourcePage#updateSelection(java.lang.Object)
671      */

672     public void updateSelection(Object JavaDoc object) {
673         // Update the global selection
674
fSelection = object;
675         // Highlight the selection if it is a manifest header
676
if (object instanceof IDocumentKey) {
677             setHighlightRange((IDocumentKey)object);
678             setCurrentHighlightRangeOffset(((IDocumentKey)object).getOffset());
679             // We don't set the selected range because it will cause the
680
// manifest header and all its value to be selected
681
return;
682         }
683         // Handle manifest header values
684
// Determine the selection range
685
IDocumentRange range = findRange();
686         // Ensure there is a range
687
if (range == null) {
688             return;
689         }
690         // Get the model
691
IBaseModel model = getInputContext().getModel();
692         // Ensure we have an editing model
693
if ((model instanceof AbstractEditingModel) == false) {
694             return;
695         }
696         // If the range offset is undefined or the source viewer is dirty,
697
// forcibly adjust the offsets and try to find the range again
698
if ((range.getOffset() == -1) ||
699                 isDirty()) {
700             try {
701                 ((AbstractEditingModel)model).adjustOffsets(
702                         ((AbstractEditingModel)model).getDocument());
703             } catch (CoreException e) {
704                 // Ignore
705
}
706             range = findRange();
707         }
708         // Set the highlight and selected range with whatever we found
709
setCurrentHighlightRangeOffset(range.getOffset());
710         setHighlightRange(range, true);
711         setSelectedRange(range, false);
712     }
713
714     /* (non-Javadoc)
715      * @see org.eclipse.pde.internal.ui.editor.PDESourcePage#handleSelectionChangedSourcePage(org.eclipse.jface.viewers.SelectionChangedEvent)
716      */

717     protected void handleSelectionChangedSourcePage(SelectionChangedEvent event) {
718         ISelection selection = event.getSelection();
719         // Ensure we have a selection
720
if (selection.isEmpty() ||
721                 ((selection instanceof ITextSelection) == false)) {
722             return;
723         }
724         // If the page has been edited, adjust the offsets; otherwise, our
725
// caculated ranges will be out of sync
726
IBaseModel model = getInputContext().getModel();
727         if (model instanceof AbstractEditingModel
728                 && isDirty()) {
729             try {
730                 ((AbstractEditingModel)model).adjustOffsets(
731                         ((AbstractEditingModel)model).getDocument());
732             } catch (CoreException e) {
733                 // Ignore
734
}
735         }
736         // Synchronize using the current cursor position in this page
737
synchronizeOutlinePage(((ITextSelection) selection).getOffset());
738     }
739     
740     /* (non-Javadoc)
741      * @see org.eclipse.pde.internal.ui.editor.PDESourcePage#synchronizeOutlinePage(int)
742      */

743     protected void synchronizeOutlinePage(int offset) {
744         // Prevent cyclical firing of events between source page and outline
745
// view
746
// If the previous offset is the same as the current offset, then
747
// the selection does not need to be updated in the outline view
748
int previous_offset = getCurrentHighlightRangeOffset();
749         if (previous_offset == offset) {
750             return;
751         }
752         // Find the range header (parent) or element (children) within range of
753
// the text selection offset
754
IDocumentRange rangeElement =
755             getRangeElement(offset, true);
756         // Set the highlight range
757
updateHighlightRange(rangeElement);
758         // Set the outline view selection
759
updateOutlinePageSelection(getTargetOutlineSelection());
760     }
761
762     protected void editorContextMenuAboutToShow(IMenuManager menu) {
763         super.editorContextMenuAboutToShow(menu);
764         StyledText text = getViewer().getTextWidget();
765         Point p = text.getSelection();
766         IDocumentRange element = getRangeElement(p.x, false);
767         // only activate rename when user is highlighting Bundle-SymbolicName header
768
if (!(element instanceof BundleSymbolicNameHeader) || !(((BundleSymbolicNameHeader)element).getModel().isEditable()))
769             return;
770         if (fRenameAction == null) {
771             IBaseModel base = ((PDEFormEditor)getEditor()).getAggregateModel();
772             if (base instanceof IPluginModelBase) {
773                 fRenameAction = new RenamePluginAction();
774                 fRenameAction.setText(NLS.bind(PDEUIMessages.BundleSourcePage_renameActionText, Constants.BUNDLE_SYMBOLICNAME));
775                 fRenameAction.setPlugin((IPluginModelBase)base);
776             }
777         }
778         if (fRenameAction != null)
779             // add rename action after Outline. This is the same order as the hyperlink actions
780
menu.insertAfter(PDEActionConstants.COMMAND_ID_QUICK_OUTLINE, fRenameAction);
781     }
782     
783     /* (non-Javadoc)
784      * @see org.eclipse.pde.internal.ui.editor.PDESourcePage#setActive(boolean)
785      */

786     public void setActive(boolean active) {
787         super.setActive(active);
788         // Update the text selection if this page is being activated
789
if (active) {
790             updateTextSelection();
791         }
792     }
793
794 }
795
Popular Tags