Bug 478611

Summary: [DataBinding] Create snippets for the SideEffect class
Product: [Eclipse Project] Platform Reporter: Simon Scholz <simon.scholz>
Component: UIAssignee: Simon Scholz <simon.scholz>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: daniel_megert, Lars.Vogel, sxenos
Version: 4.6Keywords: example
Target Milestone: 4.15 M1Flags: sxenos: review+
Hardware: PC   
OS: All   
See Also: https://git.eclipse.org/r/56927
https://git.eclipse.org/r/59623
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=05eef427b49209621d83e9fceb34501e5230d6af
https://git.eclipse.org/r/67929
https://git.eclipse.org/r/67931
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=05991be197cd33a29de2e77122f036e4c9bad551
https://git.eclipse.org/r/68082
https://git.eclipse.org/r/68123
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=b88f960b586ec5842a1d20fbd028f3ddb36431fb
https://git.eclipse.org/r/68283
https://git.eclipse.org/r/72578
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=4b5dc694f17a21124a619b566be2dbe9cf99a909
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=f9e3ffeb300ec8ab28cacd9d32f4cf05d2c86a0e
https://git.eclipse.org/r/72613
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=8c9039bbe6cd389f7a517182efabb43b545aae88
https://git.eclipse.org/r/72637
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=4a8a502b4698be997f02b1ffc24e4ba18ef4b002
https://git.eclipse.org/r/72852
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=536b6c53de3708e5c6bb59cbb887f8e60027f180
https://git.eclipse.org/r/72854
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=ea320b96d23e59e415a80e8125e2c71a24ee8183
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=748360f919fe26185a2a6a901dc426d6304b103b
https://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=421d6a1caa64c321dd5a519a412e80436e1572f1
Whiteboard:
Bug Depends on: 478456    
Bug Blocks:    

Description Simon Scholz CLA 2015-09-29 05:12:16 EDT
In Bug 478456 a new SideEffect class is being created and it would be useful to provide some snippets with examples for the usage of the SideEffect class.
Comment 1 Eclipse Genie CLA 2015-09-29 05:12:46 EDT
New Gerrit change created: https://git.eclipse.org/r/56927
Comment 2 Eclipse Genie CLA 2015-11-03 21:13:28 EST
New Gerrit change created: https://git.eclipse.org/r/59623
Comment 3 Stefan Xenos CLA 2015-11-11 20:58:52 EST
Since we still have the hashcode and equals problems with Observables, the safest use of SideEffect will probably be for one-way bindings (initializing labels, the contents of a listbox, etc.) I'd suggest adding such an example.
Comment 4 Stefan Xenos CLA 2015-11-11 20:59:38 EST
FYI, the SideEffect class was committed to master just now, so we can start committing these as well.
Comment 5 Lars Vogel CLA 2015-12-02 06:05:51 EST
Simon, any plans to finish this for M4?
Comment 7 Eclipse Genie CLA 2016-03-07 21:29:25 EST
New Gerrit change created: https://git.eclipse.org/r/67929
Comment 8 Eclipse Genie CLA 2016-03-07 22:40:41 EST
New Gerrit change created: https://git.eclipse.org/r/67931
Comment 10 Eclipse Genie CLA 2016-03-09 14:34:23 EST
New Gerrit change created: https://git.eclipse.org/r/68082
Comment 11 Eclipse Genie CLA 2016-03-09 23:34:46 EST
New Gerrit change created: https://git.eclipse.org/r/68123
Comment 14 Stefan Xenos CLA 2016-03-10 00:49:20 EST
I notice in one of the recent samples that the ISideEffect version of the validation code is more lines of code than the DataBindingContext version.

Much of the extra code is due to the need to explicitly dispose the ISideEffects.

I'd suggest we create the following helper method:

ControlSideEffect {
ISideEffect create(Control c, Supplier<T>, Consumer<T>)
}

It would create a new side effect which gets disposed along with the given control. For example:

ControlSideEffect.create(okButton, () -> validationStatus.getValue().isOK(),
okButton::setEnabled);

That would eliminate the need for explicit disposal code, and (in some cases) the need for a local variable to hold the side effect.

