aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authormescalinum <mescalinum@users.sourceforge.net>2011-10-02 16:42:06 +0000
committermescalinum <mescalinum@users.sourceforge.net>2011-10-02 16:42:06 +0000
commit44f29524444a96d9e40a76f48750f17e2fdc2974 (patch)
tree179e086e72dd64cd130ee493e78d8535a74a76ec /examples
parent5a38f01421e93db2cf5b5c05afe84fb73eb89425 (diff)
reorganize tree following template structure
svn path=/trunk/externals/loaders/tclpd/; revision=15443
Diffstat (limited to 'examples')
-rw-r--r--examples/bitmap-help.pd77
-rw-r--r--examples/bitmap-madness.pd134
-rw-r--r--examples/bitmap.tcl346
-rw-r--r--examples/colorpicker.tcl281
-rw-r--r--examples/dynreceive-help.pd22
-rw-r--r--examples/dynreceive.tcl53
-rw-r--r--examples/dynroute-help.pd26
-rw-r--r--examples/dynroute.tcl57
-rw-r--r--examples/list_change-help.pd21
-rw-r--r--examples/list_change.tcl31
-rw-r--r--examples/properties.tcl423
-rw-r--r--examples/slider2-help.pd51
-rw-r--r--examples/slider2.tcl273
13 files changed, 1795 insertions, 0 deletions
diff --git a/examples/bitmap-help.pd b/examples/bitmap-help.pd
new file mode 100644
index 0000000..e12deab
--- /dev/null
+++ b/examples/bitmap-help.pd
@@ -0,0 +1,77 @@
+#N canvas 625 330 742 518 10;
+#X obj 63 244 bitmap -cellsize 15 -uwidth 8 -uheight 8;
+#bitmap setdata 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0
+0 1 0 1 1 0 0 0 1 0 1 0 1 0 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 1 0 1 0 1
+0 1 1 0 1 0 1 0 1 0;
+#X obj 87 410 print out;
+#X msg 39 117 getrow \$1;
+#X obj 42 245 vradio 15 1 0 8 empty empty empty 0 -8 0 10 -228856 -162280
+-1 0;
+#X obj 42 410 s \$0r;
+#X obj 39 89 r \$0r;
+#X text 36 19 [bitmap] - a two dimensional array of bits (toggles)
+;
+#X text 38 49 creation arguments -cellsize <#> -uwidth <#> -uheight <#>;
+#X msg 111 117 getcol \$1;
+#X obj 111 89 r \$0c;
+#X obj 63 213 r \$0b;
+#X obj 39 157 s \$0b;
+#X obj 63 372 hradio 15 1 0 8 empty empty empty 0 -8 0 10 -228856 -162280
+-1 0;
+#X obj 157 410 s \$0c;
+#X obj 227 157 s \$0b;
+#X msg 227 117 getcell 0 1;
+#X msg 317 117 getcell 1 1;
+#X text 226 88 getcell <row> <col>;
+#X obj 247 243 bitmap -cellsize 4 -uwidth 16 -uheight 16;
+#bitmap setdata 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
+1 0 1 1 1 1 0 1 1 1 1 1 0 0 1 0 1 0 1 0 0 1 0 1 0 0 0 1 0 0 1 1 1 0
+1 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 1 1 1 1 0 0
+0 0 0 1 1 1 1 1 0 0 1 0 0 1 0 1 1 1 1 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0
+1 0 1 1 1 1 0 0 1 1 1 1 0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 1 0
+1 0 0 1 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 1 0 0 0 1 0 1 1 1 1 0 0
+0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 1 1 1 0 0 1 0 0 0 1 0 1 0 0 1 0 1 0 1
+0 0 1 1 1 1 1 0 1 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
+#X msg 447 200 setcell \$1 \$2 \$3;
+#N canvas 4 117 450 300 randomdata 0;
+#X obj 220 136 random 2;
+#X obj 62 89 t b b b;
+#X obj 62 35 inlet;
+#X obj 62 187 pack f f f;
+#X obj 62 222 outlet;
+#X obj 62 62 metro 10;
+#X obj 62 136 random 4;
+#X obj 141 136 random 4;
+#X connect 0 0 3 2;
+#X connect 1 0 6 0;
+#X connect 1 1 7 0;
+#X connect 1 2 0 0;
+#X connect 2 0 5 0;
+#X connect 3 0 4 0;
+#X connect 5 0 1 0;
+#X connect 6 0 3 0;
+#X connect 7 0 3 1;
+#X restore 447 175 pd randomdata;
+#X obj 447 151 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+1;
+#X obj 447 331 bitmap -cellsize 16 -uwidth 4 -uheight 4;
+#bitmap setdata 1 0 0 0 1 0 0 1 1 0 1 1 1 1 1 0;
+#X msg 465 231 setcol 1 0 0 0 0 \, setcol 2 0 0 0 0;
+#X msg 481 292 setrow \$1 \$2 \$2 \$3 \$3;
+#X msg 481 265 0 1 0 \, 1 1 0 \, 2 0 1 \, 3 0 1;
+#X connect 0 0 1 0;
+#X connect 2 0 11 0;
+#X connect 3 0 4 0;
+#X connect 5 0 2 0;
+#X connect 8 0 11 0;
+#X connect 9 0 8 0;
+#X connect 10 0 0 0;
+#X connect 12 0 13 0;
+#X connect 15 0 14 0;
+#X connect 16 0 14 0;
+#X connect 19 0 22 0;
+#X connect 20 0 19 0;
+#X connect 21 0 20 0;
+#X connect 23 0 22 0;
+#X connect 24 0 22 0;
+#X connect 25 0 24 0;
diff --git a/examples/bitmap-madness.pd b/examples/bitmap-madness.pd
new file mode 100644
index 0000000..49a9dd3
--- /dev/null
+++ b/examples/bitmap-madness.pd
@@ -0,0 +1,134 @@
+#N canvas 5 140 311 321 10;
+#N canvas 322 138 514 645 in 1;
+#X obj 20 462 outlet;
+#X obj 51 8 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X obj 44 60 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#N canvas 3 94 332 662 for_X_Y 0;
+#X obj 61 60 inlet;
+#X obj 71 223 until;
+#X msg 125 177 0;
+#X obj 72 261 f;
+#X obj 106 260 + 1;
+#X obj 68 141 t b b;
+#X obj 78 418 until;
+#X msg 132 372 0;
+#X obj 79 456 f;
+#X obj 113 455 + 1;
+#X obj 75 336 t b b;
+#X obj 73 297 t b f;
+#X obj 82 502 pack f f;
+#X msg 77 528 \$2 \$1;
+#X obj 74 589 outlet;
+#X msg 72 177 32;
+#X msg 79 372 32;
+#X connect 0 0 5 0;
+#X connect 1 0 3 0;
+#X connect 2 0 3 1;
+#X connect 3 0 4 0;
+#X connect 3 0 11 0;
+#X connect 4 0 3 1;
+#X connect 5 0 15 0;
+#X connect 5 1 2 0;
+#X connect 6 0 8 0;
+#X connect 7 0 8 1;
+#X connect 8 0 9 0;
+#X connect 8 0 12 0;
+#X connect 9 0 8 1;
+#X connect 10 0 16 0;
+#X connect 10 1 7 0;
+#X connect 11 0 10 0;
+#X connect 11 1 12 1;
+#X connect 12 0 13 0;
+#X connect 13 0 14 0;
+#X connect 15 0 1 0;
+#X connect 16 0 6 0;
+#X restore 50 125 pd for_X_Y;
+#X obj 78 270 sin;
+#X obj 78 227 / 64;
+#X obj 51 154 unpack f f;
+#X obj 107 190 t f f;
+#X obj 21 422 pack f f f;
+#X msg 21 442 setcell \$1 \$2 \$3;
+#X obj 76 297 + 0.5;
+#X obj 151 277 sin;
+#X obj 149 255 / 16;
+#X obj 79 321 +;
+#X obj 49 189 t f f f;
+#X obj 79 249 +;
+#X obj 228 155 f;
+#X obj 263 154 + 0.1;
+#X obj 49 94 t b b;
+#X obj 78 360 wrap;
+#X obj 77 401 i;
+#X obj 148 230 expr sqrt(pow(sin($f3)*32-$f1 \, 2)+pow(cos($f3)*34-$f2
+\, 2));
+#X obj 79 380 * 1.8;
+#X obj 79 341 * 1.2;
+#X obj 151 299 + 0.6;
+#X obj 52 35 metro 40;
+#X connect 1 0 25 0;
+#X connect 2 0 18 0;
+#X connect 3 0 6 0;
+#X connect 4 0 10 0;
+#X connect 5 0 15 0;
+#X connect 6 0 14 0;
+#X connect 6 1 7 0;
+#X connect 7 0 8 1;
+#X connect 7 1 21 1;
+#X connect 8 0 9 0;
+#X connect 9 0 0 0;
+#X connect 10 0 13 0;
+#X connect 11 0 24 0;
+#X connect 12 0 11 0;
+#X connect 13 0 23 0;
+#X connect 14 0 8 0;
+#X connect 14 1 5 0;
+#X connect 14 2 21 0;
+#X connect 15 0 4 0;
+#X connect 16 0 17 0;
+#X connect 16 0 21 2;
+#X connect 17 0 16 1;
+#X connect 18 0 3 0;
+#X connect 18 1 16 0;
+#X connect 19 0 22 0;
+#X connect 20 0 8 2;
+#X connect 21 0 12 0;
+#X connect 22 0 20 0;
+#X connect 23 0 19 0;
+#X connect 24 0 13 1;
+#X connect 25 0 18 0;
+#X restore 17 10 pd in;
+#X obj 17 34 bitmap 8 32 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
+1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
+0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
+0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1;
+#X connect 0 0 1 0;
diff --git a/examples/bitmap.tcl b/examples/bitmap.tcl
new file mode 100644
index 0000000..1cbc766
--- /dev/null
+++ b/examples/bitmap.tcl
@@ -0,0 +1,346 @@
+package require Tclpd 0.2.1
+package require TclpdLib 0.17
+
+set ::script_path [file dirname [info script]]
+
+pd::guiproc bitmap_draw_new {self c x y config data} {
+ set w [dict get $config -uwidth]
+ set h [dict get $config -uheight]
+ set sz [dict get $config -cellsize]
+ set fgcolor [dict get $config -fgcolor]
+ set bgcolor [dict get $config -bgcolor]
+ set colors [list $bgcolor $fgcolor]
+ set z 0
+ for {set i 0} {$i < $h} {incr i} {
+ for {set j 0} {$j < $w} {incr j} {
+ $c create rectangle \
+ [expr {0+$x+$j*$sz}] [expr {0+$y+$i*$sz}] \
+ [expr {1+$x+($j+1)*$sz}] [expr {1+$y+($i+1)*$sz}] \
+ -outline $fgcolor -fill [lindex $colors [lindex $data $z]] \
+ -tags [list $self cell_${j}_${i}_$self]
+ incr z
+ }
+ }
+ set x2 [expr {$x+$w*$sz+1}]
+ set y2 [expr {$y+$h*$sz+1}]
+ $c create rectangle $x $y $x2 $y2 \
+ -outline $fgcolor -tags [list $self border$self]
+}
+
+pd::guiclass bitmap {
+ constructor {
+ set s [file join $::script_path properties.tcl]
+ sys_gui "source {$s}\n"
+
+ pd::add_outlet $self float
+
+ # set defaults:
+ set @config [list]
+ lappend @config -uwidth 8
+ lappend @config -uheight 8
+ lappend @config -cellsize 16
+ lappend @config -label ""
+ lappend @config -labelpos "top"
+ lappend @config -sendsymbol ""
+ lappend @config -receivesymbol ""
+ lappend @config -fgcolor "#000000"
+ lappend @config -bgcolor "#ffffff"
+ lappend @config -lblcolor "#000000"
+ set @data {
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ }
+ # expanded ($n) send/recv symbols:
+ set @send {}
+ set @recv {}
+
+ ::$self 0 config {*}$args
+
+ set @rcvLoadData {#bitmap}
+ pd_bind [tclpd_get_instance_pd $self] [gensym $@rcvLoadData]
+ }
+
+ destructor {
+ set pdself [tclpd_get_instance_pd $self]
+ if {$@rcvLoadData != {}} {
+ #should not happen!
+ pd_unbind $pdself [gensym $@rcvLoadData]
+ }
+ if {[dict get $@config -receivesymbol] != {}} {
+ pd_unbind $pdself $@recv
+ }
+ }
+
+ 0_config {
+ if {$args == {}} {
+ return $@config
+ } else {
+ set newconf [list]
+ set optlist [pd::strip_selectors $args]
+ set optlist [pd::strip_empty $optlist]
+ for {set i 0} {$i < [llength $optlist]} {} {
+ set k [lindex $optlist $i]
+ if {![dict exists $@config $k]} {
+ return -code error "unknown option '$k'"
+ }
+ incr i
+ set v [lindex $optlist $i]
+ if {[lsearch -exact {-uwidth -uheight -cellsize} $k] != -1} {
+ set v [expr {int($v)}]
+ }
+ dict set newconf $k $v
+ incr i
+ }
+ if {[dict get $@config -uwidth] != [dict get $newconf -uwidth] ||
+ [dict get $@config -uheight] != [dict get $newconf -uheight]} {
+ $self 0 resize {*}[pd::add_selectors [list \
+ [dict get $newconf -uwidth] \
+ [dict get $newconf -uheight] \
+ ]]
+ }
+ set ui 0
+ foreach opt {label labelpos cellsize fgcolor bgcolor lblcolor} {
+ set old [dict get $@config -$opt]
+ if {[dict exists $newconf -$opt]} {
+ set new [dict get $newconf -$opt]
+ if {$old != $new} {
+ dict set @config -$opt $new
+ set ui 1
+ }
+ }
+ }
+ foreach opt {sendsymbol receivesymbol} {
+ set old [dict get $@config -$opt]
+ if {[dict exists $newconf -$opt]} {
+ set new [dict get $newconf -$opt]
+ if {$old != $new} {
+ if {$opt == "receivesymbol"} {
+ set selfpd [tclpd_get_instance_pd $self]
+ if {$old != {}} {
+ pd_unbind $selfpd $@recv
+ }
+ if {$new != {}} {
+ set @recv [canvas_realizedollar \
+ [tclpd_get_glist $self] [gensym $new]]
+ pd_bind $selfpd $@recv
+ } else {
+ set @recv {}
+ }
+ }
+ dict set @config -$opt $new
+ }
+ }
+ }
+ if {$ui && [info exists @c]} {
+ sys_gui [list $@c delete $self]\n
+ sys_gui [list bitmap_draw_new $self \
+ $@c $@x $@y $@config $@data]\n
+ }
+ }
+ }
+
+ 0_resize {
+ set w [pd::arg 0 int]
+ set h [pd::arg 1 int]
+ set oldw [dict get $@config -uwidth]
+ set oldh [dict get $@config -uheight]
+ set newd {}
+ for {set y 0} {$y < $h} {incr y} {
+ for {set x 0} {$x < $w} {incr x} {
+ if {$x < $oldw && $y < $oldh} {
+ lappend newd [lindex $@data [expr {$y*$oldw+$x}]]
+ } else {
+ lappend newd 0
+ }
+ }
+ }
+ dict set @config -uwidth $w
+ dict set @config -uheight $h
+ set @data $newd
+ }
+
+ 0_getrow {
+ set r [list]
+ set n [pd::arg 0 int]
+ set w [dict get $@config -uwidth]
+ for {set i [expr {$n*$w}]} {$i < [expr {($n+1)*$w}]} {incr i} {
+ lappend r [list float [lindex $@data $i]]
+ }
+ pd::outlet $self 0 list $r
+ }
+
+ 0_getcol {
+ set r [list]
+ set n [pd::arg 0 int]
+ set w [dict get $@config -uwidth]
+ set h [dict get $@config -uheight]
+ for {set i [expr {$n}]} {$i < [expr {$w*$h}]} {incr i $w} {
+ lappend r [list float [lindex $@data $i]]
+ }
+ pd::outlet $self 0 list $r
+ }
+
+ 0_getcell {
+ set r [pd::arg 0 int]
+ set c [pd::arg 1 int]
+ set w [dict get $@config -uwidth]
+ pd::outlet $self 0 float [lindex $@data [expr {$r*$w+$c}]]
+ }
+
+ 0_setrow {
+ set row [pd::arg 0 int]
+ set z 1
+ set col 0
+ set w [dict get $@config -uwidth]
+ set fgcolor [dict get $@config -fgcolor]
+ set bgcolor [dict get $@config -bgcolor]
+ set colors [list $bgcolor $fgcolor]
+ for {set idx [expr {$row*$w}]} {$idx < [expr {($row+1)*$w}]} {incr idx} {
+ set d [expr {0!=[pd::arg $z int]}]
+ lset @data $idx $d
+ sys_gui [list $@c itemconfigure cell_${col}_${row}_$self \
+ -fill [lindex $colors $d]]\n
+ incr z
+ incr col
+ }
+ }
+
+ 0_setcol {
+ set col [pd::arg 0 int]
+ set z 1
+ set row 0
+ set w [dict get $@config -uwidth]
+ set h [dict get $@config -uheight]
+ set fgcolor [dict get $@config -fgcolor]
+ set bgcolor [dict get $@config -bgcolor]
+ set colors [list $bgcolor $fgcolor]
+ for {set idx [expr {$col}]} {$idx < [expr {$w*$h}]} {incr idx $w} {
+ set d [expr {0!=[pd::arg $z int]}]
+ lset @data $idx $d
+ sys_gui [list $@c itemconfigure cell_${col}_${row}_$self \
+ -fill [lindex $colors $d]]\n
+ incr z
+ incr row
+ }
+ }
+
+ 0_setcell {
+ set r [pd::arg 0 int]
+ set c [pd::arg 1 int]
+ set d [expr {0!=[pd::arg 2 int]}]
+ set w [dict get $@config -uwidth]
+ set fgcolor [dict get $@config -fgcolor]
+ set bgcolor [dict get $@config -bgcolor]
+ set colors [list $bgcolor $fgcolor]
+ set idx [expr {$r*$w+$c}]
+ lset @data $idx $d
+ sys_gui [list $@c itemconfigure cell_${r}_${c}_$self \
+ -fill [lindex $colors $d]]\n
+ }
+
+ 0_setdata {
+ set d [pd::strip_selectors $args]
+ set l [llength $d]
+ set w [dict get $@config -uwidth]
+ set h [dict get $@config -uheight]
+ if {$l != $w*$h} {
+ return -code error "bad data size"
+ }
+ set @data [list]
+ foreach i $d {lappend @data [expr {int($i)}]}
+ if {$@rcvLoadData != {}} {
+ pd_unbind [tclpd_get_instance_pd $self] [gensym $@rcvLoadData]
+ set @rcvLoadData {}
+ }
+ }
+
+ object_save {
+ return [list #X obj $@x $@y bitmap {*}[pd::add_empty $@config] \; \
+ \#bitmap setdata {*}$@data \; ]
+ }
+
+ object_properties {
+ set title "\[bitmap\] properties"
+ set x_xobj_obpd [tclpd_get_object_pd $self]
+ set x [tclpd_get_instance $self]
+ set buf [list propertieswindow %s $@config $title]\n
+ gfxstub_new $x_xobj_obpd $x $buf
+ }
+
+ widgetbehavior_getrect {
+ lassign $args x1 y1
+ set w [dict get $@config -uwidth]
+ set h [dict get $@config -uheight]
+ set sz [dict get $@config -cellsize]
+ set x2 [expr {1+$x1+$w*$sz}]
+ set y2 [expr {1+$y1+$h*$sz}]
+ return [list $x1 $y1 $x2 $y2]
+ }
+
+ widgetbehavior_displace {
+ set dx [lindex $args 0]
+ set dy [lindex $args 1]
+ if {$dx != 0 || $dy != 0} {
+ incr @x $dx
+ incr @y $dy
+ sys_gui [list $@c move $self $dx $dy]\n
+ }
+ return [list $@x $@y]
+ }
+
+ widgetbehavior_select {
+ set sel [lindex $args 0]
+ set fgcolor [dict get $@config -fgcolor]
+ set bgcolor [dict get $@config -bgcolor]
+ set selcolor "blue"
+ set colors [list $selcolor $fgcolor]
+ sys_gui [list $@c itemconfigure $self \
+ -outline [lindex $colors $sel]]\n
+ }
+
+ widgetbehavior_activate {
+ }
+
+ widgetbehavior_vis {
+ set @c [lindex $args 0]
+ set @x [lindex $args 1]
+ set @y [lindex $args 2]
+ set vis [lindex $args 3]
+ set w [dict get $@config -uwidth]
+ set h [dict get $@config -uheight]
+ set sz [dict get $@config -cellsize]
+ if {$vis} {
+ sys_gui [list bitmap_draw_new $self $@c $@x $@y $@config $@data]\n
+ } else {
+ sys_gui [list $@c delete $self]\n
+ }
+ }
+
+ widgetbehavior_click {
+ set w [dict get $@config -uwidth]
+ set h [dict get $@config -uheight]
+ set sz [dict get $@config -cellsize]
+ set fgcolor [dict get $@config -fgcolor]
+ set bgcolor [dict get $@config -bgcolor]
+ set colors [list $bgcolor $fgcolor]
+ set xpix [expr {[lindex $args 0]-$@x-1}]
+ set ypix [expr {[lindex $args 1]-$@y-1}]
+ if {$xpix < 0 || $xpix >= $w*$sz} {return}
+ if {$ypix < 0 || $ypix >= $h*$sz} {return}
+ set shift [lindex $args 2]
+ set alt [lindex $args 3]
+ set dbl [lindex $args 4]
+ set doit [lindex $args 5]
+ if {$doit} {
+ set j [expr {$xpix/$sz}]
+ set i [expr {$ypix/$sz}]
+ set idx [expr {$w*${i}+${j}}]
+ set d [expr {[lindex $@data $idx]==0}]
+ lset @data $idx $d
+ sys_gui [list $@c itemconfigure cell_${j}_${i}_$self \
+ -fill [lindex $colors $d]]\n
+ }
+ }
+}
diff --git a/examples/colorpicker.tcl b/examples/colorpicker.tcl
new file mode 100644
index 0000000..0c433cb
--- /dev/null
+++ b/examples/colorpicker.tcl
@@ -0,0 +1,281 @@
+if {[info exists ::colorpicker::version]} {return}
+namespace eval ::colorpicker {
+ namespace export colorpicker
+ # =========================================
+ # colorpicker
+ set version 0.1
+ # (C) 2009 - Federico Ferri
+ # mescalinum (at) gmail (dot) com
+ #
+ # Released under GPL-3 license:
+ # http://www.gnu.org/licenses/gpl-3.0.html
+ # =========================================
+ package provide colorpicker $version
+
+ variable presets {
+ ffffff dfdfdf bbbbbb ffc7c6 ffe3c6
+ feffc6 c6ffc7 c6feff c7c6ff e3c6ff
+ 9f9f9f 7c7c7c 606060 ff0400 ff8300
+ faff00 00ff04 00faff 0400ff 9c00ff
+ 404040 202020 000000 551312 553512
+ 535512 0f4710 0e4345 131255 2f004d
+ }
+
+ proc colorpicker {w mode args} {
+ variable {}
+ set modes {switches hsv}
+ if {[lsearch -exact $modes $mode] == -1} {
+ error "bad mode: $mode. must be one of: $modes."
+ }
+ set ($w:mode) $mode
+ set ($w:color) "#000000"
+ set ($w:command) {}
+ set ($w:textvar) {}
+ frame $w
+ init_$mode $w
+ rename $w ::colorpicker::_$w
+ interp alias {} $w {} ::colorpicker::dispatch $w
+ if {$args != {}} {uplevel 1 ::colorpicker::config $w $args}
+ return $w
+ }
+
+ proc dispatch {w cmd args} {
+ variable {}
+ switch -glob -- $cmd {
+ get {set ($w:color)}
+ set {uplevel 1 [linsert $args 0 ::colorpicker::set_color_ext $w]}
+ con* {uplevel 1 [linsert $args 0 ::colorpicker::config $w]}
+ default {uplevel 1 [linsert $args 0 ::colorpicker::_$w $cmd]}
+ }
+ }
+
+ proc config {w args} {
+ variable {}
+ set options {}
+ set flag 0
+ foreach {key value} $args {
+ switch -glob -- $key {
+ -com* {
+ set ($w:command) $value
+ set flag 1
+ }
+ -textvar* {
+ set ($w:textvar) $value
+ set flag 1
+ }
+ default { lappend options $key $value }
+ }
+ }
+ if {!$flag || $options != ""} {
+ uplevel 1 [linsert $options 0 ::scrolledframe::_$w config]
+ }
+ }
+
+ proc set_color_ext {w c} {
+ # called by the widget public method
+ variable {}
+ set c [string tolower $c]
+ if {![regexp {^#[0-9a-f]{6,6}$} $c]} {
+ error "Invalid color: $c. Specify a color in the format #HHHHHH"
+ }
+ switch -exact -- $($w:mode) {
+ switches {
+ set_color $w $c
+ }
+ hsv {
+ set r [expr 0x[string range $c 1 2]]
+ set g [expr 0x[string range $c 3 4]]
+ set b [expr 0x[string range $c 5 6]]
+ set hsv [rgbToHsv $r $g $b]
+ hsv_set $w h [lindex $hsv 0]
+ hsv_set $w s [lindex $hsv 1]
+ hsv_set $w v [lindex $hsv 2]
+ set_color $w $c
+ }
+ }
+ }
+
+ proc set_color {w c} {
+ # called internally in reaction to events
+ variable {}
+ set c [string tolower $c]
+ set ($w:color) $c
+ if {$($w:command) != {}} {
+ set cmd $($w:command)
+ lappend cmd $c
+ uplevel #0 $cmd
+ }
+ if {$($w:textvar) != {}} {
+ uplevel #0 [list set $($w:textvar) $c]
+ }
+ switch -exact -- $($w:mode) {
+ switches {
+ variable presets
+ set q 0
+ for {set row 0} {$row < 3} {incr row} {
+ for {set col 0} {$col < 10} {incr col} {
+ set b [expr {$c == "#[lindex $presets $q]"}]
+ ${w}.r${row}c${col} configure \
+ -relief [lindex {raised sunken} $b]
+ incr q
+ }
+ }
+ }
+ hsv {
+ }
+ }
+ }
+
+ proc mkColor {rgb} {
+ set r [lindex $rgb 0]; set g [lindex $rgb 1]; set b [lindex $rgb 2]
+ if {$r < 0} {set r 0} elseif {$r > 255} {set r 255}
+ if {$g < 0} {set g 0} elseif {$g > 255} {set g 255}
+ if {$b < 0} {set b 0} elseif {$b > 255} {set b 255}
+ return #[format "%2.2x%2.2x%2.2x" $r $g $b]
+ }
+
+ proc rgbToHsv {r g b} {
+ set sorted [lsort -real [list $r $g $b]]
+ set temp [lindex $sorted 0]
+ set v [lindex $sorted 2]
+ set value $v
+ set bottom [expr {$v-$temp}]
+ if {$bottom == 0} {
+ set hue 0
+ set saturation 0
+ set value $v
+ } else {
+ if {$v == $r} {
+ set top [expr {$g-$b}]
+ if {$g >= $b} {
+ set angle 0
+ } else {
+ set angle 360
+ }
+ } elseif {$v == $g} {
+ set top [expr {$b-$r}]
+ set angle 120
+ } elseif {$v == $b} {
+ set top [expr {$r-$g}]
+ set angle 240
+ }
+ set hue [expr {round(60*(double($top)/$bottom)+$angle)}]
+ }
+ if {$v == 0} {
+ set saturation 0
+ } else {
+ set saturation [expr {round(255-255*(double($temp)/$v))}]
+ }
+ return [list $hue $saturation $value]
+ }
+
+ proc hsvToRgb {h s v} {
+ set hi [expr {int(double($h)/60)%6}]
+ set f [expr {double($h)/60-$hi}]
+ set s [expr {double($s)/255}]
+ set v [expr {double($v)/255}]
+ set p [expr {double($v)*(1-$s)}]
+ set q [expr {double($v)*(1-$f*$s)}]
+ set t [expr {double($v)*(1-(1-$f)*$s)}]
+ switch -- $hi {
+ 0 {set r $v; set g $t; set b $p}
+ 1 {set r $q; set g $v; set b $p}
+ 2 {set r $p; set g $v; set b $t}
+ 3 {set r $p; set g $q; set b $v}
+ 4 {set r $t; set g $p; set b $v}
+ 5 {set r $v; set g $p; set b $q}
+ default {error "[lindex [info level 0] 0]: bad H value"}
+ }
+ set r [expr {round($r*255)}]
+ set g [expr {round($g*255)}]
+ set b [expr {round($b*255)}]
+ return [list $r $g $b]
+ }
+
+ proc init_switches {w} {
+ variable {}
+ variable presets
+ set q 0
+ for {set row 0} {$row < 3} {incr row} {
+ for {set col 0} {$col < 10} {incr col} {
+ set c "#[lindex $presets $q]"
+ set b [expr {$($w:color) == $c}]
+ grid [frame ${w}.r${row}c${col} -width 18 -height 16 \
+ -borderwidth 1 -relief [lindex {raised sunken} $b] \
+ -background $c -highlightthickness 0] \
+ -row $row -column $col
+ bind ${w}.r${row}c${col} <ButtonPress-1> \
+ "[namespace current]::set_color $w $c"
+ incr q
+ }
+ }
+ }
+
+ proc init_hsv {w} {
+ variable colorhsv
+ set colorhsv($w:h) 0
+ set colorhsv($w:s) 255
+ set colorhsv($w:v) 255
+ grid [canvas ${w}.hue -width 130 -height 15 -borderwidth 1 \
+ -relief sunken -highlightthickness 0] -column 0 -row 0
+ grid [canvas ${w}.sat -width 130 -height 14 -borderwidth 1 \
+ -relief sunken -highlightthickness 0] -column 0 -row 1
+ grid [canvas ${w}.val -width 130 -height 14 -borderwidth 1 \
+ -relief sunken -highlightthickness 0] -column 0 -row 2
+ grid [canvas ${w}.test -width 46 -height 46 -borderwidth 1 \
+ -relief sunken -highlightthickness 0 -background red] \
+ -column 1 -row 0 -rowspan 3
+ variable mh
+ variable ms
+ variable mv
+ set mh($w) 0; set ms($w) 0; set mv($w) 0;
+ set sh "[namespace current]::hsv_set $w h \[expr {%x*360.0/130.0}\]"
+ set ss "[namespace current]::hsv_set $w s \[expr {%x*255.0/130.0}\]"
+ set sv "[namespace current]::hsv_set $w v \[expr {%x*255.0/130.0}\]"
+ bind ${w}.hue <ButtonPress-1> "set [namespace current]::mh($w) 1; $sh"
+ bind ${w}.sat <ButtonPress-1> "set [namespace current]::ms($w) 1; $ss"
+ bind ${w}.val <ButtonPress-1> "set [namespace current]::mv($w) 1; $sv"
+ bind ${w}.hue <ButtonRelease-1> "set [namespace current]::mh($w) 0"
+ bind ${w}.sat <ButtonRelease-1> "set [namespace current]::ms($w) 0"
+ bind ${w}.val <ButtonRelease-1> "set [namespace current]::mv($w) 0"
+ bind ${w}.hue <Motion> "if {\$[namespace current]::mh($w)} {$sh}"
+ bind ${w}.sat <Motion> "if {\$[namespace current]::ms($w)} {$ss}"
+ bind ${w}.val <Motion> "if {\$[namespace current]::mv($w)} {$sv}"
+ for {set x 0} {$x < 130} {incr x 3} {
+ set c [mkColor [hsvToRgb [expr {$x*360.0/130.0}] 255 255]]
+ ${w}.hue create rectangle $x 0 [expr {4+$x}] 16 -fill $c -outline {}
+ }
+ hsv_regen $w $colorhsv($w:h)
+ }
+
+ proc hsv_regen {w hue} {
+ ${w}.sat delete all
+ ${w}.val delete all
+ for {set x 0} {$x < 130} {incr x 3} {
+ set x1 [expr {$x*255.0/130.0}]
+ set c1 [mkColor [hsvToRgb $hue $x1 255]]
+ set c2 [mkColor [hsvToRgb $hue 255 $x1]]
+ ${w}.sat create rectangle $x 0 [expr {4+$x}] 16 \
+ -fill $c1 -outline {}
+ ${w}.val create rectangle $x 0 [expr {4+$x}] 16 \
+ -fill $c2 -outline {}
+ }
+ }
+
+ proc hsv_set {w what val} {
+ variable colorhsv
+ if {$what != {h} && $what != {s} && $what != {v}} {return}
+ set colorhsv($w:$what) $val
+ if {$colorhsv($w:$what) < 0.0} {set colorhsv($w:$what) 0}
+ if {$what == {h}} {
+ if {$colorhsv($w:$what) >= 360.0} {set colorhsv($w:$what) 0}
+ hsv_regen $w $colorhsv($w:$what)
+ } else {
+ if {$colorhsv($w:$what) > 255.0} {set colorhsv($w:$what) 255}
+ }
+ set c [mkColor [hsvToRgb \
+ $colorhsv($w:h) $colorhsv($w:s) $colorhsv($w:v)]]
+ ${w}.test configure -background $c
+ set_color $w $c
+ }
+}
diff --git a/examples/dynreceive-help.pd b/examples/dynreceive-help.pd
new file mode 100644
index 0000000..88a5568
--- /dev/null
+++ b/examples/dynreceive-help.pd
@@ -0,0 +1,22 @@
+#N canvas 416 120 513 409 10;
+#X obj 141 168 s \$0.foo;
+#X msg 46 120 bar baz;
+#X obj 60 320 dynreceive \$0.foo;
+#X floatatom 122 123 5 0 0 0 - - -;
+#X symbolatom 177 125 10 0 0 0 - - -;
+#X obj 267 125 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X text 43 86 1) send some symbols:;
+#X text 45 240 2) try to change the receive symbol:;
+#X msg 60 287 set xyz;
+#X msg 312 306 \; xyz 1 2 3;
+#X obj 60 350 print out;
+#X text 39 23 Works like [receive] \, but allows to dynamically set
+(or clear) the receive symbol.;
+#X text 139 288 <--;
+#X connect 1 0 0 0;
+#X connect 2 0 10 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 5 0 0 0;
+#X connect 8 0 2 0;
diff --git a/examples/dynreceive.tcl b/examples/dynreceive.tcl
new file mode 100644
index 0000000..8a269f7
--- /dev/null
+++ b/examples/dynreceive.tcl
@@ -0,0 +1,53 @@
+package require Tclpd 0.2.1
+package require TclpdLib 0.17
+
+pd::class dynreceive {
+ constructor {
+ set @sym {}
+ if {[pd::args] > 0} {
+ set @sym [pd::arg 0 symbol]
+ pd_bind [tclpd_get_instance_pd $self] [gensym $@sym]
+ }
+ pd::add_outlet $self
+ }
+
+ destructor {
+ # don't forget to call pd_unbind, or sending things to a symbol
+ # bound to dead object will crash pd!
+ if {$@sym != {}} {
+ pd_unbind [tclpd_get_instance_pd $self] [gensym $@sym]
+ }
+ }
+
+ 0_set {
+ # send [set empty( to clear the receive symbol
+ set s [pd::arg 0 symbol]
+ if {$@sym != {}} {
+ pd_unbind [tclpd_get_instance_pd $self] [gensym $@sym]
+ }
+ if {$s == {empty}} {
+ set @sym {}
+ } else {
+ set @sym $s
+ pd_bind [tclpd_get_instance_pd $self] [gensym $@sym]
+ }
+ }
+
+ 0_bang {
+ pd::outlet $self 0 bang
+ }
+
+ 0_float {
+ pd::outlet $self 0 float [pd::arg 0 float]
+ }
+
+ 0_symbol {
+ pd::outlet $self 0 symbol [gensym [pd::arg 0 symbol]]
+ }
+
+ 0_anything {
+ set sel [pd::arg 0 symbol]
+ set argz [lrange $args 1 end]
+ pd::outlet $self 0 $sel $argz
+ }
+}
diff --git a/examples/dynroute-help.pd b/examples/dynroute-help.pd
new file mode 100644
index 0000000..86d173e
--- /dev/null
+++ b/examples/dynroute-help.pd
@@ -0,0 +1,26 @@
+#N canvas 1022 530 786 430 10;
+#X obj 93 268 dynroute 4;
+#X msg 41 147 apple red \, banana yellow \, pear green \, apple yellow
+\, strawberry red;
+#X obj 41 194 list prepend;
+#X msg 200 224 clear \, add apple 0 \, add banana 1 \, add pear 2;
+#X msg 206 258 remove pear 2 \, add pear 0 \, add strawberry 2;
+#X text 39 32 Dynamically route lists based on first element \, according
+to the mapping specified on right inlet. Creation argument (float)
+specifies how many outlet to have (including last outlet \, which is
+used for sending unmatching items);
+#X text 44 120 Test it with some data:;
+#X obj 93 379 print out1;
+#X obj 115 352 print out2;
+#X obj 137 325 print out3;
+#X obj 160 298 print other;
+#X text 256 293 <-- non-matching stuff is sent here;
+#X text 196 192 Change the mapping:;
+#X connect 0 0 7 0;
+#X connect 0 1 8 0;
+#X connect 0 2 9 0;
+#X connect 0 3 10 0;
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 1;
+#X connect 4 0 0 1;
diff --git a/examples/dynroute.tcl b/examples/dynroute.tcl
new file mode 100644
index 0000000..2309ac7
--- /dev/null
+++ b/examples/dynroute.tcl
@@ -0,0 +1,57 @@
+package require Tclpd 0.2.1
+package require TclpdLib 0.17
+
+# dynroute: dynamically route messages based on first element
+# non-matching arguments are sent to last inlet
+# constructor: <float> specify the number of outlets (default: 1)
+# send commands to the right inlet
+# available commands:
+# add <atom> <float> route selector <atom> to output number <float>
+# remove <atom> <float> remove previously created routing
+# clear
+
+pd::class dynroute {
+ constructor {
+ pd::add_inlet $self list
+
+ set @num_outlets [pd::arg 0 int]
+ if {$@num_outlets < 0} {set @num_outlets 2}
+
+ for {set i 0} {$i < $@num_outlets} {incr i} {
+ pd::add_outlet $self list
+ }
+
+ set @routing {}
+ }
+
+ 0_list {
+ set sel [pd::arg 0 any]
+ set out [expr {$@num_outlets-1}]
+ catch {set out [dict get $@routing $sel]}
+ pd::outlet $self $out list $args
+ }
+
+ 1_add {
+ set sel [pd::arg 0 any]
+ set out [pd::arg 1 int]
+ if {$out < 0 || $out >= $@num_outlets} {
+ pd::post "error: add: outlet number out of range"
+ return
+ }
+ dict set @routing $sel $out
+ }
+
+ 1_remove {
+ set sel [pd::arg 0 any]
+ set out [pd::arg 1 int]
+ if {$out < 0 || $out >= $@num_outlets} {
+ pd::post "error: add: outlet number out of range"
+ return
+ }
+ catch {dict unset @routing $sel $out}
+ }
+
+ 1_clear {
+ set @routing {}
+ }
+}
diff --git a/examples/list_change-help.pd b/examples/list_change-help.pd
new file mode 100644
index 0000000..430b23d
--- /dev/null
+++ b/examples/list_change-help.pd
@@ -0,0 +1,21 @@
+#N canvas 617 384 635 406 10;
+#X obj 54 240 list_change;
+#X text 144 236 right inlet sets internal value without output anything
+;
+#X obj 71 271 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 54 309 print;
+#X text 33 21 Outputs its input (a list) only when it changes. You
+can set the current value using the right inlet \, or bang to force
+output;
+#X msg 117 201 list foo bar;
+#X msg 69 140 list foo bar;
+#X msg 77 163 list bar baz;
+#X msg 54 104 bang;
+#X text 98 103 output current value;
+#X connect 0 0 2 0;
+#X connect 0 0 3 0;
+#X connect 5 0 0 1;
+#X connect 6 0 0 0;
+#X connect 7 0 0 0;
+#X connect 8 0 0 0;
diff --git a/examples/list_change.tcl b/examples/list_change.tcl
new file mode 100644
index 0000000..2c70937
--- /dev/null
+++ b/examples/list_change.tcl
@@ -0,0 +1,31 @@
+package require Tclpd 0.2.1
+package require TclpdLib 0.17
+
+pd::class list_change {
+ constructor {
+ # add second inlet (first created by default)
+ pd::add_inlet $self list
+
+ # add outlet
+ pd::add_outlet $self list
+
+ set @curlist {}
+ }
+
+ 0_list {
+ # HOT inlet
+ if {$args != $@curlist} {
+ set @curlist $args
+ pd::outlet $self 0 list $@curlist
+ }
+ }
+
+ 0_bang {
+ pd::outlet $self 0 list $@curlist
+ }
+
+ 1_list {
+ # COLD inlet
+ set @curlist $args
+ }
+}
diff --git a/examples/properties.tcl b/examples/properties.tcl
new file mode 100644
index 0000000..d225d74
--- /dev/null
+++ b/examples/properties.tcl
@@ -0,0 +1,423 @@
+if {[catch {package require colorpicker}]} {
+ source [file join [file dirname [info script]] colorpicker.tcl]
+ package require colorpicker
+}
+namespace import ::colorpicker::colorpicker
+
+proc propertieswindow {gfxstub_id {options {}} {title {}}} {
+ set win $gfxstub_id
+ set ::id($win.p) $gfxstub_id
+ set ::optkeys($win.p) [list]
+ foreach {k v} $options {
+ set ::config($win.p:$k) $v
+ lappend ::optkeys($win.p) $k
+ }
+ toplevel $win
+ pack [propertiespanel $win.p]
+ wm resizable $win 0 0
+ wm title $win $title
+ set win
+}
+
+proc has_key {w key} {
+ expr {[lsearch -exact $::optkeys($w) $key] != -1}
+}
+
+proc propertiespanel {w} {
+ set pad [propertiespanel_padding $w]
+ incr pad $pad
+ frame $w -borderwidth 0 -relief raised -padx $pad -pady $pad
+ set subpanels {dimensions output behavior connective label colors}
+ foreach subpanel $subpanels {
+ set x [propertiespanel_$subpanel $w]
+ if {$x != {}} {grid $x -sticky ew -in $w}
+ }
+ set x [propertiespanel_buttons $w]
+ grid $x -in $w
+ grid columnconfigure . 0 -weight 1
+ set w
+}
+
+proc propertiespanel_padding {w} {
+ return 3
+}
+
+proc propertiespanel_dimensions {w} {
+ set x ${w}.dimensions
+ set pad [propertiespanel_padding $w]
+ labelframe $x -text "Dimensions:" -borderwidth 1 -relief raised
+ set count 0
+ set row 0; set col 0
+ if {[has_key $w -width]} {
+ grid [label ${x}.wl -text "Width (px):" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.w -textvar ::config($w:-width) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ if {[has_key $w -height]} {
+ grid [label ${x}.hl -text "Height (px):" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.h -textvar ::config($w:-height) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ incr row; set col 0
+ if {[has_key $w -uwidth]} {
+ grid [label ${x}.uwl -text "Width (cells):" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.uw -textvar ::config($w:-uwidth) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ if {[has_key $w -uheight]} {
+ grid [label ${x}.uhl -text "Height (cells):" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.uh -textvar ::config($w:-uheight) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ incr row; set col 0
+ if {[has_key $w -cellsize]} {
+ grid [label ${x}.csl -text "Cell size (pixels):" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.cs -textvar ::config($w:-cellsize) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ incr row; set col 0
+ if {[has_key $w -cellwidth]} {
+ grid [label ${x}.uwl -text "Cell width:" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.uw -textvar ::config($w:-cellwidth) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ if {[has_key $w -cellheight]} {
+ grid [label ${x}.uhl -text "Cell height:" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.uh -textvar ::config($w:-cellheight) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ incr row; set col 0
+ if {$count == 0} {return {}}
+ set x
+}
+
+proc propertiespanel_output {w} {
+ set x ${w}.output
+ set pad [propertiespanel_padding $w]
+ labelframe $x -text "Output range:" -borderwidth 1 -relief raised
+ set count 0
+ set row 0; set col 0
+ if {[has_key $w -rangebottom]} {
+ grid [label ${x}.rbl -text "Bottom:" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.rb -textvar ::config($w:-rangebottom) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ if {[has_key $w -rangetop]} {
+ grid [label ${x}.rtl -text "Top:" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.rt -textvar ::config($w:-rangetop) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ incr row; set col 0
+ if {[has_key $w -rangeleft]} {
+ grid [label ${x}.rll -text "Left:" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.rl -textvar ::config($w:-rangeleft) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ if {[has_key $w -rangeright]} {
+ grid [label ${x}.rrl -text "Right:" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.rr -textvar ::config($w:-rangeright) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ incr row; set col 0
+ if {[has_key $w -rangemin]} {
+ grid [label ${x}.rml -text "Min:" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.rm -textvar ::config($w:-rangemin) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ if {[has_key $w -rangemax]} {
+ grid [label ${x}.rMl -text "Max:" -anchor e] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ grid [entry ${x}.rM -textvar ::config($w:-rangemax) -width 5] \
+ -row $row -column $col -sticky ew -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ incr row; set col 0
+ if {[has_key $w -logarithmic]} {
+ incr col
+ grid [checkbutton ${x}.rL -variable ::config($w:-logarithmic) \
+ -text "Logarithmic"] \
+ -row $row -column $col -columnspan 3 -sticky w -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ incr row; set col 0
+ if {$count == 0} {return {}}
+ set x
+}
+
+proc propertiespanel_behavior {w} {
+ set x ${w}.behavior
+ set pad [propertiespanel_padding $w]
+ labelframe $x -text "Widget behavior:" -borderwidth 1 -relief raised
+ set count 0
+ set row 0; set col 0
+ if {[has_key $w -jumponclick]} {
+ grid [checkbutton ${x}.joc -variable ::config($w:-jumponclick) \
+ -text "Jump on click"] \
+ -row $row -column $col -sticky w -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ if {[has_key $w -init]} {
+ grid [checkbutton ${x}.init -variable ::config($w:-init) \
+ -text "Output init value"] \
+ -row $row -column $col -sticky w -padx $pad -pady $pad
+ incr col
+ incr count
+ }
+ incr row; set col 0
+ if {$count == 0} {return {}}
+ set x
+}
+
+proc propertiespanel_label {w} {
+ set x ${w}.label
+ set pad [propertiespanel_padding $w]
+ labelframe $x -text "Label:" -borderwidth 1 -relief raised
+ set count 0
+ set row 0
+ if {[has_key $w -label]} {
+ grid [label ${x}.ll -text "Text:" -anchor e] \
+ -row $row -column 0 -sticky ew -padx $pad -pady $pad
+ grid [entry ${x}.l -textvar ::config($w:-label)] \
+ -row $row -column 1 -sticky ew -padx $pad -pady $pad
+ incr row
+ incr count
+ }
+ if {[has_key $w -labelpos]} {
+ grid [label ${x}.lpl -text "Position:" -anchor e] \
+ -row $row -column 0 -sticky ew -padx $pad -pady $pad
+ frame ${x}.f
+ if {![info exists ::config($w:-labelpos)]} {
+ set ::config($w:-labelpos) top
+ }
+ grid [radiobutton ${x}.f.lp1 -variable ::config($w:-labelpos) \
+ -value top -text Top] \
+ -row 1 -column 1 -sticky w -padx $pad -pady $pad -in ${x}.f
+ grid [radiobutton ${x}.f.lp2 -variable ::config($w:-labelpos) \
+ -value bottom -text Bottom] \
+ -row 1 -column 2 -sticky w -padx $pad -pady $pad -in ${x}.f
+ grid [radiobutton ${x}.f.lp3 -variable ::config($w:-labelpos) \
+ -value left -text Left] \
+ -row 2 -column 1 -sticky w -padx $pad -pady $pad -in ${x}.f
+ grid [radiobutton ${x}.f.lp4 -variable ::config($w:-labelpos) \
+ -value right -text Right] \
+ -row 2 -column 2 -sticky w -padx $pad -pady $pad -in ${x}.f
+ grid ${x}.f -sticky w -row $row -column 1
+ incr row
+ incr count
+ }
+ if {$count == 0} {return {}}
+ set x
+}
+
+proc propertiespanel_connective {w} {
+ set x ${w}.connective
+ set pad [propertiespanel_padding $w]
+ labelframe $x -text "Messages:" -borderwidth 1 -relief raised
+ set count 0
+ set row 0
+ if {[has_key $w -sendsymbol]} {
+ grid [label ${x}.ssl -text "Send symbol:" -anchor e] \
+ -row $row -column 0 -sticky ew -padx $pad -pady $pad
+ grid [entry ${x}.ss -textvar ::config($w:-sendsymbol) -width 15] \
+ -row $row -column 1 -sticky ew -padx $pad -pady $pad
+ incr row
+ incr count
+ }
+ if {[has_key $w -receivesymbol]} {
+ grid [label ${x}.rsl -text "Receive symbol:" -anchor e] \
+ -row $row -column 0 -sticky ew -padx $pad -pady $pad
+ grid [entry ${x}.rs -textvar ::config($w:-receivesymbol) -width 15] \
+ -row $row -column 1 -sticky ew -padx $pad -pady $pad
+ incr row
+ incr count
+ }
+ if {$count == 0} {return {}}
+ set x
+}
+
+proc propertiespanel_colors {w} {
+ set colors {-bgcolor Background -fgcolor Foreground -lblcolor Label}
+ set x ${w}.colors
+ set pad [propertiespanel_padding $w]
+ labelframe $x -text "Colors:" -borderwidth 1 -relief raised
+ set count 0
+ set row 0
+ foreach {optkey color} $colors {
+ if {![has_key $w $optkey]} {continue}
+ grid [label ${x}.l$color -text "${color}:" -anchor e] \
+ -row $row -column 0 -sticky ew -padx $pad -pady $pad
+ grid [entry ${x}.t$color -textvar ::config($w:$optkey) -width 8] \
+ -row $row -column 1 -sticky ew -padx $pad -pady $pad
+ grid [frame ${x}.p$color -width 20 -height 20 \
+ -borderwidth 1 -relief sunken] \
+ -row $row -column 2 -sticky ew -padx $pad -pady $pad
+ grid [button ${x}.b$color -text "Pick..." -overrelief {} \
+ -command {} \
+ ] -row $row -column 3 -sticky ew -padx $pad -pady $pad
+ bind ${x}.b$color <Enter> {break}
+ bind ${x}.b$color <Leave> {break}
+ bind ${x}.b$color <ButtonPress-1> [list \
+ propertiespanel_colors_pick \
+ $w $x $colors ${x}.b$color ${x}.p$color ${x}.t$color]
+ trace add variable ::config($w:$optkey) write [list \
+ propertiespanel_colors_set_wrap $w $x ${x}.p$color $optkey]
+ incr row
+ incr count
+ }
+ if {![info exists ::cpt($w)]} {set ::cpt($w) switches}
+ foreach {optkey color} $colors {
+ if {![has_key $w $optkey]} {continue}
+ # trigger the variable trace:
+ if {[info exists ::config($w:$optkey)]} {
+ set ::config($w:$optkey) $::config($w:$optkey)
+ }
+ }
+ if {$count == 0} {return {}}
+ frame ${x}.f
+ grid [radiobutton ${x}.f.cpt1 -variable ::cpt($w) -justify right \
+ -value switches -text Switches] \
+ -row 0 -column 0 -sticky ew -padx $pad -pady $pad
+ grid [radiobutton ${x}.f.cpt2 -variable ::cpt($w) -justify right \
+ -value hsv -text HSV] \
+ -row 1 -column 0 -sticky ew -padx $pad -pady $pad
+ grid ${x}.f -row $row -column 0
+ grid [colorpicker ${x}.cp2 hsv] \
+ -row $row -column 1 -columnspan 3 -sticky ew -padx $pad -pady $pad
+ grid [colorpicker ${x}.cp1 switches -command [list ${x}.cp2 set]] \
+ -row $row -column 1 -columnspan 3 -sticky ew -padx $pad -pady $pad
+ raise ${x}.cp1
+ trace add variable ::cpt($w) write \
+ [list propertiespanel_colors_switchpicker $w $x $row]
+ set x
+}
+
+proc propertiespanel_colors_set_wrap {w x wp optkey config_ idx op} {
+ propertiespanel_colors_set $w $x $wp {} -1 $::config($w:$optkey)
+}
+
+proc propertiespanel_colors_switchpicker {w x row cpt idx op} {
+ raise ${x}.cp[expr {1+($::cpt($w) == {hsv})}]
+}
+
+proc propertiespanel_colors_pick {w x colors wb wp wt} {
+ foreach {k color} $colors {
+ ${x}.b$color configure -relief raised -state normal
+ }
+ set r [$wb cget -relief]
+ if {$r == {sunken}} {
+ $wb configure -relief raised
+ ${x}.cp1 configure -command {}
+ ${x}.cp2 configure -command {}
+ } else {
+ $wb configure -relief sunken
+ ${x}.cp1 configure -command \
+ [list propertiespanel_colors_set $w $x $wp $wt 1]
+ ${x}.cp2 configure -command \
+ [list propertiespanel_colors_set $w $x $wp $wt 2]
+ }
+}
+
+proc propertiespanel_colors_set {w x wp wt from color} {
+ if {$wt != {}} {$wt delete 0 end ; $wt insert 0 $color}
+ $wp configure -background $color
+ if {$::cpt($w) == {switches} && $from == 1} {
+ ${x}.cp2 set $color
+ }
+}
+
+proc propertiespanel_buttons {w} {
+ set x ${w}.buttons
+ set pad [propertiespanel_padding $w]
+ frame $x -padx $pad -pady $pad
+ set col 0
+ foreach action {Cancel Apply Ok} {
+ grid [button ${x}.btn$action \
+ -command [list propertiespanel_buttons_action $w $action] \
+ -text $action] \
+ -row 0 -column $col -padx $pad -pady $pad
+ incr col
+ }
+ set x
+}
+
+proc propertiespanel_buttons_action {w action} {
+ switch -- $action {
+ Cancel {
+ propertiespanel_close $w
+ }
+ Apply {
+ propertiespanel_apply $w
+ }
+ Ok {
+ propertiespanel_apply $w
+ propertiespanel_close $w
+ }
+ }
+}
+
+proc propertiespanel_apply {w} {
+ set newconf [list]
+ foreach key $::optkeys($w) {
+ set v $::config($w:$key)
+ if {$v == ""} {set v "empty"}
+ lappend newconf $key $v
+ }
+ set newconf [string map {$ \\$} $newconf]
+ pd [linsert $newconf 0 $::id($w) config]\;
+}
+
+proc propertiespanel_close {w} {
+ pd [concat $::id($w) cancel \;]
+}
diff --git a/examples/slider2-help.pd b/examples/slider2-help.pd
new file mode 100644
index 0000000..1f36ace
--- /dev/null
+++ b/examples/slider2-help.pd
@@ -0,0 +1,51 @@
+#N canvas 79 235 731 505 10;
+#X obj 343 150 slider2 -width 15 -height 130 -headsz 3 -rangebottom
+0 -rangetop 127 -init 0 -initvalue 94 -jumponclick 0 -label norm -labelpos
+top -orient vertical -sendsymbol empty -receivesymbol empty -fgcolor
+#000000 -bgcolor #ffffff -lblcolor #000000;
+#X obj 401 150 slider2 -width 15 -height 130 -headsz 3 -rangebottom
+127 -rangetop 0 -init 0 -initvalue 63 -jumponclick 0 -label rev -labelpos
+top -orient vertical -sendsymbol empty -receivesymbol empty -fgcolor
+#000000 -bgcolor #ffffff -lblcolor #000000;
+#X obj 522 154 slider2 -width 130 -height 15 -headsz 3 -rangebottom
+0 -rangetop 127 -init 0 -initvalue 95 -jumponclick 0 -label norm -labelpos
+top -orient horizontal -sendsymbol empty -receivesymbol empty -fgcolor
+#000000 -bgcolor #ffffff -lblcolor #000000;
+#X obj 522 213 slider2 -width 130 -height 15 -headsz 3 -rangebottom
+127 -rangetop 0 -init 0 -initvalue 70 -jumponclick 0 -label rev -labelpos
+top -orient horizontal -sendsymbol empty -receivesymbol empty -fgcolor
+#000000 -bgcolor #ffffff -lblcolor #000000;
+#X floatatom 343 295 5 0 0 0 - - -;
+#X floatatom 401 295 5 0 0 0 - - -;
+#X floatatom 522 177 5 0 0 0 - - -;
+#X floatatom 522 236 5 0 0 0 - - -;
+#X text 324 109 -orient vertical;
+#X text 523 111 -orient horizontal;
+#X text 321 61 Output range test:;
+#X obj 46 174 slider2 -width 15 -height 130 -headsz 3 -rangebottom
+0 -rangetop 127 -init 0 -initvalue 10 -jumponclick 0 -label empty -labelpos
+top -orient vertical -sendsymbol empty -receivesymbol empty -fgcolor
+#000000 -bgcolor #ffffff -lblcolor #000000;
+#X msg 46 143 config -orient vertical;
+#X msg 46 113 config -orient horizontal;
+#X floatatom 46 321 5 0 0 0 - - -;
+#X obj 159 358 slider2 -width 130 -height 15 -headsz 3 -rangebottom
+0 -rangetop 255 -init 0 -initvalue 202.795 -jumponclick 0 -label empty
+-labelpos top -orient horizontal -sendsymbol \$0.sl-out -receivesymbol
+\$0.sl-in -fgcolor #000000 -bgcolor #20ca34 -lblcolor #000000;
+#X obj 45 358 r \$0.sl-out;
+#X obj 45 466 s \$0.sl-in;
+#X msg 45 439 config -bgcolor \$1;
+#X obj 45 412 makefilename #%6.6x;
+#X obj 45 385 expr (0x20 << 16) | ($f1 << 8) | (0xff - $f1);
+#X connect 0 0 4 0;
+#X connect 1 0 5 0;
+#X connect 2 0 6 0;
+#X connect 3 0 7 0;
+#X connect 11 0 14 0;
+#X connect 12 0 11 0;
+#X connect 13 0 11 0;
+#X connect 16 0 20 0;
+#X connect 18 0 17 0;
+#X connect 19 0 18 0;
+#X connect 20 0 19 0;
diff --git a/examples/slider2.tcl b/examples/slider2.tcl
new file mode 100644
index 0000000..ff4678a
--- /dev/null
+++ b/examples/slider2.tcl
@@ -0,0 +1,273 @@
+package require Tclpd 0.2.1
+package require TclpdLib 0.17
+
+set ::script_path [file dirname [info script]]
+
+pd::guiproc slider2_draw_new {self c x y config state} {
+ # import variables from dicts:
+ foreach v {headsz width height fgcolor bgcolor orient} \
+ {set $v [dict get $config -$v]}
+ set x2 [expr {$x+$width+1}]
+ set y2 [expr {$y+$height+1}]
+ $c create rectangle $x $y $x2 $y2 \
+ -outline $fgcolor -fill $bgcolor -tags [list $self border$self]
+ switch $orient {
+ horizontal {set y1 $y; set x3 [expr {$x+$headsz}]}
+ vertical {set y1 [expr {$y2-$headsz}]; set x3 $x2}
+ }
+ $c create rectangle $x $y1 $x3 $y2 -outline {} -fill $fgcolor \
+ -tags [list $self head$self]
+ slider2_update $self $c $x $y $config $state
+}
+
+pd::guiproc slider2_update {self c x y config state} {
+ # import variables from dicts:
+ foreach v {initvalue headsz width height label labelpos lblcolor orient} \
+ {set $v [dict get $config -$v]}
+ foreach v {min max rev} {set $v [dict get $state _$v]}
+ set realvalue [expr {1.0*($initvalue-$min)/($max-$min)}]
+ if {$realvalue < 0.0} {set realvalue 0}
+ if {$realvalue > 1.0} {set realvalue 1}
+ if {$rev} {set realvalue [expr {1.0-$realvalue}]}
+ if {$orient == "vertical"} {set realvalue [expr {1.0-$realvalue}]}
+ switch $orient {
+ horizontal {
+ set hr [expr {$width-$headsz}]
+ $c coords head$self [expr {$x+$hr*$realvalue}] $y \
+ [expr {$x+$hr*$realvalue+$headsz}] [expr {$y+$height+1}]
+ }
+ vertical {
+ set vr [expr {$height-$headsz}]
+ $c coords head$self $x [expr {$y+$vr*$realvalue}] \
+ [expr {$x+$width+1}] [expr {$y+$vr*$realvalue+$headsz}]
+ }
+ }
+ $c delete label$self
+ if {$label != {}} {
+ switch $labelpos {
+ top
+ {set lx [expr {$x+$width/2}]; set ly [expr {$y}]; set a "s"}
+ bottom
+ {set lx [expr {$x+$width/2}]; set ly [expr {$y+$height+2}]; set a "n"}
+ left
+ {set lx [expr {$x}]; set ly [expr {$y+$height/2}]; set a "e"}
+ right
+ {set lx [expr {$x+$width+2}]; set ly [expr {$y+$height/2}]; set a "w"}
+ }
+ $c create text $lx $ly -anchor $a -text $label -fill $lblcolor \
+ -tags [list $self label$self]
+ }
+}
+
+pd::guiclass slider2 {
+ constructor {
+ pd::add_outlet $self float
+ sys_gui "source {[file join $::script_path properties.tcl]}\n"
+ # set defaults:
+ set @config {
+ -width 15 -height 130 -headsz 3 -rangebottom 0 -rangetop 127
+ -init 0 -initvalue 0 -jumponclick 0 -label "" -labelpos "top"
+ -orient "vertical" -sendsymbol "" -receivesymbol ""
+ -fgcolor "#000000" -bgcolor "#ffffff" -lblcolor "#000000"
+ }
+ set @state {_min 0 _max 127 _rev 0}
+ # expanded ($n) send/recv symbols:
+ set @send {}
+ set @recv {}
+ ::$self 0 config {*}$args
+ }
+
+ destructor {
+ if {[dict get $@config -receivesymbol] != {}} {
+ pd_unbind [tclpd_get_instance_pd $self] $@recv
+ }
+ }
+
+ 0_loadbang {
+ if {[dict get $@config -init]} {$self 0 bang}
+ }
+
+ 0_config {
+ set newconf [list]
+ set optlist [pd::strip_selectors $args]
+ set optlist [pd::strip_empty $optlist]
+ set int_opts {-width -height -cellsize}
+ set bool_opts {-init -jumponclick}
+ set ui_opts {-fgcolor -bgcolor -lblcolor -orient -width -height}
+ set upd_opts {-rangebottom -rangetop -label -labelpos}
+ set conn_opts {-sendsymbol -receivesymbol}
+ set ui 0
+ set upd 0
+ foreach {k v} $optlist {
+ if {![dict exists $@config $k]} {
+ return -code error "unknown option '$k'"
+ }
+ if {[dict get $@config $k] == $v} {continue}
+ if {[lsearch -exact $int_opts $k] != -1} {set v [expr {int($v)}]}
+ if {[lsearch -exact $bool_opts $k] != -1} {set v [expr {int($v)!=0}]}
+ if {[lsearch -exact $ui_opts $k] != -1} {set ui 1}
+ if {[lsearch -exact $upd_opts $k] != -1} {set upd 1}
+ dict set newconf $k $v
+ }
+ # process -{send,receive}symbol
+ if {[dict exists $newconf -receivesymbol]} {
+ set new_recv [dict get $newconf -receivesymbol]
+ set selfpd [tclpd_get_instance_pd $self]
+ if {[dict get $@config -receivesymbol] != {}} {
+ pd_unbind $selfpd $@recv
+ }
+ if {$new_recv != {}} {
+ set @recv [canvas_realizedollar \
+ [tclpd_get_glist $self] [gensym $new_recv]]
+ pd_bind $selfpd $@recv
+ } else {set @recv {}}
+ }
+ if {[dict exists $newconf -sendsymbol]} {
+ set new_send [dict get $newconf -sendsymbol]
+ if {$new_send != {}} {
+ set @send [canvas_realizedollar \
+ [tclpd_get_glist $self] [gensym $new_send]]
+ } else {set @send {}}
+ }
+ # changing orient -> swap sizes
+ if {[dict exists $newconf -orient] && ![dict exists $newconf -width]
+ && ![dict exists $newconf -height]} {
+ dict set newconf -width [dict get $@config -height]
+ dict set newconf -height [dict get $@config -width]
+ }
+ # no errors up to this point. we can safely merge options
+ set @config [dict merge $@config $newconf]
+ # adjust reverse range
+ set a [dict get $@config -rangebottom]
+ set b [dict get $@config -rangetop]
+ dict set @state _min [expr {$a>$b?$b:$a}]
+ dict set @state _max [expr {$a>$b?$a:$b}]
+ dict set @state _rev [expr {$a>$b}]
+ set orient [dict get $@config -orient]
+ switch $orient {
+ horizontal {set dim [dict get $@config -width]; set mul 1}
+ vertical {set dim [dict get $@config -height]; set mul -1}
+ default {return -code error "invalid value '$orient' for -orient"}
+ }
+ # recompute pix2units conversion
+ set @pix2units [expr {(2.0 * [dict get $@state _rev] - 1.0) *
+ ( [dict get $@state _max] - [dict get $@state _min] ) *
+ $mul / ( $dim - [dict get $@config -headsz])}]
+ # if ui changed, update it
+ if {$ui && [info exists @c]} {
+ sys_gui [list $@c delete $self]\n
+ sys_gui [list slider2_draw_new $self $@c $@x $@y $@config $@state]\n
+ } elseif {$upd && [info exists @c]} {
+ sys_gui [list slider2_update $self $@c $@x $@y $@config $@state]\n
+ }
+ if {[dict exists $newconf -width] || [dict exists $newconf -height]} {
+ canvas_fixlinesfor \
+ [tclpd_get_glist $self] [tclpd_get_instance_text $self]
+ }
+ }
+
+ 0_set {
+ foreach v {min max} {set $v [dict get $@state _$v]}
+ set f [pd::arg 0 float]
+ if {$f < $min} {set f $min}
+ if {$f > $max} {set f $max}
+ dict set @config -initvalue $f
+ if {[info exists @c]} {
+ # update ui:
+ sys_gui [list slider2_update $self $@c $@x $@y $@config $@state]\n
+ }
+ }
+
+ 0_bang {
+ foreach v {initvalue} {set $v [dict get $@config -$v]}
+ pd::outlet $self 0 float $initvalue
+ if {$@send != {}} {
+ set s_thing [$@send cget -s_thing]
+ if {$s_thing != {NULL}} {pd_float $s_thing $initvalue}
+ }
+ }
+
+ 0_float {
+ $self 0 set {*}$args
+ $self 0 bang
+ }
+
+ object_save {
+ return [list #X obj $@x $@y slider2 {*}[pd::add_empty $@config] \;]
+ }
+
+ object_properties {
+ set c [string map {$ \\$} $@config]
+ gfxstub_new [tclpd_get_object_pd $self] [tclpd_get_instance $self] \
+ [list propertieswindow %s $c "\[slider2\] properties"]\n
+ }
+
+ widgetbehavior_getrect {
+ lassign $args x1 y1
+ set x2 [expr {1+$x1+[dict get $@config -width]}]
+ set y2 [expr {1+$y1+[dict get $@config -height]}]
+ return [list $x1 $y1 $x2 $y2]
+ }
+
+ widgetbehavior_displace {
+ lassign $args dx dy
+ if {$dx != 0 || $dy != 0} {
+ incr @x $dx; incr @y $dy
+ sys_gui [list $@c move $self $dx $dy]\n
+ }
+ return [list $@x $@y]
+ }
+
+ widgetbehavior_select {
+ lassign $args sel
+ sys_gui [list $@c itemconfigure $self&&!label$self -outline [lindex \
+ [list [dict get $@config -fgcolor] {blue}] $sel]]\n
+ }
+
+ widgetbehavior_vis {
+ lassign $args @c @x @y vis
+ if {$vis} {
+ sys_gui [list slider2_draw_new $self $@c $@x $@y $@config $@state]\n
+ } else {
+ sys_gui [list $@c delete $self]\n
+ }
+ }
+
+ widgetbehavior_click {
+ lassign $args x y shift alt dbl doit
+ set h [dict get $@config -height]
+ set ypix [expr {[lindex $args 1]-$@y-1}]
+ if {$ypix < 0 || $ypix >= $h} {return}
+ if {$doit} {
+ switch [dict get $@config -orient] {
+ horizontal {
+ set @motion_start_x $x
+ set @motion_curr_x $x
+ }
+ vertical {
+ set @motion_start_y $y
+ set @motion_curr_y $y
+ }
+ }
+ set @motion_start_v [dict get $@config -initvalue]
+ tclpd_guiclass_grab [tclpd_get_instance $self] \
+ [tclpd_get_glist $self] $x $y
+ }
+ }
+
+ widgetbehavior_motion {
+ lassign $args dx dy
+ switch [dict get $@config -orient] {
+ horizontal {
+ set @motion_curr_x [expr {$dx+$@motion_curr_x}]
+ set pixdelta [expr {-1*($@motion_curr_x-$@motion_start_x)}]
+ }
+ vertical {
+ set @motion_curr_y [expr {$dy+$@motion_curr_y}]
+ set pixdelta [expr {-1*($@motion_curr_y-$@motion_start_y)}]
+ }
+ }
+ set f [expr {$@motion_start_v+$pixdelta*$@pix2units}]
+ $self 0 float {*}[pd::add_selectors [list $f]]
+ }
+}