Difference between pages "Extending the Static Checker" and "Extending the project explorer"

From Event-B
(Difference between pages)
Jump to navigationJump to search
imported>Tommy
 
imported>Renato
 
Line 1: Line 1:
 
{{TOCright}}
 
{{TOCright}}
 
= Introduction =
 
= Introduction =
The purpose of this page is to describe how to extend the static checker. It covers on the one hand, the definition of the extension, and on the other hand its implementation.
+
The purpose of this page is to describe how to extend the Event-B project explorer. It covers on the one hand, the definition of the extension, and on the other hand its implementation. The Event-B project explorer is itself an implementation of the extension-point <tt>org.eclipse.ui.views</tt>. The corresponding view id is '''fr.systerel.explorer.navigator.view''' which is defined as a subclass of <tt>org.eclipse.ui.navigator.CommonNavigator</tt> and it is over this view that we extend the project explorer.
  
The useful extension points are listed below; they offer the possibility to contribute to the static checker:
+
[[Image:EventB project explorer.png]]
* <tt>org.rodinp.core.autoTools</tt>
+
 
* <tt>org.eventb.core.configurations</tt>
+
The useful extension points are listed below; they offer the possibility to contribute to the project explorer:
* <tt>org.rodinp.core.internalElementTypes</tt>
+
* <tt>org.eclipse.ui.navigator.navigatorContent</tt>
* <tt>org.eventb.core.scModuleTypes</tt>
+
* <tt>org.eclipse.ui.navigator.viewer</tt>
* <tt>org.eventb.core.scStateTypes</tt>
 
  
 
= Before Starting =
 
= Before Starting =
  
It is necessary to define the static checked elements that are similar to the unchecked elements. We will use as an example the ''decompositionFile'' that is defined as follows:
+
It is necessary to define the elements and structure to be represented. We will use as an example the ''decompositionFile'' that is defined as follows:
  
 
*decompositionFile
 
*decompositionFile
 
**decompositionRoot
 
**decompositionRoot
***Component (machine to be decomposed)  
+
***Component with the following attributes: ''machine'' (to be decomposed)
***Configuration (''style'': shared events/shared variables;''newProjectOption'': decompose in the same project/different projects;''decomposeContextOption'':no decomposition/minimal decomposition)
+
***Configuration with the following attributes: ''style'': shared event/shared variables; ''newProjectOption'': decompose in the same project/different projects; ''decomposeContextOption'': noDecomposition/minimal decomposition)
***SubComponent (resulting decomposed parts)
+
***SubComponent (resulting decomposed parts) with the following attributes: ''label''
****SubComponentElement (elements used to decompose: variables for shared event decomposition and events for shared variable decomposition)
+
****SubComponentElement (elements used to decompose:variables for shared event and events for shared variable) with the following attributes: '' element name/identifier''
  
 
[[Image:Decomp file pretty print.png]]
 
[[Image:Decomp file pretty print.png]]
  
To extend the static checker, it is necessary to add a new content type (<tt>org.eclipse.core.contenttype.contentTypes</tt>) containing the checked version of the decompositionFile:
+
= Navigator Content =
 
 
      <content-type
 
          base-type="org.rodinp.core.rodin"
 
          file-extensions="dcc,dcc_tmp"
 
          id="scDcpFile"
 
          name="Event-B Statically Checked Decomposition File"
 
          priority="normal">
 
    </content-type>
 
 
 
and the respective file association (<tt>org.rodinp.core.fileAssociations</tt>):
 
 
 
    <fileAssociation
 
          content-type-id="ch.ethz.eventb.decomposition.core.scDcpFile"
 
          root-element-type="ch.ethz.eventb.decomposition.core.scDcpFile">
 
    </fileAssociation>
 
     
 
The respective static checked elements must be added as internal elements using the extension <tt>org.rodinp.core.internalElementTypes</tt>:
 
 
 
<extension
 
        point="org.rodinp.core.internalElementTypes">
 
    <internalElementType
 
          class="ch.ethz.eventb.decomposition.core.basis.DecompositionRoot"
 
          id="dcpFile"
 
          name="%eventBdcpFile">
 
    </internalElementType>
 
    <internalElementType
 
          class="ch.ethz.eventb.decomposition.core.basis.SCDecompositionRoot"
 
          id="scDcpFile"
 
          name="Event-B Statically Checked Decomposition Root">
 
    </internalElementType>
 
    <internalElementType
 
          class="ch.ethz.eventb.decomposition.core.basis.DecompositionConfiguration"
 
          id="configuration"
 
          name="%eventBDecompositionConfiguration">
 
    </internalElementType>
 
    <internalElementType
 
          class="ch.ethz.eventb.decomposition.core.basis.SCDecompositionConfiguration"
 
          id="scConfiguration"
 
          name="Event-B Statically Checked Decomposition Configuration">
 
    </internalElementType>
 
</extension>
 
 
 
In the above example, the first internal element type is the unckecked internal element, and the second is the same internal element but in the checked version. Having the checked elements defined, we can start to extend the static checker for our files and respective elements.
 
 
 
= AutoTools =
 
  
The static checker it is a tool that runs automatically. In order to implement the tool, it is necessary to define the following extension point <tt>org.rodinp.core.autoTools</tt>. This extension point allows tools to run automatically when changes to the Rodin database are committed. To implement the reactive model of Rodin, automatic tools run only when one of their input files has changed. As such, for each automatic tool, plugin developers must provide two kinds of contributions:
+
A content extension provides a content and label provider that can be used by a navigator content service (in out case the ''Event-B project explorer''). The navigatorContent extension defines the specific classes for the content provider, label provider, and action provider in addition to the types of elements the extension knows about. To extend the project explorer, it is also required to add the following children of the navigatorContent:
  
* Some dependency extractors.
+
* ''triggerPoints'': defines the nodes to be used when resolving the Common Navigator content provider's getElements() or getChildren(). This is also used to select the extension for providing labels, images, descriptions and for sorting.
* The tool itself.
+
*''possibleChildren'': defines the node to be used when resolving the Common Navigator content provider's getParent(). It is also used to help determine the parent when handling drop operations.
  
 
== Declaration ==
 
== Declaration ==
  
The <tt>autoTools</tt> extension-point allows tool writers to register their tool implementation under a symbolic name that is then used by the Rodin platform to find and run the tool. The symbolic name is the id of the tool extension. An example of the implementation of a static checker can be seen as follows:
+
The navigatorContent extension-point allows tool writers to register their tool implementation under a symbolic name that is then used by the Rodin platform to find and run the tool. The symbolic name is the id of the tool extension. The declaration of this extension is defined as follows:
  
  <extension
+
  <!ELEMENT navigatorContent ((enablement | (triggerPoints , possibleChildren)) , actionProvider* , commonSorter* , override? , dropAssistant* , commonWizard*)>
        point="org.rodinp.core.autoTools">
+
  <!ATTLIST navigatorContent
    <tool
+
  id               CDATA #REQUIRED
          class="ch.ethz.eventb.decomposition.internal.core.sc.DecompositionStaticChecker"
+
  name             CDATA #REQUIRED
          id="decompositionSC"
