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. 
  83 CalDays 
= [6, 0, 1, 2, 3, 4, 5] 
  84 AbrWeekday 
= {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"}
 
  87 COLOR_GRID_LINES 
= "grid_lines" 
  88 COLOR_BACKGROUND 
= "background" 
  89 COLOR_SELECTION_FONT 
= "selection_font" 
  90 COLOR_SELECTION_BACKGROUND 
= "selection_background" 
  91 COLOR_BORDER 
= "border" 
  92 COLOR_HEADER_BACKGROUND 
= "header_background" 
  93 COLOR_HEADER_FONT 
= "header_font" 
  94 COLOR_WEEKEND_BACKGROUND 
= "weekend_background" 
  95 COLOR_WEEKEND_FONT 
= "weekend_font" 
  97 COLOR_3D_LIGHT 
= "3d_light" 
  98 COLOR_3D_DARK 
= "3d_dark" 
  99 COLOR_HIGHLIGHT_FONT 
= "highlight_font" 
 100 COLOR_HIGHLIGHT_BACKGROUND 
= "highlight_background" 
 102 BusCalDays 
= [0, 1, 2, 3, 4, 5, 6] 
 104 # Calendar click event - added 12/1/03 by jmg (see above) 
 105 wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED 
= wx
.NewEventType() 
 106 EVT_CALENDAR 
= wx
.PyEventBinder(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED
, 1) 
 113             monthlist
.append(name
) 
 116 def MakeColor(in_color
): 
 118         color 
= wxNamedColour(in_color
) 
 125     colors
[COLOR_GRID_LINES
] = 'BLACK' 
 126     colors
[COLOR_BACKGROUND
] = 'WHITE' 
 127     colors
[COLOR_SELECTION_FONT
]  =  wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 128     colors
[COLOR_SELECTION_BACKGROUND
] =wx
.Colour(255,255,225) 
 129     colors
[COLOR_BORDER
] = 'BLACK' 
 130     colors
[COLOR_HEADER_BACKGROUND
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
) 
 131     colors
[COLOR_HEADER_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 132     colors
[COLOR_WEEKEND_BACKGROUND
] = 'LIGHT GREY' 
 133     colors
[COLOR_WEEKEND_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 134     colors
[COLOR_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 135     colors
[COLOR_3D_LIGHT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNHIGHLIGHT
) 
 136     colors
[COLOR_3D_DARK
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
) 
 137     colors
[COLOR_HIGHLIGHT_FONT
]  =  wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
) 
 138     colors
[COLOR_HIGHLIGHT_BACKGROUND
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
) 
 140 # calendar drawing routing 
 143     def __init__(self
, parent
): 
 147             self
.scale 
= parent
.scale
 
 157         self
.num_auto 
= True    # auto scale of the cal number day size 
 158         self
.num_size 
= 12      # default size of calendar if no auto size 
 159         self
.max_num_size 
= 12  # maximum size for calendar number 
 161         self
.num_align_horz 
= wx
.ALIGN_CENTRE    
# alignment of numbers 
 162         self
.num_align_vert 
= wx
.ALIGN_CENTRE
 
 163         self
.num_indent_horz 
= 0     # points indent from position, used to offset if not centered 
 164         self
.num_indent_vert 
= 0 
 166         self
.week_auto 
= True       # auto scale of week font text 
 168         self
.max_week_size 
= 12 
 170         self
.colors 
= DefaultColors() 
 173         self
.bold 
= wx
.NORMAL
 
 175         self
.hide_title 
= False 
 176         self
.hide_grid 
= False 
 177         self
.outer_border 
= True 
 179         self
.title_offset 
= 0 
 180         self
.cal_week_scale 
= 0.7 
 181         self
.show_weekend 
= False 
 182         self
.cal_type 
= "NORMAL" 
 184     def SetWeekColor(self
, font_color
, week_color
): 
 185         # set font and background color for week title 
 186         self
.colors
[COLOR_HEADER_FONT
] = MakeColor(font_color
) 
 187         self
.colors
[COLOR_HEADER_BACKGROUND
] = MakeColor(week_color
) 
 188         self
.colors
[COLOR_3D_LIGHT
] = MakeColor(week_color
) 
 189         self
.colors
[COLOR_3D_DARK
] = MakeColor(week_color
) 
 191     def SetSize(self
, size
): 
 192         self
.set_sizew 
= size
[0] 
 193         self
.set_sizeh 
= size
[1] 
 195     def InitValues(self
):       # default dimensions of various elements of the calendar 
 198         self
.set_cy_st 
= 0      # start position 
 201         self
.set_y_mrg 
= 1      # start of vertical draw default 
 204     def SetPos(self
, xpos
, ypos
): 
 205         self
.set_cx_st 
= xpos
 
 206         self
.set_cy_st 
= ypos
 
 208     def SetMarg(self
, xmarg
, ymarg
): 
 209         self
.set_x_mrg 
= xmarg
 
 210         self
.set_y_mrg 
= ymarg
 
 211         self
.set_y_end 
= ymarg
 
 213     def InitScale(self
):        # scale position values 
 214         self
.sizew 
= int(self
.set_sizew 
* self
.pwidth
) 
 215         self
.sizeh 
= int(self
.set_sizeh 
* self
.pheight
) 
 217         self
.cx_st 
= int(self
.set_cx_st 
* self
.pwidth
)       # draw start position 
 218         self
.cy_st 
= int(self
.set_cy_st 
* self
.pheight
) 
 220         self
.x_mrg 
= int(self
.set_x_mrg 
* self
.pwidth
)         # calendar draw margins 
 221         self
.y_mrg 
= int(self
.set_y_mrg 
* self
.pheight
) 
 222         self
.y_end 
= int(self
.set_y_end 
* self
.pheight
) 
 224     def DrawCal(self
, DC
, sel_lst
=[]): 
 229         if self
.hide_title 
is False: 
 236         if self
.show_weekend 
is True:       # highlight weekend dates 
 239         self
.AddSelect(sel_lst
)     # overrides the weekend highlight 
 241         self
.DrawSel(DC
)      # highlighted days 
 245     def AddSelect(self
, list, cfont
=None, cbackgrd 
= None): 
 247             cfont 
= self
.colors
[COLOR_SELECTION_FONT
]      # font digit color 
 249             cbackgrd 
= self
.colors
[COLOR_SELECTION_BACKGROUND
]     # select background color 
 252             self
.cal_sel
[val
] = (cfont
, cbackgrd
) 
 254     # draw border around the outside of the main display rectangle 
 255     def DrawBorder(self
, DC
, transparent 
= False):    
 256         if self
.outer_border 
is True: 
 257             if transparent 
== False: 
 258                 brush 
= wx
.Brush(MakeColor(self
.colors
[COLOR_BACKGROUND
]), wx
.SOLID
) 
 260                 brush 
= wx
.TRANSPARENT_BRUSH
 
 262             DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_BORDER
]))) 
 263             # full display window area 
 264             rect 
