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 "Eclipse4/RCP/Modeled UI/Contributing to the Model"

< Eclipse4‎ | RCP‎ | Modeled UI
(Creating Model Elements at Runtime)
 
(Model Fragments)
 
(3 intermediate revisions by one other user not shown)
Line 1: Line 1:
 
== Model Fragments ==
 
== Model Fragments ==
  
Your application model can be spread out across several e4xmi files, to be stiched together at startup.  This mechanism allows adding new mode elements or referencing existing model elements to collections defined by other model elements.  For example, you can use a fragment to define a new <tt>MWindow</tt> and add it to the <tt>MApplication</tt>'s children (a set of windows).  It is important that any model elements that you intend to reference have a unique <em>elementId</em> (e.g., the <tt>MApplication</tt>).
+
Your application model can be spread out across several e4xmi files, to be stiched together at startup.  This mechanism allows adding new mode elements or referencing existing model elements to collections defined by other model elements.  For example, you can use a fragment to define a new <tt>MWindow</tt> and add it to the <tt>MApplication</tt>'s children (a set of windows).  It is important that any model elements that you intend to reference have a unique <em>elementId</em> (e.g., the <tt>MApplication</tt>) in their relevant scope. For example, the main menu of each window will typically use the same id but different parts in the same application should use different ids.
  
 
# Create a fragment file, typically called <tt>fragment.e4xmi</tt>
 
# Create a fragment file, typically called <tt>fragment.e4xmi</tt>
Line 10: Line 10:
 
<source lang="xml">
 
<source lang="xml">
 
<fragment:ModelFragments ...elided...>
 
<fragment:ModelFragments ...elided...>
 +
  <!-- we now reference the "org.eclipse.ui.file.exit" command with "XXXX" -->
 
   <imports xsi:type="commands:Command" xmi:id="XXXX" elementId="org.eclipse.ui.file.exit"/>
 
   <imports xsi:type="commands:Command" xmi:id="XXXX" elementId="org.eclipse.ui.file.exit"/>
   <fragments xsi:type="fragment:StringModelFragment" xmi:id="..." featurename="handlers" parentElementId="my.e4.application">
+
 
 +
  <!-- add a handler for the org.eclipse.ui.file.exit command to the app's global handlers -->
 +
   <fragments xsi:type="fragment:StringModelFragment" xmi:id="..." featurename="handlers"
 +
        parentElementId="my.e4.application">
 
     <elements xsi:type="commands:Handler" xmi:id="..." elementId="handler.exit"
 
     <elements xsi:type="commands:Handler" xmi:id="..." elementId="handler.exit"
 
       contributionURI="platform:/plugin/bundle/class.to.MyExitHandler" command="XXXX"/>
 
       contributionURI="platform:/plugin/bundle/class.to.MyExitHandler" command="XXXX"/>
Line 17: Line 21:
 
</fragment:ModelFragments>
 
</fragment:ModelFragments>
 
</source>
 
</source>
 +
Although you can define such a file by hand if you like, we recommend using the Workbench Model Editor instead.
  
Finally, the fragment is then made available through the <tt>org.eclipse.e4.workbench.model</tt> extension point.
+
Finally, the fragment is made available through the <tt>org.eclipse.e4.workbench.model</tt> extension point.
 
+
<source lang="xml">
== Manipulating the Model With Processors ==
+
<extension
 
+
        point="org.eclipse.e4.workbench.model">
 +
      <fragment
 +
            uri="fragment.e4xmi">
 +
      </fragment>
 +
</extension>
 +
</source>
  
 
== Creating Model Elements at Runtime ==
 
== Creating Model Elements at Runtime ==
Line 44: Line 54:
 
container.setSelectedElement(part);  // raise to top
 
container.setSelectedElement(part);  // raise to top
 
</source>
 
</source>
 +
 +
 +
== Manipulating the Model With Processors ==
 +
 +
Model processors are objects that provided the opportunity to modify and add to the model before its rendered.  For example, we sketch here a model processor to ensure that a specific <em>AddOn</em> is configured for the application.
 +
 +
A model processor is configured through an extension to the <tt>org.eclipse.e4.workbench.model</tt> extension point.
 +
 +
<source lang="xml">
 +
<extension
 +
        point="org.eclipse.e4.workbench.model">
 +
      <!-- if beforefragment="true", then the processor is run before any fragments are stitched in -->
 +
      <processor
 +
            beforefragment="false"
 +
            class="package.FooProcessor">
 +
      </processor>
 +
</extension>
 +
</source>
 +
 +
A model processor is a normal injectable POJO class whose processing is triggered by ab <tt>@Execute</tt>-annotated method.  For example, the basic template for a processor that acts to ensure that a particular addon is configured would look something like the following:
 +
<source lang="java">
 +
// ensure the FooAddOn is defined for this application
 +
class FooProcessor {
 +
@Inject
 +
protected MApplication app;
 +
 +
@Execute
 +
public void execute() {
 +
String addonId = FooAddOn.class.getName();
 +
for (MAddon addon : app.getAddons()) {
 +
if (addonId.equals(addon.getElementId())) {
 +
// our addon was found
 +
return;
 +
}
 +
}
 +
 +
MAddon addon = MApplicationFactory.INSTANCE.createAddon();
 +
addon.setContributionURI("platform:/plugin/bundle/package.FooAddOn");
 +
addon.setElementId(addonId);
 +
app.getAddons().add(addon);
 +
}
 +
}
 +
</source>
 +
 +