+
  priority          (lowest|lower|low|normal|high|higher|highest)
          name="Decomposition Static Checker">
+
  contentProvider  CDATA #IMPLIED
        <extractor
+
  icon              CDATA #IMPLIED
              class="ch.ethz.eventb.decomposition.internal.core.sc.DecompositionStaticChecker"
+
  activeByDefault  (true | false)
              name="Decomposition Extractor of Static Checker">
+
  providesSaveables (true | false)
          <inputType
+
  labelProvider    CDATA #IMPLIED
                id="ch.ethz.eventb.decomposition.core.dcpFile">
+
>
          </inputType>
 
        </extractor>
 
    </tool>
 
  </extension>
 
  
We defined a static checking tool that will run for the defined input type (<tt>ch.ethz.eventb.decomposition.core.dcpFile</tt>). The class provided for extractors shall implement the <tt>org.rodinp.core.builder.IExtractor</tt> interface, while the class provided for tools themselves shall implement <tt>org.rodinp.core.builder.IAutomaticTool</tt>.  
+
A navigator content extension defines a content provider and label provider that can be used to provide children whenever an element matches the triggerPoints expression and also to provide a parent whenever an element matches the possibleChildren expression. Optionally, we may also provide an action provider which can provide menu contributions and action bar contributions when an element is selected that the extension contributed, or that matches the triggerPoints expression. It is possible to contribute with a sorter to sort elements that are contributed by the extension.
  
The Rodin platform (see plug-in <tt>org.eventb.core</tt>) provides a static checking automatic tool for context/machine files.
+
* id - A unique ID to identify this extension. Used for extension activation and by other extensions that would like to extend the defined extension (e.g. add another <tt>org.eclipse.ui.navigator.CommonActionProvider</tt>)
 +
* name - Specify a display name for the Content Extension. The display name is used in the activation dialog to allow clients to turn an extension on or off.
 +
* priority - Indicates the relative priority of this extension to other extensions. Used by the Common Navigator to handle sorting and organization of the contributed content from this extension in relation to content from other extensions. Defaults to "normal"
 +
* contentProvider - Supplies the name of a class which implements <tt>org.eclipse.jface.viewers.ITreeContentProvider</tt> or <tt>org.eclipse.ui.navigator.ICommonContentProvider</tt>. The content provider will be consulted when adding children to the tree. Use the enablement, triggerPoints, or possibleChildren clauses to indicate what kinds of content should trigger a request to your content provider. Elements contributed from the content provider are not guaranteed to appear in the tree in the same order. Clients should take advantage of the sorting extension (commonSorter) to ensure proper ordering of their elements. All elements contributed by this content provider are associated with this navigatorContent extension for the purposes of determining the label provider, action providers, sorters, drop assistants and common wizards.
 +
* icon - A plugin-relative path to an icon for use when displaying the metadata about the content extension to the user.
 +
* activeByDefault - Indicates whether the current extension will be active by default. Each content extension may be turned on or off by the user. The active state is differentiated from the visible state. See <tt>org.eclipse.ui.navigator.viewer/viewerContentBinding</tt> for more information on visibility
 +
*labelProvider - Supplies the name of a class which implements <tt>org.eclipse.jface.viewers.ILabelProvider</tt> or for more advanced functionality, the <tt>org.eclipse.ui.navigator.ICommonLabelProvider</tt>. Clients may also implement <tt>org.eclipse.ui.navigator.IDescriptionProvider</tt> in order to add text to the status bar at the bottom of the Eclipse workbench based on the selection in the viewer. Since Eclipse 3.4, clients may also implement <tt>org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider</tt> to provide styled text labels. Note that the empty styled string signals that the label provider does not wish to render the label.
  
== Programmatic usage ==
+
===Action Provider===
The class to be implemented usually extends the class <tt>org.eventb.core.sc.StaticChecker</tt>
 
and needs to implement the abstract method <tt>extract</tt> from the interface <tt>org.rodinp.core.builder.IExtractor</tt>:
 
  
    public void extract(IFile file, IGraph graph, IProgressMonitor monitor)throws CoreException {
+
Still inside the navigatorContent, it is possible to add the following:
        try {
 
              monitor.beginTask(Messages.bind(Messages.build_extracting, file.getName()), 1);
 
              IRodinFile source = RodinCore.valueOf(file);
 
              IDecompositionRoot root = (IDecompositionRoot) source.getRoot();
 
              IRodinFile target = root.getSCDecompositionRoot().getRodinFile();
 
              graph.addTarget(target.getResource());
 
              graph.addToolDependency(source.getResource(), target.getResource(),true);
 
            } finally {
 
              monitor.done();
 
            }
 
    }
 
  
The interface <tt>org.rodinp.core.builder.IGraph</tt> is used by the extractors registered with the builder to manipulate the dependency graph of all Rodin resources of a Rodin project. It is a façade to the more complicated ways of manipulating the dependency graph inside the builder. Some information is cached in the corresponding object, so the contents of the façade must be synchronised with the graph at the end of an extraction. Requests to add nodes to the graph must be made explicitly by calls to the method <tt>addNode</tt>. Dependencies are managed by the façade. It saves clients to have to compute dependency graph deltas themselves.
+
  <!ELEMENT actionProvider (enablement?)>
 
+
   <!ATTLIST actionProvider
We have already defined the static checking tool and the target for which it will run. Now, we need to configure the static checker tool. It is necessary to define the checks that are required for each element and this is done by providing an extension to <tt>org.eventb.core.configurations</tt>.
+
  class        CDATA #REQUIRED
 
+
   id           CDATA #IMPLIED
= Configuration =
+
   dependsOn    CDATA #IMPLIED
 
+
   overrides    CDATA #IMPLIED
The configuration is used to define which modules are used by the static checker. Similarly, it can be used for the proof obligation generator (POG).
+
  priority      (lowest|lower|low|normal|high|higher|highest)
 
+
  appearsBefore IDREF #IMPLIED
== Declaration ==
 
 
 
  <!ELEMENT configuration ((config | pogModule | scModule))+>
 
   <!ATTLIST configuration
 
   id  CDATA #REQUIRED
 
   name CDATA #REQUIRED
 
 
   >
 
   >
  id - the identifier for this attribute type (simple id token, unique for attribute types within the extension namespace). The token cannot contain dot (.) or whitespace.
 
  name - the human-readable name of this attribute type
 
  
For static checks, we need <tt>scModule</tt> and <tt>config</tt> elements. Below we see on an example how to define the configuration:
+
A top level actionProvider is visible to an abstract viewer if there is a viewerActionBinding for that actionProvider. It is possible to provide actionProvider(s) under the root extension element (peer to other navigatorContent) in order to better control their enablement and viewer binding (see viewerActionBinding). Any items contributed to the toolbar or the view menu should be removed when the actionProviders is disposed. We described the two most used attributes of this element:
  
<extension
+
* ''class'' - Supplies the name of a class that implements <tt>org.eclipse.ui.navigator.CommonActionProvider</tt>. The action provider has an opportunity to contribute to the context menu and the retargetable actions defined in the IActionBars for the view that holds the navigator. It is also possible to contribute directly to the view menu through the IActionBars view menu.
        point="org.eventb.core.configurations">
+
* ''id'' - Clients may optionally define an id to use for filtering purposes (either through activities or viewerContentBindings).
      <configuration
 
            id="dcmp"
 
            name="Decomposition Configuration">
 
        <config
 
              id="ch.ethz.eventb.decomposition.core.dcmpBaseSC">
 
        </config>
 
      </configuration>
 
      <configuration
 
            id="dcmpSC"
 
            name="Decomposition Static Checker Root Module">
 
        <scModule
 
              id="ch.ethz.eventb.decomposition.core.decompositionModule">
 
        </scModule>
 
      </configuration>
 
      <configuration
 
            id="dcmpBaseSC"
 
            name="Decomposition Static Checker Base Module">
 
        <config
 
              id="ch.ethz.eventb.decomposition.core.dcmpSC">
 
        </config>
 
        <scModule
 
              id="ch.ethz.eventb.decomposition.core.componentModule">
 
        </scModule>
 
        <scModule
 
            id="ch.ethz.eventb.decomposition.core.decompositionConfigurationModule">
 
        </scModule>
 
        <scModule
 
              id="ch.ethz.eventb.decomposition.core.subComponentModule">
 
        </scModule>
 
        <scModule
 
              id="ch.ethz.eventb.decomposition.core.subComponentElementModule">
 
        </scModule>
 
      </configuration>
 
  </extension>
 
  
We structure the configuration as follows (although it can be structured in a different way):
+
To define when to enable this actionProvider, it is necessary to define the ''enablement'':
  
* "Decomposition Configuration" (id=dcmp) is defined by a base static checker module that contains the configuration element "Decomposition Static Checker Base Module" (see "config" markup, id=ch.ethz.eventb.decomposition.core.dcmpBaseSC). This configuration element is a reference to the respective configuration.
+
<!ELEMENT enablement (not , and , or , instanceof , test , systemTest , equals , count , with , resolve , adapt , iterate , reference)*>
* "Decomposition Static Checker Root Module" (id=dcmpSC) defines the initial module for decomposition (initialisation of the static checker) as the Root Module.
 
* "Decomposition Static Checker Base Module" (id =dcmpBaseSC) defines all other modules, for each element in the decompositionFile:
 
** <tt>ch.ethz.eventb.decomposition.core.componentModule</tt>
 
** <tt>ch.ethz.eventb.decomposition.core.decompositionConfigurationModule</tt>
 
** <tt>ch.ethz.eventb.decomposition.core.subComponentModule</tt>
 
** <tt>ch.ethz.eventb.decomposition.core.subComponentElementModule</tt>
 
  
Here we are just defining the configuration of the modules. These modules shall be defined separately using the extension point <tt>org.eventb.core.scModuleTypes</tt>. These are used to process the necessary operations for each element inside a statically checked file.
+
The enablement expression allows clients to specify the same expression for both triggerPoints and possibleChildren. In the case of actionProvider, clients must define an expression that will indicate to the framework when their <tt>org.eclipse.ui.navigator.CommonActionProvider</tt> should be invoked. Because of contributions to the ''IActionBars'', clients must be invoked whenever an object they are interested in is selected. Therefore, clients should use discretion in deciding when their extension should be enabled.
  
 
== Programmatic usage ==
 
== Programmatic usage ==
{{TODO}}
 
  
= Modules =
+
In the java side, create 4 packages:
== Filter ==
 
  
Filters are used to validate inserted elements. After the successful validation of all elements, they can be processed and stored in the statically-checked file. In order to implement a filter, we use the following extension from the extension point <tt>org.eventb.core.scModuleTypes</tt>:
+
* *.*.editors.image: Where you have the class that handles the images to be used to display the elements in the project explorer (see for example: <tt>/org.eventb.ui/src/org/eventb/ui/IEventBSharedImages.java</tt>)
  
<!ELEMENT filterType (prereq)*>
+
* *.*.ui.explorer.contentProvider: contains the classes required in the extension point <tt>org.eclipse.ui.navigator.navigatorContent</tt>.
  <!ATTLIST filterType
 
  id    CDATA #REQUIRED
 
  name  CDATA #REQUIRED
 
  parent CDATA #REQUIRED
 
  class  CDATA #REQUIRED
 
  >
 
  id - the identifier for this filter type (simple id token, unique for (filter/processor/root) types within the extension namespace).  
 
  The token cannot contain dot (.) or whitespace.
 
  name - the human-readable name of this filter module
 
  parent - the optional parent (processor) module. Root modules must leave the attribute undefined. It is not allowed to choose a filter module as parent.
 
  class - the fully-qualified name of a subclass of org.eventb.core.sc.SCFilterModule
 
  
For the filter type, the classes usually extend the abstract class <tt>org.eventb.core.sc.SCFilterModule</tt>. It also contains three methods:
+
* *.*.ui.explorer.actionProvider: contains the classes that handle the actions that can be originated by the added navigatorContent.
  
* <tt>public abstract boolean accept(IRodinElement element, ISCStateRepository repository, IProgressMonitor monitor) throws CoreException;</tt>: it runs the static checker module. It returns whether the element should be accepted or not. If an error marker is associated with the element, the returned value should usually be <tt>false</tt>. Exceptions from this rule are possible, in particular if the element has been already marked with an error.
+
* *.*.ui.explorer.model: The content of the explorer is structured in classes called ''Models''. They all implement the interface <tt>fr.systerel.internal.explorer.model.IModelElement</tt>. The elements are structured in projects (''ModelProjects'') where the root file contains elements that can have proof obligations associated (in that case they should extends the abstract class <tt>fr.systerel.internal.explorer.model.ModelPOContainer</tt>). The elements of a root file are ''ModelElementNode'' similar to <tt>fr.systerel.internal.explorer.model.ModelElementNode</tt>. The models structure would look like this:
  
* <tt>public abstract void initModule(ISCStateRepository repository,IProgressMonitor monitor) throws CoreException;</tt>: Initialisation code for the module.
+
  ModelProject
 +
    - ModelRoot1
 +
        - ModelElementNode1
 +
        - ModelElementNode2
 +
        - ...
 +
    - ModelRoot2
 +
        - ModelElementNode3
 +
        - ModelElementNode4
 +
        - ...
 +
       
 +
Moreover, a class called ''ModelController'' defined as a singleton controls all the models and contains useful methods. It also implements the interface <tt>org.rodinp.core.IElementChangedListener</tt> that will be called whenever there is a change in one of the model elements. It will clean up the existing elements in the project explorer and reload with the recent changes. The ''ModelController'' instance should be called by implementing the method <tt>org.eclipse.jface.viewers.IContentProvider#inputChanged</tt> (required for classes that implement interface <tt>org.eclipse.jface.viewers.ITreeContentProvider</tt>). Usually an abstract class that implements ITreeContentProvider is created: ''AbstractContentProvider''.  
  