= wx
.Rect(self
.cx_st
, self
.cy_st
, self
.sizew
, self
.sizeh
)   
 265             DC
.DrawRectangleRect(rect
) 
 267     def DrawFocusIndicator(self
, DC
): 
 268         if self
.outer_border 
is True: 
 269             DC
.SetBrush(wx
.TRANSPARENT_BRUSH
) 
 270             DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_HIGHLIGHT_BACKGROUND
]), style
=wx
.DOT
)) 
 271             # full display window area 
 272             rect 
= wx
.Rect(self
.cx_st
, self
.cy_st
, self
.sizew
, self
.sizeh
)   
 273             DC
.DrawRectangleRect(rect
) 
 275     def DrawNumVal(self
): 
 278     # calculate the calendar days and offset position 
 279     def SetCal(self
, year
, month
): 
 280         self
.InitValues()       # reset initial values 
 286         t 
= Date(year
, month
, day
) 
 287         dow 
= self
.dow 
= t
.day_of_week     
# start day in month 
 288         dim 
= self
.dim 
= t
.days_in_month   
# number of days in month 
 290         if self
.cal_type 
== "NORMAL": 
 298         self
.st_pos 
= start_pos
 
 301         for i 
in range(start_pos
): 
 302             self
.cal_days
.append('') 
 306             self
.cal_days
.append(str(i
)) 
 309         self
.end_pos 
= start_pos 
+ dim 
- 1 
 313     def SetWeekEnd(self
, font_color
=None, backgrd 
= None): 
 314         if font_color 
!= None: 
 315             self
.SetColor(COLOR_WEEKEND_FONT
, MakeColor(font_color
)) 
 317             self
.SetColor(COLOR_WEEKEND_BACKGROUND
, MakeColor(backgrd
)) 
 319         date 
= 6 - int(self
.dow
)     # start day of first saturday 
 320         if date 
== 0:                #...unless we start on Sunday 
 321             self
.cal_sel
[1] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
)) 
 324         while date 
<= self
.dim
: 
 325             self
.cal_sel
[date
] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
))  # Saturday 
 329                 self
.cal_sel
[date
] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
))      # Sunday 
 334     # get the display rectange list of the day grid 
 339         for y 
in self
.gridy
[1:-1]: 
 340             if y 
== self
.gridy
[-2]: 
 343             for x 
in self
.gridx
[:-1]: 
 344                 assert type(y
) == int 
 345                 assert type(x
) == int 
 350                 if x 
== self
.gridx
[-2]: 
 353                 rect 
= wx
.Rect(x
, y
, w
+1, h
+1)  # create rect region 
 366     # month and year title 
 367     def DrawMonth(self
, DC
): 
 368         month 
= Month
[self
.month
] 
 371         if self
