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. 
  80 CalDays 
= [6, 0, 1, 2, 3, 4, 5] 
  81 AbrWeekday 
= {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"}
 
  84 COLOR_GRID_LINES 
= "grid_lines" 
  85 COLOR_BACKGROUND 
= "background" 
  86 COLOR_SELECTION_FONT 
= "selection_font" 
  87 COLOR_SELECTION_BACKGROUND 
= "selection_background" 
  88 COLOR_BORDER 
= "border" 
  89 COLOR_HEADER_BACKGROUND 
= "header_background" 
  90 COLOR_HEADER_FONT 
= "header_font" 
  91 COLOR_WEEKEND_BACKGROUND 
= "weekend_background" 
  92 COLOR_WEEKEND_FONT 
= "weekend_font" 
  94 COLOR_3D_LIGHT 
= "3d_light" 
  95 COLOR_3D_DARK 
= "3d_dark" 
  96 COLOR_HIGHLIGHT_FONT 
= "highlight_font" 
  97 COLOR_HIGHLIGHT_BACKGROUND 
= "highlight_background" 
  99 BusCalDays 
= [0, 1, 2, 3, 4, 5, 6] 
 101 # Calendar click event - added 12/1/03 by jmg (see above) 
 102 wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED 
= wx
.NewEventType() 
 103 EVT_CALENDAR 
= wx
.PyEventBinder(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED
, 1) 
 110             monthlist
.append(name
) 
 113 def MakeColor(in_color
): 
 115         color 
= wxNamedColour(in_color
) 
 122     colors
[COLOR_GRID_LINES
] = 'BLACK' 
 123     colors
[COLOR_BACKGROUND
] = 'WHITE' 
 124     colors
[COLOR_SELECTION_FONT
]  =  wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 125     colors
[COLOR_SELECTION_BACKGROUND
] =wx
.Colour(255,255,225) 
 126     colors
[COLOR_BORDER
] = 'BLACK' 
 127     colors
[COLOR_HEADER_BACKGROUND
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_3DFACE
) 
 128     colors
[COLOR_HEADER_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 129     colors
[COLOR_WEEKEND_BACKGROUND
] = 'LIGHT GREY' 
 130     colors
[COLOR_WEEKEND_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 131     colors
[COLOR_FONT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_WINDOWTEXT
) 
 132     colors
[COLOR_3D_LIGHT
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNHIGHLIGHT
) 
 133     colors
[COLOR_3D_DARK
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_BTNSHADOW
) 
 134     colors
[COLOR_HIGHLIGHT_FONT
]  =  wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
) 
 135     colors
[COLOR_HIGHLIGHT_BACKGROUND
] = wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
) 
 137 # calendar drawing routing 
 140     def __init__(self
, parent
): 
 144             self
.scale 
= parent
.scale
 
 154         self
.num_auto 
= True    # auto scale of the cal number day size 
 155         self
.num_size 
= 12      # default size of calendar if no auto size 
 156         self
.max_num_size 
= 12  # maximum size for calendar number 
 158         self
.num_align_horz 
= wx
.ALIGN_CENTRE    
# alignment of numbers 
 159         self
.num_align_vert 
= wx
.ALIGN_CENTRE
 
 160         self
.num_indent_horz 
= 0     # points indent from position, used to offset if not centered 
 161         self
.num_indent_vert 
= 0 
 163         self
.week_auto 
= True       # auto scale of week font text 
 165         self
.max_week_size 
= 12 
 167         self
.colors 
= DefaultColors() 
 170         self
.bold 
= wx
.NORMAL
 
 172         self
.hide_title 
= False 
 173         self
.hide_grid 
= False 
 174         self
.outer_border 
= True 
 176         self
.title_offset 
= 0 
 177         self
.cal_week_scale 
= 0.7 
 178         self
.show_weekend 
= False 
 179         self
.cal_type 
= "NORMAL" 
 181     def SetWeekColor(self
, font_color
, week_color
): 
 182         # set font and background color for week title 
 183         self
.colors
[COLOR_HEADER_FONT
] = MakeColor(font_color
) 
 184         self
.colors
[COLOR_HEADER_BACKGROUND
] = MakeColor(week_color
) 
 185         self
.colors
[COLOR_3D_LIGHT
] = MakeColor(week_color
) 
 186         self
.colors
[COLOR_3D_DARK
] = MakeColor(week_color
) 
 188     def SetSize(self
, size
): 
 189         self
.set_sizew 
= size
[0] 
 190         self
.set_sizeh 
= size
[1] 
 192     def InitValues(self
):       # default dimensions of various elements of the calendar 
 195         self
.set_cy_st 
= 0      # start position 
 198         self
.set_y_mrg 
= 1      # start of vertical draw default 
 201     def SetPos(self
, xpos
, ypos
): 
 202         self
.set_cx_st 
= xpos
 
 203         self
.set_cy_st 
= ypos
 
 205     def SetMarg(self
, xmarg
, ymarg
): 
 206         self
.set_x_mrg 
= xmarg
 
 207         self
.set_y_mrg 
= ymarg
 
 208         self
.set_y_end 
= ymarg
 
 210     def InitScale(self
):        # scale position values 
 211         self
.sizew 
= int(self
.set_sizew 
* self
.pwidth
) 
 212         self
.sizeh 
= int(self
.set_sizeh 
* self
.pheight
) 
 214         self
.cx_st 
= int(self
.set_cx_st 
* self
.pwidth
)       # draw start position 
 215         self
.cy_st 
= int(self
.set_cy_st 
* self
.pheight
) 
 217         self
.x_mrg 
= int(self
.set_x_mrg 
* self
.pwidth
)         # calendar draw margins 
 218         self
.y_mrg 
= int(self
.set_y_mrg 
* self
.pheight
) 
 219         self
.y_end 
= int(self
.set_y_end 
* self
.pheight
) 
 221     def DrawCal(self
, DC
, sel_lst
=[]): 
 226         if self
.hide_title 
is False: 
 233         if self
.show_weekend 
is True:       # highlight weekend dates 
 236         self
.AddSelect(sel_lst
)     # overrides the weekend highlight 
 238         self
.DrawSel(DC
)      # highlighted days 
 242     def AddSelect(self
, list, cfont
=None, cbackgrd 
= None): 
 244             cfont 
= self
.colors
[COLOR_SELECTION_FONT
]      # font digit color 
 246             cbackgrd 
= self
.colors
[COLOR_SELECTION_BACKGROUND
]     # select background color 
 249             self
.cal_sel
[val
] = (cfont
, cbackgrd
) 
 251     # draw border around the outside of the main display rectangle 
 252     def DrawBorder(self
, DC
, transparent 
= False):    
 253         if self
.outer_border 
is True: 
 254             if transparent 
== False: 
 255                 brush 
= wx
.Brush(MakeColor(self
.colors
[COLOR_BACKGROUND
]), wx
.SOLID
) 
 257                 brush 
= wx
.TRANSPARENT_BRUSH
 
 259             DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_BORDER
]))) 
 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 DrawFocusIndicator(self
, DC
): 
 265         if self
