OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [itcl/] [iwidgets3.0.0/] [generic/] [watch.itk] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
#
2
# Watch
3
# ----------------------------------------------------------------------
4
# Implements a a clock widget in a canvas.
5
#
6
# ----------------------------------------------------------------------
7
#  AUTHOR: John A. Tucker               EMAIL: jatucker@spd.dsccc.com
8
#
9
# ======================================================================
10
#            Copyright (c) 1997 DSC Technologies Corporation
11
# ======================================================================
12
# Permission to use, copy, modify, distribute and license this software
13
# and its documentation for any purpose, and without fee or written
14
# agreement with DSC, is hereby granted, provided that the above copyright
15
# notice appears in all copies and that both the copyright notice and
16
# warranty disclaimer below appear in supporting documentation, and that
17
# the names of DSC Technologies Corporation or DSC Communications
18
# Corporation not be used in advertising or publicity pertaining to the
19
# software without specific, written prior permission.
20
#
21
# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
22
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
23
# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
24
# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
25
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
26
# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
27
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
28
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
29
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30
# SOFTWARE.
31
# ======================================================================
32
 
33
#
34
# Default resources.
35
#
36
option add *Watch.labelFont             \
37
    -*-Courier-Medium-R-Normal--*-120-*-*-*-*-*-*       widgetDefault
38
 
39
#
40
# Usual options.
41
#
42
itk::usual Watch {
43
    keep -background -cursor -labelfont -foreground
44
}
45
 
46
class iwidgets::Watch {
47
 
48
    inherit itk::Widget
49
 
50
    itk_option define -hourradius hourRadius Radius .50
51
    itk_option define -hourcolor hourColor Color red
52
 
53
    itk_option define -minuteradius minuteRadius Radius .80
54
    itk_option define -minutecolor minuteColor Color yellow
55
 
56
    itk_option define -pivotradius pivotRadius Radius .10
57
    itk_option define -pivotcolor pivotColor Color white
58
 
59
    itk_option define -secondradius secondRadius Radius .90
60
    itk_option define -secondcolor secondColor Color black
61
 
62
    itk_option define -clockcolor clockColor Color white
63
    itk_option define -clockstipple clockStipple ClockStipple {}
64
 
65
    itk_option define -state state State normal
66
    itk_option define -showampm showAmPm ShowAmPm true
67
 
68
    itk_option define -tickcolor tickColor Color black
69
 
70
    constructor {args} {}
71
    destructor {}
72
 
73
    #
74
    # Public methods
75
    #
76
    public {
77
        method get {{format "-string"}}
78
        method show {{time "now"}}
79
        method watch {args}
80
    }
81
 
82
    #
83
    # Private methods
84
    #
85
    private {
86
        method _handMotionCB {tag x y}
87
        method _drawHand {tag}
88
        method _handReleaseCB {tag x y}
89
        method _displayClock {{when "later"}}
90
 
91
        variable _interior
92
        variable _radius
93
        variable _theta
94
        variable _extent
95
        variable _reposition ""  ;# non-null => _displayClock pending
96
        variable _timeVar
97
        variable _x0 1
98
        variable _y0 1
99
 
100
        common _ampmVar
101
        common PI [expr 2*asin(1.0)]
102
    }
103
}
104
 
105
#
106
# Provide a lowercased access method for the Watch class.
107
#
108
proc ::iwidgets::watch {pathName args} {
109
    uplevel ::iwidgets::Watch $pathName $args
110
}
111
 
112
#
113
# Use option database to override default resources of base classes.
114
#
115
option add *Watch.width 155 widgetDefault
116
option add *Watch.height 175 widgetDefault
117
 
