aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--colorpicker.tcl281
-rw-r--r--properties.tcl423
2 files changed, 704 insertions, 0 deletions
diff --git a/colorpicker.tcl b/colorpicker.tcl
new file mode 100644
index 0000000..0c433cb
--- /dev/null
+++ b/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/properties.tcl b/properties.tcl
new file mode 100644
index 0000000..addb624
--- /dev/null
+++ b/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 [concat $::id($w) config {*}$newconf \;]
+}
+
+proc propertiespanel_close {w} {
+ pd [concat $::id($w) cancel \;]
+}