1 #----------------------------------------------------------------------------
3 # Purpose: Calendar display control
5 # Author: Lorne White (email: lwhite1@planet.eon.net)
8 # Version 0.6 2000/03/30
9 # Licence: wxWindows license
10 #----------------------------------------------------------------------------
12 from wxPython
.wx
import *
18 CalDays
= [6, 0, 1, 2, 3, 4, 5]
19 AbrWeekday
= {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"}
22 BusCalDays
= [0, 1, 2, 3, 4, 5, 6]
24 # calendar drawing routing
27 def __init__(self
, parent
):
31 self
.scale
= parent
.scale
38 self
.grid_color
= 'BLACK' # grid and selection colors
39 self
.back_color
= 'WHITE'
40 self
.sel_color
= 'RED'
42 self
.high_color
= 'LIGHT BLUE'
43 self
.border_color
= 'BLACK'
44 self
.week_color
= 'LIGHT GREY'
46 self
.week_font_color
= 'BLACK' # font colors
47 self
.day_font_color
= 'BLACK'
52 self
.hide_title
= FALSE
53 self
.hide_grid
= FALSE
54 self
.outer_border
= TRUE
57 self
.cal_week_scale
= 0.7
58 self
.show_weekend
= FALSE
59 self
.cal_type
= "NORMAL"
61 def SetWeekColor(self
, font_color
, week_color
): # set font and background color for week title
62 self
.week_font_color
= font_color
63 self
.week_color
= week_color
65 def SetSize(self
, size
):
66 self
.set_sizew
= size
.width
67 self
.set_sizeh
= size
.height
69 def InitValues(self
): # default dimensions of various elements of the calendar
72 self
.set_cy_st
= 0 # start position
75 self
.set_y_mrg
= 15 # start of vertical draw default
79 def SetPos(self
, xpos
, ypos
):
83 def SetMarg(self
, xmarg
, ymarg
):
86 self
.set_y_end
= ymarg
88 def InitScale(self
): # scale position values
89 self
.sizew
= self
.set_sizew
* self
.pwidth
90 self
.sizeh
= self
.set_sizeh
* self
.pheight
92 self
.cx_st
= self
.set_cx_st
* self
.pwidth
# draw start position
93 self
.cy_st
= self
.set_cy_st
* self
.pheight
95 self
.x_mrg
= self
.set_x_mrg
* self
.pwidth
# calendar draw margins
96 self
.y_mrg
= self
.set_y_mrg
* self
.pheight
97 self
.y_end
= self
.set_y_end
* self
.pheight
99 def DrawCal(self
, DC
, sel_lst
=[]):
104 if self
.hide_title
is FALSE
:
112 if self
.show_weekend
is TRUE
: # highlight weekend dates
115 self
.AddSelect(sel_lst
) # overrides the weekend highlight
117 self
.DrawSel() # highlighted days
121 def AddSelect(self
, list, cfont
=None, cbackgrd
= None):
123 cfont
= self
.sel_color
# font digit color
125 cbackgrd
= self
.high_color
# select background color
128 self
.cal_sel
[val
] = (cfont
, cbackgrd
)
130 def DrawBorder(self
): # draw border around the outside of the main display rectangle
131 brush
= wxBrush(wxNamedColour(self
.back_color
), wxSOLID
)
132 self
.DC
.SetBrush(brush
)
133 self
.DC
.SetPen(wxPen(wxNamedColour(self
.border_color
), 1))
135 if self
.outer_border
is TRUE
:
136 rect
= wxRect(self
.cx_st
, self
.cy_st
, self
.sizew
, self
.sizeh
) # full display window area
137 self
.DC
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
)
139 def DrawNumVal(self
):
142 # calculate the calendar days and offset position
144 def SetCal(self
, year
, month
):
145 self
.InitValues() # reset initial values
151 t
= Date(year
, month
, day
)
152 dow
= self
.dow
= t
.day_of_week
# start day in month
153 dim
= self
.dim
= t
.days_in_month
# number of days in month
154 if self
.cal_type
== "NORMAL":
159 self
.st_pos
= start_pos
162 for i
in range(start_pos
):
166 self
.cal
.append(str(i
))
170 def SetWeekEnd(self
, font_color
='BLACK', backgrd
= 'LIGHT GREY'):
171 date
= 6 - int(self
.dow
) # start day of first saturday
172 while date
<= self
.dim
:
173 self
.cal_sel
[date
] = (font_color
, backgrd
) # Saturday
176 self
.cal_sel
[date
] = (font_color
, backgrd
) # Sunday
181 def GetRect(self
): # get the display rectange list of the day grid
183 for y
in self
.gridy
[1:-1]:
184 for x
in self
.gridx
[:-1]:
185 rect
= wxRect(x
, y
, self
.dl_w
, self
.dl_h
) # create rect region
196 def DrawMonth(self
): # month and year title
197 month
= Month
[self
.month
]
200 if self
.sizeh
< _MIDSIZE
:
203 f
= wxFont(sizef
, self
.font
, wxNORMAL
, self
.bold
)
206 tw
,th
= self
.DC
.GetTextExtent(month
)
207 adjust
= self
.cx_st
+ (self
.sizew
-tw
)/2
208 self
.DC
.DrawText(month
, adjust
, self
.cy_st
+ th
)
210 year
= str(self
.year
)
211 tw
,th
= self
.DC
.GetTextExtent(year
)
212 adjust
= self
.sizew
- tw
- self
.x_mrg
214 self
.title_offset
= th
* 2
216 f
= wxFont(sizef
, self
.font
, wxNORMAL
, self
.bold
)
218 self
.DC
.DrawText(year
, self
.cx_st
+ adjust
, self
.cy_st
+ th
)
220 def DrawWeek(self
): # draw the week days
222 if self
.sizeh
< _MIDSIZE
:
225 f
= wxFont(sizef
, self
.font
, wxNORMAL
, self
.bold
)
227 self
.DC
.SetTextForeground(wxNamedColour(self
.week_font_color
))
231 width
= self
.gridx
[1]-self
.gridx
[0]
232 height
= self
.gridy
[1] - self
.gridy
[0]
234 rect_w
= self
.gridx
[7]-self
.gridx
[0]
236 brush
= wxBrush(wxNamedColour(self
.week_color
), wxSOLID
)
237 self
.DC
.SetBrush(brush
)
238 # self.DC.DrawRectangle(self.gridx[0], self.gridy[0], rect_w+1, height)
240 if self
.cal_type
== "NORMAL":
243 cal_days
= BusCalDays
246 day
= AbrWeekday
[val
]
249 dw
,dh
= self
.DC
.GetTextExtent(day
)
251 diffy
= (height
-dh
)/2
253 x
= self
.gridx
[cnt_x
]
254 y
= self
.gridy
[cnt_y
]
255 self
.DC
.DrawRectangle(self
.gridx
[cnt_x
], self
.gridy
[0], width
+1, height
)
256 self
.DC
.DrawText(day
, x
+diffx
, y
+diffy
)
260 def DrawNum(self
): # draw the day numbers
262 if self
.sizeh
< _MIDSIZE
:
264 f
= wxFont(sizef
, self
.font
, wxNORMAL
, self
.bold
)
269 x
= self
.gridx
[cnt_x
]
270 y
= self
.gridy
[cnt_y
]
274 num_color
= self
.cal_sel
[num_val
][0]
276 num_color
= self
.day_font_color
278 self
.DC
.SetTextForeground(wxNamedColour(num_color
))
281 self
.DC
.DrawText(val
, x
+5, y
+5)
288 def Center(self
): # calculate the dimensions in the center of the drawing area
290 bdh
= self
.y_mrg
+ self
.y_end
+ self
.title_offset
292 self
.dl_w
= int((self
.sizew
-bdw
)/7)
293 self
.dl_h
= int((self
.sizeh
-bdh
)/7)
295 self
.dl_th
= int(self
.dl_h
*self
.cal_week_scale
) # week title adjustment
296 self
.cwidth
= self
.dl_w
* 7
297 self
.cheight
= self
.dl_h
* 6 + self
.dl_th
299 def DrawSel(self
): # highlighted selected days
300 for key
in self
.cal_sel
.keys():
301 sel_color
= self
.cal_sel
[key
][1]
302 brush
= wxBrush(wxNamedColour(sel_color
), wxSOLID
)
303 self
.DC
.SetBrush(brush
)
305 if self
.hide_grid
is FALSE
:
306 self
.DC
.SetPen(wxPen(wxNamedColour(self
.grid_color
), 0))
308 self
.DC
.SetPen(wxPen(wxNamedColour(self
.back_color
), 0))
309 nkey
= key
+ self
.st_pos
-1
311 self
.DC
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
+1, rect
.height
+1)
313 def DrawGrid(self
): # calculate and draw the grid lines
314 self
.DC
.SetPen(wxPen(wxNamedColour(self
.grid_color
), 0))
319 self
.x_st
= self
.cx_st
+ self
.x_mrg
320 self
.y_st
= self
.cy_st
+ self
.y_mrg
+ self
.title_offset
# start postion of draw
325 y2
= y1
+ self
.cheight
327 if self
.hide_grid
is FALSE
:
328 self
.DC
.DrawLine(x1
, y1
, x1
, y2
)
329 self
.gridx
.append(x1
)
335 x2
= x1
+ self
.cwidth
337 if self
.hide_grid
is FALSE
:
338 self
.DC
.DrawLine(x1
, y1
, x2
, y1
)
339 self
.gridy
.append(y1
)
346 class PrtCalDraw(CalDraw
):
347 def InitValues(self
):
350 self
.set_cx_st
= 1.0 # start draw border location
353 self
.set_y_mrg
= 0.2 # draw offset position
357 def SetPSize(self
, pwidth
, pheight
): # calculate the dimensions in the center of the drawing area
358 self
.pwidth
= int(pwidth
)/self
.scale
359 self
.pheight
= int(pheight
)/self
.scale
361 def SetPreview(self
, preview
):
362 self
.preview
= preview
364 class wxCalendar(wxWindow
):
365 def __init__(self
, parent
, id, pos
=wxDefaultPosition
, size
=wxDefaultSize
):
366 wxWindow
.__init
__(self
, parent
, id, pos
, size
)
368 # set the calendar control attributes
370 self
.grid_color
= 'BLACK'
371 self
.back_color
= 'WHITE'
372 self
.hide_grid
= FALSE
373 self
.sel_color
= 'RED'
374 self
.hide_title
= FALSE
375 self
.show_weekend
= FALSE
376 self
.cal_type
= "NORMAL"
378 self
.week_color
= 'LIGHT GREY'
379 self
.week_font_color
= 'BLACK' # font colors
381 self
.select_list
= []
383 self
.SetBackgroundColour(wxNamedColor(self
.back_color
))
384 self
.Connect(-1, -1, wxEVT_LEFT_DOWN
, self
.OnLeftEvent
)
385 self
.Connect(-1, -1, wxEVT_LEFT_DCLICK
, self
.OnLeftDEvent
)
386 self
.Connect(-1, -1, wxEVT_RIGHT_DOWN
, self
.OnRightEvent
)
387 self
.Connect(-1, -1, wxEVT_RIGHT_DCLICK
, self
.OnRightDEvent
)
389 self
.sel_key
= None # last used by
390 self
.sel_lst
= [] # highlighted selected days
392 self
.SetNow() # default calendar for current month
397 EVT_PAINT(self
, self
.OnPaint
)
400 # control some of the main calendar attributes
403 self
.hide_title
= TRUE
406 self
.hide_grid
= TRUE
408 # determine the calendar rectangle click area and draw a selection
410 def ProcessClick(self
, event
):
411 self
.x
, self
.y
= event
.GetX(), event
.GetY()
412 key
= self
.GetDayHit(self
.x
, self
.y
)
415 # tab mouse click events and process
417 def OnLeftEvent(self
, event
):
419 self
.ProcessClick(event
)
421 def OnLeftDEvent(self
, event
):
423 self
.ProcessClick(event
)
425 def OnRightEvent(self
, event
):
427 self
.ProcessClick(event
)
429 def OnRightDEvent(self
, event
):
430 self
.click
= 'DRIGHT'
431 self
.ProcessClick(event
)
433 def SetSize(self
, set_size
):
436 def SetSelDay(self
, sel
):
437 self
.sel_lst
= sel
# list of highlighted days
439 # get the current date
443 self
.month
= dt
.month
447 # set the current day
449 def SetCurrentDay(self
):
451 self
.set_day
= self
.day
453 # get the date, day, month, year set in calendar
456 return self
.day
, self
.month
, self
.year
467 # set the day, month, and year
469 def SetDayValue(self
, day
):
472 def SetMonth(self
, month
):
473 if month
>= 1 and month
<= 12:
479 def SetYear(self
, year
):
482 # increment year and month
485 self
.year
= self
.year
+ 1
489 self
.year
= self
.year
- 1
493 self
.month
= self
.month
+ 1
496 self
.year
= self
.year
+ 1
500 self
.month
= self
.month
- 1
503 self
.year
= self
.year
- 1
506 # test to see if the selection has a date and create event
508 def TestDay(self
, key
):
510 self
.day
= int(self
.cal
[key
])
516 evt
= wxPyCommandEvent(2100, self
.GetId())
517 evt
.click
, evt
.day
, evt
.month
, evt
.year
= self
.click
, self
.day
, self
.month
, self
.year
518 self
.GetEventHandler().ProcessEvent(evt
)
520 self
.set_day
= self
.day
523 # find the clicked area rectangle
525 def GetDayHit(self
, mx
, my
):
526 for key
in self
.rg
.keys():
528 ms_rect
= wxRect(mx
, my
, 1, 1)
529 if wxIntersectRect(ms_rect
, val
) is not None:
530 result
= self
.TestDay(key
)
536 def SetWeekColor(self
, font_color
, week_color
): # set font and background color for week title
537 self
.week_font_color
= font_color
538 self
.week_color
= week_color
540 def AddSelect(self
, list, font_color
, back_color
):
541 list_val
= [list, font_color
, back_color
]
542 self
.select_list
.append(list_val
)
544 def ShowWeekEnd(self
):
545 self
.show_weekend
= TRUE
# highlight weekend
547 def SetBusType(self
):
548 self
.cal_type
= "BUS"
550 def OnPaint(self
, event
):
554 def DoDrawing(self
, DC
):
558 self
.cal
= cal
= CalDraw(self
)
560 cal
.grid_color
= self
.grid_color
561 cal
.back_color
= self
.back_color
562 cal
.hide_grid
= self
.hide_grid
563 cal
.grid_color
= self
.grid_color
564 cal
.hide_title
= self
.hide_title
565 cal
.show_weekend
= self
.show_weekend
566 cal
.cal_type
= self
.cal_type
568 if self
.size
is None:
569 size
= self
.GetClientSize()
575 cal
.week_font_color
= self
.week_font_color
576 cal
.week_color
= self
.week_color
579 cal
.SetCal(self
.year
, self
.month
)
580 for val
in self
.select_list
:
581 cal
.AddSelect(val
[0], val
[1], val
[2])
583 cal
.DrawCal(DC
, self
.sel_lst
)
585 self
.rg
= cal
.GetRect()
586 self
.cal
= cal
.GetCal()
587 self
.st_pos
= cal
.GetOffset()
588 self
.ymax
= DC
.MaxY()
590 if self
.set_day
!= None:
591 self
.SetDay(self
.set_day
)
594 # draw the selection rectangle
596 def DrawRect(self
, key
, color
= 'BLACK', width
= 0):
599 DC
= wxClientDC(self
)
602 brush
= wxBrush(wxColour(0, 0xFF, 0x80), wxTRANSPARENT
)
604 DC
.SetPen(wxPen(wxNamedColour(color
), width
))
607 DC
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
+1, rect
.height
+1)
611 # set the day selection
613 def SetDay(self
, day
):
614 day
= day
+ self
.st_pos
- 1
617 def SelectDay(self
, key
):
619 self
.DrawRect(self
.sel_key
, self
.back_color
, sel_size
) # clear large selection
620 if self
.hide_grid
is FALSE
:
621 self
.DrawRect(self
.sel_key
, self
.grid_color
)
623 self
.DrawRect(key
, self
.sel_color
, sel_size
)
624 self
.sel_key
= key
# store last used by
625 self
.select_day
= None