.outer_border 
is True: 
 266             DC
.SetBrush(wx
.TRANSPARENT_BRUSH
) 
 267             DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_HIGHLIGHT_BACKGROUND
]), style
=wx
.DOT
)) 
 268             # full display window area 
 269             rect 
= wx
.Rect(self
.cx_st
, self
.cy_st
, self
.sizew
, self
.sizeh
)   
 270             DC
.DrawRectangleRect(rect
) 
 272     def DrawNumVal(self
): 
 275     # calculate the calendar days and offset position 
 276     def SetCal(self
, year
, month
): 
 277         self
.InitValues()       # reset initial values 
 283         t 
= Date(year
, month
, day
) 
 284         dow 
= self
.dow 
= t
.day_of_week     
# start day in month 
 285         dim 
= self
.dim 
= t
.days_in_month   
# number of days in month 
 287         if self
.cal_type 
== "NORMAL": 
 292         self
.st_pos 
= start_pos
 
 295         for i 
in range(start_pos
): 
 296             self
.cal_days
.append('') 
 300             self
.cal_days
.append(str(i
)) 
 303         self
.end_pos 
= start_pos 
+ dim 
- 1 
 307     def SetWeekEnd(self
, font_color
=None, backgrd 
= None): 
 308         if font_color 
!= None: 
 309             self
.SetColor(COLOR_WEEKEND_FONT
, MakeColor(font_color
)) 
 311             self
.SetColor(COLOR_WEEKEND_BACKGROUND
, MakeColor(backgrd
)) 
 313         date 
= 6 - int(self
.dow
)     # start day of first saturday 
 315         while date 
<= self
.dim
: 
 316             self
.cal_sel
[date
] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
))  # Saturday 
 320                 self
.cal_sel
[date
] = (self
.GetColor(COLOR_WEEKEND_FONT
), self
.GetColor(COLOR_WEEKEND_BACKGROUND
))      # Sunday 
 325     # get the display rectange list of the day grid 
 330         for y 
in self
.gridy
[1:-1]: 
 331             if y 
== self
.gridy
[-2]: 
 334             for x 
in self
.gridx
[:-1]: 
 335                 assert type(y
) == int 
 336                 assert type(x
) == int 
 341                 if x 
== self
.gridx
[-2]: 
 344                 rect 
= wx
.Rect(x
, y
, w
+1, h
+1)  # create rect region 
 357     # month and year title 
 358     def DrawMonth(self
, DC
): 
 359         month 
= Month
[self
.month
] 
 362         if self
.sizeh 
< _MIDSIZE
: 
 365         f 
= wx
.Font(sizef
, self
.font
, wx
.NORMAL
, self
.bold
) 
 368         tw
