<CHAPTER ID="chapter.basics">
  <TITLE>Building a window</TITLE>
<p>
The introductory example showed the building of a simple application and how its gui is expressed in QTk. This chapter will detail all the informations you need to start working with QTk. The geometry management and the different principles of QTk are described.

<section id="basics.geometry"> <TITLE>Geometry management</TITLE>

<P>
The geometry management is done by means of dedicated widgets :
<LIST>
<ITEM> <<td>> which organizes widgets top down.
<ITEM> <<lr>> which organizes widgets from left to right.
</LIST>

By default all widgets take exactly the size they need to draw themselves. If there is more space available, widgets are centered by default inside that space. That behaviour can be changed by the <<glue>> paramater all widgets have. Valid values for this parameter are atoms that are a combination of the letters <<n>>, <<s>>, <<w>> and <<e>> that correspond respectively to the top, bottom, left and right side of the widget. Gluing a side consist of placing a constraint on that side with its corresponding neighboor. Gluing two opposite sides results in the widget taking all the space available in the direction of these sides.
</P>
<P>
Let's consider :
</P> <P>
<<lr(glue:nswe
   button(text:"Left")
   button(text:"Right"))>>

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

This describes a frame with two buttons placed side by side horizontally.If the user resizes the window, the frame is split in equal space and each button is centered within its own space.

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

We can add constraints to how control the geometry of the widgets with the <<glue>> parameter :
</P> <P>

