Logo

18.6.3 Accumulator

Accumulator is an implicit type of browser whose only behavior is to accumulate panes.

Every time the #entity port of the parent pane is populated, the Accumulator searches through its panes to find one that corresponds the entity. If none is found, a new pane is created with the #entity populated. Just like in the case of the Finder, the user can specify the presentations that go in each pane.

The main use case behind this type of browser is an editor like the Eclipse main view. For this purpose, it is typically combined with a Tabulator (more details about browser composition can be seen in Section 18.6.4). The snippet below shows an example:

| browser |
browser := GLMTabulator new.
browser column: #list; column: #details span: 2.
browser title: 'Class Viewer'.
browser transmit to: #list; andShow: [ :a |
a list
format: #name;
title: 'Classes' ].
browser transmit to: #details; from: #list; andShowIfNone: [ :a |
| accumulator |
accumulator := GLMAccumulator new.
accumulator show: [ :some |
some title: #name.
some text
display: #formattedSourceText ].
a custom: accumulator ].

The overall browser is a Tabulator with two panes: one showing the list of all classes, and one showing the source code of each selected class in an Accumulator.

The #selection port of the left pane is linked with the #entity port of the right pane. Thus, every time we select a class from the list on the left, the Accumulator will spawn a new tab. A particularity of this example is the use of andShowIfNone: when specifying the transmission. Because the Accumulator is meant to accumulate, and not be replaced with every new transmission, we want the transmission to only install a new presentation when there is none in the target pane.

Running the browser on all classes from the ArgoUML model, spawns a window as shown below.

Accumulator example simulating a viewer for the classes from ArgoUML 0.28.1

The Accumulator also offers two more special ports: #entityToSelect, and #activeEntity.

The #entityToSelect port is meant to be used as an input port, and populating it with a value causes the renderer to try to select a tab that corresponds to the value. The behavior is similar to the one of #entity, the difference being that it will not create a new tab if the tab does not yet exist.

The #activeEntity port is a special one that is populated with the value behind the currently selected tab.

We can use these two ports can be used to completely simulate the Eclipse like behavior:

  • When we strong select (i.e., double click) the class from the left pane, we get a new tab. For this we connect the #strongSelection port the list pane with the #entity port from the details pane.
  • When we simply select the class from the left pane, we try to select the corresponding tab. To achieve this we connect the #selection port from the left pane with the #entityToSelect port from the details pane.
  • Finally, when we select a new tab, we select the corresponding element from the list. To this end, we connect the #activeEntity port from the right pane with the #selection port from the left pane.

The code below shows the complete script:

| browser |
browser := GLMTabulator new.
browser column: #list; column: #details span: 2.
browser title: 'Class Viewer'.
browser transmit to: #list; andShow: [ :a |
a list
format: #name;
title: 'Classes' ].
browser transmit to: #details; from: #list port: #strongSelection; andShowIfNone: [ :a |
| accumulator |
accumulator := GLMAccumulator new.
accumulator show: [ :some |
some title: #name.
some text
display: #formattedSourceText ].
a custom: accumulator ].
browser transmit to: #details port: #entityToSelect; from: #list.
browser transmit to: #list port: #selection; from: #details port: #activeEntity.

Add a Note