.sizeh 
< _MIDSIZE
: 
 374         f 
= wx
.Font(sizef
, self
.font
, wx
.NORMAL
, self
.bold
) 
 377         tw
,th 
= DC
.GetTextExtent(month
) 
 378         adjust 
= self
.cx_st 
+ (self
.sizew
-tw
)/2 
 379         DC
.DrawText(month
, adjust
, self
.cy_st 
+ th
) 
 381         year 
= str(self
.year
) 
 382         tw
,th 
= DC
.GetTextExtent(year
) 
 383         adjust 
=  self
.sizew 
- tw 
- self
.x_mrg
 
 385         self
.title_offset 
= th 
* 2 
 387         f 
= wx
.Font(sizef
, self
.font
, wx
.NORMAL
, self
.bold
) 
 389         DC
.DrawText(year
, self
.cx_st 
+ adjust
, self
.cy_st 
+ th
) 
 391     def DrawWeek(self
, DC
):     # draw the week days 
 392         # increase by 1 to include all gridlines 
 393         width  
= self
.gridx
[1] - self
.gridx
[0] + 1 
 394         height 
= self
.gridy
[1] - self
.gridy
[0] + 1 
 395         rect_w 
= self
.gridx
[-1] - self
.gridx
[0] 
 397         f 
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
)      # initial font setting 
 399         if self
.week_auto 
== True: 
 400             test_size 
= self
.max_week_size      
# max size 
 403                 f
.SetPointSize(test_size
) 
 405                 tw
,th 
= DC
.GetTextExtent(test_day
) 
 407                 if tw 
< width 
and th 
< height
: 
 410                 test_size 
= test_size 
- 1 
 412             f
.SetPointSize(self
.week_size
)   # set fixed size 
 415         DC
.SetTextForeground(MakeColor(self
.colors
[COLOR_HEADER_FONT
])) 
 420         brush 
= wx
.Brush(MakeColor(self
.colors
[COLOR_HEADER_BACKGROUND
]), wx
.SOLID
) 
 423         if self
.cal_type 
== "NORMAL": 
 426             cal_days 
= BusCalDays
 
 429             if val 
== cal_days
[-1]: 
 430                 width 
= width 
+ self
.restW
 
 432             day 
= AbrWeekday
[val
] 
 437             dw
,dh 
= DC
.GetTextExtent(day
) 
 440             diffy 
= (height
-dh
)/2 
 442             x 
= self
.gridx
[cnt_x
] 
 443             y 
= self
.gridy
[cnt_y
] 
 445             pointWH 
= (width
, height
) 
 446             if self
.hide_grid 
== False: 
 447                 pen 
= wx
.Pen(MakeColor(self
.GetColor(COLOR_GRID_LINES
)), 1, wx
.SOLID
) 
 449                 pen 
= wx
.Pen(MakeColor(self
.GetColor(COLOR_BACKGROUND
)), 1, wx
.SOLID
) 
 451             DC
.DrawRectanglePointSize( pointXY
, pointWH
) 
 453             old_pen 
= DC
.GetPen() 
 455             pen 
= wx
.Pen(MakeColor(self
.colors
[COLOR_3D_LIGHT
]), 1, wx
.SOLID
) 
 457             # draw the horizontal hilight 
 458             startPoint 
= wx
.Point(x 
+ 1 , y 
+ 1) 
 459             endPoint   
= wx
.Point(x 
+ width 
- 1, y 
+ 1) 
 460             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 462             # draw the vertical hilight 
 463             startPoint 
= wx
.Point(x 
+ 1 , y 
+ 1) 
 464             endPoint   
= wx
.Point(x 
+ 1, y 
+ height 
- 2) 
 465             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 467             pen 
= wx
.Pen(MakeColor(self
.colors
[COLOR_3D_DARK
]), 1, wx
.SOLID
) 
 470             # draw the horizontal lowlight 
 471             startPoint 
= wx
.Point(x 
+ 1, y 
+ height 
- 2) 
 472             endPoint   
= wx
.Point(x 
+ width 
- 1, y 
+ height 
- 2) 
 473             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 475             # draw the vertical lowlight 
 476             startPoint 
= wx
.Point(x 
+ width 
- 2 , y 
+ 2) 
 477             endPoint   
= wx
.Point(x 
+ width 
- 2, y 
+ height 
- 2) 
 478             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 480             pen 
= wx
.Pen(MakeColor(self
.colors
[COLOR_FONT
]), 1, wx
.SOLID
) 
 484             point 
= (x
+diffx
, y
+diffy
) 
 485             DC
.DrawTextPoint(day
, point
) 
 488     def _CalcFontSize(self
, DC
, f
): 
 489         if self
.num_auto 
== True: 
 490             test_size 
= self
.max_num_size      
# max size 
 494                 f
.SetPointSize(test_size
) 
 496                 tw
,th 
= DC
.GetTextExtent(test_day
) 
 498                 if tw 
