Skip to main content
Jump to: navigation, search

E4/Model Discussion

< E4
Revision as of 12:34, 20 June 2014 by (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Historical Document: The model has graduated to Eclipse4 and continues to evolve there

  • This is a page to collect semi-random thoughts on the E4 model, contexts, and notifications.

This page is intended to capture ideas and keep reminders for E4 developers. The information here is a work-in-progress and might change.

When you add a comment, please add comments in-line with the [my name] tag at the start.

Areas we'd like to work on

E4 Work areas
Area Interested
Contexts Oleg, Paul
Events Oleg
Model Editor Oleg, Eric
UI Model Eric, Paul
Command/Menu Contributions Paul
Toolkit Model + tools
- integration with UI Model and CSS
- 2D graphics
Hallvard Trætteberg
Row 6, Cell 1 Row 6, Cell 2
and so on... and so on...

How things work together

  • [Oleg <- McQ ] Model is static, context keeps state information?

To avoid duplication of information and questions on "which came first, the chicken or the egg?", we should keep the model static and use contexts to record state information.

Example: active part. There was a bug where model would change the active tab in the CTabFolder and send events. Event processing used context to get active part. Context was updated after the CTabFolder change. The fun result: commands were applied not to the currently selected editor, but to the previous editor.

I like Eric's approach: persisted properties go in the model, non-persisted in the context.

[Eric] I'd rephrase that a bit. We have 3 'models' in play:

  • UI Model: This is where all persistent state should go. This model is not static, it contains the layout information which can be modified by the User. It's the one we should save/restore between E4 sessions.
  • Context: This is the model of the application's current state. It is highly dynamic, changing on every part activation... It has no persistent state and should be re-constructed on application startup.
  • CSS: This is a static model providing information that controls the 'look' of the application. While it's generally used to control widget properties such as text color, borders...we've recently been looking into whether it can be enhanced to provide model-specific feedback as well (such as which factory to use to render the model element).

Compatibility Layer Approach

  • [Paul] we currently use a fragment-patch approach to create the compatibility layer.
    • [Paul] We use that to hook into some of the classes that create the 3.x IDE (IDEApplication, Workbench, WorkbenchPlugin)
    • [Paul] We then bridge a number of classes to as much e4 model support as we have implemented (WorkbenchWindow, WorkbenchPage, Perspective, WorkbenchPartSite)
    • [Paul] We create a few legacy->e4 translators, like the LegacyHandlerService
    • [Paul] we turn the system loose :-)
  • [Paul] This approach allowed us to get large parts of the IDE up and running relatively quickly, because if we didn't get to a piece of functionality we tend to pick up the legacy version.
  • [Paul] The con with this approach is we are still pulling in tonnes of 3.x code, just by default. Should we try the other approach, fork.
  • [Paul] e4 is our opportunity to simplify the internals of the workbench and ide. Is it time to change our approach and fork o.e.ui.workbench and o.e.ui.ide? Remove the internals, and only leave API. Make sure that the e4 model supports the information and transitions that we need to provide our behaviour.
  • [Paul] I think this approach would require a systematic plan:
    • [Paul] We start identifying 3.x UI tests that we consider API clean
    • [Paul] We implement enough compatibility so that they run
    • [Paul] We select tests that capture behaviour we like (but have internal references). We create e4 versions of them to encode the behaviour we want.
  • [Paul] This approach would require stepping back from the self-hosting we currently support (I'd guess on the order of 2 milestones). The cost is high. The success would be more of the appropriate usecases supported in e4, and a much cleaner compatibility layer (which we would have a hope of understanding).


  • [anonymous :-)] Do we need different model elements for editors and views? If not, what is the test to satisfy backward compatibility?

[Eric] I'd be all for calling the current 'MPart' a 'View' and having what we currently think of as an 'Editor' be a 'View' with an 'Input'. Since we introduced savable and multi-instance views the only real remaining differences are containment restrictions (Editors and Views go into different stacks) and the extra mechanisms we allow for mapping resources onto editors.

  • [Oleg] MItemPart is unnecessary. Its attributes need to be moved into MPart (the attributes are optional anyway).
  • [Oleg] Perspectives are just Sashes with different styles for the tabs. We should not need a separate model element for MPerspective, rather a tag on the MSashForm
  • [Oleg] Names: "MSashForm" as opposing to MStack, MPart, MMenu, etc. Why not "MSash"?

