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 
  72 CalDays 
= [6, 0, 1, 2, 3, 4, 5] 
  73 AbrWeekday 
= {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"}
 
  76 COLOR_GRID_LINES 
= "grid_lines" 
  77 COLOR_BACKGROUND 
= "background" 
  78 COLOR_SELECTION_FONT 
= "selection_font" 
  79 COLOR_SELECTION_BACKGROUND 
= "selection_background" 
  80 COLOR_BORDER 
= "border" 
  81 COLOR_HEADER_BACKGROUND 
= "header_background" 
  82 COLOR_HEADER_FONT 
= "header_font" 
  83 COLOR_WEEKEND_BACKGROUND 
= "weekend_background" 
  84 COLOR_WEEKEND_FONT 
= "weekend_font" 
  86 COLOR_3D_LIGHT 
= "3d_light" 
  87 COLOR_3D_DARK 
= "3d_dark" 
  88 COLOR_HIGHLIGHT_FONT 
= "highlight_font" 
  89 COLOR_HIGHLIGHT_BACKGROUND 
= "highlight_background" 
  91 BusCalDays 
= [0, 1, 2, 3, 4, 5, 6] 
  93 # Calendar click event - added 12/1/03 by jmg (see above) 
  94 wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED 
= wx
.NewEventType() 
  95 EVT_CALENDAR 
= wx
.PyEventBinder(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED
, 1) 
 102             monthlist
.append(name
) 
 105 def MakeColor(in_color
): 
 107         color 
= wxNamedColour(in_color
) 
 114     colors
[COLOR_GRID_LINES
] = 'BLACK' 
 115     colors
[COLOR_BACKGROUND
] = 'WHITE' 
 116     colors
[COLOR_SELECTION_FONT
]  =  wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 117     colors
[COLOR_SELECTION_BACKGROUND
] =wx
.Colour(255,255,225) 
 118     colors
[COLOR_BORDER
] = 'BLACK' 
 119     colors
[COLOR_HEADER_BACKGROUND
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
) 
 120     colors
[COLOR_HEADER_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 121     colors
[COLOR_WEEKEND_BACKGROUND
] = 'LIGHT GREY' 
 122     colors
[COLOR_WEEKEND_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 123     colors
[COLOR_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 124     colors
[COLOR_3D_LIGHT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNHIGHLIGHT
) 
 125     colors
[COLOR_3D_DARK
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
) 
 126     colors
[COLOR_HIGHLIGHT_FONT
]  =  wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
) 
 127     colors
[COLOR_HIGHLIGHT_BACKGROUND
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
) 
 129 # calendar drawing routing 
 132     def __init__(self
, parent
): 
 136             self
.scale 
= parent
.scale
 
 146         self
.num_auto 
= True    # auto scale of the cal number day size 
 147         self
.num_size 
= 12      # default size of calendar if no auto size 
 148         self
.max_num_size 
= 12  # maximum size for calendar number 
 150         self
.num_align_horz 
= wx
.ALIGN_CENTRE    
# alignment of numbers 
 151         self
.num_align_vert 
= wx
.ALIGN_CENTRE
 
 152         self
.num_indent_horz 
= 0     # points indent from position, used to offset if not centered 
 153         self
.num_indent_vert 
= 0 
 155         self
.week_auto 
= True       # auto scale of week font text 
 157         self
.max_week_size 
= 12 
 159         self
.colors 
= DefaultColors() 
 162         self
.bold 
= wx
.NORMAL
 
 164         self
.hide_title 
= False 
 165         self
.hide_grid 
= False 
 166         self
.outer_border 
= True 
 168         self
.title_offset 
= 0 
 169         self
.cal_week_scale 
= 0.7 
 170         self
.show_weekend 
= False 
 171         self
.cal_type 
= "NORMAL" 
 173     def SetWeekColor(self
, font_color
, week_color
): 
 174         # set font and background color for week title 
 175         self
.colors
[COLOR_HEADER_FONT
] = MakeColor(font_color
) 
 176         self
.colors
[COLOR_HEADER_BACKGROUND
] = MakeColor(week_color
) 
 177         self
.colors
[COLOR_3D_LIGHT
] = MakeColor(week_color
) 
 178         self
.colors
[COLOR_3D_DARK
] = MakeColor(week_color
) 
 180     def SetSize(self
, size
): 
 181         self
.set_sizew 
= size
[0] 
 182         self
.set_sizeh 
= size
[1] 
 184     def InitValues(self
):       # default dimensions of various elements of the calendar 
 187         self
.set_cy_st 
= 0      # start position 
 190         self
.set_y_mrg 
= 1      # start of vertical draw default 
 193     def SetPos(self
, xpos
, ypos
): 
 194         self
.set_cx_st 
= xpos
 
 195         self
.set_cy_st 
= ypos
 
 197     def SetMarg(self
, xmarg
, ymarg
): 
 198         self
.set_x_mrg 
= xmarg
 
 199         self
.set_y_mrg 
= ymarg
 
 200         self
.set_y_end 
= ymarg
 
 202     def InitScale(self
):        # scale position values 
 203         self
.sizew 
= int(self
.set_sizew 
* self
.pwidth
) 
 204         self
.sizeh 
= int(self
.set_sizeh 
* self
.pheight
) 
 206         self
.cx_st 
= int(self
.set_cx_st 
* self
.pwidth
)       # draw start position 
 207         self
.cy_st 
= int(self
.set_cy_st 
* self
.pheight
) 
 209         self
.x_mrg 
= int(self
.set_x_mrg 
* self
.pwidth
)         # calendar draw margins 
 210         self
.y_mrg 
= int(self
.set_y_mrg 
* self
.pheight
) 
 211         self
.y_end 
= int(self
.set_y_end 
* self
.pheight
) 
 213     def DrawCal(self
, DC
, sel_lst
=[]): 
 218         if self
.hide_title 
is False: 
 225         if self
.show_weekend 
is True:       # highlight weekend dates 
 228         self
.AddSelect(sel_lst
)     # overrides the weekend highlight 
 230         self
.DrawSel(DC
)      # highlighted days 
 234     def AddSelect(self
, list, cfont
=None, cbackgrd 
= None): 
 236             cfont 
= self
.colors
[COLOR_SELECTION_FONT
]      # font digit color 
 238             cbackgrd 
= self
.colors
[COLOR_SELECTION_BACKGROUND
]     # select background color 
 241             self
.cal_sel
[val
] = (cfont
, cbackgrd
) 
 243     # draw border around the outside of the main display rectangle 
 244     def DrawBorder(self
, DC
, transparent 
= False):    
 245         if self
.outer_border 
is True: 
 246             if transparent 
== False: 
 247                 brush 
= wx
.Brush(MakeColor(self
.colors
[COLOR_BACKGROUND
]), wx
.SOLID
) 
 249                 brush 
= wx
.TRANSPARENT_BRUSH
 
 251             DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_BORDER
]))) 
 252             # full display window area 
 253             rect 