The new utility could live in a new utility class, SWTObservables, or WidgetProperties. I'm not sure where the best place for it is.
Comment 15 Stefan Xenos CLA 2016-03-10 00:53:20 EST
We could also create a new utility for attaching side effects to workbench parts. It could pause and resume the side-effect when the part is hidden, and dispose the side-effect when the part is closed.

I'm not sure what the prototype should be, though, since I'm unsure how E4 parts track their own visibility.
Comment 16 Simon Scholz CLA 2016-03-10 08:55:04 EST
(In reply to Stefan Xenos from comment #14)
> I notice in one of the recent samples that the ISideEffect version of the
> validation code is more lines of code than the DataBindingContext version.
> 
> Much of the extra code is due to the need to explicitly dispose the
> ISideEffects.

Basically the DataBindingContext is a container for all local bindings. When the DataBindingContext is disposed all Bindings will be disposed too.
What do you think of having such a container for ISideEffects as well?

public class SideEffectContext implements ISideEffect {

	private IObservableList<ISideEffect> sideEffects;

	public SideEffectContext() {
		this(Realm.getDefault());
	}

	public SideEffectContext(Realm realm) {
		sideEffects = new WritableList<>(realm);
	}

	@Override
	public void dispose() {
		sideEffects.forEach(s -> s.dispose());
		sideEffects.clear();
	}

	@Override
	public void pause() {
		sideEffects.forEach(s -> s.pause());
	}

	@Override
	public void resume() {
		sideEffects.forEach(s -> s.resume());
	}

	@Override
	public void resumeAndRunIfDirty() {
		sideEffects.forEach(s -> s.resumeAndRunIfDirty());
	}

	@Override
	public void runIfDirty() {
		sideEffects.forEach(s -> s.runIfDirty());
	}

	public ISideEffect createPaused(Runnable runnable) {
		ISideEffect sideEffect = ISideEffect.createPaused(runnable);
		sideEffects.add(sideEffect);

		return sideEffect;
	}

	public ISideEffect createPaused(Realm realm, Runnable runnable) {
		ISideEffect sideEffect = ISideEffect.createPaused(realm, runnable);
		sideEffects.add(sideEffect);

		return sideEffect;
	}

	public ISideEffect create(Runnable runnable) {
		ISideEffect sideEffect = ISideEffect.create(runnable);
		sideEffects.add(sideEffect);

		return sideEffect;
	}

	public <T> ISideEffect create(Supplier<T> supplier, Consumer<T> consumer) {
		ISideEffect sideEffect = ISideEffect.create(supplier, consumer);
		sideEffects.add(sideEffect);

		return sideEffect;
	}

	public <T> ISideEffect createResumed(Supplier<T> supplier, Consumer<T> consumer) {
		ISideEffect sideEffect = ISideEffect.createResumed(supplier, consumer);
		sideEffects.add(sideEffect);

		return sideEffect;
	}

	public <T> ISideEffect consumeOnceAsync(Supplier<T> supplier, Consumer<T> consumer) {
		ISideEffect sideEffect = ISideEffect.consumeOnceAsync(supplier, consumer);
		sideEffects.add(sideEffect);

		return sideEffect;
	}
}

With this approach you can use it like this:

SideEffectContext sideEffectContext = new SideEffectContext();

sideEffectContext.create(() -> validationStatus.getValue().isOK(),
okButton::setEnabled);

sideEffectContext.create(person::getFirstName, personFirstNameText::setText);
sideEffectContext.create(personFirstNameText::getText, person::setFirstName);

// disposed all sideeffects
personFirstNameText.addDisposeListener(e -> sideEffectContext.dispose());

Then we could also have a ControlSideEffectContext with a third constructor in JFace Databinding, like this:


public class ControlSideEffectContext extends SideEffectContext {
	public ControlSideEffectContext() {
		this(Realm.getDefault());
	}

	public ControlSideEffectContext(Realm realm) {
		this(realm, null);
	}

	public ControlSideEffectContext(Realm realm, Control disposeableControl) {
		super(realm);
                disposeableControl.addDisposeListener(e -> ControlSideEffectContext.this.dispose());
	}
}

... so that even the disposal is automatically managed by using ControlSideEffectContext.

Concerning E4 Parts, we could then put this SideEffectContext into the context of a part and create a model addon, which is able to pause all SideEffects in case the part is hidden in the stack.

@Inject
@Optional
public void subscribeTopicSelectedElement(@EventTopic
    (UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT) Event event) {
  Object newValue = event.getProperty(EventTags.NEW_VALUE);
  Object oldValue = event.getProperty(EventTags.OLD_VALUE);


  if (oldValue instanceof MPart) {
      MPart oldPart = (MPart) oldValue;

     ISideEffect oldPartsSideEffect = oldPart.getContext().get(ISideEffect.class);
     if(oldPartsSideEffect != null) {
       oldPartsSideEffect.pause();
     } 
  }

  if (newValue instanceof MPart) {
      MPart newPart = (MPart) newValue;

      ISideEffect newPartsSideEffect = newPart.getContext().get(ISideEffect.class);
      if(newPartsSideEffect != null) {
        newPartsSideEffect.resume();
      } 
  }

}
Comment 17 Eclipse Genie CLA 2016-03-12 18:44:34 EST
New Gerrit change created: https://git.eclipse.org/r/68283
Comment 18 Eclipse Genie CLA 2016-05-11 18:23:55 EDT
New Gerrit change created: https://git.eclipse.org/r/72578
Comment 21 Dani Megert CLA 2016-05-12 06:33:54 EDT
Please revert those changes. No changes are allowed at this point. Please read https://dev.eclipse.org/mhonarc/lists/platform-ui-dev/msg07082.html

"
As previously mentioned by David, tonight 20:00 EDT will be our RC1 candidate build. This means, no further changes must be committed or merged after that.
"
Comment 22 Eclipse Genie CLA 2016-05-12 07:06:48 EDT
New Gerrit change created: https://git.eclipse.org/r/72613
Comment 24 Dani Megert CLA 2016-05-12 07:47:21 EDT
(In reply to Eclipse Genie from comment #23)
> Gerrit change https://git.eclipse.org/r/72613 was merged to [master].
> Commit:
> http://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=8c9039bbe6cd389f7a517182efabb43b545aae88
> 

Thanks. Please also revert the other change.
Comment 25 Dani Megert CLA 2016-05-12 10:59:14 EDT
(In reply to Dani Megert from comment #24)
> (In reply to Eclipse Genie from comment #23)
> > Gerrit change https://git.eclipse.org/r/72613 was merged to [master].
> > Commit:
> > http://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=8c9039bbe6cd389f7a517182efabb43b545aae88
> > 
> 
> Thanks. Please also revert the other change.

Not good. The rebuild started and now this bug is partially in RC1 and RC2.
Comment 26 Eclipse Genie CLA 2016-05-12 11:05:56 EDT
New Gerrit change created: https://git.eclipse.org/r/72637
Comment 28 Simon Scholz CLA 2016-05-12 11:09:29 EDT
Sorry I was busy almost all afternoon. I reverted it right now. 
I thought for example projects it would still be ok to merge.
Comment 29 Dani Megert CLA 2016-05-12 11:21:37 EDT
(In reply to Simon Scholz from comment #28)
> Sorry I was busy almost all afternoon. 

Next time, please just tell us that here, and someone else takes care of it. That's not a problem.


> I reverted it right now. 

Unfortunately, this makes it even worse. You could have checked
http://git.eclipse.org/c/platform/eclipse.platform.ui.git/
to see that your change was already picked up by the 10:00 rebuild, i.e. this is now in RC1 (unless we have to rebuild again), but you've reverted it after that build.


> I thought for example projects it would still be ok to merge.

Nope, no commit or merge is allowed, except for those that get announced as critical issues on the platform-releng mailing list. We're forgiving commits that do not affect the build, e.g. changes to N&N, webpage, etc.
Comment 30 Eclipse Genie CLA 2016-05-16 18:45:42 EDT
New Gerrit change created: https://git.eclipse.org/r/72852
Comment 32 Eclipse Genie CLA 2016-05-16 19:07:22 EDT
New Gerrit change created: https://git.eclipse.org/r/72854
Comment 35 Simon Scholz CLA 2016-05-17 03:35:32 EDT
Done with creating snippets for now.
Comment 36 Lars Vogel CLA 2019-11-27 05:48:29 EST
Still one open Gerrit.
Comment 38 Lars Vogel CLA 2020-01-06 04:03:39 EST
Thanks Simon and Jens.