* <tt>public abstract void endModule(ISCStateRepository repository,IProgressMonitor monitor) throws CoreException;</tt>: Termination code for the module.
+
public abstract class AbstractContentProvider implements ITreeContentProvider {
 +
        protected static Object[] NO_OBJECT = new Object[0];
 +
        protected IInternalElementType<?> type;
 +
        public AbstractContentProvider(IInternalElementType<?> type){this.type = type;}
 +
        public Object[] getChildren(Object parentElement) {
 +
                IModelElement model = ModelControllerDecomposition.getModelElement(parentElement);
 +
                if (model != null) {
 +
                      return model.getChildren(type, false);
 +
                }
 +
                return NO_OBJECT;
 +
        }
 +
        public Object getParent(Object element) {
 +
                IModelElement model = ModelControllerDecomposition.getModelElement(element);
 +
                if (model != null) {
 +
                        return model.getParent(true);
 +
                }
 +
                return null;
 +
      }
 +
      public boolean hasChildren(Object element) {
 +
              return getChildren(element).length>0;
 +
      }
 +
      public Object[] getElements(Object inputElement) {
 +
            return getChildren(inputElement);
 +
      }
 +
      public void dispose() {}
 +
      public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
 +
              if (viewer instanceof CommonViewer) {
 +
                    ModelControllerDecomposition.createInstance((CommonViewer)viewer);
 +
              }
 +
      }
 +
}
  
== Processor ==
+
This class is extended by the respective ''contentProviders''. For instance:
  
Processors literally process the elements, storing them in the static checked file, running sub-processors and adding states to the repository if required. To implement a processor, it is required to use the following extension from the extension point <tt>org.eventb.core.scModuleTypes</tt>:
+
public class DecompositionContentProvider extends AbstractContentProvider{...}
  
  <!ELEMENT processorType (prereq)*>
+
== Example ==
  <!ATTLIST processorType
 
  id    CDATA #REQUIRED
 
  name  CDATA #REQUIRED
 
  parent CDATA #REQUIRED
 
  class  CDATA #REQUIRED
 
  >
 
  id - the identifier for this processor type (simple id token, unique for (filter/processor/root) types within the extension namespace).
 
  The token cannot contain dot (.) or whitespace.
 
  name - the human-readable name of this processor module
 
  parent - the optional parent (processor) module. Root modules must leave the attribute undefined. It is not allowed to choose a filter module as parent.
 
  class - the fully-qualified name of a subclass of <tt>org.eventb.core.sc.SCProcessorModule</tt>
 
  
The classes that implement the root type and processor type usually extend the abstract class <tt>org.eventb.core.sc.SCProcessorModule</tt>. They contain a constant called <tt>MODULE_TYPE</tt> that identifies the <tt>scModule</tt> element. An example is:
+
An example of the implementation of this extension-point is defined below:
  
  public static final IModuleType<DecompositionModule> MODULE_TYPE = SCCore.getModuleType(DecompositionCorePlugin.PLUGIN_ID + ".decompositionModule");
+
  <extension
 +
        point="org.eclipse.ui.navigator.navigatorContent">
 +
      <navigatorContent
 +
            contentProvider="ch.ethz.eventb.decomposition.ui.explorer.contentProvider.DecompositionContentProvider"
 +
            id="ch.ethz.eventb.decomposition.ui.navigator.explorer.decomposition"
 +
            labelProvider="ch.ethz.eventb.decomposition.ui.explorer.contentProvider.DecompositionLabelProvider"
 +
            name="Decomposition Root"
 +
            priority="highest">
 +
        <triggerPoints>
 +
            <or>
 +
              <instanceof
 +
                    value="org.eclipse.core.resources.IProject">
 +
              </instanceof>
 +
              <instanceof
 +
                    value="ch.ethz.eventb.decomposition.core.IDecompositionRoot">
 +
              </instanceof>
 +
            </or></triggerPoints>
 +
        <possibleChildren>
 +
            <instanceof
 +
                  value="ch.ethz.eventb.decomposition.core.IDecompositionRoot">
 +
            </instanceof>
 +
        </possibleChildren>
 +
      </navigatorContent>
 +
      <navigatorContent
 +
            contentProvider="ch.ethz.eventb.decomposition.ui.explorer.contentProvider.ComponentContentProvider"
 +
            id="ch.ethz.eventb.decomposition.ui.navigator.explorer.component"
 +
            labelProvider="ch.ethz.eventb.decomposition.ui.explorer.contentProvider.DecompositionLabelProvider"
 +
            name="Decomposition Component"
 +
            priority="higher">
 +
        <triggerPoints>
 +
            <or>
 +
              <instanceof
 +
                    value="ch.ethz.eventb.decomposition.core.IDecompositionRoot">
 +
              </instanceof>
 +
              <instanceof
 +
                    value="ch.ethz.eventb.decomposition.core.IComponent">
 +
              </instanceof>
 +
            </or>
 +
        </triggerPoints>
 +
        <possibleChildren>
 +
            <instanceof
 +
                  value="ch.ethz.eventb.decomposition.core.IComponent">
 +
            </instanceof>
 +
        </possibleChildren>
 +
</extension>
  
that identifies the decomposition root module. Moreover, this classes should implement the three methods that are defined in the interface <tt>org.eventb.internal.core.tool.types.ISCProcessorModule</tt>:
+
Above we defined two navigatorContent elements (''DecompositionContentProvider'' and ''ComponentContentProvider'') using the same class as labelProvider (''DecompositionLabelProvider''). The first is triggered by instances of ''IProject'' and ''IDecompositionRoot'' and the possible children of this element are ''IDecompositionRoot'' as well.
  
* <tt>public abstract void initModule(IRodinElement element,ISCStateRepository repository,IProgressMonitor monitor) throws CoreException</tt>: Initialisation code for the module. Used to initialise the global variables of the class.
+
An actionProvider example is described below:
* <tt>public abstract void process(IRodinElement element,IInternalElement target, ISCStateRepository repository, IProgressMonitor monitor) throws CoreException</tt>: Runs the static checker module. It processes the element. The element itself has already been accepted. If this element has children, then the children modules should be called here (see for example <tt>ch.ethz.eventb.decomposition.core.sc.modules.DecompositionSubComponentModule</tt>).
 
* <tt>public abstract void endModule(IRodinElement element,ISCStateRepository repository,IProgressMonitor monitor) throws CoreException</tt>: Termination code for the module. It is used to clean up memory (global variables) before finishing the module call.
 
  
== Root ==
+
      <actionProvider
Similar to a processor, but applied to the root of the file. The extension that needs to be implemented is defined below:
+
            class="ch.ethz.eventb.decomposition.ui.explorer.actionProvider.DecompositionRootActionProvider"
 +
            id="ch.ethz.eventb.decomposition.ui.DecompositionRootActionProvider">
 +
        <enablement>
 +
            <or>
 +
              <instanceof
 +
                    value="ch.ethz.eventb.decomposition.core.IDecompositionRoot">
 +
              </instanceof>
 +
              <instanceof
 +
                    value="ch.ethz.eventb.decomposition.core.IDecompositionConfiguration">
 +
              </instanceof>
 +
              <instanceof
 +
                    value="ch.ethz.eventb.decomposition.core.ISubComponent">
 +
              </instanceof>
 +
              <instanceof
 +
                    value="ch.ethz.eventb.decomposition.core.ISubComponentElement">
 +
              </instanceof>
 +
              <instanceof
 +
                    value="ch.ethz.eventb.decomposition.core.IComponent">
 +
              </instanceof>
 +
            </or>
 +
        </enablement>
 +
      </actionProvider>
  
