|
Re: Setting Custom Context Variables In A Part's Context Before Part Creation [message #912427 is a reply to message #912414] |
Thu, 13 September 2012 15:03 |
Eclipse User |
|
|
|
The context is created before the part is sent to the presentation engine (before createWidget in PartRenderingEngine class is called) but there is no specific hook you can grab to. A really quick thought is to use the IEventBroker. You can subscribe to all kinds of events there and specifically you can listen for coming and going of contexts. So you subscribe to the context's creations, check if it's your part's contexts and do your specific stuff with it. That would easily give you access to your context before the rendering. I have to run so I can't elaborate how to subscribe to the contexts coming and going but I've done it here: https://bugs.eclipse.org/bugs/attachment.cgi?id=219843 Check out the registerModelListeners. It can be done more easily through DI also.
|
|
|
Re: Setting Custom Context Variables In A Part's Context Before Part Creation [message #913040 is a reply to message #912427] |
Fri, 14 September 2012 16:43 |
Rob Hatcherson Messages: 33 Registered: July 2009 Location: Fort Worth, TX, USA |
Member |
|
|
Thanks Sopot - that worked perfectly.
In summary, when a new part is created - e.g. through MBasicFactory.INSTANCE.createPart(), or partService.createPart(someDescriptorId), or probably any other way - the context won't be non-null until the part is shown though the rendering machinery as noted by Sopot above. By the time partService.showPart or partService.activate returns the part contribution's @PostConstruct method has already been called.
To set extra data in the context and make it available for injection prior to the part contribution's @PostConstruct method being called we can use Sopot's suggestion. The method below was swiped from a project we have in development, and demonstrates how we borrowed from the code in the link noted above. There are a few things in here that prevent it from being used as-is, but with just a bit of tailoring some of this might be useful to somebody.
Some of this content was borrowed from tutorials by Lars Vogel, Jonas Helming, and others.
The "View" class used in this snippet is a relatively simple convenience that sits above all our part contribution classes, and IContainedObject is the thing we wanted to stuff in the new part's context. One could easily modify this to take a more general set of data values to stuff.
public void showView(
View requestingView,
Class<? extends View> viewClass,
String targetPartStackId,
final IContainedObject containedObject
)
{
IEclipseContext context = requestingView.getPart().getContext() ;
MApplication app = context.get( MApplication.class ) ;
final EModelService modelService = context.get( EModelService.class ) ;
MUIElement uiElement = modelService.find( targetPartStackId, app ) ;
if( uiElement != null &&
uiElement instanceof MPartStack )
{
MPartStack partStack = (MPartStack)uiElement ;
// Either of these works. Not sure which is best practice.
// It probably is a tradeoff between programmatic convenience
// and having to add stuff to some Application or fragment
// e4xmi file. Note that is part descriptors are used then
// some of the calls made below are not necessary because the
// property values are loaded from the e4xmi file.
final MPart part = MBasicFactory.INSTANCE.createPart() ;
//final MPart part = partService.createPart( "com.zedasoft.viewer4.fc.view.e4.testpartdescriptor" ) ;
part.setLabel( containedObject.getDisplayName().toString() ) ;
part.setCloseable( true ) ;
part.setToBeRendered( true ) ;
part.setVisible( true ) ;
//part.setElementId( viewClass.getName() + ":" + _secondaryId++ ) ;
part.setContributionURI( viewClass.getName() ) ;
// Set up a handler to set some data in the part's context so
// it can be available to inject into the part's contribution
// and be there when the @PostConstruct method is called. Most
// of the code in this block was borrowed from:
//
// https://bugs.eclipse.org/bugs/attachment.cgi?id=219843
{
IEventBroker eventBroker = context.get( IEventBroker.class ) ;
eventBroker.subscribe( UIEvents.Context.TOPIC_CONTEXT, new EventHandler() {
public void handleEvent( Event event )
{
Object origin = event.getProperty( UIEvents.EventTags.ELEMENT ) ;
Object context = event.getProperty( UIEvents.EventTags.NEW_VALUE ) ;
if( ( origin instanceof MHandlerContainer ) &&
( UIEvents.EventTypes.SET.equals( event.getProperty( UIEvents.EventTags.TYPE ) ) &&
context instanceof IEclipseContext ) )
{
IEclipseContext eclipseContext = (IEclipseContext)context ;
MPart contextPart = eclipseContext.get( MPart.class ) ;
if( contextPart == part )
{
// Set extra context data here.
eclipseContext.set( View.CONTEXT_CONTAINED_OBJECT, containedObject ) ;
}
}
}
} ) ;
}
partStack.getChildren().add( part ) ;
{
EPartService partService = context.get( EPartService.class ) ;
// Either of these works. The latter one probably is best practice.
//partService.showPart( part, EPartService.PartState.ACTIVATE ) ;
partService.activate( part ) ;
}
}
else
{
Logger logger = context.get( Logger.class ) ;
logger.error( "Couldn't find a part stack with id \"" + targetPartStackId + "\"." ) ;
}
}
All that aside, this general topic probably is worth further discussion. It seems like it would be common in drill-down presentations to want a value present in a new part's context before the contribution springs to life. If true, then one needs to wonder why it isn't possible to simply do this before the part is shown:
newPart.getContext().set(...whatever...)
This obviously is far simpler than the event handler workaround. I can imagine reasons why context creation is deferred, but it definitely led to some hoop-jumping in this situation. Knowing little about the rationale behind E4 internals this may be a naive suggestion, but the getContext() method feels like a candidate for an "if you have it then return it, else create it then return it" approach. Then the user can put whatever they want in there, and the framework can take care of the remainder of the setup when the part is finally added to UI object graph and the rest of the context ancestry can be determined.
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03797 seconds