Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » GMF (Graphical Modeling Framework) » GMF & EMF Validation: Flush of Undo/Redo history(When using EMF live constraints in GMF the undo/redo histrory is deleted )
GMF & EMF Validation: Flush of Undo/Redo history [message #684018] Tue, 14 June 2011 21:28 Go to next message
Ekkart Kindler is currently offline Ekkart KindlerFriend
Messages: 2
Registered: June 2011
Junior Member
Dear GMF-experts,

I have integrated an EMF editor with several GMF editors working on the same
model. This integration works fine (also with undo/redo across all the editors).
Since there is also an EMF editor involved, I cannot use the GMF audit mechanism
for validation. I chose to use EMF validation instead - with many batch and
some live constraints. And this results in a minor but not user-friendly effect:

When a GMF editor is open and the user makes a change that violates a live
constraint, the change is rolled back (which it should); unfortunately,
the GMF editor also deletes the complete operation history; no undo
is possible beyond that point. Which is very nasty from a user perspective.

I analysed the source of the problem: I traced this back to the standard
GlobalUndoAction and GlobalRedoAction, which configure their "delegates" in
such a way that they flush the operation history when an exeuted command turns
out not to be executable (which is the case when a constraint is violated). I
guess that this is considered a feature of GMF, since it might help avoiding
unexpected effects when multiple editors are not properly integrated.

In order to work around that, I wrote my own GlobalUndo- and -RedoActions (minor
modifications of the standard one, just not configuring the delegate with the
flush flag set to true) and added them via a ContributionItemProvider to my
GMF editor. And I checked with the debugger that the GMF editor now used my
GlobalUndo- and RedoActions.

The actual problem is, that the orginal GlobalUndoAction and -RedoAction are
not completely removed (due to GMFs policy the are installed first, and than
overwritten by my higher priority Actions) from the GMF editor. Though the
original actions are not used in the GMF editor anymore, they are still
registered as listeners to the operation history -- and therefore, they still
flush the operation history on failed validations. This effect, I did not
expect (in the debugger, I could see that the original Undo- Redo actions
will only be disposed, when the respective GMF editor is closed).

Now my questions:
1. Should I consider this as a bug of GMF?

2. Is there a simple easy and non-intrusive way to get rid of the
original GlobalUndo- and -RedoAction -- and detach their listeners
from the operation history (or is there a non-intrusive way to get
hold of them, so that I could dispose of them myself).

3. BTW: I checked GMF's ContributionItemProvider mechanism. I found some
mechanisms to delete menus and other parts; but also here, there was no
way to really dispose of the actual PartActions. Or is there a mechanism
to do that, that I am not aware of?

4. Is there any other way to make GMF aware of RollbackExceptions caused
by EMF-Validation and make GMF ignore them instead of flushing the
operation history?

I would appreciate your help.

Best regards,
Ekkart Kindler
Re: GMF & EMF Validation: Flush of Undo/Redo history [message #697155 is a reply to message #684018] Fri, 15 July 2011 16:58 Go to previous message
Ekkart Kindler is currently offline Ekkart KindlerFriend
Messages: 2
Registered: June 2011
Junior Member
Dear all,

since I did not get any response to this post, I had a deeper look into this problem myself and implemented a workaround. This workaround is a bit more intrusive that I wanted it to be, but it should be clean and clear enough for being used in general.

In the following, I will explain the idea of the workaround and show some code snippets for the mains steps of this solution.

As stated in the original posting, the problem was that the original GlobalUndo- and GlobalRedoActions were not properly deinstalled, when pluging in new GlobalUndo- and GlobalRedoActions. Therefore, I needed to remove the original actions programmatically; I then also installed the new actions programmatically. This required the following steps:

  1. I copied the classes GlobalRedoAction, GlobalUndoAction and GlobalUndoRedoLock from the package org.eclipse.gmf.runtime.common.ui.action.actions.global (in plugin org.eclipse.gmf.runtime.common.ui.action) to to some package in my plugin. In each of the copied classes GlobalRedoAction and GlobalUndoAction, a single line in the method initializeWithContext(IUndoContext context) needed to be deleted:

          delegate.setPruneHistory(true);
    

    Note that GlobalUndoRedoLock does not need to be changed at all. It needs to be copied anyway due to some visibility restrictions on the GlobalUndoRedoLock in the original package.

    In order to avoid nameconflicts, I renamed the two changed classes to GlobalUndoActionNoPrune and GlobalRedoActionNoPrune.

  2. The next step is to remove the old actions (action handlers) along with their delegates. I figured that the best place to do that is in the init() method of the class XXXDiagramActionBarContributer.

    To this end, I renamed the originally generated method init to initGen. The new init() method, then first calls the initGen method and after that the undo and the originally installed redo action handler are removed and the new ones are installed. Here is the code snipped for removing the undo handler (the code for the redo is analog):

         // get the installed original undo action handler
         String undo = ActionFactory.UNDO.getId();
         IAction action = bars.getGlobalActionHandler(undo);
         if (action != null) {
           // set the new undo action
           bars.setGlobalActionHandler(undo, new GlobalUndoActionNoPrune(page));
           if (action instanceof GlobalUndoAction) {
             // and properly dispose of the old one (the setUndoContext(null)
             // is needed to also properly dispose of the delegate of the
             // original GlobalUndoAction (which does the actual harm)
             ((GlobalUndoAction) action).setUndoContext(null);
             ((GlobalUndoAction) action).dispose();
           }
         }
    

    The comments should explain the main steps. Note that we need to get hold of the original action before we add the new one in order to also properly get rid of the delegate that sits behind the original GlobalUndoAction. To this end, the setUndoContext method is called with null (calling the dispose only is not enough -- which is due to a fix of another bug; see comments in the original Undo and redo action handlers) and then disposed of it.

  3. The third step is needed to avoid the installation of the original Undo and Redo actions in the PropertiesBrowser and to install the new actions instead. The installation of these actions, actually, happens at a different place: these are installed by creating an adapter on the actual XXXDiagramEditor. So, I implemented the method getAdapter(Class type) in the XXXDiagramEditor (after renaming the original one to getAdapterGen). The code looks as follows:

         public Object getAdapter(Class type) {
           if (type == IPropertySheetPage.class) {
             return new PropertiesBrowserPageNoPrune(this);
           }
           return getAdapterGen(type);
         }
    

    The new class PropertiesBrowerPageNoPrune extends the original PropertiesBrowserPage; in that new class only the method setActionBars() needs to be overwritten to install the new Undo and Redo handlers instead of the original ones:

         public void setActionBars(IActionBars actionBars) {
           ITabbedPropertySheetPageContributor contributor = this.getContributor();
           if (contributor != null && contributor instanceof IWorkbenchPart) {
             actionBars.setGlobalActionHandler(
               ActionFactory.UNDO.getId(),
               new GlobalUndoActionNoPrune((IWorkbenchPart) contributor));		
             actionBars.setGlobalActionHandler(
               ActionFactory.REDO.getId(),
               new GlobalRedoActionNoPrune((IWorkbenchPart) contributor));
           }
         }
    
    


I hope that this is enough information for fixing this problem in your own GMF editor. If you need to see more details, you may have a look in my editor, which is the graphical editor of the ePNK (version 0.9.2). The code is freely available (see the ePNK home page for details; since I am not allowed to send the link, you need to google for it -- sorry). In the ePNK project, you will find this editor in the feature "ePNK Core 0.9.2" in the plugin org.pnml.tools.epnk.diagram. In this plugin, the new undo- and redo handlers can be found in package experiment.globalhandlers, which also contains the new class PropertiesBrowserPageNoPrune. The two other classes that were manually changed for solving this problem are in the package org.pnml.tools.epnk.diagram.part:

  • PNMLCoreModelDiagramActionBarContributor (method init)
  • PNMLCoreModelDiagramEditor (method getAdapter)


Best regards,
Ekkart Kindler
Previous Topic:How can I create the connection line like in the figure
Next Topic:Phantom node bugs on GMF Tooling
Goto Forum:
  


Current Time: Fri Mar 05 08:26:50 GMT 2021

Powered by FUDForum. Page generated in 0.02085 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top