Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "E4/Snippets"

< E4
(Set the input on a part at runtime)
 
(16 intermediate revisions by 2 users not shown)
Line 1: Line 1:
Here you can find '''snippets'''  and '''practical tips''' covering '''Eclipse e4'''.
+
<br>
  
 
= Parts  =
 
= Parts  =
  
== Open a part dynamically ==
+
== Open a part dynamically ==
  
Define a part descriptor and open the part with the help of the EPartService.
+
=== with a Part Descriptor  ===
 +
 
 +
This approach defines a part descriptor and opens the part with the help of the EPartService. You must include the '''org.eclipse.equinox.event''' plugin to your run configuration.  
  
 
Create a components.e4xmi file to define the part descriptor.  
 
Create a components.e4xmi file to define the part descriptor.  
Line 11: Line 13:
 
<source lang="xml">
 
<source lang="xml">
 
<?xml version="1.0" encoding="ASCII"?>
 
<?xml version="1.0" encoding="ASCII"?>
<application:ModelComponents  
+
<application:ModelComponents xmi:version="2.0"
xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xmlns:xmi="http://www.omg.org/XMI" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application"
xmlns:application="http://www.eclipse.org/ui/2008/UIModel"
+
xmi:id="_RNb6kExtEd-JN6r-4dl3-A">
xsi:schemaLocation="http://www.eclipse.org/ui/2008/UIModel ../../org.eclipse.e4.ui.model.workbench/model/UIElements.ecore " xmi:id="abc">
+
<components xmi:id="_TqGKQExtEd-JN6r-4dl3-A" parentID="application">
<components
+
<descriptors xmi:id="_n1GVsFOZEd-e5P7xr5S20g" label="View"
parentID="sampleApp">
+
tooltip="ToolTip from XMI" elementId="elementIdDeclaredInModel"
<descriptors
+
category="tagOfTarget" closeable="true"
URI="platform:/plugin/de.sampleapp.data.ui/de.sampleapp.data.ui.TestView "
+
contributionURI="platform:/plugin/org.eclipse.e4.demo.View" />
label="TestView"
+
</components>
category="viewStack"/>
+
</components>
+
 
</application:ModelComponents>
 
</application:ModelComponents>
 
</source><br>  
 
</source><br>  
 +
Notice (since 1.0M4): The <code>category</code> attribute of the <code><descriptors></code> tag is used, to find the desired
 +
container for the part on creation via <code>EPartService</code>.
 +
The <code>category</code> MUST match any <code><tag></code> added to the target container (for example in
 +
<code>Application.e4xmi</code>) to make it possible finding the desired container, at all.
  
 
Register the components.e4xmi definition through an extension.  
 
Register the components.e4xmi definition through an extension.  
Line 38: Line 42:
 
</source><br>  
 
</source><br>  
  
Get the part descriptor at runtime and open it. For this step you need the IEclipseContext. You can get it either through dependency injection or passing it from another class. You can also try to get the MApplication through dependency injection, but in my case that didn't worked.  
+
Open the part via elementId defined in model using the EPartService, which you can retrieve via dependency injection or via IEclipseContext.
  
 
<source lang="java">
 
<source lang="java">
MWindow window = (MWindow) context.get( EPartService.PART_SERVICE_ROOT );
+
public class ViewTest {
MApplication app = (MApplication) (MUIElement) window.getParent();
+
 
EList<MPartDescriptor> descriptorList = app.getDescriptors();
+
    @Inject
for( MPartDescriptor descriptorList : desc ){
+
    private EPartService injectedPartService;
if( partDesc.getId().equals( PartToOpen.ID ) ){
+
 
MPart part = servicePart.showPart( partDesc.getId() );
+
    public ViewTest() {
                 break;
+
    }
        }
+
 
 +
    @PostConstruct
 +
    public void postConstruct() {
 +
        injectedPartService.showPart(elementIdDeclaredInModel);
 +
    }
 +
 
 +
    public void openPart(String elementIdDeclaredInModel) {
 +
        EPartService partService = eclipseCtx.get(EPartService.class);
 +
        MPart part = partService.showPart(elementIdDeclaredInModel);
 +
    }
 +
}
 +
</source>
 +
 
 +
=== with the MApplicationFactory  ===
 +
 
 +
This uses the MApplicationFactory to create a part. With this method you have more control over the part at runtime and can call methods defined in the part (for example to set an input). Make sure to call the MPart.setURI() method before the MPart.setParent() method, otherwise you get a NullPointerException.
 +
 
 +
<source lang="java">
 +
IPresentationEngine renderer = (IPresentationEngine)context.get( IPresentationEngine.class.getName() );
 +
MApplicationFactory factory = ApplicationFactoryImpl.init();
 +
MPart view = factory.createPart();
 +
view.setLabel( "TestView" );
 +
 
 +
view.setURI( "platform:/plugin/de.sampleapp.client/" + ViewContainer.class.getName() );
 +
               
 +
MUIElement tableStack = ( MUIElement ) context.get( "tableStack" ); // tableStack is the id of the PartStack where the new part should be shown
 +
view.setParent( (MElementContainer<MUIElement>) tableStack );
 +
               
