View Javadoc
1   /*
2    WSMO Studio - a Semantic Web Service Editor
3    Copyright (c) 2004-2006, OntoText Lab. / SIRMA Group
4    
5    This library is free software; you can redistribute it and/or modify it under
6    the terms of the GNU Lesser General Public License as published by the Free
7    Software Foundation; either version 2.1 of the License, or (at your option)
8    any later version.
9    This library is distributed in the hope that it will be useful, but WITHOUT
10   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   details.
13   You should have received a copy of the GNU Lesser General Public License along
14   with this library; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16   */
17  
18  /***
19   * <p>Title: WSMO Studio</p>
20   * <p>Description: Semantic Web Service Editor</p>
21   * <p>Copyright:  Copyright (c) 2004-2006</p>
22   * <p>Company: OntoText Lab. / SIRMA </p>
23   */
24  
25  package org.wsmostudio.ui.views.navigator;
26  
27  import java.util.*;
28  import java.util.List;
29  
30  import org.eclipse.jface.action.*;
31  import org.eclipse.jface.dialogs.MessageDialog;
32  import org.eclipse.jface.viewers.*;
33  import org.eclipse.swt.SWT;
34  import org.eclipse.swt.events.*;
35  import org.eclipse.swt.widgets.*;
36  import org.eclipse.ui.*;
37  import org.eclipse.ui.actions.ActionFactory;
38  import org.eclipse.ui.part.ViewPart;
39  import org.eclipse.ui.views.properties.*;
40  import org.wsmo.common.Entity;
41  import org.wsmostudio.ui.*;
42  import org.wsmostudio.ui.dnd.Clipboard;
43  import org.wsmostudio.ui.dnd.WSMOTransfer;
44  import org.wsmostudio.ui.editors.extension.ExtensionManager;
45  import org.wsmostudio.ui.editors.model.*;
46  import org.wsmostudio.ui.views.navigator.actions.*;
47  import org.wsmostudio.ui.views.properties.WSMOPropertiesSource;
48  import org.eclipse.swt.dnd.*;
49  
50  /***
51   * A primary viewer component (<i>WSMO Navigator</i>) of the WSMO Studio. 
52   * It outlines the content of the opened WSMO-API objects in the workbench
53   * in a tree-styled view. It is a part of the WSMO perspective.
54   * From this viewer, different more specialized editors can be opened for
55   * the content of the visualized object. 
56   *
57   * @author not attributable
58   * @version $Revision: 1.28 $ $Date: 2006/02/20 14:58:30 $
59   */
60  
61  public class WSMONavigator extends ViewPart 
62  implements ISelectionProvider, Observer {
63  
64      protected TreeViewer treeViewer;
65      private WSMONavigatorUpdater uiUpdater;
66      private Set<ISelectionChangedListener> selListeners;
67      
68      private WSMOPropertiesSource propsSrc;
69      private ContentExtensionManager extensionManager;
70      private ActionRegistry actionRegistry;
71  
72  
73      public WSMONavigator() {
74          super();
75          uiUpdater = new WSMONavigatorUpdater(this);
76          uiUpdater.registerInOpenedEditors();
77          PlatformUI.getWorkbench()
78              .getActiveWorkbenchWindow()
79                  .getPartService()
80                      .addPartListener(uiUpdater);
81          actionRegistry = new ActionRegistry(this);
82      }
83      
84      public void createPartControl(Composite parent) {
85          treeViewer = new TreeViewer(parent);
86          extensionManager = new ContentExtensionManager();
87          treeViewer.setContentProvider(new NavigatorContentProvider(extensionManager));
88          treeViewer.setLabelProvider(new NavigatorLabelProvider(extensionManager));
89  
90          setWsmoInput(findActiveInput());
91          treeViewer.getTree().addMouseListener(new MouseAdapter() {
92              public void mouseDoubleClick(MouseEvent e) {
93                  processDoubleClick(e);
94              }
95          });
96          createContextMenu();
97          selListeners = new HashSet<ISelectionChangedListener>();
98          getViewSite().setSelectionProvider(this);
99  
100         
101         treeViewer.addSelectionChangedListener(
102                 new ISelectionChangedListener() {
103                     public void selectionChanged(SelectionChangedEvent event) {
104                         propsViewRefresh();
105                     }
106                 });
107         treeViewer.getTree().addKeyListener(new KeyAdapter() {
108             public void keyReleased(KeyEvent e) {
109                 if (e.keyCode == SWT.F5) {
110                     treeViewer.refresh();
111                 }
112             }
113         });
114         initDNDSource();
115         initWorkbenchActions();
116     }
117     
118     private void initDNDSource() {
119 
120         DragSource source = new DragSource(treeViewer.getTree(), DND.DROP_LINK); 
121         Transfer[] types = new Transfer[] {WSMOTransfer.getInstance()}; 
122         source.setTransfer(types); 
123            
124         source.addDragListener(new DragSourceListener() { 
125             public void dragStart(DragSourceEvent event) { 
126                 IStructuredSelection sel = (IStructuredSelection)treeViewer.getSelection();
127                 if (sel == null 
128                         || sel.isEmpty()) {
129                     event.doit = false;
130                 }
131                 List<Entity> selection = new LinkedList<Entity>();
132                 for(Iterator it = sel.iterator(); it.hasNext();) {
133                     Object selObj = it.next();
134                     if (selObj instanceof Entity) {
135                         selection.add((Entity)selObj);
136                     }
137                 }
138                 Clipboard.getInstance().setContent(selection);
139             } 
140             public void dragSetData(DragSourceEvent event) { 
141               if (WSMOTransfer.getInstance().isSupportedType(event.dataType)) { 
142                    event.data = Clipboard.getInstance().getContent(); 
143               } 
144             } 
145             public void dragFinished(DragSourceEvent event) { 
146                 Clipboard.getInstance().clear();
147             }
148          }); 
149         
150     }
151     
152     public static void propsViewRefresh() {
153 
154         IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
155         if (activePage == null) {
156             return;
157         }
158         IViewReference[] references = activePage.getViewReferences();
159         for (IViewReference viewRef : references) {
160             if (viewRef.getId().equals("org.eclipse.ui.views.PropertySheet")) {
161                 IViewPart part = viewRef.getView(true);
162                 if (part == null) {
163                     return;
164                 }
165                 PropertySheetPage page = (PropertySheetPage)((PropertySheet)part).getCurrentPage();
166                 if (page != null) {
167                     page.refresh();
168                 }
169             }
170         }
171     }
172     
173     protected void initWorkbenchActions() {
174         IWorkbenchWindow window = getSite().getWorkbenchWindow();
175         createWbAction(ActionFactory.MAXIMIZE, window);
176         createWbAction(ActionFactory.MINIMIZE, window);
177         createWbAction(ActionFactory.REFRESH, window);
178 
179         createWbAction(ActionFactory.SAVE, window);
180         createWbAction(ActionFactory.SAVE_ALL, window);
181     }
182     
183     private void createWbAction(ActionFactory factory, IWorkbenchWindow window) {
184         ActionFactory.IWorkbenchAction action = factory.create(window);
185         getSite().getKeyBindingService().registerAction(action);
186     }
187     
188     public void notifyActiveFiltersChange() {
189         extensionManager.updateFilters();
190         treeViewer.refresh(true);
191     }
192 
193     void setWsmoInput(IEditorInput newInput) {
194         IEditorInput oldInput = (IEditorInput)treeViewer.getInput();
195         if (oldInput == null) {
196             if (newInput == null) {
197                 return; // no change needed
198             }
199         }
200         else if (false == oldInput.equals(newInput)) {
201             if (oldInput.getAdapter(Observable.class) != null) {
202                 ((Observable)oldInput.getAdapter(Observable.class)).deleteObserver(this);
203             }
204         }
205         else {
206             return; // no need to update
207         }
208 
209         treeViewer.setInput(newInput);
210         treeViewer.expandToLevel(2);
211         if (newInput != null 
212                 && newInput.getAdapter(Observable.class) != null) {
213             ((Observable)newInput.getAdapter(Observable.class)).deleteObserver(this);
214         }
215     }
216     
217     public IEditorInput getWsmoInput() {
218         if (this.treeViewer == null) {
219             return null;
220         }
221         return (IEditorInput)this.treeViewer.getInput();
222     }
223     
224     public void update(Observable o, Object target) {
225         if (false == o.equals(getWsmoInput().getAdapter(Observable.class))) {
226             return; // not a relevant notification
227         }
228         treeViewer.refresh(true);
229     }
230 
231     public void setFocus() {
232         treeViewer.getControl().setFocus();
233     }
234 
235     public void processDoubleClick(MouseEvent e) {
236         ISelection selection = treeViewer.getSelection();
237         if (false == selection instanceof IStructuredSelection) {
238             return; 
239         }
240         Object target = ((IStructuredSelection)selection).getFirstElement();
241         if (hasRegisteredEditor(target)) {
242             new EditAction(this).run();
243         }
244         IAction editAction = actionRegistry.getCustomEditAction(target);
245         if(editAction != null) {
246             editAction.run();
247         }
248     }
249     
250     private void createContextMenu() {
251         MenuManager menuMgr = new MenuManager();
252         menuMgr.setRemoveAllWhenShown(true);
253         menuMgr.addMenuListener(new IMenuListener() {
254                 public void menuAboutToShow(IMenuManager mgr) {
255                     fillContextMenu(mgr);
256                 }
257         });
258         
259         // Create menu.
260         Menu contextMenu = menuMgr.createContextMenu(treeViewer.getControl());
261         treeViewer.getControl().setMenu(contextMenu);
262         
263         // Register menu for extension.
264         getSite().registerContextMenu(menuMgr, treeViewer);
265     }
266 
267     private void fillContextMenu(IMenuManager mgr) {
268         mgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
269 
270         IStructuredSelection sSel = (IStructuredSelection)treeViewer.getSelection();
271         Object target = sSel.getFirstElement();
272         if (target == null) {
273             return; // no seleciton
274         }
275         
276         actionRegistry.initAddActions(mgr, target);
277         if (mgr.getItems().length > 0) {
278             mgr.add(new Separator());
279         }
280         addEditMenu(mgr, target);
281         initEditWithMenu(mgr, target);
282         if (mgr.getItems().length > 0) {
283             mgr.add(new Separator());
284         }
285         actionRegistry.initRemoveActions(mgr, target);
286         if (mgr.getItems().length > 0) {
287             mgr.add(new Separator());
288         }
289         actionRegistry.initMiscActions(mgr, target);
290     }
291     
292     private void addEditMenu(IMenuManager mManager, final Object object) {
293         if (hasRegisteredEditor(object)) {
294             EditAction action = new EditAction(this);
295             action.setText("Edit");
296             mManager.add(action);
297         }
298     }
299     
300     private boolean hasRegisteredEditor(Object target) {
301         final ExtensionManager manager = WsmoUIPlugin.getDefault().getExtensionManager();
302         LinkedList<String> allEditors = manager.findEditorsForObject(target);
303         return allEditors != null 
304                 && allEditors.size() > 0;
305     }
306     
307     private void initEditWithMenu(IMenuManager mManager, final Object object) {
308         final ExtensionManager manager = WsmoUIPlugin.getDefault().getExtensionManager();
309         LinkedList<String> allEditors = manager.findEditorsForObject(object);
310         if (allEditors == null 
311                 || allEditors.size() < 2) {
312             return; // no need this menu
313         }
314         mManager.add(new Separator());
315         MenuManager subMenu = new MenuManager("Edit With ...");
316         mManager.add(subMenu);
317         String preferredEditor = manager.findPreferredEditor(object);
318         
319         for (Iterator it = allEditors.iterator(); it.hasNext();) {
320             final String edID = (String)it.next();
321             final String editorDescr = manager.getEditorDescription(edID);
322             Action action = new Action((editorDescr != null) ? editorDescr : edID) {
323                 public void run() {
324                     manager.setPreferredEditor(object, edID);
325                     new EditAction(WSMONavigator.this).run();
326                 }
327             };
328             action.setChecked(edID.equals(preferredEditor));
329             subMenu.add(action);
330         }
331     }
332     
333     public void dispose() {
334         uiUpdater.unregisterFromOpenedEditors();
335         PlatformUI.getWorkbench()
336             .getActiveWorkbenchWindow()
337                 .getPartService()
338                     .removePartListener(uiUpdater);
339         treeViewer = null;
340     }
341 
342     public Object getAdapter(Class adapter) {
343         if (adapter == IPropertySource.class) {
344             if (treeViewer.getTree().getSelectionCount() == 0) {
345                 return null;
346             }
347             Object selection = ((IStructuredSelection)treeViewer.getSelection()).getFirstElement();
348             if (false == selection instanceof Entity) {
349                 return null;
350             }
351             if (propsSrc == null) {
352                 propsSrc =  new WSMOPropertiesSource((Entity)selection);
353             }
354             else {
355                 propsSrc.setData((Entity)selection);
356             }
357             return propsSrc;
358 		}
359         return null;
360      }
361     
362     public boolean ensureEditorForEntityIsClosed(Entity entity) {
363 
364         IWorkbenchPage page = PlatformUI.getWorkbench()
365                                   .getActiveWorkbenchWindow()
366                                       .getActivePage();
367         if (page == null) {
368             return true;
369         }
370         Set<IEditorInput> inputs = Utils.findInputsForEntity(entity);
371         
372         if (inputs == null 
373                 || inputs.size() == 0) {
374             return true;
375         }
376         if (MessageDialog.openConfirm(getSite().getShell(), 
377                                       "Editor Closing", 
378                                       "The selected entity is currently opened in an editor."
379                                       +"\nDo you want to proceed with closing the editor?")) {
380             for(IEditorInput input : inputs) {
381                 IEditorPart editor = page.findEditor(input); 
382                 page.closeEditor(editor, false);
383             }
384         }
385         else {
386             return false;
387         }
388         return true;
389     }
390     
391     public void fireEntityChanged(Entity entity) {
392         Set<ObservableModel> models = Utils.findModelsForEntity(entity);
393         for(ObservableModel model : models) {
394             model.notifyObservers(entity);
395         }
396     }
397 
398     
399     public void addSelectionChangedListener(ISelectionChangedListener listener) {
400         selListeners.add(listener);
401     }
402     
403     public ISelection getSelection() {
404         return new StructuredSelection(this);
405     }
406     
407     public void removeSelectionChangedListener(ISelectionChangedListener listener) {
408         selListeners.remove(listener);
409     }
410     
411     public void setSelection(ISelection selection) {
412     }
413     
414     private IEditorInput findActiveInput() {
415         IWorkbenchPage page = PlatformUI.getWorkbench()
416                                   .getActiveWorkbenchWindow()
417                                       .getActivePage();
418         if (page == null) {
419             return null; // not initialized yet - no active input
420         }
421         
422         IEditorPart editor = page.getActiveEditor();
423         if (editor != null) {
424             IEditorInput input = editor.getEditorInput();
425             if (input.getAdapter(Entity.class) != null) { // only if adaptable to wsmo
426                 return input;
427             }
428         }
429         return null;
430     }
431 
432     public TreeViewer getTree() {
433         return treeViewer;
434     }
435     
436     public void selectionChanged(SelectionChangedEvent event) {
437     }
438 }
439 
440 /*
441  * $Log: WSMONavigator.java,v $
442  * Revision 1.28  2006/02/20 14:58:30  alex_simov
443  * issue[1428325]: Objects without dedicated editors but having custom
444  * edit actions not opened on mouse double-click in the WSMO Navigator
445  *
446  * Revision 1.27  2006/01/10 13:41:26  alex_simov
447  * bugfix: navigator's restored content allowed invalid input data
448  *
449  * Revision 1.26  2006/01/09 12:51:14  alex_simov
450  * Copyright message in header updated
451  *
452  * Revision 1.25  2006/01/06 14:40:43  alex_simov
453  * method modifier signature changed (propsViewRefresh())
454  *
455  * Revision 1.24  2005/11/18 12:51:18  alex_simov
456  * keyboard shortcuts enabled
457  *
458  * Revision 1.23  2005/11/17 16:08:26  alex_simov
459  * fix
460  *
461  * Revision 1.22  2005/11/15 15:56:05  alex_simov
462  * Drag-and-drop support added from WSMO Navigator to related (ontology) editors
463  *
464  * Revision 1.21  2005/11/10 13:42:44  alex_simov
465  * update
466  *
467  * Revision 1.20  2005/11/09 16:14:34  alex_simov
468  * UIModels notification improved
469  *
470  * Revision 1.19  2005/11/02 14:50:57  alex_simov
471  * moving to MVC architecture cont'd
472  *
473  * Revision 1.18  2005/11/02 08:48:16  alex_simov
474  * org.wsmostudio.ui.navigator_content ext-point enriched with actions for objects
475  *
476  * Revision 1.17  2005/10/14 13:25:18  alex_simov
477  * WSMO Navigator's extension point creation
478  *
479  * Revision 1.16  2005/09/21 15:09:11  alex_simov
480  * minor fixes
481  *
482  * Revision 1.15  2005/09/12 09:27:55  alex_simov
483  * selection actions now update Properties view
484  *
485  * Revision 1.14  2005/09/08 16:46:25  alex_simov
486  * Migrating to Java 1.5
487  *
488  * Revision 1.13  2005/09/02 11:54:10  alex_simov
489  * bugfix: [1280465] ClassCastException
490  *
491  * Revision 1.12  2005/08/05 15:32:29  alex_simov
492  * editors input change notification mechanism added
493  *
494  * Revision 1.11  2005/08/04 15:00:55  alex_simov
495  * editor <-> subeditor dependency links established
496  *
497  * Revision 1.10  2005/08/02 10:33:21  alex_simov
498  * minor code and/or javadoc fixes
499  *
500  * Revision 1.9  2005/07/29 15:08:03  alex_simov
501  * added javadoc: class description, footer
502  *
503  *
504  */