< self
.cellW 
and th 
< self
.cellH
: 
 501                 test_size 
= test_size 
- 1 
 503             f
.SetPointSize(self
.num_size
)   # set fixed size 
 506     # draw the day numbers 
 507     def DrawNum(self
, DC
):       
 508         f 
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
)      # initial font setting 
 509         self
._CalcFontSize
(DC
, f
) 
 513         for val 
in self
.cal_days
: 
 514             x 
= self
.gridx
[cnt_x
] 
 515             y 
= self
.gridy
[cnt_y
] 
 517             self
._DrawDayText
(x
, y
, val
, f
, DC
) 
 525     def _DrawDayText(self
, x
, y
, text
, font
, DC
): 
 529             num_color 
= self
.cal_sel
[num_val
][0] 
 531             num_color 
= self
.colors
[COLOR_FONT
] 
 533         DC
.SetTextForeground(MakeColor(num_color
)) 
 536         tw
,th 
= DC
.GetTextExtent(text
) 
 538         if self
.num_align_horz 
== wx
.ALIGN_CENTRE
: 
 539             adj_h 
= (self
.cellW 
- tw
)/2 
 540         elif self
.num_align_horz 
== wx
.ALIGN_RIGHT
: 
 541             adj_h 
= self
.cellW 
- tw
 
 543             adj_h 
= 0   # left alignment 
 545         adj_h 
= adj_h 
+ self
.num_indent_horz
 
 547         if self
.num_align_vert 
== wx
.ALIGN_CENTRE
: 
 548             adj_v 
= (self
.cellH 
- th
)/2 
 549         elif self
.num_align_vert 
== wx
.ALIGN_BOTTOM
: 
 550             adj_v 
= self
.cellH 
- th
 
 552             adj_v 
= 0   # left alignment 
 554         adj_v 
= adj_v 
+ self
.num_indent_vert
 
 556         DC
.DrawTextPoint(text
, (x
+adj_h
, y
+adj_v
)) 
 558     def DrawDayText(self
, DC
, key
): 
 559         f 
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
)      # initial font setting 
 560         self
._CalcFontSize
(DC
, f
) 
 562         if key 
> self
.end_pos
:  
 565         val 
= self
.cal_days
[key
] 
 567         cnt_y 
= int(key 
/ 7)+1 
 568         x 
= self
.gridx
[cnt_x
] 
 569         y 
= self
.gridy
[cnt_y
] 
 570         self
._DrawDayText
(x
, y
, val
, f
, DC
) 
 573     # calculate the dimensions in the center of the drawing area 
 575         borderW 
= self
.x_mrg 
* 2 
 576         borderH 
= self
.y_mrg 
+ self
.y_end 
+ self
.title_offset
 
 578         self
.cellW 
= int((self
.sizew 
- borderW
)/7) 
 579         self
.cellH 
= int((self
.sizeh 
- borderH
)/7) 
 581         self
.restW 
= ((self
.sizew 
- borderW
)%7 ) - 1 
 583         # week title adjustment 
 584         self
.weekHdrCellH 
= int(self
.cellH 
* self
.cal_week_scale
) 
 585         # recalculate the cell height exkl. the week header and 
 586         # subtracting the size 
 587         self
.cellH 
= int((self
.sizeh 
- borderH 
- self
.weekHdrCellH
)/6) 
 589         self
.restH 
= ((self
.sizeh 
- borderH 
- self
.weekHdrCellH
)%6 ) - 1 
 590         self
.calW 
= self
.cellW 
* 7 
 591         self
.calH 
= self
.cellH 
* 6 + self
.weekHdrCellH
 
 593     # highlighted selected days 
 594     def DrawSel(self
, DC
): 
 596         for key 
in self
.cal_sel
.keys(): 
 597             sel_color 
= self
.cal_sel
[key
][1] 
 598             brush 
= wx
.Brush(MakeColor(sel_color
), wx
.SOLID
) 
 601             if self
.hide_grid 
is False: 
 602                 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_GRID_LINES
]), 0)) 
 604                 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_BACKGROUND
]), 0)) 
 606             nkey 
= key 
+ self
.st_pos 
-1 
 609             DC
.DrawRectangleRect(rect
) 
 611     # calculate and draw the grid lines 
 612     def DrawGrid(self
, DC
): 
 613         DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_GRID_LINES
]), 0)) 
 618         self
.x_st 
= self
.cx_st 
+ self
.x_mrg
 
 619         # start postion of draw 
 620         self
.y_st 
= self
.cy_st 
+ self
.y_mrg 
+ self
.title_offset
 
 624         y2 
= y1 
+ self
.calH 
+ self
.restH
 
 630             if self
.hide_grid 
is False: 
 631                 DC
.DrawLinePoint((x1
, y1
), (x1
, y2
)) 
 633             self
.gridx
.append(x1
) 
 639         x2 