Model processors differ from fragments in two key ways.  First, a processor can perform more sophisticated manipulations of the model, such as deleting elements or moving elements within the model, as well as creating new elements.  The fragment example above, that installed a handler for the <tt>org.eclipse.ui.file.exit</tt> command, may not perform as expected if there is an existing global handler for that command.  Second, model processors are not specific to a particular application instance.  Although our <tt>FooAddOn</tt> could have been installed through a model fragment, the fragment would have had to explicitly specify the application's <tt>elementId</tt> to be extended, and thus been locked-in.  Typically fragments are used for application extensions, and model processors for installing services that are application-independent.  This pattern is used in the E4AP itself, such as to configure the MacOS X Cocoa enhancement (found in <tt>org.eclipse.e4.ui.workbench.renderers.swt.cocoa</tt>).

Latest revision as of 11:21, 12 December 2017

Model Fragments

Your application model can be spread out across several e4xmi files, to be stiched together at startup. This mechanism allows adding new mode elements or referencing existing model elements to collections defined by other model elements. For example, you can use a fragment to define a new MWindow and add it to the MApplication's children (a set of windows). It is important that any model elements that you intend to reference have a unique elementId (e.g., the MApplication) in their relevant scope. For example, the main menu of each window will typically use the same id but different parts in the same application should use different ids.

  1. Create a fragment file, typically called fragment.e4xmi
  2. Add the necessary imports to bring in model elements that will be referenced, as opposed to being extended
  3. Add StringModelFragments for each of the model elements to be extended. The parentElementId is the elementId of the element to be extended. featureame is the container feature name where new or existing elements will be added to.

For example, the following is a very simplified example of a fragment adding a command handler for the standard Exit/Quit command, where the command was defined elsewhere and thus imported:

<fragment:ModelFragments ...elided...>
  <!-- we now reference the "org.eclipse.ui.file.exit" command with "XXXX" -->
  <imports xsi:type="commands:Command" xmi:id="XXXX" elementId="org.eclipse.ui.file.exit"/>
 
  <!-- add a handler for the org.eclipse.ui.file.exit command to the app's global handlers -->
  <fragments xsi:type="fragment:StringModelFragment" xmi:id="..." featurename="handlers"
         parentElementId="my.e4.application">
    <elements xsi:type="commands:Handler" xmi:id="..." elementId="handler.exit"
       contributionURI="platform:/plugin/bundle/class.to.MyExitHandler" command="XXXX"/>
   </fragments>
</fragment:ModelFragments>

Although you can define such a file by hand if you like, we recommend using the Workbench Model Editor instead.

Finally, the fragment is made available through the org.eclipse.e4.workbench.model extension point.

<extension
         point="org.eclipse.e4.workbench.model">
      <fragment
            uri="fragment.e4xmi">
      </fragment>
</extension>

Creating Model Elements at Runtime

New elements are created and incorporated into the model using standard EMF patterns:

  1. Obtain the appropriate factory for the package.
  2. Create the desired object.
  3. Incorporate it into the model, typically by adding it to the appropriate container, to cause the element to be rendered.

For example, to create a new part:

// the container will hold the new element; maybe obtained using the EModelService
MPartStack container = ...; 
MPart part = MBasicFactory.INSTANCE.createPart();
part.setLabel("The Part Label");
part.setElementId("a-unique-identifier-for-this-part");
part.getPersistedState().put("input", "http://eclipse.org");
part.setContributionURI("platform:/plugin/bundle/classname");
 
container.getChildren().add(part);
container.setSelectedElement(part);  // raise to top


Manipulating the Model With Processors

Model processors are objects that provided the opportunity to modify and add to the model before its rendered. For example, we sketch here a model processor to ensure that a specific AddOn is configured for the application.

A model processor is configured through an extension to the org.eclipse.e4.workbench.model extension point.

<extension
         point="org.eclipse.e4.workbench.model">
      <!-- if beforefragment="true", then the processor is run before any fragments are stitched in -->
      <processor
            beforefragment="false"
            class="package.FooProcessor">
      </processor>
</extension>

A model processor is a normal injectable POJO class whose processing is triggered by ab @Execute-annotated method. For example, the basic template for a processor that acts to ensure that a particular addon is configured would look something like the following:

// ensure the FooAddOn is defined for this application
class FooProcessor {
	@Inject
	protected MApplication app;
 
	@Execute
	public void execute() {
		String addonId = FooAddOn.class.getName();
		for (MAddon addon : app.getAddons()) {
			if (addonId.equals(addon.getElementId())) {
				// our addon was found
				return;
			}
		}
 
		MAddon addon = MApplicationFactory.INSTANCE.createAddon();
		addon.setContributionURI("platform:/plugin/bundle/package.FooAddOn");
		addon.setElementId(addonId);
		app.getAddons().add(addon);
	}
}

Model processors differ from fragments in two key ways. First, a processor can perform more sophisticated manipulations of the model, such as deleting elements or moving elements within the model, as well as creating new elements. The fragment example above, that installed a handler for the org.eclipse.ui.file.exit command, may not perform as expected if there is an existing global handler for that command. Second, model processors are not specific to a particular application instance. Although our FooAddOn could have been installed through a model fragment, the fragment would have had to explicitly specify the application's elementId to be extended, and thus been locked-in. Typically fragments are used for application extensions, and model processors for installing services that are application-independent. This pattern is used in the E4AP itself, such as to configure the MacOS X Cocoa enhancement (found in org.eclipse.e4.ui.workbench.renderers.swt.cocoa).

Back to the top