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

Subversion Repositories or1k

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
# Spindate
2
# ----------------------------------------------------------------------
3
# Implements a Date spinner widget.  A date spinner contains three
4
# Spinner widgets:  one Spinner for months, one SpinInt for days,
5
# and one SpinInt for years.  Months can be specified as abbreviated
6
# strings, integers or a user-defined list.  Options exist to manage to
7
# behavior, appearance, and format of each component spinner.
8
#
9
# ----------------------------------------------------------------------
10
#  AUTHOR: Sue Yockey                  EMAIL: yockey@actc.com
11
#          Mark L. Ulferts                    mulferts@austin.dsccc.com
12
#
13
#   @(#) $Id: spindate.itk,v 1.1.1.1 2002-01-16 10:24:50 markom Exp $
14
# ----------------------------------------------------------------------
15
#            Copyright (c) 1997 DSC Technologies Corporation
16
# ======================================================================
17
# Permission to use, copy, modify, distribute and license this software
18
# and its documentation for any purpose, and without fee or written
19
# agreement with DSC, is hereby granted, provided that the above copyright
20
# notice appears in all copies and that both the copyright notice and
21
# warranty disclaimer below appear in supporting documentation, and that
22
# the names of DSC Technologies Corporation or DSC Communications
23
# Corporation not be used in advertising or publicity pertaining to the
24
# software without specific, written prior permission.
25
#
26
# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
28
# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
29
# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
30
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
31
# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
32
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
33
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
34
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
35
# SOFTWARE.
36
# ======================================================================
37
 
38
#
39
# Default resources.
40
#
41
option add *Spindate.monthLabel "Month" widgetDefault
42
option add *Spindate.dayLabel "Day" widgetDefault
43
option add *Spindate.yearLabel "Year" widgetDefault
44
option add *Spindate.monthWidth 4 widgetDefault
45
option add *Spindate.dayWidth 4 widgetDefault
46
option add *Spindate.yearWidth 4 widgetDefault
47
 
48
#
49
# Usual options.
50
#
51
itk::usual Spindate {
52
    keep -background -cursor -foreground -labelfont -textbackground -textfont
53
}
54
 
55
# ------------------------------------------------------------------
56
#                            SPINDATE
57
# ------------------------------------------------------------------
58
class iwidgets::Spindate {
59
    inherit itk::Widget
60
 
61
    constructor {args} {}
62
    destructor {}
63
 
64
    itk_option define -labelpos labelPos Position w
65
    itk_option define -orient orient Orient vertical
66
    itk_option define -monthon monthOn MonthOn true
67
    itk_option define -dayon dayOn DayOn true
68
    itk_option define -yearon yearOn YearOn true
69
    itk_option define -datemargin dateMargin Margin 1
70
    itk_option define -yeardigits yearDigits YearDigits 4
71
    itk_option define -monthformat monthFormat MonthFormat integer
72
 
73
    public {
74
        method get {{format "-string"}}
75
        method show {{date now}}
76
    }
77
 
78
    protected {
79
        method _packDate {{when later}}
80
        variable _repack {}             ;# Reconfiguration flag.
81
    }
82
 
83
    private {
84
        method _lastDay {month year}
85
        method _spinMonth {direction}
86
        method _spinDay {direction}
87
 
88
        variable _monthFormatStr "%m"
89
        variable _yearFormatStr "%Y"
90
        variable _interior
91
    }
92
}
93
 
94
#
95
# Provide a lowercased access method for the Spindate class.
96
#
97
proc ::iwidgets::spindate {pathName args} {
98
    uplevel ::iwidgets::Spindate $pathName $args
99
}
100
 
