To communicate with the Walk user interface, we need to define another data model. This view model is designed to communicate information in a way that the declarative API understands. We will create a type named EmailClientModel, which will handle translating data from our client code to our user interface definition. Create a new file, model.go, where you can start to define these models. The first section of the code allows an email server to be set causing the email list to update accordingly.
For brevity, the trivial methods for walk.TreeModel have been left out—you can find them in the full code listing for this book:
type EmailClientModel struct {
Server *client.EmailServer
root walk.TreeItem
itemsResetPublisher walk.TreeItemEventPublisher
itemChangedPublisher walk.TreeItemEventPublisher
}
// TreeModel methods omitted - see full code listing
func (e *EmailClientModel) SetServer(s *client.EmailServer) {
e.Server = s
e.root = NewInboxList(s.ListMessages())
e.itemsResetPublisher.Publish(e.root)
}
func NewEmailClientModel() *EmailClientModel{
return &EmailClientModel{}
}
The email list for this model needs to represent our email list as items in a tree, rather than a simple list as returned by the client code. To support this we need another type, EmailModel, that implements the walk.TreeItem interface. Here, again, we have omitted the trivial details—each email item will never contain child elements and so we can ignore this complexity:
type EmailModel struct {
email *client.EmailMessage
parent walk.TreeItem
}
// TreeItem functions omitted - see full code listing
We want to group our emails under an Inbox heading, so we need to build the root node and then populate the email list within it. For this, we define one more type, InboxList, which also implements walk.TreeItem, but this time it will allow access to the child list (emails) it holds. We will also need to write a method for building the inbox list from a list of messages (which we would be provided by the client code). See how the final method in this code snippet creates instances of EmailModel for each message and adds them to the inbox list:
type InboxList struct {
emails []walk.TreeItem
}
func (i *InboxList) Text() string {
return "Inbox"
}
func NewInboxList(l []*client.EmailMessage) *InboxList {
list := &InboxList{}
for _, item := range l {
list.emails = append(list.emails, &EmailModel{item, list})
}
return list
}