[Eric] All the names should be revisited, starting with removing the 'M' (I know I drove this change but, hey, I was wrong to trash the naming just to make the coding easier...;-). As far as 'MSash' goes perhaps it'd be better as 'MTiled'. The 'sash' is really an implementation detail, the real difference between an MStack and an MTile is that one only shows a single child at a time while the other shows them all.

  • [Oleg] Separation of models

We have the "basic" "application" model and "advanced" "workbench" model. I think this separation creates confusion rather then solves it. What we need is one model and 2 pictures: a UML diagram in the documentation with only "basic" elements shown and a UML diagram with both "basic" and "advanced" elements shown.

[Eric] I agree...the current separation of the models causes more problems than it solves. I'd also prefer to see a single model with basic and advanced (IDE) components.

  • [Oleg] make UML diagrams for the E4 model and put pictures somewhere in the doc/wiki.

Done: E4modelbeta.png and E4fullmodelbeta.png

Base E4 model
Full E4 model

  • [Oleg] A large number of typecasts used when walking the model. We need to either modify the EMF model or create wrappers / utilities to limit the number of typecasts (which are essentially implicit rules of what can go into the model).
  • [Eric] Question: what happens with persisted XMI models when we change model structure, say between Eclipse 4.0 and 4.1? Will we be able to read "old" models?
  • [Oleg] Does EMF help with model searches? We have number of places (most notably in WorkbenchPage) that repeat similar code pieces: find all parts, or all editors, or all modified parts, etc. Does EMF have a built-in fast way to walk the model?

[Paul] See Lifecycle section as well

  • [Oleg] Menu items should have "isChecked" (Project -> Build Automatically.)
  • [Oleg] We should be able to bring part to top without activating it. Example: editor might need to be brought to top of the editor stack without activating it.


  • [Oleg] The active child and selection

The selection currently follows active child. This is not always correct: For instance, when we click on a tab containing property view, that tab becomes active with null selection. However, the property view is really interested in the object that was selected in the previously active view, such as Project Explorer.

  • [Oleg] Replace output contexts with the concept of "controlled variable"

Done: IEclipseContext.modify() + IEclipseContext.declareModifiable(). There are two remaining uses of IContextConstants.OUTPUTS; they will be cleaned up.

  • [Boris, Oleg] Debugging context events is not for the weak :-). In fact, it is next to impossible. We will probably need:
    • A debug view to explore context information for the MApplicationElement with info grouped in some logical way
    • A view with animation of propagation of changes

[Eric] Agreed, I've been working (very part-time) on one of these for 2 months...Moreover I think that having the tooling to visualize and manipulate all three of our models (UI Mode, Context, CSS) is really important, it's our proof that we know what we have and how it works. Also, the implementation of these views will be a direct reflection of the complexity of the underlying model; if we find it hard to keep these views in synch with ongoing changes it's a sign that we're going in the wrong direction (i.e. the current UI Model Editor is < 1000 lines of java...if it starts to get a bunch of funky if statements and switches it's likely that we're making the actual model overly complex).

  • [Oleg] Null values vs. no values

We'll need to either define an Object NOT_A_VALUE or add a method "isSet()" to differentiate between cases where variable is set to null or not set.

  • Maintaining links when reparenting

Consider model viewer: A tree-like view with model elements that passes its selection to the specialized properties view. Ideally, if that properties view is dragged somewhere else in the E4 model we'd still like to receive selection from that original model viewer. This means that we need to be able to establish "links" that would survive changes of the context tree.

  • [Paul] Well defined lookup functions. ex, for many of the services provided in 3.x, the lookup algorithm that works:
  1. starting with the provided context, walk to the bottom of the active child chain.
  2. look up variables by walking up the parent chain.
  • This isn't quite what we have at the moment, it will walk up the parent chain and then down the application active child chain.

Command and Menu Contributions and other Framework Services

