Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse 4 » Where should ISaveHandler be registered?
Where should ISaveHandler be registered? [message #903559] Fri, 24 August 2012 10:42 Go to next message
Markus Wiederkehr is currently offline Markus Wiederkehr
Messages: 17
Registered: August 2012
Junior Member
I am working on a e4-based RCP application and I am not very happy with the default dialog for saving parts.

I understand that I have to put a custom ISaveHandler (and/or IWindowCloseHandler) in the context of the MWindow. Lars Vogel gave an example where he registered a IWindowCloseHandler from within a handler method (annotated with @Execute), see [1].

The questions is where or how should I trigger that handler so that the IWindowCloseHandler get registered automatically when the application starts up?

Other things I tried is set the IWindowCloseHandler from a life cycle handler (@PostContextCreate) and from an Addon that listens for new windows being created. Form what I can say both seems to happen too soon, i.e. the IWindowCloseHandler seems to get overwritten later by the framework.

[1] (I am not allowed to link to H T T P : //) www.vogella.com/articles/EclipseRCP/article.html#context_who
Re: Where should ISaveHandler be registered? [message #904004 is a reply to message #903559] Mon, 27 August 2012 14:41 Go to previous messageGo to next message
Joseph Carroll is currently offline Joseph Carroll
Messages: 174
Registered: May 2012
Location: Milwaukee, WI
Senior Member

Are you trying to replace the functionality of the IWindowCloseHandler or ISavePart?

In either case, you want to add a model contribution. Normally, you would be able to do this directly through a fragment or by creating a MHandler in your Application.e4xmi. However, since you need to need to "bind" your custom implementation with a specific class you will need to use a processor [1].

When you "bind" an implementation to a class, what you are saying is whenever there is a need of the class use the implementation. In your case this would be the equivalent of any time there is an injection dependency of ISavePart, inject MySavePartImpl.

This of course is all relative to the local context [2]. To accomplish this, use the IEclipseContext.set() method.

JD



[1] http://www.vogella.com/articles/Eclipse4Modularity/article.html#contributeprocessors
[2] http://wiki.eclipse.org/Eclipse4/RCP/Dependency_Injection
Re: Where should ISaveHandler be registered? [message #904710 is a reply to message #903559] Wed, 29 August 2012 02:12 Go to previous messageGo to next message
Justin Unterreiner is currently offline Justin Unterreiner
Messages: 10
Registered: August 2012
Junior Member
I have the same question; I would like to register a custom implementation of ISaveHandler for my parts, but haven't been able to get it to work.

The method I have been trying is adding an entry to the context with a key of ISaveHandler.class and a value of a new instance of a ISaveHandler with implementations for the two methods (both promptToSave signatures).

It is my understanding that when this is set into the context it should get injected into the part etc.

I've tried doing this in the a method in the part that is annotated with @PostConstruct as well as several other places (adding to the application model context in the @ProcessAdditions in my life cycle manager). But nothing seems to work; I just see the default handler.

Can we get a code sample on how to achieve this?

Ultimately, I want to have similar behavior to that of 3.x; a singular dialog when closing a part "[Resource] has been modified. Save changes? Yes/No/Cancel" and to change the wording in the multiple save dialog (from "Select the parts to save:" to "Select the records/resources to save:" or similar). I may end up using my own dialog entirely, but at least getting this custom handler to be utilized would be a start.
Re: Where should ISaveHandler be registered? [message #908426 is a reply to message #904004] Wed, 05 September 2012 11:13 Go to previous messageGo to next message
Markus Wiederkehr is currently offline Markus Wiederkehr
Messages: 17
Registered: August 2012
Junior Member
Thanks Joseph,

I was able to register a processor and get my main window injected. The problem is that the Window's context is still null at this point. So I cannot register my custom IWindowCloseHandler.

Here's the code I used:

public class WindowProcessor {
	@Inject
	@Named("com.example.window")
	private MWindow window;

	@Execute
	public void execute() {
		System.out.println("Window: " + window);

		final IEclipseContext context = window.getContext();
		System.out.println("Context: " + context);
	}
}

Extension in plugin.xml:

<extension
      id="id1"
      point="org.eclipse.e4.workbench.model">
   <processor
         beforefragment="false"
         class="com.example.handlers.WindowProcessor">
      <element
            id="com.example.window">
      </element>
   </processor>
</extension>

When I run the program I get "Context: null".
Re: Where should ISaveHandler be registered? [message #908449 is a reply to message #908426] Wed, 05 September 2012 12:07 Go to previous messageGo to next message
Sopot Cela is currently offline Sopot Cela
Messages: 597
Registered: December 2010
Senior Member

If the processor is a "too early" approach you can also use IEventBroker and listen for the initial creation or activation of the window and populate the IEC at this point. You can use IEB.subscribe and supply the topic. Check out the UIEvents class which has all sorts of event topics to hook your code to a specific life cycle event (UILifeCycle) and specific event type (UIEventsType).
Re: Where should ISaveHandler be registered? [message #908487 is a reply to message #908426] Wed, 05 September 2012 13:21 Go to previous messageGo to next message
Joseph Carroll is currently offline Joseph Carroll
Messages: 174
Registered: May 2012
Location: Milwaukee, WI
Senior Member

You're right, it would be null at that point...

(IMO) I feel as though that is a bug, but I am not sure how everyone else will feel about this. Please file a bug report detailing what you are experiencing (just what you already posted). I already have a patch in the works and we will see if it is picked up. (it should be) If it is picked up, I wouldn't expect it to be in the SR1.

To get around this for now, treat this as an addon and use @ProcessAdditions.

The one issue we might run into is how the model handles setting the context. The main issue is that the MApplication does not have its context set at that point. So there might be some issues with setting the MApplication context and then adding certain features with processors.

I'll take a look, but please file the bug report and post it here. We'll see what happens.

JD
Re: Where should ISaveHandler be registered? [message #908495 is a reply to message #908487] Wed, 05 September 2012 13:28 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 5330
Registered: July 2009
Senior Member
An element only gets an IEclipseContext at the moment it gets rendered!
So that's NOT a bug but expected and desired behavior, the context even
changes when you un and rerender it!

Tom

Am 05.09.12 15:21, schrieb Joseph Carroll:
> You're right, it would be null at that point...
>
> (IMO) I feel as though that is a bug, but I am not sure how everyone
> else will feel about this. Please file a bug report detailing what you
> are experiencing (just what you already posted). I already have a patch
> in the works and we will see if it is picked up. (it should be) If it
> is picked up, I wouldn't expect it to be in the SR1.
>
> To get around this for now, treat this as an addon and use
> @ProcessAdditions.
>
> The one issue we might run into is how the model handles setting the
> context. The main issue is that the MApplication does not have its
> context set at that point. So there might be some issues with setting
> the MApplication context and then adding certain features with processors.
>
> I'll take a look, but please file the bug report and post it here.
> We'll see what happens.
>
> JD
Re: Where should ISaveHandler be registered? [message #908501 is a reply to message #908495] Wed, 05 September 2012 13:31 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 5330
Registered: July 2009
Senior Member
What we can discuss if one can preregister transient context values
similar to MContext#properties! This would free you from listening to
the event broker.

Tom

Am 05.09.12 15:28, schrieb Tom Schindl:
> An element only gets an IEclipseContext at the moment it gets rendered!
> So that's NOT a bug but expected and desired behavior, the context even
> changes when you un and rerender it!
>
> Tom
>
> Am 05.09.12 15:21, schrieb Joseph Carroll:
>> You're right, it would be null at that point...
>>
>> (IMO) I feel as though that is a bug, but I am not sure how everyone
>> else will feel about this. Please file a bug report detailing what you
>> are experiencing (just what you already posted). I already have a patch
>> in the works and we will see if it is picked up. (it should be) If it
>> is picked up, I wouldn't expect it to be in the SR1.
>>
>> To get around this for now, treat this as an addon and use
>> @ProcessAdditions.
>>
>> The one issue we might run into is how the model handles setting the
>> context. The main issue is that the MApplication does not have its
>> context set at that point. So there might be some issues with setting
>> the MApplication context and then adding certain features with processors.
>>
>> I'll take a look, but please file the bug report and post it here.
>> We'll see what happens.
>>
>> JD
>
Re: Where should ISaveHandler be registered? [message #908523 is a reply to message #908495] Wed, 05 September 2012 14:18 Go to previous messageGo to next message
Joseph Carroll is currently offline Joseph Carroll
Messages: 174
Registered: May 2012
Location: Milwaukee, WI
Senior Member

Well there's the one issue... Thanks Tom! Smile

I'll look into preregistering transient context values, has any work already been done on this?

JD
Re: Where should ISaveHandler be registered? [message #909167 is a reply to message #908523] Thu, 06 September 2012 16:57 Go to previous messageGo to next message
Markus Wiederkehr is currently offline Markus Wiederkehr
Messages: 17
Registered: August 2012
Junior Member
Thanks all!

@Joseph: I guess I don't have to file a bug report then?

@All: So the proper way to this now is to listen to the event broker? But then where should I subscribe to the events? From within a processor?

So should I register a processor like I did and then in that processor subscribe to the event broker?
Re: Where should ISaveHandler be registered? [message #909203 is a reply to message #909167] Thu, 06 September 2012 18:21 Go to previous messageGo to next message
Joseph Carroll is currently offline Joseph Carroll
Messages: 174
Registered: May 2012
Location: Milwaukee, WI
Senior Member

No you should not file a bug report. As Tom eluded to (and I didn't think of), when a workbench model element receives a context, it is not a context for life. Not every workbench model element will receive a unique context, but for those that do, the context remains valid only as long as it is rendered and its heirarchy does not change.

For now the method Sopot suggested using the event broker is the approach you should use. Something like this:

public class YourProcessor {

	@Inject
	private IEventBroker eventBroker;
	
	private EventHandler addHandler = new EventHandler() {
		
		@Override
		public void handleEvent(Event event) {
			if (!(event.getProperty(UIEvents.EventTags.ELEMENT) instanceof MWindow))
				return;
			
			if (!UIEvents.isCREATE(event)) 
				return;
			
			// do something
		}
	};
	
	@Execute
	protected void init() {
		eventBroker.subscribe(UIEvents.Window.TOPIC_ALL, addHandler);
		//eventBroker.subscribe(UIEvents.TrimmedWindow.TOPIC_ALL, addHandler);
	}
	
}
Re: Where should ISaveHandler be registered? [message #922724 is a reply to message #909203] Tue, 25 September 2012 09:11 Go to previous messageGo to next message
Markus Wiederkehr is currently offline Markus Wiederkehr
Messages: 17
Registered: August 2012
Junior Member
Hi Joseph,

Sorry for bringing this up again but that approach does not seem to be working either.

Even when I subscribe to "org/eclipse/e4/*" the EventHandler does not receive a single CREATE event. Here is all I get during startup of my application:

org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/Context/context/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/renderer/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/application/ApplicationElement/tags/ADD]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/widget/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/renderer/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/widget/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/renderer/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/widget/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/menu/HandledItem/wbCommand/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/renderer/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/widget/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/renderer/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/widget/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/application/ApplicationElement/tags/ADD]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/menu/HandledItem/wbCommand/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/widget/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/ElementContainer/selectedElement/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/basic/Window/x/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/basic/Window/y/SET]
org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/menu/Item/enabled/SET]


Maybe I could hook into Window/x/SET but that would be a bit of a hack and also I'd be interested in knowing why I don't receive a single CREATE event...

Thanks
Markus
Re: Where should ISaveHandler be registered? [message #966231 is a reply to message #922724] Wed, 31 October 2012 21:29 Go to previous messageGo to next message
René Brandstetter is currently offline René Brandstetter
Messages: 17
Registered: July 2012
Junior Member
Hi Markus,

it's still a hack put with this processor you should be able to replace the default IWindowCloseHandler from WBWRenderer with your own impl.

package com.test.application.addons;

import javax.inject.Inject;
import javax.inject.Named;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.IWindowCloseHandler;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

@SuppressWarnings("restriction")
public class QuitProcessor {
  
  private final MWindow window;
  private final IEventBroker eventBroker;
  
  @Inject
  public QuitProcessor(@Named("at.renbrand.sentinel.mainWindow")MWindow window, IEventBroker eventBroker){
    this.window = window;
    this.eventBroker = eventBroker;
  }
  
  @Execute
  void installIntoContext(){
    eventBroker.subscribe(UIEvents.Context.TOPIC_CONTEXT, new EventHandler(){

      @Override
      public void handleEvent(Event event) {
        if( UIEvents.isSET(event) ){
          if( window.equals( event.getProperty("ChangedElement") ) && window.getContext() != null ){
            // use RunAndTrack to get notified after the IWindowCloseHanlder was changed in the IEclipseContext
            window.getContext().runAndTrack(new RunAndTrack(){
              
              private final IWindowCloseHandler quitHandler = new QuitHandler();

              @Override
              public boolean changed(IEclipseContext context) {
                Object value = context.get(IWindowCloseHandler.class);  // access the context value to be reevaluated on every future change of the value
                
                if(!quitHandler.equals(value)){  // prevents endless loop
                  context.set(IWindowCloseHandler.class, quitHandler);
                }
                
                return true;  // ture keeps tracking and the quitHandler as the only opportunity
              }
              
            });
          }
        }
      }
      
    });
  }
}

[Updated on: Thu, 01 November 2012 10:14]

Report message to a moderator

Re: Where should ISaveHandler be registered? [message #1060947 is a reply to message #966231] Wed, 29 May 2013 09:27 Go to previous messageGo to next message
Uti Devel is currently offline Uti Devel
Messages: 7
Registered: May 2013
Junior Member
Hi,

i'm fairly new to RCP4 so i'm still trying to figure out how to connect all the odds and ends. If i take the code from above, what to do with it? I tried to register the QuitProcessor as an addon so it gets loaded on startup. Now a get the following exception:

!ENTRY org.eclipse.e4.ui.workbench 4 0 2013-05-29 11:18:48.886
!MESSAGE Unable to create class 'com.test.application.addons.QuitProcessor' from bundle '68'
!STACK 0
org.eclipse.e4.core.di.InjectionException: Could not find satisfiable constructor in com.test.application.addons.QuitProcessor
at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:330)
at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:255)
at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:185)
at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:105)
at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:71)
at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:49)
at org.eclipse.e4.ui.internal.workbench.swt.E4Application.createE4Workbench(E4Application.java:258)
at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:132)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
at org.eclipse.equinox.launcher.Main.main(Main.java:1414)

I think the model is not created by now, so the window can not be found. How to delay the creation of the Processor?

Thank You

René Brandstetter wrote on Wed, 31 October 2012 17:29
Hi Markus,

it's still a hack put with this processor you should be able to replace the default IWindowCloseHandler from WBWRenderer with your own impl.

package com.test.application.addons;

import javax.inject.Inject;
import javax.inject.Named;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.IWindowCloseHandler;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

@SuppressWarnings("restriction")
public class QuitProcessor {
  
  private final MWindow window;
  private final IEventBroker eventBroker;
  
  @Inject
  public QuitProcessor(@Named("at.renbrand.sentinel.mainWindow")MWindow window, IEventBroker eventBroker){
    this.window = window;
    this.eventBroker = eventBroker;
  }
  
  @Execute
  void installIntoContext(){
    eventBroker.subscribe(UIEvents.Context.TOPIC_CONTEXT, new EventHandler(){

      @Override
      public void handleEvent(Event event) {
        if( UIEvents.isSET(event) ){
          if( window.equals( event.getProperty("ChangedElement") ) && window.getContext() != null ){
            // use RunAndTrack to get notified after the IWindowCloseHanlder was changed in the IEclipseContext
            window.getContext().runAndTrack(new RunAndTrack(){
              
              private final IWindowCloseHandler quitHandler = new QuitHandler();

              @Override
              public boolean changed(IEclipseContext context) {
                Object value = context.get(IWindowCloseHandler.class);  // access the context value to be reevaluated on every future change of the value
                
                if(!quitHandler.equals(value)){  // prevents endless loop
                  context.set(IWindowCloseHandler.class, quitHandler);
                }
                
                return true;  // ture keeps tracking and the quitHandler as the only opportunity
              }
              
            });
          }
        }
      }
      
    });
  }
}


Re: Where should ISaveHandler be registered? [message #1060965 is a reply to message #1060947] Wed, 29 May 2013 10:41 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 5330
Registered: July 2009
Senior Member
The addon context only holds the MApplication instance! You could in
there traverse the windows but the problem is that at this point the
IEclipseContext has not been created.

The strategy to use is that your addon registers itself as a listener on
the event-bus to detect when the IEclipseContext has been set and the
push in this context the respective handler.

Tom


On 29.05.13 11:27, Uti Devel wrote:
> Hi,
>
> i'm fairly new to RCP4 so i'm still trying to figure out how to connect
> all the odds and ends. If i take the code from above, what to do with
> it? I tried to register the QuitProcessor as an addon so it gets loaded
> on startup. Now a get the following exception:
>
> !ENTRY org.eclipse.e4.ui.workbench 4 0 2013-05-29 11:18:48.886
> !MESSAGE Unable to create class
> 'com.test.application.addons.QuitProcessor' from bundle '68'
> !STACK 0
> org.eclipse.e4.core.di.InjectionException: Could not find satisfiable
> constructor in com.test.application.addons.QuitProcessor
> at
> org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:330)
>
> at
> org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:255)
> at
> org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:185)
>
> at
> org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:105)
>
> at
> org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:71)
>
> at
> org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:49)
>
> at
> org.eclipse.e4.ui.internal.workbench.swt.E4Application.createE4Workbench(E4Application.java:258)
>
> at
> org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:132)
>
> at
> org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
>
> at
> org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
>
> at
> org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
>
> at
> org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
>
> at
> org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
>
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
>
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>
> at java.lang.reflect.Method.invoke(Method.java:601)
> at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
> at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
> at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
> at org.eclipse.equinox.launcher.Main.main(Main.java:1414)
>
> I think the model is not created by now, so the window can not be found.
> How to delay the creation of the Processor?
>
> Thank You
>
> René Brandstetter wrote on Wed, 31 October 2012 17:29
>> Hi Markus,
>>
>> it's still a hack put with this processor you should be able to
>> replace the default IWindowCloseHandler from WBWRenderer with your own
>> impl.
>>
>>
>> package com.test.application.addons;
>>
>> import javax.inject.Inject;
>> import javax.inject.Named;
>>
>> import org.eclipse.e4.core.contexts.IEclipseContext;
>> import org.eclipse.e4.core.contexts.RunAndTrack;
>> import org.eclipse.e4.core.di.annotations.Execute;
>> import org.eclipse.e4.core.services.events.IEventBroker;
>> import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
>> import org.eclipse.e4.ui.workbench.UIEvents;
>> import org.eclipse.e4.ui.workbench.modeling.IWindowCloseHandler;
>> import org.osgi.service.event.Event;
>> import org.osgi.service.event.EventHandler;
>>
>> @SuppressWarnings("restriction")
>> public class QuitProcessor {
>> private final MWindow window;
>> private final IEventBroker eventBroker;
>> @Inject
>> public
>> QuitProcessor(@Named("at.renbrand.sentinel.mainWindow")MWindow window,
>> IEventBroker eventBroker){
>> this.window = window;
>> this.eventBroker = eventBroker;
>> }
>> @Execute
>> void installIntoContext(){
>> eventBroker.subscribe(UIEvents.Context.TOPIC_CONTEXT, new
>> EventHandler(){
>>
>> @Override
>> public void handleEvent(Event event) {
>> if( UIEvents.isSET(event) ){
>> if( window.equals( event.getProperty("ChangedElement") ) &&
>> window.getContext() != null ){
>> // use RunAndTrack to get notified after the
>> IWindowCloseHanlder was changed in the IEclipseContext
>> window.getContext().runAndTrack(new RunAndTrack(){
>> private final IWindowCloseHandler quitHandler = new
>> QuitHandler();
>>
>> @Override
>> public boolean changed(IEclipseContext context) {
>> Object value =
>> context.get(IWindowCloseHandler.class); // access the context value
>> to be reevaluated on every future change of the value
>> if(!quitHandler.equals(value)){ // prevents endless loop
>> context.set(IWindowCloseHandler.class, quitHandler);
>> }
>> return true; // ture keeps tracking and the
>> quitHandler as the only opportunity
>> }
>> });
>> }
>> }
>> }
>> });
>> }
>> }
>
>
Re: Where should ISaveHandler be registered? [message #1061146 is a reply to message #1060947] Thu, 30 May 2013 08:32 Go to previous messageGo to next message
René Brandstetter is currently offline René Brandstetter
Messages: 17
Registered: July 2012
Junior Member
Hi,

sorry maybe I forgot to add some glue explaination which will do the trick for this code to work.

First of all it's not registered as an Addon as the name of the class tells you it has to be registered as a Processor. A processor will be registered inside the plugin.xml with an extension and not inside the e4xmi application model. So register it with the following configuration inside your plugin.xml.

 <extension
         id="id2"
         point="org.eclipse.e4.workbench.model">
      <processor
            beforefragment="false"
            class="com.test.application.addons.QuitProcessor">
         <element
               id="at.renbrand.sentinel.mainWindow">
         </element>
      </processor>
   </extension>


And the last thing to check is that my TrimmedWindow in the example has set its ID to "at.renbrand.sentinel.mainWindow" inside the e4xmi application model. This ID is used inside the QuitProcessor-Constructor as a @Named parameter and is also mentioned inside the plugin.xml above. It has to be named in the plugin.xml too because otherwise it wouldn't be injected (for more details have a look at Lars Blog http://www.vogella.com/articles/Eclipse4Modularity/article.html#contributeprocessors).

Afterwards the QuitProcessor will register to an EventTopic as Tom wrote.

So I hope this message brings some clarification.

René
Re: Where should ISaveHandler be registered? [message #1061166 is a reply to message #1061146] Thu, 30 May 2013 10:40 Go to previous messageGo to next message
Uti Devel is currently offline Uti Devel
Messages: 7
Registered: May 2013
Junior Member
Hi,

now its working. I think i didn't understand that only setting the processor up after the creation of the window is not enough. Now that i'm waiting for the context being created i get the expected results.

But seems to be a little crude, to just overwrite the handler every time something changes in the context. Is there no explicit way to tell eclipse to use THIS handler and none other?

(I just thought of two of this little RunAndTrack-critters trying to set differed instances for the same Handler...)

Anyway thanks for enlightening me Smile

Dennis
Re: Where should ISaveHandler be registered? [message #1061421 is a reply to message #1061166] Fri, 31 May 2013 14:30 Go to previous message
René Brandstetter is currently offline René Brandstetter
Messages: 17
Registered: July 2012
Junior Member
Hi Dennis,

as I wrote it's a "Hack" because as far as I can remember there was a problem with specifing the IWindowCloseHandler after the application has already been started and so that's the reason for the event registration stuff.

During the startup of the application the IWindowCloseHandler will be hardcoded overwritten by some unaccessible (internal private) platform code. So I used the functionality of the RunAndTrack method to set the custom QuitHandler again as soon as the IWindowCloseHandler becomes overwritten by the platform code.
If you take a look at the JavaDoc of the RunAndTrack class you will see that the changed() method is only called if a variable which is accessed during the changed() method changes again. This means that the changed() method in this example will only be triggered again if the IWindowCloseHandler variable in the context changes. So it's not a change of the handler every time you change something in the context.

I hope you understand the RunAndTrack thing I wanted to explain. Sorry, my english isn't that good so if you have any further questions take a look at Lars Blog http://www.vogella.com/articles/EclipseRCP/article.html#extentcontext_turnandtrack . But be careful the last paragraph of the chapter isn't correct (I've already told him) the RunAndTrack isn't stopped if you do not access any values it is stopped if the changed() method return false and goes on tracking if it returns true.

René
Previous Topic:Updating the application model in a batch
Next Topic:Menu defined in the model look and feel
Goto Forum:
  


Current Time: Sun Sep 21 16:15:50 GMT 2014

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

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