= wx
.Rect(self
.cx_st
, self
.cy_st
, self
.sizew
, self
.sizeh
)   
 254             DC
.DrawRectangleRect(rect
) 
 256     def DrawFocusIndicator(self
, DC
): 
 257         if self
.outer_border 
is True: 
 258             DC
.SetBrush(wx
.TRANSPARENT_BRUSH
) 
 259             DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_HIGHLIGHT_BACKGROUND
]), style
=wx
.DOT
)) 
 260             # full display window area 
 261             rect 
= wx
.Rect(self
.cx_st
, self
.cy_st
, self
.sizew
, self
.sizeh
)   
 262             DC
.DrawRectangleRect(rect
) 
 264     def DrawNumVal(self
): 
 267     # calculate the calendar days and offset position 
 268     def SetCal(self
, year
, month
): 
 269         self
.InitValues()       # reset initial values 
 275         t 
= Date(year
, month
, day
) 
 276         dow 
= self
.dow 
= t
.day_of_week     
# start day in month 
 277         dim 
= self
.dim 
= t
.days_in_month   
# number of days in month 
 279         if self
.cal_type 
== "NORMAL": 
 284         self
.st_pos 
= start_pos
 
 287         for i 
in range(start_pos
): 
 288             self
.cal_days
.append('') 
 292             self
.cal_days
.append(str(i
)) 
 295         self
.end_pos 
= dow 
+ dim
 
 299     def SetWeekEnd(self
, font_color
=None, backgrd 
= None): 
 300         if font_color 
!= None: 
 301             self
.SetColor(COLOR_WEEKEND_FONT
, MakeColor(font_color
)) 
 303             self
.SetColor(COLOR_WEEKEND_BACKGROUND
, MakeColor(backgrd
)) 
 305         date 
= 6 - int(self
.dow
)     # start day of first saturday 
 307         while date 
<= self
.dim
: 
 308             self
.cal_sel
[date
] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
))  # Saturday 
 312                 self
.cal_sel
[date
] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
))      # Sunday 
 317     # get the display rectange list of the day grid 
 322         for y 
in self
.gridy
[1:-1]: 
 323             if y 
== self
.gridy
[-2]: 
 326             for x 
in self
.gridx
[:-1]: 
 327                 assert type(y
) == int 
 328                 assert type(x
) == int 
 333                 if x 
== self
.gridx
[-2]: 
 336                 rect 
= wx
.Rect(x
, y
, w
+1, h
+1)  # create rect region 
 349     # month and year title 
 350     def DrawMonth(self
, DC
): 
 351         month 
= Month
[self
.month
] 
 354         if self
.sizeh 
< _MIDSIZE
: 
 357         f 