101
# ------------------------------------------------------------------
102
#                        CONSTRUCTOR
103
# ------------------------------------------------------------------
104
body iwidgets::Spindate::constructor {args} {
105
    set _interior $itk_interior
106
 
107
    set clicks [clock seconds]
108
 
109
    #
110
    # Create Month Spinner
111
    #
112
    itk_component add month {
113
        iwidgets::Spinner $itk_interior.month  -fixed 2 -justify right \
114
            -decrement [code $this _spinMonth -1] \
115
            -increment [code $this _spinMonth 1]
116
    } {
117
        keep -background -cursor -arroworient -foreground \
118
                -labelfont -labelmargin -relief -textbackground \
119
                -textfont -repeatdelay -repeatinterval
120
 
121
        rename -labeltext -monthlabel monthLabel Text
122
        rename -width -monthwidth monthWidth Width
123
    }
124
 
125
    #
126
    # Take off the default bindings for selction and motion.
127
    #
128
    bind [$itk_component(month) component entry] <1> {break}
129
    bind [$itk_component(month) component entry]  {break}
130
 
131
    #
132
    # Create Day Spinner
133
    #
134
    itk_component add day {
135
        iwidgets::Spinint $itk_interior.day -fixed 2 -justify right \
136
            -decrement [code $this _spinDay -1] \
137
            -increment [code $this _spinDay 1]
138
    } {
139
        keep -background -cursor -arroworient -foreground \
140
                -labelfont -labelmargin -relief -textbackground \
141
                -textfont -repeatdelay -repeatinterval
142
 
143
        rename -labeltext -daylabel dayLabel Text
144
        rename -width -daywidth dayWidth Width
145
    }
146
 
147
    #
148
    # Take off the default bindings for selction and motion.
149
    #
150
    bind [$itk_component(day) component entry] <1> {break}
151
    bind [$itk_component(day) component entry]  {break}
152
 
153
    #
154
    # Create Year Spinner
155
    #
156
    itk_component add year {
157
        iwidgets::Spinint $itk_interior.year -fixed 2 -justify right \
158
            -range {1900 3000}
159
    } {
160
        keep -background -cursor -arroworient -foreground \
161
                -labelfont -labelmargin -relief -textbackground \
162
                -textfont -repeatdelay -repeatinterval
163
 
164
        rename -labeltext -yearlabel yearLabel Text
165
        rename -width -yearwidth yearWidth Width
166
    }
167
 
168
    #
169
    # Take off the default bindings for selction and motion.
170
    #
171
    bind [$itk_component(year) component entry] <1> {break}
172
    bind [$itk_component(year) component entry]  {break}
173
 
174
    #
175
    # Initialize the widget based on the command line options.
176
    #
177
    eval itk_initialize $args
178
 
179
    #
180
    # Show the current date.
181
    #
182
    show now
183
}
184
 
185
# ------------------------------------------------------------------
186
#                           DESTRUCTOR
187
# ------------------------------------------------------------------
188
body iwidgets::Spindate::destructor {} {
189
    if {$_repack != ""} {after cancel $_repack}
190
}
191
 
192
# ------------------------------------------------------------------
193
#                             OPTIONS
194
# ------------------------------------------------------------------
195
 
196
# ------------------------------------------------------------------
197
# OPTION: -labelpos
198
#
199
# Specifies the location of all 3 spinners' labels.
200
# ------------------------------------------------------------------
201
configbody iwidgets::Spindate::labelpos {
202
    switch $itk_option(-labelpos) {
203
        n {
204
            $itk_component(month) configure -labelpos n
205
            $itk_component(day) configure -labelpos n
206
            $itk_component(year) configure -labelpos n
207
 
208
            #
209
            # Un-align labels
210
            #
211
            $itk_component(month) configure -labelmargin 1
212
            $itk_component(day) configure -labelmargin 1
213
            $itk_component(year) configure -labelmargin 1
214
        }
215
 
216
        s {
217
            $itk_component(month) configure -labelpos s
218
            $itk_component(day) configure -labelpos s
219
            $itk_component(year) configure -labelpos s
220
 
221
            #
222
            # Un-align labels
223
            #
224
            $itk_component(month) configure -labelmargin 1
225
            $itk_component(day) configure -labelmargin 1
226
            $itk_component(year) configure -labelmargin 1
227
        }
228
 
229
        w {
230
            $itk_component(month) configure -labelpos w
231
            $itk_component(day) configure -labelpos w
232
            $itk_component(year) configure -labelpos w
233
        }
234
 
235
        e {
236
            $itk_component(month) configure -labelpos e
237
            $itk_component(day) configure -labelpos e
238
            $itk_component(year) configure -labelpos e
239
 
240
            #
241
            # Un-align labels
242
            #
243
            $itk_component(month) configure -labelmargin 1
244
            $itk_component(day) configure -labelmargin 1
245
            $itk_component(year) configure -labelmargin 1
246
        }
247
 
248
        default {
249
            error "bad labelpos option \"$itk_option(-labelpos)\",\
250
                    should be n, s, w or e"
251
        }
252
    }
253
 
254
    _packDate
255
}
256
 
