You can add new item types to the Slate by writing an Itcl class. You need to inherit from Picture or a subclass. The Picture class and its subclasses are not proper classes, but a mechanism for manipulating items IDs and tags to give the Slate client the appearance of a single complex item, which is made of many primitive items.
As an example, we will create a simple class that is an oval
with a text label in the center of it. This is a simple version of the
LabelledOval class. Firstly, we'll create the class body (the
details will be filled in shortly):
class ::tycho::Simple {
inherit ::tycho::Picture
proc construct {id canvas slate tags x0 y0 x1 y1 args}
proc coords {id canvas slate args}
proc _text {id canvas slate tx}
common _text
common textitem
common shape "oval"
common methodtable
array set methodtable [array get ::tycho::Picture::methodtable]
set methodtable(construct) ::tycho::Simple::construct
set methodtable(coords) ::tycho::Simple::coords
set methodtable(_text) ::tycho::Simple::_text
common optiondefault
array set optiondefault [array get ::tycho::Picture::optiondefault]
set optiondefault(-text) ""
}
Notice that the class contains procedures only -- not methods. The first three arguments to each procedure are always id (the item ID), canvas (the canvas widget inside the slate we are drawing on) and slate (the slate widget). Notice also that all data is ``common'': each is an array indexed by the item ID. Every Picture subclass must have at least the common variables shape, methodtable, and optiondefault.
To simulate inheritance, methodtable
must first be set
with the names of the procs in the parent class (the first array
set
), and then updated with procs defined in this class. The
options are also inherited: the same procedure must be followed with
the optiondefault
array. This class has a single optoin,
-text
.
The construct
procedure is called to create a new item.
It must start by setting the options: the first three lines of code are
common to every construct
procedure. In this case, the
text
array will have an entry set to the supplied value of
the -text
option, or the default value if none is supplied.
The next line creates the "primary" item -- every picture must create
one of these, which must be a primitive items. It is used by the slate
to get the coordinates of the complex item. In this example, the
primary item is also displayed; in other cases, it may not be displayed
(by setting its -outline
option to {}
). The
final line of code creates the text label, using the -text
option, and remembers the text item ID in the textitem
array.
body ::tycho::Simple::construct {id canvas slate tags x0 y0 x1 y1 args} {
# Initialize the options
foreach {option value} [concat [array get optiondefault] $args] {
set _[string trimleft $option -]($id) $value
}
# Create the primary component. This is the displayed oval.
set primary($id) [$canvas create oval $x0 $y0 $x1 $y1 \
-tags $tags]
# Create the text label
set textitem($id) [$canvas create text \
[expr ($x0+$x1)/2] [expr ($y0+$y1)/2] \
-text $_text($id) -tags $tags]
}
When the -text
option is configured, the slate calls a
procedure with the same name as the option (without the leading dash).
Here is the text
procedure -- it updates the text in the
text item:
body ::tycho::Simple::_text {id canvas slate text} {
set _text($id) $text
$canvas itemconfigure $textitem($id) -text $_text($id)
}
Finally, we provide a special implementation of the
coords
procedure to handle a change in the coordinates.
(In this example, it is not really necessary: the Slate provides a
default behavior based on item scaling that will be adequate for
many complex items.)
body ::tycho::Simple::coords {id canvas slate args} {
if { $args == "" } {
return [$canvas coords $primary($id)]
}
assign x0 y0 x1 y1 $args
# Move the oval
$canvas coords $primary($id) $x0 $y0 $x1 $y1
# Move the text item
$canvas coords $textitem($id) [expr ($x0+$x1)/2] [expr ($y0+$y1)/2]
}
To try out your new item type, just call the Slate as before:
set m [$slate create Simple 20 60 60 80 -text Foo]
Move it:
$slate move $m 10 10
Change its coordinates:
$slate coords $m 10 10 90 90
Change its label:
$slate itemconfigure $m -text Bar