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 |
Michael Scharf 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 |
Ed Merks Messages: 33236 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 #1184742 is a reply to message #1184711] |
Wed, 13 November 2013 17:01 |
Ed Merks Messages: 33236 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/
|
|
| | |
Goto Forum:
Current Time: Sat Oct 19 15:24:53 GMT 2024
Powered by FUDForum. Page generated in 0.04625 seconds
|