class move_handler : public handler {
public:
move_handler( canvas* cv ) : c(cv) { dragging = 0; }
void press( event& e ) { // if overlapping start dragging
x = e.x(); y = e.y();
id = c->overlapping(x, y);
if (id) dragging = 1;
}
void motion( event& e ) { // if dragging move
if (dragging) {
id.move( e.x() - x, e.y() - y );
x = e.x(); y = e.y();
}
}
void release( event& ) { dragging = 0; } // stop dragging
protected:
canvas* c; int dragging; item id; int x,y;
};
slide: Moving items on a canvas
The move_handler class is derived from the class
handler.
It makes use of the dispatch
and operator() function defined for
handler,
but redefines the (virtual) functions
press, motion and release.
When creating an instance of move_handler,
a pointer to the canvas must be given to the constructor.
In addition, the class has data members to record
position coordinates
and whether a particular item is being moved.
Actually moving an item occurs by pressing the (left)
mouse button on an item and dragging the item along.
When the mouse button is released, moving stops.
To identify the item, the function overlapping
is used.
The movement is determined by the distance
between the last recorded position and the
current position of the cursor.
In an analogous manner,
a box_handler may be defined,
which is used for drawing rectangles and allows
for rubberbanding.
The box_handler sets dragging
to true when the button is pressed
and creates a rectangle of zero width and height.
Each time the function motion is called,
the item created in the previous round is deleted
and a new rectangle is created:
void box_handler::motion( event& e ) { // if dragging stretch
if (dragging) {
id.del();
id = c->rectangle(x,y,e.x(),e.y()); // x and y are fixed
}
}
slide: A box handler
where c is a pointer to the canvas
and x and y the button pointer coordinates
stored when dragging began.
For circles and lines, it suffices to replace the call
to rectangle with a call to the appropriate
figure creation function.
slide: Hypertext help
Both the Tk canvas and text widget allow to bind
actions to particular items
and hence to define dynamically what we may call
hyperstructures.
A different, in a way more static, approach is offered
by the hypertext widget originally developed by
George Howlett. %%george.howlett@att.com.
The hypertext widget may be used to display text
files containing embedded Tcl code.
The Tcl code must be placed between
escapes, that take the form of %%
for both the begin and end of the code.
A screen shot of a fragment of the on-line help
for drawtool is given in
figure [Help].
Notice, that the on-line help provides a
replica of the drawtool application, surrounded
by text.
When looking at (again a fragment of) the hypertext
file specifying the contents of the on-line help,
given below,
you see that the drawtool command defined
in section [new]
is employed to create the embedded widget:
>
Rubber banding: press the left mouse button
and release when the rectangle is of appropriate
size
%%
drawtool \$this.draw
\$this append \$this.draw
\$this.draw create rectangle 20 20 80 80
\$this.draw create rectangle 10 30 70 90
\$this.draw create oval 40 40 90 90
\$this append \$this.draw
%%
For additional information click on the %%
button \$this.goto -text instruction -command end-of-text
\$this append \$this.goto
%%
button. Press %%
button \$this.quit -command { destroy . } -text quit -bg pink
\$this append quit
%% to remove the window.
slide: Rubber banding
When specifying the hypertext file,
widgets may be
given a pathname relative to the pathname of the
hypertext widget by using the variable this.
In addition the hypertext widget offers the variables
thisline and thisfile to identify the
current line number and current file name.
Any of the widgets and commands offered by Tcl/Tk or supported
by hush may be included in a hypertext file,
including the ones defined by the program
itself.
intro
Tcl/Tk
programs
handler actions to events
widgets
graphics
appendix