<!ELEMENT rootType EMPTY>
+
This actionProvider, described by the class <tt>ch.ethz.eventb.decomposition.ui.explorer.actionProvider.DecompositionRootActionProvider</tt> is enabled by instances of IDecompositionRoot, IDecompositionConfiguration, ISubComponent, ISubComponentElement and IComponent.
  <!ATTLIST rootType
 
  id    CDATA #REQUIRED
 
  name  CDATA #REQUIRED
 
  input CDATA #REQUIRED
 
  class CDATA #REQUIRED
 
  >
 
  id - the identifier for this root type (simple id token, unique for (filter/processor/root) types within the extension namespace). The token cannot contain dot (.) or whitespace.
 
  name - the human-readable name of this root module
 
  input - identifier of the input file element type for this root module.
 
  class - the fully-qualified name of a subclass of org.eventb.core.sc.SCProcessorModule
 
  
== Sequencing ==
+
= Navigator Viewer =
  
 +
The viewer element defines the configuration for a common viewer. The extension may provide a custom popup menu id, override whether the viewer provides link with editor support, provides a filter dialog, and/or provides an "Available customizations" dialog. In addition, nested configuration elements give full control over the structure and behavior of the popup context menu. We define two children of this extension point:
  
=== Parent ===
+
* viewerContentBinding: to define the visibility of ''contentProviders''.
{{TODO}}
+
* viewerActionBinding: to define the visibility of ''actionProviders''.
  
=== Prerequisite ===
+
== Declaration ==
 
 
Some static checks rely on already done static checks so they work as pre-requirements. For instance, if a concrete event is refined, it is necessary to know the abstract machine defined in the refine machine section. So the refine machine is a static check pre-requirement for the refinement an event. To implement a pre-requirement, it is necessary to use the following extension point:
 
  
  <!ELEMENT prereq EMPTY>
+
  <!ELEMENT viewerContentBinding (includes? , excludes?)>
   <!ATTLIST prereq
+
   <!ATTLIST viewerContentBinding
   id CDATA #REQUIRED
+
   viewerId CDATA #REQUIRED
 
   >
 
   >
  id - the full ids of all (filter and processor) modules that must be run before this module
 
 
== Example ==
 
 
An example of module declaration is given below:
 
 
  <extension
 
          point="org.eventb.core.scModuleTypes">
 
        <rootType
 
              class="ch.ethz.eventb.decomposition.core.sc.modules.DecompositionModule"
 
              id="decompositionModule"
 
              input="ch.ethz.eventb.decomposition.core.dcpFile"
 
              name="Decomposition SC Root Module">
 
        </rootType>
 
        <processorType
 
              class="ch.ethz.eventb.decomposition.core.sc.modules.DecompositionComponentModule"
 
              id="decompositionComponentModule"
 
              name="Decomposition SC Component Module"
 
              parent="ch.ethz.eventb.decomposition.core.decompositionModule">
 
        </processorType>
 
        .
 
        .
 
        .
 
        <filterType
 
              class="ch.ethz.eventb.decomposition.core.sc.modules.DecompositionSubComponentElementFilterModule"
 
              id="decompositionSubComponentElementFilterModule"
 
              name="Decomposition SC SubComponentElement Filter Module"
 
              parent="ch.ethz.eventb.decomposition.core.decompositionCommitSubComponentElementModule">
 
          <prereq
 
                id="ch.ethz.eventb.decomposition.core.decompositionConfigurationModule">
 
          </prereq>
 
          <prereq
 
                id="ch.ethz.eventb.decomposition.core.decompositionComponentModule">
 
          </prereq>
 
        </filterType>
 
    </extension>
 
 
Below is an example of the call of the three processor/root methods in the class <tt>ch.ethz.eventb.decomposition.core.sc.modules.DecompositionModule</tt>:
 
  
        @Override
+
Clients must define one or more viewerContentBinding elements to describe which content extensions, common filters, and link helpers are visible to the viewer. A content extension or common filter is visible if the id of the content extension or common filter matches an includes statement under a viewerContentBinding and is not excluded by an excludes statement. If a content extension or common filter is not visible to a viewer, then the extension will never be asked for content by a content service for that viewer or be presented to the user in the available filters dialog. Clients may define an includes element to select which extensions are visible to the viewer, and similarly an excludes element for extensions that should not be made visible to the viewer. Clients may further define the extensions that should be explicitly queried for root elements (through ITreeContentProvider.getElements()) by the "isRoot" attribute. If one or more contentExtension elements have "isRoot" set to true within the includes statement, only those extensions will be queried for root elements. The "isRoot" attribute has no effect for exclusions. A viewer may have multiple viewerContentBindings defined, and their includes/excludes statements will be aggregated to produce the final behavior.
        public void initModule(IRodinElement element,ISCStateRepository repository,  IProgressMonitor monitor) throws CoreException {
 
                accuracyInfo = new DecompositionAccuracyInfo();
 
                final IDecompositionLabelSymbolTable labelSymbolTable = new DecompositionLabelSymbolTable(LABEL_SYMTAB_SIZE);
 
                repository.setState(labelSymbolTable);
 
                repository.setState(accuracyInfo);
 
                initProcessorModules(element, repository, monitor);
 
        }
 
  
        public void process(IRodinElement element, IInternalElement target,ISCStateRepository repository, IProgressMonitor monitor)throws CoreException {
+
* viewerId - The id of the common viewer. If the viewer is in a common navigator then the id must match the navigator's id defined in its org.eclipse.ui.views extension.
                scRoot = (ISCDecompositionRoot) target;
 
              processModules(element, target, repository, monitor);
 
        }
 
 
        @Override
 
        public void endModule(IRodinElement element,ISCStateRepository repository, IProgressMonitor monitor) throws CoreException {
 
                scRoot.setAccuracy(accuracyInfo.isAccurate(), monitor);
 
              endProcessorModules(element, repository, monitor);
 
        }
 
 
Whenever a problem is encountered by the static checker, it is possible to raise a warning or an error, highlighting the associated element, using the method <tt>org.eventb.core.sc.SCModule#createProblemMarker</tt>. An example can be seen below:
 
  
        public void process(IRodinElement element, IInternalElement target,ISCStateRepository repository, IProgressMonitor monitor)throws CoreException {
+
<!ELEMENT viewerActionBinding (includes? , excludes?)>
                monitor.subTask(Messages.bind(Messages.progress_DecompositionComponent));
+
   <!ATTLIST viewerActionBinding
                IComponent[] decompositionComponents = decompositionFile.getDecompositionComponents();
+
   viewerId CDATA #REQUIRED
                if (decompositionComponents.length > 1) {
 
                        for (int k = 1; k < decompositionComponents.length; k++) {
 
                                createProblemMarker(decompositionComponents[k], DecompositionConfigurationAttributes.TARGET_ATTRIBUTE,
 
                                                              DecompositionGraphProblem.TooManyComponentsError);
 
                        }
 
              }
 
              ...
 
              repository.setState(new ComponentMachineInfo(scComponentMachineRoot,component));
 
              ...
 
              monitor.worked(1);
 
      }
 
 
 