= wx
.Font(sizef
, self
.font
, wx
.NORMAL
, self
.bold
) 
 360         tw
,th 
= DC
.GetTextExtent(month
) 
 361         adjust 
= self
.cx_st 
+ (self
.sizew
-tw
)/2 
 362         DC
.DrawText(month
, adjust
, self
.cy_st 
+ th
) 
 364         year 
= str(self
.year
) 
 365         tw
,th 
= DC
.GetTextExtent(year
) 
 366         adjust 
=  self
.sizew 
- tw 
- self
.x_mrg
 
 368         self
.title_offset 
= th 
* 2 
 370         f 
= wx
.Font(sizef
, self
.font
, wx
.NORMAL
, self
.bold
) 
 372         DC
.DrawText(year
, self
.cx_st 
+ adjust
, self
.cy_st 
+ th
) 
 374     def DrawWeek(self
, DC
):     # draw the week days 
 375         # increase by 1 to include all gridlines 
 376         width  
= self
.gridx
[1] - self
.gridx
[0] + 1 
 377         height 
= self
.gridy
[1] - self
.gridy
[0] + 1 
 378         rect_w 
= self
.gridx
[-1] - self
.gridx
[0] 
 380         f 
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
)      # initial font setting 
 382         if self
.week_auto 
== True: 
 383             test_size 
= self
.max_week_size      
# max size 
 386                 f
.SetPointSize(test_size
) 
 388                 tw
,th 
= DC
.GetTextExtent(test_day
) 
 390                 if tw 
< width 
and th 
< height
: 
 393                 test_size 
= test_size 
- 1 
 395             f
.SetPointSize(self
.week_size
)   # set fixed size 
 398         DC
.SetTextForeground(MakeColor(self
.colors
[COLOR_HEADER_FONT
])) 
 403         brush 
= wx
.Brush(MakeColor(self
.colors
[COLOR_HEADER_BACKGROUND
]), wx
.SOLID
) 
 406         if self
.cal_type 
== "NORMAL": 
 409             cal_days 
= BusCalDays
 
 412             if val 
== cal_days
[-1]: 
 413                 width 
= width 
+ self
.restW
 
 415             day 
= AbrWeekday
[val
] 
 420             dw
,dh 
= DC
.GetTextExtent(day
) 
 423             diffy 
= (height
-dh
)/2 
 425             x 
= self
.gridx
[cnt_x
] 
 426             y 
= self
.gridy
[cnt_y
] 
 428             pointWH 
= (width
, height
) 
 429             if self
.hide_grid 
== False: 
 430                 pen 
= wx
.Pen(MakeColor(self
.GetColor(COLOR_GRID_LINES
)), 1, wx
.SOLID
) 
 432                 pen 
= wx
.Pen(MakeColor(self
.GetColor(COLOR_BACKGROUND
)), 1, wx
.SOLID
) 
 434             DC
.DrawRectanglePointSize( pointXY
, pointWH
) 
 436             old_pen 
= DC
.GetPen() 
 438             pen 
= wx
.Pen(MakeColor(self
.colors
[COLOR_3D_LIGHT
]), 1, wx
.SOLID
) 
 440             # draw the horizontal hilight 
 441             startPoint 
= wx
.Point(x 
+ 1 , y 
+ 1) 
 442             endPoint   
= wx
.Point(x 
+ width 
- 1, y 
+ 1) 
 443             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 445             # draw the vertical hilight 
 446             startPoint 
= wx
.Point(x 
+ 1 , y 
+ 1) 
 447             endPoint   
= wx
.Point(x 
+ 1, y 
+ height 
- 2) 
 448             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 450             pen 
= wx
.Pen(MakeColor(self
.colors
[COLOR_3D_DARK
]), 1, wx
.SOLID
) 
 453             # draw the horizontal lowlight 
 454             startPoint 
= wx
.Point(x 
+ 1, y 
+ height 
- 2) 
 455             endPoint   
= wx
.Point(x 
+ width 
- 1, y 
+ height 
- 2) 
 456             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 458             # draw the vertical lowlight 
 459             startPoint 
= wx
.Point(x 
+ width 
- 2 , y 
+ 2) 
 460             endPoint   
= wx
.Point(x 
+ width 
- 2, y 
+ height 
- 2) 
 461             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 463             pen 
= wx
.Pen(MakeColor(self
.colors
[COLOR_FONT
]), 1, wx
.SOLID
) 
 467             point 
= (x
+diffx
, y
+diffy
) 
 468             DC
.DrawTextPoint(day
, point
) 
 471     def _CalcFontSize(self
, DC
, f
): 
 472         if self
.num_auto 
== True: 
 473             test_size 
= self
.max_num_size      
# max size 
 477                 f
.SetPointSize(test_size
) 
 479                 tw
,th 
= DC
.GetTextExtent(test_day
) 
 481                 if tw 