118
# -----------------------------------------------------------------------------
119
#                        CONSTRUCTOR
120
# -----------------------------------------------------------------------------
121
body iwidgets::Watch::constructor { args } {
122
    #
123
    # Add back to the hull width and height options and make the
124
    # borderwidth zero since we don't need it.
125
    #
126
    set _interior $itk_interior
127
 
128
    itk_option add hull.width hull.height
129
    component hull configure -borderwidth 0
130
    grid propagate $itk_component(hull) no
131
 
132
    set _ampmVar($this) "AM"
133
    set _radius(outer) 1
134
 
135
    set _radius(hour) 1
136
    set _radius(minute) 1
137
    set _radius(second) 1
138
 
139
    set _theta(hour) 30
140
    set _theta(minute) 6
141
    set _theta(second) 6
142
 
143
    set _extent(hour) 14
144
    set _extent(minute) 14
145
    set _extent(second) 2
146
 
147
    set _timeVar(hour) 12
148
    set _timeVar(minute) 0
149
    set _timeVar(second) 0
150
 
151
    #
152
    # Create the frame in which the "AM" and "PM" radiobuttons will be drawn
153
    #
154
    itk_component add frame {
155
        frame $itk_interior.frame
156
    }
157
 
158
    #
159
    # Create the canvas in which the clock will be drawn
160
    #
161
    itk_component add canvas {
162
        canvas $itk_interior.canvas
163
    }
164
    bind $itk_component(canvas)  +[code $this _displayClock]
165
    bind $itk_component(canvas)  +[code $this _displayClock]
166
 
167
    #
168
    # Create the "AM" and "PM" radiobuttons to be drawn in the canvas
169
    #
170
    itk_component add am {
171
        radiobutton $itk_component(frame).am \
172
            -text "AM" \
173
            -value "AM" \
174
            -variable [scope _ampmVar($this)]
175
    } {
176
        usual
177
        rename -font -labelfont labelFont Font
178
    }
179
 
180
    itk_component add pm {
181
        radiobutton $itk_component(frame).pm \
182
            -text "PM" \
183
            -value "PM" \
184
            -variable [scope _ampmVar($this)]
185
    } {
186
        usual
187
        rename -font -labelfont labelFont Font
188
    }
189
 
190
    #
191
    # Create the canvas item for displaying the main oval which encapsulates
192
    # the entire clock.
193
    #
194
    watch create oval 0 0 2 2 -width 5 -tags clock
195
 
196
    #
197
    # Create the canvas items for displaying the 60 ticks marks around the
198
    # inner perimeter of the watch.
199
    #
200
    set extent 3
201
    for {set i 0} {$i < 60} {incr i} {
202
        set start [expr $i*6-1]
203
        set tag [expr {[expr $i%5] == 0 ? "big" : "little"}]
204
        watch create arc 0 0 0 0 \
205
            -style arc \
206
            -extent $extent \
207
            -start $start \
208
            -tags "tick$i tick $tag"
209
    }
210
 
211
    #
212
    # Create the canvas items for displaying the hour, minute, and second hands
213
    # of the watch.  Add bindings to allow the mouse to move and set the
214
    # clock hands.
215
    #
216
    watch create arc 1 1 1 1 -extent 30 -tags minute
217
    watch create arc 1 1 1 1 -extent 30 -tags hour
218
    watch create arc 1 1 1 1 -tags second
219
 
220
    #
221
    # Create the canvas item for displaying the center of the watch in which
222
    # the hour, minute, and second hands will pivot.
223
    #
224
    watch create oval 0 0 1 1 -width 5 -fill black -tags pivot
225
 
226
    #
227
    # Position the "AM/PM" button frame and watch canvas.
228
    #
229
    grid $itk_component(frame) -row 0 -column 0 -sticky new
230
    grid $itk_component(canvas) -row 1 -column 0 -sticky nsew
231
 
232
    grid rowconfigure    $itk_interior 0 -weight 0
233
    grid rowconfigure    $itk_interior 1 -weight 1
234
    grid columnconfigure $itk_interior 0 -weight 1
235
 
236
    eval itk_initialize $args
237
}
238
 
239
# -----------------------------------------------------------------------------
240
#                           DESTURCTOR
241
# -----------------------------------------------------------------------------
242
body iwidgets::Watch::destructor {} {
243
    if {$_reposition != ""} {
244
        after cancel $_reposition
245
    }
246
}
247
 
248
# -----------------------------------------------------------------------------
249
#                            METHODS
250
# -----------------------------------------------------------------------------
251
 
252
# -----------------------------------------------------------------------------
253
# METHOD: _handReleaseCB tag x y
254
#
255
# -----------------------------------------------------------------------------
256
body iwidgets::Watch::_handReleaseCB {tag x y} {
257
 
258
    set atanab [expr atan2(double($y-$_y0),double($x-$_x0))*(180/$PI)]
259
    set degrees [expr {$atanab > 0 ? [expr 360-$atanab] : abs($atanab)}]
260
    set ticks [expr round($degrees/$_theta($tag))]
261
    set _timeVar($tag) [expr ((450-$ticks*$_theta($tag))%360)/$_theta($tag)]
262
 
263
    if {$tag == "hour" && $_timeVar(hour) == 0} {
264
        set _timeVar($tag) 12
265
    }
266
 
267
    _drawHand $tag
268
}
269
 
