1 #----------------------------------------------------------------------------
3 # Purpose: Calendar display control
5 # Author: Lorne White (email: lorne.white@telusplanet.net)
10 # Licence: wxWindows license
11 #----------------------------------------------------------------------------
12 # 12/01/2003 - Jeff Grimmett (grimmtooth@softhome.net)
14 # o Updated for wx namespace
15 # o Tested with updated demo
16 # o Added new event type EVT_CALENDAR. The reason for this is that the original
17 # library used a hardcoded ID of 2100 for generating events. This makes it
18 # very difficult to fathom when trying to decode the code since there's no
19 # published API. Creating the new event binder might seem like overkill -
20 # after all, you might ask, why not just use a new event ID and be done with
21 # it? However, a consistent interface is very useful at times; also it makes
22 # it clear that we're not just hunting for mouse clicks -- we're hunting
23 # wabbit^H^H^H^H (sorry bout that) for calender-driven mouse clicks. So
24 # that's my sad story. Shoot me if you must :-)
25 # o There's still one deprecation warning buried in here somewhere, but I
26 # haven't been able to find it yet. It only occurs when displaying a
27 # print preview, and only the first time. It *could* be an error in the
30 # Here's the traceback:
32 # C:\Python\lib\site-packages\wx\core.py:949: DeprecationWarning:
33 # integer argument expected, got float
34 # newobj = _core.new_Rect(*args, **kwargs)
36 # 12/17/2003 - Jeff Grimmett (grimmtooth@softhome.net)
38 # o A few style-guide nips and tucks
39 # o Renamed wxCalendar to Calendar
40 # o Couple of bugfixes
42 # 06/02/2004 - Joerg "Adi" Sieker adi@sieker.info
44 # o Changed color handling, use dictionary instead of members.
45 # This causes all color changes to be ignored if they manipluate the members directly.
46 # SetWeekColor and other method color methods were adapted to use the new dictionary.
47 # o Added COLOR_* constants
48 # o Added SetColor method for Calendar class
49 # o Added 3D look of week header
50 # o Added colors for 3D look of header
51 # o Fixed width calculation.
52 # Because of rounding difference the total width and height of the
53 # calendar could be up to 6 pixels to small. The last column and row
54 # are now wider/taller by the missing amount.
55 # o Added SetTextAlign method to wxCalendar. This exposes logic
56 # which was already there.
57 # o Fixed CalDraw.SetMarg which set set_x_st and set_y_st which don't get used anywhere.
58 # Instead set set_x_mrg and set_y_mrg
59 # o Changed default X and Y Margin to 0.
60 # o Added wxCalendar.SetMargin.
62 # 17/03/2004 - Joerg "Adi" Sieker adi@sieker.info
63 # o Added keyboard navigation to the control.
64 # Use the cursor keys to navigate through the ages. :)
65 # The Home key function as go to today
66 # o select day is now a filled rect instead of just an outline
68 # 15/04/2005 - Joe "shmengie" Brown joebrown@podiatryfl.com
69 # o Adjusted spin control size/placement (On Windows ctrls were overlapping).
70 # o Set Ok/Cancel buttons to wx.ID_OK & wx.ID_CANCEL to provide default dialog
72 # o If no date has been clicked clicked, OnOk set the result to calend's date,
73 # important if keyboard only navigation is used.
75 # 12/10/2006 - Walter Barnes walter_barnes05@yahoo.com
76 # o Fixed CalDraw to properly render months that start on a Sunday.
78 # 21/10/2006 - Walter Barnes walter_barnes05@yahoo.com
79 # o Fixed a bug in Calendar: Shift and Control key status was only recorded for
81 # o Added handlers for wxEVT_MIDDLE_DOWN and wxEVT_MIDDLE_DCLICK to generate
82 # EVT_CALENDAR for these mouse events.
89 CalDays
= [6, 0, 1, 2, 3, 4, 5]
90 AbrWeekday
= {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"}
93 COLOR_GRID_LINES
= "grid_lines"
94 COLOR_BACKGROUND
= "background"
95 COLOR_SELECTION_FONT
= "selection_font"
96 COLOR_SELECTION_BACKGROUND
= "selection_background"
97 COLOR_BORDER
= "border"
98 COLOR_HEADER_BACKGROUND
= "header_background"
99 COLOR_HEADER_FONT
= "header_font"
100 COLOR_WEEKEND_BACKGROUND
= "weekend_background"
101 COLOR_WEEKEND_FONT
= "weekend_font"
103 COLOR_3D_LIGHT
= "3d_light"
104 COLOR_3D_DARK
= "3d_dark"
105 COLOR_HIGHLIGHT_FONT
= "highlight_font"
106 COLOR_HIGHLIGHT_BACKGROUND
= "highlight_background"
108 BusCalDays
= [0, 1, 2, 3, 4, 5, 6]
110 # Calendar click event - added 12/1/03 by jmg (see above)
111 wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED
= wx
.NewEventType()
112 EVT_CALENDAR
= wx
.PyEventBinder(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED
, 1)
119 monthlist
.append(name
)
122 def MakeColor(in_color
):
124 color
= wxNamedColour(in_color
)
131 colors
[COLOR_GRID_LINES
] = 'BLACK'
132 colors
[COLOR_BACKGROUND
] = 'WHITE'
133 colors
[COLOR_SELECTION_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
)
134 colors
[COLOR_SELECTION_BACKGROUND
] =wx
.Colour(255,255,225)
135 colors
[COLOR_BORDER
] = 'BLACK'
136 colors
[COLOR_HEADER_BACKGROUND
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
)
137 colors
[COLOR_HEADER_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
)
138 colors
[COLOR_WEEKEND_BACKGROUND
] = 'LIGHT GREY'
139 colors
[COLOR_WEEKEND_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
)
140 colors
[COLOR_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
)
141 colors
[COLOR_3D_LIGHT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNHIGHLIGHT
)
142 colors
[COLOR_3D_DARK
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
)
143 colors
[COLOR_HIGHLIGHT_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
)
144 colors
[COLOR_HIGHLIGHT_BACKGROUND
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
)
146 # calendar drawing routing
149 def __init__(self
, parent
):
153 self
.scale
= parent
.scale
163 self
.num_auto
= True # auto scale of the cal number day size
164 self
.num_size
= 12 # default size of calendar if no auto size
165 self
.max_num_size
= 12 # maximum size for calendar number
167 self
.num_align_horz
= wx
.ALIGN_CENTRE
# alignment of numbers
168 self
.num_align_vert
= wx
.ALIGN_CENTRE
169 self
.num_indent_horz
= 0 # points indent from position, used to offset if not centered
170 self
.num_indent_vert
= 0
172 self
.week_auto
= True # auto scale of week font text
174 self
.max_week_size
= 12
176 self
.colors
= DefaultColors()
179 self
.bold
= wx
.NORMAL
181 self
.hide_title
= False
182 self
.hide_grid
= False
183 self
.outer_border
= True
185 self
.title_offset
= 0
186 self
.cal_week_scale
= 0.7
187 self
.show_weekend
= False
188 self
.cal_type
= "NORMAL"
190 def SetWeekColor(self
, font_color
, week_color
):
191 # set font and background color for week title
192 self
.colors
[COLOR_HEADER_FONT
] = MakeColor(font_color
)
193 self
.colors
[COLOR_HEADER_BACKGROUND
] = MakeColor(week_color
)
194 self
.colors
[COLOR_3D_LIGHT
] = MakeColor(week_color
)
195 self
.colors
[COLOR_3D_DARK
] = MakeColor(week_color
)
197 def SetSize(self
, size
):
198 self
.set_sizew
= size
[0]
199 self
.set_sizeh
= size
[1]
201 def InitValues(self
): # default dimensions of various elements of the calendar
204 self
.set_cy_st
= 0 # start position
207 self
.set_y_mrg
= 1 # start of vertical draw default
210 def SetPos(self
, xpos
, ypos
):
211 self
.set_cx_st
= xpos
212 self
.set_cy_st
= ypos
214 def SetMarg(self
, xmarg
, ymarg
):
215 self
.set_x_mrg
= xmarg
216 self
.set_y_mrg
= ymarg
217 self
.set_y_end
= ymarg
219 def InitScale(self
): # scale position values
220 self
.sizew
= int(self
.set_sizew
* self
.pwidth
)
221 self
.sizeh
= int(self
.set_sizeh
* self
.pheight
)
223 self
.cx_st
= int(self
.set_cx_st
* self
.pwidth
) # draw start position
224 self
.cy_st
= int(self
.set_cy_st
* self
.pheight
)
226 self
.x_mrg
= int(self
.set_x_mrg
* self
.pwidth
) # calendar draw margins
227 self
.y_mrg
= int(self
.set_y_mrg
* self
.pheight
)
228 self
.y_end
= int(self
.set_y_end
* self
.pheight
)
230 def DrawCal(self
, DC
, sel_lst
=[]):
235 if self
.hide_title
is False:
242 if self
.show_weekend
is True: # highlight weekend dates
245 self
.AddSelect(sel_lst
) # overrides the weekend highlight
247 self
.DrawSel(DC
) # highlighted days
251 def AddSelect(self
, list, cfont
=None, cbackgrd
= None):
253 cfont
= self
.colors
[COLOR_SELECTION_FONT
] # font digit color
255 cbackgrd
= self
.colors
[COLOR_SELECTION_BACKGROUND
] # select background color
258 self
.cal_sel
[val
] = (cfont
, cbackgrd
)
260 # draw border around the outside of the main display rectangle
261 def DrawBorder(self
, DC
, transparent
= False):
262 if self
.outer_border
is True:
263 if transparent
== False:
264 brush
= wx
.Brush(MakeColor(self
.colors
[COLOR_BACKGROUND
]), wx
.SOLID
)
266 brush
= wx
.TRANSPARENT_BRUSH
268 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_BORDER
])))
269 # full display window area
270 rect
= wx
.Rect(self
.cx_st
, self
.cy_st
, self
.sizew
, self
.sizeh
)
271 DC
.DrawRectangleRect(rect
)
273 def DrawFocusIndicator(self
, DC
):
274 if self
.outer_border
is True:
275 DC
.SetBrush(wx
.TRANSPARENT_BRUSH
)
276 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_HIGHLIGHT_BACKGROUND
]), style
=wx
.DOT
))
277 # full display window area
278 rect
= wx
.Rect(self
.cx_st
, self
.cy_st
, self
.sizew
, self
.sizeh
)
279 DC
.DrawRectangleRect(rect
)
281 def DrawNumVal(self
):
284 # calculate the calendar days and offset position
285 def SetCal(self
, year
, month
):
286 self
.InitValues() # reset initial values
292 t
= Date(year
, month
, day
)
293 dow
= self
.dow
= t
.day_of_week
# start day in month
294 dim
= self
.dim
= t
.days_in_month
# number of days in month
296 if self
.cal_type
== "NORMAL":
304 self
.st_pos
= start_pos
307 for i
in range(start_pos
):
308 self
.cal_days
.append('')
312 self
.cal_days
.append(str(i
))
315 self
.end_pos
= start_pos
+ dim
- 1
319 def SetWeekEnd(self
, font_color
=None, backgrd
= None):
320 if font_color
!= None:
321 self
.SetColor(COLOR_WEEKEND_FONT
, MakeColor(font_color
))
323 self
.SetColor(COLOR_WEEKEND_BACKGROUND
, MakeColor(backgrd
))
325 date
= 6 - int(self
.dow
) # start day of first saturday
326 if date
== 0: #...unless we start on Sunday
327 self
.cal_sel
[1] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
))
330 while date
<= self
.dim
:
331 self
.cal_sel
[date
] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
)) # Saturday
335 self
.cal_sel
[date
] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
)) # Sunday
340 # get the display rectange list of the day grid
345 for y
in self
.gridy
[1:-1]:
346 if y
== self
.gridy
[-2]:
349 for x
in self
.gridx
[:-1]:
350 assert type(y
) == int
351 assert type(x
) == int
356 if x
== self
.gridx
[-2]:
359 rect
= wx
.Rect(x
, y
, w
+1, h
+1) # create rect region
372 # month and year title
373 def DrawMonth(self
, DC
):
374 month
= Month
[self
.month
]
377 if self
.sizeh
< _MIDSIZE
:
380 f
= wx
.Font(sizef
, self
.font
, wx
.NORMAL
, self
.bold
)
383 tw
,th
= DC
.GetTextExtent(month
)
384 adjust
= self
.cx_st
+ (self
.sizew
-tw
)/2
385 DC
.DrawText(month
, adjust
, self
.cy_st
+ th
)
387 year
= str(self
.year
)
388 tw
,th
= DC
.GetTextExtent(year
)
389 adjust
= self
.sizew
- tw
- self
.x_mrg
391 self
.title_offset
= th
* 2
393 f
= wx
.Font(sizef
, self
.font
, wx
.NORMAL
, self
.bold
)
395 DC
.DrawText(year
, self
.cx_st
+ adjust
, self
.cy_st
+ th
)
397 def DrawWeek(self
, DC
): # draw the week days
398 # increase by 1 to include all gridlines
399 width
= self
.gridx
[1] - self
.gridx
[0] + 1
400 height
= self
.gridy
[1] - self
.gridy
[0] + 1
401 rect_w
= self
.gridx
[-1] - self
.gridx
[0]
403 f
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
) # initial font setting
405 if self
.week_auto
== True:
406 test_size
= self
.max_week_size
# max size
409 f
.SetPointSize(test_size
)
411 tw
,th
= DC
.GetTextExtent(test_day
)
413 if tw
< width
and th
< height
:
416 test_size
= test_size
- 1
418 f
.SetPointSize(self
.week_size
) # set fixed size
421 DC
.SetTextForeground(MakeColor(self
.colors
[COLOR_HEADER_FONT
]))
426 brush
= wx
.Brush(MakeColor(self
.colors
[COLOR_HEADER_BACKGROUND
]), wx
.SOLID
)
429 if self
.cal_type
== "NORMAL":
432 cal_days
= BusCalDays
435 if val
== cal_days
[-1]:
436 width
= width
+ self
.restW
438 day
= AbrWeekday
[val
]
443 dw
,dh
= DC
.GetTextExtent(day
)
446 diffy
= (height
-dh
)/2
448 x
= self
.gridx
[cnt_x
]
449 y
= self
.gridy
[cnt_y
]
451 pointWH
= (width
, height
)
452 if self
.hide_grid
== False:
453 pen
= wx
.Pen(MakeColor(self
.GetColor(COLOR_GRID_LINES
)), 1, wx
.SOLID
)
455 pen
= wx
.Pen(MakeColor(self
.GetColor(COLOR_BACKGROUND
)), 1, wx
.SOLID
)
457 DC
.DrawRectanglePointSize( pointXY
, pointWH
)
459 old_pen
= DC
.GetPen()
461 pen
= wx
.Pen(MakeColor(self
.colors
[COLOR_3D_LIGHT
]), 1, wx
.SOLID
)
463 # draw the horizontal hilight
464 startPoint
= wx
.Point(x
+ 1 , y
+ 1)
465 endPoint
= wx
.Point(x
+ width
- 1, y
+ 1)
466 DC
.DrawLinePoint(startPoint
, endPoint
)
468 # draw the vertical hilight
469 startPoint
= wx
.Point(x
+ 1 , y
+ 1)
470 endPoint
= wx
.Point(x
+ 1, y
+ height
- 2)
471 DC
.DrawLinePoint(startPoint
, endPoint
)
473 pen
= wx
.Pen(MakeColor(self
.colors
[COLOR_3D_DARK
]), 1, wx
.SOLID
)
476 # draw the horizontal lowlight
477 startPoint
= wx
.Point(x
+ 1, y
+ height
- 2)
478 endPoint
= wx
.Point(x
+ width
- 1, y
+ height
- 2)
479 DC
.DrawLinePoint(startPoint
, endPoint
)
481 # draw the vertical lowlight
482 startPoint
= wx
.Point(x
+ width
- 2 , y
+ 2)
483 endPoint
= wx
.Point(x
+ width
- 2, y
+ height
- 2)
484 DC
.DrawLinePoint(startPoint
, endPoint
)
486 pen
= wx
.Pen(MakeColor(self
.colors
[COLOR_FONT
]), 1, wx
.SOLID
)
490 point
= (x
+diffx
, y
+diffy
)
491 DC
.DrawTextPoint(day
, point
)
494 def _CalcFontSize(self
, DC
, f
):
495 if self
.num_auto
== True:
496 test_size
= self
.max_num_size
# max size
500 f
.SetPointSize(test_size
)
502 tw
,th
= DC
.GetTextExtent(test_day
)
504 if tw
< self
.cellW
and th
< self
.cellH
:
507 test_size
= test_size
- 1
509 f
.SetPointSize(self
.num_size
) # set fixed size
512 # draw the day numbers
513 def DrawNum(self
, DC
):
514 f
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
) # initial font setting
515 self
._CalcFontSize
(DC
, f
)
519 for val
in self
.cal_days
:
520 x
= self
.gridx
[cnt_x
]
521 y
= self
.gridy
[cnt_y
]
523 self
._DrawDayText
(x
, y
, val
, f
, DC
)
531 def _DrawDayText(self
, x
, y
, text
, font
, DC
):
535 num_color
= self
.cal_sel
[num_val
][0]
537 num_color
= self
.colors
[COLOR_FONT
]
539 DC
.SetTextForeground(MakeColor(num_color
))
542 tw
,th
= DC
.GetTextExtent(text
)
544 if self
.num_align_horz
== wx
.ALIGN_CENTRE
:
545 adj_h
= (self
.cellW
- tw
)/2
546 elif self
.num_align_horz
== wx
.ALIGN_RIGHT
:
547 adj_h
= self
.cellW
- tw
549 adj_h
= 0 # left alignment
551 adj_h
= adj_h
+ self
.num_indent_horz
553 if self
.num_align_vert
== wx
.ALIGN_CENTRE
:
554 adj_v
= (self
.cellH
- th
)/2
555 elif self
.num_align_vert
== wx
.ALIGN_BOTTOM
:
556 adj_v
= self
.cellH
- th
558 adj_v
= 0 # left alignment
560 adj_v
= adj_v
+ self
.num_indent_vert
562 DC
.DrawTextPoint(text
, (x
+adj_h
, y
+adj_v
))
564 def DrawDayText(self
, DC
, key
):
565 f
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
) # initial font setting
566 self
._CalcFontSize
(DC
, f
)
568 if key
> self
.end_pos
:
571 val
= self
.cal_days
[key
]
573 cnt_y
= int(key
/ 7)+1
574 x
= self
.gridx
[cnt_x
]
575 y
= self
.gridy
[cnt_y
]
576 self
._DrawDayText
(x
, y
, val
, f
, DC
)
579 # calculate the dimensions in the center of the drawing area
581 borderW
= self
.x_mrg
* 2
582 borderH
= self
.y_mrg
+ self
.y_end
+ self
.title_offset
584 self
.cellW
= int((self
.sizew
- borderW
)/7)
585 self
.cellH
= int((self
.sizeh
- borderH
)/7)
587 self
.restW
= ((self
.sizew
- borderW
)%7 ) - 1
589 # week title adjustment
590 self
.weekHdrCellH
= int(self
.cellH
* self
.cal_week_scale
)
591 # recalculate the cell height exkl. the week header and
592 # subtracting the size
593 self
.cellH
= int((self
.sizeh
- borderH
- self
.weekHdrCellH
)/6)
595 self
.restH
= ((self
.sizeh
- borderH
- self
.weekHdrCellH
)%6 ) - 1
596 self
.calW
= self
.cellW
* 7
597 self
.calH
= self
.cellH
* 6 + self
.weekHdrCellH
599 # highlighted selected days
600 def DrawSel(self
, DC
):
602 for key
in self
.cal_sel
.keys():
603 sel_color
= self
.cal_sel
[key
][1]
604 brush
= wx
.Brush(MakeColor(sel_color
), wx
.SOLID
)
607 if self
.hide_grid
is False:
608 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_GRID_LINES
]), 0))
610 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_BACKGROUND
]), 0))
612 nkey
= key
+ self
.st_pos
-1
615 DC
.DrawRectangleRect(rect
)
617 # calculate and draw the grid lines
618 def DrawGrid(self
, DC
):
619 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_GRID_LINES
]), 0))
624 self
.x_st
= self
.cx_st
+ self
.x_mrg
625 # start postion of draw
626 self
.y_st
= self
.cy_st
+ self
.y_mrg
+ self
.title_offset
630 y2
= y1
+ self
.calH
+ self
.restH
636 if self
.hide_grid
is False:
637 DC
.DrawLinePoint((x1
, y1
), (x1
, y2
))
639 self
.gridx
.append(x1
)
645 x2
= x1
+ self
.calW
+ self
.restW
651 if self
.hide_grid
is False:
652 DC
.DrawLinePoint((x1
, y1
), (x2
, y1
))
654 self
.gridy
.append(y1
)
657 y1
= y1
+ self
.weekHdrCellH
661 def GetColor(self
, name
):
662 return MakeColor(self
.colors
[name
])
664 def SetColor(self
, name
, value
):
665 self
.colors
[name
] = MakeColor(value
)
667 class PrtCalDraw(CalDraw
):
668 def InitValues(self
):
671 # start draw border location
675 # draw offset position
680 # calculate the dimensions in the center of the drawing area
681 def SetPSize(self
, pwidth
, pheight
):
682 self
.pwidth
= int(pwidth
)/self
.scale
683 self
.pheight
= int(pheight
)/self
.scale
685 def SetPreview(self
, preview
):
686 self
.preview
= preview
688 class Calendar( wx
.PyControl
):
689 def __init__(self
, parent
, id, pos
=wx
.DefaultPosition
, size
=wx
.Size(200,200),
690 style
= 0, validator
=wx
.DefaultValidator
,
692 wx
.PyControl
.__init
__(self
, parent
, id, pos
, size
, style | wx
.WANTS_CHARS
, validator
, name
)
694 self
.hasFocus
= False
695 # set the calendar control attributes
697 self
.hide_grid
= False
698 self
.hide_title
= False
699 self
.show_weekend
= False
700 self
.cal_type
= "NORMAL"
701 self
.outer_border
= True
702 self
.num_align_horz
= wx
.ALIGN_CENTRE
703 self
.num_align_vert
= wx
.ALIGN_CENTRE
704 self
.colors
= DefaultColors()
709 self
.select_list
= []
711 self
.SetBackgroundColour(MakeColor(self
.colors
[COLOR_BACKGROUND
]))
712 self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftEvent
)
713 self
.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnLeftDEvent
)
714 self
.Bind(wx
.EVT_RIGHT_DOWN
, self
.OnRightEvent
)
715 self
.Bind(wx
.EVT_RIGHT_DCLICK
, self
.OnRightDEvent
)
716 self
.Bind(wx
.EVT_MIDDLE_DOWN
, self
.OnMiddleEvent
)
717 self
.Bind(wx
.EVT_MIDDLE_DCLICK
, self
.OnMiddleDEvent
)
718 self
.Bind(wx
.EVT_SET_FOCUS
, self
.OnSetFocus
)
719 self
.Bind(wx
.EVT_KILL_FOCUS
, self
.OnKillFocus
)
720 self
.Bind(wx
.EVT_KEY_DOWN
, self
.OnKeyDown
)
722 self
.sel_key
= None # last used by
723 self
.sel_lst
= [] # highlighted selected days
725 # default calendar for current month
731 self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
)
732 self
.Bind(wx
.EVT_SIZE
, self
.OnSize
)
734 def AcceptsFocus(self
):
735 return self
.IsShown() and self
.IsEnabled()
737 def GetColor(self
, name
):
738 return MakeColor(self
.colors
[name
])
740 def SetColor(self
, name
, value
):
741 self
.colors
[name
] = MakeColor(value
)
743 # control some of the main calendar attributes
746 self
.hide_title
= True
749 self
.hide_grid
= True
751 # determine the calendar rectangle click area and draw a selection
753 def ProcessClick(self
, event
):
755 self
.x
, self
.y
= event
.GetX(), event
.GetY()
756 self
.shiftkey
= event
.ShiftDown()
757 self
.ctrlkey
= event
.ControlDown()
758 key
= self
.GetDayHit(self
.x
, self
.y
)
761 # tab mouse click events and process
763 def OnLeftEvent(self
, event
):
765 self
.ProcessClick(event
)
767 def OnLeftDEvent(self
, event
):
769 self
.ProcessClick(event
)
771 def OnRightEvent(self
, event
):
773 self
.ProcessClick(event
)
775 def OnRightDEvent(self
, event
):
776 self
.click
= 'DRIGHT'
777 self
.ProcessClick(event
)
779 def OnMiddleEvent(self
, event
):
780 self
.click
= 'MIDDLE'
781 self
.ProcessClick(event
)
783 def OnMiddleDEvent(self
, event
):
784 self
.click
= 'DMIDDLE'
785 self
.ProcessClick(event
)
787 def OnSetFocus(self
, event
):
789 self
.DrawFocusIndicator(True)
791 def OnKillFocus(self
, event
):
792 self
.hasFocus
= False
793 self
.DrawFocusIndicator(False)
795 def OnKeyDown(self
, event
):
796 if not self
.hasFocus
:
800 key_code
= event
.GetKeyCode()
802 if key_code
== wx
.WXK_TAB
:
803 forward
= not event
.ShiftDown()
804 ne
= wx
.NavigationKeyEvent()
805 ne
.SetDirection(forward
)
806 ne
.SetCurrentFocus(self
)
807 ne
.SetEventObject(self
)
808 self
.GetParent().GetEventHandler().ProcessEvent(ne
)
814 if key_code
== wx
.WXK_UP
:
816 elif key_code
== wx
.WXK_DOWN
:
818 elif key_code
== wx
.WXK_LEFT
:
820 elif key_code
== wx
.WXK_RIGHT
:
822 elif key_code
== wx
.WXK_HOME
:
823 curDate
= wx
.DateTimeFromDMY(int(self
.cal_days
[self
.sel_key
]),self
.month
- 1,self
.year
)
824 newDate
= wx
.DateTime_Now()
825 ts
= newDate
- curDate
829 curDate
= wx
.DateTimeFromDMY(int(self
.cal_days
[self
.sel_key
]),self
.month
- 1,self
.year
)
830 timeSpan
= wx
.TimeSpan_Days(delta
)
831 newDate
= curDate
+ timeSpan
833 if curDate
.GetMonth() == newDate
.GetMonth():
834 self
.set_day
= newDate
.GetDay()
835 key
= self
.sel_key
+ delta
838 self
.month
= newDate
.GetMonth() + 1
839 self
.year
= newDate
.GetYear()
840 self
.set_day
= newDate
.GetDay()
842 self
.DoDrawing(wx
.ClientDC(self
))
846 def SetSize(self
, set_size
):
849 def SetSelDay(self
, sel
):
850 # list of highlighted days
853 # get the current date
856 self
.month
= dt
.month
860 # set the current day
861 def SetCurrentDay(self
):
863 self
.set_day
= self
.day
865 # get the date, day, month, year set in calendar
868 return self
.day
, self
.month
, self
.year
879 # set the day, month, and year
881 def SetDayValue(self
, day
):
885 def SetMonth(self
, month
):
886 if month
>= 1 and month
<= 12:
892 def SetYear(self
, year
):
895 # increment year and month
898 self
.year
= self
.year
+ 1
902 self
.year
= self
.year
- 1
906 self
.month
= self
.month
+ 1
909 self
.year
= self
.year
+ 1
913 self
.month
= self
.month
- 1
916 self
.year
= self
.year
- 1
919 # test to see if the selection has a date and create event
921 def TestDay(self
, key
):
923 self
.day
= int(self
.cal_days
[key
])
930 # Changed 12/1/03 by jmg (see above) to support 2.5 event binding
931 evt
= wx
.PyCommandEvent(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED
, self
.GetId())
932 evt
.click
, evt
.day
, evt
.month
, evt
.year
= self
.click
, self
.day
, self
.month
, self
.year
933 evt
.shiftkey
= self
.shiftkey
934 evt
.ctrlkey
= self
.ctrlkey
935 self
.GetEventHandler().ProcessEvent(evt
)
937 self
.set_day
= self
.day
940 # find the clicked area rectangle
942 def GetDayHit(self
, mx
, my
):
943 for key
in self
.rg
.keys():
945 ms_rect
= wx
.Rect(mx
, my
, 1, 1)
946 if wx
.IntersectRect(ms_rect
, val
) is not None:
947 result
= self
.TestDay(key
)
954 def SetWeekColor(self
, font_color
, week_color
):
955 # set font and background color for week title
956 self
.colors
[COLOR_HEADER_FONT
] = MakeColor(font_color
)
957 self
.colors
[COLOR_HEADER_BACKGROUND
] = MakeColor(week_color
)
958 self
.colors
[COLOR_3D_LIGHT
] = MakeColor(week_color
)
959 self
.colors
[COLOR_3D_DARK
] = MakeColor(week_color
)
961 def SetTextAlign(self
, vert
, horz
):
962 self
.num_align_horz
= horz
963 self
.num_align_vert
= vert
965 def AddSelect(self
, list, font_color
, back_color
):
966 list_val
= [list, font_color
, back_color
]
967 self
.select_list
.append(list_val
)
969 def ShowWeekEnd(self
):
971 self
.show_weekend
= True
973 def SetBusType(self
):
974 self
.cal_type
= "BUS"
976 def OnSize(self
, evt
):
980 def OnPaint(self
, event
):
981 DC
= wx
.PaintDC(self
)
984 def DoDrawing(self
, DC
):
985 #DC = wx.PaintDC(self)
991 self
.caldraw
= CalDraw(self
)
994 cal
.hide_grid
= self
.hide_grid
995 cal
.hide_title
= self
.hide_title
996 cal
.show_weekend
= self
.show_weekend
997 cal
.cal_type
= self
.cal_type
998 cal
.outer_border
= self
.outer_border
999 cal
.num_align_horz
= self
.num_align_horz
1000 cal
.num_align_vert
= self
.num_align_vert
1001 cal
.colors
= self
.colors
1003 if self
.size
is None:
1004 size
= self
.GetClientSize()
1008 # drawing attributes
1011 cal
.SetCal(self
.year
, self
.month
)
1013 # these have to set after SetCal as SetCal would overwrite them again.
1014 cal
.set_x_mrg
= self
.set_x_mrg
1015 cal
.set_y_mrg
= self
.set_y_mrg
1016 cal
.set_y_end
= self
.set_y_end
1018 for val
in self
.select_list
:
1019 cal
.AddSelect(val
[0], val
[1], val
[2])
1021 cal
.DrawCal(DC
, self
.sel_lst
)
1023 self
.rg
= cal
.GetRect()
1024 self
.cal_days
= cal
.GetCal()
1025 self
.st_pos
= cal
.GetOffset()
1026 self
.ymax
= DC
.MaxY()
1028 if self
.set_day
!= None:
1029 self
.SetDay(self
.set_day
)
1033 # draw the selection rectangle
1034 def DrawFocusIndicator(self
, draw
):
1035 DC
= wx
.ClientDC(self
)
1038 self
.caldraw
.DrawFocusIndicator(DC
)
1040 self
.caldraw
.DrawBorder(DC
,True)
1044 def DrawRect(self
, key
, bgcolor
= 'WHITE', fgcolor
= 'PINK',width
= 0):
1048 DC
= wx
.ClientDC(self
)
1051 brush
= wx
.Brush(MakeColor(bgcolor
))
1054 DC
.SetPen(wx
.TRANSPARENT_PEN
)
1057 DC
.DrawRectangle(rect
.x
+1, rect
.y
+1, rect
.width
-2, rect
.height
-2)
1059 self
.caldraw
.DrawDayText(DC
,key
)
1063 def DrawRectOrg(self
, key
, fgcolor
= 'BLACK', width
= 0):
1067 DC
= wx
.ClientDC(self
)
1070 brush
= wx
.Brush(wx
.Colour(0, 0xFF, 0x80), wx
.TRANSPARENT
)
1074 DC
.SetPen(wx
.Pen(MakeColor(fgcolor
), width
))
1076 DC
.SetPen(wx
.Pen(MakeColor(self
.GetColor(COLOR_GRID_LINES
)), width
))
1079 DC
.DrawRectangleRect(rect
)
1083 # set the day selection
1085 def SetDay(self
, day
):
1086 d
= day
+ self
.st_pos
- 1
1089 def IsDayInWeekend(self
, key
):
1091 t
= Date(self
.year
, self
.month
, 1)
1093 day
= self
.cal_days
[key
]
1094 day
= int(day
) + t
.day_of_week
1096 if day
% 7 == 6 or day
% 7 == 0:
1101 def SelectDay(self
, key
):
1103 # clear large selection
1105 if self
.sel_key
!= None:
1106 (cfont
, bgcolor
) = self
.__GetColorsForDay
(self
.sel_key
)
1107 self
.DrawRect(self
.sel_key
, bgcolor
,cfont
, sel_size
)
1109 self
.DrawRect(key
, self
.GetColor(COLOR_HIGHLIGHT_BACKGROUND
), self
.GetColor(COLOR_HIGHLIGHT_FONT
), sel_size
)
1110 # store last used by
1115 def SetMargin(self
, xmarg
, ymarg
):
1116 self
.set_x_mrg
= xmarg
1117 self
.set_y_mrg
= ymarg
1118 self
.set_y_end
= ymarg
1119 def __GetColorsForDay(self
, key
):
1120 cfont
= self
.GetColor(COLOR_FONT
)
1121 bgcolor
= self
.GetColor(COLOR_BACKGROUND
)
1123 if self
.IsDayInWeekend(key
) is True and self
.show_weekend
is True:
1124 cfont
= self
.GetColor(COLOR_WEEKEND_FONT
)
1125 bgcolor
= self
.GetColor(COLOR_WEEKEND_BACKGROUND
)
1128 dayIdx
= int(self
.cal_days
[key
])
1129 (cfont
, bgcolor
) = self
.caldraw
.cal_sel
[dayIdx
]
1133 return (cfont
, bgcolor
)
1135 class CalenDlg(wx
.Dialog
):
1136 def __init__(self
, parent
, month
=None, day
= None, year
=None):
1137 wx
.Dialog
.__init
__(self
, parent
, -1, "Event Calendar", wx
.DefaultPosition
, (280, 360))
1140 # set the calendar and attributes
1141 self
.calend
= Calendar(self
, -1, (20, 60), (240, 200))
1144 self
.calend
.SetCurrentDay()
1145 start_month
= self
.calend
.GetMonth()
1146 start_year
= self
.calend
.GetYear()
1148 self
.calend
.month
= start_month
= month
1149 self
.calend
.year
= start_year
= year
1150 self
.calend
.SetDayValue(day
)
1152 self
.calend
.HideTitle()
1155 # get month list from DateTime
1156 monthlist
= GetMonthList()
1159 self
.date
= wx
.ComboBox(self
, -1, Month
[start_month
], (20, 20), (90, -1),
1160 monthlist
, wx
.CB_DROPDOWN
)
1161 self
.Bind(wx
.EVT_COMBOBOX
, self
.EvtComboBox
, self
.date
)
1163 # alternate spin button to control the month
1164 h
= self
.date
.GetSize().height
1165 self
.m_spin
= wx
.SpinButton(self
, -1, (115, 20), (h
*1.5, h
), wx
.SP_VERTICAL
)
1166 self
.m_spin
.SetRange(1, 12)
1167 self
.m_spin
.SetValue(start_month
)
1168 self
.Bind(wx
.EVT_SPIN
, self
.OnMonthSpin
, self
.m_spin
)
1170 # spin button to control the year
1171 self
.dtext
= wx
.TextCtrl(self
, -1, str(start_year
), (160, 20), (60, -1))
1172 h
= self
.dtext
.GetSize().height
1174 self
.y_spin
= wx
.SpinButton(self
, -1, (225, 20), (h
*1.5, h
), wx
.SP_VERTICAL
)
1175 self
.y_spin
.SetRange(1980, 2010)
1176 self
.y_spin
.SetValue(start_year
)
1178 self
.Bind(wx
.EVT_SPIN
, self
.OnYrSpin
, self
.y_spin
)
1179 self
.Bind(EVT_CALENDAR
, self
.MouseClick
, self
.calend
)
1185 btn
= wx
.Button(self
, wx
.ID_OK
, ' Ok ', (x_pos
, y_pos
), but_size
)
1186 self
.Bind(wx
.EVT_BUTTON
, self
.OnOk
, btn
)
1188 btn
= wx
.Button(self
, wx
.ID_CANCEL
, ' Close ', (x_pos
+ 120, y_pos
), but_size
)
1189 self
.Bind(wx
.EVT_BUTTON
, self
.OnCancel
, btn
)
1191 def OnOk(self
, evt
):
1192 self
.result
= ['None', str(self
.calend
.day
), Month
[self
.calend
.month
], str(self
.calend
.year
)]
1193 self
.EndModal(wx
.ID_OK
)
1195 def OnCancel(self
, event
):
1196 self
.EndModal(wx
.ID_CANCEL
)
1198 # log the mouse clicks
1199 def MouseClick(self
, evt
):
1200 self
.month
= evt
.month
1201 # result click type and date
1202 self
.result
= [evt
.click
, str(evt
.day
), Month
[evt
.month
], str(evt
.year
)]
1204 if evt
.click
== 'DLEFT':
1205 self
.EndModal(wx
.ID_OK
)
1207 # month and year spin selection routines
1208 def OnMonthSpin(self
, event
):
1209 month
= event
.GetPosition()
1210 self
.date
.SetValue(Month
[month
])
1211 self
.calend
.SetMonth(month
)
1212 self
.calend
.Refresh()
1214 def OnYrSpin(self
, event
):
1215 year
= event
.GetPosition()
1216 self
.dtext
.SetValue(str(year
))
1217 self
.calend
.SetYear(year
)
1218 self
.calend
.Refresh()
1220 def EvtComboBox(self
, event
):
1221 name
= event
.GetString()
1222 monthval
= self
.date
.FindString(name
)
1223 self
.m_spin
.SetValue(monthval
+1)
1225 self
.calend
.SetMonth(monthval
+1)
1228 # set the calendar for highlighted days
1230 def ResetDisplay(self
):
1231 month
= self
.calend
.GetMonth()
1232 self
.calend
.Refresh()