source: trunk/gui/scripts/radiodial.tcl @ 4735

Last change on this file since 4735 was 3330, checked in by gah, 12 years ago

merge (by hand) with Rappture1.2 branch

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