[GPS]: This page serves to demonstrate the design behind the [Smalltick] Tk widgets. For years I've thought about widgets with inheritance for Tcl/Tk. A couple of weeks ago the ideas hit me, and I realized I might be able to bring these ideas to fruition. The code needed to produce the image below will be discussed. [http://www.xmission.com/~georgeps/tmp/Smalltick_Container.png] Top down we have: set con [Container [new.object] $mw] $con -column 0 -row 0 -sticky news -map Smalltick provides the '''new.object''' command. The Container class takes our new object and adds methods and variables for the Container widget. In Smalltick, classes are simply procedures. First our Container class (which you will see later) inherits from the Widget class. Here is the Widget class (from Widget.proc): proc Widget {w} { $w set {_column {}} $w set {_row {}} $w set {_sticky {}} $w : -column c { $self set [list _column $c] } $w : -row r { $self set [list _row $r] } $w : -sticky s { $self set [list _sticky $s] } $w : -map {} { grid [$self get window-path] \ -column [$self get _column] \ -row [$self get _row] \ -sticky [$self get _sticky] } $w : -unmap {} { grid forget [$self get window-path] } return $w } As you can see the code above defines several methods for our object passed to the procedure. We now have the mapping and geometry management handled. Now let's move onto a simple Container class (Container.proc): proc Container {c p} { Widget $c $c set [list window-path \ [set w [gui.get.unique.window.path [$p get window-path]]]] set wid [gui.get.window.id [gui.create.window $w]] $c set [list wid $wid] #These 3 sets of commands are very alike. #I can't think of the best way to factor them yet. $c set [list bg-gc [gui.create.gc $wid]] $c set [list bg-color [gui.create.color gray70]] gui.set.gc.color [$c get bg-gc] [$c get bg-color] $c set [list bd-light-gc [gui.create.gc $wid]] $c set [list bd-light-color [gui.create.color gray90]] gui.set.gc.color [$c get bd-light-gc] [$c get bd-light-color] $c set [list bd-dark-gc [gui.create.gc $wid]] $c set [list bd-dark-color [gui.create.color gray30]] gui.set.gc.color [$c get bd-dark-gc] [$c get bd-dark-color] $c set {draw-is-pending 0} $c : -bg color { gui.destroy.color [$self get bg-color] $self set [list bg-color [gui.create.color $color]] gui.set.gc.color [$self get bg-gc] [$self get bg-color] $self draw.when.idle } $c : draw {} { gui.draw.rectangle \ [$self get wid] [$self get bg-gc] \ 0 0 \ [winfo width [$self get window-path]] \ [winfo height [$self get window-path]] $self draw.border $self set {draw-is-pending 0} } $c : draw.border {} { set w [winfo width [$self get window-path]] set h [winfo height [$self get window-path]] gui.draw.line \ [$self get wid] \ [$self get bd-light-gc] \ 0 0 0 $h gui.draw.line \ [$self get wid] \ [$self get bd-light-gc] \ 0 0 $w 0 gui.draw.line \ [$self get wid] \ [$self get bd-dark-gc] \ [expr {$w - 1}] 0 [expr {$w - 1}] $h gui.draw.line \ [$self get wid] \ [$self get bd-dark-gc] \ 0 [expr {$h - 1}] $w [expr {$h - 1}] } $c : draw.when.idle {} { if {[$self get draw-is-pending]} return $self set {draw-is-pending 1} after idle [list $self draw] } $c : Configure {} { $self draw.when.idle } $c : Expose {} { $self draw.when.idle } bind $w [list $c Configure] bind $w [list $c Expose] gui.request.geometry $w 100 100 $c draw return $c } ---- You may wonder: why is this cool? To me it's cool because the widgets are mostly written in Tcl. The various gui.* commands you see used above are provided by a simple C extension I wrote. That said, there is work left to do. The code above is unfinished, because it doesn't provide cleanup for memory allocated, but I felt it was interesting to share the ideas behind this on the Wiki so that people in the chat might discuss it. ---- [Category GUI]