Class AbstractTreePart<C extends org.eclipse.emf.ecore.EObject,E extends TreeElement<C>>

java.lang.Object
com.amalgamasimulation.desktop.appelements.tree.AbstractTreePart<C,E>
Type Parameters:
C - container type
E - tree element type

public abstract class AbstractTreePart<C extends org.eclipse.emf.ecore.EObject,E extends TreeElement<C>> extends Object
Base part for a tree of a model container. The container is the model object the tree is built from, and every TreeElement keeps it. The part builds the tree from the current container, updates it when the container or its fields change, and sends the selection to other parts through PlatformTopics.

How to use

Extend the class and register the subclass as a part in Application.e4xmi. e4 creates the part, injects the fields and calls postConstruct(Composite). The subclass implements three methods: Everything else is optional: names with counts in initializeTreeElementTypesToNamesMap(Map), the container fields that update the tree in initializeDependentContainerListFields(List) and initializeDependentContainerValueFields(List), toolbar buttons in createToolbar(Composite), the context menu in createMenuItems(Menu, TreeElement).

Tree elements

Use TreeElement as it is, without a subclass. A group is an element without an object (new TreeElement<>(type, container)), a model object is an element with one (new TreeElement<>(type, container, object)).

Updates

The tree is rebuilt when a new container is loaded (PlatformTopics.NEW_SCENARIO, onNewContainer()). It is also refreshed when a dependent field of the container changes. The subclass lists these fields: list features in initializeDependentContainerListFields(List), single-value features in initializeDependentContainerValueFields(List); the part observes them on the current container. After other changes of the model, call refresh(). treeViewer.refresh() only repaints the labels and keeps the old children.

Selection

When the user selects an element, onSelectionChanged(TreeElement) sends events about it. The part selects an element itself when another part sends PlatformTopics.PROPERTY_SELECTION_CHANGED with an object or a type (onExternalSelection(Object)), or PlatformTopics.CHANGE_SELECTED_TREE_ELEMENT with a type. Such a selection does not call onSelectionChanged(TreeElement) and does not send events. Only one element can be selected.

Services and subscriptions