257
# ------------------------------------------------------------------
258
# OPTION: -orient
259
#
260
# Specifies the orientation of the 3 spinners for Month, Day
261
# and year.
262
# ------------------------------------------------------------------
263
configbody iwidgets::Spindate::orient {
264
    _packDate
265
}
266
 
267
# ------------------------------------------------------------------
268
# OPTION: -monthon
269
#
270
# Specifies whether or not to display the month spinner.
271
# ------------------------------------------------------------------
272
configbody iwidgets::Spindate::monthon {
273
    _packDate
274
}
275
 
276
# ------------------------------------------------------------------
277
# OPTION: -dayon
278
#
279
# Specifies whether or not to display the day spinner.
280
# ------------------------------------------------------------------
281
configbody iwidgets::Spindate::dayon {
282
    _packDate
283
}
284
 
285
# ------------------------------------------------------------------
286
# OPTION: -yearon
287
#
288
# Specifies whether or not to display the year spinner.
289
# ------------------------------------------------------------------
290
configbody iwidgets::Spindate::yearon {
291
    _packDate
292
}
293
 
294
# ------------------------------------------------------------------
295
# OPTION: -datemargin
296
#
297
# Specifies the margin space between the month and day spinners
298
# and the day and year spinners.
299
# ------------------------------------------------------------------
300
configbody iwidgets::Spindate::datemargin {
301
    _packDate
302
}
303
 
304
# ------------------------------------------------------------------
305
# OPTION: -yeardigits
306
#
307
# Number of digits for year display, 2 or 4
308
# ------------------------------------------------------------------
309
configbody iwidgets::Spindate::yeardigits {
310
    set clicks [clock seconds]
311
 
312
    switch $itk_option(-yeardigits) {
313
        "2" {
314
            $itk_component(year) configure -width 2 -fixed 2
315
            $itk_component(year) clear
316
            $itk_component(year) insert 0 [clock format $clicks -format "%y"]
317
            set _yearFormatStr "%y"
318
        }
319
 
320
        "4" {
321
            $itk_component(year) configure -width 4 -fixed 4
322
            $itk_component(year) clear
323
            $itk_component(year) insert 0 [clock format $clicks -format "%Y"]
324
            set _yearFormatStr "%Y"
325
        }
326
 
327
        default {
328
            error "bad yeardigits option \"$itk_option(-yeardigits)\",\
329
                    should be 2 or 4"
330
        }
331
    }
332
}
333
 
334
# ------------------------------------------------------------------
335
# OPTION: -monthformat
336
#
337
# Format of month display, integers (1-12) or brief strings (Jan -
338
# Dec), or full strings (January - December).
339
# ------------------------------------------------------------------
340
configbody iwidgets::Spindate::monthformat {
341
    set clicks [clock seconds]
342
 
343
    if {$itk_option(-monthformat) == "brief"} {
344
        $itk_component(month) configure -width 3 -fixed 3
345
        $itk_component(month) delete 0 end
346
        $itk_component(month) insert 0 [clock format $clicks -format "%b"]
347
        set _monthFormatStr "%b"
348
 
349
    } elseif {$itk_option(-monthformat) == "full"} {
350
        $itk_component(month) configure -width 9 -fixed 9
351
        $itk_component(month) delete 0 end
352
        $itk_component(month) insert 0 [clock format $clicks -format "%B"]
353
        set _monthFormatStr "%B"
354
 
355
    } elseif {$itk_option(-monthformat) == "integer"} {
356
        $itk_component(month) configure -width 2 -fixed 2
357
        $itk_component(month) delete 0 end
358
        $itk_component(month) insert 0 [clock format $clicks -format "%m"]
359
        set _monthFormatStr "%m"
360
 
361
    } else {
362
        error "bad monthformat option\
363
                \"$itk_option(-monthformat)\", should be\
364
                \"integer\", \"brief\" or \"full\""
365
    }
366
}
367
 