[Paul] In 3.x, this encompasses both commands/handlers/menu and toolbar contributions and the supporting services:

  • [Paul] IServiceLocator/AbstractServiceFactory - The service locator hierarchy mostly matches the part hierarchy.
    • [Paul] It provides each part with an access point to the framework (to help avoid singletons).
    • [Paul] Services can have their behavour scoped to that service locator.
    • [Paul] consumed resources can be cleaned up when that service locator is disposed
    • [Paul] AbstractServiceFactory provides a way to override the lookup algorithm at a specific service locator.
    • [Paul] activating service locators can issue activate/deactivate events to local services that care.
  • [Paul] IEvaluationService - the 3.x mechanism that collects variable change events from contributed source providers. It also holds the collection of declarative and programmatic core expressions and re-evaluates them when necessary. It then fires property change events.
  • [Paul] IContextService - A set of context IDs that are active at any given time. It is heavily used by the keybinding service. The IDs are provided as a source to the evaluation service.
  • [Paul] IBindingService - manages the list of active keybindings. It builds an active context tree, then prunes one branch based on in dialog or in window. It then builds a list of active keybindings taking into account scheme, context, locale, and platform.
  • [Paul] IWorkbenchLocationService - supposed to allow a part to find a useful piece of the model. Not published API yet.
  • [Paul] IHandlerService - calculates active handlers based on expressions and priorities, then sets them in the Commands. Can also create execution events with the correct information.
  • [Paul] IMenuService - service for filling contributions into ContributionManager (includes menus and toolbars). It uses the IEvaluationService to determine visibility, and controls the logic of when to refresh a ContributionManager.
  • [Paul] ISelectionService - this is the workbench window level service that mediates one active selection per window. It also has methods to add selection listeners per part-id, but that API has problems (editors, and multi-instance views).

Life Cycle

  • [Eric] One of the areas that really needs immediate attention is defining the life cycle of the application and, as a subset, the life cycle of the parts within it. Not having really clear states is leading to the code being somewhat arbitrarily located; we just put it 'where it works' as opposed to identifying what the code is doing and then placing it into some well-defined slot for that type of code.

[Paul] differing states that came up w.r.t. part lifecycle (workbench parts and perspectives)

  • A part can be visible or not
  • A part can be restored or not (rendered)
  • A part can be open or not (an open part has a tab, even if it hasn't been restored or is not visible)
  • an an attribute of the application: A part can be active, both for the entire application (active part) or for a give subsection (active editor)

[Paul] It seems a part placeholder would be an MCP that's not visible or restored or open. For stacks, just a comment that we've had requests for both behaviours (empty stacks disappear and empty stacks sit there, empty).

For example here's a possible state diagram for an application:

  • Starting: the application is initializing
    • App Init: define the App's Context and populate any 'core' services, variables...
    • Workspace init: Open a Workspace to use or create a new one
    • CSS Init: Locate a CSS definition (if any) and set up the engine.
    • Model Init: Populate the initial UI Model instance. This may be some combination of loading a saved model plus changes needed to handle extensions...
  • Running: The UI (if any) is up and the application is usable
    • Nornal: What we usually see
    • Dialog/Wizard: A dialog/wizard is up. We need to remap keybindings...
  • Shutting Down: The application is on the way down; note that we wouldn't enter this state until we're sure we're actually shutting down, all queries (save editors...) that could lead to a cancel of the close have already been processed...

If we allow clients to place code between the states (i.e. 'Pre Workspace Init' or 'Post Model Init'...) then they have logical slots for most tweaks, additions...

I think it'd be a good idea to actually have the code reflect that this is a state machine, allowing for the addition of new states and or replacement of the default implementation of a particular state.

Notifications / Events

Please see the E4/Event Processing for the current state of development.

  • [Oleg] Whiteboard pattern / event bus
  • [Eric] I'm quite interested in this but I'm not sure whether the two ideas are the same. Could you and Tom post a thumbnail explanation of them? Whatever strategy we come up with it should be the only one we use; if it's a 'global' listener (ContentAdapter) then we should use just the one for all model eventing.

[Oleg] Update: All of those are really what's described by the "publish/subscribe" models. There are tons of them with different degrees of sophistication, from relatively simple OSGi's Event Admin to Java's Java Message Service to full enterprise implementations of "Advanced Message Queuing Protocol". Personally, I think that we need to stick with the most trivial (and performant) approach we can find: it just has to be good enough for Eclipse needs.

  • [Eric] We should also see what events we should add into E4 and then use those events to implement the events in the compatibility layer using a translate and forward mechanism.

Related Defects

The following are defects that contain at least some discussion about architectural issues or suggestions on future direction:

  • 278631 Extensions and E4
  • 279681 E4 model: define events and lifecycles
  • 260408 {CSS} SWT requirements for CSS
  • 282901 {UI} Need better support for switching renderer to use
  • 248439 {E4} UI Model feedback
  • 264204 {Model} remove uses of 'Policy' to control orientation
  • 265171 Support different Stack types within the UI
  • 279263 {Compatibility} Consider addition of legacy view / editor containers
  • 280076 Make model loading plugable
  • 283040 Cleanup e4 terminology and API
  • 263820 {UI} Handlers seems to resolve their URIs early
  • 277947 Lets rename Eclipse RCP
  • 280962 New workbench part is instantiated everytime setVisible(true) is called on an MContributedPart

Back to the top