,th 
= DC
.GetTextExtent(month
) 
 369         adjust 
= self
.cx_st 
+ (self
.sizew
-tw
)/2 
 370         DC
.DrawText(month
, adjust
, self
.cy_st 
+ th
) 
 372         year 
= str(self
.year
) 
 373         tw
,th 
= DC
.GetTextExtent(year
) 
 374         adjust 
=  self
.sizew 
- tw 
- self
.x_mrg
 
 376         self
.title_offset 
= th 
* 2 
 378         f 
= wx
.Font(sizef
, self
.font
, wx
.NORMAL
, self
.bold
) 
 380         DC
.DrawText(year
, self
.cx_st 
+ adjust
, self
.cy_st 
+ th
) 
 382     def DrawWeek(self
, DC
):     # draw the week days 
 383         # increase by 1 to include all gridlines 
 384         width  
= self
.gridx
[1] - self
.gridx
[0] + 1 
 385         height 
= self
.gridy
[1] - self
.gridy
[0] + 1 
 386         rect_w 
= self
.gridx
[-1] - self
.gridx
[0] 
 388         f 
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
)      # initial font setting 
 390         if self
.week_auto 
== True: 
 391             test_size 
= self
.max_week_size      
# max size 
 394                 f
.SetPointSize(test_size
) 
 396                 tw
,th 
= DC
.GetTextExtent(test_day
) 
 398                 if tw 
< width 
and th 
< height
: 
 401                 test_size 
= test_size 
- 1 
 403             f
.SetPointSize(self
.week_size
)   # set fixed size 
 406         DC
.SetTextForeground(MakeColor(self
.colors
[COLOR_HEADER_FONT
])) 
 411         brush 
= wx
.Brush(MakeColor(self
.colors
[COLOR_HEADER_BACKGROUND
]), wx
.SOLID
) 
 414         if self
.cal_type 
== "NORMAL": 
 417             cal_days 
= BusCalDays
 
 420             if val 
== cal_days
[-1]: 
 421                 width 
= width 
+ self
.restW
 
 423             day 
= AbrWeekday
[val
] 
 428             dw
,dh 
= DC
.GetTextExtent(day
) 
 431             diffy 
= (height
-dh
)/2 
 433             x 
= self
.gridx
[cnt_x
] 
 434             y 
= self
.gridy
[cnt_y
] 
 436             pointWH 
= (width
, height
) 
 437             if self
.hide_grid 
== False: 
 438                 pen 
= wx
.Pen(MakeColor(self
.GetColor(COLOR_GRID_LINES
)), 1, wx
.SOLID
) 
 440                 pen 
= wx
.Pen(MakeColor(self
.GetColor(COLOR_BACKGROUND
)), 1, wx
.SOLID
) 
 442             DC
.DrawRectanglePointSize( pointXY
, pointWH
) 
 444             old_pen 
= DC
.GetPen() 
 446             pen 
= wx
.Pen(MakeColor(self
.colors
[COLOR_3D_LIGHT
]), 1, wx
.SOLID
) 
 448             # draw the horizontal hilight 
 449             startPoint 
= wx
.Point(x 
+ 1 , y 
+ 1) 
 450             endPoint   
= wx
.Point(x 
+ width 
- 1, y 
+ 1) 
 451             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 453             # draw the vertical hilight 
 454             startPoint 
= wx
.Point(x 
+ 1 , y 
+ 1) 
 455             endPoint   
= wx
.Point(x 
+ 1, y 
+ height 
- 2) 
 456             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 458             pen 
= wx
.Pen(MakeColor(self
.colors
[COLOR_3D_DARK
]), 1, wx
.SOLID
) 
 461             # draw the horizontal lowlight 
 462             startPoint 
= wx
.Point(x 
+ 1, y 
+ height 
- 2) 
 463             endPoint   
= wx
.Point(x 
+ width 
- 1, y 
+ height 
- 2) 
 464             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 466             # draw the vertical lowlight 
 467             startPoint 
= wx
.Point(x 
+ width 
- 2 , y 
+ 2) 
 468             endPoint   
= wx
.Point(x 
+ width 
- 2, y 
+ height 
- 2) 
 469             DC
.DrawLinePoint(startPoint
, endPoint 
) 
 471             pen 
= wx
.Pen(MakeColor(self
.colors
[COLOR_FONT
]), 1, wx
.SOLID
) 
 475             point 
= (x
+diffx
, y
+diffy
) 
 476             DC
.DrawTextPoint(day
, point
) 
 479     def _CalcFontSize(self
, DC
, f
): 
 480         if self
.num_auto 
== True: 
 481             test_size 
= self
.max_num_size      
# max size 
 485                 f
.SetPointSize(test_size
) 
 487                 tw
,th 
= DC
.GetTextExtent(test_day
) 
 489                 if tw 
< self
.cellW 
and th 
< self
.cellH
: 
 492                 test_size 
