15.3Rendering and Brushes
We define the method model
to access the singleton of ToDoList
as follows.
ToDoListView>>model
^ ToDoList default
A word about design. Note that directly accessing a singleton instead of using an instance variable is definitively not a good design since it favors procedural-like global access over encapsulation and distribution of knowledge. Here we use it because we want to produce a running application quickly. The singleton design pattern looks trivial but it is often misunderstood: it should be used when you want to ensure that there is never more than one instance; it does not limit access to one instance at a time. In general, if you can avoid a singleton by adding an instance variable to an object, then you do not need the singleton.
The method renderContentOn:
is called by Seaside to render a component. We will now begin to implement this method. First we just display the title of our todo list by defining the method as follows:
ToDoListView>>renderContentOn: html
html text: self model title
If you refresh your browser you should obtain Figure 100.
Now we will make some changes that will help us render the list and its elements. We will define a CSS style so we redefine the method renderContentOn:
to use the brush heading
.
ToDoListView>>renderContentOn: html
html heading: self model title
Refresh your browser to see that you did not change much, except that you will get a bigger title. To render a list of items we define a method renderItemsOn:
that we will invoke from renderContentOn:
. To render an individual item we define a method called renderItem:on:
.
ToDoListView>>renderContentOn: html
html heading: self model title.
html unorderedList: [ self renderItemsOn: html ]
ToDoListView>>renderItemsOn: html
self model items
do: [ :each | self renderItem: each on: html ]
ToDoListView>>renderItem: anItem on: html
html listItem
class: 'done' if: anItem isDone;
class: 'overdue' if: anItem isOverdue;
with: anItem title
As you see, we are rendering the todo items as an unordered list. We also conditionally assign CSS classes to each list item, depending on its state. To do this, we will use the handy method class:if:
since it allows us to write the condition and the class name in the cascade of the brush. Each item will get a class that indicates whether it is completed or overdue. The CSS will cause each item to be displayed with a color determined by its class. Because we haven’t defined any CSS yet, if you refresh your browser now, you will see the plain list.
Next, we edit the style of this component either by clicking on the halos and the pencil and editing the style directly, or by defining the method style
on the class ToDoListView
in your code browser. Check Chapter 8 to learn more about the use of style-sheets and CSS classes.
ToDoListView>>style
^ 'body {
color: #222;
font-size: 75%;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
h1 {
color: #111;
font-size: 2em;
font-weight: normal;
margin-bottom: 0.5em;
}
ul {
list-style: none;
padding-left: 0;
margin-bottom: 1em;
}
li.overdue {
color: #8a1f11;
}
li.done {
color: #264409;
}'
Refresh your browser and you should see the list of items and the todo list title as shown in Figure 101.