270
# -----------------------------------------------------------------------------
271
# PROTECTED METHOD: _handMotionCB tag x y
272
#
273
# -----------------------------------------------------------------------------
274
body iwidgets::Watch::_handMotionCB {tag x y} {
275
    if {$x == $_x0 || $y == $_y0} {
276
        return
277
    }
278
 
279
    set a [expr $y-$_y0]
280
    set b [expr $x-$_x0]
281
    set c [expr hypot($a,$b)]
282
 
283
    set atanab [expr atan2(double($a),double($b))*(180/$PI)]
284
    set degrees [expr {$atanab > 0 ? [expr 360-$atanab] : abs($atanab)}]
285
 
286
    set x2 [expr $_x0+$_radius($tag)*($b/double($c))]
287
    set y2 [expr $_y0+$_radius($tag)*($a/double($c))]
288
    watch coords $tag \
289
        [expr $x2-$_radius($tag)] \
290
        [expr $y2-$_radius($tag)] \
291
        [expr $x2+$_radius($tag)] \
292
        [expr $y2+$_radius($tag)]
293
    set start [expr $degrees-180-($_extent($tag)/2)]
294
    watch itemconfigure $tag -start $start -extent $_extent($tag)
295
}
296
 
297
# -----------------------------------------------------------------------------
298
# PROTECTED METHOD: get ?format?
299
#
300
# -----------------------------------------------------------------------------
301
body iwidgets::Watch::get {{format "-string"}} {
302
    set timestr [format "%02d:%02d:%02d %s" \
303
                     $_timeVar(hour) $_timeVar(minute) \
304
                     $_timeVar(second) $_ampmVar($this)]
305
 
306
    switch -- $format {
307
        "-string" {
308
            return $timestr
309
        }
310
        "-clicks" {
311
            return [clock scan $timestr]
312
        }
313
        default {
314
            error "bad format option \"$format\":\
315
                   should be -string or -clicks"
316
        }
317
    }
318
}
319
 
320
# -----------------------------------------------------------------------------
321
# METHOD: watch ?args?
322
#
323
# Evaluates the specified args against the canvas component.
324
# -----------------------------------------------------------------------------
325
body iwidgets::Watch::watch {args} {
326
    return [eval $itk_component(canvas) $args]
327
}
328
 
329
# -----------------------------------------------------------------------------
330
# METHOD: _drawHand tag
331
#
332
# -----------------------------------------------------------------------------
333
body iwidgets::Watch::_drawHand {tag} {
334
 
335
    set degrees [expr abs(450-($_timeVar($tag)*$_theta($tag)))%360]
336
    set radians [expr $degrees*($PI/180)]
337
    set x [expr $_x0+$_radius($tag)*cos($radians)]
338
    set y [expr $_y0+$_radius($tag)*sin($radians)*(-1)]
339
    watch coords $tag \
340
        [expr $x-$_radius($tag)] \
341
        [expr $y-$_radius($tag)] \
342
        [expr $x+$_radius($tag)] \
343
        [expr $y+$_radius($tag)]
344
    set start [expr $degrees-180-($_extent($tag)/2)]
345
    watch itemconfigure $tag -start $start
346
}
347
 
348
# ------------------------------------------------------------------
349
# PUBLIC METHOD: show time
350
#
351
# Changes the currently displayed time to be that of the time
352
# argument.  The time may be specified either as a string or an
353
# integer clock value.  Reference the clock command for more
354
# information on obtaining times and their formats.
355
# ------------------------------------------------------------------
356
body iwidgets::Watch::show {{time "now"}} {
357
    if {$time == "now"} {
358
        set seconds [clock seconds]
359
    } elseif {![catch {clock format $time}]} {
360
        set seconds $time
361
    } elseif {[catch {set seconds [clock scan $time]}]} {
362
        error "bad time: \"$time\", must be a valid time\
363
               string, clock clicks value or the keyword now"
364
    }
365
 
366
    set timestring [clock format $seconds -format "%I %M %S %p"]
367
    set _timeVar(hour)   [expr int(1[lindex $timestring 0] - 100)]
368
    set _timeVar(minute) [expr int(1[lindex $timestring 1] - 100)]
369
    set _timeVar(second) [expr int(1[lindex $timestring 2] - 100)]
370
    set _ampmVar($this) [lindex $timestring 3]
371
 
372
    _drawHand hour
373
    _drawHand minute
374
    _drawHand second
375
}
376
 