368
# ------------------------------------------------------------------
369
#                            METHODS
370
# ------------------------------------------------------------------
371
 
372
# ------------------------------------------------------------------
373
# METHOD: get ?format?
374
#
375
# Return the current contents of the spindate widget in one of
376
# two formats string or as an integer clock value using the -string
377
# and -clicks options respectively.  The default is by string.
378
# Reference the clock command for more information on obtaining dates
379
# and their formats.
380
# ------------------------------------------------------------------
381
body iwidgets::Spindate::get {{format "-string"}} {
382
    set month [$itk_component(month) get]
383
    set day [$itk_component(day) get]
384
    set year [$itk_component(year) get]
385
 
386
    if {[regexp {[0-9]+} $month]} {
387
        set datestr "$month/$day/$year"
388
    } else {
389
        set datestr "$day $month $year"
390
    }
391
 
392
    switch -- $format {
393
        "-string" {
394
            return $datestr
395
        }
396
        "-clicks" {
397
            return [clock scan $datestr]
398
        }
399
        default {
400
            error "bad format option \"$format\":\
401
                   should be -string or -clicks"
402
        }
403
    }
404
}
405
 
406
# ------------------------------------------------------------------
407
# PUBLIC METHOD: show date
408
#
409
# Changes the currently displayed date to be that of the date
410
# argument.  The date may be specified either as a string or an
411
# integer clock value.  Reference the clock command for more
412
# information on obtaining dates and their formats.
413
# ------------------------------------------------------------------
414
body iwidgets::Spindate::show {{date "now"}} {
415
    #
416
    # Convert the date to a clock clicks value.
417
    #
418
    if {$date == "now"} {
419
        set seconds [clock seconds]
420
    } else {
421
        if {[catch {clock format $date}] == 0} {
422
            set seconds $date
423
        } elseif {[catch {set seconds [clock scan $date]}] != 0} {
424
            error "bad date: \"$date\", must be a valid date\
425
               string, clock clicks value or the keyword now"
426
        }
427
    }
428
 
429
    #
430
    # Display the month based on the -monthformat option.
431
    #
432
    switch $itk_option(-monthformat) {
433
        "brief" {
434
            $itk_component(month) delete 0 end
435
            $itk_component(month) insert 0 [clock format $seconds -format "%b"]
436
        }
437
        "full" {
438
            $itk_component(month) delete 0 end
439
            $itk_component(month) insert 0 [clock format $seconds -format "%B"]
440
        }
441
        "integer" {
442
            $itk_component(month) delete 0 end
443
            $itk_component(month) insert 0 [clock format $seconds -format "%m"]
444
        }
445
    }
446
 
447
    #
448
    # Display the day.
449
    #
450
    $itk_component(day) delete 0 end
451
    $itk_component(day) insert end [clock format $seconds -format "%d"]
452
 
453
    #
454
    # Display the year based on the -yeardigits option.
455
    #
456
    switch $itk_option(-yeardigits) {
457
        "2" {
458
            $itk_component(year) delete 0 end
459
            $itk_component(year) insert 0 [clock format $seconds -format "%y"]
460
        }
461
 
462
        "4" {
463
            $itk_component(year) delete 0 end
464
            $itk_component(year) insert 0 [clock format $seconds -format "%Y"]
465
        }
466
    }
467
 
468
    return
469
}
470
 
471
# ----------------------------------------------------------------
472
# PRIVATE METHOD: _spinMonth direction
473
#
474
# Increment or decrement month value.  We need to get the values
475
# for all three fields so we can make sure the day agrees with
476
# the month.  Should the current day be greater than the day for
477
# the spun month, then the day is set to the last day for the
478
# new month.
479
# ----------------------------------------------------------------
480
body iwidgets::Spindate::_spinMonth {direction} {
481
    set month [$itk_component(month) get]
482
    set day [$itk_component(day) get]
483
    set year [$itk_component(year) get]
484
 
485
    #
486
    # There appears to be a bug in the Tcl clock command in that it
487
    # can't scan a date like "12/31/1999 1 month" or any other date with
488
    # a year above 2000, but it has no problem scanning "07/01/1998 1 month".
489
    # So, we're going to play a game and increment by days until this
490
    # is fixed in Tcl.
491
    #
492
    if {$direction == 1} {
493
        set incrdays 32
494
        set day 01
495
    } else {
496
        set incrdays -28
497
        set day 28
498
    }
499
 
500
    if {[regexp {[0-9]+} $month]} {
501
        set clicks [clock scan "$month/$day/$year $incrdays day"]
502
    } else {
503
        set clicks [clock scan "$day $month $year $incrdays day"]
504
    }
505
 
506
    $itk_component(month) clear
507
    $itk_component(month) insert 0 \
508
        [clock format $clicks -format $_monthFormatStr]
509
 
510
    set lastday [_lastDay [$itk_component(month) get] $year]
511
 
512
    if {$day > $lastday} {
513
        $itk_component(day) clear
514
        $itk_component(day) insert end $lastday
515
    }
516
}
517
 
518
# ----------------------------------------------------------------
519
# PRIVATE METHOD: _spinDay direction
520
#
521
# Increment or decrement day value.  If the previous day was the
522
# first, then set the new day to the last day for the current
523
# month.  If it was the last day of the month, change it to the
524
# first.  Otherwise, spin it to the next day.
525
# ----------------------------------------------------------------
526
body iwidgets::Spindate::_spinDay {direction} {
527
    set month [$itk_component(month) get]
528
    set day [$itk_component(day) get]
529
    set year [$itk_component(year) get]
530
    set lastday [_lastDay $month $year]
531
    set currclicks [get -clicks]
532
 
533
    $itk_component(day) delete 0 end
534
 
535
    if {(($day == "01") || ($day == "1")) && ($direction == -1)} {
536
        $itk_component(day) insert 0 $lastday
537
        return
538
    }
539
 
540
    if {($day == $lastday) && ($direction == 1)} {
541
        $itk_component(day) insert 0 "01"
542
        return
543
    }
544
 
545
    set clicks [clock scan "$direction day" -base $currclicks]
546
    $itk_component(day) insert 0 [clock format $clicks -format "%d"]
547
}
548
 
549
# ------------------------------------------------------------------
550
# PRIVATE METHOD: _packDate when
551
#
552
# Pack the components of the date spinner.  If "when" is "now", the
553
# change is applied immediately.  If it is "later" or it is not
554
# specified, then the change is applied later, when the application
555
# is idle.
556
# ------------------------------------------------------------------
557
body iwidgets::Spindate::_packDate {{when later}} {
558
    if {$when == "later"} {
559
        if {$_repack == ""} {
560
            set _repack [after idle [code $this _packDate now]]
561
        }
562
        return
563
    } elseif {$when != "now"} {
564
        error "bad option \"$when\": should be now or later"
565
    }
566
 
567
    #
568
    # Turn off the minsizes for all the rows and columns.
569
    #
570
    for {set i 0} {$i < 5} {incr i} {
571
        grid rowconfigure $_interior $i -minsize 0
572
        grid columnconfigure $_interior $i -minsize 0
573
    }
574
 
575
    #
576
    # Get some boolean 1/0 values for the -monthon and -dayon options.
577
    # We need this later so that Tcl doesn't complain about operands
578
    # of || being strings.
579
    #
580
    set monthon [expr {$itk_option(-monthon) == "1"}]
581
    set dayon [expr {$itk_option(-dayon) == "1"}]
582
 
583
    set _repack ""
584
 
585
    #
586
    # Based on the orientation, use the grid to place the components into
587
    # the proper rows and columns.
588
    #
589
    switch $itk_option(-orient) {
590
        vertical {
591
            set row -1
592
 
593
            if {$itk_option(-monthon)} {
594
                grid $itk_component(month) -row [incr row] -column 0 \
595
                    -sticky nsew
596
            } else {
597
                grid forget $itk_component(month)
598
            }
599
 
600
            if {$itk_option(-dayon)} {
601
                if {$itk_option(-dayon)} {
602
                    grid rowconfigure $_interior [incr row] \
603
                        -minsize $itk_option(-datemargin)
604
                }
605
 
606
                grid $itk_component(day) -row [incr row] -column 0 \
607
                    -sticky nsew
608
            } else {
609
                grid forget $itk_component(day)
610
            }
611
 
612
            if {$itk_option(-yearon)} {
613
                if {$monthon || $dayon} {
614
                    grid rowconfigure $_interior [incr row] \
615
                        -minsize $itk_option(-datemargin)
616
                }
617
 
618
                grid $itk_component(year) -row [incr row] -column 0 \
619
                    -sticky nsew
620
            } else {
621
                grid forget $itk_component(year)
622
            }
623
 
624
            if {$itk_option(-labelpos) == "w"} {
625
                iwidgets::Labeledwidget::alignlabels $itk_component(month) \
626
                        $itk_component(day) $itk_component(year)
627
            }
628
        }
629
 
630
        horizontal {
631
            set column -1
632
 
633
            if {$itk_option(-monthon)} {
634
                grid $itk_component(month) -row 0 -column [incr column] \
635
                    -sticky nsew
636
            } else {
637
                grid forget $itk_component(month)
638
            }
639
 
640
            if {$itk_option(-dayon)} {
641
                if {$itk_option(-monthon)} {
642
                    grid columnconfigure $_interior [incr column] \
643
                        -minsize $itk_option(-datemargin)
644
                }
645
 
646
                grid $itk_component(day) -row 0 -column [incr column] \
647
                    -sticky nsew
648
            } else {
649
                grid forget $itk_component(day)
650
            }
651
 
652
            if {$itk_option(-yearon)} {
653
                if {$monthon || $dayon} {
654
                    grid columnconfigure $_interior [incr column] \
655
                        -minsize $itk_option(-datemargin)
656
                }
657
 
658
                grid $itk_component(year) -row 0 -column [incr column] \
659
                    -sticky nsew
660
            } else {
661
                grid forget $itk_component(year)
662
            }
663
 
664
            #
665
            # Un-align labels.
666
            #
667
            $itk_component(month) configure -labelmargin 1
668
            $itk_component(day) configure -labelmargin 1
669
            $itk_component(year) configure -labelmargin 1
670
        }
671
 
672
        default {
673
            error "bad orient option \"$itk_option(-orient)\", should\
674
                    be \"vertical\" or \"horizontal\""
675
        }
676
    }
677
}
678
 
679
# ------------------------------------------------------------------
680
# PRIVATE METHOD: _lastDay month year
681
#
682
# Internal method which determines the last day of the month for
683
# the given month and year.  We start at 28 and go forward till
684
# we fail.  Crude but effective.
685
# ------------------------------------------------------------------
686
body iwidgets::Spindate::_lastDay {month year} {
687
    set lastone 28
688
 
689
    for {set lastone 28} {$lastone < 32} {incr lastone} {
690
        if {[regexp {[0-9]+} $month]} {
691
            if {[catch {clock scan "$month/[expr $lastone + 1]/$year"}] != 0} {
692
                return $lastone
693
            }
694
        } else {
695
            if {[catch {clock scan "[expr $lastone + 1] $month $year"}] != 0} {
696
                return $lastone
697
            }
698
        }
699
    }
700
}

powered by: WebSVN 2.1.0

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