 +
renderer.createGui( view );
 +
       
 +
ETabFolder w = (ETabFolder) ((MPartStack) tableStack).getWidget();
 +
w.setSelection( w.getItemCount() - 1 );
 +
       
 +
Bundle bundle = Activator.getDefault().getBundle();
 +
ViewContainer viewContainer = (ViewContainer)view.getObject();
 +
ITestView testView;
 +
testView = (ITestView)bundle.loadClass( "de.sampleapp.client.TestView" ).newInstance();
 +
testView.setInput( partInput );
 +
       
 +
viewContainer.setViewPart( testView );
 +
</source>
 +
 
 +
<br>
 +
 
 +
== Set the input on a part at runtime  ==
 +
 
 +
This approach uses a variable defined in the Application.e4xmi and dependency injection to pass the input to a part.
 +
 
 +
Create the variable in the Application.e4xmi.
 +
 
 +
<source lang="xml">
 +
<variables>input</variables>
 +
</source>
 +
'''Update''': Declaration of variable in Application.e4xmi not neccessary, anymore (see [http://www.eclipse.org/forums/index.php?t=msg&&th=161887&goto=511703 here]).
 +
 
 +
Define a method in the part which gets the input using dependency injection
 +
 
 +
<source lang="java">
 +
@Inject
 +
@Optional
 +
public void setPartInput( @Named( "input" ) Object partInput ) { ... }
 +
</source>
 +
 
 +
Set the input with the help of the IEclipseContext of the part. You need to declare the variable as modifiable to change it multiple times.
 +
 
 +
'''Note:''' we don't use this facility anymore
 +
 
 +
<source lang="java">
 +
part.getContext().modify( "input", partInput );
 +
part.getContext().declareModifiable( "input" );
 +
</source>
 +
 
 +
== Execute Command/Handler manually ==
 +
 
 +
To execute an command/handler, which is defined in application model can be invoked manually using the services ECommandService and EHandlerService.
 +
The code could look like this:
 +
<source lang="java">
 +
ECommandService commandService = eclipseCtx.get(ECommandService.class);
 +
EHandlerService handlerService = eclipseCtx.get(EHandlerService.class);
 +
 
 +
ParameterizedCommand myCommand = commandService.createCommand(MY_COMMAND_ID, ARGUMENTS_MAP);
 +
Object result = handlerService.executeHandler(myCommand);
 +
</source>
 +
 
 +
 
 +
Please notice, that the methods in the handler class must be annotated:
 +
<source lang="java">
 +
import org.eclipse.e4.core.di.annotations.CanExecute;
 +
import org.eclipse.e4.core.di.annotations.Execute;
 +
 
 +
public class MyCommandHandler {
 +
 
 +
@Execute
 +
public void execute() {
 +
System.out.println("execute()");
 +
}
 +
 
 +
@CanExecute
 +
public boolean canExecute() {
 +
                 boolean mayExecute = checkConditions();
 +
return true;
 +
}
 +
 
 +
}
 +
</source>
 +
 
 +
= Event Processing =
 +
 
 +
== Event Broker ==
 +
 
 +
=== Send Events ===
 +
 
 +
Use the IEclipseContext to get the EventBroker and send the event using an event name and the event data:
 +
 
 +
<source lang="java">
 +
IEventBroker eventBroker = (IEventBroker) context.get( IEventBroker.class.getName() );
 +
if ( eventBroker != null )
 +
    eventBroker.post( EVENT_NAME, new String( "Update_Table" ) );
 +
</source>
 +
 
 +
=== Receive Events ===
 +
 
 +
Register your receiver with the event:
 +
 
 +
<source lang="java">
 +
IEventBroker eventBroker = ( IEventBroker) context.get(IEventBroker.class.getName() );
 +
eventBroker.subscribe( EVENT_NAME, this );
 +
</source>
 +
 
 +
Implement the EventHandler interface, to handle incoming events:
 +
 
 +
<source lang="java">
 +
@Override
 +
public void handleEvent( Event event ) {
 +
 
 +
  // get the event topic ( which is the EVENT_NAME in this example )
 +
  String eventTopic = event.getTopic();
 +
 
 +
  // get the event data ( which is the String "Update_Table" in this example )
 +
  Object eventData = event.getProperty( "org.eclipse.e4.data" );
 +
 
 +
  ...
 
}
 
}
 
</source>
 
</source>

Latest revision as of 15:30, 22 June 2011


Parts

Open a part dynamically

with a Part Descriptor

This approach defines a part descriptor and opens the part with the help of the EPartService. You must include the org.eclipse.equinox.event plugin to your run configuration.

Create a components.e4xmi file to define the part descriptor.

<?xml version="1.0" encoding="ASCII"?>
<application:ModelComponents xmi:version="2.0"
	xmlns:xmi="http://www.omg.org/XMI" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application"
	xmi:id="_RNb6kExtEd-JN6r-4dl3-A">
	<components xmi:id="_TqGKQExtEd-JN6r-4dl3-A" parentID="application">
		<descriptors xmi:id="_n1GVsFOZEd-e5P7xr5S20g" label="View"
			tooltip="ToolTip from XMI" elementId="elementIdDeclaredInModel"
			category="tagOfTarget" closeable="true"
			contributionURI="platform:/plugin/org.eclipse.e4.demo.View" />
	</components>
</application:ModelComponents>

Notice (since 1.0M4): The category attribute of the <descriptors> tag is used, to find the desired container for the part on creation via EPartService. The category MUST match any <tag> added to the target container (for example in Application.e4xmi) to make it possible finding the desired container, at all.

Register the components.e4xmi definition through an extension.

<extension 
	id="SampleApp"
	name="SampleApp"
	point="org.eclipse.e4.workbench.model">
		<snippet
			uri="xmi/components.e4xmi">
		</snippet>
</extension>

Open the part via elementId defined in model using the EPartService, which you can retrieve via dependency injection or via IEclipseContext.

public class ViewTest {
 
    @Inject
    private EPartService injectedPartService;
 
    public ViewTest() {
    }
 
    @PostConstruct
    public void postConstruct() {
        injectedPartService.showPart(elementIdDeclaredInModel);
    }
 
    public void openPart(String elementIdDeclaredInModel) {
        EPartService partService = eclipseCtx.get(EPartService.class);
        MPart part = partService.showPart(elementIdDeclaredInModel);
    }
}

with the MApplicationFactory

This uses the MApplicationFactory to create a part. With this method you have more control over the part at runtime and can call methods defined in the part (for example to set an input). Make sure to call the MPart.setURI() method before the MPart.setParent() method, otherwise you get a NullPointerException.

IPresentationEngine renderer = (IPresentationEngine)context.get( IPresentationEngine.class.getName() );
MApplicationFactory factory = ApplicationFactoryImpl.init();
MPart view = factory.createPart();
view.setLabel( "TestView" );
 
view.setURI( "platform:/plugin/de.sampleapp.client/" + ViewContainer.class.getName() );
 
MUIElement tableStack = ( MUIElement ) context.get( "tableStack" ); // tableStack is the id of the PartStack where the new part should be shown
view.setParent( (MElementContainer<MUIElement>) tableStack );
 
renderer.createGui( view );
 
ETabFolder w = (ETabFolder) ((MPartStack) tableStack).getWidget();
w.setSelection( w.getItemCount() - 1 );
 
Bundle bundle = Activator.getDefault().getBundle();
ViewContainer viewContainer = (ViewContainer)view.getObject();
ITestView testView;
testView = (ITestView)bundle.loadClass( "de.sampleapp.client.TestView" ).newInstance();
testView.setInput( partInput );
 
viewContainer.setViewPart( testView );


Set the input on a part at runtime

This approach uses a variable defined in the Application.e4xmi and dependency injection to pass the input to a part.

Create the variable in the Application.e4xmi.

<variables>input</variables>

Update: Declaration of variable in Application.e4xmi not neccessary, anymore (see here).

Define a method in the part which gets the input using dependency injection

@Inject
@Optional
public void setPartInput( @Named( "input" ) Object partInput ) { ... }

Set the input with the help of the IEclipseContext of the part. You need to declare the variable as modifiable to change it multiple times.

Note: we don't use this facility anymore

part.getContext().modify( "input", partInput );
part.getContext().declareModifiable( "input" );

Execute Command/Handler manually

To execute an command/handler, which is defined in application model can be invoked manually using the services ECommandService and EHandlerService. The code could look like this:

ECommandService commandService = eclipseCtx.get(ECommandService.class);
EHandlerService handlerService = eclipseCtx.get(EHandlerService.class);
 
ParameterizedCommand myCommand = commandService.createCommand(MY_COMMAND_ID, ARGUMENTS_MAP);
Object result = handlerService.executeHandler(myCommand);


Please notice, that the methods in the handler class must be annotated:

import org.eclipse.e4.core.di.annotations.CanExecute;
import org.eclipse.e4.core.di.annotations.Execute;
 
public class MyCommandHandler {
 
	@Execute
	public void execute() {
		System.out.println("execute()");
	}
 
	@CanExecute
	public boolean canExecute() {
                boolean mayExecute = checkConditions();
		return true;
	}
 
}

Event Processing

Event Broker

Send Events

Use the IEclipseContext to get the EventBroker and send the event using an event name and the event data:

IEventBroker eventBroker = (IEventBroker) context.get( IEventBroker.class.getName() );
if ( eventBroker != null )
     eventBroker.post( EVENT_NAME, new String( "Update_Table" ) );

Receive Events

Register your receiver with the event:

IEventBroker eventBroker = ( IEventBroker) context.get(IEventBroker.class.getName() );
eventBroker.subscribe( EVENT_NAME, this );

Implement the EventHandler interface, to handle incoming events:

@Override
public void handleEvent( Event event ) {
 
   // get the event topic ( which is the EVENT_NAME in this example )
   String eventTopic = event.getTopic();
 
   // get the event data ( which is the String "Update_Table" in this example )
   Object eventData = event.getProperty( "org.eclipse.e4.data" );
 
   ...
}

Back to the top