The protected fields with @Inject are set before postConstruct(Composite); a subclass uses them and does not declare its own fields for the same services. RedrawRestrictionManager has no @Optional: the application registers it as a service in its Activator, otherwise e4 cannot create the part. Subscribe with subscribe(String, Consumer): the part removes such subscriptions, the observers of the container fields and its listener of redrawRestrictionManager when the tree is disposed.
  • Field Details

    • eventBroker

      @Inject protected org.eclipse.e4.core.services.events.IEventBroker eventBroker
    • messageManager

      @Inject protected com.amalgamasimulation.desktop.utils.MessageManager messageManager
    • modelService

      @Inject protected org.eclipse.e4.ui.workbench.modeling.EModelService modelService
    • application

      @Inject protected org.eclipse.e4.ui.model.application.MApplication application
    • partService

      @Inject protected org.eclipse.e4.ui.workbench.modeling.EPartService partService
    • handlerService

      @Inject protected org.eclipse.e4.core.commands.EHandlerService handlerService
    • commandService

      @Inject protected org.eclipse.e4.core.commands.ECommandService commandService
    • redrawRestrictionManager

      @Inject protected RedrawRestrictionManager redrawRestrictionManager
    • currentContainerObservable

      protected org.eclipse.core.databinding.observable.value.IObservableValue<C extends org.eclipse.emf.ecore.EObject> currentContainerObservable
    • treeViewer

      protected Tree<E extends TreeElement<C>> treeViewer
    • toolbar

      protected org.eclipse.swt.widgets.ToolBar toolbar
  • Constructor Details

    • AbstractTreePart

      public AbstractTreePart()
  • Method Details

    • getContainer

      protected abstract C getContainer()
      Returns the current container. The part calls it once when it is created and then on each PlatformTopics.NEW_SCENARIO event. The event data is not used, so the container must already be in the application data when the event is sent.
      Returns:
      the current container, or null when none is open; the tree is empty then
    • createRootTreeElement

      protected abstract E createRootTreeElement(C container)
      Creates the root element for a new container. The root is the only element of the first level.
      Parameters:
      container - the container from getContainer(), not null; the method is not called when there is no container
      Returns:
      the root element, not null
    • getChildren

      protected abstract List<E> getChildren(E treeElement)
      Returns the children of an element in the order they are shown. The tree calls it for every element of the tree, collapsed ones included, when a container is loaded and on each refresh(). Between these calls the tree keeps the children it got last time.

      The method may create new elements on each call: equal elements keep their expanded and selected state. An element must not be equal to an element under another parent.

      Parameters:
      treeElement - the element whose children are needed, not null
      Returns:
      the children, an empty list for a leaf; not null
    • postConstruct

      @PostConstruct public void postConstruct(org.eclipse.swt.widgets.Composite parent)
    • createToolbar

      protected void createToolbar(org.eclipse.swt.widgets.Composite parent)
      Creates toolbar with two buttons: "Expand all" calls expandAll(), "Collapse all" calls collapseAll().
      Parameters:
      parent - the composite above the tree
    • createContents

      protected void createContents(org.eclipse.swt.widgets.Composite parent)
    • initializeTreeElementTypesToNamesMap

      protected void initializeTreeElementTypesToNamesMap(Map<AbstractTreeElementType,Function<E,String>> map)
      Fills the names of elements by type. Called once when the part is created. An element whose type is not in the map shows AbstractTreeElementType.getName().

      Each function gets the element and runs every time the tree updates its label, so the name follows the model after refresh(). For a group with a count, use withCount(Function).

      Parameters:
      map - an empty map to fill
    • withCount

      protected Function<E,String> withCount(Function<E,Collection<?>> collection)
      Returns a name in the form "Type name (N)", where N is the size of the collection the function returns for the element.
      Parameters:
      collection - returns the objects to count for the element; not null and must not return null
      Returns:
      a name function for initializeTreeElementTypesToNamesMap(Map)
    • getTreeElementName

      protected String getTreeElementName(E treeElement)
      Returns the text of an element: the function from initializeTreeElementTypesToNamesMap(Map) for its type, otherwise the type name.
      Parameters:
      treeElement - the element, not null
      Returns:
      the text of the element
    • getTreeElementIcon

      protected org.eclipse.swt.graphics.Image getTreeElementIcon(E treeElement)
      Returns the icon of an element: the image at AbstractTreeElementType.getIconPath() of its type. PlatformImages looks for the file first in the bundle of the subclass, then in the bundles it has already loaded images from.
      Parameters:
      treeElement - the element, not null
      Returns:
      the icon of the element
    • getTreeElementFont

      protected org.eclipse.swt.graphics.Font getTreeElementFont(E treeElement)
      Returns the font of an element, for example bold for the active element. Returns null by default, which means the tree font.
      Parameters:
      treeElement - the element, not null
      Returns:
      the font, or null for the tree font
    • getTreeElementColor

      protected org.eclipse.swt.graphics.Color getTreeElementColor(E treeElement)
      Returns the text color of an element, for example grey for an object that is turned off. Returns null by default, which means the tree color.
      Parameters:
      treeElement - the element, not null
      Returns:
      the text color, or null for the tree color
    • initializeDependentContainerListFields

      protected void initializeDependentContainerListFields(List<org.eclipse.emf.ecore.EStructuralFeature> list)
      Fills the list features of the container whose change refreshes the tree.

      The features belong to the container class itself. The part observes them on the current container. Adding, removing or moving an object in the list calls refresh(); a change inside an object of the list does not.

      Parameters:
      list - an empty list to fill
    • initializeDependentContainerValueFields

      protected void initializeDependentContainerValueFields(List<org.eclipse.emf.ecore.EStructuralFeature> list)
      Fills the single-value features of the container whose change refreshes the tree.

      The features belong to the container class itself. The part observes them on the current container; a new value calls refresh().

      Parameters:
      list - an empty list to fill
    • refresh

      public final void refresh()
      Asks getChildren(TreeElement) for the children of every element again and updates the names, icons, fonts and colors. Expanded and selected elements stay as they were if equal elements are still in the tree.

      Call this method after a change of the model that the dependent fields do not cover. treeViewer.refresh() is not enough: it repaints the labels but keeps the old children.

    • setRedrawRestricted

      public final void setRedrawRestricted(boolean redrawRestricted)
      Turns the redraw restriction on or off. While it is on, refresh() only remembers the request; when it is turned off, one refresh runs if there was a request.

      The part already listens to redrawRestrictionManager. An application with its own source of the restriction subscribes this method to it.

      Parameters:
      redrawRestricted - true to restrict redrawing, false to allow it
    • onNewContainer

      protected void onNewContainer()
      Shows the current container. Takes it from getContainer(), creates the root with createRootTreeElement(EObject) (no root for null, the tree is empty), switches the observers of the dependent fields to the container, rebuilds the tree and collapses it with collapseAll().

      Called on each PlatformTopics.NEW_SCENARIO event and once when the part is created.

    • onSelectionChanged

      protected void onSelectionChanged(E treeElement)
      Called when the user selects an element. By default sends with eventBroker.send: Not called when the selection is cleared and when the part selects an element itself.
      Parameters:
      treeElement - the selected element, not null
    • getPropertySelection

      protected Object getPropertySelection(E treeElement)
      Returns the object sent in PlatformTopics.PROPERTY_SELECTION_CHANGED for a selected element: the container for the root, TreeElement.getObject() for the other elements. For a group it is null, and the event is not sent.
      Parameters:
      treeElement - the selected element, not null
      Returns:
      the object to send, or null to send nothing
    • onExternalSelection

      protected void onExternalSelection(Object eventData)
      Selects the element for an object selected in another part. Called on each PlatformTopics.PROPERTY_SELECTION_CHANGED event, including the ones this part sends. For a type, the method selects the first element of this type; for another object, the first element whose TreeElement.getObject() equals it.
      Parameters:
      eventData - the event data; null is ignored
    • selectTreeElement

      protected final boolean selectTreeElement(Predicate<E> predicate)
    • onDoubleClick

      protected void onDoubleClick(E treeElement)
      Called when the user double-clicks an element. Does nothing by default.
      Parameters:
      treeElement - the element, not null
    • createMenuItems

      protected void createMenuItems(org.eclipse.swt.widgets.Menu menu, E treeElement)
      Adds items to the context menu of an element. Called each time the user opens the menu over an element. Does nothing by default.
      Parameters:
      menu - the menu to fill
      treeElement - the element under the mouse, not null
    • expandAll

      protected void expandAll()
      Expands all elements. Called by the "Expand all" button.
    • collapseAll

      protected void collapseAll()
      Collapses the tree so that only the root and its children are visible. Called by the "Collapse all" button and after each new container.
    • subscribe

      protected final <T> void subscribe(String topic, Consumer<T> handler)
      Subscribes a handler to a topic through messageManager and unsubscribes it when the tree is disposed. The handler gets the event data cast to T.
      Type Parameters:
      T - type of the event data
      Parameters:
      topic - the topic
      handler - the handler of the event data