= x1 
+ self
.calW 
+ self
.restW
 
 645             if self
.hide_grid 
is False: 
 646                 DC
.DrawLinePoint((x1
, y1
), (x2
, y1
)) 
 648             self
.gridy
.append(y1
) 
 651                 y1 
= y1 
+ self
.weekHdrCellH
 
 655     def GetColor(self
, name
): 
 656         return MakeColor(self
.colors
[name
]) 
 658     def SetColor(self
, name
, value
): 
 659         self
.colors
[name
] = MakeColor(value
) 
 661 class PrtCalDraw(CalDraw
): 
 662     def InitValues(self
): 
 665         # start draw border location 
 669         # draw offset position 
 674     # calculate the dimensions in the center of the drawing area 
 675     def SetPSize(self
, pwidth
, pheight
):     
 676         self
.pwidth 
= int(pwidth
)/self
.scale
 
 677         self
.pheight 
= int(pheight
)/self
.scale
 
 679     def SetPreview(self
, preview
): 
 680         self
.preview 
= preview
 
 682 class Calendar( wx
.PyControl 
): 
 683     def __init__(self
, parent
, id, pos
=wx
.DefaultPosition
, size
=wx
.Size(200,200), 
 684                    style
= 0, validator
=wx
.DefaultValidator
, 
 686         wx
.PyControl
.__init
__(self
, parent
, id, pos
, size
, style | wx
.WANTS_CHARS
, validator
, name
) 
 688         self
.hasFocus 
= False 
 689         # set the calendar control attributes 
 691         self
.hide_grid 
= False 
 692         self
.hide_title 
= False 
 693         self
.show_weekend 
= False 
 694         self
.cal_type 
= "NORMAL" 
 695         self
.outer_border 
= True 
 696         self
.num_align_horz 
= wx
.ALIGN_CENTRE
 
 697         self
.num_align_vert 
= wx
.ALIGN_CENTRE
 
 698         self
.colors 
= DefaultColors() 
 703         self
.select_list 
= [] 
 705         self
.SetBackgroundColour(MakeColor(self
.colors
[COLOR_BACKGROUND
])) 
 706         self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftEvent
) 
 707         self
.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnLeftDEvent
) 
 708         self
.Bind(wx
.EVT_RIGHT_DOWN
, self
.OnRightEvent
) 
 709         self
.Bind(wx
.EVT_RIGHT_DCLICK
, self
.OnRightDEvent
) 
 710         self
.Bind(wx
.EVT_SET_FOCUS
, self
.OnSetFocus
) 
 711         self
.Bind(wx
.EVT_KILL_FOCUS
, self
.OnKillFocus
) 
 712         self
.Bind(wx
.EVT_KEY_DOWN
, self
.OnKeyDown
) 
 714         self
.sel_key 
= None      #  last used by 
 715         self
.sel_lst 
= []        # highlighted selected days 
 717         # default calendar for current month 
 723         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
 724         self
.Bind(wx
.EVT_SIZE
, self
.OnSize
) 
 726     def AcceptsFocus(self
): 
 727         return self
.IsShown() and self
.IsEnabled() 
 729     def GetColor(self
, name
): 
 730         return MakeColor(self
.colors
[name
]) 
 732     def SetColor(self
, name
, value
): 
 733         self
.colors
[name
] = MakeColor(value
) 
 735     # control some of the main calendar attributes 
 738         self
.hide_title 
= True 
 741         self
.hide_grid 
= True 
 743     # determine the calendar rectangle click area and draw a selection 
 745     def ProcessClick(self
, event
): 
 746         self
.x
, self
.y 
= event
.GetX(), event
.GetY() 
 747         key 
= self
.GetDayHit(self
.x
, self
.y
) 
 750     # tab mouse click events and process 
 752     def OnLeftEvent(self
, event
): 
 754         self
.shiftkey 
= event
.ShiftDown() 
 755         self
.ctrlkey 
= event
.ControlDown() 
 756         self
.ProcessClick(event
) 
 758     def OnLeftDEvent(self
, event
): 
 760         self
.ProcessClick(event
) 
 762     def OnRightEvent(self
, event
): 
 764         self
.ProcessClick(event
) 
 766     def OnRightDEvent(self
, event
): 
 767         self
.click 
= 'DRIGHT' 
 768         self
.ProcessClick(event
) 
 770     def OnSetFocus(self
, event
): 
 772         self
.DrawFocusIndicator(True) 
 774     def OnKillFocus(self
, event
): 
 775         self
.hasFocus 
= False 
 776         self
.DrawFocusIndicator(False) 
 778     def OnKeyDown(self
, event
): 
 779         if not self
.hasFocus
: 
 783         key_code 
= event
.GetKeyCode() 
 785         if key_code 
== wx
.WXK_TAB
: 
 786             forward 
= not event
.ShiftDown() 
 787             ne 