< self
.cellW 
and th 
< self
.cellH
: 
 484                 test_size 
= test_size 
- 1 
 486             f
.SetPointSize(self
.num_size
)   # set fixed size 
 489     # draw the day numbers 
 490     def DrawNum(self
, DC
):       
 491         f 
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
)      # initial font setting 
 492         self
._CalcFontSize
(DC
, f
) 
 496         for val 
in self
.cal_days
: 
 497             x 
= self
.gridx
[cnt_x
] 
 498             y 
= self
.gridy
[cnt_y
] 
 500             self
._DrawDayText
(x
, y
, val
, f
, DC
) 
 508     def _DrawDayText(self
, x
, y
, text
, font
, DC
): 
 512             num_color 
= self
.cal_sel
[num_val
][0] 
 514             num_color 
= self
.colors
[COLOR_FONT
] 
 516         DC
.SetTextForeground(MakeColor(num_color
)) 
 519         tw
,th 
= DC
.GetTextExtent(text
) 
 521         if self
.num_align_horz 
== wx
.ALIGN_CENTRE
: 
 522             adj_h 
= (self
.cellW 
- tw
)/2 
 523         elif self
.num_align_horz 
== wx
.ALIGN_RIGHT
: 
 524             adj_h 
= self
.cellW 
- tw
 
 526             adj_h 
= 0   # left alignment 
 528         adj_h 
= adj_h 
+ self
.num_indent_horz
 
 530         if self
.num_align_vert 
== wx
.ALIGN_CENTRE
: 
 531             adj_v 
= (self
.cellH 
- th
)/2 
 532         elif self
.num_align_vert 
== wx
.ALIGN_BOTTOM
: 
 533             adj_v 
= self
.cellH 
- th
 
 535             adj_v 
= 0   # left alignment 
 537         adj_v 
= adj_v 
+ self
.num_indent_vert
 
 539         DC
.DrawTextPoint(text
, (x
+adj_h
, y
+adj_v
)) 
 541     def DrawDayText(self
, DC
, key
): 
 542         f 
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
)      # initial font setting 
 543         self
._CalcFontSize
(DC
, f
) 
 545         if key 
> self
.end_pos
:  
 548         val 
= self
.cal_days
[key
] 
 550         cnt_y 
= int(key 
/ 7)+1 
 551         x 
= self
.gridx
[cnt_x
] 
 552         y 
= self
.gridy
[cnt_y
] 
 553         self
._DrawDayText
(x
, y
, val
, f
, DC
) 
 556     # calculate the dimensions in the center of the drawing area 
 558         borderW 
= self
.x_mrg 
* 2 
 559         borderH 
= self
.y_mrg 
+ self
.y_end 
+ self
.title_offset
 
 561         self
.cellW 
= int((self
.sizew 
- borderW
)/7) 
 562         self
.cellH 
= int((self
.sizeh 
- borderH
)/7) 
 564         self
.restW 
= ((self
.sizew 
- borderW
)%7 ) - 1 
 566         # week title adjustment 
 567         self
.weekHdrCellH 
= int(self
.cellH 
* self
.cal_week_scale
) 
 568         # recalculate the cell height exkl. the week header and 
 569         # subtracting the size 
 570         self
.cellH 
= int((self
.sizeh 
- borderH 
- self
.weekHdrCellH
)/6) 
 572         self
.restH 
= ((self
.sizeh 
- borderH 
- self
.weekHdrCellH
)%6 ) - 1 
 573         self
.calW 
= self
.cellW 
* 7 
 574         self
.calH 
= self
.cellH 
* 6 + self
.weekHdrCellH
 
 576     # highlighted selected days 
 577     def DrawSel(self
, DC
): 
 579         for key 
in self
.cal_sel
.keys(): 
 580             sel_color 
= self
.cal_sel
[key
][1] 
 581             brush 
= wx
.Brush(MakeColor(sel_color
), wx
.SOLID
) 
 584             if self
.hide_grid 
is False: 
 585                 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_GRID_LINES
]), 0)) 
 587                 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_BACKGROUND
]), 0)) 
 589             nkey 
= key 
+ self
.st_pos 
-1 
 592             DC
.DrawRectangleRect(rect
) 
 594     # calculate and draw the grid lines 
 595     def DrawGrid(self
, DC
): 
 596         DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_GRID_LINES
]), 0)) 
 601         self
.x_st 
= self
.cx_st 
+ self
.x_mrg
 
 602         # start postion of draw 
 603         self
.y_st 
= self
.cy_st 
+ self
.y_mrg 
+ self
.title_offset
 
 607         y2 
= y1 
+ self
.calH 
+ self
.restH
 
 613             if self
.hide_grid 
is False: 
 614                 DC
.DrawLinePoint((x1
, y1
), (x1
, y2
)) 
 616             self
