OSDN Git Service

touched all sources to ease next import
[pf3gnuchains/pf3gnuchains3x.git] / itcl / iwidgets3.0.0 / generic / dateentry.itk
1 #
2 # Dateentry
3 # ----------------------------------------------------------------------
4 # Implements a quicken style date entry field with a popup calendar
5 # by combining the datefield and calendar widgets together.  This
6 # allows a user to enter the date via the keyboard or by using the
7 # mouse by selecting the calendar icon which brings up a popup calendar.
8 # ----------------------------------------------------------------------
9 #   AUTHOR:  Mark L. Ulferts          E-mail: mulferts@austin.dsccc.com
10 #
11 #   @(#) $Id$
12 # ----------------------------------------------------------------------
13 #            Copyright (c) 1997 DSC Technologies Corporation
14 # ======================================================================
15 # Permission to use, copy, modify, distribute and license this software 
16 # and its documentation for any purpose, and without fee or written 
17 # agreement with DSC, is hereby granted, provided that the above copyright 
18 # notice appears in all copies and that both the copyright notice and 
19 # warranty disclaimer below appear in supporting documentation, and that 
20 # the names of DSC Technologies Corporation or DSC Communications 
21 # Corporation not be used in advertising or publicity pertaining to the 
22 # software without specific, written prior permission.
23
24 # DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
25 # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
26 # INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
27 # AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, 
28 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL 
29 # DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
30 # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
31 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
32 # ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
33 # SOFTWARE.
34 # ======================================================================
35
36 #
37 # Usual options.
38 #
39 itk::usual Dateentry {
40     keep -background -borderwidth -currentdatefont -cursor \
41         -datefont -dayfont -foreground -highlightcolor \
42         -highlightthickness -labelfont -textbackground -textfont \
43         -titlefont
44 }
45
46 # ------------------------------------------------------------------
47 #                              DATEENTRY
48 # ------------------------------------------------------------------
49 class iwidgets::Dateentry {
50     inherit iwidgets::Datefield
51     
52     constructor {args} {}
53
54     itk_option define -grab grab Grab "global"
55     itk_option define -icon icon Icon {}
56     
57     #
58     # The calendar widget isn't created until needed, yet we need
59     # its options to be available upon creation of a dateentry widget.
60     # So, we'll define them in these class now so they can just be
61     # propagated onto the calendar later.
62     #
63     itk_option define -days days Days {Su Mo Tu We Th Fr Sa}
64     itk_option define -forwardimage forwardImage Image {}
65     itk_option define -backwardimage backwardImage Image {}
66     itk_option define -weekdaybackground weekdayBackground Background \#d9d9d9
67     itk_option define -weekendbackground weekendBackground Background \#d9d9d9
68     itk_option define -outline outline Outline \#d9d9d9
69     itk_option define -buttonforeground buttonForeground Foreground blue
70     itk_option define -foreground foreground Foreground black
71     itk_option define -selectcolor selectColor Foreground red
72     itk_option define -selectthickness selectThickness SelectThickness 3
73     itk_option define -titlefont titleFont Font \
74         -*-helvetica-bold-r-normal--*-140-*
75     itk_option define -dayfont dayFont Font \
76         -*-helvetica-medium-r-normal--*-120-*
77     itk_option define -datefont dateFont Font \
78         -*-helvetica-medium-r-normal--*-120-*
79     itk_option define -currentdatefont currentDateFont Font \
80         -*-helvetica-bold-r-normal--*-120-*
81     itk_option define -startday startDay Day sunday
82     itk_option define -height height Height 165
83     itk_option define -width width Width 200
84     itk_option define -state state State normal
85
86     protected {
87         method _getPopupDate {date}
88         method _releaseGrab {}
89         method _releaseGrabCheck {rootx rooty}
90         method _popup {}
91         method _getDefaultIcon {}
92
93         common _defaultIcon ""
94     }
95 }
96
97 #
98 # Provide a lowercased access method for the dateentry class.
99
100 proc ::iwidgets::dateentry {pathName args} {
101     uplevel ::iwidgets::Dateentry $pathName $args
102 }
103
104 # ------------------------------------------------------------------
105 #                        CONSTRUCTOR
106 # ------------------------------------------------------------------
107 body iwidgets::Dateentry::constructor {args} {
108     #
109     # Create an icon label to act as a button to bring up the 
110     # calendar popup.
111     #
112     itk_component add iconbutton {
113         label $itk_interior.iconbutton -relief raised
114     } {
115         keep -borderwidth -cursor -foreground 
116     }
117     grid $itk_component(iconbutton) -row 0 -column 0 -sticky ns
118     
119     #
120     # Initialize the widget based on the command line options.
121     #
122     eval itk_initialize $args
123 }
124
125 # ------------------------------------------------------------------
126 #                             OPTIONS
127 # ------------------------------------------------------------------
128
129 # ------------------------------------------------------------------
130 # OPTION: -icon
131 #
132 # Specifies the calendar icon image to be used in the date.
133 # Should one not be provided, then a default pixmap will be used
134 # if possible, bitmap otherwise.
135 # ------------------------------------------------------------------
136 configbody iwidgets::Dateentry::icon {
137     if {$itk_option(-icon) == {}} {
138         $itk_component(iconbutton) configure -image [_getDefaultIcon]
139     } else {
140         if {[lsearch [image names] $itk_option(-icon)] == -1} {
141             error "bad icon option \"$itk_option(-icon)\":\
142                    should be an existing image"
143         } else {
144             $itk_component(iconbutton) configure -image $itk_option(-icon)
145         }
146     }
147 }
148
149 # ------------------------------------------------------------------
150 # OPTION: -grab
151 #
152 # Specifies the grab level, local or global, to be obtained when 
153 # bringing up the popup calendar.  The default is global.
154 # ------------------------------------------------------------------
155 configbody iwidgets::Dateentry::grab {
156     switch -- $itk_option(-grab) {
157         "local" - "global" {}
158         default {
159             error "bad grab option \"$itk_option(-grab)\":\
160                    should be local or global"
161         }
162     }
163 }
164
165 # ------------------------------------------------------------------
166 # OPTION: -state
167 #
168 # Specifies the state of the widget which may be disabled or
169 # normal.  A disabled state prevents selection of the date field
170 # or date icon button.
171 # ------------------------------------------------------------------
172 configbody iwidgets::Dateentry::state {
173     switch -- $itk_option(-state) {
174         normal {
175             bind $itk_component(iconbutton) <Button-1> [code $this _popup]
176         }
177         disabled {
178             bind $itk_component(iconbutton) <Button-1> {}
179         }
180     }
181 }
182
183 # ------------------------------------------------------------------
184 #                            METHODS
185 # ------------------------------------------------------------------
186
187 # ------------------------------------------------------------------
188 # PROTECTED METHOD: _getDefaultIcon
189 #
190 # This method is invoked uto retrieve the name of the default icon
191 # image displayed in the icon button.
192 # ------------------------------------------------------------------
193 body iwidgets::Dateentry::_getDefaultIcon {} {
194     if {[lsearch [image types] pixmap] != -1} {
195       set _defaultIcon [image create pixmap -data {
196           /* XPM */
197           static char *calendar[] = {
198           /* width height num_colors chars_per_pixel */
199           "    25    20        6            1",
200           /* colors */
201           ". c #808080",
202           "# c #040404",
203           "a c #848484",
204           "b c #fc0404",
205           "c c #fcfcfc",
206           "d c #c0c0c0",
207           /* pixels */
208           "d##########d###########dd",
209           "d#ccccccccc##ccccccccca#d",
210           "##ccccccccc.#ccccccccc..#",
211           "##cccbbcccca#cccbbbccca.#",
212           "##cccbbcccc.#ccbbbbbcc..#",
213           "##cccbbccc####ccccbbcc..#",
214           "##cccbbcccca#ccccbbbcca.#",
215           "##cccbbcccc.#cccbbbccc..#",
216           "##cccbbcccca#ccbbbcccca.#",
217           "##cccbbbccc.#ccbbbbbcc..#",
218           "##ccccccccc.#ccccccccc..#",
219           "##ccccccccca#ccccccccca.#",
220           "##cc#####c#cd#c#####cc..#",
221           "##cccccccc####cccccccca.#",
222           "##cc#####cc.#cc#####cc..#",
223           "##ccccccccc.#ccccccccc..#",
224           "##ccccccccc.#ccccccccc..#",
225           "##..........#...........#",
226           "###..........#..........#",
227           "#########################"
228          };
229         }]
230     } else {
231         set _defaultIcon [image create bitmap -data {
232             #define calendr2_width 25
233             #define calendr2_height 20
234             static char calendr2_bits[] = {
235                 0xfe,0xf7,0x7f,0xfe,0x02,0x18,0xc0,0xfe,0x03,
236                 0x18,0x80,0xff,0x63,0x10,0x47,0xff,0x43,0x98,
237                 0x8a,0xff,0x63,0x3c,0x4c,0xff,0x43,0x10,0x8a,
238                 0xff,0x63,0x18,0x47,0xff,0x23,0x90,0x81,0xff,
239                 0xe3,0x98,0x4e,0xff,0x03,0x10,0x80,0xff,0x03,
240                 0x10,0x40,0xff,0xf3,0xa5,0x8f,0xff,0x03,0x3c,
241                 0x40,0xff,0xf3,0x99,0x8f,0xff,0x03,0x10,0x40,
242                 0xff,0x03,0x18,0x80,0xff,0x57,0x55,0x55,0xff,
243                 0x57,0xb5,0xaa,0xff,0xff,0xff,0xff,0xff};
244         }]
245     }
246
247     #
248     # Since this image will only need to be created once, we redefine
249     # this method to just return the image name for subsequent calls.
250     #
251     body ::iwidgets::Dateentry::_getDefaultIcon {} {
252         return $_defaultIcon
253     }
254
255     return $_defaultIcon
256 }
257
258 # ------------------------------------------------------------------
259 # PROTECTED METHOD: _popup
260 #
261 # This method is invoked upon selection of the icon button.  It 
262 # creates a calendar widget within a toplevel popup, calculates 
263 # the position at which to display the calendar, performs a grab
264 # and displays the calendar.
265 # ------------------------------------------------------------------
266 body iwidgets::Dateentry::_popup {} {
267     #
268     # First, let's nullify the icon binding so that any another 
269     # selections are ignored until were done with this one.  Next,
270     # change the relief of the icon.
271     #
272     bind $itk_component(iconbutton) <Button-1> {}
273     $itk_component(iconbutton) configure -relief sunken
274
275     #
276     # Create a withdrawn toplevel widget and remove the window 
277     # decoration via override redirect.
278     #
279     itk_component add -private popup {
280         toplevel $itk_interior.popup 
281     } 
282     $itk_component(popup) configure -borderwidth 2 -background black
283     wm withdraw $itk_component(popup)
284     wm overrideredirect $itk_component(popup) 1
285
286     #
287     # Add a binding to button 1 events in order to detect mouse
288     # clicks off the calendar in which case we'll release the grab.
289     # Also add a binding for Escape to always release.
290     #
291     bind $itk_component(popup) <1> [code $this _releaseGrabCheck %X %Y]
292     bind $itk_component(popup) <KeyPress-Escape> [code $this _releaseGrab]
293
294     #
295     # Create the calendar widget and set its cursor properly.
296     #
297     itk_component add calendar {
298         iwidgets::Calendar $itk_component(popup).calendar \
299             -command [code $this _getPopupDate %d]
300     } {
301         usual
302         keep -days -forwardimage -backwardimage -weekdaybackground \
303             -weekendbackground -outline -buttonforeground -selectcolor \
304             -selectthickness -titlefont -dayfont -datefont \
305             -currentdatefont -startday -width -height
306     }
307     grid $itk_component(calendar) -row 0 -column 0
308     $itk_component(calendar) configure -cursor top_left_arrow
309
310     #
311     # The icon button will be used as the basis for the position of the
312     # popup on the screen.  We'll always attempt to locate the popup
313     # off the lower right corner of the button.  If that would put
314     # the popup off the screen, then we'll put above the upper left.
315     #
316     set rootx [winfo rootx $itk_component(iconbutton)]
317     set rooty [winfo rooty $itk_component(iconbutton)]
318     set popupwidth [winfo reqwidth $itk_component(popup)]
319     set popupheight [winfo reqheight $itk_component(popup)]
320
321     set popupx [expr $rootx + 3 + \
322                     [winfo width $itk_component(iconbutton)]]
323     set popupy [expr $rooty + 3 + \
324                     [winfo height $itk_component(iconbutton)]]
325
326     if {([expr $popupx + $popupwidth] > [winfo screenwidth .]) || \
327             ([expr $popupy + $popupheight] > [winfo screenheight .])} {
328         set popupx [expr $rootx - 3 - $popupwidth]
329         set popupy [expr $rooty - 3 - $popupheight]
330     }
331     
332     #
333     # Get the current date from the datefield widget and both
334     # show and select it on the calendar.
335     #
336     $itk_component(calendar) show [get]
337     $itk_component(calendar) select [get]
338
339     #
340     # Display the popup at the calculated position.
341     #
342     wm geometry $itk_component(popup) +$popupx+$popupy
343     wm deiconify $itk_component(popup)
344     tkwait visibility $itk_component(popup)
345
346     #
347     # Perform either a local or global grab based on the -grab option.
348     #
349     if {$itk_option(-grab) == "local"} {
350         grab $itk_component(popup)
351     } else {
352         grab -global $itk_component(popup)
353     }
354
355     #
356     # Make sure the widget is above all others and give it focus.
357     #
358     raise $itk_component(popup)
359     focus $itk_component(calendar)
360 }
361
362 # ------------------------------------------------------------------
363 # PROTECTED METHOD: _popupGetDate
364 #
365 # This method is the callback for selection of a date on the 
366 # calendar.  It releases the grab and sets the date in the
367 # datefield widget.
368 # ------------------------------------------------------------------
369 body iwidgets::Dateentry::_getPopupDate {date} {
370     _releaseGrab 
371     show $date
372 }
373
374 # ------------------------------------------------------------------
375 # PROTECTED METHOD: _releaseGrabCheck rootx rooty
376 #
377 # This method handles mouse button 1 events.  If the selection
378 # occured within the bounds of the calendar, then return normally
379 # and let the calendar handle the event.  Otherwise, we'll drop
380 # the calendar and release the grab.
381 # ------------------------------------------------------------------
382 body iwidgets::Dateentry::_releaseGrabCheck {rootx rooty} {
383     set calx [winfo rootx $itk_component(calendar)]
384     set caly [winfo rooty $itk_component(calendar)]
385     set calwidth [winfo reqwidth $itk_component(calendar)]
386     set calheight [winfo reqheight $itk_component(calendar)]
387
388     if {($rootx < $calx) || ($rootx > [expr $calx + $calwidth]) || \
389             ($rooty < $caly) || ($rooty > [expr $caly + $calheight])} {
390         _releaseGrab
391         return -code break
392     }
393 }
394
395 # ------------------------------------------------------------------
396 # PROTECTED METHOD: _releaseGrab
397 #
398 # This method releases the grab, destroys the popup, changes the 
399 # relief of the button back to raised and reapplies the binding
400 # to the icon button that engages the popup action.
401 # ------------------------------------------------------------------
402 body iwidgets::Dateentry::_releaseGrab {} {
403     grab release $itk_component(popup)
404     $itk_component(iconbutton) configure -relief raised
405     destroy $itk_component(popup) 
406     bind $itk_component(iconbutton) <Button-1> [code $this _popup]
407 }