A simple drawing canvas in hush

Instructor's Guide


drawtool, design, specification, summary, Q/A, literature
The Tcl/Tk toolkit provides a very powerful scripting environment for realizing graphical user interfaces,  [Ousterhout91]. The hush Java/C++ library gives convenient access to the Tcl/Tk toolkit in an object-oriented style. See also  [HUSH].

slide: The hush class hierarchy

The hush library provides three kinds of classes, namely (a) the widget classes, which mimic the functionality of Tk, (b) the handler and event classes, which are involved in the handling of events and the binding of Java/C++ code to Tcl commands, and (c) the classes kit and session, which encapsulate the embedded interpreter and the window management system,

In the widget class hierarchy depicted on the right in slide hush-overview, the widget class represents an abstract widget, defining the commands that are valid for each of the descendant concrete widget classes. The widget class, however, is not an abstract class in Java or C++ terms. It may be used for creating references to widgets defined in Tcl. In contrast, employing the constructor of one of the concrete widget classes results in actually creating a widget.



slide: Drawing canvas

Widgets are the elements from which a GUI is made. They appear as windows on the screen to display text or graphics and may respond to events such as motioning the mouse or pressing a key by calling an action associated with that event. The interface of the widget class may be defined by the (pseudo) interface below.
  public interface widget { 
widget
public String path(); public void eval(String cmd); public void pack(String s); public void bind(handler h,String s); public void bind(String p, handler h,String s); public void configure(String cmd); public void geometry(int x, int y); public void xscroll(widget w); public void yscroll(widget w); public widget self();
to define compound widgets
public void redirect(widget inner); };

slide: The widget class

The function path delivers the path name of a widget object. Each widget created by Tk actually defines a Tcl command associated with the path name of the widget. In other words, an actual widget may be regarded as an object which can be asked to evaluate commands. For example a widget `.b' may be asked to change its background color by a Tcl command like .b configure -background blue The function eval enables the programmer to apply Tcl commands to the widget directly, as does the configure command. The function geometry sets the width and height of the widget.

As an example look at the code for the drawing canvas widget depicted in slide drawing-canvas.


  import hush.dv.api.event;
  import hush.dv.widgets.canvas;
  
  class draw extends canvas { 
draw go.java
boolean dragging; public draw(String path) { super(path); dragging = false; bind(this); } public void press(event ev) { dragging = true; } public void release(event ev) { dragging = false; } public void motion(event ev) { if (dragging) circle(ev.x(),ev.y(),2,"-fill black"); } };

slide: Drawing application

The class draw has an instance variable dragging, that reflects whether the user is actually drawing a figure. If dragging is true, motions with the mouse will result in small dots on the screen.

slide: Drawing canvas

A structural view of the draw class is given in slide draw-structure. The draw class is derived from a canvas, which is itself (indirectly) derived from a handler class. The handler class dispatches events to predefined handler methods, such as press, motion and release.

For the draw class we must distinguish between a handler and a canvas part. The handler part is defined by the methods press, release and motion. The canvas part allows for drawing figures, such as a small circle.



slide: Drawing canvas

In slide draw-interact it is depicted how these two parts interact when the user draws a figure. Actions of the user result in events that activate the handler. Note that the UML sequence diagrams are not completely adequate here, since it is difficult to express information concerning the events and the state of the draw instance.

Widgets may respond to events. To associate an event with an action, an explicit binding must be specified for that particular widget. Some widgets provide default bindings. These may, however, be overruled.

The function bind is used to associate handlers with events. The first string parameter of bind may be used to specify the event type. Common event types are, for example, ButtonPress, ButtonRelease and Motion, which are the default events for canvas widgets. Also keystrokes may be defined as events, for example Return, which is the default event for the entry widget. The function bind(handler,String) may be used to associate a handler object with the default bindings for the widget. Concrete widgets may not override the bind function itself, but must define the protected function install. Typically, the install function consists of calls to bind for each of the event types that is relevant to the widget.

In addition, the widget class offers two functions that may be used when defining compound or mega widgets. The function redirect(w) must by used to delegate the invocation of the eval, configure and bind functions to the widget w. The function self() gives access to the widget to which the commands are redirected. The function path will still deliver the path name of the outer widget. Calling redirect when creating the compound widget class suffices for most situations. However, when the default events must be changed or the declaration of a handler must take effect for several component widgets, the function install must be redefined to handle the delegation explicitly.