In this particular case, if the number of <tt>IComponent</tT> elements is greater than 1, then an error is generated for the related <tt>IComponent</tt> element:
 
 
 
[[Image:More_than_one_component_error.png]]
 
 
 
=States=
 
 
 
The static check of the elements in a file are independent of each other (different and independent modules). Nevertheless, some information depends on other elements. For instance, for label elements, it is necessary to know which labels have been previously used before checking the elements. Since the elements checks are independent, the solution is to ‘share data‘ through states implemented using the extension point <tt>org.eventb.core.scStateTypes</tt>. They are used to dynamically store data that will be used by dependencies. The data are stored in the <tt>SCStateRepository</tt> base, which contains a key and respective contents.
 
 
 
==Declaration==
 
 
 
<!ELEMENT stateType EMPTY>
 
   <!ATTLIST stateType
 
  id    CDATA #REQUIRED
 
  name  CDATA #REQUIRED
 
   class CDATA #REQUIRED
 
 
   >
 
   >
  id - the identifier for this attribute type (simple id token, unique for attribute types within the extension namespace). The token cannot contain dot (.) or whitespace.
 
  name - the human-readable name of this attribute type
 
  class - the fully-qualified name of a subclass of org.eventb.core.sc.state.ISCState
 
  
==Programmatic Usage==
+
Clients must define which action providers are visible to their viewer. Clients may define an includes element to select which extensions are visible to the viewer, and similarly an excludes element for extensions that should not be made visible to the viewer. A viewer may have multiple viewerActionBindings defined, and their includes/excludes statements will be aggregated to produce the final behavior.
  
To store data, we need to call the method
+
== Example ==
  
<tt>void setState(I state)</tt> [I extends IState]
+
An example of the use of this extension point is defined below:
 
 
defined in the interface <tt>org.eventb.core.tool.IStateRepository</tt> (See method <tt>initModule</tt> above).
 
 
 
To retrieve date, we call the method:
 
 
 
</tt>I getState(IStateType<? extends I> stateType) throws CoreException</tt>
 
 
 
In order to use the stored state, it is necessary to define the ‘key‘ in the extension point <tt>stateType</tt>.
 
 
 
==Example==
 
 
 
An example of usage can be seen below:
 
 
 
<extension
 
          point="org.eventb.core.scStateTypes">
 
        <stateType
 
              class="ch.ethz.eventb.decomposition.core.sc.state.IDecompositionAccuracyInfo"
 
              id="decompositionAccuracyInfo"
 
              name="Decomposition Accuracy Info">
 
        </stateType>
 
        <stateType
 
              class="ch.ethz.eventb.decomposition.core.sc.state.IDecompositionLabelSymbolTable"
 
              id="decompositionLabelSymbolTable"
 
              name="Decomposition Label-Symbol Table">
 
        </stateType>
 
        <stateType
 
              class="ch.ethz.eventb.decomposition.core.sc.state.IComponentAccuracyInfo"
 
              id="componentDecompositionInfo"
 
              name="Decomposition Component Machine Information">
 
        </stateType>
 
        <stateType
 
              class="ch.ethz.eventb.decomposition.core.sc.state.IDecompositionStyle"
 
              id="style"
 
              name="Decomposition Style">
 
        </stateType>
 
    </extension>
 
  
For instance, the last <tt>stateType</tt> element defined above is ''Decomposition Style''. It is required to check which kind of ''subComponentElements'' are expected:
+
<extension
 +
        point="org.eclipse.ui.navigator.viewer">
 +
      <viewerContentBinding
 +
            viewerId="fr.systerel.explorer.navigator.view">
 +
        <includes>
 +
            <contentExtension
 +
                  pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.decomposition">
 +
            </contentExtension>
 +
            <contentExtension
 +
                  pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.component">
 +
          </contentExtension>
 +
            <contentExtension
 +
                  pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.configuration">
 +
            </contentExtension>
 +
            <contentExtension
 +
                  pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.subComponent">
 +
            </contentExtension>
 +
            <contentExtension
 +
                  pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.subComponentElement">
 +
            </contentExtension>
 +
        </includes>
 +
      </viewerContentBinding>
 +
      <viewerActionBinding
 +
            viewerId="fr.systerel.explorer.navigator.view">
 +
        <includes>
 +
            <actionExtension
 +
                  pattern="ch.ethz.eventb.decomposition.ui.DecompositionRootActionProvider">
 +
            </actionExtension>
 +
        </includes>
 +
      </viewerActionBinding>
 +
  </extension>
  
* if ''style''= shared event => ''subComponentElement'' expected type is ''variables''.
+
The pattern correspond to the ids in the contentProvider and actionProvider extension-points defined above (see the navigatorContent example section).
* if ''style''= shared variable => ''subComponentElement'' expected type is ''events''.
 
  
 
[[Category:Developer documentation]]
 
[[Category:Developer documentation]]
[[Category:Work in progress]]
+
[[Category:Rodin Platform]]

Revision as of 16:12, 24 May 2010

Introduction

The purpose of this page is to describe how to extend the Event-B project explorer. It covers on the one hand, the definition of the extension, and on the other hand its implementation. The Event-B project explorer is itself an implementation of the extension-point org.eclipse.ui.views. The corresponding view id is fr.systerel.explorer.navigator.view which is defined as a subclass of org.eclipse.ui.navigator.CommonNavigator and it is over this view that we extend the project explorer.

EventB project explorer.png

The useful extension points are listed below; they offer the possibility to contribute to the project explorer:

  • org.eclipse.ui.navigator.navigatorContent
  • org.eclipse.ui.navigator.viewer

Before Starting

It is necessary to define the elements and structure to be represented. We will use as an example the decompositionFile that is defined as follows:

  • decompositionFile
    • decompositionRoot
      • Component with the following attributes: machine (to be decomposed)
      • Configuration with the following attributes: style: shared event/shared variables; newProjectOption: decompose in the same project/different projects; decomposeContextOption: noDecomposition/minimal decomposition)
      • SubComponent (resulting decomposed parts) with the following attributes: label
        • SubComponentElement (elements used to decompose:variables for shared event and events for shared variable) with the following attributes: element name/identifier

Decomp file pretty print.png

Navigator Content

A content extension provides a content and label provider that can be used by a navigator content service (in out case the Event-B project explorer). The navigatorContent extension defines the specific classes for the content provider, label provider, and action provider in addition to the types of elements the extension knows about. To extend the project explorer, it is also required to add the following children of the navigatorContent:

  • triggerPoints: defines the nodes to be used when resolving the Common Navigator content provider's getElements() or getChildren(). This is also used to select the extension for providing labels, images, descriptions and for sorting.
  • possibleChildren: defines the node to be used when resolving the Common Navigator content provider's getParent(). It is also used to help determine the parent when handling drop operations.

