Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog
[EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900231] Sun, 05 August 2012 22:08 Go to next message
Paco Blanco is currently offline Paco Blanco
Messages: 28
Registered: June 2012
Junior Member
I try to do this:
- To change an EMF model object by an UI Dialog (jface TitleAreaDialog)
- To register the changes in the CommandStack only if user does a click in the Ok Button of the Dialog
- To undo the possible changes in the dialog if user does a click in the Cancel Button (not register the changes in the CommandStack)

To register the changes, I use ChangeCommand.
My Code is more or less the next:
Collection<Notifier> objectsToRecord = new ArrayList<Notifier>();
objectsToRecord.add(objectToRegisterChanges);
cancel = false;
ChangeCommand changeCommand = new ChangeCommand(objectsToRecord) {
   @Override
   protected void doExecute() {
      CustomDialog editorDialog =  new CustomDialog(
         PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.NONE,
         objectToRegisterChanges);
      editorDialog.create();
      if (editorDialog.open() != Window.OK) {
         cancel = true;
      }
   }
};
getCommandStack().execute(command);
if(cancel) {
   getCommandStack().undo();
}


objectToRegisterChanges is an EMF Object
CustomDialog extends JFace TitleAreaDialog where attributes and list belong to objectToRegisterChanges are changed
getCommandStack() returns my own BasicCommandStack

Even if user does a click in Cancel Button, the changes in the objectToRegisterChanges are added to CommandStack by the ChangeCommand. My code logically does the undo in this case but the command is on the top of the CommandStack and it can be redo

