View Javadoc

1   /*
2    * Created on Jul 24, 2005.
3    * Copyright 1999-2006 Faculty of Mathematics, Physics and Informatics, Comenius University, Bratislava.
4    * This file is protected by the Mozilla Public License
5    * version 1.1 (the "License"); you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at 
7    * 
8    *      http://euromath2.sourceforge.net/license.html
9    * 
10   * Unless required by applicable law or agreed to in writing, software 
11   * distributed under the License is distributed on an "AS IS" BASIS, 
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License. 
15   */
16  package sk.uniba.euromath.editor.xmlEditor.actions;
17  
18  import java.util.HashMap;
19  import java.util.List;
20  import java.util.Map;
21  
22  import javax.xml.namespace.QName;
23  
24  import org.eclipse.gef.GraphicalViewer;
25  import org.eclipse.gef.ui.actions.ActionRegistry;
26  import org.eclipse.jface.action.IAction;
27  import org.eclipse.jface.action.ICoolBarManager;
28  import org.eclipse.jface.action.IMenuListener;
29  import org.eclipse.jface.action.IMenuManager;
30  import org.eclipse.jface.action.IStatusLineManager;
31  import org.eclipse.jface.action.IToolBarManager;
32  import org.eclipse.jface.action.Separator;
33  import org.eclipse.swt.widgets.Menu;
34  import org.eclipse.ui.IWorkbenchActionConstants;
35  import org.eclipse.ui.IWorkbenchPart;
36  import org.w3c.dom.Attr;
37  import org.w3c.dom.Element;
38  import org.w3c.dom.NamedNodeMap;
39  import org.w3c.dom.Node;
40  
41  import sk.baka.ikslibs.DOMUtils;
42  import sk.baka.xml.gene.ExportUtils;
43  import sk.uniba.euromath.editor.EditorSite;
44  import sk.uniba.euromath.editor.actions.AbstractActionContributor;
45  import sk.uniba.euromath.editor.actions.IActionContributor;
46  import sk.uniba.euromath.editor.xmlEditor.actions.lang.Messages;
47  
48  /***
49   * Contributor for XMLEditor. Creates and fills context menu with actions for
50   * selecting and editing.
51   * 
52   * @author Tomáš Studva Sep 19, 2005
53   */
54  
55  public class XMLActionContributor extends AbstractActionContributor implements
56                  IActionContributor {
57  
58          /***
59           * Menu mamager for context menu.
60           */
61          protected EMMenuManager contextMenu;
62  
63          /***
64           * Insert before submenu manager.
65           */
66          protected EMMenuManager insertBeforeMenu;
67  
68          /***
69           * Insert child submenu manager.
70           */
71          protected EMMenuManager insertChildMenu;
72  
73          /***
74           * Insert after submenu manager.
75           */
76          protected EMMenuManager insertAfterMenu;
77  
78          /***
79           * Insert attribute submenu manager.
80           */
81          protected EMMenuManager attributeMenu;
82  
83          /***
84           * Global action registry.
85           */
86          private ActionRegistry globalActionRegistry;
87  
88          /***
89           * EditorSite.
90           */
91          private EditorSite editorSite;
92  
93          /***
94           * GraphicalViewer.
95           */
96          private GraphicalViewer graphicalViewer;
97  
98          /***
99           * Constructor.
100          * 
101          * @param site
102          *                EditorSite instance
103          * @param viewer
104          *                GraphicalViewer from XMLEditor, to which this
105          *                contributor contributes context menu
106          */
107         public XMLActionContributor(EditorSite site, GraphicalViewer viewer) {
108                 // site is selection provider, actions handles with editorsite
109                 // global
110                 // selection from all IEditors
111                 super(site, viewer.getEditDomain().getCommandStack());
112                 setEditorSite(site);
113                 setXMLAccess(site.getXMLAccess());
114                 setGraphicalViewer(viewer);
115                 createContextMenu();
116         }
117 
118         @Override
119         protected void configureFactory() {
120                 // undo, redo
121                 getActionFactory().registerAction(UndoAction.id,
122                                 UndoAction.class);
123                 getActionFactory().registerAction(RedoAction.id,
124                                 RedoAction.class);
125                 // clipboard actions
126                 getActionFactory()
127                                 .registerAction(CutAction.id, CutAction.class);
128                 getActionFactory().registerAction(CopyAction.id,
129                                 CopyAction.class);
130                 getActionFactory().registerAction(PasteAction.id,
131                                 PasteAction.class);
132                 // delete actions
133                 getActionFactory().registerAction(DeleteSelectionAction.id,
134                                 DeleteSelectionAction.class);
135                 // en(de)close
136                 getActionFactory().registerAction(DecloseElementAction.id,
137                                 DecloseElementAction.class);
138                 getActionFactory().registerAction(EnclosingAction.id,
139                                 EnclosingAction.class);
140                 // selections
141                 getActionFactory().registerAction(SelectParentAction.id,
142                                 SelectParentAction.class);
143                 // attribute actions
144                 getActionFactory().registerAction(AddAttributeWizardAction.id,
145                                 AddAttributeWizardAction.class);
146                 getActionFactory().registerAction(ModifyNodeAction.id,
147                                 ModifyNodeAction.class);
148         }
149 
150         /***
151          * Creates context menu on GraphicalViewer's control.
152          */
153         protected void createContextMenu() {
154                 // create and setup menuManager
155                 this.contextMenu = new EMMenuManager(
156                                 Messages
157                                                 .getString("XMLActionContributor.ContextMenuText"), //$NON-NLS-1$
158                                 ActionConsts.CONTEXT_MENU);
159                 this.contextMenu.setRemoveAllWhenShown(true);
160                 this.contextMenu.addMenuListener(new IMenuListener() {
161                         public void menuAboutToShow(IMenuManager manager) {
162                                 contributeToContextMenu(manager);
163                         }
164                 });
165                 // create SWT controll
166                 Menu contextMenu = this.contextMenu
167                                 .createContextMenu(getGraphicalViewer()
168                                                 .getControl());
169                 getGraphicalViewer().getControl().setMenu(contextMenu);
170                 // Be sure to register it so that other plug-ins can add
171                 // actions.
172                 getEditorSite().getSite().registerContextMenu(this.contextMenu,
173                                 getEditorSite());
174 
175                 // create and setup submenus
176                 this.insertBeforeMenu = new EMMenuManager(
177                                 Messages
178                                                 .getString("XMLActionContributor.InsertBeforeSubmenuText"), //$NON-NLS-1$,
179                                 ActionConsts.INSERT_BEFORE_SUBMENU);
180                 this.insertBeforeMenu.setRemoveAllWhenShown(true);
181                 this.insertBeforeMenu.addMenuListener(new IMenuListener() {
182                         public void menuAboutToShow(IMenuManager manager) {
183                                 populateInsertPositionMenu(manager,
184                                                 InsertPosition.Before);
185                         }
186                 });
187                 this.insertChildMenu = new EMMenuManager(
188                                 Messages
189                                                 .getString("XMLActionContributor.InsertChildSubmenuText"), //$NON-NLS-1$,
190                                 ActionConsts.INSERT_CHILD_SUBMENU);
191                 this.insertChildMenu.setRemoveAllWhenShown(true);
192                 this.insertChildMenu.addMenuListener(new IMenuListener() {
193                         public void menuAboutToShow(IMenuManager manager) {
194                                 populateInsertPositionMenu(manager,
195                                                 InsertPosition.AsFirstChild);
196                         }
197                 });
198                 this.insertAfterMenu = new EMMenuManager(
199                                 Messages
200                                                 .getString("XMLActionContributor.InsertAfterSubmenuText"), //$NON-NLS-1$
201                                 ActionConsts.INSERT_AFTER_SUBMENU);
202                 this.insertAfterMenu.setRemoveAllWhenShown(true);
203                 this.insertAfterMenu.addMenuListener(new IMenuListener() {
204                         public void menuAboutToShow(IMenuManager manager) {
205                                 populateInsertPositionMenu(manager,
206                                                 InsertPosition.After);
207                         }
208                 });
209                 this.attributeMenu = new EMMenuManager(
210                                 Messages
211                                                 .getString("XMLActionContributor.AttributeSubmenuText"), //$NON-NLS-1$
212                                 ActionConsts.ATTRIBUTE_SUBMENU);
213                 this.attributeMenu.setRemoveAllWhenShown(true);
214                 this.attributeMenu.addMenuListener(new IMenuListener() {
215                         public void menuAboutToShow(IMenuManager manager) {
216                                 populateAttributeMenu(manager);
217                         }
218                 });
219 
220         }
221 
222         /***
223          * Initialization of this contributor with access to global registry.
224          * 
225          * @param actionRegistry
226          *                global action registry
227          */
228         public void init(ActionRegistry actionRegistry) {
229                 this.globalActionRegistry = actionRegistry;
230         }
231 
232         /*
233          * (non-Javadoc)
234          * 
235          * @see sk.uniba.euromath.api.editor.IActionContributor#contributeToToolBar(org.eclipse.jface.action.IToolBarManager)
236          */
237         public void contributeToToolBar(IToolBarManager manager) {
238 
239         }
240 
241         /*
242          * (non-Javadoc)
243          * 
244          * @see sk.uniba.euromath.api.editor.IActionContributor#contributeToStatusLine(org.eclipse.jface.action.IStatusLineManager)
245          */
246         public void contributeToStatusLine(IStatusLineManager manager) {
247                 // position of cursor of mouse
248                 // manager.add();
249         }
250 
251         /*
252          * (non-Javadoc)
253          * 
254          * @see sk.uniba.euromath.api.editor.IActionContributor#contributeCoolBar(org.eclipse.jface.action.ICoolBarManager)
255          */
256         public void contributeCoolBar(ICoolBarManager manager) {
257 
258         }
259 
260         /*
261          * (non-Javadoc)
262          * 
263          * @see sk.uniba.euromath.api.editor.IActionContributor#contributeToMenu(org.eclipse.jface.action.IMenuManager)
264          */
265         public void contributeToMenu(IMenuManager manager) {
266 
267         }
268 
269         /***
270          * Fills context menu.
271          * 
272          * @param manager
273          */
274         protected void contributeToContextMenu(IMenuManager manager) {
275                 manager.add(new Separator(
276                                 IWorkbenchActionConstants.MB_ADDITIONS));
277 
278                 // Separator
279                 manager.add(new Separator(ActionConsts.UNDO_GROUP));
280                 // Undo
281                 manager.add(checkOrCreateAction(UndoAction.id));
282                 // Redo
283                 manager.add(checkOrCreateAction(RedoAction.id));
284                 // Separator
285                 manager.add(new Separator(ActionConsts.CLIPBOARD_GROUP));
286                 manager.add(checkOrCreateAction(CutAction.id));
287                 manager.add(checkOrCreateAction(CopyAction.id));
288                 manager.add(checkOrCreateAction(PasteAction.id));
289 
290                 // Separator
291                 manager.add(new Separator(ActionConsts.SELECTION_GROUP));
292                 // Delete
293                 manager.add(checkOrCreateAction(DeleteSelectionAction.id));
294                 manager.add(checkOrCreateAction(EnclosingAction.id));
295 
296                 // Separator
297                 manager.add(new Separator(ActionConsts.SELECTED_ELEMENT_GROUP));
298                 // declose action
299                 manager.add(checkOrCreateAction(DecloseElementAction.id));
300                 // Insert before - submenu
301                 this.insertBeforeMenu.add(checkOrCreateAction(EmptyAction.id));
302                 manager.add(this.insertBeforeMenu);
303                 // Insert as child - submenu
304                 this.insertChildMenu.add(checkOrCreateAction(EmptyAction.id));
305                 manager.add(this.insertChildMenu);
306                 // Insert after - submenu
307                 this.insertAfterMenu.add(checkOrCreateAction(EmptyAction.id));
308                 manager.add(this.insertAfterMenu);
309                 // Attribute - submenu
310                 this.attributeMenu.add(checkOrCreateAction(EmptyAction.id));
311                 manager.add(this.attributeMenu);
312                 // SelectParent action
313                 manager.add(checkOrCreateAction(SelectParentAction.id));
314 
315                 // Separator
316                 manager
317                                 .add(new Separator(
318                                                 ActionConsts.ANCESTORS_ELEMENT_GROUP));
319 
320                 // Element's submenus
321                 // retreive first element on path from selected to root
322                 // using SelectParentAction
323                 SelectParentAction action = (SelectParentAction) checkOrCreateAction(SelectParentAction.id);
324                 Node node = action.nodeToSelect;
325                 while ((node != null) && (node instanceof Element)) {
326                         EMMenuManager elementMenu = new EMMenuManager(node
327                                         .getNodeName());
328                         elementMenu.setRemoveAllWhenShown(true);
329                         elementMenu.setNode(node);
330 
331                         elementMenu.add(checkOrCreateAction(EmptyAction.id));
332 
333                         elementMenu.addMenuListener(new IMenuListener() {
334                                 public void menuAboutToShow(IMenuManager manager) {
335                                         populateElementMenu(manager);
336                                 }
337                         });
338                         node = node.getParentNode();
339                         manager.add(elementMenu);
340                 }
341                 manager.updateAll(true);
342         }
343 
344         /***
345          * Fills up element menu to right content. Prior element menu must be
346          * empty.
347          * 
348          * @param manager
349          *                of element menu
350          */
351         protected void populateElementMenu(IMenuManager manager) {
352                 EMMenuManager elementMenu = (EMMenuManager) (manager);
353 
354                 // Insert before - submenu
355                 EMMenuManager insertBeforeMenu = new EMMenuManager(
356                                 Messages
357                                                 .getString("XMLActionContributor.InsertBeforeSubmenuText"), //$NON-NLS-1$
358                                 ActionConsts.INSERT_BEFORE_SUBMENU);
359                 insertBeforeMenu.setRemoveAllWhenShown(true);
360                 insertBeforeMenu.setNode(elementMenu.getNode());
361                 insertBeforeMenu.addMenuListener(new IMenuListener() {
362                         public void menuAboutToShow(IMenuManager manager) {
363                                 populateInsertPositionMenu(manager,
364                                                 InsertPosition.Before);
365                         }
366                 });
367                 insertBeforeMenu.add(checkOrCreateAction(EmptyAction.id));
368                 elementMenu.add(insertBeforeMenu);
369                 //
370                 // Insert as child - submenu
371                 EMMenuManager insertChildMenu = new EMMenuManager(
372                                 Messages
373                                                 .getString("XMLActionContributor.InsertChildSubmenuText"), //$NON-NLS-1$
374                                 ActionConsts.INSERT_CHILD_SUBMENU);
375                 insertChildMenu.setRemoveAllWhenShown(true);
376                 insertChildMenu.setNode(elementMenu.getNode());
377                 insertChildMenu.addMenuListener(new IMenuListener() {
378                         public void menuAboutToShow(IMenuManager manager) {
379                                 populateInsertPositionMenu(manager,
380                                                 InsertPosition.AsFirstChild);
381                         }
382                 });
383                 insertChildMenu.add(checkOrCreateAction(EmptyAction.id));
384                 elementMenu.add(insertChildMenu);
385                 //
386                 // Insert after - submenu
387                 EMMenuManager insertAfterMenu = new EMMenuManager(
388                                 Messages
389                                                 .getString("XMLActionContributor.InsertAfterSubmenuText"), //$NON-NLS-1$
390                                 ActionConsts.INSERT_AFTER_SUBMENU);
391                 insertAfterMenu.setRemoveAllWhenShown(true);
392                 insertAfterMenu.setNode(elementMenu.getNode());
393                 insertAfterMenu.addMenuListener(new IMenuListener() {
394                         public void menuAboutToShow(IMenuManager manager) {
395                                 populateInsertPositionMenu(manager,
396                                                 InsertPosition.After);
397                         }
398                 });
399                 insertAfterMenu.add(checkOrCreateAction(EmptyAction.id));
400                 elementMenu.add(insertAfterMenu);
401                 //
402                 // Attribute - submenu
403                 EMMenuManager attributeMenu = new EMMenuManager(
404                                 Messages
405                                                 .getString("XMLActionContributor.AttributeSubmenuText"), //$NON-NLS-1$
406                                 ActionConsts.ATTRIBUTE_SUBMENU);
407                 attributeMenu.setRemoveAllWhenShown(true);
408                 attributeMenu.setNode(elementMenu.getNode());
409                 attributeMenu.addMenuListener(new IMenuListener() {
410                         public void menuAboutToShow(IMenuManager manager) {
411                                 populateAttributeMenu(manager);
412                         }
413                 });
414                 attributeMenu.add(checkOrCreateAction(EmptyAction.id));
415                 elementMenu.add(attributeMenu);
416 
417                 // Select action
418                 String nodeId = getXMLAccess().getIDManager().getID(
419                                 elementMenu.getNode());
420                 elementMenu.add(new SelectAction(nodeId, getWorkbenchPart()));
421 
422                 // Delete action
423                 elementMenu.add(new DeleteNodeAction(elementMenu.getNode(),
424                                 getWorkbenchPart()));
425 
426                 elementMenu.updateAll(true);
427         }
428 
429         /***
430          * Fills up insert before/child/after/ at caret menu to right content.
431          * Insert menu must be empty prior.
432          * 
433          * @param manager
434          *                of insert before menu
435          * @param position
436          *                any of {@link InsertPosition}
437          */
438         protected void populateInsertPositionMenu(IMenuManager manager,
439                         InsertPosition position) {
440                 manager.add(new PasteAction(position, getWorkbenchPart()));
441                 manager.add(new Separator());
442                 // if menu is not context, is has associated element it works
443                 // with
444                 Element element = (Element) (((EMMenuManager) manager)
445                                 .getNode());
446                 InsertAction action = null;
447 
448                 if (element != null) {
449                         action = new InsertElementAction(element, position,
450                                         null, getWorkbenchPart());
451                 } else {
452                         action = new InsertElementAction(position, null,
453                                         getWorkbenchPart());
454                 }
455 
456                 action.update();
457                 manager.add(action);
458 
459                 // Separator
460                 manager.add(new Separator(
461                                 ActionConsts.INSERT_ELEMENT_WITH_NAME_GROUP));
462                 // Insert actions by element name
463                 if (action.isEnabled()) {
464                         List<QName> qNames = getDocumentModifyHelper()
465                                         .getInsertableElementsQNames(
466                                                         action.getPointer());
467                         for (QName qName : qNames) {
468                                 if (element == null) {
469                                         XMLAccessModifyAction act = new InsertElementAction(
470                                                         position, qName,
471                                                         getWorkbenchPart());
472                                         act.update();
473                                         manager.add(act);
474                                 } else {
475                                         XMLAccessModifyAction act = new InsertElementAction(
476                                                         element, position,
477                                                         qName,
478                                                         getWorkbenchPart());
479                                         act.update();
480                                         manager.add(act);
481                                 }
482 
483                         }
484                 }
485                 manager.updateAll(true);
486         }
487 
488         /***
489          * Fills up attribute menu to right content. Prior attribute menu must
490          * be empty.
491          * 
492          * @param manager
493          *                of attribute menu
494          */
495         protected void populateAttributeMenu(IMenuManager manager) {
496                 Element element = (Element) (((EMMenuManager) manager)
497                                 .getNode());
498                 AddAttributeWizardAction addWizardAction;
499 
500                 if (element != null) {
501                         addWizardAction = new AddAttributeWizardAction(element,
502                                         getWorkbenchPart());
503                 } else {
504                         addWizardAction = (AddAttributeWizardAction) (checkOrCreateAction(AddAttributeWizardAction.id));
505                 }
506                 addWizardAction.update();
507 
508                 if (addWizardAction.isEnabled()) {
509 
510                         NamedNodeMap attributes = addWizardAction.getNode()
511                                         .getAttributes();
512                         for (int i = 0; i < attributes.getLength(); i++) {
513                                 Attr attribute = (Attr) (attributes.item(i));
514                                 // if it
515                                 // is
516                                 // emp:id attribute, ignore it
517                                 if (!(DOMUtils
518                                                 .equalsNodeQName(
519                                                                 attribute,
520                                                                 ExportUtils.GENE_ID_ATTRIBUTE_QNAME))) {
521                                         EMMenuManager attrMenu = new EMMenuManager(
522                                                         attribute.getName());
523                                         attrMenu.add(new DeleteNodeAction(
524                                                         attribute,
525                                                         getWorkbenchPart()));
526                                         IAction action = new ModifyNodeAction(
527                                                         attribute,
528                                                         getWorkbenchPart());
529                                         action.setText("Modify value");
530                                         attrMenu.add(action);
531                                         manager.add(attrMenu);
532                                 }
533                         }
534 
535                 }
536                 manager.add(new Separator(ActionConsts.ADD_ATTRIBUTE_GROUP));
537                 manager.add(addWizardAction);
538                 manager.updateAll(true);
539         }
540 
541         /*
542          * (non-Javadoc)
543          * 
544          * @see sk.uniba.euromath.editor.actions.IActionContributor#getGlobalActionHandlers()
545          */
546         public Map<String, IAction> getGlobalActionHandlers() {
547                 Map<String, IAction> result = new HashMap<String, IAction>();
548                 // undo, redo
549                 result.put(UndoAction.id, checkOrCreateAction(UndoAction.id));
550                 result.put(RedoAction.id, checkOrCreateAction(RedoAction.id));
551                 // cut, copy, paste
552                 result.put(CutAction.id, checkOrCreateAction(CutAction.id));
553                 result.put(CopyAction.id, checkOrCreateAction(CopyAction.id));
554                 result.put(PasteAction.id, checkOrCreateAction(PasteAction.id));
555                 // delete
556                 result.put(DeleteSelectionAction.id,
557                                 checkOrCreateAction(DeleteSelectionAction.id));
558                 return result;
559         }
560 
561         /***
562          * Global registry for all IEditors.
563          * 
564          * @return action registry
565          */
566         public ActionRegistry getGlobalActionRegistry() {
567                 return this.globalActionRegistry;
568         }
569 
570         /***
571          * @return Returns the editorSite.
572          */
573         public EditorSite getEditorSite() {
574                 return this.editorSite;
575         }
576 
577         /***
578          * @param editorSite
579          *                The editorSite to set.
580          */
581         public void setEditorSite(EditorSite editorSite) {
582                 this.editorSite = editorSite;
583         }
584 
585         /***
586          * @return Returns the graphicalViewer.
587          */
588         public GraphicalViewer getGraphicalViewer() {
589                 return this.graphicalViewer;
590         }
591 
592         /***
593          * @param graphicalViewer
594          *                The graphicalViewer to set.
595          */
596         public void setGraphicalViewer(GraphicalViewer graphicalViewer) {
597                 this.graphicalViewer = graphicalViewer;
598         }
599 
600         /***
601          * @param globalActionRegistry
602          *                The globalActionRegistry to set.
603          */
604         public void setGlobalActionRegistry(ActionRegistry globalActionRegistry) {
605                 this.globalActionRegistry = globalActionRegistry;
606         }
607 
608         @Override
609         public IWorkbenchPart getWorkbenchPart() {
610                 return getEditorSite();
611         }
612 
613         @Override
614         public ActionRegistry getActionRegistry() {
615                 return this.globalActionRegistry;
616         }
617 }