= test_size 
- 1 
 494             f
.SetPointSize(self
.num_size
)   # set fixed size 
 497     # draw the day numbers 
 498     def DrawNum(self
, DC
):       
 499         f 
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
)      # initial font setting 
 500         self
._CalcFontSize
(DC
, f
) 
 504         for val 
in self
.cal_days
: 
 505             x 
= self
.gridx
[cnt_x
] 
 506             y 
= self
.gridy
[cnt_y
] 
 508             self
._DrawDayText
(x
, y
, val
, f
, DC
) 
 516     def _DrawDayText(self
, x
, y
, text
, font
, DC
): 
 520             num_color 
= self
.cal_sel
[num_val
][0] 
 522             num_color 
= self
.colors
[COLOR_FONT
] 
 524         DC
.SetTextForeground(MakeColor(num_color
)) 
 527         tw
,th 
= DC
.GetTextExtent(text
) 
 529         if self
.num_align_horz 
== wx
.ALIGN_CENTRE
: 
 530             adj_h 
= (self
.cellW 
- tw
)/2 
 531         elif self
.num_align_horz 
== wx
.ALIGN_RIGHT
: 
 532             adj_h 
= self
.cellW 
- tw
 
 534             adj_h 
= 0   # left alignment 
 536         adj_h 
= adj_h 
+ self
.num_indent_horz
 
 538         if self
.num_align_vert 
== wx
.ALIGN_CENTRE
: 
 539             adj_v 
= (self
.cellH 
- th
)/2 
 540         elif self
.num_align_vert 
== wx
.ALIGN_BOTTOM
: 
 541             adj_v 
= self
.cellH 
- th
 
 543             adj_v 
= 0   # left alignment 
 545         adj_v 
= adj_v 
+ self
.num_indent_vert
 
 547         DC
.DrawTextPoint(text
, (x
+adj_h
, y
+adj_v
)) 
 549     def DrawDayText(self
, DC
, key
): 
 550         f 
= wx
.Font(10, self
.font
, wx
.NORMAL
, self
.bold
)      # initial font setting 
 551         self
._CalcFontSize
(DC
, f
) 
 553         if key 
> self
.end_pos
:  
 556         val 
= self
.cal_days
[key
] 
 558         cnt_y 
= int(key 
/ 7)+1 
 559         x 
= self
.gridx
[cnt_x
] 
 560         y 
= self
.gridy
[cnt_y
] 
 561         self
._DrawDayText
(x
, y
, val
, f
, DC
) 
 564     # calculate the dimensions in the center of the drawing area 
 566         borderW 
= self
.x_mrg 
* 2 
 567         borderH 
= self
.y_mrg 
+ self
.y_end 
+ self
.title_offset
 
 569         self
.cellW 
= int((self
.sizew 
- borderW
)/7) 
 570         self
.cellH 
= int((self
.sizeh 
- borderH
)/7) 
 572         self
.restW 
= ((self
.sizew 
- borderW
)%7 ) - 1 
 574         # week title adjustment 
 575         self
.weekHdrCellH 
= int(self
.cellH 
* self
.cal_week_scale
) 
 576         # recalculate the cell height exkl. the week header and 
 577         # subtracting the size 
 578         self
.cellH 
= int((self
.sizeh 
- borderH 
- self
.weekHdrCellH
)/6) 
 580         self
.restH 
= ((self
.sizeh 
- borderH 
- self
.weekHdrCellH
)%6 ) - 1 
 581         self
.calW 
= self
.cellW 
* 7 
 582         self
.calH 
= self
.cellH 
* 6 + self
.weekHdrCellH
 
 584     # highlighted selected days 
 585     def DrawSel(self
, DC
): 
 587         for key 
in self
.cal_sel
.keys(): 
 588             sel_color 
= self
.cal_sel
[key
][1] 
 589             brush 
= wx
.Brush(MakeColor(sel_color
), wx
.SOLID
) 
 592             if self
.hide_grid 
is False: 
 593                 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_GRID_LINES
]), 0)) 
 595                 DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_BACKGROUND
]), 0)) 
 597             nkey 
= key 
+ self
.st_pos 
-1 
 600             DC
.DrawRectangleRect(rect
) 
 602     # calculate and draw the grid lines 
 603     def DrawGrid(self
, DC
): 
 604         DC
.SetPen(wx
.Pen(MakeColor(self
.colors
[COLOR_GRID_LINES
]), 0)) 
 609         self
.x_st 
= self
.cx_st 
+ self
.x_mrg
 
 610         # start postion of draw 
 611         self
.y_st 
= self
.cy_st 
+ self
.y_mrg 
+ self
.title_offset
 
 615         y2 
= y1 
+ self
.calH 
+ self
.restH
 
 621             if self
.hide_grid 
is False: 
 622                 DC
.DrawLinePoint((x1
, y1
), (x1
, y2
)) 
 624             self