377
# -----------------------------------------------------------------------------
378
# PROTECTED METHOD: _displayClock ?when?
379
#
380
# Places the hour, minute, and second dials in the canvas.  If "when" is "now",
381
# the change is applied immediately.  If it is "later" or it is not specified,
382
# then the change is applied later, when the application is idle.
383
# -----------------------------------------------------------------------------
384
body iwidgets::Watch::_displayClock {{when "later"}} {
385
 
386
    if {$when == "later"} {
387
        if {$_reposition == ""} {
388
            set _reposition [after idle [code $this _displayClock now]]
389
        }
390
        return
391
    }
392
 
393
    #
394
    # Compute the center coordinates for the clock based on the
395
    # with and height of the canvas.
396
    #
397
    set width [winfo width $itk_component(canvas)]
398
    set height [winfo height $itk_component(canvas)]
399
    set _x0 [expr $width/2]
400
    set _y0 [expr $height/2]
401
 
402
    #
403
    # Set the radius of the watch, pivot, hour, minute and second items.
404
    #
405
    set _radius(outer) [expr {$_x0 < $_y0 ? $_x0 : $_y0}]
406
    set _radius(pivot) [expr $itk_option(-pivotradius)*$_radius(outer)]
407
    set _radius(hour) [expr $itk_option(-hourradius)*$_radius(outer)]
408
    set _radius(minute) [expr $itk_option(-minuteradius)*$_radius(outer)]
409
    set _radius(second) [expr $itk_option(-secondradius)*$_radius(outer)]
410
    set outerWidth [watch itemcget clock -width]
411
 
412
    #
413
    # Set the coordinates of the clock item
414
    #
415
    set x1Outer $outerWidth
416
    set y1Outer $outerWidth
417
    set x2Outer [expr $width-$outerWidth]
418
    set y2Outer [expr $height-$outerWidth]
419
    watch coords clock $x1Outer $y1Outer $x2Outer $y2Outer
420
 
421
    #
422
    # Set the coordinates of the tick items
423
    #
424
    set offset [expr $outerWidth*2]
425
    set x1Tick [expr $x1Outer+$offset]
426
    set y1Tick [expr $y1Outer+$offset]
427
    set x2Tick [expr $x2Outer-$offset]
428
    set y2Tick [expr $y2Outer-$offset]
429
    for {set i 0} {$i < 60} {incr i} {
430
        watch coords tick$i $x1Tick $y1Tick $x2Tick $y2Tick
431
    }
432
    set maxTickWidth [expr $_radius(outer)-$_radius(second)+1]
433
    set minTickWidth [expr round($maxTickWidth/2)]
434
    watch itemconfigure big -width $maxTickWidth
435
    watch itemconfigure little -width [expr round($maxTickWidth/2)]
436
 
437
    #
438
    # Set the coordinates of the pivot item
439
    #
440
    set x1Center [expr $_x0-$_radius(pivot)]
441
    set y1Center [expr $_y0-$_radius(pivot)]
442
    set x2Center [expr $_x0+$_radius(pivot)]
443
    set y2Center [expr $_y0+$_radius(pivot)]
444
    watch coords pivot $x1Center $y1Center $x2Center $y2Center
445
 
446
    #
447
    # Set the coordinates of the hour, minute, and second dial items
448
    #
449
    watch itemconfigure hour -extent $_extent(hour)
450
    _drawHand hour
451
 
452
    watch itemconfigure minute -extent $_extent(minute)
453
    _drawHand minute
454
 
455
    watch itemconfigure second -extent $_extent(second)
456
    _drawHand second
457
 
458
    set _reposition ""
459
}
460
 
461
# -----------------------------------------------------------------------------
462
#                             OPTIONS
463
# -----------------------------------------------------------------------------
464
 
