Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/port80/eclipse/jdt/annotation/AnnotationView.java


1   package com.port80.eclipse.jdt.annotation;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.eclipse.core.internal.runtime.Assert;
7   import org.eclipse.core.resources.IFile;
8   import org.eclipse.core.resources.ResourcesPlugin;
9   import org.eclipse.jdt.core.IJavaElement;
10  import org.eclipse.jdt.core.IType;
11  import org.eclipse.jface.action.Action;
12  import org.eclipse.jface.action.IMenuListener;
13  import org.eclipse.jface.action.IMenuManager;
14  import org.eclipse.jface.action.IStatusLineManager;
15  import org.eclipse.jface.action.IToolBarManager;
16  import org.eclipse.jface.action.MenuManager;
17  import org.eclipse.jface.action.Separator;
18  import org.eclipse.jface.dialogs.MessageDialog;
19  import org.eclipse.jface.util.IPropertyChangeListener;
20  import org.eclipse.jface.util.PropertyChangeEvent;
21  import org.eclipse.jface.viewers.DoubleClickEvent;
22  import org.eclipse.jface.viewers.IDoubleClickListener;
23  import org.eclipse.jface.viewers.ISelection;
24  import org.eclipse.jface.viewers.ISelectionChangedListener;
25  import org.eclipse.jface.viewers.IStructuredSelection;
26  import org.eclipse.jface.viewers.SelectionChangedEvent;
27  import org.eclipse.jface.viewers.StructuredSelection;
28  import org.eclipse.jface.viewers.TreeViewer;
29  import org.eclipse.jface.window.Window;
30  import org.eclipse.swt.SWT;
31  import org.eclipse.swt.SWTError;
32  import org.eclipse.swt.dnd.DND;
33  import org.eclipse.swt.dnd.TextTransfer;
34  import org.eclipse.swt.dnd.Transfer;
35  import org.eclipse.swt.events.KeyEvent;
36  import org.eclipse.swt.events.KeyListener;
37  import org.eclipse.swt.widgets.Composite;
38  import org.eclipse.swt.widgets.Menu;
39  import org.eclipse.swt.widgets.MessageBox;
40  import org.eclipse.ui.IActionBars;
41  import org.eclipse.ui.IEditorInput;
42  import org.eclipse.ui.IEditorPart;
43  import org.eclipse.ui.IMemento;
44  import org.eclipse.ui.IPartListener;
45  import org.eclipse.ui.ISharedImages;
46  import org.eclipse.ui.IViewSite;
47  import org.eclipse.ui.IWorkbenchPart;
48  import org.eclipse.ui.PartInitException;
49  import org.eclipse.ui.PlatformUI;
50  import org.eclipse.ui.part.FileEditorInput;
51  import org.eclipse.ui.part.ViewPart;
52  
53  import com.port80.eclipse.jdt.IConstants;
54  import com.port80.eclipse.jdt.JdtPlugin;
55  import com.port80.eclipse.jdt.Util;
56  import com.port80.eclipse.jdt.util.JavaUtil;
57  import com.port80.eclipse.jdt.util.PersistentFolder;
58  import com.port80.eclipse.jdt.util.PersistentItem;
59  import com.port80.eclipse.util.IncrementalFindTreeTarget;
60  import com.port80.eclipse.util.UtilPluginImages;
61  
62  /**
63   * A TreeViewer that shows content of the AnnotationModel.
64   * 
65   * The View provides various filter and sorting functions for inspecting and searching in the Annotation.
66   * The Annotation machanism automatically maintain the set of IResource/IJavaElement visited in various way with
67   * access information.  The Annotation can be used for backtracing to previous location and for annotation.
68   */
69  public class AnnotationView
70    extends ViewPart
71    implements KeyListener, IAnnotationModelListener, IPropertyChangeListener {
72  
73    ////////////////////////////////////////////////////////////////////////
74  
75    public static final String ID = "com.port80.eclipse.jdt.annotation.AnnotationView";
76  
77    private static final String NAME = "AnnotationView";
78    private static final String VERSION = "v0.1";
79    private static final boolean DEBUG = true;
80    private static final boolean TRACE = true;
81  
82    private static final int FIND_KEYMASK = 0;
83    private static final int FIND_FORWARD_KEYCHAR = 's';
84    private static final int FIND_BACKWARD_KEYCHAR = 'r';
85    private static final int ACTION_KEYMASK = 0;
86    private static final int DELETE_ACTION_KEYCHAR = 'd';
87  
88    ////////////////////////////////////////////////////////////////////////
89  
90    private TreeViewer fViewer;
91    private AnnotationManager fAnnotationManager;
92    private String fSortKey;
93    private String fDefaultFolderName; /** Current folder. */
94    private IncrementalFindTreeTarget fFindTarget;
95    //
96    private Action fActionHeader;
97    private Action fActionEdit;
98    private Action fActionClipboard;
99    private Action fActionAdd;
100   private Action fActionCopy;
101   private Action fActionMove;
102   private Action fActionDelete;
103   private Action fActionSort;
104   private Action fActionResolve;
105   private Action fActionSetInbox;
106   private Action fActionAbout;
107 
108   private IPartListener fPartListener;
109 
110   ////////////////////////////////////////////////////////////////////////
111 
112   /**
113    * The constructor.
114    */
115   public AnnotationView() {
116     if (TRACE)
117       System.err.println(NAME + "()");
118     fSortKey = AnnotationSorter.DEF_SORTKEY;
119   }
120 
121   ////////////////////////////////////////////////////////////////////////
122 
123   public void init(IViewSite site, IMemento memento) throws PartInitException {
124     super.init(site, memento);
125     if (TRACE)
126       System.err.println(NAME + ".init()");
127     if (memento != null) {
128       fSortKey = memento.getString("SortBy");
129       if (fSortKey == null)
130         fSortKey = AnnotationSorter.DEF_SORTKEY;
131       fDefaultFolderName = memento.getString("Folder");
132     }
133     //NOTE: init() is called before createPartControl().
134     fAnnotationManager = JdtPlugin.getAnnotationManager();
135     if (fDefaultFolderName == null)
136       fDefaultFolderName = AnnotationManager.INBOX;
137     PersistentFolder folder = fAnnotationManager.findFolder(fDefaultFolderName);
138     folder.setActive(true);
139   }
140 
141   /**
142    * @see IWorkbenchPart#dispose()
143    */
144   public void dispose() {
145     getSite().getPage().removePartListener(fPartListener);
146     JdtPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
147     fAnnotationManager.removeModelListener(this);
148     super.dispose();
149   }
150 
151   /**
152    * This is a callback that will allow us to create the viewer and initialize it.
153    */
154   public void createPartControl(Composite parent) {
155     if (TRACE)
156       System.err.println(NAME + ".createPartControl()");
157     fViewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
158     fViewer.setContentProvider(fAnnotationManager);
159     fViewer.setLabelProvider(fAnnotationManager);
160     fViewer.setSorter(new AnnotationSorter(fSortKey));
161     fViewer.setInput(ResourcesPlugin.getWorkspace());
162     fViewer.refresh();
163     fViewer.expandAll();
164     getViewSite().setSelectionProvider(fViewer);
165     fViewer.addSelectionChangedListener(new ISelectionChangedListener() {
166       public void selectionChanged(SelectionChangedEvent event) {
167         handleSelectionChanged(event);
168       }
169     });
170     makeActions();
171     hookContextMenu();
172     hookDoubleClickAction();
173     hookKeyListener();
174     contributeToActionBars();
175     fAnnotationManager.addModelListener(this);
176     JdtPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
177     hookPartListener();
178     JdtPlugin.getDefault().enableEditorHistory();
179   }
180 
181   // IPropertyChangeListener methods //////////////////////////////
182   //
183 
184   /**
185    * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
186    */
187   public void propertyChange(PropertyChangeEvent event) {
188     if (IConstants.PREF_ANNOTATIONVIEW_INBOX_LIMIT.equals(event.getProperty())) {
189       fAnnotationManager.initPrefs();
190     }
191   }
192 
193   // PartListener methods /////////////////////////////////////////
194   //
195 
196   /** Listen to any part activation and update the method view if an editor part is activated. */
197   private void hookPartListener() {
198     fPartListener = new IPartListener() {
199       public void partActivated(IWorkbenchPart part) {
200         editorActivation(part);
201       }
202       public void partBroughtToTop(IWorkbenchPart part) {
203       }
204       public void partClosed(IWorkbenchPart part) {
205       }
206       public void partDeactivated(IWorkbenchPart part) {
207       }
208       public void partOpened(IWorkbenchPart part) {
209       }
210     };
211     getSite().getPage().addPartListener(fPartListener);
212   }
213 
214   /**
215    * Select the IResources for the activated editor if it exists in the AnnotationModel.
216    * Otherwise, do nothing.
217    * //FIXME: For now, this only works for IJavaElement.
218    */
219   void editorActivation(IWorkbenchPart part) {
220     if (!(part instanceof IEditorPart))
221       return;
222     addFromEditor((IEditorPart)part, AnnotationManager.INBOX);
223     //    IJavaElement element = JavaUtil.getSelectedElementFromEditor(part);
224     //    if (element == null)
225     //      return;
226     //    IType type = Util.findJavaType(element);
227     //    if (type != null)
228     //      fAnnotationManager.addAutomatic(element);
229   }
230 
231   ////////////////////////////////////////////////////////////////////////
232 
233   public void saveState(IMemento memento) {
234     //NOTE: memento is already a child created for this view.
235     memento.putString("SortBy", fSortKey);
236     memento.putString("Folder", fDefaultFolderName);
237     if (fAnnotationManager != null)
238       fAnnotationManager.saveXMLState();
239   }
240 
241   ////////////////////////////////////////////////////////////////////////
242 
243   public TreeViewer getViewer() {
244     return fViewer;
245   }
246 
247   ////////////////////////////////////////////////////////////////////////
248 
249   /**
250    * Add and edit annotation on a object.  
251    * If user cancel editing, item is not added and if item already exists, it is not modified.
252    */
253   public void addAnnotation(Object a) {
254     PersistentItem item;
255     if (a instanceof PersistentItem) {
256       item = (PersistentItem) a;
257     } else {
258       item = PersistentItem.create(a, fDefaultFolderName);
259       if (item == null) {
260         showMessage("Invalid object: " + a);
261         return;
262       }
263     }
264     PersistentItem original = fAnnotationManager.get(item);
265     if (original != null)
266       item = original;
267     String folder = editAnnotation(item);
268     if (folder == null) // Cancelled.
269       return;
270     if (original == null) {
271       fAnnotationManager.add(item, folder);
272       refresh();
273     } else {
274       if (folder.equals(item.getParent())) {
275         refresh(item);
276       } else {
277         fAnnotationManager.moveItem(item, folder);
278       }
279     }
280   }
281 
282   /**
283    * Popup a dialog to edit the given item's annotation.
284    * @return null if edit cancelled, else the new folder name.
285    */
286   public String editAnnotation(PersistentItem item) {
287     // Find all existing folders.
288     Object[] aa = fAnnotationManager.getElements(null);
289     List folders = new ArrayList();
290     for (int i = 0; i < aa.length; ++i) {
291       if (aa[i] instanceof PersistentFolder) {
292         folders.add(((PersistentFolder) aa[i]).getName());
293       }
294     }
295     StringBuffer label = new StringBuffer();
296     label.append("Kind = " + item.getKindName() + "\n");
297     label.append("Name =  " + item.getName() + "\n");
298     label.append("FullName =  " + item.getFullName() + "\n");
299     label.append("FullPath =  " + item.getFullPath() + "\n");
300     label.append("Project = " + item.getProject() + "\n");
301     label.append("Create Time =  " + item.getCTime().toString() + "\n");
302     label.append("Last Access Time =  " + item.getCTime().toString() + "\n");
303     label.append("Count =  " + item.getCount());
304     //label.append("\n" + i18n("EditAnnotation.Label"));
305     EditAnnotationDialog dialog =
306       new EditAnnotationDialog(
307         getSite().getShell(),
308         JdtPlugin.getString("AnnotationView.editAnnotation.title"),
309         label.toString(),
310         item.getParent(),
311         folders,
312         item.getAnnotation());
313     if (dialog.open() == Window.OK) {
314       setInbox(dialog.getFolder());
315       item.setAnnotation(dialog.getText());
316       return dialog.getFolder();
317     }
318     return null;
319   }
320 
321   /**
322    * Passing the focus request to the viewer's control.
323    */
324   public void setFocus() {
325     fViewer.getControl().setFocus();
326   }
327 
328   public void setSortKey(String key) {
329     //NOTE: Setting key to be same as old one, effectly refresh the sorting.
330     if (AnnotationSorter.SORTKEYMAP.get(key) != null)
331       fSortKey = key;
332     fViewer.setSorter(new AnnotationSorter(fSortKey));
333   }
334 
335   public String getSortKey() {
336     return fSortKey;
337   }
338 
339   public String[] getSortKeys() {
340     return AnnotationSorter.SORTKEYS;
341   }
342 
343   // AnnotationModelListener ///////////////////////////////////////////
344 
345   public void refresh() {
346     fViewer.refresh();
347   }
348   public void refresh(PersistentItem item) {
349     fViewer.refresh(item);
350   }
351 
352   public void setSelection(ISelection selection, boolean reveal) {
353     if (selection != null && selection.equals(fViewer.getSelection()))
354       return;
355     fViewer.setSelection(selection, reveal);
356   }
357 
358   // ISelectionChangedListener //////////////////////////////////////////
359 
360   /**
361    * Update status message on viewer selection changes.  This can also be used to execute action on single click
362    * selection.
363    * 
364    * @see ISelectionListener#selectionChanged(IWorkbenchPart, ISelection)
365    */
366   public void handleSelectionChanged(SelectionChangedEvent e) {
367     ISelection selection = e.getSelection();
368     if (selection == null || selection.isEmpty())
369       return;
370     if (!(selection instanceof IStructuredSelection))
371       return;
372     PersistentItem item = (PersistentItem) ((IStructuredSelection) selection).getFirstElement();
373     IStatusLineManager manager = getViewSite().getActionBars().getStatusLineManager();
374     String str = item.getFullName() + " - " + item.getFullPath();
375     manager.setMessage(str);
376   }
377 
378   // KeyListener ///////////////////////////////////////////////////////
379 
380   public void keyPressed(KeyEvent event) {
381     if (DEBUG)
382       System.out.println(
383         NAME
384           + ".keyPressed(): mask="
385           + event.stateMask
386           + ", code="
387           + event.keyCode
388           + ", character="
389           + event.character);
390     if (event.stateMask == FIND_KEYMASK && event.character == FIND_FORWARD_KEYCHAR) {
391       beginSession(true);
392     } else if (event.stateMask == FIND_KEYMASK && event.character == FIND_BACKWARD_KEYCHAR) {
393       beginSession(false);
394     }
395   }
396   public void keyReleased(KeyEvent event) {
397     if (DEBUG)
398       System.out.println(
399         NAME
400           + ".keyReleased(): mask="
401           + event.stateMask
402           + ", code="
403           + event.keyCode
404           + ", character="
405           + event.character);
406     if (event.stateMask == ACTION_KEYMASK && event.character == DELETE_ACTION_KEYCHAR) {
407       deleteAction();
408     }
409   }
410 
411   public void beginSession(boolean forward) {
412     fFindTarget =
413       new IncrementalFindTreeTarget(
414         fViewer,
415         getViewSite().getActionBars().getStatusLineManager(),
416         this);
417     fFindTarget.beginSession(forward, null);
418   }
419 
420   ////////////////////////////////////////////////////////////////////////
421 
422   private void makeActions() {
423     fActionHeader = new Action() {
424       public void run() {
425       }
426     };
427     fActionHeader.setText("AnnotationView Menu:");
428     fActionHeader.setEnabled(false);
429     //
430     fActionEdit = new Action() {
431       public void run() {
432         editAction();
433       }
434     };
435     fActionEdit.setText("Edit Annotation");
436     fActionEdit.setToolTipText("Edit Annotation");
437     fActionEdit.setImageDescriptor(
438       PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
439         ISharedImages.IMG_OBJS_TASK_TSK));
440     //
441     fActionClipboard = new Action() {
442       public void run() {
443         clipboardAction();
444       }
445     };
446     fActionClipboard.setText("Clipboard");
447     fActionClipboard.setToolTipText("Copy name to clipboard");
448     fActionClipboard.setImageDescriptor(
449       PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJ_FILE));
450     //
451     fActionAdd = new Action() {
452       public void run() {
453         addAction();
454       }
455     };
456     fActionAdd.setText("Add");
457     fActionAdd.setToolTipText("Add from editor");
458     //
459     fActionCopy = new Action() {
460       public void run() {
461         copyAction();
462       }
463     };
464     fActionCopy.setText("Copy");
465     fActionCopy.setToolTipText("Copy items");
466     //
467     fActionMove = new Action() {
468       public void run() {
469         moveAction();
470       }
471     };
472     fActionMove.setText("Move");
473     fActionMove.setToolTipText("Move items to another folder");
474     //
475     fActionDelete = new Action() {
476       public void run() {
477         deleteAction();
478       }
479     };
480     fActionDelete.setText("Delete");
481     fActionDelete.setToolTipText("Delete");
482     UtilPluginImages.setToolImageDescriptors(fActionDelete, UtilPluginImages.IMG_DELETE);
483     //
484     fActionResolve = new Action() {
485       public void run() {
486         resolveAction();
487       }
488     };
489     fActionResolve.setText("Resolve");
490     fActionResolve.setToolTipText("Scan for non-exist object");
491     UtilPluginImages.setLocalImageDescriptors(fActionResolve, UtilPluginImages.IMG_REFRESH);
492     //
493     fActionSetInbox = new Action() {
494       public void run() {
495         setInboxAction();
496       }
497     };
498     fActionSetInbox.setText("Set As Inbox");
499     fActionSetInbox.setToolTipText("Set folder as inbox");
500     //FIXME: Choose a better icon.
501     fActionSetInbox.setImageDescriptor(
502       PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
503         ISharedImages.IMG_OBJS_TASK_TSK));
504     //
505     fActionAbout = new Action() {
506       public void run() {
507         showMessage(NAME + " " + VERSION);
508       }
509     };
510     fActionAbout.setText("About");
511     fActionAbout.setToolTipText("About AnnotationView");
512     fActionAbout.setImageDescriptor(
513       PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
514         ISharedImages.IMG_OBJS_INFO_TSK));
515     //
516     fActionSort = new SortAction(this);
517   }
518   private void contributeToActionBars() {
519     IActionBars bars = getViewSite().getActionBars();
520     fillLocalPullDown(bars.getMenuManager());
521     fillLocalToolBar(bars.getToolBarManager());
522   }
523   private void fillLocalPullDown(IMenuManager manager) {
524     manager.add(new Separator());
525     manager.add(fActionAbout);
526   }
527   private void fillLocalToolBar(IToolBarManager manager) {
528     manager.add(fActionResolve);
529     manager.add(new Separator());
530     manager.add(fActionSort);
531     manager.add(new Separator());
532   }
533   private void hookContextMenu() {
534     MenuManager manager = new MenuManager("#PopupMenu");
535     manager.setRemoveAllWhenShown(true);
536     manager.addMenuListener(new IMenuListener() {
537       public void menuAboutToShow(IMenuManager manager) {
538         AnnotationView.this.fillContextMenu(manager);
539       }
540     });
541     Menu menu = manager.createContextMenu(fViewer.getControl());
542     fViewer.getControl().setMenu(menu);
543     // Register menu so that other plugin can contribute to it.
544     getSite().registerContextMenu(manager, fViewer);
545   }
546 
547   void fillContextMenu(IMenuManager manager) {
548     manager.add(fActionHeader);
549     manager.add(new Separator());
550     manager.add(fActionSetInbox);
551     manager.add(new Separator());
552     manager.add(fActionClipboard);
553     manager.add(fActionCopy);
554     manager.add(fActionMove);
555     manager.add(fActionDelete);
556     manager.add(new Separator());
557     manager.add(fActionAdd);
558     manager.add(fActionEdit);
559     // Visited item list.
560     //JdtPlugin.getDefault().addVisitedHistoryAction(manager);
561     // Other plug-ins can contribute there actions here
562     manager.add(new Separator("Additions"));
563   }
564   private void hookDoubleClickAction() {
565     fViewer.addDoubleClickListener(new IDoubleClickListener() {
566       public void doubleClick(DoubleClickEvent event) {
567         showInEditorAction();
568       }
569     });
570   }
571 
572   /** Temporary hack to do the incremental search.  Should move to StructuredViewer later.
573    */
574   private void hookKeyListener() {
575     fViewer.getControl().addKeyListener(this);
576   }
577 
578   void showMessage(String message) {
579     MessageDialog.openInformation(fViewer.getControl().getShell(), NAME, message);
580   }
581 
582   // Actions /////////////////////////////////////////////////////////////
583   //
584   void clipboardAction() {
585     IStructuredSelection selection = getSelection();
586     if (selection == null || selection.isEmpty())
587       return;
588     PersistentItem item = (PersistentItem) selection.getFirstElement();
589     if (item == null)
590       return;
591     String text = item.toString();
592     if (DEBUG)
593       System.out.println(NAME + ".clipboardAction(): text=" + text);
594     try {
595       JdtPlugin.getClipboard().setContents(
596         new Object[] { text },
597         new Transfer[] { TextTransfer.getInstance()});
598     } catch (SWTError e) {
599       if (e.code != DND.ERROR_CANNOT_SET_CLIPBOARD)
600         throw e;
601     }
602   }
603 
604   void addAction() {
605     IStructuredSelection selection = getSelection();
606     String folder = null;
607     if (selection != null && !selection.isEmpty()) {
608       Object a = selection.getFirstElement();
609       if (a instanceof PersistentFolder)
610         folder = ((PersistentFolder) a).getName();
611       else if (a instanceof PersistentItem)
612         folder = ((PersistentItem) a).getParent();
613     }
614     if (folder == null)
615       folder = promptForFolder();
616     if (folder == null)
617       return;
618     IEditorPart editor = getSite().getPage().getActiveEditor();
619     addFromEditor(editor, folder);
620   }
621 
622   private void addFromEditor(IEditorPart editor, String folder) {
623     IJavaElement element = JavaUtil.getSelectedElementFromEditor(editor);
624     if (element != null) {
625       IType type = Util.findJavaType(element);
626       if (type != null) {
627         PersistentItem item = fAnnotationManager.add(PersistentItem.create(type), folder);
628         setSelection(new StructuredSelection(item), true);
629         return;
630       }
631     }
632     IEditorInput input = editor.getEditorInput();
633     if (input instanceof FileEditorInput) {
634       IFile file = ((FileEditorInput) input).getFile();
635       PersistentItem item = fAnnotationManager.add(PersistentItem.create(file), folder);
636       setSelection(new StructuredSelection(item), true);
637     }
638   }
639 
640   void copyAction() {
641     IStructuredSelection selection = getSelection();
642     if (selection == null || selection.isEmpty())
643       return;
644     String newfolder = promptForFolder();
645     if (newfolder != null) {
646       fAnnotationManager.copyItems(selection.toArray(), newfolder);
647     }
648   }
649 
650   void moveAction() {
651     IStructuredSelection selection = getSelection();
652     if (selection == null || selection.isEmpty())
653       return;
654     String newfolder = promptForFolder();
655     if (newfolder != null) {
656       fAnnotationManager.moveItems(selection.toArray(), newfolder);
657     }
658   }
659 
660   private String promptForFolder() {
661     // Find all existing folders.
662     Object[] aa = fAnnotationManager.getElements(null);
663     List folders = new ArrayList();
664     for (int i = 0; i < aa.length; ++i) {
665       if (aa[i] instanceof PersistentFolder) {
666         folders.add(((PersistentFolder) aa[i]).getName());
667       }
668     }
669     PromptForFolderDialog dialog =
670       new PromptForFolderDialog(
671         getSite().getShell(),
672         JdtPlugin.getString(NAME, "promptForFolder", "PleaseSpecifyFolder"),
673         fDefaultFolderName,
674         folders);
675     if (dialog.open() == Window.OK)
676       return dialog.getFolder();
677     return null;
678   }
679 
680   void deleteAction() {
681     IStructuredSelection selection = getSelection();
682     if (selection == null || selection.isEmpty())
683       return;
684     Object[] aa = selection.toArray();
685     if (aa.length != 0) {
686       StringBuffer buf = new StringBuffer("Do you really want to delete the following?\n\n");
687       for (int i = 0; i < aa.length; ++i) {
688         buf.append("#  " + ((PersistentItem) aa[i]).getFullName());
689         buf.append("\n");
690       }
691       MessageBox box =
692         new MessageBox(
693           getSite().getShell(),
694           SWT.ICON_QUESTION | SWT.YES | SWT.NO | SWT.SYSTEM_MODAL);
695       box.setText("Confirm delete");
696       box.setMessage(buf.toString());
697       int result = box.open();
698       if (result != SWT.YES)
699         return;
700       fAnnotationManager.removeAll(aa);
701     }
702   }
703 
704   void editAction() {
705     IStructuredSelection selection = getSelection();
706     if (selection == null || selection.isEmpty())
707       return;
708     Object a = selection.getFirstElement();
709     if (!(a instanceof PersistentItem))
710       return;
711     PersistentItem item = (PersistentItem) a;
712     String folder = editAnnotation(item);
713     if (folder == null)
714       return;
715     if (folder.equals(item.getParent())) {
716       refresh(item);
717     } else {
718       fAnnotationManager.moveItem(item, folder);
719     }
720   }
721 
722   void resolveAction() {
723     List ret = new ArrayList();
724     resolveAction(fAnnotationManager.getRoot(), ret);
725     fViewer.setSelection(new StructuredSelection(ret));
726     fViewer.refresh();
727   }
728 
729   void setInboxAction() {
730     IStructuredSelection selection = getSelection();
731     if (selection == null || selection.isEmpty())
732       return;
733     Object a = selection.getFirstElement();
734     if (!(a instanceof PersistentFolder))
735       return;
736     setInbox(((PersistentFolder) a).getName());
737   }
738 
739   private void setInbox(String name) {
740     PersistentFolder folder;
741     if (name == null)
742       name = AnnotationManager.INBOX;
743     if (fDefaultFolderName != null && fDefaultFolderName.equals(name))
744       return;
745     if (fDefaultFolderName != null) {
746       folder = fAnnotationManager.findFolder(fDefaultFolderName);
747       folder.setActive(false);
748     }
749     fDefaultFolderName = name;
750     folder = fAnnotationManager.findFolder(fDefaultFolderName);
751     folder.setActive(true);
752     refresh();
753   }
754 
755   /**
756    * @return List of unresolvable elements in 'ret'.
757    */
758   private void resolveAction(Object a, List ret) {
759     if (a instanceof PersistentFolder) {
760       Object[] aa = ((PersistentFolder) a).getChildren();
761       for (int i = 0; i < aa.length; ++i)
762         resolveAction(aa[i], ret);
763     } else {
764       if (a instanceof PersistentItem) {
765         if (((PersistentItem) a).resolve() != null)
766           return;
767       }
768       ret.add(a);
769     }
770   }
771 
772   void showInEditorAction() {
773     IStructuredSelection selection = getSelection();
774     if (selection == null || selection.isEmpty())
775       return;
776     Object a = selection.getFirstElement();
777     if (!(a instanceof PersistentItem))
778       return;
779     Util.editItem((PersistentItem) a);
780   }
781 
782   ////////////////////////////////////////////////////////////////////////
783 
784   private IStructuredSelection getSelection() {
785     return (IStructuredSelection) fViewer.getSelection();
786   }
787 
788   private String getSelectedItemText() {
789     IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
790     if (selection == null || selection.isEmpty())
791       return null;
792     Object a = selection.getFirstElement();
793     if (Assert.isTrue(a instanceof PersistentItem, "selection not a annotation item"));
794     else
795       return null;
796     PersistentItem item = (PersistentItem) a;
797     return fAnnotationManager.getText(item);
798   }
799 
800   ////////////////////////////////////////////////////////////////////////
801 
802 }