.gridx
.append(x1
) 
 622         x2 
= x1 
+ self
.calW 
+ self
.restW
 
 628             if self
.hide_grid 
is False: 
 629                 DC
.DrawLinePoint((x1
, y1
), (x2
, y1
)) 
 631             self
.gridy
.append(y1
) 
 634                 y1 
= y1 
+ self
.weekHdrCellH
 
 638     def GetColor(self
, name
): 
 639         return MakeColor(self
.colors
[name
]) 
 641     def SetColor(self
, name
, value
): 
 642         self
.colors
[name
] = MakeColor(value
) 
 644 class PrtCalDraw(CalDraw
): 
 645     def InitValues(self
): 
 648         # start draw border location 
 652         # draw offset position 
 657     # calculate the dimensions in the center of the drawing area 
 658     def SetPSize(self
, pwidth
, pheight
):     
 659         self
.pwidth 
= int(pwidth
)/self
.scale
 
 660         self
.pheight 
= int(pheight
)/self
.scale
 
 662     def SetPreview(self
, preview
): 
 663         self
.preview 
= preview
 
 665 class Calendar( wx
.PyControl 
): 
 666     def __init__(self
, parent
, id, pos
=wx
.DefaultPosition
, size
=wx
.Size(200,200), 
 667                    style
= 0, validator
=wx
.DefaultValidator
, 
 669         wx
.PyControl
.__init
__(self
, parent
, id, pos
, size
, style | wx
.WANTS_CHARS
, validator
, name
) 
 671         self
.hasFocus 
= False 
 672         # set the calendar control attributes 
 674         self
.hide_grid 
= False 
 675         self
.hide_title 
= False 
 676         self
.show_weekend 
= False 
 677         self
.cal_type 
= "NORMAL" 
 678         self
.outer_border 
= True 
 679         self
.num_align_horz 
= wx
.ALIGN_CENTRE
 
 680         self
.num_align_vert 
= wx
.ALIGN_CENTRE
 
 681         self
.colors 
= DefaultColors() 
 686         self
.select_list 
= [] 
 688         self
.SetBackgroundColour(MakeColor(self
.colors
[COLOR_BACKGROUND
])) 
 689         self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftEvent
) 
 690         self
.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnLeftDEvent
) 
 691         self
.Bind(wx
.EVT_RIGHT_DOWN
, self
.OnRightEvent
) 
 692         self
.Bind(wx
.EVT_RIGHT_DCLICK
, self
.OnRightDEvent
) 
 693         self
.Bind(wx
.EVT_SET_FOCUS
, self
.OnSetFocus
) 
 694         self
.Bind(wx
.EVT_KILL_FOCUS
, self
.OnKillFocus
) 
 695         self
.Bind(wx
.EVT_KEY_DOWN
, self
.OnKeyDown
) 
 697         self
.sel_key 
= None      #  last used by 
 698         self
.sel_lst 
= []        # highlighted selected days 
 700         # default calendar for current month 
 706         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
 707         self
.Bind(wx
.EVT_SIZE
, self
.OnSize
) 
 709     def AcceptsFocus(self
): 
 710         return self
.IsShown() and self
.IsEnabled() 
 712     def GetColor(self
, name
): 
 713         return MakeColor(self
.colors
[name
]) 
 715     def SetColor(self
, name
, value
): 
 716         self
.colors
[name
] = MakeColor(value
) 
 718     # control some of the main calendar attributes 
 721         self
.hide_title 
= True 
 724         self
.hide_grid 
= True 
 726     # determine the calendar rectangle click area and draw a selection 
 728     def ProcessClick(self
, event
): 
 729         self
.x
, self
.y 
= event
.GetX(), event
.GetY() 
 730         key 
= self
.GetDayHit(self
.x
, self
.y
) 
 733     # tab mouse click events and process 
 735     def OnLeftEvent(self
, event
): 
 737         self
.shiftkey 
= event
.ShiftDown() 
 738         self
.ctrlkey 
= event
.ControlDown() 
 739         self
.ProcessClick(event
) 
 741     def OnLeftDEvent(self
, event
): 
 743         self
.ProcessClick(event
) 
 745     def OnRightEvent(self
, event
): 
 747         self
.ProcessClick(event
) 
 749     def OnRightDEvent(self
, event
): 
 750         self
.click 
= 'DRIGHT' 
 751         self
.ProcessClick(event
) 
 753     def OnSetFocus(self
, event
): 
 755         self
.DrawFocusIndicator(True) 
 757     def OnKillFocus(self
, event
): 
 758         self
.hasFocus 
= False 
 759         self
.DrawFocusIndicator(False) 
 761     def OnKeyDown(self
, event
): 
 762         if not self
.hasFocus
: 
 766         key_code 
= event
.KeyCode() 
 768         if key_code 
== wx
.WXK_TAB
: 
 769             forward 
