<CHAPTER ID="chapter.example">
  <TITLE>Tutorial Example : a simple word processing application</TITLE>
<p>
The example given in this chapter describes how a gui is built using QTk module. The creation of the widgets, their geometry inside the window and their interaction with Mozart are described.

<figure id="figure.picture3">
<caption>Notepad application</caption>
<picture.extern to="picture3.gif" type=gif>

<section> <TITLE>Geometry management</TITLE>

<P>
The example application will consist of a window composed by

<LIST>
<ITEM> A toolbar with the following buttons : Save, Load and Quit.
<ITEM> A main area where the user can type the text.
</LIST>

The construction of a window is completely described by a record. This record defines the widgets that compose the window, how these widgets must be placed and what is their behaviour is they must be resized. The label of the record defines the widget that must be placed. The content of the record defines the parameters of the widget. Some widgets act as containers for other widgets. The two main containers are :

<LIST>
<ITEM> <<td>> : all widgets contained in this one are placed top to down
<ITEM> <<lr>> : all widgets contained in this one are placed left to right
</LIST>

The toolbar wil be composed of <<button>> widgets. The <<text>> parameter defines the text of the button. 

<figure id="figure.picture1">
<picture.extern to="picture1.gif" type=gif>

The toolbar is described by :
<CODE DISPLAY>Toolbar=lr(button(text:"Save")
           button(text:"Load")
           button(text:"Quit"))</CODE>

which literally means : place these three buttons respectively from left to right, each button taking the size it needs to display itself.

Combining with the text widget, we obtain :
<CODE DISPLAY>Description=td(Toolbar
               text)</CODE>
which literally means : place the toolbar and the text respectively from top to bottom, each widget taking the size it needs to display itself.
</P>
<P>
Now we can build a window from this description by the command :
<CODE DISPLAY>Window={QTk.build Description}</CODE>
This window is hidden by default, so you have to show it to make it visible :
<CODE DISPLAY>{Window show}</CODE>
If you resize the window, the widgets don't resize in a very clever way inside the window.

<figure id="figure.picture2">
<picture.extern to="picture2.gif" type=gif>


One expects the toolbar to stick itself to the top left of the window, and the text widget to take all remaining available size below. All widgets have a glue parameter that allow to specify contraints to the geometry manager. Valid values for the glue parameters are atoms that are combinations of <<n>>, <<s>>, <<w>> and <<e>>. By default a widget takes as much place as it needs to draw itself, and if the area in which it is drawed is bigger than that size, the widget is centered inside. By specifying <<n>> (resp <<s>>, <<w>>, <<e>>) you enforce the north (resp south, west and east) border of the widget to glue to its top (resp down, left, right) neighboor. If you specify both <<ns>> (resp <<we>>) you enforce both opposite border to stick to their respective neighboor, resulting in the widget taking all the vertical (resp horizontal) space available.
</P>
<P>
Using the glue parameter we define :
<CODE DISPLAY>Toolbar=lr(glue:we                     % the toolbar glues itself to the top left of the window
           button(text:"Save" glue:w)  % the button glues itself to the left of the lr widget
           button(text:"Load" glue:w)  % idem
           button(text:"Quit" glue:w)) % idem</CODE>
and also
<CODE DISPLAY>Description=td(Toolbar
               text(glue:nswe))</CODE>
Note that the very first <<td>> or <<lr>> widget is always implicitely <<glue:nswe>>.
Rebuilding and showing the window, we obtain an application that has a complete graphical user interface, except that it is an empty shell.
</P>

<section> <TITLE>Interaction with the user</TITLE>

<P>
An action can be associated to buttons. It is executed when the user clicks the button :
<CODE DISPLAY>button(text:"Quit" glue:w action:proc{$} {Application.exit 0})}</CODE>
This definition makes the oz application terminate when the user clicks the Quit button. Another parameter for closes the window :
<CODE DISPLAY>button(text:"Quit" glue:w action:toplevel#close)</CODE>
Let's make procedures for the Save and Load buttons. The new definitions for these buttons are thus :
<CODE DISPLAY>button(text:"Save" glue:w action:SaveText)
button(text:"Load" glue:w action:LoadText)</CODE>
The <<LoadText>> and <<SaveText>> procedures will do these things :

<LIST>
<ITEM> Ask a filename. Standard dialog boxes are provided in QTk : <<{QTk.dialogbox load(...)}>> and <<{QTk.dialogbox save(...)}>>
<ITEM> Get the contents of the text widget and save it to the file or get the contents of the file and change the contents of the text widget accordingly.
</LIST>

We need a way to dynamically change or get its state, i.e. interact with the widget. This can be done with an handle :
<CODE DISPLAY>TextHandle
Description=td(Toolbar
               text(glue:nswe handle:TextHandle))</CODE>
After the window is built, the unbound variable TextHandle is bound to an object that controls the text widget. The current text can be obtained by :
<CODE DISPLAY>{TextHandle get($)}</CODE>
and set by :
<CODE DISPLAY>{TextHandle set($)}</CODE>
We can now give the <<SaveText>> and <<LoadText>> procedures :
<CODE DISPLAY>proc{SaveText}
  Name={QTk.dialogbox save($)}
in
  try
    File={New Open.file init(name:Name flags:[write create])}
    Contents={TextHandle get($)}
  in
    {File write(vs:Contents)}
    {File close}
  catch _ then skip end
end

proc{LoadText}
  Name={QTk.dialogbox load($)}
  Contents={TextHandle get($)}
in
  try
    File={New Open.file init(name:Name)}
    Contents={File read(list:$ size:all)}
  in
    {TextHandle set(Contents)}
    {File close}
  catch _ then skip end
end</CODE>
And the application is now complete.
</P>

<section> <TITLE>Enhancements</TITLE>

<P>
Instead of using standard buttons, we might want to use a toolbar look and feel. A QTk widget does that : <<tbbutton>>. As its interface is the same as standard buttons, we just have to change le label of the record :
<CODE DISPLAY>Toolbar=lr(glue:we
           tbbutton(text:"Save" glue:w)
           tbbutton(text:"Load" glue:w)
           tbbutton(text:"Quit" glue:w))</CODE>
If there is a lot of text, scrollbars are usefull to allow easy mouse navigation. This can be added with a parameter :
<CODE DISPLAY>text(glue:nswe handle:TextHandle tdscrollbar:true)</CODE>

Moreover one may prefer the white color as background color for the text :
<CODE DISPLAY>text(glue:nswe handle:TextHandle tdscrollbar:true bg:white)</CODE>

As you can see, widgets are highly configurable by parameters. Most of these parameters can be dynamically changed :

<CODE DISPLAY>{TextHandle set(bg:white)}</CODE>

Sets also the background to white but it can be done at any time as soon as the window is built and as long as it isn't closed. Interfaces to widgets were made as uniform as possible and similar widgets have similar parameters name and use.

<section> <TITLE>The complete code</TITLE>

 <para><title><ref.extern to="notepad.oz">Source
File</ref.extern></title>
<code.extern display to="notepad.oz" proglang=oz></para>

</CHAPTER>