Declaration

The navigatorContent extension-point allows tool writers to register their tool implementation under a symbolic name that is then used by the Rodin platform to find and run the tool. The symbolic name is the id of the tool extension. The declaration of this extension is defined as follows:

<!ELEMENT navigatorContent ((enablement | (triggerPoints , possibleChildren)) , actionProvider* , commonSorter* , override? , dropAssistant* , commonWizard*)>
 <!ATTLIST navigatorContent
 id                CDATA #REQUIRED
 name              CDATA #REQUIRED
 priority          (lowest|lower|low|normal|high|higher|highest)
 contentProvider   CDATA #IMPLIED
 icon              CDATA #IMPLIED
 activeByDefault   (true | false)
 providesSaveables (true | false)
 labelProvider     CDATA #IMPLIED
>

A navigator content extension defines a content provider and label provider that can be used to provide children whenever an element matches the triggerPoints expression and also to provide a parent whenever an element matches the possibleChildren expression. Optionally, we may also provide an action provider which can provide menu contributions and action bar contributions when an element is selected that the extension contributed, or that matches the triggerPoints expression. It is possible to contribute with a sorter to sort elements that are contributed by the extension.

  • id - A unique ID to identify this extension. Used for extension activation and by other extensions that would like to extend the defined extension (e.g. add another org.eclipse.ui.navigator.CommonActionProvider)
  • name - Specify a display name for the Content Extension. The display name is used in the activation dialog to allow clients to turn an extension on or off.
  • priority - Indicates the relative priority of this extension to other extensions. Used by the Common Navigator to handle sorting and organization of the contributed content from this extension in relation to content from other extensions. Defaults to "normal"
  • contentProvider - Supplies the name of a class which implements org.eclipse.jface.viewers.ITreeContentProvider or org.eclipse.ui.navigator.ICommonContentProvider. The content provider will be consulted when adding children to the tree. Use the enablement, triggerPoints, or possibleChildren clauses to indicate what kinds of content should trigger a request to your content provider. Elements contributed from the content provider are not guaranteed to appear in the tree in the same order. Clients should take advantage of the sorting extension (commonSorter) to ensure proper ordering of their elements. All elements contributed by this content provider are associated with this navigatorContent extension for the purposes of determining the label provider, action providers, sorters, drop assistants and common wizards.
  • icon - A plugin-relative path to an icon for use when displaying the metadata about the content extension to the user.
  • activeByDefault - Indicates whether the current extension will be active by default. Each content extension may be turned on or off by the user. The active state is differentiated from the visible state. See org.eclipse.ui.navigator.viewer/viewerContentBinding for more information on visibility
  • labelProvider - Supplies the name of a class which implements org.eclipse.jface.viewers.ILabelProvider or for more advanced functionality, the org.eclipse.ui.navigator.ICommonLabelProvider. Clients may also implement org.eclipse.ui.navigator.IDescriptionProvider in order to add text to the status bar at the bottom of the Eclipse workbench based on the selection in the viewer. Since Eclipse 3.4, clients may also implement org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider to provide styled text labels. Note that the empty styled string signals that the label provider does not wish to render the label.

Action Provider

Still inside the navigatorContent, it is possible to add the following:

<!ELEMENT actionProvider (enablement?)>
 <!ATTLIST actionProvider
 class         CDATA #REQUIRED
 id            CDATA #IMPLIED
 dependsOn     CDATA #IMPLIED
 overrides     CDATA #IMPLIED
 priority      (lowest|lower|low|normal|high|higher|highest)
 appearsBefore IDREF #IMPLIED
 >

A top level actionProvider is visible to an abstract viewer if there is a viewerActionBinding for that actionProvider. It is possible to provide actionProvider(s) under the root extension element (peer to other navigatorContent) in order to better control their enablement and viewer binding (see viewerActionBinding). Any items contributed to the toolbar or the view menu should be removed when the actionProviders is disposed. We described the two most used attributes of this element:

  • class - Supplies the name of a class that implements org.eclipse.ui.navigator.CommonActionProvider. The action provider has an opportunity to contribute to the context menu and the retargetable actions defined in the IActionBars for the view that holds the navigator. It is also possible to contribute directly to the view menu through the IActionBars view menu.
  • id - Clients may optionally define an id to use for filtering purposes (either through activities or viewerContentBindings).

To define when to enable this actionProvider, it is necessary to define the enablement:

<!ELEMENT enablement (not , and , or , instanceof , test , systemTest , equals , count , with , resolve , adapt , iterate , reference)*>

The enablement expression allows clients to specify the same expression for both triggerPoints and possibleChildren. In the case of actionProvider, clients must define an expression that will indicate to the framework when their org.eclipse.ui.navigator.CommonActionProvider should be invoked. Because of contributions to the IActionBars, clients must be invoked whenever an object they are interested in is selected. Therefore, clients should use discretion in deciding when their extension should be enabled.

Programmatic usage

In the java side, create 4 packages:

  • *.*.editors.image: Where you have the class that handles the images to be used to display the elements in the project explorer (see for example: /org.eventb.ui/src/org/eventb/ui/IEventBSharedImages.java)
  • *.*.ui.explorer.contentProvider: contains the classes required in the extension point org.eclipse.ui.navigator.navigatorContent.
  • *.*.ui.explorer.actionProvider: contains the classes that handle the actions that can be originated by the added navigatorContent.
  • *.*.ui.explorer.model: The content of the explorer is structured in classes called Models. They all implement the interface fr.systerel.internal.explorer.model.IModelElement. The elements are structured in projects (ModelProjects) where the root file contains elements that can have proof obligations associated (in that case they should extends the abstract class fr.systerel.internal.explorer.model.ModelPOContainer). The elements of a root file are ModelElementNode similar to fr.systerel.internal.explorer.model.ModelElementNode. The models structure would look like this:
 ModelProject
   - ModelRoot1
       - ModelElementNode1
       - ModelElementNode2
       - ...
   - ModelRoot2
        - ModelElementNode3
        - ModelElementNode4
        - ...
        

Moreover, a class called ModelController defined as a singleton controls all the models and contains useful methods. It also implements the interface org.rodinp.core.IElementChangedListener that will be called whenever there is a change in one of the model elements. It will clean up the existing elements in the project explorer and reload with the recent changes. The ModelController instance should be called by implementing the method org.eclipse.jface.viewers.IContentProvider#inputChanged (required for classes that implement interface org.eclipse.jface.viewers.ITreeContentProvider). Usually an abstract class that implements ITreeContentProvider is created: AbstractContentProvider.

public abstract class AbstractContentProvider implements ITreeContentProvider {	
       protected static Object[] NO_OBJECT = new Object[0];
       protected IInternalElementType<?> type;
       public AbstractContentProvider(IInternalElementType<?> type){this.type = type;}
       public Object[] getChildren(Object parentElement) {
               IModelElement model = ModelControllerDecomposition.getModelElement(parentElement);
               if (model != null) {
                     return model.getChildren(type, false);
               }
               return NO_OBJECT;
       }
       public Object getParent(Object element) {
               IModelElement model = ModelControllerDecomposition.getModelElement(element);
               if (model != null) {
                       return model.getParent(true);
               }
               return null;
      }
      public boolean hasChildren(Object element) {
             return getChildren(element).length>0;
      }
      public Object[] getElements(Object inputElement) {
           return getChildren(inputElement);
      }
      public void dispose() {}
      public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
             if (viewer instanceof CommonViewer) {
                   ModelControllerDecomposition.createInstance((CommonViewer)viewer);
             }
      }
}

