When creating a Model-View-Presenter triad, you will have decided whether the component can be built from a collaboration of other components or whether it is elemental in nature. This pattern discusses how to create an elemental or Basic component once the underlying domain model class has been designed.
Diagrammatic representation of a basic component triad
You will already have created a model class. We assume here that there is no existing presenter and view combination suitable for providing the user interface for this model. We also assume that you cannot, or do not, want to create a composite component to handle the model.
Since there is no existing presenter class to handle your model's user interface you must create one.
You will use the New Class pattern to create a new presenter class. First of all, you must decide where this is to be subclassed from. All presenters inherit from Presenter in the class hierarchy. Follow these rules to decide on a suitable superclass.
#defaultModel -- Once you have created a presenter class you should add a #defaultModel class method to answer an object to use as the default model when an instance of this presenter component is created. This is normally a suitably initialized instance of your model class although, if you have created a ValuePresenter subclass you should wrap this in a ValueHolder by sending #asValue to the model object.
#defaultView -- A presenter must also support a #defaultView class method to answer the name of a resource that will yield a default view to be used when a instance of the presenter is created. You may choose to delay writing this method until after you have created a suitable view class and registered a named instance with the Resource Manager.
Obviously, you must add additional methods to the presenter class to perform manipulations of the model as required by the user. It's probably make sense to add these methods later once you have had a first pass at designing a view class and testing the entire MVP triad together.
It may well be that an existing view class can be attached to your newly created presenter. However, it is more likely that you will have to create a new view class to support the display of the model's data in an appropriate format and to pass user gestures to the presenter. Once again, you'll use New Class and follow these rules to determine a suitable parent class:
A view is primarily responsible for displaying its model's data and registering with the model to receive change notifications so that appropriate portions of the display can be re-drawn when model is updated.
#onPaintRequired: -- override this method for all views that do not descend from ControlView. This should access the model data and render it to a Canvas onto the view's window as required. Note that, ControlViews, since they are Windows controls, are already expected to provide their own internal painting code so it is not usually appropriate to override this yourself.
#model: -- override this method to register with any required change notifications of the supplied model. Check through the superclass chain for your view to see what notifications are already intercepted by default.
A presenter can only connect to a view instance that has been created and a registered with the Resource Manager. Once you have created a view class you must install an instance of it as a resource. You do this by sending #makeResource:inClass: to the view class. In general, you will install a resource into the class of presenter that is likely to use it. A typical use of this method might be:
ScribbleView makeResource: 'Basic scribble view' inClass: Scribble
The name given to the resource here is that which must be answered by the presenter's #defaultView class method. Now is the time to update this if you have not already done so.
Once you have installed the view into the Resource Manager you may edit it in the View Composer (to set its default attributes such as size, font etc.) simply by double-clicking on its entry in the Resource Browser.
Example A: A drawing/scribble component has a mutable model since the contents of the drawing can be changed by adding or removing primitive operations. Therefore it should be descended from Presenter rather than ValuePresenter. In fact, you may well have chosen to make the model a ListModel in which case the Scribble presenter class should be beneath ListPresenter. In this case the inherited ListModel>>defaultModel method is probably entirely suitable. You should create ScribbleView as a subclass of View and override #onPaintRequired: to draw the representation of the model in the view's window. Since the drawing can be updated by adding or removing primitives from the ListModel then the view should register with the list's #item:addedAtIndex: and #itemRemovedAtIndex: notifications to redraw the appropriate portions of the window. A minimum implementation might be for the view to cause a complete repaint by sending itself an #invalidate message.
Example B: A text editing component using a String as a basic model could in truth be mutable. However, bearing in mind that descending from ValuePresenter and wrapping the String as a ValueModel is more flexible, this latter strategy is to be preferred. Hence, TextPresenter appears as a subclass of ValuePresenter and has as its default model:
^String new asValue
The TextEdit view class uses the standard Windows 'EDIT' control. It is descended from ValueConvertingControlView since it is also associated with a ValueModel. Because this is a Windows control there is no need to provide a specific #onPaintRequired: handler.
There are many classes in the standard development image for basic MVP components. These are used by the development tools and to provide a starter set of components for your own applications. Typical examples are: ListPresenter, ClassListPresenter, TextPresenter, DatePresenter etc.