I recently implemented a generic builder for dynamic spec presenters.
It is now integrated in latest Pharo 7.0 images. So to try the code provided in this article, make sure to download a recent image.
The builder takes:
- A collection of objects;
- The presenter class to use and a BlockClosure describing how to configure an instance of this presenter class; and
- A layout describing how to organise presenters generated.
From these inputs, it builds an instance of DynamicComposablePresenter holding one instance of the presenter class per object in the input collection.
Here is a simple example of checkboxes informing the user of their state when clicked:
builder := DynamicPresentersListBuilder new
modelObjects: (1 to: 19);
configuredAs: [ :presenter :modelObject |
label: modelObject asString;
UIManager default inform: modelObject asString , ' activated.' ];
UIManager default inform: modelObject asString , ' deactivated.' ] ];
layoutBuilder: (DynamicTopToBottomColumnsLayout columns: 5);
dynamicPresenter := builder build.dynamicPresenter
title: 'Checkboxes informing their states';
The cool thing with this builder is: contrarily to common Spec usage which is quite static, you can generate an arbitrary number of presenters depending on a collection of objects of your choice easily.
A slightly more elaborated example implementing a memory game is available in SpecDemoDynamicMemoryGamePresenter class. You can open it by evaluating:
SpecDemoDynamicMemoryGamePresenter new openWithSpec
or by browsing SpecDemos. This presenters allows you to modify the number of cards to use in the memory game dynamically (using the slider).
Buttons are used to represent cards in the UI. When the slider value changes, the builder is used to re-generate a DynamicComposablePresenter with the new number of buttons specified by the slider.
To use the builder in your ComposablePresenters, use ComposablePresenter>>newDynamicPresentersListIn:usingBuilder:. The first argument is a symbol which is the accessor for the DynamicPresenter instance previously set. The mutator for this DynamicPresenter instance should be the accessor with “:” as suffix (e.g., #myDynamicPresenter -> #myDynamicPresenter:). The second argument is the builder instance.
See SpecDemoDynamicMemoryGamePresenter>>#rebuildDynamicPresenter for a concrete example of newDynamicPresentersListIn:usingBuilder: method usage.