.gridx
.append(x1
) 
 630         x2 
= x1 
+ self
.calW 
+ self
.restW
 
 636             if self
.hide_grid 
is False: 
 637                 DC
.DrawLinePoint((x1
, y1
), (x2
, y1
)) 
 639             self
.gridy
.append(y1
) 
 642                 y1 
= y1 
+ self
.weekHdrCellH
 
 646     def GetColor(self
, name
): 
 647         return MakeColor(self
.colors
[name
]) 
 649     def SetColor(self
, name
, value
): 
 650         self
.colors
[name
] = MakeColor(value
) 
 652 class PrtCalDraw(CalDraw
): 
 653     def InitValues(self
): 
 656         # start draw border location 
 660         # draw offset position 
 665     # calculate the dimensions in the center of the drawing area 
 666     def SetPSize(self
, pwidth
, pheight
):     
 667         self
.pwidth 
= int(pwidth
)/self
.scale
 
 668         self
.pheight 
= int(pheight
)/self
.scale
 
 670     def SetPreview(self
, preview
): 
 671         self
.preview 
= preview
 
 673 class Calendar( wx
.PyControl 
): 
 674     def __init__(self
, parent
, id, pos
=wx
.DefaultPosition
, size
=wx
.Size(200,200), 
 675                    style
= 0, validator
=wx
.DefaultValidator
, 
 677         wx
.PyControl
.__init
__(self
, parent
, id, pos
, size
, style | wx
.WANTS_CHARS
, validator
, name
) 
 679         self
.hasFocus 
= False 
 680         # set the calendar control attributes 
 682         self
.hide_grid 
= False 
 683         self
.hide_title 
= False 
 684         self
.show_weekend 
= False 
 685         self
.cal_type 
= "NORMAL" 
 686         self
.outer_border 
= True 
 687         self
.num_align_horz 
= wx
.ALIGN_CENTRE
 
 688         self
.num_align_vert 
= wx
.ALIGN_CENTRE
 
 689         self
.colors 
= DefaultColors() 
 694         self
.select_list 
= [] 
 696         self
.SetBackgroundColour(MakeColor(self
.colors
[COLOR_BACKGROUND
])) 
 697         self
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnLeftEvent
) 
 698         self
.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnLeftDEvent
) 
 699         self
.Bind(wx
.EVT_RIGHT_DOWN
, self
.OnRightEvent
) 
 700         self
.Bind(wx
.EVT_RIGHT_DCLICK
, self
.OnRightDEvent
) 
 701         self
.Bind(wx
.EVT_SET_FOCUS
, self
.OnSetFocus
) 
 702         self
.Bind(wx
.EVT_KILL_FOCUS
, self
.OnKillFocus
) 
 703         self
.Bind(wx
.EVT_KEY_DOWN
, self
.OnKeyDown
) 
 705         self
.sel_key 
= None      #  last used by 
 706         self
.sel_lst 
= []        # highlighted selected days 
 708         # default calendar for current month 
 714         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
 715         self
.Bind(wx
.EVT_SIZE
, self
.OnSize
) 
 717     def AcceptsFocus(self
): 
 718         return self
.IsShown() and self
.IsEnabled() 
 720     def GetColor(self
, name
): 
 721         return MakeColor(self
.colors
[name
]) 
 723     def SetColor(self
, name
, value
): 
 724         self
.colors
[name
] = MakeColor(value
) 
 726     # control some of the main calendar attributes 
 729         self
.hide_title 
= True 
 732         self
.hide_grid 
= True 
 734     # determine the calendar rectangle click area and draw a selection 
 736     def ProcessClick(self
, event
): 
 737         self
.x
, self
.y 
= event
.GetX(), event
.GetY() 
 738         key 
= self
.GetDayHit(self
.x
, self
.y
) 
 741     # tab mouse click events and process 
 743     def OnLeftEvent(self
, event
): 
 745         self
.shiftkey 
= event
.ShiftDown() 
 746         self
.ctrlkey 
= event
.ControlDown() 
 747         self
.ProcessClick(event
) 
 749     def OnLeftDEvent(self
, event
): 
 751         self
.ProcessClick(event
) 
 753     def OnRightEvent(self
, event
): 
 755         self
.ProcessClick(event
) 
 757     def OnRightDEvent(self
, event
): 
 758         self
.click 
= 'DRIGHT' 
 759         self
.ProcessClick(event
) 
 761     def OnSetFocus(self
, event
): 
 763         self
.DrawFocusIndicator(True) 
 765     def OnKillFocus(self
, event
): 
 766         self
.hasFocus 
= False 
 767         self
.DrawFocusIndicator(False) 
 769     def OnKeyDown(self
, event
): 
 770         if not self
.hasFocus
: 
 774         key_code 
= event
.KeyCode() 
 776         if key_code 
== wx
.WXK_TAB
: 
 777             forward 