This class is extended by the respective contentProviders. For instance:

public class DecompositionContentProvider extends AbstractContentProvider{...}

Example

An example of the implementation of this extension-point is defined below:

<extension
        point="org.eclipse.ui.navigator.navigatorContent">
     <navigatorContent
           contentProvider="ch.ethz.eventb.decomposition.ui.explorer.contentProvider.DecompositionContentProvider"
           id="ch.ethz.eventb.decomposition.ui.navigator.explorer.decomposition"
           labelProvider="ch.ethz.eventb.decomposition.ui.explorer.contentProvider.DecompositionLabelProvider"
           name="Decomposition Root"
           priority="highest">
        <triggerPoints>
           <or>
              <instanceof
                    value="org.eclipse.core.resources.IProject">
              </instanceof>
              <instanceof
                    value="ch.ethz.eventb.decomposition.core.IDecompositionRoot">
              </instanceof>
           </or></triggerPoints>
        <possibleChildren>
           <instanceof
                 value="ch.ethz.eventb.decomposition.core.IDecompositionRoot">
           </instanceof>
        </possibleChildren>
     </navigatorContent>
     <navigatorContent
           contentProvider="ch.ethz.eventb.decomposition.ui.explorer.contentProvider.ComponentContentProvider"
           id="ch.ethz.eventb.decomposition.ui.navigator.explorer.component"
           labelProvider="ch.ethz.eventb.decomposition.ui.explorer.contentProvider.DecompositionLabelProvider"
           name="Decomposition Component"
           priority="higher">
        <triggerPoints>
           <or>
              <instanceof
                    value="ch.ethz.eventb.decomposition.core.IDecompositionRoot">
              </instanceof>
              <instanceof
                    value="ch.ethz.eventb.decomposition.core.IComponent">
              </instanceof>
           </or>
        </triggerPoints>
        <possibleChildren>
           <instanceof
                 value="ch.ethz.eventb.decomposition.core.IComponent">
           </instanceof>
        </possibleChildren>
</extension>

Above we defined two navigatorContent elements (DecompositionContentProvider and ComponentContentProvider) using the same class as labelProvider (DecompositionLabelProvider). The first is triggered by instances of IProject and IDecompositionRoot and the possible children of this element are IDecompositionRoot as well.

An actionProvider example is described below:

     <actionProvider
           class="ch.ethz.eventb.decomposition.ui.explorer.actionProvider.DecompositionRootActionProvider"
           id="ch.ethz.eventb.decomposition.ui.DecompositionRootActionProvider">
        <enablement>
           <or>
              <instanceof
                    value="ch.ethz.eventb.decomposition.core.IDecompositionRoot">
              </instanceof>
              <instanceof
                    value="ch.ethz.eventb.decomposition.core.IDecompositionConfiguration">
              </instanceof>
              <instanceof
                    value="ch.ethz.eventb.decomposition.core.ISubComponent">
              </instanceof>
              <instanceof
                    value="ch.ethz.eventb.decomposition.core.ISubComponentElement">
              </instanceof>
              <instanceof
                    value="ch.ethz.eventb.decomposition.core.IComponent">
              </instanceof>
           </or>
        </enablement>
     </actionProvider>

This actionProvider, described by the class ch.ethz.eventb.decomposition.ui.explorer.actionProvider.DecompositionRootActionProvider is enabled by instances of IDecompositionRoot, IDecompositionConfiguration, ISubComponent, ISubComponentElement and IComponent.

Navigator Viewer

The viewer element defines the configuration for a common viewer. The extension may provide a custom popup menu id, override whether the viewer provides link with editor support, provides a filter dialog, and/or provides an "Available customizations" dialog. In addition, nested configuration elements give full control over the structure and behavior of the popup context menu. We define two children of this extension point:

  • viewerContentBinding: to define the visibility of contentProviders.
  • viewerActionBinding: to define the visibility of actionProviders.

Declaration

<!ELEMENT viewerContentBinding (includes? , excludes?)>
 <!ATTLIST viewerContentBinding
 viewerId CDATA #REQUIRED
 >

Clients must define one or more viewerContentBinding elements to describe which content extensions, common filters, and link helpers are visible to the viewer. A content extension or common filter is visible if the id of the content extension or common filter matches an includes statement under a viewerContentBinding and is not excluded by an excludes statement. If a content extension or common filter is not visible to a viewer, then the extension will never be asked for content by a content service for that viewer or be presented to the user in the available filters dialog. Clients may define an includes element to select which extensions are visible to the viewer, and similarly an excludes element for extensions that should not be made visible to the viewer. Clients may further define the extensions that should be explicitly queried for root elements (through ITreeContentProvider.getElements()) by the "isRoot" attribute. If one or more contentExtension elements have "isRoot" set to true within the includes statement, only those extensions will be queried for root elements. The "isRoot" attribute has no effect for exclusions. A viewer may have multiple viewerContentBindings defined, and their includes/excludes statements will be aggregated to produce the final behavior.

  • viewerId - The id of the common viewer. If the viewer is in a common navigator then the id must match the navigator's id defined in its org.eclipse.ui.views extension.
<!ELEMENT viewerActionBinding (includes? , excludes?)>
 <!ATTLIST viewerActionBinding
 viewerId CDATA #REQUIRED
 >

Clients must define which action providers are visible to their viewer. Clients may define an includes element to select which extensions are visible to the viewer, and similarly an excludes element for extensions that should not be made visible to the viewer. A viewer may have multiple viewerActionBindings defined, and their includes/excludes statements will be aggregated to produce the final behavior.

Example

An example of the use of this extension point is defined below:

<extension 
        point="org.eclipse.ui.navigator.viewer">
     <viewerContentBinding 
           viewerId="fr.systerel.explorer.navigator.view">
        <includes>
           <contentExtension 
                 pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.decomposition">
           </contentExtension>
           <contentExtension 
                 pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.component">
         	 </contentExtension>
           <contentExtension 
                 pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.configuration">
           </contentExtension>
           <contentExtension 
                 pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.subComponent">
           </contentExtension>
           <contentExtension
                 pattern="ch.ethz.eventb.decomposition.ui.navigator.explorer.subComponentElement">
           </contentExtension>
        </includes>
     </viewerContentBinding>
     <viewerActionBinding
           viewerId="fr.systerel.explorer.navigator.view">
        <includes>
           <actionExtension
                 pattern="ch.ethz.eventb.decomposition.ui.DecompositionRootActionProvider">
           </actionExtension>
        </includes>
     </viewerActionBinding>
  </extension> 

The pattern correspond to the ids in the contentProvider and actionProvider extension-points defined above (see the navigatorContent example section).