source: branches/nanovis2/gui/scripts/radiodial.tcl @ 3305

Last change on this file since 3305 was 3305, checked in by ldelgass, 11 years ago

sync with trunk

File size: 28.9 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: Radiodial - selector, like the dial on a car radio
3#
4#  This widget looks like the dial on an old-fashioned car radio.
5#  It draws a series of values along an axis, and allows a selector
6#  to move back and forth to select the values.
7# ======================================================================
8#  AUTHOR:  Michael McLennan, Purdue University
9#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
10#
11#  See the file "license.terms" for information on usage and
12#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13# ======================================================================
14package require Itk
15
16option add *Radiodial.thickness 10 widgetDefault
17option add *Radiodial.length 2i widgetDefault
18option add *Radiodial.knobImage knob widgetDefault
19option add *Radiodial.knobPosition n@middle widgetDefault
20option add *Radiodial.dialOutlineColor black widgetDefault
21option add *Radiodial.dialFillColor white widgetDefault
22option add *Radiodial.lineColor gray widgetDefault
23option add *Radiodial.activeLineColor black widgetDefault
24option add *Radiodial.padding 0 widgetDefault
25option add *Radiodial.valueWidth 10 widgetDefault
26option add *Radiodial.valuePadding 0.1 widgetDefault
27option add *Radiodial.foreground black widgetDefault
28option add *Radiodial.font \
29    -*-helvetica-medium-r-normal-*-12-* widgetDefault
30
31itcl::class Rappture::Radiodial {
32    inherit itk::Widget
33
34    itk_option define -min min Min ""
35    itk_option define -max max Max ""
36    itk_option define -variable variable Variable ""
37
38    itk_option define -thickness thickness Thickness 0
39    itk_option define -length length Length 0
40    itk_option define -padding padding Padding 0
41
42    itk_option define -foreground foreground Foreground "black"
43    itk_option define -dialoutlinecolor dialOutlineColor Color "black"
44    itk_option define -dialfillcolor dialFillColor Color "white"
45    itk_option define -dialprogresscolor dialProgressColor Color ""
46    itk_option define -linecolor lineColor Color "black"
47    itk_option define -activelinecolor activeLineColor Color "black"
48    itk_option define -knobimage knobImage KnobImage ""
49    itk_option define -knobposition knobPosition KnobPosition ""
50
51    itk_option define -font font Font ""
52    itk_option define -valuewidth valueWidth ValueWidth 0
53    itk_option define -valuepadding valuePadding ValuePadding 0
54
55    itk_option define -interactcommand interactCommand InteractCommand ""
56
57
58    constructor {args} { # defined below }
59    destructor { # defined below }
60
61    public method add {label {value ""}}
62    public method clear {}
63    public method get {args}
64    public method current {args}
65    public method color {value}
66                                                                               
67    protected method _setCurrent {val}
68    protected method _redraw {}
69    protected method _click {x y}
70    protected method _navigate {offset}
71    protected method _limits {}
72    protected method _findLabel {str}
73    protected method _fixSize {}
74    protected method _fixValue {args}
75    protected method _doInteract {}
76
77    private variable _values ""       ;# list of all values on the dial
78    private variable _val2label       ;# maps value => string label(s)
79    private variable _current ""      ;# current value (where pointer is)
80    private variable _variable ""     ;# variable associated with -variable
81
82    private variable _knob ""         ;# image for knob
83    private variable _spectrum ""     ;# width allocated for values
84    private variable _activecolor ""  ;# width allocated for values
85    private variable _vwidth 0        ;# width allocated for values
86}
87                                                                               
88itk::usual Radiodial {
89    keep -background -foreground -cursor -font
90}
91
92# ----------------------------------------------------------------------
93# CONSTRUCTOR
94# ----------------------------------------------------------------------
95itcl::body Rappture::Radiodial::constructor {args} {
96    itk_component add dial {
97        canvas $itk_interior.dial
98    }
99    pack $itk_component(dial) -expand yes -fill both
100    bind $itk_component(dial) <Configure> [itcl::code $this _redraw]
101
102    bind $itk_component(dial) <ButtonPress-1> [itcl::code $this _click %x %y]
103    bind $itk_component(dial) <B1-Motion> [itcl::code $this _click %x %y]
104    bind $itk_component(dial) <ButtonRelease-1> [itcl::code $this _click %x %y]
105
106    bind $itk_component(hull) <KeyPress-Left> [itcl::code $this _navigate -1]
107    bind $itk_component(hull) <KeyPress-Right> [itcl::code $this _navigate 1]
108
109    eval itk_initialize $args
110
111    _fixSize
112}
113
114# ----------------------------------------------------------------------
115# DESTRUCTOR
116# ----------------------------------------------------------------------
117itcl::body Rappture::Radiodial::destructor {} {
118    configure -variable ""  ;# remove variable trace
119    after cancel [itcl::code $this _redraw]
120}
121
122# ----------------------------------------------------------------------
123# USAGE: add <label> ?<value>?
124#
125# Clients use this to add new values to the dial.  Values are always
126# sorted in order along the dial.  If the value is not specified,
127# then it is created automatically based on the number of elements
128# on the dial.
129# ----------------------------------------------------------------------
130itcl::body Rappture::Radiodial::add {label {value ""}} {
131    if {"" == $value} {
132        set value [llength $_values]
133    }
134
135    # Add this value if we've never see it before
136    if {[lsearch -real $_values $value] < 0} {
137        lappend _values $value
138        set _values [lsort -real $_values]
139    }
140
141    # Keep all equivalent strings for this value.
142    # That way, we can later select either "1e18" or "1.0e+18"
143    lappend _val2label($value) $label
144
145    if {"" == $_current} {
146        _setCurrent $value
147    }
148
149    after cancel [itcl::code $this _redraw]
150    after idle [itcl::code $this _redraw]
151}
152
153# ----------------------------------------------------------------------
154# USAGE: clear
155#
156# Clients use this to remove all existing values from the dial.
157# ----------------------------------------------------------------------
158itcl::body Rappture::Radiodial::clear {} {
159    set _values ""
160    _setCurrent ""
161    catch {unset _val2label}
162
163    after cancel [itcl::code $this _redraw]
164    after idle [itcl::code $this _redraw]
165}
166
167# ----------------------------------------------------------------------
168# USAGE: get ?-format what? ?current|@index?
169#
170# Clients use this to query values within this radiodial.  With no
171# args, it returns a list of all values stored in the widget.  The
172# "current" arg requests only the current value on the radiodial.
173# The @index syntax can be used to request a particular value at
174# an index within the list of values.
175#
176# By default, this method returns the label for each value.  The
177# format option can be used to request the label, the value, or
178# both.
179# ----------------------------------------------------------------------
180itcl::body Rappture::Radiodial::get {args} {
181    Rappture::getopts args params {
182        value -format "label"
183    }
184    if {[llength $args] > 1} {
185        error "wrong # args: should be \"get ?-format f? ?current|@index\""
186    }
187    set index [lindex $args 0]
188    if {"" == $index} {
189        set ilist ""
190        for {set i 0} {$i < [llength $_values]} {incr i} {
191            lappend ilist $i
192        }
193    } elseif {"current" == $index} {
194        set ilist [lsearch -exact $_values $_current]
195        if {$ilist < 0} {
196            set ilist ""
197        }
198    } elseif {[regexp {^@([0-9]+|end)$} $index match i]} {
199        set ilist $i
200    }
201    if {[llength $ilist] == 1} {
202        set op set
203    } else {
204        set op lappend
205    }
206
207    set rlist ""
208    foreach i $ilist {
209        switch -- $params(-format) {
210            label {
211                set v [lindex $_values $i]
212                $op rlist [lindex $_val2label($v) 0]
213            }
214            value {
215                $op rlist [lindex $_values $i]
216            }
217            position {
218                foreach {min max} [_limits] break
219                set v [lindex $_values $i]
220                set frac [expr {double($v-$min)/($max-$min)}]
221                $op rlist $frac
222            }
223            all {
224                set v [lindex $_values $i]
225                foreach {min max} [_limits] break
226                set frac [expr {double($v-$min)/($max-$min)}]
227                set l [lindex $_val2label($v) 0]
228                $op rlist [list $l $v $frac]
229            }
230            default {
231                error "bad value \"$v\": should be label, value, position, all"
232            }
233        }
234    }
235    return $rlist
236}
237
238# ----------------------------------------------------------------------
239# USAGE: current ?<newval>?
240#
241# Clients use this to get/set the current value for this widget.
242# ----------------------------------------------------------------------
243itcl::body Rappture::Radiodial::current {args} {
244    if {[llength $args] == 0} {
245        return $_current
246    } elseif {[llength $args] == 1} {
247        set newval [lindex $args 0]
248        set n [_findLabel $newval]
249
250        # Don't use expr (?:) because it evaluates the resulting string.
251        # For example, it changes -0.020 to -0.02.
252        if { $n >= 0 } {
253            set rawval [lindex $_values $n]
254        } else {
255            set rawval ""
256        }
257        _setCurrent $rawval
258
259        after cancel [itcl::code $this _redraw]
260        after idle [itcl::code $this _redraw]
261        event generate $itk_component(hull) <<Value>>
262
263        return $_current
264    }
265    error "wrong # args: should be \"current ?newval?\""
266}
267
268# ----------------------------------------------------------------------
269# USAGE: color <value>
270#
271# Clients use this to query the color associated with a <value>
272# along the dial.
273# ----------------------------------------------------------------------
274itcl::body Rappture::Radiodial::color {value} {
275    _findLabel $value  ;# make sure this label is recognized
276
277    if {"" != $_spectrum} {
278        foreach {min max} [_limits] break
279        set frac [expr {double($value-$min)/($max-$min)}]
280        set color [$_spectrum get $frac]
281    } else {
282        if {$value == $_current} {
283            set color $_activecolor
284        } else {
285            set color $itk_option(-linecolor)
286        }
287    }
288    return $color
289}
290
291# ----------------------------------------------------------------------
292# USAGE: _setCurrent <value>
293#
294# Called automatically whenever the widget changes size to redraw
295# all elements within it.
296# ----------------------------------------------------------------------
297itcl::body Rappture::Radiodial::_setCurrent {value} {
298    set _current $value
299    if {"" != $_variable} {
300        upvar #0 $_variable var
301        if {[info exists _val2label($value)]} {
302            set var [lindex $_val2label($value) 0]
303        } else {
304            set var $value
305        }
306    }
307}
308
309# ----------------------------------------------------------------------
310# USAGE: _redraw
311#
312# Called automatically whenever the widget changes size to redraw
313# all elements within it.
314# ----------------------------------------------------------------------
315itcl::body Rappture::Radiodial::_redraw {} {
316    set c $itk_component(dial)
317    $c delete all
318
319    set fg $itk_option(-foreground)
320
321    set w [winfo width $c]
322    set h [winfo height $c]
323    set p [winfo pixels $c $itk_option(-padding)]
324    set t [expr {$itk_option(-thickness)+1}]
325    set y1 [expr {$h-1}]
326
327    if {"" != $_knob} {
328        set kw [image width $_knob]
329        set kh [image height $_knob]
330
331        switch -- $itk_option(-knobposition) {
332            n@top - nw@top - ne@top {
333                set extra [expr {$t-$kh}]
334                if {$extra < 0} {set extra 0}
335                set y1 [expr {$h-$extra-1}]
336            }
337            n@middle - nw@middle - ne@middle {
338                set extra [expr {int(ceil($kh-0.5*$t))}]
339                if {$extra < 0} {set extra 0}
340                set y1 [expr {$h-$extra-1}]
341            }
342            n@bottom - nw@bottom - ne@bottom {
343                set y1 [expr {$h-$kh-1}]
344            }
345
346            e@top - w@top - center@top -
347            e@bottom - w@bottom - center@bottom {
348                set extra [expr {int(ceil(0.5*$kh))}]
349                set y1 [expr {$h-$extra-1}]
350            }
351            e@middle - w@middle - center@middle {
352                set extra [expr {int(ceil(0.5*($kh-$t)))}]
353                if {$extra < 0} {set extra 0}
354                set y1 [expr {$h-$extra-1}]
355            }
356
357            s@top - sw@top - se@top -
358            s@middle - sw@middle - se@middle -
359            s@bottom - sw@bottom - se@bottom {
360                set y1 [expr {$h-2}]
361            }
362        }
363    }
364    set y0 [expr {$y1-$t}]
365    set x0 [expr {$p+1}]
366    set x1 [expr {$w-$_vwidth-$p-4}]
367    foreach {min max} [_limits] break
368
369    # draw the background rectangle
370    $c create rectangle $x0 $y0 $x1 $y1 \
371        -outline $itk_option(-dialoutlinecolor) \
372        -fill $itk_option(-dialfillcolor)
373
374    # draw the optional progress bar, from start to current
375    if {"" != $itk_option(-dialprogresscolor)
376          && [llength $_values] > 0 && "" != $_current} {
377        if {$max != $min} {
378            set frac [expr {double($_current-$min)/($max-$min)}]
379        } else {
380            set frac 0.
381        }
382        set xx1 [expr {$frac*($x1-$x0) + $x0}]
383        $c create rectangle [expr {$x0+1}] [expr {$y0+3}] $xx1 [expr {$y1-2}] \
384            -outline "" -fill $itk_option(-dialprogresscolor)
385    }
386
387    # draw lines for all values
388    if {$max > $min} {
389        foreach v $_values {
390            set frac [expr {double($v-$min)/($max-$min)}]
391            if {"" != $_spectrum} {
392                set color [$_spectrum get $frac]
393            } else {
394                if {$v == $_current} {
395                    set color $_activecolor
396                } else {
397                    set color $itk_option(-linecolor)
398                }
399            }
400            set thick [expr {($v == $_current) ? 3 : 1}]
401
402            if {"" != $color} {
403                set x [expr {$frac*($x1-$x0) + $x0}]
404                $c create line $x [expr {$y0+1}] $x $y1 \
405                    -fill $color -width $thick
406            }
407        }
408
409        if {"" != $_current} {
410            set x [expr {double($_current-$min)/($max-$min)*($x1-$x0) + $x0}]
411            regexp {([nsew]+|center)@} $itk_option(-knobposition) match anchor
412            switch -glob -- $itk_option(-knobposition) {
413                *@top    { set kpos $y0 }
414                *@middle { set kpos [expr {int(ceil(0.5*($y1+$y0)))}] }
415                *@bottom { set kpos $y1 }
416            }
417            $c create image $x $kpos -anchor $anchor -image $_knob
418        }
419    }
420
421    # if the -valuewidth is > 0, then make room for the value
422    set vw $itk_option(-valuewidth)
423    if {$vw > 0 && "" != $_current} {
424        set str [lindex $_val2label($_current) 0]
425        if {[string length $str] >= $vw} {
426            set str "[string range $str 0 [expr {$vw-3}]]..."
427        }
428
429        set dy [expr {([font metrics $itk_option(-font) -linespace]
430                        - [font metrics $itk_option(-font) -ascent])/2}]
431
432        set id [$c create text [expr {$x1+4}] [expr {($y1+$y0)/2+$dy}] \
433            -anchor w -text $str -font $itk_option(-font) -foreground $fg]
434        foreach {x0 y0 x1 y1} [$c bbox $id] break
435        set x0 [expr {$x0 + 10}]
436
437        # set up a tooltip so you can mouse over truncated values
438        Rappture::Tooltip::text $c [lindex $_val2label($_current) 0]
439        $c bind $id <Enter> \
440            [list ::Rappture::Tooltip::tooltip pending %W +$x0,$y1]
441        $c bind $id <Leave> \
442            [list ::Rappture::Tooltip::tooltip cancel]
443        $c bind $id <ButtonPress> \
444            [list ::Rappture::Tooltip::tooltip cancel]
445        $c bind $id <KeyPress> \
446            [list ::Rappture::Tooltip::tooltip cancel]
447    }
448}
449
450# ----------------------------------------------------------------------
451# USAGE: _click <x> <y>
452#
453# Called automatically whenever the user clicks or drags on the widget
454# to select a value.  Moves the current value to the one nearest the
455# click point.  If the value actually changes, it generates a <<Value>>
456# event to notify clients.
457# ----------------------------------------------------------------------
458itcl::body Rappture::Radiodial::_click {x y} {
459    set c $itk_component(dial)
460    set w [winfo width $c]
461    set h [winfo height $c]
462    set x0 1
463    set x1 [expr {$w-$_vwidth-4}]
464
465    focus $itk_component(hull)
466
467    # draw lines for all values
468    foreach {min max} [_limits] break
469    if {$max > $min && $x >= $x0 && $x <= $x1} {
470        set dmin $w
471        set xnearest 0
472        set vnearest ""
473        foreach v $_values {
474            set xv [expr {double($v-$min)/($max-$min)*($x1-$x0) + $x0}]
475            if {abs($xv-$x) < $dmin} {
476                set dmin [expr {abs($xv-$x)}]
477                set xnearest $xv
478                set vnearest $v
479            }
480        }
481
482        if {$vnearest != $_current} {
483            _setCurrent $vnearest
484            _redraw
485
486            event generate $itk_component(hull) <<Value>>
487            _doInteract
488        }
489    }
490}
491
492# ----------------------------------------------------------------------
493# USAGE: _navigate <offset>
494#
495# Called automatically whenever the user presses left/right keys
496# to nudge the current value left or right by some <offset>.  If the
497# value actually changes, it generates a <<Value>> event to notify
498# clients.
499# ----------------------------------------------------------------------
500itcl::body Rappture::Radiodial::_navigate {offset} {
501    set index [lsearch -exact $_values $_current]
502    if {$index >= 0} {
503        incr index $offset
504        if {$index >= [llength $_values]} {
505            set index [expr {[llength $_values]-1}]
506        } elseif {$index < 0} {
507            set index 0
508        }
509
510        set newval [lindex $_values $index]
511        if {$newval != $_current} {
512            _setCurrent $newval
513            _redraw
514
515            event generate $itk_component(hull) <<Value>>
516            _doInteract
517        }
518    }
519}
520
521# ----------------------------------------------------------------------
522# USAGE: _limits
523#
524# Used internally to compute the overall min/max limits for the
525# radio dial.  Returns {min max}, representing the end values for
526# the scale.
527# ----------------------------------------------------------------------
528itcl::body Rappture::Radiodial::_limits {} {
529    if {[llength $_values] == 0} {
530        set min 0
531        set max 0
532    } else {
533        set min [lindex $_values 0]
534        set max $min
535        foreach v [lrange $_values 1 end] {
536            if {$v < $min} { set min $v }
537            if {$v > $max} { set max $v }
538        }
539        set del [expr {$max-$min}]
540        set min [expr {$min-$itk_option(-valuepadding)*$del}]
541        set max [expr {$max+$itk_option(-valuepadding)*$del}]
542    }
543
544    if {"" != $itk_option(-min)} {
545        set min $itk_option(-min)
546    }
547    if {"" != $itk_option(-max)} {
548        set max $itk_option(-max)
549    }
550    return [list $min $max]
551}
552
553# ----------------------------------------------------------------------
554# USAGE: _findLabel <string>
555#
556# Used internally to search for the given <string> label among the
557# known values.  Returns an index into the _values list, or throws
558# an error if the string is not recognized.  Given the null string,
559# it returns -1, indicating that the value is not in _values, but
560# it is valid.
561# ----------------------------------------------------------------------
562itcl::body Rappture::Radiodial::_findLabel {str} {
563    if {"" == $str} {
564        return -1
565    }
566    for {set nv 0} {$nv < [llength $_values]} {incr nv} {
567        set v [lindex $_values $nv]
568        if {[lsearch -exact $_val2label($v) $str] >= 0} {
569            return $nv
570        }
571    }
572
573    # didn't match -- build a return string of possible values
574    set labels ""
575    foreach vlist $_values {
576        foreach v $vlist {
577            lappend labels "\"$_val2label($v)\""
578        }
579    }
580    error "bad value \"$str\": should be one of [join $labels ,]"
581}
582
583# ----------------------------------------------------------------------
584# USAGE: _fixSize
585#
586# Used internally to compute the overall size of the widget based
587# on the -thickness and -length options.
588# ----------------------------------------------------------------------
589itcl::body Rappture::Radiodial::_fixSize {} {
590    set h [winfo pixels $itk_component(hull) $itk_option(-thickness)]
591
592    if {"" != $_knob} {
593        set kh [image height $_knob]
594
595        switch -- $itk_option(-knobposition) {
596            n@top - nw@top - ne@top -
597            s@bottom - sw@bottom - se@bottom {
598                if {$kh > $h} { set h $kh }
599            }
600            n@middle - nw@middle - ne@middle -
601            s@middle - sw@middle - se@middle {
602                set h [expr {int(ceil(0.5*$h + $kh))}]
603            }
604            n@bottom - nw@bottom - ne@bottom -
605            s@top - sw@top - se@top {
606                set h [expr {$h + $kh}]
607            }
608            e@middle - w@middle - center@middle {
609                set h [expr {(($h > $kh) ? $h : $kh) + 1}]
610            }
611            n@middle - ne@middle - nw@middle -
612            s@middle - se@middle - sw@middle {
613                set extra [expr {int(ceil($kh-0.5*$h))}]
614                if {$extra < 0} { set extra 0 }
615                set h [expr {$h+$extra}]
616            }
617        }
618    }
619    incr h 1
620
621    set w [winfo pixels $itk_component(hull) $itk_option(-length)]
622
623    # if the -valuewidth is > 0, then make room for the value
624    if {$itk_option(-valuewidth) > 0} {
625        set charw [font measure $itk_option(-font) "n"]
626        set _vwidth [expr {$itk_option(-valuewidth)*$charw}]
627        set w [expr {$w+$_vwidth+4}]
628    } else {
629        set _vwidth 0
630    }
631
632    $itk_component(dial) configure -width $w -height $h
633}
634
635# ----------------------------------------------------------------------
636# USAGE: _fixValue ?<name1> <name2> <op>?
637#
638# Invoked automatically whenever the -variable associated with this
639# widget is modified.  Copies the value to the current settings for
640# the widget.
641# ----------------------------------------------------------------------
642itcl::body Rappture::Radiodial::_fixValue {args} {
643    if {"" == $itk_option(-variable)} {
644        return
645    }
646    upvar #0 $itk_option(-variable) var
647
648    set newval $var
649    set n [_findLabel $newval]
650    set rawval [expr {($n >= 0) ? [lindex $_values $n] : ""}]
651    set _current $rawval  ;# set current directly, so we don't trigger again
652
653    after cancel [itcl::code $this _redraw]
654    after idle [itcl::code $this _redraw]
655    event generate $itk_component(hull) <<Value>>
656}
657
658# ----------------------------------------------------------------------
659# USAGE: _doInteract
660#
661# Used internally to call the -interactcommand code whenever the user
662# changes the value of the widget.  This is different from the <<Value>>
663# event, which gets invoked whenever the value changes for any reason,
664# including programmatic changes.  If there is no command code, then
665# this does nothing.
666# ----------------------------------------------------------------------
667itcl::body Rappture::Radiodial::_doInteract {} {
668    if {[string length $itk_option(-interactcommand)] > 0} {
669        uplevel #0 $itk_option(-interactcommand)
670    }
671}
672
673# ----------------------------------------------------------------------
674# CONFIGURE: -thickness
675# ----------------------------------------------------------------------
676itcl::configbody Rappture::Radiodial::thickness {
677    _fixSize
678}
679
680# ----------------------------------------------------------------------
681# CONFIGURE: -length
682# ----------------------------------------------------------------------
683itcl::configbody Rappture::Radiodial::length {
684    _fixSize
685}
686
687# ----------------------------------------------------------------------
688# CONFIGURE: -font
689# ----------------------------------------------------------------------
690itcl::configbody Rappture::Radiodial::font {
691    _fixSize
692}
693
694# ----------------------------------------------------------------------
695# CONFIGURE: -valuewidth
696# ----------------------------------------------------------------------
697itcl::configbody Rappture::Radiodial::valuewidth {
698    if {![string is integer $itk_option(-valuewidth)]} {
699        error "bad value \"$itk_option(-valuewidth)\": should be integer"
700    }
701    _fixSize
702    after cancel [itcl::code $this _redraw]
703    after idle [itcl::code $this _redraw]
704}
705
706# ----------------------------------------------------------------------
707# CONFIGURE: -foreground
708# ----------------------------------------------------------------------
709itcl::configbody Rappture::Radiodial::foreground {
710    after cancel [itcl::code $this _redraw]
711    after idle [itcl::code $this _redraw]
712}
713
714# ----------------------------------------------------------------------
715# CONFIGURE: -dialoutlinecolor
716# ----------------------------------------------------------------------
717itcl::configbody Rappture::Radiodial::dialoutlinecolor {
718    after cancel [itcl::code $this _redraw]
719    after idle [itcl::code $this _redraw]
720}
721
722# ----------------------------------------------------------------------
723# CONFIGURE: -dialfillcolor
724# ----------------------------------------------------------------------
725itcl::configbody Rappture::Radiodial::dialfillcolor {
726    after cancel [itcl::code $this _redraw]
727    after idle [itcl::code $this _redraw]
728}
729
730# ----------------------------------------------------------------------
731# CONFIGURE: -dialprogresscolor
732# ----------------------------------------------------------------------
733itcl::configbody Rappture::Radiodial::dialprogresscolor {
734    after cancel [itcl::code $this _redraw]
735    after idle [itcl::code $this _redraw]
736}
737
738# ----------------------------------------------------------------------
739# CONFIGURE: -linecolor
740# ----------------------------------------------------------------------
741itcl::configbody Rappture::Radiodial::linecolor {
742    after cancel [itcl::code $this _redraw]
743    after idle [itcl::code $this _redraw]
744}
745
746# ----------------------------------------------------------------------
747# CONFIGURE: -activelinecolor
748# ----------------------------------------------------------------------
749itcl::configbody Rappture::Radiodial::activelinecolor {
750    set val $itk_option(-activelinecolor)
751    if {[catch {$val isa ::Rappture::Spectrum} valid] == 0 && $valid} {
752        set _spectrum $val
753        set _activecolor ""
754    } elseif {[catch {winfo rgb $itk_component(hull) $val}] == 0} {
755        set _spectrum ""
756        set _activecolor $val
757    } elseif {"" != $val} {
758        error "bad value \"$val\": should be Spectrum object or color"
759    }
760    after cancel [itcl::code $this _redraw]
761    after idle [itcl::code $this _redraw]
762}
763
764# ----------------------------------------------------------------------
765# CONFIGURE: -knobimage
766# ----------------------------------------------------------------------
767itcl::configbody Rappture::Radiodial::knobimage {
768    if {[regexp {^image[0-9]+$} $itk_option(-knobimage)]} {
769        set _knob $itk_option(-knobimage)
770    } elseif {"" != $itk_option(-knobimage)} {
771        set _knob [Rappture::icon $itk_option(-knobimage)]
772    } else {
773        set _knob ""
774    }
775    _fixSize
776
777    after cancel [itcl::code $this _redraw]
778    after idle [itcl::code $this _redraw]
779}
780
781# ----------------------------------------------------------------------
782# CONFIGURE: -knobposition
783# ----------------------------------------------------------------------
784itcl::configbody Rappture::Radiodial::knobposition {
785    if {![regexp {^([nsew]+|center)@(top|middle|bottom)$} $itk_option(-knobposition)]} {
786        error "bad value \"$itk_option(-knobposition)\": should be anchor@top|middle|bottom"
787    }
788    _fixSize
789
790    after cancel [itcl::code $this _redraw]
791    after idle [itcl::code $this _redraw]
792}
793
794# ----------------------------------------------------------------------
795# CONFIGURE: -padding
796# This adds padding on left/right side of dial background.
797# ----------------------------------------------------------------------
798itcl::configbody Rappture::Radiodial::padding {
799    if {[catch {winfo pixels $itk_component(hull) $itk_option(-padding)}]} {
800        error "bad value \"$itk_option(-padding)\": should be size in pixels"
801    }
802}
803
804# ----------------------------------------------------------------------
805# CONFIGURE: -valuepadding
806# This shifts min/max limits in by a fraction of the overall size.
807# ----------------------------------------------------------------------
808itcl::configbody Rappture::Radiodial::valuepadding {
809    if {![string is double $itk_option(-valuepadding)]
810          || $itk_option(-valuepadding) < 0} {
811        error "bad value \"$itk_option(-valuepadding)\": should be >= 0.0"
812    }
813}
814
815# ----------------------------------------------------------------------
816# CONFIGURE: -variable
817# ----------------------------------------------------------------------
818itcl::configbody Rappture::Radiodial::variable {
819    if {"" != $_variable} {
820        upvar #0 $_variable var
821        trace remove variable var write [itcl::code $this _fixValue]
822    }
823
824    set _variable $itk_option(-variable)
825
826    if {"" != $_variable} {
827        upvar #0 $_variable var
828        trace add variable var write [itcl::code $this _fixValue]
829
830        # sync to the current value of this variable
831        if {[info exists var]} {
832            _fixValue
833        }
834    }
835}
Note: See TracBrowser for help on using the repository browser.