The tk canvas is a great thing: it is extremely flexible in order to implement all-you-could-imagine on top of it. Consider a graphical editor, in which the user edit a diagram composed by some kind of object (UML entities, ER entities, etc) and connectors that links these objects. In these situations, the implementor should write the diagram code over the tk canvas. While writing GNU Ferret (http://www.gnu.org/software/ferret) i felt the need for a library supporting diagrams on tk. So i wrote diagram.tcl A diagram is composed by objects and connectors. An object is composed by an arbitrary number of tagged canvas elements (text, lines, rectangles, etc). When you declare a new object, you also set a shape for it: rectangle, ovoid, romboid, etc. The shape do not need to be visible. Connectors are orthogonal editable paths of lines connecting diagram objects. Download the diagram package at: http://es.gnu.org/~jemarch/downloads/diagram.tcl Usage example (double click on the connector line to modify it): lappend auto_path . package require BWidget package require diagram # Draw proc proc object_drawproc {dname oname location type} { set canvas [diagram::get_canvas $dname] # Draw some elements on this object $canvas create text \ [expr [diagram::px $location] + 10] [expr [diagram::py $location] + 10] \ -text "Object $oname at ([diagram::px $location],[diagram::py $location])" \ -anchor w \ -tags [list $dname $oname] # Bind for movement $canvas bind ${oname} \ [list diagram::mark_drag_object $dname $oname %x %y] $canvas bind ${oname} \ [list diagram::drag_object $dname $oname %x %y] # Return the new geometry of this object set bbox [$canvas bbox $oname] return [list \ $location \ [diagram::point [expr [lindex $bbox 2] + 10] [expr [lindex $bbox 3] + 10]]] } # Create a new diagram on .d diagram::create_diagram my_diagram .d pack .d -fill both -expand true # Create two objects diagram::create_object my_diagram object1 rectangle object_drawproc [diagram::point 10 10] diagram::create_object my_diagram object2 rectangle object_drawproc [diagram::point 300 300] # Create a connector diagram::create_connector my_diagram my_connector object2 object1 "connector" {} - diagram::update_object my_diagram object1 diagram::update_object my_diagram object2 ---- See also [Playing UML]