= not event
.ShiftDown() 
 770             ne 
= wx
.NavigationKeyEvent() 
 771             ne
.SetDirection(forward
) 
 772             ne
.SetCurrentFocus(self
) 
 773             ne
.SetEventObject(self
) 
 774             self
.GetParent().GetEventHandler().ProcessEvent(ne
) 
 780         if key_code 
== wx
.WXK_UP
: 
 782         elif key_code 
== wx
.WXK_DOWN
: 
 784         elif key_code 
== wx
.WXK_LEFT
: 
 786         elif key_code 
== wx
.WXK_RIGHT
: 
 788         elif key_code 
== wx
.WXK_HOME
: 
 789             curDate 
= wx
.DateTimeFromDMY(int(self
.cal_days
[self
.sel_key
]),self
.month 
- 1,self
.year
) 
 790             newDate 
= wx
.DateTime_Now() 
 791             ts 
= newDate 
- curDate
 
 795             curDate 
= wx
.DateTimeFromDMY(int(self
.cal_days
[self
.sel_key
]),self
.month 
- 1,self
.year
) 
 796             timeSpan 
= wx
.TimeSpan_Days(delta
) 
 797             newDate 
= curDate 
+ timeSpan
 
 799             if curDate
.GetMonth() == newDate
.GetMonth(): 
 800                 self
.set_day 
= newDate
.GetDay() 
 801                 key 
= self
.sel_key 
+ delta
 
 804                 self
.month 
= newDate
.GetMonth() + 1 
 805                 self
.year 
= newDate
.GetYear() 
 806                 self
.set_day 
= newDate
.GetDay() 
 808                 self
.DoDrawing(wx
.ClientDC(self
)) 
 812     def SetSize(self
, set_size
): 
 815     def SetSelDay(self
, sel
): 
 816         # list of highlighted days 
 819     # get the current date 
 822         self
.month 
= dt
.month
 
 826     # set the current day 
 827     def SetCurrentDay(self
): 
 829         self
.set_day 
= self
.day
 
 831     # get the date, day, month, year set in calendar 
 834         return self
.day
, self
.month
, self
.year
 
 845     # set the day, month, and year 
 847     def SetDayValue(self
, day
): 
 850     def SetMonth(self
, month
): 
 851         if month 
>= 1 and month 
<= 12: 
 857     def SetYear(self
, year
): 
 860     # increment year and month 
 863         self
.year 
= self
.year 
+ 1 
 867         self
.year 
= self
.year 
- 1 
 871         self
.month 
= self
.month 
+ 1 
 874             self
.year 
= self
.year 
+ 1 
 878         self
.month 
= self
.month 
- 1 
 881             self
.year 
= self
.year 
- 1 
 884     # test to see if the selection has a date and create event 
 886     def TestDay(self
, key
): 
 888             self
.day 
= int(self
.cal_days
[key
]) 
 895             # Changed 12/1/03 by jmg (see above) to support 2.5 event binding 
 896             evt 
= wx
.PyCommandEvent(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED
, self
.GetId()) 
 897             evt
.click
, evt
.day
, evt
.month
, evt
.year 
= self
.click
, self
.day
, self
.month
, self
.year
 
 898             evt
.shiftkey 
= self
.shiftkey
 
 899             evt
.ctrlkey 
= self
.ctrlkey
 
 900             self
.GetEventHandler().ProcessEvent(evt
) 
 902             self
.set_day 
= self
.day
 
 905     # find the clicked area rectangle 
 907     def GetDayHit(self
, mx
, my
): 
 908         for key 
in self
.rg
.keys(): 
 910             ms_rect 
= wx
.Rect(mx
, my
, 1, 1) 
 911             if wx
.IntersectRect(ms_rect
, val
) is not None: 
 912                 result 
= self
.TestDay(key
) 
 919     def SetWeekColor(self
, font_color
, week_color
):      
 920         # set font and background color for week title 
 921         self
.colors
[COLOR_HEADER_FONT
] = MakeColor(font_color
) 
 922         self
.colors
[COLOR_HEADER_BACKGROUND
] = MakeColor(week_color
) 
 923         self
.colors
[COLOR_3D_LIGHT
] = MakeColor(week_color
) 
 924         self
.colors
[COLOR_3D_DARK
] = MakeColor(week_color
) 
 926     def SetTextAlign(self
, vert
, horz
): 
 927         self
.num_align_horz 
= horz
 
 928         self
.num_align_vert 
= vert
 
 930     def AddSelect(self
, list, font_color
, back_color
): 
 931         list_val 
= [list, font_color
, back_color
] 
 932         self
.select_list
.append(list_val
) 
 934     def ShowWeekEnd(self
): 
 936         self
.show_weekend 
= True 
 938     def SetBusType(self
): 
 939         self
.cal_type 
= "BUS" 
 941     def OnSize(self
, evt
): 
 945     def OnPaint(self
, event
): 
 946         DC 