= not event
.ShiftDown() 
 778             ne 
= wx
.NavigationKeyEvent() 
 779             ne
.SetDirection(forward
) 
 780             ne
.SetCurrentFocus(self
) 
 781             ne
.SetEventObject(self
) 
 782             self
.GetParent().GetEventHandler().ProcessEvent(ne
) 
 788         if key_code 
== wx
.WXK_UP
: 
 790         elif key_code 
== wx
.WXK_DOWN
: 
 792         elif key_code 
== wx
.WXK_LEFT
: 
 794         elif key_code 
== wx
.WXK_RIGHT
: 
 796         elif key_code 
== wx
.WXK_HOME
: 
 797             curDate 
= wx
.DateTimeFromDMY(int(self
.cal_days
[self
.sel_key
]),self
.month 
- 1,self
.year
) 
 798             newDate 
= wx
.DateTime_Now() 
 799             ts 
= newDate 
- curDate
 
 803             curDate 
= wx
.DateTimeFromDMY(int(self
.cal_days
[self
.sel_key
]),self
.month 
- 1,self
.year
) 
 804             timeSpan 
= wx
.TimeSpan_Days(delta
) 
 805             newDate 
= curDate 
+ timeSpan
 
 807             if curDate
.GetMonth() == newDate
.GetMonth(): 
 808                 self
.set_day 
= newDate
.GetDay() 
 809                 key 
= self
.sel_key 
+ delta
 
 812                 self
.month 
= newDate
.GetMonth() + 1 
 813                 self
.year 
= newDate
.GetYear() 
 814                 self
.set_day 
= newDate
.GetDay() 
 816                 self
.DoDrawing(wx
.ClientDC(self
)) 
 820     def SetSize(self
, set_size
): 
 823     def SetSelDay(self
, sel
): 
 824         # list of highlighted days 
 827     # get the current date 
 830         self
.month 
= dt
.month
 
 834     # set the current day 
 835     def SetCurrentDay(self
): 
 837         self
.set_day 
= self
.day
 
 839     # get the date, day, month, year set in calendar 
 842         return self
.day
, self
.month
, self
.year
 
 853     # set the day, month, and year 
 855     def SetDayValue(self
, day
): 
 858     def SetMonth(self
, month
): 
 859         if month 
>= 1 and month 
<= 12: 
 865     def SetYear(self
, year
): 
 868     # increment year and month 
 871         self
.year 
= self
.year 
+ 1 
 875         self
.year 
= self
.year 
- 1 
 879         self
.month 
= self
.month 
+ 1 
 882             self
.year 
= self
.year 
+ 1 
 886         self
.month 
= self
.month 
- 1 
 889             self
.year 
= self
.year 
- 1 
 892     # test to see if the selection has a date and create event 
 894     def TestDay(self
, key
): 
 896             self
.day 
= int(self
.cal_days
[key
]) 
 903             # Changed 12/1/03 by jmg (see above) to support 2.5 event binding 
 904             evt 
= wx
.PyCommandEvent(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED
, self
.GetId()) 
 905             evt
.click
, evt
.day
, evt
.month
, evt
.year 
= self
.click
, self
.day
, self
.month
, self
.year
 
 906             evt
.shiftkey 
= self
.shiftkey
 
 907             evt
.ctrlkey 
= self
.ctrlkey
 
 908             self
.GetEventHandler().ProcessEvent(evt
) 
 910             self
.set_day 
= self
.day
 
 913     # find the clicked area rectangle 
 915     def GetDayHit(self
, mx
, my
): 
 916         for key 
in self
.rg
.keys(): 
 918             ms_rect 
= wx
.Rect(mx
, my
, 1, 1) 
 919             if wx
.IntersectRect(ms_rect
, val
) is not None: 
 920                 result 
= self
.TestDay(key
) 
 927     def SetWeekColor(self
, font_color
, week_color
):      
 928         # set font and background color for week title 
 929         self
.colors
[COLOR_HEADER_FONT
] = MakeColor(font_color
) 
 930         self
.colors
[COLOR_HEADER_BACKGROUND
] = MakeColor(week_color
) 
 931         self
.colors
[COLOR_3D_LIGHT
] = MakeColor(week_color
) 
 932         self
.colors
[COLOR_3D_DARK
] = MakeColor(week_color
) 
 934     def SetTextAlign(self
, vert
, horz
): 
 935         self
.num_align_horz 
= horz
 
 936         self
.num_align_vert 
= vert
 
 938     def AddSelect(self
, list, font_color
, back_color
): 
 939         list_val 
= [list, font_color
, back_color
] 
 940         self
.select_list
.append(list_val
) 
 942     def ShowWeekEnd(self
): 
 944         self
.show_weekend 
= True 
 946     def SetBusType(self
): 
 947         self
.cal_type 
= "BUS" 
 949     def OnSize(self
, evt
): 
 953     def OnPaint(self
, event
): 
 954         DC 