= wx
.NavigationKeyEvent() 
 788             ne
.SetDirection(forward
) 
 789             ne
.SetCurrentFocus(self
) 
 790             ne
.SetEventObject(self
) 
 791             self
.GetParent().GetEventHandler().ProcessEvent(ne
) 
 797         if key_code 
== wx
.WXK_UP
: 
 799         elif key_code 
== wx
.WXK_DOWN
: 
 801         elif key_code 
== wx
.WXK_LEFT
: 
 803         elif key_code 
== wx
.WXK_RIGHT
: 
 805         elif key_code 
== wx
.WXK_HOME
: 
 806             curDate 
= wx
.DateTimeFromDMY(int(self
.cal_days
[self
.sel_key
]),self
.month 
- 1,self
.year
) 
 807             newDate 
= wx
.DateTime_Now() 
 808             ts 
= newDate 
- curDate
 
 812             curDate 
= wx
.DateTimeFromDMY(int(self
.cal_days
[self
.sel_key
]),self
.month 
- 1,self
.year
) 
 813             timeSpan 
= wx
.TimeSpan_Days(delta
) 
 814             newDate 
= curDate 
+ timeSpan
 
 816             if curDate
.GetMonth() == newDate
.GetMonth(): 
 817                 self
.set_day 
= newDate
.GetDay() 
 818                 key 
= self
.sel_key 
+ delta
 
 821                 self
.month 
= newDate
.GetMonth() + 1 
 822                 self
.year 
= newDate
.GetYear() 
 823                 self
.set_day 
= newDate
.GetDay() 
 825                 self
.DoDrawing(wx
.ClientDC(self
)) 
 829     def SetSize(self
, set_size
): 
 832     def SetSelDay(self
, sel
): 
 833         # list of highlighted days 
 836     # get the current date 
 839         self
.month 
= dt
.month
 
 843     # set the current day 
 844     def SetCurrentDay(self
): 
 846         self
.set_day 
= self
.day
 
 848     # get the date, day, month, year set in calendar 
 851         return self
.day
, self
.month
, self
.year
 
 862     # set the day, month, and year 
 864     def SetDayValue(self
, day
): 
 868     def SetMonth(self
, month
): 
 869         if month 
>= 1 and month 
<= 12: 
 875     def SetYear(self
, year
): 
 878     # increment year and month 
 881         self
.year 
= self
.year 
+ 1 
 885         self
.year 
= self
.year 
- 1 
 889         self
.month 
= self
.month 
+ 1 
 892             self
.year 
= self
.year 
+ 1 
 896         self
.month 
= self
.month 
- 1 
 899             self
.year 
= self
.year 
- 1 
 902     # test to see if the selection has a date and create event 
 904     def TestDay(self
, key
): 
 906             self
.day 
= int(self
.cal_days
[key
]) 
 913             # Changed 12/1/03 by jmg (see above) to support 2.5 event binding 
 914             evt 
= wx
.PyCommandEvent(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED
, self
.GetId()) 
 915             evt
.click
, evt
.day
, evt
.month
, evt
.year 
= self
.click
, self
.day
, self
.month
, self
.year
 
 916             evt
.shiftkey 
= self
.shiftkey
 
 917             evt
.ctrlkey 
= self
.ctrlkey
 
 918             self
.GetEventHandler().ProcessEvent(evt
) 
 920             self
.set_day 
= self
.day
 
 923     # find the clicked area rectangle 
 925     def GetDayHit(self
, mx
, my
): 
 926         for key 
in self
.rg
.keys(): 
 928             ms_rect 
= wx
.Rect(mx
, my
, 1, 1) 
 929             if wx
.IntersectRect(ms_rect
, val
) is not None: 
 930                 result 
= self
.TestDay(key
) 
 937     def SetWeekColor(self
, font_color
, week_color
):      
 938         # set font and background color for week title 
 939         self
.colors
[COLOR_HEADER_FONT
] = MakeColor(font_color
) 
 940         self
.colors
[COLOR_HEADER_BACKGROUND
] = MakeColor(week_color
) 
 941         self
.colors
[COLOR_3D_LIGHT
] = MakeColor(week_color
) 
 942         self
.colors
[COLOR_3D_DARK
] = MakeColor(week_color
) 
 944     def SetTextAlign(self
, vert
, horz
): 
 945         self
.num_align_horz 
= horz
 
 946         self
.num_align_vert 
= vert
 
 948     def AddSelect(self
, list, font_color
, back_color
): 
 949         list_val 
= [list, font_color
, back_color
] 
 950         self
.select_list
.append(list_val
) 
 952     def ShowWeekEnd(self
): 
 954         self
.show_weekend 
= True 
 956     def SetBusType(self
): 
 957         self
.cal_type 
= "BUS" 
 959     def OnSize(self
, evt
): 
 963     def OnPaint(self
, event
): 
 964         DC 