Does someone say to me the best solution for my situation or guide me??
Re: [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900243 is a reply to message #900231] Mon, 06 August 2012 07:02 Go to previous messageGo to next message
Christoph Keimel is currently offline Christoph Keimel
Messages: 371
Registered: December 2010
Location: Germany
Senior Member
Commands should be executed AFTER the user has presses OK in your dialog. That could look something like this:

CustomDialog editorDialog =  new CustomDialog(..., objectsToRecord);
editorDialog.create()
if (editorDialog.open() == Window.OK) {
    ChangeCommand changeCommand = new ChangeCommand(objectsToRecord);
    getCommandStack().execute(command);
}
Re: [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900266 is a reply to message #900243] Mon, 06 August 2012 09:18 Go to previous messageGo to next message
Paco Blanco is currently offline Paco Blanco
Messages: 28
Registered: June 2012
Junior Member
Christoph, Thank for your answer but I think it does not work.
I know the correct way to put Command in the stack is after Ok pressing but two things:
- ChangeCommand is an abstract class that needs a doExecute method where the changes must be produced (or at least I think so)
- If user cancels the dialog, we have to undo all possibles changes (in the dialog, I like to use EMF databinding so changes in UI components are automatically reflected in the attributes of the model object)
Re: [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900299 is a reply to message #900266] Mon, 06 August 2012 12:07 Go to previous messageGo to next message
Christoph Keimel is currently offline Christoph Keimel
Messages: 371
Registered: December 2010
Location: Germany
Senior Member
Hi Paco

my approach to this is:
- copy the object to edit (detached from the resource)
- let the user edit all he likes in the dialog or wizard
- on cancel: do nothing (because the original object is unchanged)
- on ok: use an emf command to copy the changed attributes to the original object

I only use undo() if the user chooses the undo-action in the menu or toolbar.

Greetings
Christoph
Re: [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900318 is a reply to message #900299] Mon, 06 August 2012 13:05 Go to previous messageGo to next message
Ed Merks is currently offline Ed Merks
Messages: 26150
Registered: July 2009
Senior Member
Christoph,

Yes, that sounds better.


On 06/08/2012 2:07 PM, Christoph Keimel wrote:
> Hi Paco
>
> my approach to this is:
> - copy the object to edit (detached from the resource)
> - let the user edit all he likes in the dialog or wizard
> - on cancel: do nothing (because the original object is unchanged)
> - on ok: use an emf command to copy the changed attributes to the
> original object
>
> I only use undo() if the user chooses the undo-action in the menu or
> toolbar.
>
> Greetings
> Christoph
Re: [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900332 is a reply to message #900299] Mon, 06 August 2012 14:17 Go to previous messageGo to next message
John Steele is currently offline John Steele
Messages: 49
Registered: January 2010
Member
Yep, I'd do it the same way. Another reason why I like to only change the model if the user selects okay is because if other clients (e.g., views, editors, etc) are using the same data they will reflect those changes even though the changes might not be permanent. This could cause those views to trigger webservices, etc.
Re: [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900347 is a reply to message #900332] Mon, 06 August 2012 14:53 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 5434
Registered: July 2009
Senior Member
We are directly executing the changes on the model, because our
validation system can not do cross object validations without it.

Our approach is that we've customized the EditingDomain so that we can
set a SavePoint on it (similar to what you do with a database), if the
user hits cancel we simply rollback to the save point.

In pseudo code we do:

ISavePointEditingDomain d = ....
SavePoint p = d.createSavePoint();

TitleAreaDialog d = ....
if( d.open() == Window.OK ) {
p.dispose();
} else {
p.rollback();
}

Tom

Am 06.08.12 16:17, schrieb John Steele:
> Yep, I'd do it the same way. Another reason why I like to only change
> the model if the user selects okay is because if other clients (e.g.,
> views, editors, etc) are using the same data they will reflect those
> changes even though the changes might not be permanent. This could cause
> those views to trigger webservices, etc.
Re: [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900358 is a reply to message #900347] Mon, 06 August 2012 15:33 Go to previous messageGo to next message
Paco Blanco is currently offline Paco Blanco
Messages: 28
Registered: June 2012
Junior Member
Step by step:
- Christoph / John. You are right that changes in the model are automatically reflected in other views/editors with databinding. In my case, I use CDO to manage model modifications so other clients/views/editors have their own CDO instance that are only refreshed when a commit is executed.
1) My model object has a list, not more than 10 items inside. But do you considerer the copy of the object is the better way if you have a list with 1000 items?


- Thomas, savePoint could give a solution but
2) where is the commandStack to undo/redo the changes? Because if user hits Ok, we want to give him the possibility of undo/redo these changes.


My new code that works Razz
Collection<Notifier> objectsToRecord = new ArrayList<Notifier>();
objectsToRecord.add(objectToRegisterChanges);
ChangeRecorder changeRecorder = new ChangeRecorder();
changeRecorder.beginRecording(objectsToRecord);
CustomDialog editorDialog =  new CustomDialog(..., objectToRegisterChanges);
editorDialog .create();
int respond = editorDialog.open();
MyChangeCommand changeCommand = new MyChangeCommand(changeRecorder, objectsToRecord) {
   @Override
   protected void doExecute() {}
};
if (respond == Window.OK) {
   getCommandStack().execute(changeCommand);				    	
} else {
   changeCommand.execute();
   changeCommand.undo();
}


....


abstract class MyChangeCommand extends ChangeCommand {
  public MyChangeCommand(ChangeRecorder changeRecorder, Collection<Notifier> notifiers) {
     super(notifiers);
     this.changeRecorder = changeRecorder;
  }
		
  @Override
  public void execute() { 
     ChangeRecorder changeRecorder = getChangeRecorder();
     if (changeRecorder == null) {
        changeRecorder = createChangeRecorder();
        changeRecorder.beginRecording(notifier != null ? Collections.singleton(notifier) : notifiers);
     }
     try {
        doExecute();
     } finally {
        setChangeDescription(changeRecorder.endRecording());
        disposeChangeRecorder(changeRecorder);
     }    
  }  
}


What is your opinion?

[Updated on: Mon, 06 August 2012 15:41]

Report message to a moderator

Re: [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900410 is a reply to message #900358] Mon, 06 August 2012 21:42 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 5434
Registered: July 2009
Senior Member
So you want to undo those changes in one big undo instead of step by
step ones?

Tom

Am 06.08.12 17:33, schrieb Paco Blanco:
> Step by step:
> - Christoph / John. You are right that changes in the model are
> automatically reflected in other views/editors with databinding. In my
> case, I use CDO to manage model modifications so other
> clients/views/editors have their own CDO instance that be only refreshed
> when a commit is executed.
> 1) My model object has a list, not much than 10 items inside. But do
> you considerer the copy of the object is the better way if you have a
> list with 1000 items?
>
>
> - Thomas, savePoint could give a solution but 2) where is the
> commandStack to undo/redo the changes? Because if user hits Ok, we want
> to give him the possibility of undo/redo these changes.
>
>
> My new code that works :p
>
> Collection<Notifier> objectsToRecord = new ArrayList<Notifier>();
> objectsToRecord.add(objectToRegisterChanges);
> ChangeRecorder changeRecorder = new ChangeRecorder();
> changeRecorder.beginRecording(objectsToRecord);
> CustomDialog editorDialog = new CustomDialog(...,
> objectToRegisterChanges);
> editorDialog .create();
> int respond = editorDialog.open();
> MyChangeCommand changeCommand = new MyChangeCommand(changeRecorder,
> objectsToRecord) {
> @Override
> protected void doExecute() {}
> };
> if (respond == Window.OK) {
> getCommandStack().execute(changeCommand);
> } else {
> changeCommand.execute();
> changeCommand.undo();
> }
>
>
> ...
>
>
> abstract class MyChangeCommand extends ChangeCommand {
> public MyChangeCommand(ChangeRecorder changeRecorder,
> Collection<Notifier> notifiers) {
> super(notifiers);
> this.changeRecorder = changeRecorder;
> }
>
> @Override
> public void execute() { ChangeRecorder changeRecorder =
> getChangeRecorder();
> if (changeRecorder == null) {
> changeRecorder = createChangeRecorder();
> changeRecorder.beginRecording(notifier != null ?
> Collections.singleton(notifier) : notifiers);
> }
> try {
> doExecute();
> } finally {
> setChangeDescription(changeRecorder.endRecording());
> disposeChangeRecorder(changeRecorder);
> } } }
>
>
> What is your opinion?
Re: [EMF] [CommandStack] Best Practices to use ChangeCommand around UI Dialog [message #900512 is a reply to message #900410] Tue, 07 August 2012 10:43 Go to previous message
Paco Blanco is currently offline Paco Blanco
Messages: 28
Registered: June 2012
Junior Member
Yes, I do. It is my approach. (Inside the dialog, we can put step by step undo/redo of each change. When users exists, all of them must be in an only command)
Previous Topic:XMLTypeFactoryImpl doesn't support XSD compliant representations of infinity
Next Topic:[CDO/Hibernate] NPE: at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromJoinElement(HqlSqlWalk
Goto Forum:
  


Current Time: Thu Oct 30 14:33:31 GMT 2014

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

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