= wx
.PaintDC(self
) 
 957     def DoDrawing(self
, DC
): 
 958         #DC = wx.PaintDC(self) 
 964             self
.caldraw 
= CalDraw(self
) 
 967         cal
.hide_grid 
= self
.hide_grid
 
 968         cal
.hide_title 
= self
.hide_title
 
 969         cal
.show_weekend 
= self
.show_weekend
 
 970         cal
.cal_type 
= self
.cal_type
 
 971         cal
.outer_border 
= self
.outer_border
 
 972         cal
.num_align_horz 
= self
.num_align_horz
 
 973         cal
.num_align_vert 
= self
.num_align_vert
 
 974         cal
.colors 
= self
.colors
 
 976         if self
.size 
is None: 
 977             size 
= self
.GetClientSize() 
 984         cal
.SetCal(self
.year
, self
.month
) 
 986         # these have to set after SetCal as SetCal would overwrite them again. 
 987         cal
.set_x_mrg 
= self
.set_x_mrg 
 
 988         cal
.set_y_mrg 
= self
.set_y_mrg 
 
 989         cal
.set_y_end 
= self
.set_y_end 
 
 991         for val 
in self
.select_list
: 
 992             cal
.AddSelect(val
[0], val
[1], val
[2]) 
 994         cal
.DrawCal(DC
, self
.sel_lst
) 
 996         self
.rg 
= cal
.GetRect() 
 997         self
.cal_days 
= cal
.GetCal() 
 998         self
.st_pos 
= cal
.GetOffset() 
 999         self
.ymax 
= DC
.MaxY() 
1001         if self
.set_day 
!= None: 
1002             self
.SetDay(self
.set_day
) 
1006     # draw the selection rectangle 
1007     def DrawFocusIndicator(self
, draw
): 
1008         DC 
= wx
.ClientDC(self
) 
1011                 self
.caldraw
.DrawFocusIndicator(DC
) 
1013                 self
.caldraw
.DrawBorder(DC
,True) 
1017     def DrawRect(self
, key
, bgcolor 
= 'WHITE', fgcolor
= 'PINK',width 
= 0): 
1021         DC 
= wx
.ClientDC(self
) 
1024         brush 
= wx
.Brush(MakeColor(bgcolor
)) 
1027         DC
.SetPen(wx
.TRANSPARENT_PEN
) 
1030         DC
.DrawRectangle(rect
.x
+1, rect
.y
+1, rect
.width
-2, rect
.height
-2) 
1032         self
.caldraw
.DrawDayText(DC
,key
) 
1036     def DrawRectOrg(self
, key
, fgcolor 
= 'BLACK', width 
= 0): 
1040         DC 
= wx
.ClientDC(self
) 
1043         brush 
= wx
.Brush(wx
.Colour(0, 0xFF, 0x80), wx
.TRANSPARENT
) 
1047             DC
.SetPen(wx
.Pen(MakeColor(fgcolor
), width
)) 
1049             DC
.SetPen(wx
.Pen(MakeColor(self
.GetColor(COLOR_GRID_LINES
)), width
)) 
1052         DC
.DrawRectangleRect(rect
) 
1056     # set the day selection 
1058     def SetDay(self
, day
): 
1059         d 
= day 
+ self
.st_pos 
- 1 
1062     def IsDayInWeekend(self
, key
): 
1064             t 
= Date(self
.year
, self
.month
, 1) 
1066             day 
= self
.cal_days
[key
] 
1067             day 
= int(day
) + t
.day_of_week
 
1069             if day 
% 7 == 6 or day 
% 7 == 0: 
1074     def SelectDay(self
, key
): 
1076         # clear large selection 
1078         if self
.sel_key 
!= None: 
1079             (cfont
, bgcolor
) = self
.__GetColorsForDay
(self
.sel_key
) 
1080             self
.DrawRect(self
.sel_key
, bgcolor
,cfont
, sel_size
) 
1082         self
.DrawRect(key
, self
.GetColor(COLOR_HIGHLIGHT_BACKGROUND
), self
.GetColor(COLOR_HIGHLIGHT_FONT
), sel_size
) 
1083         # store last used by 
1088     def SetMargin(self
, xmarg
, ymarg
): 
1089         self
.set_x_mrg 
= xmarg
 
1090         self
.set_y_mrg 
= ymarg
 
1091         self
.set_y_end 
= ymarg
 