= wx
.PaintDC(self
) 
 967     def DoDrawing(self
, DC
): 
 968         #DC = wx.PaintDC(self) 
 974             self
.caldraw 
= CalDraw(self
) 
 977         cal
.hide_grid 
= self
.hide_grid
 
 978         cal
.hide_title 
= self
.hide_title
 
 979         cal
.show_weekend 
= self
.show_weekend
 
 980         cal
.cal_type 
= self
.cal_type
 
 981         cal
.outer_border 
= self
.outer_border
 
 982         cal
.num_align_horz 
= self
.num_align_horz
 
 983         cal
.num_align_vert 
= self
.num_align_vert
 
 984         cal
.colors 
= self
.colors
 
 986         if self
.size 
is None: 
 987             size 
= self
.GetClientSize() 
 994         cal
.SetCal(self
.year
, self
.month
) 
 996         # these have to set after SetCal as SetCal would overwrite them again. 
 997         cal
.set_x_mrg 
= self
.set_x_mrg 
 
 998         cal
.set_y_mrg 
= self
.set_y_mrg 
 
 999         cal
.set_y_end 
= self
.set_y_end 
 
1001         for val 
in self
.select_list
: 
1002             cal
.AddSelect(val
[0], val
[1], val
[2]) 
1004         cal
.DrawCal(DC
, self
.sel_lst
) 
1006         self
.rg 
= cal
.GetRect() 
1007         self
.cal_days 
= cal
.GetCal() 
1008         self
.st_pos 
= cal
.GetOffset() 
1009         self
.ymax 
= DC
.MaxY() 
1011         if self
.set_day 
!= None: 
1012             self
.SetDay(self
.set_day
) 
1016     # draw the selection rectangle 
1017     def DrawFocusIndicator(self
, draw
): 
1018         DC 
= wx
.ClientDC(self
) 
1021                 self
.caldraw
.DrawFocusIndicator(DC
) 
1023                 self
.caldraw
.DrawBorder(DC
,True) 
1027     def DrawRect(self
, key
, bgcolor 
= 'WHITE', fgcolor
= 'PINK',width 
= 0): 
1031         DC 
= wx
.ClientDC(self
) 
1034         brush 
= wx
.Brush(MakeColor(bgcolor
)) 
1037         DC
.SetPen(wx
.TRANSPARENT_PEN
) 
1040         DC
.DrawRectangle(rect
.x
+1, rect
.y
+1, rect
.width
-2, rect
.height
-2) 
1042         self
.caldraw
.DrawDayText(DC
,key
) 
1046     def DrawRectOrg(self
, key
, fgcolor 
= 'BLACK', width 
= 0): 
1050         DC 
= wx
.ClientDC(self
) 
1053         brush 
= wx
.Brush(wx
.Colour(0, 0xFF, 0x80), wx
.TRANSPARENT
) 
1057             DC
.SetPen(wx
.Pen(MakeColor(fgcolor
), width
)) 
1059             DC
.SetPen(wx
.Pen(MakeColor(self
.GetColor(COLOR_GRID_LINES
)), width
)) 
1062         DC
.DrawRectangleRect(rect
) 
1066     # set the day selection 
1068     def SetDay(self
, day
): 
1069         d 
= day 
+ self
.st_pos 
- 1 
1072     def IsDayInWeekend(self
, key
): 
1074             t 
= Date(self
.year
, self
.month
, 1) 
1076             day 
= self
.cal_days
[key
] 
1077             day 
= int(day
) + t
.day_of_week
 
1079             if day 
% 7 == 6 or day 
% 7 == 0: 
1084     def SelectDay(self
, key
): 
1086         # clear large selection 
1088         if self
.sel_key 
!= None: 
1089             (cfont
, bgcolor
) = self
.__GetColorsForDay
(self
.sel_key
) 
1090             self
.DrawRect(self
.sel_key
, bgcolor
,cfont
, sel_size
) 
1092         self
.DrawRect(key
, self
.GetColor(COLOR_HIGHLIGHT_BACKGROUND
), self
.GetColor(COLOR_HIGHLIGHT_FONT
), sel_size
) 
1093         # store last used by 
1098     def SetMargin(self
, xmarg
, ymarg
): 
1099         self
.set_x_mrg 
= xmarg
 
1100         self
.set_y_mrg 
= ymarg
 
1101         self
.set_y_end 
= ymarg
 