= wx
.PaintDC(self
) 
 949     def DoDrawing(self
, DC
): 
 950         #DC = wx.PaintDC(self) 
 956             self
.caldraw 
= CalDraw(self
) 
 959         cal
.hide_grid 
= self
.hide_grid
 
 960         cal
.hide_title 
= self
.hide_title
 
 961         cal
.show_weekend 
= self
.show_weekend
 
 962         cal
.cal_type 
= self
.cal_type
 
 963         cal
.outer_border 
= self
.outer_border
 
 964         cal
.num_align_horz 
= self
.num_align_horz
 
 965         cal
.num_align_vert 
= self
.num_align_vert
 
 966         cal
.colors 
= self
.colors
 
 968         if self
.size 
is None: 
 969             size 
= self
.GetClientSize() 
 976         cal
.SetCal(self
.year
, self
.month
) 
 978         # these have to set after SetCal as SetCal would overwrite them again. 
 979         cal
.set_x_mrg 
= self
.set_x_mrg 
 
 980         cal
.set_y_mrg 
= self
.set_y_mrg 
 
 981         cal
.set_y_end 
= self
.set_y_end 
 
 983         for val 
in self
.select_list
: 
 984             cal
.AddSelect(val
[0], val
[1], val
[2]) 
 986         cal
.DrawCal(DC
, self
.sel_lst
) 
 988         self
.rg 
= cal
.GetRect() 
 989         self
.cal_days 
= cal
.GetCal() 
 990         self
.st_pos 
= cal
.GetOffset() 
 991         self
.ymax 
= DC
.MaxY() 
 993         if self
.set_day 
!= None: 
 994             self
.SetDay(self
.set_day
) 
 998     # draw the selection rectangle 
 999     def DrawFocusIndicator(self
, draw
): 
1000         DC 
= wx
.ClientDC(self
) 
1003                 self
.caldraw
.DrawFocusIndicator(DC
) 
1005                 self
.caldraw
.DrawBorder(DC
,True) 
1009     def DrawRect(self
, key
, bgcolor 
= 'WHITE', fgcolor
= 'PINK',width 
= 0): 
1013         DC 
= wx
.ClientDC(self
) 
1016         brush 
= wx
.Brush(MakeColor(bgcolor
)) 
1019         DC
.SetPen(wx
.TRANSPARENT_PEN
) 
1022         DC
.DrawRectangle(rect
.x
+1, rect
.y
+1, rect
.width
-2, rect
.height
-2) 
1024         self
.caldraw
.DrawDayText(DC
,key
) 
1028     def DrawRectOrg(self
, key
, fgcolor 
= 'BLACK', width 
= 0): 
1032         DC 
= wx
.ClientDC(self
) 
1035         brush 
= wx
.Brush(wx
.Colour(0, 0xFF, 0x80), wx
.TRANSPARENT
) 
1039             DC
.SetPen(wx
.Pen(MakeColor(fgcolor
), width
)) 
1041             DC
.SetPen(wx
.Pen(MakeColor(self
.GetColor(COLOR_GRID_LINES
)), width
)) 
1044         DC
.DrawRectangleRect(rect
) 
1048     # set the day selection 
1050     def SetDay(self
, day
): 
1051         d 
= day 
+ self
.st_pos 
- 1 
1054     def IsDayInWeekend(self
, key
): 
1056             t 
= Date(self
.year
, self
.month
, 1) 
1058             day 
= self
.cal_days
[key
] 
1059             day 
= int(day
) + t
.day_of_week
 
1061             if day 
% 7 == 6 or day 
% 7 == 0: 
1066     def SelectDay(self
, key
): 
1068         # clear large selection 
1070         if self
.sel_key 
!= None: 
1071             (cfont
, bgcolor
) = self
.__GetColorsForDay
(self
.sel_key
) 
1072             self
.DrawRect(self
.sel_key
, bgcolor
,cfont
, sel_size
) 
1074         self
.DrawRect(key
, self
.GetColor(COLOR_HIGHLIGHT_BACKGROUND
), self
.GetColor(COLOR_HIGHLIGHT_FONT
), sel_size
) 
1076         # store last used by 
1078         self
.select_day 
= None 
1082     def SetMargin(self
, xmarg
, ymarg
): 
1083         self
.set_x_mrg 
= xmarg
 
1084         self
.set_y_mrg 
= ymarg
 
1085         self
.set_y_end 
= ymarg
 
