]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/calendar.py
Updated version number
[wxWidgets.git] / wxPython / wx / lib / calendar.py
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 #----------------------------------------------------------------------------
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 #
36 # 12/17/2003 - Jeff Grimmett (grimmtooth@softhome.net)
37 #
38 # o A few style-guide nips and tucks
39 # o Renamed wxCalendar to Calendar
40 # o Couple of bugfixes
41 #
42 # 06/02/2004 - Joerg "Adi" Sieker adi@sieker.info
43 #
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.
61
62 import wx
63
64 from CDate import *
65
66 CalDays = [6, 0, 1, 2, 3, 4, 5]
67 AbrWeekday = {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"}
68 _MIDSIZE = 180
69
70 COLOR_GRID_LINES = "grid_lines"
71 COLOR_BACKGROUND = "background"
72 COLOR_SELECTION_FONT = "selection_font"
73 COLOR_SELECTION_BACKGROUND = "selection_background"
74 COLOR_BORDER = "border"
75 COLOR_HEADER_BACKGROUND = "header_background"
76 COLOR_HEADER_FONT = "header_font"
77 COLOR_WEEKEND_BACKGROUND = "weekend_background"
78 COLOR_WEEKEND_FONT = "weekend_font"
79 COLOR_FONT = "font"
80 COLOR_3D_LIGHT = "3d_light"
81 COLOR_3D_DARK = "3d_dark"
82 COLOR_HIGHLIGHT_FONT = "highlight_font"
83 COLOR_HIGHLIGHT_BACKGROUND = "highlight_background"
84
85 BusCalDays = [0, 1, 2, 3, 4, 5, 6]
86
87 # Calendar click event - added 12/1/03 by jmg (see above)
88 wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED = wx.NewEventType()
89 EVT_CALENDAR = wx.PyEventBinder(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED, 1)
90
91 def GetMonthList():
92 monthlist = []
93 for i in range(13):
94 name = Month[i]
95 if name != None:
96 monthlist.append(name)
97 return monthlist
98
99 def MakeColor(in_color):
100 try:
101 color = wxNamedColour(in_color)
102 except:
103 color = in_color
104 return color
105
106 def DefaultColors():
107 colors = {}
108 colors[COLOR_GRID_LINES] = 'BLACK'
109 colors[COLOR_BACKGROUND] = 'WHITE'
110 colors[COLOR_SELECTION_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
111 colors[COLOR_SELECTION_BACKGROUND] =wx.Colour(255,255,225)
112 colors[COLOR_BORDER] = 'BLACK'
113 colors[COLOR_HEADER_BACKGROUND] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
114 colors[COLOR_HEADER_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
115 colors[COLOR_WEEKEND_BACKGROUND] = 'LIGHT GREY'
116 colors[COLOR_WEEKEND_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
117 colors[COLOR_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
118 colors[COLOR_3D_LIGHT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNHIGHLIGHT)
119 colors[COLOR_3D_DARK] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
120 colors[COLOR_HIGHLIGHT_FONT] = 'PINK'
121 colors[COLOR_HIGHLIGHT_BACKGROUND] = 'RED'
122 return colors
123 # calendar drawing routing
124
125 class CalDraw:
126 def __init__(self, parent):
127 self.pwidth = 1
128 self.pheight = 1
129 try:
130 self.scale = parent.scale
131 except:
132 self.scale = 1
133
134 self.gridx = []
135 self.gridy = []
136
137 self.DefParms()
138
139 def DefParms(self):
140 self.num_auto = True # auto scale of the cal number day size
141 self.num_size = 12 # default size of calendar if no auto size
142 self.max_num_size = 12 # maximum size for calendar number
143
144 self.num_align_horz = wx.ALIGN_CENTRE # alignment of numbers
145 self.num_align_vert = wx.ALIGN_CENTRE
146 self.num_indent_horz = 0 # points indent from position, used to offset if not centered
147 self.num_indent_vert = 0
148
149 self.week_auto = True # auto scale of week font text
150 self.week_size = 10
151 self.max_week_size = 12
152
153 self.colors = DefaultColors()
154
155 self.font = wx.SWISS
156 self.bold = wx.NORMAL
157
158 self.hide_title = False
159 self.hide_grid = False
160 self.outer_border = True
161
162 self.title_offset = 0
163 self.cal_week_scale = 0.7
164 self.show_weekend = False
165 self.cal_type = "NORMAL"
166
167 def SetWeekColor(self, font_color, week_color):
168 # set font and background color for week title
169 self.colors[COLOR_HEADER_FONT] = MakeColor(font_color)
170 self.colors[COLOR_HEADER_BACKGROUND] = MakeColor(week_color)
171 self.colors[COLOR_3D_LIGHT] = MakeColor(week_color)
172 self.colors[COLOR_3D_DARK] = MakeColor(week_color)
173
174 def SetSize(self, size):
175 self.set_sizew = size[0]
176 self.set_sizeh = size[1]
177
178 def InitValues(self): # default dimensions of various elements of the calendar
179 self.rg = {}
180 self.cal_sel = {}
181 self.set_cy_st = 0 # start position
182 self.set_cx_st = 0
183
184 self.set_y_mrg = 1 # start of vertical draw default
185 self.set_x_mrg = 1
186 self.set_y_end = 1
187 def SetPos(self, xpos, ypos):
188 self.set_cx_st = xpos
189 self.set_cy_st = ypos
190
191 def SetMarg(self, xmarg, ymarg):
192 self.set_x_mrg = xmarg
193 self.set_y_mrg = ymarg
194 self.set_y_end = ymarg
195
196 def InitScale(self): # scale position values
197 self.sizew = int(self.set_sizew * self.pwidth)
198 self.sizeh = int(self.set_sizeh * self.pheight)
199
200 self.cx_st = int(self.set_cx_st * self.pwidth) # draw start position
201 self.cy_st = int(self.set_cy_st * self.pheight)
202
203 self.x_mrg = int(self.set_x_mrg * self.pwidth) # calendar draw margins
204 self.y_mrg = int(self.set_y_mrg * self.pheight)
205 self.y_end = int(self.set_y_end * self.pheight)
206
207 def DrawCal(self, DC, sel_lst=[]):
208 self.InitScale()
209
210 self.DrawBorder(DC)
211
212 if self.hide_title is False:
213 self.DrawMonth(DC)
214
215 self.Center()
216
217 self.DrawGrid(DC)
218 self.GetRect()
219 if self.show_weekend is True: # highlight weekend dates
220 self.SetWeekEnd()
221
222 self.AddSelect(sel_lst) # overrides the weekend highlight
223
224 self.DrawSel(DC) # highlighted days
225 self.DrawWeek(DC)
226 self.DrawNum(DC)
227
228 def AddSelect(self, list, cfont=None, cbackgrd = None):
229 if cfont is None:
230 cfont = self.colors[COLOR_SELECTION_FONT] # font digit color
231 if cbackgrd is None:
232 cbackgrd = self.colors[COLOR_SELECTION_BACKGROUND] # select background color
233
234 for val in list:
235 self.cal_sel[val] = (cfont, cbackgrd)
236
237 # draw border around the outside of the main display rectangle
238 def DrawBorder(self, DC):
239 brush = wx.Brush(MakeColor(self.colors[COLOR_BACKGROUND]), wx.SOLID)
240 DC.SetBrush(brush)
241 DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_BORDER]), 1))
242 if self.outer_border is True:
243 # full display window area
244 rect = wx.Rect(self.cx_st, self.cy_st, self.sizew, self.sizeh)
245 DC.DrawRectangleRect(rect)
246
247 def DrawNumVal(self):
248 self.DrawNum()
249
250 # calculate the calendar days and offset position
251 def SetCal(self, year, month):
252 self.InitValues() # reset initial values
253
254 self.year = year
255 self.month = month
256
257 day = 1
258 t = Date(year, month, day)
259 dow = self.dow = t.day_of_week # start day in month
260 dim = self.dim = t.days_in_month # number of days in month
261
262 if self.cal_type == "NORMAL":
263 start_pos = dow+1
264 else:
265 start_pos = dow
266
267 self.st_pos = start_pos
268
269 self.cal_days = []
270 for i in range(start_pos):
271 self.cal_days.append('')
272
273 i = 1
274 while i <= dim:
275 self.cal_days.append(str(i))
276 i = i + 1
277
278 return start_pos
279
280 def SetWeekEnd(self, font_color=None, backgrd = None):
281 if font_color != None:
282 self.SetColor(COLOR_WEEKEND_FONT, MakeColor(font_color))
283 if backgrd != None:
284 self.SetColor(COLOR_WEEKEND_BACKGROUND, MakeColor(backgrd))
285
286 date = 6 - int(self.dow) # start day of first saturday
287
288 while date <= self.dim:
289 self.cal_sel[date] = (self.GetColor(COLOR_WEEKEND_FONT), self.GetColor(COLOR_WEEKEND_BACKGROUND)) # Saturday
290 date = date + 1
291
292 if date <= self.dim:
293 self.cal_sel[date] = (self.GetColor(COLOR_WEEKEND_FONT), self.GetColor(COLOR_WEEKEND_BACKGROUND)) # Sunday
294 date = date + 6
295 else:
296 date = date + 7
297
298 # get the display rectange list of the day grid
299 def GetRect(self):
300 cnt = 0
301 for y in self.gridy[1:-1]:
302 if y == self.gridy[-2]:
303 h = h + self.restH
304
305 for x in self.gridx[:-1]:
306 assert type(y) == int
307 assert type(x) == int
308
309 w = self.cellW
310 h = self.cellH
311
312 if x == self.gridx[-2]:
313 w = w + self.restW
314
315 rect = wx.Rect(x, y, w+1, h+1) # create rect region
316
317 self.rg[cnt] = rect
318 cnt = cnt + 1
319
320 return self.rg
321
322 def GetCal(self):
323 return self.cal_days
324
325 def GetOffset(self):
326 return self.st_pos
327
328 # month and year title
329 def DrawMonth(self, DC):
330 month = Month[self.month]
331
332 sizef = 11
333 if self.sizeh < _MIDSIZE:
334 sizef = 10
335
336 f = wx.Font(sizef, self.font, wx.NORMAL, self.bold)
337 DC.SetFont(f)
338
339 tw,th = DC.GetTextExtent(month)
340 adjust = self.cx_st + (self.sizew-tw)/2
341 DC.DrawText(month, (adjust, self.cy_st + th))
342
343 year = str(self.year)
344 tw,th = DC.GetTextExtent(year)
345 adjust = self.sizew - tw - self.x_mrg
346
347 self.title_offset = th * 2
348
349 f = wx.Font(sizef, self.font, wx.NORMAL, self.bold)
350 DC.SetFont(f)
351 DC.DrawText(year, (self.cx_st + adjust, self.cy_st + th))
352
353 def DrawWeek(self, DC): # draw the week days
354 # increase by 1 to include all gridlines
355 width = self.gridx[1] - self.gridx[0] + 1
356 height = self.gridy[1] - self.gridy[0] + 1
357 rect_w = self.gridx[-1] - self.gridx[0]
358
359 f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting
360
361 if self.week_auto == True:
362 test_size = self.max_week_size # max size
363 test_day = ' Sun '
364 while test_size > 2:
365 f.SetPointSize(test_size)
366 DC.SetFont(f)
367 tw,th = DC.GetTextExtent(test_day)
368
369 if tw < width and th < height:
370 break
371
372 test_size = test_size - 1
373 else:
374 f.SetPointSize(self.week_size) # set fixed size
375 DC.SetFont(f)
376
377 DC.SetTextForeground(MakeColor(self.colors[COLOR_HEADER_FONT]))
378
379 cnt_x = 0
380 cnt_y = 0
381
382 brush = wx.Brush(MakeColor(self.colors[COLOR_HEADER_BACKGROUND]), wx.SOLID)
383 DC.SetBrush(brush)
384
385 if self.cal_type == "NORMAL":
386 cal_days = CalDays
387 else:
388 cal_days = BusCalDays
389
390 for val in cal_days:
391 if val == cal_days[-1]:
392 width = width + self.restW
393
394 day = AbrWeekday[val]
395
396 if self.sizew < 200:
397 day = day[0]
398
399 dw,dh = DC.GetTextExtent(day)
400
401 diffx = (width-dw)/2
402 diffy = (height-dh)/2
403
404 x = self.gridx[cnt_x]
405 y = self.gridy[cnt_y]
406 pointXY = (x, y)
407 pointWH = (width, height)
408 if self.hide_grid == False:
409 pen = wx.Pen(MakeColor(self.GetColor(COLOR_GRID_LINES)), 1, wx.SOLID)
410 else:
411 pen = wx.Pen(MakeColor(self.GetColor(COLOR_BACKGROUND)), 1, wx.SOLID)
412 DC.SetPen(pen)
413 DC.DrawRectangle( pointXY, pointWH)
414
415 old_pen = DC.GetPen()
416
417 pen = wx.Pen(MakeColor(self.colors[COLOR_3D_LIGHT]), 1, wx.SOLID)
418 DC.SetPen(pen)
419 # draw the horizontal hilight
420 startPoint = wx.Point(x + 1 , y + 1)
421 endPoint = wx.Point(x + width - 1, y + 1)
422 DC.DrawLine(startPoint, endPoint )
423
424 # draw the vertical hilight
425 startPoint = wx.Point(x + 1 , y + 1)
426 endPoint = wx.Point(x + 1, y + height - 2)
427 DC.DrawLine(startPoint, endPoint )
428
429 pen = wx.Pen(MakeColor(self.colors[COLOR_3D_DARK]), 1, wx.SOLID)
430 DC.SetPen(pen)
431
432 # draw the horizontal lowlight
433 startPoint = wx.Point(x + 1, y + height - 2)
434 endPoint = wx.Point(x + width - 1, y + height - 2)
435 DC.DrawLine(startPoint, endPoint )
436
437 # draw the vertical lowlight
438 startPoint = wx.Point(x + width - 2 , y + 2)
439 endPoint = wx.Point(x + width - 2, y + height - 2)
440 DC.DrawLine(startPoint, endPoint )
441
442 pen = wx.Pen(MakeColor(self.colors[COLOR_FONT]), 1, wx.SOLID)
443
444 DC.SetPen(pen)
445
446 point = (x+diffx, y+diffy)
447 DC.DrawText(day, point)
448 cnt_x = cnt_x + 1
449
450 # draw the day numbers
451 def DrawNum(self, DC):
452 f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting
453
454 if self.num_auto == True:
455 test_size = self.max_num_size # max size
456 test_day = ' 99 '
457
458 while test_size > 2:
459 f.SetPointSize(test_size)
460 DC.SetFont(f)
461 tw,th = DC.GetTextExtent(test_day)
462
463 if tw < self.cellW and th < self.cellH:
464 sizef = test_size
465 break
466 test_size = test_size - 1
467 else:
468 f.SetPointSize(self.num_size) # set fixed size
469 DC.SetFont(f)
470
471 cnt_x = 0
472 cnt_y = 1
473 for val in self.cal_days:
474 x = self.gridx[cnt_x]
475 y = self.gridy[cnt_y]
476
477 self.DrawDayText(x, y, val, f, DC)
478
479 if cnt_x < 6:
480 cnt_x = cnt_x + 1
481 else:
482 cnt_x = 0
483 cnt_y = cnt_y + 1
484
485 def DrawDayText(self, x, y, text, font, DC):
486 try:
487 num_val = int(text)
488 num_color = self.cal_sel[num_val][0]
489 except:
490 num_color = self.colors[COLOR_FONT]
491
492 DC.SetTextForeground(MakeColor(num_color))
493 DC.SetFont(font)
494
495 tw,th = DC.GetTextExtent(text)
496
497 if self.num_align_horz == wx.ALIGN_CENTRE:
498 adj_h = (self.cellW - tw)/2
499 elif self.num_align_horz == wx.ALIGN_RIGHT:
500 adj_h = self.cellW - tw
501 else:
502 adj_h = 0 # left alignment
503
504 adj_h = adj_h + self.num_indent_horz
505
506 if self.num_align_vert == wx.ALIGN_CENTRE:
507 adj_v = (self.cellH - th)/2
508 elif self.num_align_vert == wx.ALIGN_BOTTOM:
509 adj_v = self.cellH - th
510 else:
511 adj_v = 0 # left alignment
512
513 adj_v = adj_v + self.num_indent_vert
514
515 DC.DrawText(text, (x+adj_h, y+adj_v))
516
517 # calculate the dimensions in the center of the drawing area
518 def Center(self):
519 borderW = self.x_mrg * 2
520 borderH = self.y_mrg + self.y_end + self.title_offset
521
522 self.cellW = int((self.sizew-borderW)/7)
523 self.cellH = int((self.sizeh-borderH)/7)
524
525 self.restW = ((self.sizew - borderW)%7 ) - 1
526
527 # week title adjustment
528 self.weekHdrCellH = int(self.cellH*self.cal_week_scale)
529 # recalculate the cell height exkl. the week header and
530 # subtracting the size
531 self.cellH = int((self.sizeh-borderH-self.weekHdrCellH)/6)
532
533 self.restH = ((self.sizeh-borderH-self.weekHdrCellH)%6 ) - 1
534 self.calW = self.cellW * 7
535 self.calH = self.cellH * 6 + self.weekHdrCellH
536
537 # highlighted selected days
538 def DrawSel(self, DC):
539
540 for key in self.cal_sel.keys():
541 sel_color = self.cal_sel[key][1]
542 brush = wx.Brush(MakeColor(sel_color), wx.SOLID)
543 DC.SetBrush(brush)
544
545 if self.hide_grid is False:
546 DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_GRID_LINES]), 0))
547 else:
548 DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_BACKGROUND]), 0))
549
550 nkey = key + self.st_pos -1
551 rect = self.rg[nkey]
552
553 DC.DrawRectangle((rect.x, rect.y), (rect.width, rect.height))
554
555 # calculate and draw the grid lines
556 def DrawGrid(self, DC):
557 DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_GRID_LINES]), 0))
558
559 self.gridx = []
560 self.gridy = []
561
562 self.x_st = self.cx_st + self.x_mrg
563 # start postion of draw
564 self.y_st = self.cy_st + self.y_mrg + self.title_offset
565
566 x1 = self.x_st
567 y1 = self.y_st
568 y2 = y1 + self.calH + self.restH
569
570 for i in range(8):
571 if i == 7:
572 x1 = x1 + self.restW
573
574 if self.hide_grid is False:
575 DC.DrawLine((x1, y1), (x1, y2))
576
577 self.gridx.append(x1)
578
579 x1 = x1 + self.cellW
580
581 x1 = self.x_st
582 y1 = self.y_st
583 x2 = x1 + self.calW + self.restW
584
585 for i in range(8):
586 if i == 7:
587 y1 = y1 + self.restH
588
589 if self.hide_grid is False:
590 DC.DrawLine((x1, y1), (x2, y1))
591
592 self.gridy.append(y1)
593
594 if i == 0:
595 y1 = y1 + self.weekHdrCellH
596 else:
597 y1 = y1 + self.cellH
598
599 def GetColor(self, name):
600 return MakeColor(self.colors[name])
601
602 def SetColor(self, name, value):
603 self.colors[name] = MakeColor(value)
604
605 class PrtCalDraw(CalDraw):
606 def InitValues(self):
607 self.rg = {}
608 self.cal_sel = {}
609 # start draw border location
610 self.set_cx_st = 1.0
611 self.set_cy_st = 1.0
612
613 # draw offset position
614 self.set_y_mrg = 0.2
615 self.set_x_mrg = 0.2
616 self.set_y_end = 0.2
617
618 # calculate the dimensions in the center of the drawing area
619 def SetPSize(self, pwidth, pheight):
620 self.pwidth = int(pwidth)/self.scale
621 self.pheight = int(pheight)/self.scale
622
623 def SetPreview(self, preview):
624 self.preview = preview
625
626 class Calendar(wx.Window):
627 def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize):
628 wx.Window.__init__(self, parent, id, pos, size)
629
630 # set the calendar control attributes
631 self.cal = None
632
633 self.hide_grid = False
634 self.hide_title = False
635 self.show_weekend = False
636 self.cal_type = "NORMAL"
637 self.outer_border = True
638 self.num_align_horz = wx.ALIGN_CENTRE
639 self.num_align_vert = wx.ALIGN_CENTRE
640 self.colors = DefaultColors()
641 self.set_x_mrg = 1
642 self.set_y_mrg = 1
643 self.set_y_end = 1
644
645 self.select_list = []
646
647 self.SetBackgroundColour(MakeColor(self.colors[COLOR_BACKGROUND]))
648 self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftEvent)
649 self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDEvent)
650 self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightEvent)
651 self.Bind(wx.EVT_RIGHT_DCLICK, self.OnRightDEvent)
652
653 self.sel_key = None # last used by
654 self.sel_lst = [] # highlighted selected days
655
656 # default calendar for current month
657 self.SetNow()
658
659 self.size = None
660 self.set_day = None
661
662 self.Bind(wx.EVT_PAINT, self.OnPaint)
663 self.Bind(wx.EVT_SIZE, self.OnSize)
664
665 def GetColor(self, name):
666 return MakeColor(self.colors[name])
667
668 def SetColor(self, name, value):
669 self.colors[name] = MakeColor(value)
670
671 # control some of the main calendar attributes
672
673 def HideTitle(self):
674 self.hide_title = True
675
676 def HideGrid(self):
677 self.hide_grid = True
678
679 # determine the calendar rectangle click area and draw a selection
680
681 def ProcessClick(self, event):
682 self.x, self.y = event.GetX(), event.GetY()
683 key = self.GetDayHit(self.x, self.y)
684 self.SelectDay(key)
685
686 # tab mouse click events and process
687
688 def OnLeftEvent(self, event):
689 self.click = 'LEFT'
690 self.shiftkey = event.ShiftDown()
691 self.ctrlkey = event.ControlDown()
692 self.ProcessClick(event)
693
694 def OnLeftDEvent(self, event):
695 self.click = 'DLEFT'
696 self.ProcessClick(event)
697
698 def OnRightEvent(self, event):
699 self.click = 'RIGHT'
700 self.ProcessClick(event)
701
702 def OnRightDEvent(self, event):
703 self.click = 'DRIGHT'
704 self.ProcessClick(event)
705
706 def SetSize(self, set_size):
707 self.size = set_size
708
709 def SetSelDay(self, sel):
710 # list of highlighted days
711 self.sel_lst = sel
712
713 # get the current date
714 def SetNow(self):
715 dt = now()
716 self.month = dt.month
717 self.year = dt.year
718 self.day = dt.day
719
720 # set the current day
721 def SetCurrentDay(self):
722 self.SetNow()
723 self.set_day = self.day
724
725 # get the date, day, month, year set in calendar
726
727 def GetDate(self):
728 return self.day, self.month, self.year
729
730 def GetDay(self):
731 return self.day
732
733 def GetMonth(self):
734 return self.month
735
736 def GetYear(self):
737 return self.year
738
739 # set the day, month, and year
740
741 def SetDayValue(self, day):
742 self.set_day = day
743
744 def SetMonth(self, month):
745 if month >= 1 and month <= 12:
746 self.month = month
747 else:
748 self.month = 1
749 self.set_day = None
750
751 def SetYear(self, year):
752 self.year = year
753
754 # increment year and month
755
756 def IncYear(self):
757 self.year = self.year + 1
758 self.set_day = None
759
760 def DecYear(self):
761 self.year = self.year - 1
762 self.set_day = None
763
764 def IncMonth(self):
765 self.month = self.month + 1
766 if self.month > 12:
767 self.month = 1
768 self.year = self.year + 1
769 self.set_day = None
770
771 def DecMonth(self):
772 self.month = self.month - 1
773 if self.month < 1:
774 self.month = 12
775 self.year = self.year - 1
776 self.set_day = None
777
778 # test to see if the selection has a date and create event
779
780 def TestDay(self, key):
781 try:
782 self.day = int(self.cal_days[key])
783 except:
784 return None
785
786 if self.day == "":
787 return None
788 else:
789 # Changed 12/1/03 by jmg (see above) to support 2.5 event binding
790 evt = wx.PyCommandEvent(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED, self.GetId())
791 evt.click, evt.day, evt.month, evt.year = self.click, self.day, self.month, self.year
792 evt.shiftkey = self.shiftkey
793 evt.ctrlkey = self.ctrlkey
794 self.GetEventHandler().ProcessEvent(evt)
795
796 self.set_day = self.day
797 return key
798
799 # find the clicked area rectangle
800
801 def GetDayHit(self, mx, my):
802 for key in self.rg.keys():
803 val = self.rg[key]
804 ms_rect = wx.Rect(mx, my, 1, 1)
805 if wx.IntersectRect(ms_rect, val) is not None:
806 result = self.TestDay(key)
807 return result
808
809 return None
810
811 # calendar drawing
812
813 def SetWeekColor(self, font_color, week_color):
814 # set font and background color for week title
815 self.colors[COLOR_HEADER_FONT] = MakeColor(font_color)
816 self.colors[COLOR_HEADER_BACKGROUND] = MakeColor(week_color)
817 self.colors[COLOR_3D_LIGHT] = MakeColor(week_color)
818 self.colors[COLOR_3D_DARK] = MakeColor(week_color)
819
820 def SetTextAlign(self, vert, horz):
821 self.num_align_horz = horz
822 self.num_align_vert = vert
823
824 def AddSelect(self, list, font_color, back_color):
825 list_val = [list, font_color, back_color]
826 self.select_list.append(list_val)
827
828 def ShowWeekEnd(self):
829 # highlight weekend
830 self.show_weekend = True
831
832 def SetBusType(self):
833 self.cal_type = "BUS"
834
835 def OnSize(self, evt):
836 self.Refresh(False)
837 evt.Skip()
838
839 def OnPaint(self, event):
840 DC = wx.PaintDC(self)
841 self.DoDrawing(DC)
842
843 def DoDrawing(self, DC):
844 #DC = wx.PaintDC(self)
845 DC.BeginDrawing()
846
847 try:
848 cal = self.caldraw
849 except:
850 self.caldraw = CalDraw(self)
851 cal = self.caldraw
852
853 cal.hide_grid = self.hide_grid
854 cal.hide_title = self.hide_title
855 cal.show_weekend = self.show_weekend
856 cal.cal_type = self.cal_type
857 cal.outer_border = self.outer_border
858 cal.num_align_horz = self.num_align_horz
859 cal.num_align_vert = self.num_align_vert
860 cal.colors = self.colors
861
862 if self.size is None:
863 size = self.GetClientSize()
864 else:
865 size = self.size
866
867 # drawing attributes
868
869 cal.SetSize(size)
870 cal.SetCal(self.year, self.month)
871
872 # these have to set after SetCal as SetCal would overwrite them again.
873 cal.set_x_mrg = self.set_x_mrg
874 cal.set_y_mrg = self.set_y_mrg
875 cal.set_y_end = self.set_y_end
876
877 for val in self.select_list:
878 cal.AddSelect(val[0], val[1], val[2])
879
880 cal.DrawCal(DC, self.sel_lst)
881
882 self.rg = cal.GetRect()
883 self.cal_days = cal.GetCal()
884 self.st_pos = cal.GetOffset()
885 self.ymax = DC.MaxY()
886
887 if self.set_day != None:
888 self.SetDay(self.set_day)
889
890 DC.EndDrawing()
891
892 # draw the selection rectangle
893 def DrawRect(self, key, fgcolor = 'BLACK', width = 0):
894 if key == None:
895 return
896
897 DC = wx.ClientDC(self)
898 DC.BeginDrawing()
899
900 brush = wx.Brush(wx.Colour(0, 0xFF, 0x80), wx.TRANSPARENT)
901 DC.SetBrush(brush)
902
903 try:
904 DC.SetPen(wx.Pen(MakeColor(fgcolor), width))
905 except:
906 DC.SetPen(wx.Pen(MakeColor(self.GetColor(COLOR_GRID_LINES)), width))
907
908 rect = self.rg[key]
909 DC.DrawRectangle((rect.x, rect.y), (rect.width, rect.height))
910
911 DC.EndDrawing()
912
913 # set the day selection
914
915 def SetDay(self, day):
916 day = day + self.st_pos - 1
917 self.SelectDay(day)
918
919 def SelectDay(self, key):
920 sel_size = 1
921 # clear large selection
922 self.DrawRect(self.sel_key, self.GetColor(COLOR_BACKGROUND), sel_size)
923
924 if self.hide_grid is False:
925 self.DrawRect(self.sel_key, self.GetColor(COLOR_GRID_LINES), sel_size)
926
927 self.DrawRect(key, self.GetColor(COLOR_HIGHLIGHT_BACKGROUND), sel_size)
928 # store last used by
929 self.sel_key = key
930 self.select_day = None
931
932 def ClearDsp(self):
933 self.Clear()
934 def SetMargin(self, xmarg, ymarg):
935 self.set_x_mrg = xmarg
936 self.set_y_mrg = ymarg
937 self.set_y_end = ymarg
938
939 class CalenDlg(wx.Dialog):
940 def __init__(self, parent, month=None, day = None, year=None):
941 wx.Dialog.__init__(self, parent, -1, "Event Calendar", wx.DefaultPosition, (280, 360))
942
943 # set the calendar and attributes
944 self.calend = Calendar(self, -1, (20, 60), (240, 200))
945
946 if month == None:
947 self.calend.SetCurrentDay()
948 start_month = self.calend.GetMonth()
949 start_year = self.calend.GetYear()
950 else:
951 self.calend.month = start_month = month
952 self.calend.year = start_year = year
953 self.calend.SetDayValue(day)
954
955 self.calend.HideTitle()
956 self.ResetDisplay()
957
958 # get month list from DateTime
959 monthlist = GetMonthList()
960
961 # select the month
962 self.date = wx.ComboBox(self, -1, Month[start_month], (20, 20), (90, -1),
963 monthlist, wx.CB_DROPDOWN)
964 self.Bind(wx.EVT_COMBOBOX, self.EvtComboBox, self.date)
965
966 # alternate spin button to control the month
967 h = self.date.GetSize().height
968 self.m_spin = wx.SpinButton(self, -1, (130, 20), (h*2, h), wx.SP_VERTICAL)
969 self.m_spin.SetRange(1, 12)
970 self.m_spin.SetValue(start_month)
971 self.Bind(wx.EVT_SPIN, self.OnMonthSpin, self.m_spin)
972
973 # spin button to control the year
974 self.dtext = wx.TextCtrl(self, -1, str(start_year), (160, 20), (60, -1))
975 h = self.dtext.GetSize().height
976
977 self.y_spin = wx.SpinButton(self, -1, (220, 20), (h*2, h), wx.SP_VERTICAL)
978 self.y_spin.SetRange(1980, 2010)
979 self.y_spin.SetValue(start_year)
980
981 self.Bind(wx.EVT_SPIN, self.OnYrSpin, self.y_spin)
982 self.Bind(EVT_CALENDAR, self.MouseClick, self.calend)
983
984 x_pos = 50
985 y_pos = 280
986 but_size = (60, 25)
987
988 btn = wx.Button(self, -1, ' Ok ', (x_pos, y_pos), but_size)
989 self.Bind(wx.EVT_BUTTON, self.OnOk, btn)
990
991 btn = wx.Button(self, -1, ' Close ', (x_pos + 120, y_pos), but_size)
992 self.Bind(wx.EVT_BUTTON, self.OnCancel, btn)
993
994 def OnOk(self, event):
995 self.EndModal(wx.ID_OK)
996
997 def OnCancel(self, event):
998 self.EndModal(wx.ID_CANCEL)
999
1000 # log the mouse clicks
1001 def MouseClick(self, evt):
1002 self.month = evt.month
1003 # result click type and date
1004 self.result = [evt.click, str(evt.day), Month[evt.month], str(evt.year)]
1005
1006 if evt.click == 'DLEFT':
1007 self.EndModal(wx.ID_OK)
1008
1009 # month and year spin selection routines
1010 def OnMonthSpin(self, event):
1011 month = event.GetPosition()
1012 self.date.SetValue(Month[month])
1013 self.calend.SetMonth(month)
1014 self.calend.Refresh()
1015
1016 def OnYrSpin(self, event):
1017 year = event.GetPosition()
1018 self.dtext.SetValue(str(year))
1019 self.calend.SetYear(year)
1020 self.calend.Refresh()
1021
1022 def EvtComboBox(self, event):
1023 name = event.GetString()
1024 monthval = self.date.FindString(name)
1025 self.m_spin.SetValue(monthval+1)
1026
1027 self.calend.SetMonth(monthval+1)
1028 self.ResetDisplay()
1029
1030 # set the calendar for highlighted days
1031
1032 def ResetDisplay(self):
1033 month = self.calend.GetMonth()
1034 self.calend.Refresh()
1035
1036
1037