Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » How to use swt TextField to edit an attribute?
How to use swt TextField to edit an attribute? [message #387801] Mon, 20 September 2004 23:14 Go to next message
Michael Scharf is currently offline Michael ScharfFriend
Messages: 301
Registered: July 2009
Senior Member
Hi,

I wonder what is the best way to edit a simple attribute using
as TextField.

To set the value I do something like:

void setModelValue(Object value, EObject eObject, EStructuralFeature feature) {
EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject);
if(editingDomain==null) {
eObject.eSet(feature,value);
} else {
editingDomain.getCommandStack().execute(SetCommand.create(ed itingDomain, eObject, feature, value));
}
}

The problem is the number of commands executed, when I use
Text field=...;
....
field.addModifyListener(new ModifyListener(){
public void modifyText(ModifyEvent e) {
setModelValue(...);
}
});
With this approach I execute a new command on each keystroke.

To prevent this, I could do:

field.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
setModelValue(...);
}
});


With this approach, I execute the command only if the user leaves the
field. This is a bit problematic, because if the user enters something
into the field and then goes to the menu bar Edit->Undo there is nothing
to undo until field has lost the focus.

The propery editors have the same problem: edit a field and you can only
undo if the focus has left the property editor.

Is there another way attaching a text field with an attribute?

Is there a way to accumulate edit operations that are executed as one
operation in the undo stack? ET++ had this feature 15 years ago in the
editor: when the user started typing a new command was created (and added to
the undo stack). While the user was typing the command object was "extended"
unless the cursor was moved or the focus changed, the typing was added to the
single command. Does something like this exist in EMF or would I have to create
it myself?


