]>
Commit | Line | Data |
---|---|---|
d14a1e28 RD |
1 | #---------------------------------------------------------------------------- |
2 | # Name: calendar.py | |
3 | # Purpose: Calendar display control | |
4 | # | |
5 | # Author: Lorne White (email: lorne.white@telusplanet.net) | |
6 | # | |
7 | # Created: | |
8 | # Version 0.92 | |
9 | # Date: Nov 26, 2001 | |
10 | # Licence: wxWindows license | |
11 | #---------------------------------------------------------------------------- | |
b881fc78 RD |
12 | # 12/01/2003 - Jeff Grimmett (grimmtooth@softhome.net) |
13 | # | |
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 | |
28 | # demo, I suppose. | |
29 | # | |
30 | # Here's the traceback: | |
31 | # | |
32 | # C:\Python\lib\site-packages\wx\core.py:949: DeprecationWarning: | |
33 | # integer argument expected, got float | |
34 | # newobj = _core.new_Rect(*args, **kwargs) | |
35 | # | |
d14a1e28 | 36 | |
b881fc78 | 37 | import wx |
d14a1e28 RD |
38 | |
39 | from CDate import * | |
40 | ||
d14a1e28 RD |
41 | CalDays = [6, 0, 1, 2, 3, 4, 5] |
42 | AbrWeekday = {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"} | |
43 | _MIDSIZE = 180 | |
44 | ||
45 | BusCalDays = [0, 1, 2, 3, 4, 5, 6] | |
46 | ||
b881fc78 RD |
47 | # Calendar click event - added 12/1/03 by jmg (see above) |
48 | wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED = wx.NewEventType() | |
49 | EVT_CALENDAR = wx.PyEventBinder(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED, 1) | |
d14a1e28 RD |
50 | |
51 | def GetMonthList(): | |
52 | monthlist = [] | |
53 | for i in range(13): | |
54 | name = Month[i] | |
55 | if name != None: | |
56 | monthlist.append(name) | |
57 | return monthlist | |
58 | ||
b881fc78 RD |
59 | # calendar drawing routing |
60 | ||
d14a1e28 RD |
61 | class CalDraw: |
62 | def __init__(self, parent): | |
63 | self.pwidth = 1 | |
64 | self.pheight = 1 | |
65 | try: | |
66 | self.scale = parent.scale | |
67 | except: | |
68 | self.scale = 1 | |
69 | ||
70 | self.DefParms() | |
71 | ||
72 | def DefParms(self): | |
73 | self.num_auto = True # auto scale of the cal number day size | |
74 | self.num_size = 12 # default size of calendar if no auto size | |
75 | self.max_num_size = 12 # maximum size for calendar number | |
76 | ||
b881fc78 RD |
77 | self.num_align_horz = wx.ALIGN_CENTRE # alignment of numbers |
78 | self.num_align_vert = wx.ALIGN_CENTRE | |
d14a1e28 RD |
79 | self.num_indent_horz = 0 # points indent from position, used to offset if not centered |
80 | self.num_indent_vert = 0 | |
81 | ||
82 | self.week_auto = True # auto scale of week font text | |
83 | self.week_size = 10 | |
84 | self.max_week_size = 12 | |
85 | ||
86 | self.grid_color = 'BLACK' # grid and selection colors | |
87 | self.back_color = 'WHITE' | |
88 | self.sel_color = 'RED' | |
89 | ||
90 | self.high_color = 'LIGHT BLUE' | |
91 | self.border_color = 'BLACK' | |
92 | self.week_color = 'LIGHT GREY' | |
93 | ||
94 | self.week_font_color = 'BLACK' # font colors | |
95 | self.day_font_color = 'BLACK' | |
96 | ||
b881fc78 RD |
97 | self.font = wx.SWISS |
98 | self.bold = wx.NORMAL | |
d14a1e28 RD |
99 | |
100 | self.hide_title = False | |
101 | self.hide_grid = False | |
102 | self.outer_border = True | |
103 | ||
104 | self.title_offset = 0 | |
105 | self.cal_week_scale = 0.7 | |
106 | self.show_weekend = False | |
107 | self.cal_type = "NORMAL" | |
108 | ||
109 | def SetWeekColor(self, font_color, week_color): # set font and background color for week title | |
110 | self.week_font_color = font_color | |
111 | self.week_color = week_color | |
112 | ||
113 | def SetSize(self, size): | |
b881fc78 RD |
114 | self.set_sizew = size[0] |
115 | self.set_sizeh = size[1] | |
d14a1e28 RD |
116 | |
117 | def InitValues(self): # default dimensions of various elements of the calendar | |
118 | self.rg = {} | |
119 | self.cal_sel = {} | |
120 | self.set_cy_st = 0 # start position | |
121 | self.set_cx_st = 0 | |
122 | ||
123 | self.set_y_mrg = 15 # start of vertical draw default | |
124 | self.set_x_mrg = 10 | |
125 | self.set_y_end = 10 | |
126 | ||
127 | def SetPos(self, xpos, ypos): | |
128 | self.set_cx_st = xpos | |
129 | self.set_cy_st = ypos | |
130 | ||
131 | def SetMarg(self, xmarg, ymarg): | |
132 | self.set_x_st = xmarg | |
133 | self.set_y_st = ymarg | |
134 | self.set_y_end = ymarg | |
135 | ||
136 | def InitScale(self): # scale position values | |
137 | self.sizew = self.set_sizew * self.pwidth | |
138 | self.sizeh = self.set_sizeh * self.pheight | |
139 | ||
140 | self.cx_st = self.set_cx_st * self.pwidth # draw start position | |
141 | self.cy_st = self.set_cy_st * self.pheight | |
142 | ||
143 | self.x_mrg = self.set_x_mrg * self.pwidth # calendar draw margins | |
144 | self.y_mrg = self.set_y_mrg * self.pheight | |
145 | self.y_end = self.set_y_end * self.pheight | |
146 | ||
147 | def DrawCal(self, DC, sel_lst=[]): | |
148 | self.DC = DC | |
149 | self.InitScale() | |
150 | ||
151 | self.DrawBorder() | |
b881fc78 | 152 | |
d14a1e28 RD |
153 | if self.hide_title is False: |
154 | self.DrawMonth() | |
155 | ||
156 | self.Center() | |
157 | ||
158 | self.DrawGrid() | |
159 | self.GetRect() | |
160 | ||
161 | if self.show_weekend is True: # highlight weekend dates | |
162 | self.SetWeekEnd() | |
163 | ||
164 | self.AddSelect(sel_lst) # overrides the weekend highlight | |
165 | ||
166 | self.DrawSel() # highlighted days | |
167 | self.DrawWeek() | |
168 | self.DrawNum() | |
169 | ||
170 | def AddSelect(self, list, cfont=None, cbackgrd = None): | |
171 | if cfont is None: | |
172 | cfont = self.sel_color # font digit color | |
b881fc78 | 173 | |
d14a1e28 RD |
174 | if cbackgrd is None: |
175 | cbackgrd = self.high_color # select background color | |
176 | ||
177 | for val in list: | |
178 | self.cal_sel[val] = (cfont, cbackgrd) | |
179 | ||
b881fc78 RD |
180 | # draw border around the outside of the main display rectangle |
181 | def DrawBorder(self): | |
182 | brush = wx.Brush(wx.NamedColour(self.back_color), wx.SOLID) | |
d14a1e28 | 183 | self.DC.SetBrush(brush) |
b881fc78 | 184 | self.DC.SetPen(wx.Pen(wx.NamedColour(self.border_color), 1)) |
d14a1e28 RD |
185 | |
186 | if self.outer_border is True: | |
b881fc78 RD |
187 | # full display window area |
188 | rect = wx.Rect(self.cx_st, self.cy_st, self.sizew, self.sizeh) | |
fd3f2efe | 189 | self.DC.DrawRectangleRect(rect) |
d14a1e28 RD |
190 | |
191 | def DrawNumVal(self): | |
192 | self.DrawNum() | |
193 | ||
194 | # calculate the calendar days and offset position | |
195 | ||
196 | def SetCal(self, year, month): | |
197 | self.InitValues() # reset initial values | |
198 | ||
199 | self.year = year | |
200 | self.month = month | |
201 | ||
202 | day = 1 | |
203 | t = Date(year, month, day) | |
204 | dow = self.dow = t.day_of_week # start day in month | |
205 | dim = self.dim = t.days_in_month # number of days in month | |
b881fc78 | 206 | |
d14a1e28 RD |
207 | if self.cal_type == "NORMAL": |
208 | start_pos = dow+1 | |
209 | else: | |
210 | start_pos = dow | |
211 | ||
212 | self.st_pos = start_pos | |
213 | ||
214 | self.cal = [] | |
215 | for i in range(start_pos): | |
216 | self.cal.append('') | |
b881fc78 | 217 | |
d14a1e28 RD |
218 | i = 1 |
219 | while i <= dim: | |
220 | self.cal.append(str(i)) | |
221 | i = i + 1 | |
b881fc78 | 222 | |
d14a1e28 RD |
223 | return start_pos |
224 | ||
225 | def SetWeekEnd(self, font_color='BLACK', backgrd = 'LIGHT GREY'): | |
226 | date = 6 - int(self.dow) # start day of first saturday | |
b881fc78 | 227 | |
d14a1e28 RD |
228 | while date <= self.dim: |
229 | self.cal_sel[date] = (font_color, backgrd) # Saturday | |
230 | date = date + 1 | |
b881fc78 | 231 | |
d14a1e28 RD |
232 | if date <= self.dim: |
233 | self.cal_sel[date] = (font_color, backgrd) # Sunday | |
234 | date = date + 6 | |
235 | else: | |
236 | date = date + 7 | |
237 | ||
238 | def GetRect(self): # get the display rectange list of the day grid | |
239 | cnt = 0 | |
240 | for y in self.gridy[1:-1]: | |
241 | for x in self.gridx[:-1]: | |
b881fc78 | 242 | rect = wx.Rect(x, y, self.dl_w, self.dl_h) # create rect region |
d14a1e28 RD |
243 | self.rg[cnt] = rect |
244 | cnt = cnt + 1 | |
b881fc78 | 245 | |
d14a1e28 RD |
246 | return self.rg |
247 | ||
248 | def GetCal(self): | |
249 | return self.cal | |
250 | ||
251 | def GetOffset(self): | |
252 | return self.st_pos | |
253 | ||
254 | def DrawMonth(self): # month and year title | |
255 | month = Month[self.month] | |
256 | ||
257 | sizef = 11 | |
258 | if self.sizeh < _MIDSIZE: | |
259 | sizef = 10 | |
260 | ||
b881fc78 | 261 | f = wx.Font(sizef, self.font, wx.NORMAL, self.bold) |
d14a1e28 RD |
262 | self.DC.SetFont(f) |
263 | ||
264 | tw,th = self.DC.GetTextExtent(month) | |
265 | adjust = self.cx_st + (self.sizew-tw)/2 | |
fd3f2efe | 266 | self.DC.DrawText(month, (adjust, self.cy_st + th)) |
d14a1e28 RD |
267 | |
268 | year = str(self.year) | |
269 | tw,th = self.DC.GetTextExtent(year) | |
270 | adjust = self.sizew - tw - self.x_mrg | |
271 | ||
272 | self.title_offset = th * 2 | |
273 | ||
b881fc78 | 274 | f = wx.Font(sizef, self.font, wx.NORMAL, self.bold) |
d14a1e28 | 275 | self.DC.SetFont(f) |
fd3f2efe | 276 | self.DC.DrawText(year, (self.cx_st + adjust, self.cy_st + th)) |
d14a1e28 RD |
277 | |
278 | def DrawWeek(self): # draw the week days | |
279 | width = self.gridx[1]-self.gridx[0] | |
280 | height = self.gridy[1] - self.gridy[0] | |
281 | rect_w = self.gridx[7]-self.gridx[0] | |
282 | ||
b881fc78 RD |
283 | f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting |
284 | ||
d14a1e28 RD |
285 | if self.week_auto == True: |
286 | test_size = self.max_week_size # max size | |
287 | test_day = ' Sun ' | |
288 | while test_size > 2: | |
289 | f.SetPointSize(test_size) | |
290 | self.DC.SetFont(f) | |
291 | tw,th = self.DC.GetTextExtent(test_day) | |
b881fc78 | 292 | |
d14a1e28 RD |
293 | if tw < width and th < height: |
294 | break | |
b881fc78 | 295 | |
d14a1e28 RD |
296 | test_size = test_size - 1 |
297 | else: | |
298 | f.SetPointSize(self.week_size) # set fixed size | |
299 | self.DC.SetFont(f) | |
300 | ||
b881fc78 | 301 | self.DC.SetTextForeground(wx.NamedColour(self.week_font_color)) |
d14a1e28 RD |
302 | |
303 | cnt_x = 0 | |
304 | cnt_y = 0 | |
305 | ||
b881fc78 | 306 | brush = wx.Brush(wx.NamedColour(self.week_color), wx.SOLID) |
d14a1e28 | 307 | self.DC.SetBrush(brush) |
b881fc78 | 308 | self.DC.DrawRectangle((self.gridx[0], self.gridy[0]), (rect_w+1, height)) |
d14a1e28 RD |
309 | |
310 | if self.cal_type == "NORMAL": | |
311 | cal_days = CalDays | |
312 | else: | |
313 | cal_days = BusCalDays | |
314 | ||
315 | for val in cal_days: | |
316 | day = AbrWeekday[val] | |
b881fc78 | 317 | |
d14a1e28 RD |
318 | if self.sizew < 200: |
319 | day = day[0] | |
b881fc78 | 320 | |
d14a1e28 RD |
321 | dw,dh = self.DC.GetTextExtent(day) |
322 | diffx = (width-dw)/2 | |
323 | diffy = (height-dh)/2 | |
324 | ||
325 | x = self.gridx[cnt_x] | |
326 | y = self.gridy[cnt_y] | |
fd3f2efe RD |
327 | self.DC.DrawRectangle((self.gridx[cnt_x], self.gridy[0]), (width+1, height)) |
328 | self.DC.DrawText(day, (x+diffx, y+diffy)) | |
d14a1e28 RD |
329 | cnt_x = cnt_x + 1 |
330 | ||
331 | def DrawNum(self): # draw the day numbers | |
b881fc78 RD |
332 | f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting |
333 | ||
d14a1e28 RD |
334 | if self.num_auto == True: |
335 | test_size = self.max_num_size # max size | |
336 | test_day = ' 99 ' | |
b881fc78 | 337 | |
d14a1e28 RD |
338 | while test_size > 2: |
339 | f.SetPointSize(test_size) | |
340 | self.DC.SetFont(f) | |
341 | tw,th = self.DC.GetTextExtent(test_day) | |
b881fc78 | 342 | |
d14a1e28 RD |
343 | if tw < self.dl_w and th < self.dl_h: |
344 | sizef = test_size | |
345 | break | |
346 | test_size = test_size - 1 | |
347 | else: | |
348 | f.SetPointSize(self.num_size) # set fixed size | |
349 | self.DC.SetFont(f) | |
350 | ||
351 | cnt_x = 0 | |
352 | cnt_y = 1 | |
353 | for val in self.cal: | |
354 | x = self.gridx[cnt_x] | |
355 | y = self.gridy[cnt_y] | |
356 | ||
357 | try: | |
358 | num_val = int(val) | |
359 | num_color = self.cal_sel[num_val][0] | |
360 | except: | |
361 | num_color = self.day_font_color | |
362 | ||
b881fc78 | 363 | self.DC.SetTextForeground(wx.NamedColour(num_color)) |
d14a1e28 RD |
364 | self.DC.SetFont(f) |
365 | ||
366 | tw,th = self.DC.GetTextExtent(val) | |
b881fc78 RD |
367 | |
368 | if self.num_align_horz == wx.ALIGN_CENTRE: | |
d14a1e28 | 369 | adj_h = (self.dl_w - tw)/2 |
b881fc78 | 370 | elif self.num_align_horz == wx.ALIGN_RIGHT: |
d14a1e28 RD |
371 | adj_h = self.dl_w - tw |
372 | else: | |
373 | adj_h = 0 # left alignment | |
374 | ||
375 | adj_h = adj_h + self.num_indent_horz | |
376 | ||
b881fc78 | 377 | if self.num_align_vert == wx.ALIGN_CENTRE: |
d14a1e28 | 378 | adj_v = (self.dl_h - th)/2 |
b881fc78 | 379 | elif self.num_align_horz == wx.ALIGN_RIGHT: |
d14a1e28 RD |
380 | adj_v = self.dl_h - th |
381 | else: | |
382 | adj_v = 0 # left alignment | |
383 | ||
384 | adj_v = adj_v + self.num_indent_vert | |
385 | ||
fd3f2efe | 386 | self.DC.DrawText(val, (x+adj_h, y+adj_v)) |
b881fc78 | 387 | |
d14a1e28 RD |
388 | if cnt_x < 6: |
389 | cnt_x = cnt_x + 1 | |
390 | else: | |
391 | cnt_x = 0 | |
392 | cnt_y = cnt_y + 1 | |
393 | ||
394 | def Center(self): # calculate the dimensions in the center of the drawing area | |
395 | bdw = self.x_mrg * 2 | |
396 | bdh = self.y_mrg + self.y_end + self.title_offset | |
397 | ||
398 | self.dl_w = int((self.sizew-bdw)/7) | |
399 | self.dl_h = int((self.sizeh-bdh)/7) | |
400 | ||
401 | self.dl_th = int(self.dl_h*self.cal_week_scale) # week title adjustment | |
402 | self.cwidth = self.dl_w * 7 | |
403 | self.cheight = self.dl_h * 6 + self.dl_th | |
404 | ||
405 | def DrawSel(self): # highlighted selected days | |
406 | for key in self.cal_sel.keys(): | |
407 | sel_color = self.cal_sel[key][1] | |
b881fc78 | 408 | brush = wx.Brush(wx.NamedColour(sel_color), wx.SOLID) |
d14a1e28 RD |
409 | self.DC.SetBrush(brush) |
410 | ||
411 | if self.hide_grid is False: | |
b881fc78 | 412 | self.DC.SetPen(wx.Pen(wx.NamedColour(self.grid_color), 0)) |
d14a1e28 | 413 | else: |
b881fc78 RD |
414 | self.DC.SetPen(wx.Pen(wx.NamedColour(self.back_color), 0)) |
415 | ||
d14a1e28 RD |
416 | nkey = key + self.st_pos -1 |
417 | rect = self.rg[nkey] | |
fd3f2efe | 418 | self.DC.DrawRectangle((rect.x, rect.y), (rect.width+1, rect.height+1)) |
d14a1e28 RD |
419 | |
420 | def DrawGrid(self): # calculate and draw the grid lines | |
b881fc78 | 421 | self.DC.SetPen(wx.Pen(wx.NamedColour(self.grid_color), 0)) |
d14a1e28 RD |
422 | |
423 | self.gridx = [] | |
424 | self.gridy = [] | |
425 | ||
426 | self.x_st = self.cx_st + self.x_mrg | |
427 | self.y_st = self.cy_st + self.y_mrg + self.title_offset # start postion of draw | |
428 | ||
429 | x1 = self.x_st | |
430 | y1 = self.y_st | |
d14a1e28 | 431 | y2 = y1 + self.cheight |
b881fc78 | 432 | |
d14a1e28 RD |
433 | for i in range(8): |
434 | if self.hide_grid is False: | |
fd3f2efe | 435 | self.DC.DrawLine((x1, y1), (x1, y2)) |
d14a1e28 RD |
436 | self.gridx.append(x1) |
437 | x1 = x1 + self.dl_w | |
438 | ||
439 | x1 = self.x_st | |
440 | y1 = self.y_st | |
d14a1e28 | 441 | x2 = x1 + self.cwidth |
b881fc78 | 442 | |
d14a1e28 RD |
443 | for i in range(8): |
444 | if self.hide_grid is False: | |
fd3f2efe | 445 | self.DC.DrawLine((x1, y1), (x2, y1)) |
b881fc78 | 446 | |
d14a1e28 | 447 | self.gridy.append(y1) |
b881fc78 | 448 | |
d14a1e28 RD |
449 | if i == 0: |
450 | y1 = y1 + self.dl_th | |
451 | else: | |
452 | y1 = y1 + self.dl_h | |
453 | ||
454 | ||
455 | class PrtCalDraw(CalDraw): | |
456 | def InitValues(self): | |
457 | self.rg = {} | |
458 | self.cal_sel = {} | |
459 | self.set_cx_st = 1.0 # start draw border location | |
460 | self.set_cy_st = 1.0 | |
461 | ||
462 | self.set_y_mrg = 0.2 # draw offset position | |
463 | self.set_x_mrg = 0.2 | |
464 | self.set_y_end = 0.2 | |
465 | ||
b881fc78 RD |
466 | # calculate the dimensions in the center of the drawing area |
467 | def SetPSize(self, pwidth, pheight): | |
d14a1e28 RD |
468 | self.pwidth = int(pwidth)/self.scale |
469 | self.pheight = int(pheight)/self.scale | |
470 | ||
471 | def SetPreview(self, preview): | |
472 | self.preview = preview | |
473 | ||
b881fc78 RD |
474 | class wxCalendar(wx.Window): |
475 | def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize): | |
476 | wx.Window.__init__(self, parent, id, pos, size) | |
d14a1e28 RD |
477 | |
478 | # set the calendar control attributes | |
479 | ||
480 | self.grid_color = 'BLACK' | |
481 | self.back_color = 'WHITE' | |
482 | self.hide_grid = False | |
483 | self.sel_color = 'RED' | |
484 | self.hide_title = False | |
485 | self.show_weekend = False | |
486 | self.cal_type = "NORMAL" | |
487 | ||
488 | self.week_color = 'LIGHT GREY' | |
489 | self.week_font_color = 'BLACK' # font colors | |
490 | ||
491 | self.select_list = [] | |
492 | ||
b881fc78 RD |
493 | self.SetBackgroundColour(self.back_color) |
494 | self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftEvent) | |
495 | self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDEvent) | |
496 | self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightEvent) | |
497 | self.Bind(wx.EVT_RIGHT_DCLICK, self.OnRightDEvent) | |
d14a1e28 RD |
498 | |
499 | self.sel_key = None # last used by | |
500 | self.sel_lst = [] # highlighted selected days | |
501 | ||
502 | self.SetNow() # default calendar for current month | |
503 | ||
504 | self.size = None | |
505 | self.set_day = None | |
506 | ||
b881fc78 RD |
507 | self.Bind(wx.EVT_PAINT, self.OnPaint) |
508 | self.Bind(wx.EVT_SIZE, self.OnSize) | |
d14a1e28 RD |
509 | |
510 | # control some of the main calendar attributes | |
511 | ||
512 | def HideTitle(self): | |
513 | self.hide_title = True | |
514 | ||
515 | def HideGrid(self): | |
516 | self.hide_grid = True | |
517 | ||
518 | # determine the calendar rectangle click area and draw a selection | |
519 | ||
520 | def ProcessClick(self, event): | |
521 | self.x, self.y = event.GetX(), event.GetY() | |
522 | key = self.GetDayHit(self.x, self.y) | |
523 | self.SelectDay(key) | |
524 | ||
525 | # tab mouse click events and process | |
526 | ||
527 | def OnLeftEvent(self, event): | |
528 | self.click = 'LEFT' | |
529 | self.shiftkey = event.ShiftDown() | |
530 | self.ctrlkey = event.ControlDown() | |
531 | self.ProcessClick(event) | |
532 | ||
533 | def OnLeftDEvent(self, event): | |
534 | self.click = 'DLEFT' | |
535 | self.ProcessClick(event) | |
536 | ||
537 | def OnRightEvent(self, event): | |
538 | self.click = 'RIGHT' | |
539 | self.ProcessClick(event) | |
540 | ||
541 | def OnRightDEvent(self, event): | |
542 | self.click = 'DRIGHT' | |
543 | self.ProcessClick(event) | |
544 | ||
545 | def SetSize(self, set_size): | |
546 | self.size = set_size | |
547 | ||
548 | def SetSelDay(self, sel): | |
549 | self.sel_lst = sel # list of highlighted days | |
550 | ||
551 | # get the current date | |
552 | ||
553 | def SetNow(self): | |
554 | dt = now() | |
555 | self.month = dt.month | |
556 | self.year = dt.year | |
557 | self.day = dt.day | |
558 | ||
559 | # set the current day | |
560 | ||
561 | def SetCurrentDay(self): | |
562 | self.SetNow() | |
563 | self.set_day = self.day | |
564 | ||
565 | # get the date, day, month, year set in calendar | |
566 | ||
567 | def GetDate(self): | |
568 | return self.day, self.month, self.year | |
569 | ||
570 | def GetDay(self): | |
571 | return self.day | |
572 | ||
573 | def GetMonth(self): | |
574 | return self.month | |
575 | ||
576 | def GetYear(self): | |
577 | return self.year | |
578 | ||
579 | # set the day, month, and year | |
580 | ||
581 | def SetDayValue(self, day): | |
582 | self.set_day = day | |
583 | ||
584 | def SetMonth(self, month): | |
585 | if month >= 1 and month <= 12: | |
586 | self.month = month | |
587 | else: | |
588 | self.month = 1 | |
589 | self.set_day = None | |
590 | ||
591 | def SetYear(self, year): | |
592 | self.year = year | |
593 | ||
594 | # increment year and month | |
595 | ||
596 | def IncYear(self): | |
597 | self.year = self.year + 1 | |
598 | self.set_day = None | |
599 | ||
600 | def DecYear(self): | |
601 | self.year = self.year - 1 | |
602 | self.set_day = None | |
603 | ||
604 | def IncMonth(self): | |
605 | self.month = self.month + 1 | |
606 | if self.month > 12: | |
607 | self.month = 1 | |
608 | self.year = self.year + 1 | |
609 | self.set_day = None | |
610 | ||
611 | def DecMonth(self): | |
612 | self.month = self.month - 1 | |
613 | if self.month < 1: | |
614 | self.month = 12 | |
615 | self.year = self.year - 1 | |
616 | self.set_day = None | |
617 | ||
618 | # test to see if the selection has a date and create event | |
619 | ||
620 | def TestDay(self, key): | |
621 | try: | |
622 | self.day = int(self.cal[key]) | |
623 | except: | |
624 | return None | |
625 | if self.day == "": | |
626 | return None | |
627 | else: | |
b881fc78 RD |
628 | # Changed 12/1/03 by jmg (see above) to support 2.5 event binding |
629 | evt = wx.PyCommandEvent(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED, self.GetId()) | |
d14a1e28 RD |
630 | evt.click, evt.day, evt.month, evt.year = self.click, self.day, self.month, self.year |
631 | evt.shiftkey = self.shiftkey | |
632 | evt.ctrlkey = self.ctrlkey | |
633 | self.GetEventHandler().ProcessEvent(evt) | |
634 | ||
635 | self.set_day = self.day | |
636 | return key | |
637 | ||
638 | # find the clicked area rectangle | |
639 | ||
640 | def GetDayHit(self, mx, my): | |
641 | for key in self.rg.keys(): | |
642 | val = self.rg[key] | |
b881fc78 RD |
643 | ms_rect = wx.Rect(mx, my, 1, 1) |
644 | if wx.IntersectRect(ms_rect, val) is not None: | |
d14a1e28 RD |
645 | result = self.TestDay(key) |
646 | return result | |
b881fc78 | 647 | |
d14a1e28 RD |
648 | return None |
649 | ||
650 | # calendar drawing | |
651 | ||
652 | def SetWeekColor(self, font_color, week_color): # set font and background color for week title | |
653 | self.week_font_color = font_color | |
654 | self.week_color = week_color | |
655 | ||
656 | def AddSelect(self, list, font_color, back_color): | |
657 | list_val = [list, font_color, back_color] | |
658 | self.select_list.append(list_val) | |
659 | ||
660 | def ShowWeekEnd(self): | |
661 | self.show_weekend = True # highlight weekend | |
662 | ||
663 | def SetBusType(self): | |
664 | self.cal_type = "BUS" | |
665 | ||
666 | def OnSize(self, evt): | |
667 | self.Refresh(False) | |
668 | evt.Skip() | |
669 | ||
670 | def OnPaint(self, event): | |
b881fc78 | 671 | DC = wx.PaintDC(self) |
d14a1e28 RD |
672 | self.DoDrawing(DC) |
673 | ||
674 | def DoDrawing(self, DC): | |
b881fc78 | 675 | DC = wx.PaintDC(self) |
d14a1e28 RD |
676 | DC.BeginDrawing() |
677 | ||
678 | self.cal = cal = CalDraw(self) | |
679 | ||
680 | cal.grid_color = self.grid_color | |
681 | cal.back_color = self.back_color | |
682 | cal.hide_grid = self.hide_grid | |
683 | cal.grid_color = self.grid_color | |
684 | cal.hide_title = self.hide_title | |
685 | cal.show_weekend = self.show_weekend | |
686 | cal.cal_type = self.cal_type | |
687 | ||
688 | if self.size is None: | |
689 | size = self.GetClientSize() | |
690 | else: | |
691 | size = self.size | |
692 | ||
693 | # drawing attributes | |
694 | ||
695 | cal.week_font_color = self.week_font_color | |
696 | cal.week_color = self.week_color | |
697 | ||
698 | cal.SetSize(size) | |
699 | cal.SetCal(self.year, self.month) | |
b881fc78 | 700 | |
d14a1e28 RD |
701 | for val in self.select_list: |
702 | cal.AddSelect(val[0], val[1], val[2]) | |
703 | ||
704 | cal.DrawCal(DC, self.sel_lst) | |
705 | ||
706 | self.rg = cal.GetRect() | |
707 | self.cal = cal.GetCal() | |
708 | self.st_pos = cal.GetOffset() | |
709 | self.ymax = DC.MaxY() | |
710 | ||
711 | if self.set_day != None: | |
712 | self.SetDay(self.set_day) | |
b881fc78 | 713 | |
d14a1e28 RD |
714 | DC.EndDrawing() |
715 | ||
716 | # draw the selection rectangle | |
717 | ||
718 | def DrawRect(self, key, color = 'BLACK', width = 0): | |
719 | if key == None: | |
720 | return | |
b881fc78 RD |
721 | |
722 | DC = wx.ClientDC(self) | |
d14a1e28 RD |
723 | DC.BeginDrawing() |
724 | ||
b881fc78 | 725 | brush = wx.Brush(wx.Colour(0, 0xFF, 0x80), wx.TRANSPARENT) |
d14a1e28 | 726 | DC.SetBrush(brush) |
b881fc78 | 727 | DC.SetPen(wx.Pen(wx.NamedColour(color), width)) |
d14a1e28 RD |
728 | |
729 | rect = self.rg[key] | |
fd3f2efe | 730 | DC.DrawRectangle((rect.x, rect.y), (rect.width+1, rect.height+1)) |
d14a1e28 RD |
731 | |
732 | DC.EndDrawing() | |
733 | ||
734 | # set the day selection | |
735 | ||
736 | def SetDay(self, day): | |
737 | day = day + self.st_pos - 1 | |
738 | self.SelectDay(day) | |
739 | ||
740 | def SelectDay(self, key): | |
741 | sel_size = 1 | |
742 | self.DrawRect(self.sel_key, self.back_color, sel_size) # clear large selection | |
b881fc78 | 743 | |
d14a1e28 RD |
744 | if self.hide_grid is False: |
745 | self.DrawRect(self.sel_key, self.grid_color) | |
746 | ||
747 | self.DrawRect(key, self.sel_color, sel_size) | |
748 | self.sel_key = key # store last used by | |
749 | self.select_day = None | |
750 | ||
751 | def ClearDsp(self): | |
752 | self.Clear() | |
753 | ||
b881fc78 | 754 | class CalenDlg(wx.Dialog): |
d14a1e28 | 755 | def __init__(self, parent, month=None, day = None, year=None): |
b881fc78 | 756 | wx.Dialog.__init__(self, parent, -1, "Event Calendar", wx.DefaultPosition, (280, 360)) |
d14a1e28 RD |
757 | |
758 | # set the calendar and attributes | |
b881fc78 RD |
759 | self.calend = wxCalendar(self, -1, (20, 60), (240, 200)) |
760 | ||
d14a1e28 RD |
761 | if month == None: |
762 | self.calend.SetCurrentDay() | |
763 | start_month = self.calend.GetMonth() | |
764 | start_year = self.calend.GetYear() | |
765 | else: | |
766 | self.calend.month = start_month = month | |
767 | self.calend.year = start_year = year | |
768 | self.calend.SetDayValue(day) | |
769 | ||
770 | self.calend.HideTitle() | |
771 | self.ResetDisplay() | |
772 | ||
773 | # get month list from DateTime | |
774 | monthlist = GetMonthList() | |
775 | ||
776 | # select the month | |
b881fc78 RD |
777 | self.date = wx.ComboBox(self, -1, Month[start_month], (20, 20), (90, -1), |
778 | monthlist, wx.CB_DROPDOWN) | |
779 | self.Bind(wx.EVT_COMBOBOX, self.EvtComboBox, self.date) | |
d14a1e28 RD |
780 | |
781 | # alternate spin button to control the month | |
d14a1e28 | 782 | h = self.date.GetSize().height |
b881fc78 | 783 | self.m_spin = wx.SpinButton(self, -1, (130, 20), (h*2, h), wx.SP_VERTICAL) |
d14a1e28 RD |
784 | self.m_spin.SetRange(1, 12) |
785 | self.m_spin.SetValue(start_month) | |
b881fc78 | 786 | self.Bind(wx.EVT_SPIN, self.OnMonthSpin, self.m_spin) |
d14a1e28 RD |
787 | |
788 | # spin button to control the year | |
b881fc78 | 789 | self.dtext = wx.TextCtrl(self, -1, str(start_year), (160, 20), (60, -1)) |
d14a1e28 RD |
790 | h = self.dtext.GetSize().height |
791 | ||
b881fc78 | 792 | self.y_spin = wx.SpinButton(self, -1, (220, 20), (h*2, h), wx.SP_VERTICAL) |
d14a1e28 RD |
793 | self.y_spin.SetRange(1980, 2010) |
794 | self.y_spin.SetValue(start_year) | |
795 | ||
b881fc78 RD |
796 | self.Bind(wx.EVT_SPIN, self.OnYrSpin, self.y_spin) |
797 | self.Bind(EVT_CALENDAR, self.MouseClick, self.calend) | |
d14a1e28 RD |
798 | |
799 | x_pos = 50 | |
800 | y_pos = 280 | |
b881fc78 | 801 | but_size = (60, 25) |
d14a1e28 | 802 | |
b881fc78 RD |
803 | btn = wx.Button(self, -1, ' Ok ', (x_pos, y_pos), but_size) |
804 | self.Bind(wx.EVT_BUTTON, self.OnOk, btn) | |
d14a1e28 | 805 | |
b881fc78 RD |
806 | btn = wx.Button(self, mID, ' Close ', (x_pos + 120, y_pos), but_size) |
807 | self.Bind(wx.EVT_BUTTON, self.OnCancel, btn) | |
d14a1e28 RD |
808 | |
809 | def OnOk(self, event): | |
b881fc78 | 810 | self.EndModal(wx.ID_OK) |
d14a1e28 RD |
811 | |
812 | def OnCancel(self, event): | |
b881fc78 | 813 | self.EndModal(wx.ID_CANCEL) |
d14a1e28 RD |
814 | |
815 | # log the mouse clicks | |
816 | def MouseClick(self, evt): | |
817 | self.month = evt.month | |
818 | self.result = [evt.click, str(evt.day), Month[evt.month], str(evt.year)] # result click type and date | |
819 | ||
820 | if evt.click == 'DLEFT': | |
b881fc78 | 821 | self.EndModal(wx.ID_OK) |
d14a1e28 RD |
822 | |
823 | # month and year spin selection routines | |
824 | def OnMonthSpin(self, event): | |
825 | month = event.GetPosition() | |
826 | self.date.SetValue(Month[month]) | |
827 | self.calend.SetMonth(month) | |
828 | self.calend.Refresh() | |
829 | ||
830 | def OnYrSpin(self, event): | |
831 | year = event.GetPosition() | |
832 | self.dtext.SetValue(str(year)) | |
833 | self.calend.SetYear(year) | |
834 | self.calend.Refresh() | |
835 | ||
836 | def EvtComboBox(self, event): | |
837 | name = event.GetString() | |
838 | monthval = self.date.FindString(name) | |
839 | self.m_spin.SetValue(monthval+1) | |
840 | ||
841 | self.calend.SetMonth(monthval+1) | |
842 | self.ResetDisplay() | |
843 | ||
844 | # set the calendar for highlighted days | |
845 | ||
846 | def ResetDisplay(self): | |
847 | month = self.calend.GetMonth() | |
848 | self.calend.Refresh() | |
849 | ||
1fded56b | 850 | |
1fded56b | 851 |