# ACTIVESTATE TEAPOT-PKG BEGIN TM -*- tcl -*- # -- Tcl Module # @@ Meta Begin # Package voltmeter 0.1 # Meta as::build::date 2015-05-26 # Meta as::origin http://sourceforge.net/projects/tcllib # Meta license BSD # Meta platform tcl # Meta require {Tcl 8.5} # Meta require {Tk 8.5} # Meta require snit # @@ Meta End # ACTIVESTATE TEAPOT-PKG BEGIN DECLARE package provide voltmeter 0.1 # ACTIVESTATE TEAPOT-PKG END DECLARE # ACTIVESTATE TEAPOT-PKG END TM # voltmeter.tcl -- # # Adapted by Arjen Markus (snitified), july 2010 # # # # # Part of: The TCL'ers Wiki # Contents: a voltmeter-like widget # Date: Fri Jun 13, 2003 # # Abstract # # # # Copyright (c) 2003 Marco Maggi # # The author hereby grant permission to use, copy, modify, distribute, # and license this software and its documentation for any purpose, # provided that existing copyright notices are retained in all copies # and that this notice is included verbatim in any distributions. No # written agreement, license, or royalty fee is required for any of the # authorized uses. Modifications to this software may be copyrighted by # their authors and need not follow the licensing terms described here, # provided that the new terms are clearly indicated on the first page of # each file where they apply. # # IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHOR HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND # NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, # AND THE AUTHOR AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE # MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # # $Id: voltmeter.tcl,v 1.3 2010/09/10 17:16:29 andreas_kupries Exp $ # package require Tk 8.5 package require snit package provide voltmeter 0.1 namespace eval controlwidget { namespace export voltmeter } # voltmeter -- # Voltmeter-like widget # snit::widget controlwidget::voltmeter { # # widget default values # option -borderwidth -default 1 option -background -default gray option -dialcolor -default white option -needlecolor -default black option -scalecolor -default black option -indexid -default {} option -variable -default {} -configuremethod VariableName option -min -default 0.0 option -max -default 100.0 option -labelcolor -default black option -titlecolor -default black option -labelfont -default {Helvetica 8} option -titlefont -default {Helvetica 9} option -labels -default {} option -title -default {} option -width -default 50m option -height -default 25m option -highlightthickness -default 0 option -relief -default raised variable pi [expr {3.14159265359/180.0}] variable motion variable xc variable yc constructor args { # # Configure the widget # $self configurelist $args canvas $win.c -background $options(-background) -width $options(-width) -height $options(-height) \ -relief $options(-relief) -borderwidth $options(-borderwidth) grid $win.c -sticky news -padx 2m -pady 2m if {$options(-variable) ne ""} { trace add variable ::$options(-variable) write [mymethod tracer $options(-variable)] } set width [$win.c cget -width] set height [$win.c cget -height] set xcentre [expr {$width*0.5}] set ycentre [expr {$width*1.4}] set t 1.15 set t1 1.25 $win.c create arc \ [expr {$xcentre-$width*$t}] [expr {$ycentre-$width*$t}] \ [expr {$xcentre+$width*$t}] [expr {$ycentre+$width*$t}] \ -start 70.5 -extent 37 -style arc -outline lightgray \ -width [expr {$ycentre*0.245}] $win.c create arc \ [expr {$xcentre-$width*$t}] [expr {$ycentre-$width*$t}] \ [expr {$xcentre+$width*$t}] [expr {$ycentre+$width*$t}] \ -start 71 -extent 36 -style arc -outline $options(-dialcolor) \ -width [expr {$ycentre*0.23}] $win.c create arc \ [expr {$xcentre-$width*$t1}] [expr {$ycentre-$width*$t1}] \ [expr {$xcentre+$width*$t1}] [expr {$ycentre+$width*$t1}] \ -start 75 -extent 30 \ -fill black -outline $options(-scalecolor) -style arc -width 0.5m set num [llength $options(-labels)] set angle 255.0 set delta [expr {30.0/($num-1)}] set l1 [expr {$width*$t1}] set l2 [expr {$width*$t1*0.95}] set l3 [expr {$width*$t1*0.92}] for {set i 0} {$i < $num} {incr i} { set a [expr {($angle+$delta*$i)*$pi}] set x1 [expr {$xcentre+$l1*cos($a)}] set y1 [expr {$ycentre+$l1*sin($a)}] set x2 [expr {$xcentre+$l2*cos($a)}] set y2 [expr {$ycentre+$l2*sin($a)}] $win.c create line $x1 $y1 $x2 $y2 -fill $options(-scalecolor) -width 0.5m set x1 [expr {$xcentre+$l3*cos($a)}] set y1 [expr {$ycentre+$l3*sin($a)}] set label [lindex $options(-labels) $i] if { [string length $label] } { $win.c create text $x1 $y1 \ -anchor center -justify center -fill $options(-labelcolor) \ -text $label -font $options(-labelfont) } } set title $options(-title) if { [string length $title] } { $win.c create text $xcentre [expr {$ycentre-$width*1.05}] \ -anchor center -justify center -fill $options(-titlecolor) \ -text $title -font $options(-titlefont) } rivet $win.c 10 10 rivet $win.c [expr {$width-10}] 10 rivet $win.c 10 [expr {$height-10}] rivet $win.c [expr {$width-10}] [expr {$height-10}] set motion 0 set xc $xcentre set yc $ycentre bind $win.c [list $self needleRelease %W] bind $win.c [list $self needleMotion %W %x %y] set value 0 $self drawline $win $value } method destructor {} { set varname ::$options(-variable)] trace remove variable $varname write \ [namespace code "mymethod tracer $win $varname"] } # # public methods -- # method set {newValue} { if { $options(-variable) != "" } { set ::$options(-variable) $newValue ;#! This updates the dial too } else { set options(-value) $newValue $self draw $win.c $options(-value) } } method get {} { return $options(-value) } # # private methods -- # method VariableName {option name} { # Could be still constructing in which case # $win.c does not exist: if {![winfo exists $win.c]} { set options(-variable) $name return; } # Remove any old traces if {$options(-variable) ne ""} { trace remove variable ::$options(-variable) write [mymethod tracer $options(-variable)] } # Set new trace if appropriate and update value. set options(-variable) $name if {$options(-variable) ne ""} { trace add variable ::$options(-variable) write [mymethod tracer $options(-variable)] $self drawline $win.c [set ::$options(-variable)] } } method tracer { varname args } \ { set options(-value) [set ::$varname] $self drawline $win [set ::$varname] } method drawline { widget value } { set id $options(-indexid) set min $options(-min) set max $options(-max) set c $widget.c set v [expr { ($value <= ($max*1.05))? $value : ($max*1.05) }] set angle [expr {((($v-$min)/(1.0*($max-$min)))*30.0+165.0)*$pi}] set width [$c cget -width] set xcentre [expr {$width/2.0}] set ycentre [expr {$width*1.4}] set l1 [expr {$ycentre*0.85}] set l2 [expr {$ycentre*0.7}] set xl [expr {$xcentre-$l1*sin($angle)}] set yl [expr {$ycentre+$l1*cos($angle)}] set xs [expr {$xcentre-$l2*sin($angle)}] set ys [expr {$ycentre+$l2*cos($angle)}] catch {$c delete $id} set id [$c create line $xs $ys $xl $yl -fill $options(-needlecolor) -width 0.6m] $c bind $id [list $self needlePress %W] set options(-indexid) $id } method needlePress {w} \ { set motion 1 } method needleRelease {w} \ { set motion 0 } method needleMotion {w x y} \ { if {! $motion} { return } if {$y == $yc && $x == $xc} { return } # # Compute the angle with the positive y-axis - easier to examine! # set angle [expr {atan2($xc - $x,$yc - $y) / $pi}] if { $angle >= 15.0 } { set angle 15.0 } if { $angle < -15.0 } { set angle -15.0 } set ::$options(-variable) [expr {$options(-min) + ($options(-max)-$options(-min))*(15.0-$angle) / 30.0}] } proc rivet { c xc yc } { shadowcircle $c \ [expr {$xc-4}] [expr {$yc-4}] [expr {$xc+4}] [expr {$yc+4}] \ 5 0.5m -45.0 } proc shadowcircle { canvas x1 y1 x2 y2 ticks width orient } { set radius [expr {($x2-$x1)/2.0}] set angle $orient set delta [expr {180.0/$ticks}] for {set i 0} {$i <= $ticks} {incr i} { set a [expr {($angle+$i*$delta)}] set b [expr {($angle-$i*$delta)}] set color [expr {40+$i*(200/$ticks)}] set color [format "#%x%x%x" $color $color $color] $canvas create arc $x1 $y1 $x2 $y2 -start $a -extent $delta \ -style arc -outline $color -width $width $canvas create arc $x1 $y1 $x2 $y2 -start $b -extent $delta \ -style arc -outline $color -width $width } } } if {0} { # main -- # Demonstration of the voltmeter object # proc main { argc argv } { global forever wm withdraw . wm title . "A voltmeter-like widget" wm geometry . +10+10 ::controlwidget::voltmeter .t1 -variable value1 -labels { 0 50 100 } -title "Voltmeter (V)" scale .s1 -command "set ::value1" -variable value1 ::controlwidget::voltmeter .t2 -variable value2 -labels { 0 {} 2.5 {} 5 } \ -width 80m -height 40m -title "Ampere (mA)" -dialcolor lightgreen -scalecolor white \ -min 0 -max 5 scale .s2 -command "set ::value2" -variable value2 button .b -text Quit -command "set ::forever 1" grid .t1 .s1 .t2 .s2 .b wm deiconify . vwait forever .t1 destructor .t2 destructor exit 0 } main $argc $argv } ### end of file # Local Variables: # mode: tcl # page-delimiter: "^#PAGE" # End: