18.1 A glimpse of Glamour
How exactly does Glamour help us build dedicated browsers? The rest of this section tries to answer this question via a hands-on example.
First, let us observe in more details the essence of a browser. As a case study, let us take a classic code browser like the one from the figure below.
We get four panes: three at the top and one below. The top-left pane holds the namespaces (or packages) from the system presented as a list or as a tree. Once a package is selected, its classes are shown as a list on the top-center pane. In the same way, the methods of a selected class are shown on the top-right pane. The pane at the bottom shows the source code of a selected method. The essence of the browser is shown schematically below.
We get five main concepts. A browser (1) is made of panes (2) which represent spatial locations on which various objects (3) are presented (4). Furthermore, the result of acting on the graphical presentation (4) is transmitted (5) to other panes.
It is actually quite simple. Let’s see how we can express this browser using Glamour. If you are not fluent in Smalltalk, reading the code aloud as regular text will help. The example is based on using a FAMIX code model (see more details about FAMIX in Chapter 11). To try this example, just open a workspace, enter the full code and execute it.
We first create the browser:
| browser |
browser := GLMTabulator new.
The browser is composed by four panes which we will call: #namespaces
, #classes
, #methods
and #details
. These panes are arranged in two rows, where the top one is further composed by three columns:
browser
row: [ :r | r column: #namespaces; column: #classes; column: #methods ];
row: #details.
Given an input Moose model, we want to show the namespaces objects from the model on the #namespaces
pane. These namespaces are presented as a tree. We start from the root namespaces, and then we show all children. The frame of the specification is given by Glamour (e.g., showOn:
or tree
), while for the actual details of programatically navigating the code we use methods offered by the data model (e.g., allNamespaces
, isRoot
or childScopes
).
browser transmit to: #namespaces; andShow: [ :a |
a tree
display: [ :model | model allNamespaces select: [ :each | each isRoot ] ];
children: [ :namespace | namespace childScopes ];
format: [ :namespace | namespace stubFormattedName ] ].
Once we select a namespace, we want to transmit to the #classes
pane that it should display a list with all the classes from the namespace:
browser transmit from: #namespaces; to: #classes; andShow: [ :a |
a list
display: [ :namespace | namespace classes ];
format: [ :class | class stubFormattedName ] ].
In a similar way, we want to show the methods of a class:
browser transmit from: #classes; to: #methods; andShow: [ :a |
a list
display: [ :class | class methods ];
format: [ :method | method stubFormattedName ] ].
We want the source code for a selected method to be shown in the #details
pane:
browser transmit from: #methods; to: #details; andShow: [ :a |
a text
display: [ :method | method sourceText ] ].
Finally, we start the browser by providing a MooseModel:
browser openOn: MooseModel root allModels anyOne.
That’s it. The result of running the above code is seen below.