Michael
Re: How to use swt TextField to edit an attribute? [message #387804 is a reply to message #387801] Tue, 21 September 2004 12:59 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Michael,

The focus approach sounds right. Technically, when editing an entry
field, the Edit menu's undo should reflect the popup action you would
get in the entry field, which will undo the changes in the entry field,
not the model action. One could also use a timeout approach where no
changes after a long enough delay will make the changes "kick in", but
that doesn't seem better. Note that you can always remember the top of
the stack when you started and undo back to that point, even if you did
execute multiple commands. EMF doesn't have any way to accumulate a
command; that kind of thing makes more sense in a text editor than when
editing attribute values of a structured model, since adding a character
to a numeric value isn't simply an extension of what's already done,
it's a whole new different value.

I'd be very interested to hear opinions from other folks who have
implemented stuff like this.


Michael Scharf wrote:

> Hi,
>
> I wonder what is the best way to edit a simple attribute using
> as TextField.
>
> To set the value I do something like:
>
> void setModelValue(Object value, EObject eObject,
> EStructuralFeature feature) {
> EditingDomain editingDomain =
> AdapterFactoryEditingDomain.getEditingDomainFor(eObject);
> if(editingDomain==null) {
> eObject.eSet(feature,value);
> } else {
>
> editingDomain.getCommandStack().execute(SetCommand.create(ed itingDomain,
> eObject, feature, value));
> }
> }
>
> The problem is the number of commands executed, when I use
> Text field=...;
> ....
> field.addModifyListener(new ModifyListener(){
> public void modifyText(ModifyEvent e) {
> setModelValue(...);
> }
> });
> With this approach I execute a new command on each keystroke.
>
> To prevent this, I could do:
>
> field.addFocusListener(new FocusListener() {
> public void focusGained(FocusEvent e) {
> }
> public void focusLost(FocusEvent e) {
> setModelValue(...);
> }
> });
>
>
> With this approach, I execute the command only if the user leaves the
> field. This is a bit problematic, because if the user enters something
> into the field and then goes to the menu bar Edit->Undo there is nothing
> to undo until field has lost the focus.
>
> The propery editors have the same problem: edit a field and you can only
> undo if the focus has left the property editor.
>
> Is there another way attaching a text field with an attribute?
>
> Is there a way to accumulate edit operations that are executed as one
> operation in the undo stack? ET++ had this feature 15 years ago in the
> editor: when the user started typing a new command was created (and
> added to
> the undo stack). While the user was typing the command object was
> "extended"
> unless the cursor was moved or the focus changed, the typing was added
> to the
> single command. Does something like this exist in EMF or would I have
> to create
> it myself?
>
>
> Michael


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: How to use swt TextField to edit an attribute? [message #1184569 is a reply to message #387804] Wed, 13 November 2013 14:46 Go to previous messageGo to next message
Ingo Mohr is currently offline Ingo MohrFriend
Messages: 23
Registered: September 2011
Junior Member
Hi all,

it's some time since the last post, so maybe there is some built-in solution for this, now. I hope so. Smile

I have a couple of editors that work on EMF models and that use SWT-Text widgets with ModifyListeners - so each character typed into a Text widget is executed as a single EMF Command on the CommandStack. And thus each Undo undoes exactly the last character-change.

What I'm looking for is some solution in which...
- ... the user can type as they want, then invoke "undo" and have the last bunch of characters undone (as for text editors)
- ... that immediately causes the editor to get dirty (at the very first character typed in)
- ... that does not require the user to move the focus out of the Text widget in order to "kick-in" the changes to the model

Maybe there is a way of "merging" commands on the stack? I didn't find a solution to this, so far. The emf-generated editor plug-ins don't seem to use Text widgets as such. They use CellEditors instead which follow a different usecase-approach (you're typing the text and then "send-in" that text). This would do, but I cannot change the UI.

Do you have any suggestions?

Big thanks in advance!

Ingo
Re: How to use swt TextField to edit an attribute? [message #1184590 is a reply to message #1184569] Wed, 13 November 2013 15:04 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Ingo,

Perhaps the JFace data binding framework supports such delays
reactions. Alternatively you could change the design so you apply the
change when your the widget loses focus...

On 13/11/2013 3:46 PM, Ingo Mohr wrote:
> Hi all,
>
> it's some time since the last post, so maybe there is some built-in
> solution for this, now. I hope so. :)
>
> I have a couple of editors that work on EMF models and that use
> SWT-Text widgets with ModifyListeners - so each character typed into a
> Text widget is executed as a single EMF Command on the CommandStack.
> And thus each Undo undoes exactly the last character-change.
>
> What I'm looking for is some solution in which...
> - ... the user can type as they want, then invoke "undo" and have the
> last bunch of characters undone (as for text editors)
> - ... that immediately causes the editor to get dirty (at the very
> first character typed in)
> - ... that does not require the user to move the focus out of the Text
> widget in order to "kick-in" the changes to the model
>
> Maybe there is a way of "merging" commands on the stack? I didn't find
> a solution to this, so far. The emf-generated editor plug-ins don't
> seem to use Text widgets as such. They use CellEditors instead which
> follow a different usecase-approach (you're typing the text and then
> "send-in" that text). This would do, but I cannot change the UI.
>
> Do you have any suggestions?
>
> Big thanks in advance!
>
> Ingo


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: How to use swt TextField to edit an attribute? [message #1184711 is a reply to message #1184569] Wed, 13 November 2013 16:40 Go to previous messageGo to next message
Mikael Barbero is currently offline Mikael BarberoFriend
Messages: 55
Registered: July 2009
Member
Databinding is providing something functional but if you don't use it, you have to rewrite the behavior. A solution is to use a background thread and reschedule it everytime a character is entered. I like to use java's ScheduledExecutorService (Java 5+) for that. Something like this should work:

class DelayedExecutor {

	private static final int DELAY = 500;

	private final ScheduledExecutorService executor;

	private Future<?> currentFuture;

	DelayedExecutor(ScheduledExecutorService executor) {
		this.executor = executor;
	}

	public void schedule(Runnable run) {
		if (currentFuture != null && !currentFuture.isDone()) {
			currentFuture.cancel(false);
		}
		final ScheduledFuture<?> future = executor.schedule(run, DELAY, TimeUnit.MILLISECONDS);
		currentFuture = future;
	}
}


And then in your class where your SWT Text is located:

private DelayedExecutor delayedExecutor;
private ScheduledExecutorService executorService;

executorService = Executors.newSingleThreadScheduledExecutor();
delayedExecutor = new DelayedExecutor(executorService);

textWidget.addModifyListener(new ModifyListener() {
  public void modifyText(ModifyEvent e) {
    // execute the desired command on the command stack.
  }
});


Do not forget to shutdown the executor service when not needed anymore (probably disposal of your editor)

try {
  executorService.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
  throw new RuntimeException(e);
}
executorService.shutdown();


The only requirement it does not fill is

Quote:
... that immediately causes the editor to get dirty (at the very first character typed in).

But I don't see any way to do it while supporting the undo/redo properly.

Hope this helps.


Best regards,

Mikael Barbero
Obeo
Re: How to use swt TextField to edit an attribute? [message #1184742 is a reply to message #1184711] Wed, 13 November 2013 17:01 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Mikael,

Comments below.

On 13/11/2013 5:40 PM, Mikael Barbero wrote:
> Databinding is providing something functional but if you don't use it,
> you have to rewrite the behavior. A solution is to use a background
> thread and reschedule it everytime a character is entered.
I've done something similar using
org.eclipse.swt.widgets.Display.timerExec(int, Runnable) where I record
in the runnable the current contents and check if they've changed when
the timer event arrives. If not, I do it again. Much the same idea,
but no extra thread.
> I like to use java's ScheduledExecutorService (Java 5+) for that.
> Something like this should work:
>
>
> class DelayedExecutor {
>
> private static final int DELAY = 500;
>
> private final ScheduledExecutorService executor;
>
> private Future<?> currentFuture;
>
> DelayedExecutor(ScheduledExecutorService executor) {
> this.executor = executor;
> }
>
> public void schedule(Runnable run) {
> if (currentFuture != null && !currentFuture.isDone()) {
> currentFuture.cancel(false);
> }
> final ScheduledFuture<?> future = executor.schedule(run,
> DELAY, TimeUnit.MILLISECONDS);
> currentFuture = future;
> }
> }
>
>
> And then in your class where your SWT Text is located:
>
>
> private DelayedExecutor delayedExecutor;
> private ScheduledExecutorService executorService;
>
> executorService = Executors.newSingleThreadScheduledExecutor();
> delayedExecutor = new DelayedExecutor(executorService);
>
> textWidget.addModifyListener(new ModifyListener() {
> public void modifyText(ModifyEvent e) {
> // execute the desired command on the command stack.
> }
> });
>
>
> Do not forget to shutdown the executor service when not needed anymore
> (probably disposal of your editor)
>
>
> try {
> executorService.awaitTermination(1, TimeUnit.SECONDS);
> } catch (InterruptedException e) {
> throw new RuntimeException(e);
> }
> executorService.shutdown();
>
>
> The only requirement it does not fill is
> Quote:
>> ... that immediately causes the editor to get dirty (at the very
>> first character typed in).
>
> But I don't see any way to do it while supporting the undo/redo properly.
>
> Hope this helps.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: How to use swt TextField to edit an attribute? [message #1194240 is a reply to message #1184569] Mon, 18 November 2013 12:02 Go to previous messageGo to next message
Felix Dorner is currently offline Felix DornerFriend
Messages: 295
Registered: March 2012
Senior Member
If you don't use Databinding, you could give it a shot before pulling
out the heavy artillery aka java.concurrent.

I played around once with it using SWTObservables.delayedObservableValue

Felix
Re: How to use swt TextField to edit an attribute? [message #1194330 is a reply to message #1194240] Mon, 18 November 2013 13:03 Go to previous message
Ingo Mohr is currently offline Ingo MohrFriend
Messages: 23
Registered: September 2011
Junior Member
Thank you all. This should give me some base to decide what to do with those Text widgets.
Previous Topic:Understanding Net4j
Next Topic:Manipulating files with EMF
Goto Forum:
  


Current Time: Wed Apr 24 22:47:27 GMT 2024

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

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

Back to the top