George Peter Staplin: July 5, 2004: My Smalltick widgets are progressing well. I've managed to create a canvas-like widget that can be used to draw images. Today I implemented most of a decode.png command to go with a gui.create.image (for creating XImages) and displayed my first PNG using it. I just need to complete the < 24-bit display handling. I will then focus on storing pixmaps with encode.png (through gui.get.image (to get an XImage with ->data)).
I've wanted to clone A symmetric doodler for quite some time using Smalltick, and I may soon achieve that goal. I also have plans to write decode.jpeg and encode.jpeg.
Without further ado we can begin the example code:
Here's the usercode for the DrawingEditor widget/class:
proc create.gui mw { [set topc [Container [new.object] $mw]] \ -row 0 -column 0 -sticky we -map [set botc [Container [new.object] $mw]] \ -row 1 -column 0 -sticky news -map [set de [DrawingEditor [new.object] $botc]] \ -width 400 -height 450 -row 0 -column 0 -sticky news -map set i 0 foreach col [list red green blue orange purple] { [Button [new.object] $topc] \ -text $col -command [list [list $de -set.pen.color $col]] \ -bg $col -row 0 -column $i -map incr i } } proc main {} { set mw [Widget [new.object]] $mw set {window-path .} \ -column.weight [list 0 100] \ -row.weight [list 0 100] create.gui $mw } main
And here we have the DrawingEditor widget/class implementation:
proc DrawingEditor {d p} { Widget $d $d create.window $p $d set {drawing-editor-pixmap {}} $d set {drawing-editor-pen-color {}} $d set {drawing-editor-pen-color-string {}} $d set [list drawing-editor-pen-gc [gui.create.gc [$d get wid]]] $d set {drawing-editor-pen-start-x 0} $d set {drawing-editor-pen-start-y 0} $d set {drawing-editor-busy 0} $d set {drawing-editor-pixmap-width 2000} $d set {drawing-editor-pixmap-height 2000} $d append.destroy.command \ [list {gui.destroy.gc [$self get drawing-editor-pen-gc]}] \ append.destroy.command \ [list {gui.destroy.pixmap [$self get drawing-editor-pixmap]}] \ append.destroy.command \ [list {gui.destroy.gc [$self get drawing-editor-pen-gc]}] \ append.destroy.command \ [list {gui.destroy.color [$self get drawing-editor-pen-color]}] $d : -set.pen.color color-string { $self ?set [list drawing-editor-pen-color-string [set color-string]] if {"" != [set gcol [$self get drawing-editor-pen-color]]} { gui.destroy.color $gcol } $self ?set \ [list drawing-editor-pen-color [set col [gui.create.color [set color-string]]]] gui.set.gc.color [$self get drawing-editor-pen-gc] $col } $d : create.drawing.editor.pixmap {} { if {"" != [set p [$self get drawing-editor-pixmap]]} { gui.destroy.pixmap $p } $self ?set \ [list drawing-editor-pixmap [gui.create.pixmap [$self get window-path] \ [$self get drawing-editor-pixmap-width] \ [$self get drawing-editor-pixmap-height]]] set gc [gui.create.gc [$self get wid]] gui.set.gc.color $gc [set col [gui.create.color white]] gui.draw.rectangle \ [$self get drawing-editor-pixmap] \ $gc \ 0 0 \ [$self get drawing-editor-pixmap-width] \ [$self get drawing-editor-pixmap-height] gui.destroy.color $col gui.destroy.gc $gc } $d : draw.drawing.editor {} { $self ?set {drawing-editor-busy 0} gui.copy.area \ [$self get drawing-editor-pen-gc] \ [$self get drawing-editor-pixmap] \ [$self get wid] \ 0 0 \ [winfo width [$self get window-path]] \ [winfo height [$self get window-path]] \ 0 0 } $d : draw.drawing.editor.when.idle {} { if {[$self get drawing-editor-busy]} return $self ?set {drawing-editor-busy 1} after idle [list $self draw.drawing.editor] } $d : draw.on.pixmap {x y} { gui.draw.line \ [$self get drawing-editor-pixmap] \ [$self get drawing-editor-pen-gc] \ [$self get drawing-editor-pen-start-x] \ [$self get drawing-editor-pen-start-y] \ $x $y $self set.initial.start.coordinates [list $x $y] $self draw.drawing.editor.when.idle } $d : drawing.editor.configure.event {w h} { $self draw.drawing.editor.when.idle } $d : dump.structure {} { puts PIXMAP:[$self get drawing-editor-pixmap] puts PEN_COLOR:[$self get drawing-editor-pen-color] puts COLOR_STRING:[$self get drawing-editor-pen-color-string] puts PEN_GC:[$self get drawing-editor-pen-gc] puts START_X:[$self get drawing-editor-pen-start-x] puts START_Y:[$self get drawing-editor-pen-start-y] } $d : set.initial.start.coordinates {x y} { $self ?set [list drawing-editor-pen-start-x $x] $self ?set [list drawing-editor-pen-start-y $y] } $d create.drawing.editor.pixmap $d -set.pen.color red bind DrawingEditor$d <ButtonPress-1> \ [list $d set.initial.start.coordinates {%x %y}] bind DrawingEditor$d <B1-Motion> \ [list $d draw.on.pixmap {%x %y}] bind DrawingEditor$d <Expose> [list $d draw.drawing.editor.when.idle] bind DrawingEditor$d <Configure> \ [list $d drawing.editor.configure.event {%w %h}] set w [$d get window-path] #bindtags $w [list $w DrawingEditor$d] bindtags $w [linsert [bindtags $w] end DrawingEditor$d] $d draw.drawing.editor.when.idle return $d}
This is what it can look like with the usercode: