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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
#
2
# Calendar
3
# ----------------------------------------------------------------------
4
# Implements a calendar widget for the selection of a date.  It displays
5
# a single month at a time.  Buttons exist on the top to change the
6
# month in effect turning th pages of a calendar.  As a page is turned,
7
# the dates for the month are modified.  Selection of a date visually
8
# marks that date.  The selected value can be monitored via the
9
# -command option or just retrieved using the get method.  Methods also
10
# exist to select a date and show a particular month.  The option set
11
# allows the calendars appearance to take on many forms.
12
# ----------------------------------------------------------------------
13
# AUTHOR:  Mark L. Ulferts             E-mail: mulferts@austin.dsccc.com
14
#
15
# ACKNOWLEDGEMENTS: Michael McLennan   E-mail: mmclennan@lucent.com
16
#
17
# This code is an [incr Tk] port of the calendar code shown in Michael
18
# J. McLennan's book "Effective Tcl" from Addison Wesley.  Small
19
# modificiations were made to the logic here and there to make it a
20
# mega-widget and the command and option interface was expanded to make
21
# it even more configurable, but the underlying logic is the same.
22
#
23
# @(#) $Id: calendar.itk,v 1.1.1.1 2002-01-16 10:24:50 markom Exp $
24
# ----------------------------------------------------------------------
25
#            Copyright (c) 1997 DSC Technologies Corporation
26
# ======================================================================
27
# Permission to use, copy, modify, distribute and license this software
28
# and its documentation for any purpose, and without fee or written
29
# agreement with DSC, is hereby granted, provided that the above copyright
30
# notice appears in all copies and that both the copyright notice and
31
# warranty disclaimer below appear in supporting documentation, and that
32
# the names of DSC Technologies Corporation or DSC Communications
33
# Corporation not be used in advertising or publicity pertaining to the
34
# software without specific, written prior permission.
35
#
36
# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
37
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
38
# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
39
# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
40
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
41
# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
44
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45
# SOFTWARE.
46
# ======================================================================
47
 
48
#
49
# Usual options.
50
#
51
itk::usual Calendar {
52
    keep -background -cursor
53
}
54
 
55
# ------------------------------------------------------------------
56
#                            CALENDAR
57
# ------------------------------------------------------------------
58
class iwidgets::Calendar {
59
    inherit itk::Widget
60
 
61
    constructor {args} {}
62
 
63
    itk_option define -days days Days {Su Mo Tu We Th Fr Sa}
64
    itk_option define -command command Command {}
65
    itk_option define -forwardimage forwardImage Image {}
66
    itk_option define -backwardimage backwardImage Image {}
67
    itk_option define -weekdaybackground weekdayBackground Background \#d9d9d9
68
    itk_option define -weekendbackground weekendBackground Background \#d9d9d9
69
    itk_option define -outline outline Outline \#d9d9d9
70
    itk_option define -buttonforeground buttonForeground Foreground blue
71
    itk_option define -foreground foreground Foreground black
72
    itk_option define -selectcolor selectColor Foreground red
73
    itk_option define -selectthickness selectThickness SelectThickness 3
74
    itk_option define -titlefont titleFont Font \
75
        -*-helvetica-bold-r-normal--*-140-*
76
    itk_option define -dayfont dayFont Font \
77
        -*-helvetica-medium-r-normal--*-120-*
78
    itk_option define -datefont dateFont Font \
79
        -*-helvetica-medium-r-normal--*-120-*
80
    itk_option define -currentdatefont currentDateFont Font \
81
        -*-helvetica-bold-r-normal--*-120-*
82
    itk_option define -startday startDay Day sunday
83
 
84
    public method get {{format "-string"}} ;# Returns the selected date
85
    public method select {{date_ "now"}}   ;# Selects date, moving select ring
86
    public method show {{date_ "now"}}     ;# Displays a specific date
87
 
88
    protected method _drawtext {canvas_ day_ date_ now_ x0_ y0_ x1_ y1_}
89
 
90
    private method _change {delta_}
91
    private method _configureHandler {}
92
    private method _redraw {}
93
    private method _days {{wmax {}}}
94
    private method _layout {time_}
95
    private method _select {date_}
96
    private method _selectEvent {date_}
97
    private method _adjustday {day_}
98
    private method _percentSubst {pattern_ string_ subst_}
99
 
100
    private variable _time {}
101
    private variable _selected {}
102
    private variable _initialized 0
103
    private variable _offset 0
104
}
105
 
106
#
107
# Provide a lowercased access method for the Calendar class.
108
#
109
proc ::iwidgets::calendar {pathName args} {
110
    uplevel ::iwidgets::Calendar $pathName $args
111
}
112
 
113
#
114
# Use option database to override default resources of base classes.
115
#
116
option add *Calendar.width 200 widgetDefault
117
option add *Calendar.height 165 widgetDefault
118
 
119
# ------------------------------------------------------------------
120
#                        CONSTRUCTOR
121
# ------------------------------------------------------------------
122
body iwidgets::Calendar::constructor {args} {
123
    #
124
    # Create the canvas which displays each page of the calendar.
125
    #
126
    itk_component add page {
127
        canvas $itk_interior.page
128
    } {
129
        keep -background -cursor -width -height
130
    }
131
    pack $itk_component(page) -expand yes -fill both
132
 
133
    #
134
    # Create the forward and backward buttons.  Rather than pack
135
    # them directly in the hull, we'll waittill later and make
136
    # them canvas window items.
137
    #
138
    itk_component add backward {
139
        button $itk_component(page).backward \
140
                -command [code $this _change -1]
141
    } {
142
        keep -background -cursor
143
    }
144
 
145
    itk_component add forward {
146
        button $itk_component(page).forward \
147
                -command [code $this _change +1]
148
    } {
149
        keep -background -cursor
150
    }
151
 
152
    #
153
    # Set the initial time to now.
154
    #
155
    set _time [clock seconds]
156
 
157
    #
158
    # Bind to the configure event which will be used to redraw
159
    # the calendar and display the month.
160
    #
161
    bind $itk_component(page)  [code $this _configureHandler]
162
 
163
    #
164
    # Evaluate the option arguments.
165
    #
166
    eval itk_initialize $args
167
}
168
 
169
# ------------------------------------------------------------------
170
#                             OPTIONS
171
# ------------------------------------------------------------------
172
 
173
# ------------------------------------------------------------------
174
# OPTION: -command
175
#
176
# Sets the selection command for the calendar.  When the user
177
# selects a date on the calendar, the date is substituted in
178
# place of "%d" in this command, and the command is executed.
179
# ------------------------------------------------------------------
180
configbody iwidgets::Calendar::command {}
181
 
182
# ------------------------------------------------------------------
183
# OPTION: -days
184
#
185
# The days option takes a list of values to set the text used to display the
186
# days of the week header above the dates.  The default value is
187
# {Su Mo Tu We Th Fr Sa}.
188
# ------------------------------------------------------------------
189
configbody iwidgets::Calendar::days {
190
    if {$_initialized} {
191
        if {[$itk_component(page) find withtag days] != {}} {
192
            $itk_component(page) delete days
193
            _days
194
        }
195
    }
196
}
197
 
