Tycho's IncrCanvas and Slate classes extends the Tk canvas with support for hierarchical complex items, symbolic access to item coordinates, a graphical selection, and re-usable interaction mechanisms. In theory, these classes are upwards-compatible with the Tk canvas and are as easy to use as the Tk canvas. In practice, however, it's not that simple, either because the performance constraints of Tcl forced some short-cuts that occasionally show up in the interface, or because we just boo-booed. Here's a frank listing of possible problems and hard questions that might come up, in no particular order.
(For the sake of brevity, "Slate" means "the IncrCanvas and Slate classes.")
$id.myitem
, and got some kind of
"item class not found" message. What's up?
Answer: The Slate uses the following tests to figure out if an argument is a the ID of a simple (Tk canvas) item, a complex item, or a tag (anything else):
if [string match {[0-9]*} $tag] { # $tag is a simple item ... } elseif [string match {_*} $tag] { # $tag is a complex item ... } else { # $tag is a tag ... }(Complex item IDs start with an underscore.) We (i.e. Reekie, it's all his fault) did this because we were concerned about the cost of using a full regular expression match. Because of this, the Slate interprets any tag starting with an underscore as a complex item id, which is why it complains when it turns out that
$id.myitem
is not in fact
a complex item.
Work-around: Use myitem.$id
instead.
Cure: We should replace string matches with proper regexps once we have the byte-compiler:
if [regexp {[0-9]+} $tag] { # $tag is a simple item ... } elseif [regexp {_[0-9]+} $tag] { # $tag is a complex item ... } else { # $tag is a tag ... }
Answer: Unfortunately, full upwards compatibility got lost because a) we insisted on implementing the Slate entirely in Itcl to maintain portability and b) we had to make a few compromises made along the way. Here are the most likely causes of incompatibility:
Answer: In real applications, the Slate is "not all that much slower" than the Tk canvas. If you've noticed a noticeable slow-down, it could be because you're using tags to access items instead of item ID's.
Let me explain: The Tk canvas allow items to be accessed by tag or by item ID. For example, you might have some code triggered by a mouse event like this:
$canvas dothis current args $canvas dothat current args("current" denotes the item being moused on.) With the Slate, this will still work (in theory), because each Slate method tries to figure out whether it's being passed an item ID or a tag and act in the same or similar manner to the Tk canvas. Unfortunately, if you do pass the Slate a tag instead of an item ID, it has to do a certain amount of work to figure out what item or items are actually represented by that tag. Since the code is written in Tcl ("Takes Considerably Longer"), that means noticeable delays.
Work-around: Instead of accessing items by tag, access them by item ID. For example, replace the above code by:
set id [$slate find withtag current] $slate dothis $id args $slate dothat $id args
Cure: The cure is to integrate Tk into Java and use that... Good luck!
$slate addtag current withtag
$item
, and I'm getting some bizarre errors. Any clues?
Answer: The Slate doesn't prevent you from assigning the "current" tag to a complex item. Unfortunately, it doesn't cope when you attempt to "find" the current item, since it assumes that there is only a single canvas item with the "current" tag. As a result, you will be getting a list of the canvas items when you try to "find" the current item, rather than a single complex item id.
Work-around: Instead of assigning to the tag to a complex item, assign it to a simple component. Here's the most likely code to work:
$slate addtag current withtag [$slate primary $id]
Cure: The find withtag
operation should
deal with the case where multiple canvas items have the
current
tag.
tycho/slate
directory contain common arrays indexed by the id of an item.
Some, though, use just the item ID, while others do a weird
thing with an id obtained from a slate, like this:
set unique $id.[$slate uniqueid] set option(foo.$unique) ...Why?
Answer: Well, you realize that the common arrays are indexed by item ID because actually creating Itcl objects for each complex item turned out to be too expensive. In effect, we are trying to implement OO in a non-OO way. Now, since the arrays are common, we have to guarantee that the indexes are unique. There are two situations, which arise because of the ways that various classes in these directories are implemented. (Note, by the way, that the IDs of complex items are generated from a common variable in IncrCanvas.) The two situations are:
foo.$id
Work-around: No work-around is required.
Cure: There is no cure! (At least, not one that would making writing ComplexItem subclasses harder to write.)
Answer: We did that... and it was too slow. Not horrendously slow... not breathtakingly slow (well, not any more than Tcl was to start with...)... but slow enough to worry us. So we "flattened" the OO structure into an essentially-procedural implementation and it turned out to be about three times faster. So that was that....
As it turned out, the procedural version was simpler to develop anyway. Much as I'd like to do a full OO implementation, Itcl is not really designed for that granularity, and the procedural version of the ComplexItem classes just "works better."
Tycho Slate class documentation
Tycho Home Page