1102     def __GetColorsForDay(self
, key
): 
1103         cfont   
= self
.GetColor(COLOR_FONT
) 
1104         bgcolor 
= self
.GetColor(COLOR_BACKGROUND
) 
1106         if self
.IsDayInWeekend(key
) is True and self
.show_weekend 
is True: 
1107             cfont   
= self
.GetColor(COLOR_WEEKEND_FONT
) 
1108             bgcolor 
= self
.GetColor(COLOR_WEEKEND_BACKGROUND
) 
1111             dayIdx 
= int(self
.cal_days
[key
]) 
1112             (cfont
, bgcolor
) = self
.caldraw
.cal_sel
[dayIdx
] 
1116         return (cfont
, bgcolor
) 
1118 class CalenDlg(wx
.Dialog
): 
1119     def __init__(self
, parent
, month
=None, day 
= None, year
=None): 
1120         wx
.Dialog
.__init
__(self
, parent
, -1, "Event Calendar", wx
.DefaultPosition
, (280, 360)) 
1123         # set the calendar and attributes 
1124         self
.calend 
= Calendar(self
, -1, (20, 60), (240, 200)) 
1127             self
.calend
.SetCurrentDay() 
1128             start_month 
= self
.calend
.GetMonth() 
1129             start_year 
= self
.calend
.GetYear() 
1131             self
.calend
.month 
= start_month 
= month
 
1132             self
.calend
.year 
= start_year 
= year
 
1133             self
.calend
.SetDayValue(day
) 
1135         self
.calend
.HideTitle() 
1138         # get month list from DateTime 
1139         monthlist 
= GetMonthList() 
1142         self
.date 
= wx
.ComboBox(self
, -1, Month
[start_month
], (20, 20), (90, -1),  
1143                                 monthlist
, wx
.CB_DROPDOWN
) 
1144         self
.Bind(wx
.EVT_COMBOBOX
, self
.EvtComboBox
, self
.date
) 
1146         # alternate spin button to control the month 
1147         h 
= self
.date
.GetSize().height
 
1148         self
.m_spin 
= wx
.SpinButton(self
, -1, (115, 20), (h
*1.5, h
), wx
.SP_VERTICAL
) 
1149         self
.m_spin
.SetRange(1, 12) 
1150         self
.m_spin
.SetValue(start_month
) 
1151         self
.Bind(wx
.EVT_SPIN
, self
.OnMonthSpin
, self
.m_spin
) 
1153         # spin button to control the year 
1154         self
.dtext 
= wx
.TextCtrl(self
, -1, str(start_year
), (160, 20), (60, -1)) 
1155         h 
= self
.dtext
.GetSize().height
 
1157         self
.y_spin 
= wx
.SpinButton(self
, -1, (225, 20), (h
*1.5, h
), wx
.SP_VERTICAL
) 
1158         self
.y_spin
.SetRange(1980, 2010) 
1159         self
.y_spin
.SetValue(start_year
) 
1161         self
.Bind(wx
.EVT_SPIN
, self
.OnYrSpin
, self
.y_spin
) 
1162         self
.Bind(EVT_CALENDAR
, self
.MouseClick
, self
.calend
) 
1168         btn 
= wx
.Button(self
, wx
.ID_OK
, ' Ok ', (x_pos
, y_pos
), but_size
) 
1169         self
.Bind(wx
.EVT_BUTTON
, self
.OnOk
, btn
) 
1171         btn 
= wx
.Button(self
, wx
.ID_CANCEL
, ' Close ', (x_pos 
+ 120, y_pos
), but_size
) 
1172         self
.Bind(wx
.EVT_BUTTON
, self
.OnCancel
, btn
) 
1174     def OnOk(self
, evt
): 
1175         self
.result 
= ['None', str(self
.calend
.day
), Month
[self
.calend
.month
], str(self
.calend
.year
)] 
1176         self
.EndModal(wx
.ID_OK
) 
1178     def OnCancel(self
, event
): 
1179         self
.EndModal(wx
.ID_CANCEL
) 
1181     # log the mouse clicks 
1182     def MouseClick(self
, evt
): 
1183         self
.month 
= evt
.month
 
1184         # result click type and date 
1185         self
.result 
= [evt
.click
, str(evt
.day
), Month
[evt
.month
], str(evt
.year
)]   
1187         if evt
.click 
== 'DLEFT': 
1188             self
.EndModal(wx
.ID_OK
) 
1190     # month and year spin selection routines 
1191     def OnMonthSpin(self
, event
): 
1192         month 
= event
.GetPosition() 
1193         self
.date
.SetValue(Month
[month
]) 
1194         self
.calend
.SetMonth(month
) 
1195         self
.calend
.Refresh() 
1197     def OnYrSpin(self
, event
): 
1198         year 
= event
.GetPosition() 
1199         self
.dtext
.SetValue(str(year
)) 
1200         self
.calend
.SetYear(year
) 
1201         self
.calend
.Refresh() 
1203     def EvtComboBox(self
, event
): 
1204         name 
= event
.GetString() 
1205         monthval 
= self
.date
.FindString(name
) 
1206         self
.m_spin
.SetValue(monthval
+1) 
1208         self
.calend
.SetMonth(monthval
+1) 
1211     # set the calendar for highlighted days 
1213     def ResetDisplay(self
): 
1214         month 
= self
.calend
.GetMonth() 
1215         self
.calend
.Refresh()