Next Previous Up Top Contents Index

5 Adding Callbacks to the Application

5.1 Defining the underlying data structures for tasks

Before defining any real callbacks, it is time to consider how you can represent task lists, and the information contained in them. This is essential, not just for handling tasks within the application, but for saving task lists to disk, and loading them back into the application.

Add the code described in this section to task-list.dylan.

There are two basic kinds of object that you need to model: task lists and tasks. A task list is a collection of one or more tasks. The best way to represent these is by defining a <task-list> class and a <task> class.

The definition of <task-list>, below, contains three slots:

task-list-tasks

This slot specifies a sequence of tasks that are contained in the task list. Each object in the sequence will be an instance of <task>. The default for new task lists is an empty stretchy vector. An init-keyword has been specified so that this slot can be set when an instance of the class is initialized.
task-list-filename

This slot specifies the file on disk to which the task list has been saved, if it has been saved at all. The default for new task lists is #f, since the task list has not yet been saved to disk. An init-keyword has been specified so that this slot can be set when an instance of the class is initialized.
task-list-modified?

The purpose for this slot is less obvious. It is useful to flag whether or not a task list has been modified so that, for instance, the Save command in the application can be disabled if the task list is unmodified. There is no init-keyword defined for this class, because you only ever want to use the supplied default value for new instances of <task-list>.
define class <task-list> (<object>)
  constant slot task-list-tasks = make(<stretchy-vector>),
    init-keyword: tasks:;
  slot task-list-filename :: false-or(<string>) = #f,
    init-keyword: filename:;
  slot task-list-modified? :: <boolean> = #f;
end class <task-list>;

Next, consider the information that needs to be encoded in each individual task. There are two pieces of information that need to be recorded:

Priorities can be recorded using a constant, as shown below:

define constant <priority> = one-of(#"low", #"medium", #"high");

Notice that it is most straightforward to encode each priority as a symbol. Later on, you will see how you can use as to convert each symbol to a format that can be saved to disk and read back into the application as a symbol.

The <task> class can then be defined as having two slots: one for the task text itself, and another for the priority. Both have init-keywords so that they can be specified when a new instance is created, and both init-keywords are required; they must be specified whenever a task is created.

define class <task> (<object>)
  slot task-name :: <string>,
    required-init-keyword: name:;
  slot task-priority :: <priority>,
    required-init-keyword: priority:;
end class <task>;

These three definitions are all that is needed to be able to represent tasks and task lists within the task list application.

In order to handle tasks effectively in the GUI of the task list manager, some changes are necessary to the definition of the task-list pane in the definition of <task-frame>. These changes are needed to ensure that information about tasks is passed to the task-list pane correctly. Make these changes to the existing definition in the file frame.dylan.

In Section 4.3 on page 35, the definition of task-list was given as:

// definition of list
  pane task-list (frame)
    make (<list-box>, items: #(), lines: 15,
          activate-callback: not-yet-implemented);

First, you need to ensure that the items passed to task-list are the tasks in the <task-list> associated with the frame. Recall that a frame-task-list slot was specified in the definition of <task-frame>; this slot is used to hold the instance of <task-list> that is associated with the <task-frame>. The sequence of tasks contained in the associated frame-task-list can then be found using the frame-task-list.task-list-tasks accessor. To display these tasks in the task-list pane, the items: init-keyword needs to be set to the value of this accessor:

items: frame.frame-task-list.task-list-tasks,

Next, you need to ensure that the label for each task in the task-list pane is the text of the task itself. As described above, the text of any task is stored in its task-name slot. In order to display this text as the label for every item in the list box, you need to specify the task-name slot as the gadget-label-key of the list box. A label key is a function that is used to calculate the label of each item in a gadget, and it can be specified using the label-key: init-keyword:

label-key: task-name,

This gives the following new definition for the task-list pane:

// definition of list
  pane task-list (frame)
    make (<list-box>,
          items: frame.frame-task-list.task-list-tasks,
          label-key: task-name,
          lines: 15,
          activate-callback: not-yet-implemented);

There is one final change that still needs to be made to this pane definition. This is described in Section 5.3.3 on page 64.


Building Applications Using DUIM - 26 May 1999

Next Previous Up Top Contents Index