<<lr(glue:nswe
   button(text:"Left" glue:e)
   button(text:"Right")>>

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

Now the east border of the left button is constrained with its right neighboor. When the window is resized, the two buttons stick themselves together, centering themselves in all the available space.
</P> <P>
<<lr(glue:nswe
   button(text:"Left"
   button(text:"Right" glue:w))>>

<figure id="figure.picture7">
<picture.extern to="picture6.gif" type=gif>
  
This is the same as the previous example as the west border of right button  is constrained with its left neighboor.

</P> <P>

It is also possible to ask widgets to take as much space as is available:
</P> <P>
<<lr(glue:nswe
  button(text:"Left" glue:we)
  button(text:"Right"))>>

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

The first button is glued to both horizontal side. The second button takes just its necessary size (default behaviour). The result is that the second button is stuck to the right while the first button takes all the remaining available horizontal space.
</P> <P>

<<td>> widgets can be included inside <<lr>> widgets and vice versa. Combining with the <<glue>> parameter, complex windows can be built. However it is hard to obtain windows that need a grid structure like a calculator :

</P> <P>
<<td(lr(button(text:"One") button(text:"Two") button(text:"Three"))
  lr(button(text:"Four") button(text:"Five") button(text:"Six"))
  lr(button(text:"Seven") button(text:"Height") button(text:"Nine"))
  button(text:"Zero"))>>

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

As the text labels aren't the same width, the buttons are not vertically centered. There is a command to achieve this : <<newline>>.

</P> <P>
<<lr(button(text:"One") button(text:"Two") button(text:"Three")   newline
  button(text:"Four") button(text:"Five") button(text:"Six")     newline
  button(text:"Seven") button(text:"Height") button(text:"Nine") newline
  button(text:"Zero"))>>

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

<<newline>> introduces a new line (or column for the <<td>> widget) with a grid structure, such that widgets are aligned on several lines.
</P><P>
Another uselfull command is <<empty>> which leaves an empty space :

</P> <P>
<<lr(button(text:"One") button(text:"Two") button(text:"Three")   newline
  button(text:"Four") button(text:"Five") button(text:"Six")     newline
  button(text:"Seven") button(text:"Height") button(text:"Nine") newline
  empty button(text:"Zero") empty)>>

<figure id="figure.picture11">
<picture.extern to="picture11.gif" type=gif>
</P> <P>

Note that <<newline>> and <<empty>> are <EM>not</EM> widgets and that they don't have any parameter (they don't have a <<glue>> or a <<handle>> parameter for instance).

<section id="basics.interaction"> <TITLE>Interacting with widgets</TITLE>

<P>

The description record of the window defines :


<LIST>
<ITEM> The geometry fo the window
<ITEM> The initial state of the widgets
</LIST>

This section will describe how the state of the widgets can be dynamically changed. Changin the geometry of the window is made by using the <<placeholder>> widget, and will not be detailed here.
</P> <P>

To modify the state of a widget, we first need to have a mean of referencing this widget. This is done by giving an unbound variable to the handle parameter of the widget description :
<CODE DISPLAY>local
  B
  Desc=td(button(text:"One" handle:B))
  Window={QTk.build Desc}
in
  {Window show}
  {B set(text:"Two")}
end
</CODE>

While building the window, all <<handle>> variables are bound to objects that grant control over the corresponding widgets. These objects have interfaces depending on the nature of the widgets they are controlling. However these interfaces were made as uniform as possible and contains at least the following methods:

<LIST>
<ITEM> <<set(parameter:value)>> : dynamically changes the value of the parameter of the widget.
<ITEM> <<get(parameter:free_variable)>> : binds the variable to the contents of the parameter of the widget.
</LIST>

Several parameters can be set or get in a single command :
<CODE DISPLAY>{B set(text:"Three" bg:red)}</CODE>

See the specific widget documentation to see what are the parameters and what type is their value.
</P> <P>

Another way of getting an handle is to use the feature parameter :
<CODE DISPLAY>local
  Desc=td(button(text:"One" feature:button))
  Window={QTk.build Desc}
in
  {Window show}
  {Window.button set(text:"Two")}
end
</CODE>

This is strictly equivalent to the previous example. Instead of using a variable, this method uses a feature of the parent object. Using handles or features is just a matter of taste as both methods are equivalent.
</P> <P>

Most widgets have a <<init>> parameter that sets the initial state of the widget (depending on the nature of the widget).
<CODE DISPLAY>local
  Window={QTk.build td(checkbutton(init:true  text:"Initial state is on")
                       checkbutton(init:false text:"Initial state is off"))}
in
  {Window.show}
end</CODE>

Many widgets have also a <<return>> parameter to help you build dialogbox-like windows. The variables given to these parameters are bound to a value depending on the state of the widget WHEN the window is closed. For example a dialogbox that asks for the name of the user can be written as :
<CODE DISPLAY>local
  E
  Window={QTk.build lr(label(text:"Enter your name then close the window :")
                        entry(return:E))}
in
  {Window show}
  {Wait E}   % E is bound when the window is closed
  {Browse E} % Displays E
end</CODE>
See the specific documentation for widgets to see if it supports the return parameter and what is the returned value.
</P> <P>

The <<return>> parameter makes the creation of simple dialog boxes easier :

<CODE DISPLAY>local
  Name
  Window={QTk.build lr(label(text:"What's your name ?")
                       entry(return:Name))}
in
  {Window show}
  {Wait Name}
  {Show Name}
end</CODE>


<section> <TITLE> Events and actions </TITLE>

<P>
So far we are still unable to dynamically interact with the user, as we don't now what he is doing. Actions can be associated to user events. Many widgets have a main event that corresponding to the most obvious use of the widget. All other events can be finely defined using the <<bind>> method.

<subsection id=basics.events> <TITLE>Main events</TITLE>
<P>
Most widgets raises an event just after the user has interacted with them :
<LIST>
<ITEM> After the user clicked on a button
<ITEM> After the user selected an item in a list
<ITEM> After the user typed a letter in an entry
<ITEM> After the user checked or unchecked a checkbutton
<ITEM> And so on depending on the widget type
</LIST>

These are called main events. Most simple uses are covered by these events. These events are defined by then <<action>> parameter of the object. This parameter can be one of the following :

<LIST>
<ITEM> A zero parameter procedure
<ITEM> A pair objet_variable#method
<ITEM> A pair port_variable#message
<ITEM> A pair <<toplevel>>#method
<ITEM> A pair <<widget>>#method
</LIST>

Where the last two are just shortcuts to objet_variable#method with objet_variable being a reference respectively to the window or the widget itself.
<CODE DISPLAY>local

  class C
    meth init skip end
    meth show(Msg) {Show Msg} end
  end
  O={New C init}

  R
  P={NewPort R}
  thread
    {ForAll R proc{$ Msg} {Show Msg} end}
  end

  Window={QTk.build td(button(text:"Procedure"
                              action:proc{$} {Show 'Procedure'} end)
                       button(text:"Object"
                              action:O#show('Object'))
                       button(text:"Port"
                              action:P#'Port')
                       button(text:"toplevel"
                              action:toplevel#set(title:"Toplevel"))
                       button(text:"widget"
                              action:widget#set(text:"widget clicked")))}
in
  {Window show}
end</CODE>

As you can see the <<toplevel#..>> and <<widget#...>> are just shortcuts. A frequent use is <<button(text:"Close" action:toplevel#close)>>.
</P> <P>

<subsection> <TITLE>Concurrency between actions</TITLE>

<P>
A unique thread is associated to each window : all actions are serialized and executed in the first in first out order. If the window is closed, pending actions are simply ignored.
<CODE DISPLAY>local
  Window={QTk.build td(button(text:"1"     action:proc{$} {Delay 2000} {Show 1} end)
                       button(text:"2"     action:proc{$} {Delay 2000} {Show 2} end)
                       button(text:"close" action:toplevel#close))}
in
  {Window show}
end</CODE>
See specific widget documentations for further details.
</P><P>


<subsection id="basics.otherevents"> <TITLE>Other events</TITLE>

<P>
There are many other events that you might want to observe. Widgets have the <<bind>> method that allows you to add actions to all these events.
</P> <P>

<<local
  Window={QTk.build td(canvas(glue:nswe handle:C))}
in
  {Window show}
  {C bind(event:"<1>"
          args:[int(x) int(y)]
          action:proc{$ X Y} {C create(circle X-5 Y-5 X+5 Y+5)} end)}
end>>

</P> <P>
The <<event>> parameter is a string describing the event you want to listen. Here <<"<1>">> is the left mouse button being pushed down. The <<action>> parameter can only take the procedure, method or port message forms. However these events can also receive parameters. The example above shows how the coordinates of the mouse are obtained. The parameters you want to received are specified by the <<args>> parameter. See the specific widget documentation to see valid codes. The action is called with as much parameters as specified with <<args>>.

</CHAPTER>