465
# ------------------------------------------------------------------
466
# OPTION: state
467
#
468
# Configure the editable state of the widget.  Valid values are
469
# normal and disabled.  In a disabled state, the hands of the
470
# watch are not selectabled.
471
# ------------------------------------------------------------------
472
configbody ::iwidgets::Watch::state {
473
    if {$itk_option(-state) == "normal"} {
474
        watch bind minute  \
475
            [code $this _handMotionCB minute %x %y]
476
        watch bind minute  \
477
            [code $this _handReleaseCB minute %x %y]
478
 
479
        watch bind hour  \
480
            [code $this _handMotionCB hour %x %y]
481
        watch bind hour  \
482
            [code $this _handReleaseCB hour %x %y]
483
 
484
        watch bind second  \
485
            [code $this _handMotionCB second %x %y]
486
        watch bind second  \
487
            [code $this _handReleaseCB second %x %y]
488
 
489
        $itk_component(am) configure -state normal
490
        $itk_component(pm) configure -state normal
491
 
492
    } elseif {$itk_option(-state) == "disabled"} {
493
        watch bind minute  {}
494
        watch bind minute  {}
495
 
496
        watch bind hour  {}
497
        watch bind hour  {}
498
 
499
        watch bind second  {}
500
        watch bind second  {}
501
 
502
        $itk_component(am) configure -state disabled \
503
            -disabledforeground [$itk_component(am) cget -background]
504
        $itk_component(pm) configure -state normal \
505
            -disabledforeground [$itk_component(am) cget -background]
506
 
507
    } else {
508
        error "bad state option \"$itk_option(-state)\":\
509
                   should be normal or disabled"
510
    }
511
}
512
 
513
# ------------------------------------------------------------------
514
# OPTION: showampm
515
#
516
# Configure the display of the AM/PM radio buttons.
517
# ------------------------------------------------------------------
518
configbody ::iwidgets::Watch::showampm {
519
    switch -- $itk_option(-showampm) {
520
 
521
            pack forget $itk_component(am)
522
            pack forget $itk_component(pm)
523
        }
524
 
525
        1 - yes - true - on {
526
            pack $itk_component(am) -side left -fill both -expand 1
527
            pack $itk_component(pm) -side right -fill both -expand 1
528
        }
529
 
530
        default {
531
            error "bad showampm option \"$itk_option(-showampm)\":\
532
                   should be boolean"
533
        }
534
    }
535
}
536
 
537
# ------------------------------------------------------------------
538
# OPTION: pivotcolor
539
#
540
# Configure the color of the clock pivot.
541
#
542
configbody ::iwidgets::Watch::pivotcolor {
543
    watch itemconfigure pivot -fill $itk_option(-pivotcolor)
544
}
545
 
546
# ------------------------------------------------------------------
547
# OPTION: clockstipple
548
#
549
# Configure the stipple pattern for the clock fill color.
550
#
551
configbody ::iwidgets::Watch::clockstipple {
552
    watch itemconfigure clock -stipple $itk_option(-clockstipple)
553
}
554
 
555
# ------------------------------------------------------------------
556
# OPTION: clockcolor
557
#
558
# Configure the color of the clock.
559
#
560
configbody ::iwidgets::Watch::clockcolor {
561
    watch itemconfigure clock -fill $itk_option(-clockcolor)
562
}
563
 
564
# ------------------------------------------------------------------
565
# OPTION: hourcolor
566
#
567
# Configure the color of the hour hand.
568
#
569
configbody ::iwidgets::Watch::hourcolor {
570
    watch itemconfigure hour -fill $itk_option(-hourcolor)
571
}
572
 
573
# ------------------------------------------------------------------
574
# OPTION: minutecolor
575
#
576
# Configure the color of the minute hand.
577
#
578
configbody ::iwidgets::Watch::minutecolor {
579
    watch itemconfigure minute -fill $itk_option(-minutecolor)
580
}
581
 
582
# ------------------------------------------------------------------
583
# OPTION: secondcolor
584
#
585
# Configure the color of the second hand.
586
#
587
configbody ::iwidgets::Watch::secondcolor {
588
    watch itemconfigure second -fill $itk_option(-secondcolor)
589
}
590
 
591
# ------------------------------------------------------------------
592
# OPTION: tickcolor
593
#
594
# Configure the color of the ticks.
595
#
596
configbody ::iwidgets::Watch::tickcolor {
597
    watch itemconfigure tick -fill $itk_option(-tickcolor)
598
}
599
 
600
# ------------------------------------------------------------------
601
# OPTION: hourradius
602
#
603
# Configure the radius of the hour hand.
604
#
605
configbody ::iwidgets::Watch::hourradius {
606
    _displayClock
607
}
608
 
609
# ------------------------------------------------------------------
610
# OPTION: minuteradius
611
#
612
# Configure the radius of the minute hand.
613
#
614
configbody ::iwidgets::Watch::minuteradius {
615
    _displayClock
616
}
617
 
618
# ------------------------------------------------------------------
619
# OPTION: secondradius
620
#
621
# Configure the radius of the second hand.
622
#
623
configbody ::iwidgets::Watch::secondradius {
624
    _displayClock
625
}
626
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.