1086     def __GetColorsForDay(self
, key
): 
1087         cfont   
= self
.GetColor(COLOR_FONT
) 
1088         bgcolor 
= self
.GetColor(COLOR_BACKGROUND
) 
1090         if self
.IsDayInWeekend(key
) is True and self
.show_weekend 
is True: 
1091             cfont   
= self
.GetColor(COLOR_WEEKEND_FONT
) 
1092             bgcolor 
= self
.GetColor(COLOR_WEEKEND_BACKGROUND
) 
1095             dayIdx 
= int(self
.cal_days
[key
]) 
1096             (cfont
, bgcolor
) = self
.caldraw
.cal_sel
[dayIdx
] 
1100         return (cfont
, bgcolor
) 
1102 class CalenDlg(wx
.Dialog
): 
1103     def __init__(self
, parent
, month
=None, day 
= None, year
=None): 
1104         wx
.Dialog
.__init
__(self
, parent
, -1, "Event Calendar", wx
.DefaultPosition
, (280, 360)) 
1106         # set the calendar and attributes 
1107         self
.calend 
= Calendar(self
, -1, (20, 60), (240, 200)) 
1110             self
.calend
.SetCurrentDay() 
1111             start_month 
= self
.calend
.GetMonth() 
1112             start_year 
= self
.calend
.GetYear() 
1114             self
.calend
.month 
= start_month 
= month
 
1115             self
.calend
.year 
= start_year 
= year
 
1116             self
.calend
.SetDayValue(day
) 
1118         self
.calend
.HideTitle() 
1121         # get month list from DateTime 
1122         monthlist 
= GetMonthList() 
1125         self
.date 
= wx
.ComboBox(self
, -1, Month
[start_month
], (20, 20), (90, -1),  
1126                                 monthlist
, wx
.CB_DROPDOWN
) 
1127         self
.Bind(wx
.EVT_COMBOBOX
, self
.EvtComboBox
, self
.date
) 
1129         # alternate spin button to control the month 
1130         h 
= self
.date
.GetSize().height
 
1131         self
.m_spin 
= wx
.SpinButton(self
, -1, (130, 20), (h
*2, h
), wx
.SP_VERTICAL
) 
1132         self
.m_spin
.SetRange(1, 12) 
1133         self
.m_spin
.SetValue(start_month
) 
1134         self
.Bind(wx
.EVT_SPIN
, self
.OnMonthSpin
, self
.m_spin
) 
1136         # spin button to control the year 
1137         self
.dtext 
= wx
.TextCtrl(self
, -1, str(start_year
), (160, 20), (60, -1)) 
1138         h 
= self
.dtext
.GetSize().height
 
1140         self
.y_spin 
= wx
.SpinButton(self
, -1, (220, 20), (h
*2, h
), wx
.SP_VERTICAL
) 
1141         self
.y_spin
.SetRange(1980, 2010) 
1142         self
.y_spin
.SetValue(start_year
) 
1144         self
.Bind(wx
.EVT_SPIN
, self
.OnYrSpin
, self
.y_spin
) 
1145         self
.Bind(EVT_CALENDAR
, self
.MouseClick
, self
.calend
) 
1151         btn 
= wx
.Button(self
, -1, ' Ok ', (x_pos
, y_pos
), but_size
) 
1152         self
.Bind(wx
.EVT_BUTTON
, self
.OnOk
, btn
) 
1154         btn 
= wx
.Button(self
, -1, ' Close ', (x_pos 
+ 120, y_pos
), but_size
) 
1155         self
.Bind(wx
.EVT_BUTTON
, self
.OnCancel
, btn
) 
1157     def OnOk(self
, event
): 
1158         self
.EndModal(wx
.ID_OK
) 
1160     def OnCancel(self
, event
): 
1161         self
.EndModal(wx
.ID_CANCEL
) 
1163     # log the mouse clicks 
1164     def MouseClick(self
, evt
): 
1165         self
.month 
= evt
.month
 
1166         # result click type and date 
1167         self
.result 
= [evt
.click
, str(evt
.day
), Month
[evt
.month
], str(evt
.year
)]   
1169         if evt
.click 
== 'DLEFT': 
1170             self
.EndModal(wx
.ID_OK
) 
1172     # month and year spin selection routines 
1173     def OnMonthSpin(self
, event
): 
1174         month 
= event
.GetPosition() 
1175         self
.date
.SetValue(Month
[month
]) 
1176         self
.calend
.SetMonth(month
) 
1177         self
.calend
.Refresh() 
1179     def OnYrSpin(self
, event
): 
1180         year 
= event
.GetPosition() 
1181         self
.dtext
.SetValue(str(year
)) 
1182         self
.calend
.SetYear(year
) 
1183         self
.calend
.Refresh() 
1185     def EvtComboBox(self
, event
): 
1186         name 
= event
.GetString() 
1187         monthval 
= self
.date
.FindString(name
) 
1188         self
.m_spin
.SetValue(monthval
+1) 
1190         self
.calend
.SetMonth(monthval
+1) 
1193     # set the calendar for highlighted days 
1195     def ResetDisplay(self
): 
1196         month 
= self
.calend
.GetMonth() 
1197         self
.calend
.Refresh()