summaryrefslogtreecommitdiff
path: root/iwidgets/generic/watch.itk
diff options
context:
space:
mode:
Diffstat (limited to 'iwidgets/generic/watch.itk')
-rw-r--r--iwidgets/generic/watch.itk626
1 files changed, 626 insertions, 0 deletions
diff --git a/iwidgets/generic/watch.itk b/iwidgets/generic/watch.itk
new file mode 100644
index 00000000000..ace2cc94655
--- /dev/null
+++ b/iwidgets/generic/watch.itk
@@ -0,0 +1,626 @@
+#
+# Watch
+# ----------------------------------------------------------------------
+# Implements a a clock widget in a canvas.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: John A. Tucker EMAIL: jatucker@spd.dsccc.com
+#
+# ======================================================================
+# Copyright (c) 1997 DSC Technologies Corporation
+# ======================================================================
+# Permission to use, copy, modify, distribute and license this software
+# and its documentation for any purpose, and without fee or written
+# agreement with DSC, is hereby granted, provided that the above copyright
+# notice appears in all copies and that both the copyright notice and
+# warranty disclaimer below appear in supporting documentation, and that
+# the names of DSC Technologies Corporation or DSC Communications
+# Corporation not be used in advertising or publicity pertaining to the
+# software without specific, written prior permission.
+#
+# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
+# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
+# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
+# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
+# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
+# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+# SOFTWARE.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Watch.labelFont \
+ -*-Courier-Medium-R-Normal--*-120-*-*-*-*-*-* widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Watch {
+ keep -background -cursor -labelfont -foreground
+}
+
+itcl::class iwidgets::Watch {
+
+ inherit itk::Widget
+
+ itk_option define -hourradius hourRadius Radius .50
+ itk_option define -hourcolor hourColor Color red
+
+ itk_option define -minuteradius minuteRadius Radius .80
+ itk_option define -minutecolor minuteColor Color yellow
+
+ itk_option define -pivotradius pivotRadius Radius .10
+ itk_option define -pivotcolor pivotColor Color white
+
+ itk_option define -secondradius secondRadius Radius .90
+ itk_option define -secondcolor secondColor Color black
+
+ itk_option define -clockcolor clockColor Color white
+ itk_option define -clockstipple clockStipple ClockStipple {}
+
+ itk_option define -state state State normal
+ itk_option define -showampm showAmPm ShowAmPm true
+
+ itk_option define -tickcolor tickColor Color black
+
+ constructor {args} {}
+ destructor {}
+
+ #
+ # Public methods
+ #
+ public {
+ method get {{format "-string"}}
+ method show {{time "now"}}
+ method watch {args}
+ }
+
+ #
+ # Private methods
+ #
+ private {
+ method _handMotionCB {tag x y}
+ method _drawHand {tag}
+ method _handReleaseCB {tag x y}
+ method _displayClock {{when "later"}}
+
+ variable _interior
+ variable _radius
+ variable _theta
+ variable _extent
+ variable _reposition "" ;# non-null => _displayClock pending
+ variable _timeVar
+ variable _x0 1
+ variable _y0 1
+
+ common _ampmVar
+ common PI [expr {2*asin(1.0)}]
+ }
+}
+
+#
+# Provide a lowercased access method for the Watch class.
+#
+proc ::iwidgets::watch {pathName args} {
+ uplevel ::iwidgets::Watch $pathName $args
+}
+
+#
+# Use option database to override default resources of base classes.
+#
+option add *Watch.width 155 widgetDefault
+option add *Watch.height 175 widgetDefault
+
+# -----------------------------------------------------------------------------
+# CONSTRUCTOR
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::constructor { args } {
+ #
+ # Add back to the hull width and height options and make the
+ # borderwidth zero since we don't need it.
+ #
+ set _interior $itk_interior
+
+ itk_option add hull.width hull.height
+ component hull configure -borderwidth 0
+ grid propagate $itk_component(hull) no
+
+ set _ampmVar($this) "AM"
+ set _radius(outer) 1
+
+ set _radius(hour) 1
+ set _radius(minute) 1
+ set _radius(second) 1
+
+ set _theta(hour) 30
+ set _theta(minute) 6
+ set _theta(second) 6
+
+ set _extent(hour) 14
+ set _extent(minute) 14
+ set _extent(second) 2
+
+ set _timeVar(hour) 12
+ set _timeVar(minute) 0
+ set _timeVar(second) 0
+
+ #
+ # Create the frame in which the "AM" and "PM" radiobuttons will be drawn
+ #
+ itk_component add frame {
+ frame $itk_interior.frame
+ }
+
+ #
+ # Create the canvas in which the clock will be drawn
+ #
+ itk_component add canvas {
+ canvas $itk_interior.canvas
+ }
+ bind $itk_component(canvas) <Map> +[itcl::code $this _displayClock]
+ bind $itk_component(canvas) <Configure> +[itcl::code $this _displayClock]
+
+ #
+ # Create the "AM" and "PM" radiobuttons to be drawn in the canvas
+ #
+ itk_component add am {
+ radiobutton $itk_component(frame).am \
+ -text "AM" \
+ -value "AM" \
+ -variable [itcl::scope _ampmVar($this)]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ itk_component add pm {
+ radiobutton $itk_component(frame).pm \
+ -text "PM" \
+ -value "PM" \
+ -variable [itcl::scope _ampmVar($this)]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ #
+ # Create the canvas item for displaying the main oval which encapsulates
+ # the entire clock.
+ #
+ watch create oval 0 0 2 2 -width 5 -tags clock
+
+ #
+ # Create the canvas items for displaying the 60 ticks marks around the
+ # inner perimeter of the watch.
+ #
+ set extent 3
+ for {set i 0} {$i < 60} {incr i} {
+ set start [expr {$i*6-1}]
+ set tag [expr {[expr {$i%5}] == 0 ? "big" : "little"}]
+ watch create arc 0 0 0 0 \
+ -style arc \
+ -extent $extent \
+ -start $start \
+ -tags "tick$i tick $tag"
+ }
+
+ #
+ # Create the canvas items for displaying the hour, minute, and second hands
+ # of the watch. Add bindings to allow the mouse to move and set the
+ # clock hands.
+ #
+ watch create arc 1 1 1 1 -extent 30 -tags minute
+ watch create arc 1 1 1 1 -extent 30 -tags hour
+ watch create arc 1 1 1 1 -tags second
+
+ #
+ # Create the canvas item for displaying the center of the watch in which
+ # the hour, minute, and second hands will pivot.
+ #
+ watch create oval 0 0 1 1 -width 5 -fill black -tags pivot
+
+ #
+ # Position the "AM/PM" button frame and watch canvas.
+ #
+ grid $itk_component(frame) -row 0 -column 0 -sticky new
+ grid $itk_component(canvas) -row 1 -column 0 -sticky nsew
+
+ grid rowconfigure $itk_interior 0 -weight 0
+ grid rowconfigure $itk_interior 1 -weight 1
+ grid columnconfigure $itk_interior 0 -weight 1
+
+ eval itk_initialize $args
+}
+
+# -----------------------------------------------------------------------------
+# DESTURCTOR
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::destructor {} {
+ if {$_reposition != ""} {
+ after cancel $_reposition
+ }
+}
+
+# -----------------------------------------------------------------------------
+# METHODS
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# METHOD: _handReleaseCB tag x y
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::_handReleaseCB {tag x y} {
+
+ set atanab [expr {atan2(double($y-$_y0),double($x-$_x0))*(180/$PI)}]
+ set degrees [expr {$atanab > 0 ? [expr {360-$atanab}] : abs($atanab)}]
+ set ticks [expr {round($degrees/$_theta($tag))}]
+ set _timeVar($tag) [expr {((450-$ticks*$_theta($tag))%360)/$_theta($tag)}]
+
+ if {$tag == "hour" && $_timeVar(hour) == 0} {
+ set _timeVar($tag) 12
+ }
+
+ _drawHand $tag
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: _handMotionCB tag x y
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::_handMotionCB {tag x y} {
+ if {$x == $_x0 || $y == $_y0} {
+ return
+ }
+
+ set a [expr {$y-$_y0}]
+ set b [expr {$x-$_x0}]
+ set c [expr {hypot($a,$b)}]
+
+ set atanab [expr {atan2(double($a),double($b))*(180/$PI)}]
+ set degrees [expr {$atanab > 0 ? [expr 360-$atanab] : abs($atanab)}]
+
+ set x2 [expr {$_x0+$_radius($tag)*($b/double($c))}]
+ set y2 [expr {$_y0+$_radius($tag)*($a/double($c))}]
+ watch coords $tag \
+ [expr {$x2-$_radius($tag)}] \
+ [expr {$y2-$_radius($tag)}] \
+ [expr {$x2+$_radius($tag)}] \
+ [expr {$y2+$_radius($tag)}]
+ set start [expr {$degrees-180-($_extent($tag)/2)}]
+ watch itemconfigure $tag -start $start -extent $_extent($tag)
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: get ?format?
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::get {{format "-string"}} {
+ set timestr [format "%02d:%02d:%02d %s" \
+ $_timeVar(hour) $_timeVar(minute) \
+ $_timeVar(second) $_ampmVar($this)]
+
+ switch -- $format {
+ "-string" {
+ return $timestr
+ }
+ "-clicks" {
+ return [clock scan $timestr]
+ }
+ default {
+ error "bad format option \"$format\":\
+ should be -string or -clicks"
+ }
+ }
+}
+
+# -----------------------------------------------------------------------------
+# METHOD: watch ?args?
+#
+# Evaluates the specified args against the canvas component.
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::watch {args} {
+ return [eval $itk_component(canvas) $args]
+}
+
+# -----------------------------------------------------------------------------
+# METHOD: _drawHand tag
+#
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::_drawHand {tag} {
+
+ set degrees [expr {abs(450-($_timeVar($tag)*$_theta($tag)))%360}]
+ set radians [expr {$degrees*($PI/180)}]
+ set x [expr {$_x0+$_radius($tag)*cos($radians)}]
+ set y [expr {$_y0+$_radius($tag)*sin($radians)*(-1)}]
+ watch coords $tag \
+ [expr {$x-$_radius($tag)}] \
+ [expr {$y-$_radius($tag)}] \
+ [expr {$x+$_radius($tag)}] \
+ [expr {$y+$_radius($tag)}]
+ set start [expr {$degrees-180-($_extent($tag)/2)}]
+ watch itemconfigure $tag -start $start
+}
+
+# ------------------------------------------------------------------
+# PUBLIC METHOD: show time
+#
+# Changes the currently displayed time to be that of the time
+# argument. The time may be specified either as a string or an
+# integer clock value. Reference the clock command for more
+# information on obtaining times and their formats.
+# ------------------------------------------------------------------
+itcl::body iwidgets::Watch::show {{time "now"}} {
+ if {$time == "now"} {
+ set seconds [clock seconds]
+ } elseif {![catch {clock format $time}]} {
+ set seconds $time
+ } elseif {[catch {set seconds [clock scan $time]}]} {
+ error "bad time: \"$time\", must be a valid time\
+ string, clock clicks value or the keyword now"
+ }
+
+ set timestring [clock format $seconds -format "%I %M %S %p"]
+ set _timeVar(hour) [expr int(1[lindex $timestring 0] - 100)]
+ set _timeVar(minute) [expr int(1[lindex $timestring 1] - 100)]
+ set _timeVar(second) [expr int(1[lindex $timestring 2] - 100)]
+ set _ampmVar($this) [lindex $timestring 3]
+
+ _drawHand hour
+ _drawHand minute
+ _drawHand second
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: _displayClock ?when?
+#
+# Places the hour, minute, and second dials in the canvas. If "when" is "now",
+# the change is applied immediately. If it is "later" or it is not specified,
+# then the change is applied later, when the application is idle.
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Watch::_displayClock {{when "later"}} {
+
+ if {$when == "later"} {
+ if {$_reposition == ""} {
+ set _reposition [after idle [itcl::code $this _displayClock now]]
+ }
+ return
+ }
+
+ #
+ # Compute the center coordinates for the clock based on the
+ # with and height of the canvas.
+ #
+ set width [winfo width $itk_component(canvas)]
+ set height [winfo height $itk_component(canvas)]
+ set _x0 [expr {$width/2}]
+ set _y0 [expr {$height/2}]
+
+ #
+ # Set the radius of the watch, pivot, hour, minute and second items.
+ #
+ set _radius(outer) [expr {$_x0 < $_y0 ? $_x0 : $_y0}]
+ set _radius(pivot) [expr {$itk_option(-pivotradius)*$_radius(outer)}]
+ set _radius(hour) [expr {$itk_option(-hourradius)*$_radius(outer)}]
+ set _radius(minute) [expr {$itk_option(-minuteradius)*$_radius(outer)}]
+ set _radius(second) [expr {$itk_option(-secondradius)*$_radius(outer)}]
+ set outerWidth [watch itemcget clock -width]
+
+ #
+ # Set the coordinates of the clock item
+ #
+ set x1Outer $outerWidth
+ set y1Outer $outerWidth
+ set x2Outer [expr {$width-$outerWidth}]
+ set y2Outer [expr {$height-$outerWidth}]
+ watch coords clock $x1Outer $y1Outer $x2Outer $y2Outer
+
+ #
+ # Set the coordinates of the tick items
+ #
+ set offset [expr {$outerWidth*2}]
+ set x1Tick [expr {$x1Outer+$offset}]
+ set y1Tick [expr {$y1Outer+$offset}]
+ set x2Tick [expr {$x2Outer-$offset}]
+ set y2Tick [expr {$y2Outer-$offset}]
+ for {set i 0} {$i < 60} {incr i} {
+ watch coords tick$i $x1Tick $y1Tick $x2Tick $y2Tick
+ }
+ set maxTickWidth [expr {$_radius(outer)-$_radius(second)+1}]
+ set minTickWidth [expr {round($maxTickWidth/2)}]
+ watch itemconfigure big -width $maxTickWidth
+ watch itemconfigure little -width [expr {round($maxTickWidth/2)}]
+
+ #
+ # Set the coordinates of the pivot item
+ #
+ set x1Center [expr {$_x0-$_radius(pivot)}]
+ set y1Center [expr {$_y0-$_radius(pivot)}]
+ set x2Center [expr {$_x0+$_radius(pivot)}]
+ set y2Center [expr {$_y0+$_radius(pivot)}]
+ watch coords pivot $x1Center $y1Center $x2Center $y2Center
+
+ #
+ # Set the coordinates of the hour, minute, and second dial items
+ #
+ watch itemconfigure hour -extent $_extent(hour)
+ _drawHand hour
+
+ watch itemconfigure minute -extent $_extent(minute)
+ _drawHand minute
+
+ watch itemconfigure second -extent $_extent(second)
+ _drawHand second
+
+ set _reposition ""
+}
+
+# -----------------------------------------------------------------------------
+# OPTIONS
+# -----------------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+# OPTION: state
+#
+# Configure the editable state of the widget. Valid values are
+# normal and disabled. In a disabled state, the hands of the
+# watch are not selectabled.
+# ------------------------------------------------------------------
+itcl::configbody ::iwidgets::Watch::state {
+ if {$itk_option(-state) == "normal"} {
+ watch bind minute <B1-Motion> \
+ [itcl::code $this _handMotionCB minute %x %y]
+ watch bind minute <ButtonRelease-1> \
+ [itcl::code $this _handReleaseCB minute %x %y]
+
+ watch bind hour <B1-Motion> \
+ [itcl::code $this _handMotionCB hour %x %y]
+ watch bind hour <ButtonRelease-1> \
+ [itcl::code $this _handReleaseCB hour %x %y]
+
+ watch bind second <B1-Motion> \
+ [itcl::code $this _handMotionCB second %x %y]
+ watch bind second <ButtonRelease-1> \
+ [itcl::code $this _handReleaseCB second %x %y]
+
+ $itk_component(am) configure -state normal
+ $itk_component(pm) configure -state normal
+
+ } elseif {$itk_option(-state) == "disabled"} {
+ watch bind minute <B1-Motion> {}
+ watch bind minute <ButtonRelease-1> {}
+
+ watch bind hour <B1-Motion> {}
+ watch bind hour <ButtonRelease-1> {}
+
+ watch bind second <B1-Motion> {}
+ watch bind second <ButtonRelease-1> {}
+
+ $itk_component(am) configure -state disabled \
+ -disabledforeground [$itk_component(am) cget -background]
+ $itk_component(pm) configure -state normal \
+ -disabledforeground [$itk_component(am) cget -background]
+
+ } else {
+ error "bad state option \"$itk_option(-state)\":\
+ should be normal or disabled"
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: showampm
+#
+# Configure the display of the AM/PM radio buttons.
+# ------------------------------------------------------------------
+itcl::configbody ::iwidgets::Watch::showampm {
+ switch -- $itk_option(-showampm) {
+ 0 - no - false - off {
+ pack forget $itk_component(am)
+ pack forget $itk_component(pm)
+ }
+
+ 1 - yes - true - on {
+ pack $itk_component(am) -side left -fill both -expand 1
+ pack $itk_component(pm) -side right -fill both -expand 1
+ }
+
+ default {
+ error "bad showampm option \"$itk_option(-showampm)\":\
+ should be boolean"
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# OPTION: pivotcolor
+#
+# Configure the color of the clock pivot.
+#
+itcl::configbody ::iwidgets::Watch::pivotcolor {
+ watch itemconfigure pivot -fill $itk_option(-pivotcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: clockstipple
+#
+# Configure the stipple pattern for the clock fill color.
+#
+itcl::configbody ::iwidgets::Watch::clockstipple {
+ watch itemconfigure clock -stipple $itk_option(-clockstipple)
+}
+
+# ------------------------------------------------------------------
+# OPTION: clockcolor
+#
+# Configure the color of the clock.
+#
+itcl::configbody ::iwidgets::Watch::clockcolor {
+ watch itemconfigure clock -fill $itk_option(-clockcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: hourcolor
+#
+# Configure the color of the hour hand.
+#
+itcl::configbody ::iwidgets::Watch::hourcolor {
+ watch itemconfigure hour -fill $itk_option(-hourcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: minutecolor
+#
+# Configure the color of the minute hand.
+#
+itcl::configbody ::iwidgets::Watch::minutecolor {
+ watch itemconfigure minute -fill $itk_option(-minutecolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: secondcolor
+#
+# Configure the color of the second hand.
+#
+itcl::configbody ::iwidgets::Watch::secondcolor {
+ watch itemconfigure second -fill $itk_option(-secondcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: tickcolor
+#
+# Configure the color of the ticks.
+#
+itcl::configbody ::iwidgets::Watch::tickcolor {
+ watch itemconfigure tick -outline $itk_option(-tickcolor)
+}
+
+# ------------------------------------------------------------------
+# OPTION: hourradius
+#
+# Configure the radius of the hour hand.
+#
+itcl::configbody ::iwidgets::Watch::hourradius {
+ _displayClock
+}
+
+# ------------------------------------------------------------------
+# OPTION: minuteradius
+#
+# Configure the radius of the minute hand.
+#
+itcl::configbody ::iwidgets::Watch::minuteradius {
+ _displayClock
+}
+
+# ------------------------------------------------------------------
+# OPTION: secondradius
+#
+# Configure the radius of the second hand.
+#
+itcl::configbody ::iwidgets::Watch::secondradius {
+ _displayClock
+}
+