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 06: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 10:41 Go to previous messageGo to next message
Joseph Carroll is currently offline Joseph Carroll
Messages: 156
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] Tue, 28 August 2012 22: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 07: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 08:07 Go to previous messageGo to next message
Sopot Cela is currently offline Sopot Cela
Messages: 446
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 09:21 Go to previous messageGo to next message
Joseph Carroll is currently offline Joseph Carroll
Messages: 156
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 09:28 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 4462
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 09:31 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 4462
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 10:18 Go to previous messageGo to next message
Joseph Carroll is currently offline Joseph Carroll
Messages: 156
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 12: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 14:21 Go to previous messageGo to next message
Joseph Carroll is currently offline Joseph Carroll
Messages: 156
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 05: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 17:29 Go to previous message
René Brandstetter is currently offline René Brandstetter
Messages: 8
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 06:14]

Report message to a moderator

Previous Topic:Sample Project with one view bug
Next Topic:Eclipse4 Model Concept: Model Tree of Fragments? (SOLVED)
Goto Forum:
  


Current Time: Sun May 19 12:03:21 EDT 2013

Powered by FUDForum. Page generated in 0.12037 seconds