198
# ------------------------------------------------------------------
199
# OPTION: -backwardimage
200
#
201
# Specifies a image to be displayed on the backwards calendar
202
# button.  If none is specified, a default is provided.
203
# ------------------------------------------------------------------
204
configbody iwidgets::Calendar::backwardimage {
205
 
206
    #
207
    # If no image is given, then we'll use the default image.
208
    #
209
    if {$itk_option(-backwardimage) == {}} {
210
 
211
        #
212
        # If the default image hasn't yet been created, then we
213
        # need to create it.
214
        #
215
        if {[lsearch [image names] $this-backward] == -1} {
216
            image create bitmap $this-backward \
217
                    -foreground $itk_option(-buttonforeground) -data {
218
                #define back_width 16
219
                #define back_height 16
220
                static unsigned char back_bits[] = {
221
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x30,
222
                    0xe0, 0x38, 0xf0, 0x3c, 0xf8, 0x3e, 0xfc, 0x3f,
223
                    0xfc, 0x3f, 0xf8, 0x3e, 0xf0, 0x3c, 0xe0, 0x38,
224
                    0xc0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
225
                }
226
        }
227
 
228
        #
229
        # Configure the button to use the default image.
230
        #
231
        $itk_component(backward) configure -image $this-backward
232
 
233
    #
234
    # Else, an image has been specified.  First, we'll need to make sure
235
    # the image really exists before configuring the button to use it.
236
    # If it doesn't generate an error.
237
    #
238
    } else {
239
        if {[lsearch [image names] $itk_option(-backwardimage)] != -1} {
240
            $itk_component(backward) configure \
241
                    -image $itk_option(-backwardimage)
242
        } else {
243
            error "bad image name \"$itk_option(-backwardimage)\":\
244
                    image does not exist"
245
        }
246
 
247
        #
248
        # If we previously created a default image, we'll just remove it.
249
        #
250
        if {[lsearch [image names] $this-backward] != -1} {
251
            image delete $this-backward
252
        }
253
    }
254
}
255
 
256
 
257
# ------------------------------------------------------------------
258
# OPTION: -forwardimage
259
#
260
# Specifies a image to be displayed on the forwards calendar
261
# button.  If none is specified, a default is provided.
262
# ------------------------------------------------------------------
263
configbody iwidgets::Calendar::forwardimage {
264
 
265
    #
266
    # If no image is given, then we'll use the default image.
267
    #
268
    if {$itk_option(-forwardimage) == {}} {
269
 
270
        #
271
        # If the default image hasn't yet been created, then we
272
        # need to create it.
273
        #
274
        if {[lsearch [image names] $this-forward] == -1} {
275
            image create bitmap $this-forward \
276
                    -foreground $itk_option(-buttonforeground) -data {
277
                #define fwd_width 16
278
                #define fwd_height 16
279
                static unsigned char fwd_bits[] = {
280
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03,
281
                    0x1c, 0x07, 0x3c, 0x0f, 0x7c, 0x1f, 0xfc, 0x3f,
282
                    0xfc, 0x3f, 0x7c, 0x1f, 0x3c, 0x0f, 0x1c, 0x07,
283
                    0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
284
                }
285
        }
286
 
287
        #
288
        # Configure the button to use the default image.
289
        #
290
        $itk_component(forward) configure -image $this-forward
291
 
292
    #
293
    # Else, an image has been specified.  First, we'll need to make sure
294
    # the image really exists before configuring the button to use it.
295
    # If it doesn't generate an error.
296
    #
297
    } else {
298
        if {[lsearch [image names] $itk_option(-forwardimage)] != -1} {
299
            $itk_component(forward) configure \
300
                    -image $itk_option(-forwardimage)
301
        } else {
302
            error "bad image name \"$itk_option(-forwardimage)\":\
303
                    image does not exist"
304
        }
305
 
306
        #
307
        # If we previously created a default image, we'll just remove it.
308
        #
309
        if {[lsearch [image names] $this-forward] != -1} {
310
            image delete $this-forward
311
        }
312
    }
313
}
314
 
315
# ------------------------------------------------------------------
316
# OPTION: -weekdaybackground
317
#
318
# Specifies the background for the weekdays which allows it to
319
# be visually distinguished from the weekend.
320
# ------------------------------------------------------------------
321
configbody iwidgets::Calendar::weekdaybackground {
322
    if {$_initialized} {
323
        $itk_component(page) itemconfigure weekday \
324
                -fill $itk_option(-weekdaybackground)
325
    }
326
}
327
 
328
# ------------------------------------------------------------------
329
# OPTION: -weekendbackground
330
#
331
# Specifies the background for the weekdays which allows it to
332
# be visually distinguished from the weekdays.
333
# ------------------------------------------------------------------
334
configbody iwidgets::Calendar::weekendbackground {
335
    if {$_initialized} {
336
        $itk_component(page) itemconfigure weekend \
337
                -fill $itk_option(-weekendbackground)
338
    }
339
}
340
 
341
# ------------------------------------------------------------------
342
# OPTION: -foreground
343
#
344
# Specifies the foreground color for the textual items, buttons,
345
# and divider on the calendar.
346
# ------------------------------------------------------------------
347
configbody iwidgets::Calendar::foreground {
348
    if {$_initialized} {
349
        $itk_component(page) itemconfigure text \
350
                -fill $itk_option(-foreground)
351
        $itk_component(page) itemconfigure line \
352
                -fill $itk_option(-foreground)
353
    }
354
}
355
 
356
# ------------------------------------------------------------------
357
# OPTION: -outline
358
#
359
# Specifies the outline color used to surround the date text.
360
# ------------------------------------------------------------------
361
configbody iwidgets::Calendar::outline {
362
    if {$_initialized} {
363
        $itk_component(page) itemconfigure square \
364
                -outline $itk_option(-outline)
365
    }
366
}
367
 
368
# ------------------------------------------------------------------
369
# OPTION: -buttonforeground
370
#
371
# Specifies the foreground color of the forward and backward buttons.
372
# ------------------------------------------------------------------
373
configbody iwidgets::Calendar::buttonforeground {
374
    if {$_initialized} {
375
        if {$itk_option(-forwardimage) == {}} {
376
            if {[lsearch [image names] $this-forward] != -1} {
377
                $this-forward configure \
378
                    -foreground $itk_option(-buttonforeground)
379
            }
380
        } else {
381
            $itk_option(-forwardimage) configure \
382
                    -foreground $itk_option(-buttonforeground)
383
        }
384
 
385
        if {$itk_option(-backwardimage) == {}} {
386
            if {[lsearch [image names] $this-backward] != -1} {
387
                $this-backward configure \
388
                    -foreground $itk_option(-buttonforeground)
389
            }
390
        } else {
391
            $itk_option(-backwardimage) configure \
392
                    -foreground $itk_option(-buttonforeground)
393
        }
394
    }
395
}
396
 
397
# ------------------------------------------------------------------
398
# OPTION: -selectcolor
399
#
400
# Specifies the color of the ring displayed that distinguishes the
401
# currently selected date.
402
# ------------------------------------------------------------------
403
configbody iwidgets::Calendar::selectcolor {
404
    if {$_initialized} {
405
        $itk_component(page) itemconfigure $_selected-sensor \
406
                -outline $itk_option(-selectcolor)
407
    }
408
}
409
 
410
# ------------------------------------------------------------------
411
# OPTION: -selectthickness
412
#
413
# Specifies the thickness of the ring displayed that distinguishes
414
# the currently selected date.
415
# ------------------------------------------------------------------
416
configbody iwidgets::Calendar::selectthickness {
417
    if {$_initialized} {
418
        $itk_component(page) itemconfigure $_selected-sensor \
419
                -width $itk_option(-selectthickness)
420
    }
421
}
422
 
423
# ------------------------------------------------------------------
424
# OPTION: -titlefont
425
#
426
# Specifies the font used for the title text that consists of the
427
# month and year.
428
# ------------------------------------------------------------------
429
configbody iwidgets::Calendar::titlefont {
430
    if {$_initialized} {
431
        $itk_component(page) itemconfigure title \
432
                -font $itk_option(-titlefont)
433
    }
434
}
435
 
436
# ------------------------------------------------------------------
437
# OPTION: -datefont
438
#
439
# Specifies the font used for the date text that consists of the
440
# day of the month.
441
# ------------------------------------------------------------------
442
configbody iwidgets::Calendar::datefont {
443
    if {$_initialized} {
444
        $itk_component(page) itemconfigure date \
445
                -font $itk_option(-datefont)
446
    }
447
}
448
 
449
# ------------------------------------------------------------------
450
# OPTION: -currentdatefont
451
#
452
# Specifies the font used for the current date text.
453
# ------------------------------------------------------------------
454
configbody iwidgets::Calendar::currentdatefont {
455
    if {$_initialized} {
456
        $itk_component(page) itemconfigure now \
457
                -font $itk_option(-currentdatefont)
458
    }
459
}
460
 
461
# ------------------------------------------------------------------
462
# OPTION: -dayfont
463
#
464
# Specifies the font used for the day of the week text.
465
# ------------------------------------------------------------------
466
configbody iwidgets::Calendar::dayfont {
467
    if {$_initialized} {
468
        $itk_component(page) itemconfigure days \
469
                -font $itk_option(-dayfont)
470
    }
471
}
472
 
473
# ------------------------------------------------------------------
474
# OPTION: -startday
475
#
476
# Specifies the starting day for the week.  The value must be a day of the
477
# week: sunday, monday, tuesday, wednesday, thursday, friday, or
478
# saturday.  The default is sunday.
479
# ------------------------------------------------------------------
480
configbody iwidgets::Calendar::startday {
481
    set day [string tolower $itk_option(-startday)]
482
 
483
    switch $day {
484
        sunday {set _offset 0}
485
        monday {set _offset 1}
486
        tuesday {set _offset 2}
487
        wednesday {set _offset 3}
488
        thursday {set _offset 4}
489
        friday {set _offset 5}
490
        saturday {set _offset 6}
491
        default {
492
            error "bad startday option \"$itk_option(-startday)\":\
493
                   should be sunday, monday, tuesday, wednesday,\
494
                   thursday, friday, or saturday"
495
        }
496
    }
497
 
498
    if {$_initialized} {
499
        $itk_component(page) delete all-page
500
        _redraw
501
    }
502
}
503
 
504
# ------------------------------------------------------------------
505
#                            METHODS
506
# ------------------------------------------------------------------
507
 
508
# ------------------------------------------------------------------
509
# PUBLIC METHOD: get ?format?
510
#
511
# Returns the currently selected date in one of two formats, string
512
# or as an integer clock value using the -string and -clicks
513
# options respectively.  The default is by string.  Reference the
514
# clock command for more information on obtaining dates and their
515
# formats.
516
# ------------------------------------------------------------------
517
body iwidgets::Calendar::get {{format "-string"}} {
518
    switch -- $format {
519
        "-string" {
520
            return $_selected
521
        }
522
        "-clicks" {
523
            return [clock scan $_selected]
524
        }
525
        default {
526
            error "bad format option \"$format\":\
527
                   should be -string or -clicks"
528
        }
529
    }
530
}
531
 
532
# ------------------------------------------------------------------
533
# PUBLIC METHOD: select date_
534
#
535
# Changes the currently selected date to the value specified.
536
# ------------------------------------------------------------------
537
body iwidgets::Calendar::select {{date_ "now"}} {
538
    if {$date_ == "now"} {
539
        set time [clock seconds]
540
    } else {
541
        if {[catch {clock format $date_}] == 0} {
542
            set time $date_
543
        } elseif {[catch {set time [clock scan $date_]}] != 0} {
544
            error "bad date: \"$date_\", must be a valid date string, clock clicks value or the keyword now"
545
        }
546
    }
547
 
548
    _select [clock format $time -format "%m/%d/%Y"]
549
}
550
 
551
# ------------------------------------------------------------------
552
# PUBLIC METHOD: show date_
553
#
554
# Changes the currently display month to be that of the specified
555
# date.
556
# ------------------------------------------------------------------
557
body iwidgets::Calendar::show {{date_ "now"}} {
558
    if {$date_ == "now"} {
559
        set _time [clock seconds]
560
    } else {
561
        if {[catch {clock format $date_}] == 0} {
562
            set _time $date_
563
        } elseif {[catch {set _time [clock scan $date_]}] != 0} {
564
            error "bad date: \"$date_\", must be a valid date string, clock clicks value or the keyword now"
565
        }
566
    }
567
 
568
    $itk_component(page) delete all-page
569
    _redraw
570
}
571
 
572
# ------------------------------------------------------------------
573
# PROTECTED METHOD: _drawtext canvas_ day_ date_ now_
574
#                             x0_ y0_ x1_ y1_
575
#
576
# Draws the text in the date square.  The method is protected such that
577
# it can be overridden in derived classes that may wish to add their
578
# own unique text.  The method receives the day to draw along with
579
# the coordinates of the square.
580
# ------------------------------------------------------------------
581
body iwidgets::Calendar::_drawtext {canvas_ day_ date_ now_ x0_ y0_ x1_ y1_} {
582
    set item [$canvas_ create text \
583
                  [expr (($x1_ - $x0_) / 2) + $x0_] \
584
                  [expr (($y1_ -$y0_) / 2) + $y0_ + 1] \
585
                  -anchor center -text "$day_" \
586
                  -fill $itk_option(-foreground)]
587
 
588
    if {$date_ == $now_} {
589
        $canvas_ itemconfigure $item \
590
            -font $itk_option(-currentdatefont) \
591
            -tags [list all-page date text now]
592
    } else {
593
        $canvas_ itemconfigure $item \
594
            -font $itk_option(-datefont) \
595
            -tags [list all-page date text]
596
    }
597
}
598
 
599
# ------------------------------------------------------------------
600
# PRIVATE METHOD: _configureHandler
601
#
602
# Processes a configure event received on the canvas.  The method
603
# deletes all the current canvas items and forces a redraw.
604
# ------------------------------------------------------------------
605
body iwidgets::Calendar::_configureHandler {} {
606
    set _initialized 1
607
 
608
    $itk_component(page) delete all
609
    _redraw
610
}
611
 
612
# ------------------------------------------------------------------
613
# PRIVATE METHOD: _change delta_
614
#
615
# Changes the current month displayed in the calendar, moving
616
# forward or backward by  months where  is +/-
617
# some number.
618
# ------------------------------------------------------------------
619
body iwidgets::Calendar::_change {delta_} {
620
    set dir [expr ($delta_ > 0) ? 1 : -1]
621
    set month [clock format $_time -format "%m"]
622
    set month [string trimleft $month 0]
623
    set year [clock format $_time -format "%Y"]
624
 
625
    for {set i 0} {$i < abs($delta_)} {incr i} {
626
        incr month $dir
627
        if {$month < 1} {
628
            set month 12
629
            incr year -1
630
        } elseif {$month > 12} {
631
            set month 1
632
            incr year 1
633
        }
634
    }
635
    if {[catch {set _time [clock scan "$month/1/$year"]}]} {
636
        bell
637
    } else {
638
        _redraw
639
    }
640
}
641
 
642
# ------------------------------------------------------------------
643
# PRIVATE METHOD: _redraw
644
#
645
# Redraws the calendar.  This method is invoked whenever the
646
# calendar changes size or we need to effect a change such as draw
647
# it with a new month.
648
# ------------------------------------------------------------------
649
body iwidgets::Calendar::_redraw {} {
650
    #
651
    # Remove all the items that typically change per redraw request
652
    # such as the title and dates.  Also, get the maximum width and
653
    # height of the page.
654
    #
655
    $itk_component(page) delete all-page
656
 
657
    set wmax [winfo width $itk_component(page)]
658
    set hmax [winfo height $itk_component(page)]
659
 
660
    #
661
    # If we haven't yet created the forward and backwards buttons,
662
    # then dot it; otherwise, skip it.
663
    #
664
    if {[$itk_component(page) find withtag button] == {}} {
665
        $itk_component(page) create window 3 3 -anchor nw \
666
                -window $itk_component(backward) -tags button
667
        $itk_component(page) create window [expr $wmax-3] 3 -anchor ne \
668
                -window $itk_component(forward) -tags button
669
    }
670
 
671
    #
672
    # Create the title centered between the buttons.
673
    #
674
    foreach {x0 y0 x1 y1} [$itk_component(page) bbox button] {
675
        set x [expr (($x1-$x0)/2)+$x0]
676
        set y [expr (($y1-$y0)/2)+$y0]
677
    }
678
 
679
    set title [clock format $_time -format "%B %Y"]
680
    $itk_component(page) create text $x $y -anchor center \
681
        -text $title -font $itk_option(-titlefont) \
682
        -fill $itk_option(-foreground) \
683
        -tags [list title text all-page]
684
 
685
    #
686
    # Add the days of the week labels if they haven't yet been created.
687
    #
688
    if {[$itk_component(page) find withtag days] == {}} {
689
        _days $wmax
690
    }
691
 
692
    #
693
    # Add a line between the calendar header and the dates if needed.
694
    #
695
    set bottom [expr [lindex [$itk_component(page) bbox all] 3] + 3]
696
 
697
    if {[$itk_component(page) find withtag line] == {}} {
698
        $itk_component(page) create line 0 $bottom $wmax $bottom \
699
                -width 2 -tags line
700
    }
701
 
702
    incr bottom 3
703
 
704
    #
705
    # Get the layout for the time value and create the date squares.
706
    # This includes the surrounding date rectangle, the date text,
707
    # and the sensor.  Bind selection to the sensor.
708
    #
709
    set current ""
710
    set now [clock format [clock seconds] -format "%m/%d/%Y"]
711
 
712
    set layout [_layout $_time]
713
    set weeks [expr [lindex $layout end] + 1]
714
 
715
    foreach {day date kind dcol wrow} $layout {
716
        set x0 [expr $dcol*($wmax-7)/7+3]
717
        set y0 [expr $wrow*($hmax-$bottom-4)/$weeks+$bottom]
718
        set x1 [expr ($dcol+1)*($wmax-7)/7+3]
719
        set y1 [expr ($wrow+1)*($hmax-$bottom-4)/$weeks+$bottom]
720
 
721
        if {$date == $_selected} {
722
            set current $date
723
        }
724
 
725
        #
726
        # Create the rectangle that surrounds the date and configure
727
        # its background based on the wheather it is a weekday or
728
        # a weekend.
729
        #
730
        set item [$itk_component(page) create rectangle $x0 $y0 $x1 $y1 \
731
                -outline $itk_option(-outline)]
732
 
733
        if {$kind == "weekend"} {
734
            $itk_component(page) itemconfigure $item \
735
                    -fill $itk_option(-weekendbackground) \
736
                    -tags [list all-page square weekend]
737
        } else {
738
            $itk_component(page) itemconfigure $item \
739
                    -fill $itk_option(-weekdaybackground) \
740
                    -tags [list all-page square weekday]
741
        }
742
 
743
        #
744
        # Create the date text and configure its font based on the
745
        # wheather or not it is the current date.
746
        #
747
        _drawtext $itk_component(page) $day $date $now $x0 $y0 $x1 $y1
748
 
749
        #
750
        # Create a sensor area to detect selections.  Bind the
751
        # sensor and pass the date to the bind script.
752
        #
753
        $itk_component(page) create rectangle $x0 $y0 $x1 $y1 \
754
            -outline "" -fill "" \
755
            -tags [list $date-sensor all-sensor all-page]
756
 
757
        $itk_component(page) bind $date-sensor  \
758
            [code $this _selectEvent $date]
759
    }
760
 
761
    #
762
    # Highlight the selected date if it is on this page.
763
    #
764
    if {$current != ""} {
765
        $itk_component(page) itemconfigure $current-sensor \
766
            -outline $itk_option(-selectcolor) \
767
            -width $itk_option(-selectthickness)
768
 
769
        $itk_component(page) raise $current-sensor
770
 
771
    } elseif {$_selected == ""} {
772
        set date [clock format $_time -format "%m/%d/%Y"]
773
        _select $date
774
    }
775
}
776
 
777
# ------------------------------------------------------------------
778
# PRIVATE METHOD: _days
779
#
780
# Used to rewite the days of the week label just below the month
781
# title string.  The days are given in the -days option.
782
# ------------------------------------------------------------------
783
body iwidgets::Calendar::_days {{wmax {}}} {
784
    if {$wmax == {}} {
785
        set wmax [winfo width $itk_component(page)]
786
    }
787
 
788
    set col 0
789
    set bottom [expr [lindex [$itk_component(page) bbox title buttons] 3] + 7]
790
 
791
    foreach dayoweek $itk_option(-days) {
792
        set x0 [expr $col*($wmax/7)]
793
        set x1 [expr ($col+1)*($wmax/7)]
794
 
795
        $itk_component(page) create text \
796
            [expr (($x1 - $x0) / 2) + $x0] $bottom \
797
            -anchor n -text "$dayoweek" \
798
            -fill $itk_option(-foreground) \
799
            -font $itk_option(-dayfont) \
800
            -tags [list days text]
801
 
802
        incr col
803
    }
804
}
805
 
806
# ------------------------------------------------------------------
807
# PRIVATE METHOD: _layout time_
808
#
809
# Used whenever the calendar is redrawn.  Finds the month containing
810
# a  in seconds, and returns a list for all of the days in
811
# that month.  The list looks like this:
812
#
813
#    {day1 date1 kind1 c1 r1  day2 date2 kind2 c2 r2  ...}
814
#
815
# where dayN is a day number like 1,2,3,..., dateN is the date for
816
# dayN, kindN is the day type of weekday or weekend, and cN,rN
817
# are the column/row indices for the square containing that date.
818
# ------------------------------------------------------------------
819
body iwidgets::Calendar::_layout {time_} {
820
    set month [clock format $time_ -format "%m"]
821
    set year  [clock format $time_ -format "%Y"]
822
 
823
    foreach lastday {31 30 29 28} {
824
        if {[catch {clock scan "$month/$lastday/$year"}] == 0} {
825
            break
826
        }
827
    }
828
    set seconds [clock scan "$month/1/$year"]
829
    set firstday [_adjustday [clock format $seconds -format %w]]
830
 
831
    set weeks [expr ceil(double($lastday+$firstday)/7)]
832
 
833
    set rlist ""
834
    for {set day 1} {$day <= $lastday} {incr day} {
835
        set seconds [clock scan "$month/$day/$year"]
836
        set date [clock format $seconds -format "%m/%d/%Y"]
837
        set dayoweek [clock format $seconds -format %w]
838
 
839
        if {$dayoweek == 0 || $dayoweek == 6} {
840
            set kind "weekend"
841
        } else {
842
            set kind "weekday"
843
        }
844
 
845
        set daycol [_adjustday $dayoweek]
846
 
847
        set weekrow [expr ($firstday+$day-1)/7]
848
        lappend rlist $day $date $kind $daycol $weekrow
849
    }
850
    return $rlist
851
}
852
 
853
# ------------------------------------------------------------------
854
# PRIVATE METHOD: _adjustday day_
855
#
856
# Modifies the day to be in accordance with the startday option.
857
# ------------------------------------------------------------------
858
body iwidgets::Calendar::_adjustday {day_} {
859
    set retday [expr $day_ - $_offset]
860
 
861
    if {$retday < 0} {
862
        set retday [expr $retday + 7]
863
    }
864
 
865
    return $retday
866
}
867
 
868
# ------------------------------------------------------------------
869
# PRIVATE METHOD: _select date_
870
#
871
# Selects the current  on the calendar.  Highlights the date
872
# on the calendar, and executes the command associated with the
873
# calendar, with the selected date substituted in place of "%d".
874
# ------------------------------------------------------------------
875
body iwidgets::Calendar::_select {date_} {
876
    set time [clock scan $date_]
877
    set date [clock format $time -format "%m/%d/%Y"]
878
 
879
    set _selected $date
880
 
881
    set current [clock format $_time -format "%m %Y"]
882
    set selected [clock format $time -format "%m %Y"]
883
 
884
    if {$current == $selected} {
885
        $itk_component(page) itemconfigure all-sensor \
886
            -outline "" -width 1
887
 
888
        $itk_component(page) itemconfigure $date-sensor \
889
            -outline $itk_option(-selectcolor) \
890
            -width $itk_option(-selectthickness)
891
        $itk_component(page) raise $date-sensor
892
    } else {
893
        set $_time $time
894
        _redraw
895
    }
896
}
897
 
898
# ------------------------------------------------------------------
899
# PRIVATE METHOD: _selectEvent date_
900
#
901
# Selects the current  on the calendar.  Highlights the date
902
# on the calendar, and executes the command associated with the
903
# calendar, with the selected date substituted in place of "%d".
904
# ------------------------------------------------------------------
905
body iwidgets::Calendar::_selectEvent {date_} {
906
    _select $date_
907
 
908
    if {[string trim $itk_option(-command)] != ""} {
909
        set cmd $itk_option(-command)
910
        set cmd [_percentSubst %d $cmd [get]]
911
        uplevel #0 $cmd
912
    }
913
}
914
 
915
# ------------------------------------------------------------------
916
# PRIVATE METHOD: _percentSubst pattern_ string_ subst_
917
#
918
# This command is a "safe" version of regsub, for substituting
919
# each occurance of <%pattern_> in  with .  The
920
# usual Tcl "regsub" command does the same thing, but also
921
# converts characters like "&" and "\0", "\1", etc. that may
922
# be present in the  string.
923
#
924
# Returns  with  substituted in place of each
925
# <%pattern_>.
926
# ------------------------------------------------------------------
927
body iwidgets::Calendar::_percentSubst {pattern_ string_ subst_} {
928
    if {![string match %* $pattern_]} {
929
        error "bad pattern \"$pattern_\": should be %something"
930
    }
931
 
932
    set rval ""
933
    while {[regexp "(.*)${pattern_}(.*)" $string_ all head tail]} {
934
        set rval "$subst_$tail$rval"
935
        set string_ $head
936
    }
937
    set rval "$string_$rval"
938
}

powered by: WebSVN 2.1.0

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