1092     def __GetColorsForDay(self
, key
): 
1093         cfont   
= self
.GetColor(COLOR_FONT
) 
1094         bgcolor 
= self
.GetColor(COLOR_BACKGROUND
) 
1096         if self
.IsDayInWeekend(key
) is True and self
.show_weekend 
is True: 
1097             cfont   
= self
.GetColor(COLOR_WEEKEND_FONT
) 
1098             bgcolor 
= self
.GetColor(COLOR_WEEKEND_BACKGROUND
) 
1101             dayIdx 
= int(self
.cal_days
[key
]) 
1102             (cfont
, bgcolor
) = self
.caldraw
.cal_sel
[dayIdx
] 
1106         return (cfont
, bgcolor
) 
1108 class CalenDlg(wx
.Dialog
): 
1109     def __init__(self
, parent
, month
=None, day 
= None, year
=None): 
1110         wx
.Dialog
.__init
__(self
, parent
, -1, "Event Calendar", wx
.DefaultPosition
, (280, 360)) 
1113         # set the calendar and attributes 
1114         self
.calend 
= Calendar(self
, -1, (20, 60), (240, 200)) 
1117             self
.calend
.SetCurrentDay() 
1118             start_month 
= self
.calend
.GetMonth() 
1119             start_year 
= self
.calend
.GetYear() 
1121             self
.calend
.month 
= start_month 
= month
 
1122             self
.calend
.year 
= start_year 
= year
 
1123             self
.calend
.SetDayValue(day
) 
1125         self
.calend
.HideTitle() 
1128         # get month list from DateTime 
1129         monthlist 
= GetMonthList() 
1132         self
.date 
= wx
.ComboBox(self
, -1, Month
[start_month
], (20, 20), (90, -1),  
1133                                 monthlist
, wx
.CB_DROPDOWN
) 
1134         self
.Bind(wx
.EVT_COMBOBOX
, self
.EvtComboBox
, self
.date
) 
1136         # alternate spin button to control the month 
1137         h 
= self
.date
.GetSize().height
 
1138         self
.m_spin 
= wx
.SpinButton(self
, -1, (115, 20), (h
*1.5, h
), wx
.SP_VERTICAL
) 
1139         self
.m_spin
.SetRange(1, 12) 
1140         self
.m_spin
.SetValue(start_month
) 
1141         self
.Bind(wx
.EVT_SPIN
, self
.OnMonthSpin
, self
.m_spin
) 
1143         # spin button to control the year 
1144         self
.dtext 
= wx
.TextCtrl(self
, -1, str(start_year
), (160, 20), (60, -1)) 
1145         h 
= self
.dtext
.GetSize().height
 
1147         self
.y_spin 
= wx
.SpinButton(self
, -1, (225, 20), (h
*1.5, h
), wx
.SP_VERTICAL
) 
1148         self
.y_spin
.SetRange(1980, 2010) 
1149         self
.y_spin
.SetValue(start_year
) 
1151         self
.Bind(wx
.EVT_SPIN
, self
.OnYrSpin
, self
.y_spin
) 
1152         self
.Bind(EVT_CALENDAR
, self
.MouseClick
, self
.calend
) 
1158         btn 
= wx
.Button(self
, wx
.ID_OK
, ' Ok ', (x_pos
, y_pos
), but_size
) 
1159         self
.Bind(wx
.EVT_BUTTON
, self
.OnOk
, btn
) 
1161         btn 
= wx
.Button(self
, wx
.ID_CANCEL
, ' Close ', (x_pos 
+ 120, y_pos
), but_size
) 
1162         self
.Bind(wx
.EVT_BUTTON
, self
.OnCancel
, btn
) 
1164     def OnOk(self
, evt
): 
1165         self
.result 
= ['None', str(self
.calend
.day
), Month
[self
.calend
.month
], str(self
.calend
.year
)] 
1166         self
.EndModal(wx
.ID_OK
) 
1168     def OnCancel(self
, event
): 
1169         self
.EndModal(wx
.ID_CANCEL
) 
1171     # log the mouse clicks 
1172     def MouseClick(self
, evt
): 
1173         self
.month 
= evt
.month
 
1174         # result click type and date 
1175         self
.result 
= [evt
.click
, str(evt
.day
), Month
[evt
.month
], str(evt
.year
)]   
1177         if evt
.click 
== 'DLEFT': 
1178             self
.EndModal(wx
.ID_OK
) 
1180     # month and year spin selection routines 
1181     def OnMonthSpin(self
, event
): 
1182         month 
= event
.GetPosition() 
1183         self
.date
.SetValue(Month
[month
]) 
1184         self
.calend
.SetMonth(month
) 
1185         self
.calend
.Refresh() 
1187     def OnYrSpin(self
, event
): 
1188         year 
= event
.GetPosition() 
1189         self
.dtext
.SetValue(str(year
)) 
1190         self
.calend
.SetYear(year
) 
1191         self
.calend
.Refresh() 
1193     def EvtComboBox(self
, event
): 
1194         name 
= event
.GetString() 
1195         monthval 
= self
.date
.FindString(name
) 
1196         self
.m_spin
.SetValue(monthval
+1) 
1198         self
.calend
.SetMonth(monthval
+1) 
1201     # set the calendar for highlighted days 
1203     def ResetDisplay(self
): 
1204         month 
= self
.calend
.GetMonth() 
1205         self
.calend
.Refresh()