]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/calendar.py
Give BitmapButton its own demo, get rid of ErrorDialogs
[wxWidgets.git] / wxPython / wx / lib / calendar.py
CommitLineData
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#
c1ea08d3
RD
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#
b25cb7db
RD
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
62import wx
d14a1e28
RD
63
64from CDate import *
65
d14a1e28
RD
66CalDays = [6, 0, 1, 2, 3, 4, 5]
67AbrWeekday = {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"}
68_MIDSIZE = 180
69
b25cb7db
RD
70COLOR_GRID_LINES = "grid_lines"
71COLOR_BACKGROUND = "background"
72COLOR_SELECTION_FONT = "selection_font"
73COLOR_SELECTION_BACKGROUND = "selection_background"
74COLOR_BORDER = "border"
75COLOR_HEADER_BACKGROUND = "header_background"
76COLOR_HEADER_FONT = "header_font"
77COLOR_WEEKEND_BACKGROUND = "weekend_background"
78COLOR_WEEKEND_FONT = "weekend_font"
79COLOR_FONT = "font"
80COLOR_3D_LIGHT = "3d_light"
81COLOR_3D_DARK = "3d_dark"
82COLOR_HIGHLIGHT_FONT = "highlight_font"
83COLOR_HIGHLIGHT_BACKGROUND = "highlight_background"
84
d14a1e28
RD
85BusCalDays = [0, 1, 2, 3, 4, 5, 6]
86
b881fc78
RD
87# Calendar click event - added 12/1/03 by jmg (see above)
88wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED = wx.NewEventType()
89EVT_CALENDAR = wx.PyEventBinder(wxEVT_COMMAND_PYCALENDAR_DAY_CLICKED, 1)
d14a1e28
RD
90
91def 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
b25cb7db
RD
99def MakeColor(in_color):
100 try:
101 color = wxNamedColour(in_color)
102 except:
103 color = in_color
104 return color
105
106def 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
b881fc78
RD
123# calendar drawing routing
124
d14a1e28
RD
125class 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
b25cb7db
RD
134 self.gridx = []
135 self.gridy = []
136
d14a1e28
RD
137 self.DefParms()
138
139 def DefParms(self):
c1ea08d3
RD
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
d14a1e28 143
b881fc78
RD
144 self.num_align_horz = wx.ALIGN_CENTRE # alignment of numbers
145 self.num_align_vert = wx.ALIGN_CENTRE
d14a1e28
RD
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
b25cb7db 153 self.colors = DefaultColors()
d14a1e28 154
b881fc78
RD
155 self.font = wx.SWISS
156 self.bold = wx.NORMAL
d14a1e28
RD
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
b25cb7db
RD
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)
d14a1e28
RD
173
174 def SetSize(self, size):
b881fc78
RD
175 self.set_sizew = size[0]
176 self.set_sizeh = size[1]
d14a1e28
RD
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
b25cb7db
RD
184 self.set_y_mrg = 1 # start of vertical draw default
185 self.set_x_mrg = 1
186 self.set_y_end = 1
d14a1e28
RD
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):
b25cb7db
RD
192 self.set_x_mrg = xmarg
193 self.set_y_mrg = ymarg
d14a1e28
RD
194 self.set_y_end = ymarg
195
196 def InitScale(self): # scale position values
c8431295
RD
197 self.sizew = int(self.set_sizew * self.pwidth)
198 self.sizeh = int(self.set_sizeh * self.pheight)
d14a1e28 199
c8431295
RD
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)
d14a1e28 202
c8431295
RD
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)
d14a1e28
RD
206
207 def DrawCal(self, DC, sel_lst=[]):
d14a1e28
RD
208 self.InitScale()
209
b25cb7db 210 self.DrawBorder(DC)
b881fc78 211
d14a1e28 212 if self.hide_title is False:
b25cb7db 213 self.DrawMonth(DC)
d14a1e28
RD
214
215 self.Center()
216
b25cb7db 217 self.DrawGrid(DC)
d14a1e28 218 self.GetRect()
d14a1e28
RD
219 if self.show_weekend is True: # highlight weekend dates
220 self.SetWeekEnd()
221
222 self.AddSelect(sel_lst) # overrides the weekend highlight
223
b25cb7db
RD
224 self.DrawSel(DC) # highlighted days
225 self.DrawWeek(DC)
226 self.DrawNum(DC)
d14a1e28
RD
227
228 def AddSelect(self, list, cfont=None, cbackgrd = None):
229 if cfont is None:
b25cb7db 230 cfont = self.colors[COLOR_SELECTION_FONT] # font digit color
d14a1e28 231 if cbackgrd is None:
b25cb7db 232 cbackgrd = self.colors[COLOR_SELECTION_BACKGROUND] # select background color
d14a1e28
RD
233
234 for val in list:
235 self.cal_sel[val] = (cfont, cbackgrd)
236
b881fc78 237 # draw border around the outside of the main display rectangle
b25cb7db
RD
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))
d14a1e28 242 if self.outer_border is True:
b881fc78
RD
243 # full display window area
244 rect = wx.Rect(self.cx_st, self.cy_st, self.sizew, self.sizeh)
b25cb7db 245 DC.DrawRectangleRect(rect)
d14a1e28
RD
246
247 def DrawNumVal(self):
248 self.DrawNum()
249
c1ea08d3 250 # calculate the calendar days and offset position
d14a1e28
RD
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
b881fc78 261
d14a1e28
RD
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
b25cb7db 269 self.cal_days = []
d14a1e28 270 for i in range(start_pos):
b25cb7db 271 self.cal_days.append('')
b881fc78 272
d14a1e28
RD
273 i = 1
274 while i <= dim:
b25cb7db 275 self.cal_days.append(str(i))
d14a1e28 276 i = i + 1
b881fc78 277
d14a1e28
RD
278 return start_pos
279
b25cb7db
RD
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
d14a1e28 286 date = 6 - int(self.dow) # start day of first saturday
b881fc78 287
d14a1e28 288 while date <= self.dim:
b25cb7db 289 self.cal_sel[date] = (self.GetColor(COLOR_WEEKEND_FONT), self.GetColor(COLOR_WEEKEND_BACKGROUND)) # Saturday
d14a1e28 290 date = date + 1
b881fc78 291
d14a1e28 292 if date <= self.dim:
b25cb7db 293 self.cal_sel[date] = (self.GetColor(COLOR_WEEKEND_FONT), self.GetColor(COLOR_WEEKEND_BACKGROUND)) # Sunday
d14a1e28
RD
294 date = date + 6
295 else:
296 date = date + 7
297
c1ea08d3
RD
298 # get the display rectange list of the day grid
299 def GetRect(self):
d14a1e28
RD
300 cnt = 0
301 for y in self.gridy[1:-1]:
b25cb7db
RD
302 if y == self.gridy[-2]:
303 h = h + self.restH
304
d14a1e28 305 for x in self.gridx[:-1]:
c8431295
RD
306 assert type(y) == int
307 assert type(x) == int
b25cb7db
RD
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
d14a1e28
RD
317 self.rg[cnt] = rect
318 cnt = cnt + 1
b881fc78 319
d14a1e28
RD
320 return self.rg
321
322 def GetCal(self):
b25cb7db 323 return self.cal_days
d14a1e28
RD
324
325 def GetOffset(self):
326 return self.st_pos
327
c1ea08d3 328 # month and year title
b25cb7db 329 def DrawMonth(self, DC):
d14a1e28
RD
330 month = Month[self.month]
331
332 sizef = 11
333 if self.sizeh < _MIDSIZE:
334 sizef = 10
335
b881fc78 336 f = wx.Font(sizef, self.font, wx.NORMAL, self.bold)
b25cb7db 337 DC.SetFont(f)
d14a1e28 338
b25cb7db 339 tw,th = DC.GetTextExtent(month)
d14a1e28 340 adjust = self.cx_st + (self.sizew-tw)/2
b25cb7db 341 DC.DrawText(month, (adjust, self.cy_st + th))
d14a1e28
RD
342
343 year = str(self.year)
b25cb7db 344 tw,th = DC.GetTextExtent(year)
d14a1e28
RD
345 adjust = self.sizew - tw - self.x_mrg
346
347 self.title_offset = th * 2
348
b881fc78 349 f = wx.Font(sizef, self.font, wx.NORMAL, self.bold)
b25cb7db
RD
350 DC.SetFont(f)
351 DC.DrawText(year, (self.cx_st + adjust, self.cy_st + th))
d14a1e28 352
b25cb7db
RD
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]
d14a1e28 358
b881fc78
RD
359 f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting
360
d14a1e28
RD
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)
b25cb7db
RD
366 DC.SetFont(f)
367 tw,th = DC.GetTextExtent(test_day)
b881fc78 368
d14a1e28
RD
369 if tw < width and th < height:
370 break
b881fc78 371
d14a1e28
RD
372 test_size = test_size - 1
373 else:
374 f.SetPointSize(self.week_size) # set fixed size
b25cb7db 375 DC.SetFont(f)
d14a1e28 376
b25cb7db 377 DC.SetTextForeground(MakeColor(self.colors[COLOR_HEADER_FONT]))
d14a1e28
RD
378
379 cnt_x = 0
380 cnt_y = 0
381
b25cb7db
RD
382 brush = wx.Brush(MakeColor(self.colors[COLOR_HEADER_BACKGROUND]), wx.SOLID)
383 DC.SetBrush(brush)
d14a1e28
RD
384
385 if self.cal_type == "NORMAL":
386 cal_days = CalDays
387 else:
388 cal_days = BusCalDays
389
390 for val in cal_days:
b25cb7db
RD
391 if val == cal_days[-1]:
392 width = width + self.restW
393
d14a1e28 394 day = AbrWeekday[val]
b881fc78 395
d14a1e28
RD
396 if self.sizew < 200:
397 day = day[0]
b881fc78 398
b25cb7db
RD
399 dw,dh = DC.GetTextExtent(day)
400
d14a1e28
RD
401 diffx = (width-dw)/2
402 diffy = (height-dh)/2
403
404 x = self.gridx[cnt_x]
405 y = self.gridy[cnt_y]
b25cb7db
RD
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)
d14a1e28
RD
448 cnt_x = cnt_x + 1
449
c1ea08d3 450 # draw the day numbers
b25cb7db 451 def DrawNum(self, DC):
b881fc78
RD
452 f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting
453
d14a1e28
RD
454 if self.num_auto == True:
455 test_size = self.max_num_size # max size
456 test_day = ' 99 '
b881fc78 457
d14a1e28
RD
458 while test_size > 2:
459 f.SetPointSize(test_size)
b25cb7db
RD
460 DC.SetFont(f)
461 tw,th = DC.GetTextExtent(test_day)
b881fc78 462
b25cb7db 463 if tw < self.cellW and th < self.cellH:
d14a1e28
RD
464 sizef = test_size
465 break
466 test_size = test_size - 1
467 else:
468 f.SetPointSize(self.num_size) # set fixed size
b25cb7db 469 DC.SetFont(f)
d14a1e28
RD
470
471 cnt_x = 0
472 cnt_y = 1
b25cb7db 473 for val in self.cal_days:
d14a1e28
RD
474 x = self.gridx[cnt_x]
475 y = self.gridy[cnt_y]
476
b25cb7db 477 self.DrawDayText(x, y, val, f, DC)
d14a1e28 478
b25cb7db
RD
479 if cnt_x < 6:
480 cnt_x = cnt_x + 1
d14a1e28 481 else:
b25cb7db
RD
482 cnt_x = 0
483 cnt_y = cnt_y + 1
d14a1e28 484
b25cb7db
RD
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
d14a1e28 503
b25cb7db 504 adj_h = adj_h + self.num_indent_horz
d14a1e28 505
b25cb7db
RD
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
d14a1e28 512
b25cb7db 513 adj_v = adj_v + self.num_indent_vert
b881fc78 514
b25cb7db 515 DC.DrawText(text, (x+adj_h, y+adj_v))
d14a1e28 516
c1ea08d3
RD
517 # calculate the dimensions in the center of the drawing area
518 def Center(self):
b25cb7db
RD
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)
d14a1e28 524
b25cb7db 525 self.restW = ((self.sizew - borderW)%7 ) - 1
d14a1e28 526
c1ea08d3 527 # week title adjustment
b25cb7db
RD
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
d14a1e28 536
c1ea08d3 537 # highlighted selected days
b25cb7db
RD
538 def DrawSel(self, DC):
539
d14a1e28
RD
540 for key in self.cal_sel.keys():
541 sel_color = self.cal_sel[key][1]
b25cb7db
RD
542 brush = wx.Brush(MakeColor(sel_color), wx.SOLID)
543 DC.SetBrush(brush)
d14a1e28
RD
544
545 if self.hide_grid is False:
b25cb7db 546 DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_GRID_LINES]), 0))
d14a1e28 547 else:
b25cb7db
RD
548 DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_BACKGROUND]), 0))
549
d14a1e28
RD
550 nkey = key + self.st_pos -1
551 rect = self.rg[nkey]
b25cb7db
RD
552
553 DC.DrawRectangle((rect.x, rect.y), (rect.width, rect.height))
d14a1e28 554
c1ea08d3 555 # calculate and draw the grid lines
b25cb7db
RD
556 def DrawGrid(self, DC):
557 DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_GRID_LINES]), 0))
d14a1e28
RD
558
559 self.gridx = []
560 self.gridy = []
561
562 self.x_st = self.cx_st + self.x_mrg
c1ea08d3
RD
563 # start postion of draw
564 self.y_st = self.cy_st + self.y_mrg + self.title_offset
b25cb7db 565
d14a1e28
RD
566 x1 = self.x_st
567 y1 = self.y_st
b25cb7db 568 y2 = y1 + self.calH + self.restH
b881fc78 569
d14a1e28 570 for i in range(8):
b25cb7db
RD
571 if i == 7:
572 x1 = x1 + self.restW
573
d14a1e28 574 if self.hide_grid is False:
b25cb7db
RD
575 DC.DrawLine((x1, y1), (x1, y2))
576
d14a1e28 577 self.gridx.append(x1)
b25cb7db
RD
578
579 x1 = x1 + self.cellW
d14a1e28
RD
580
581 x1 = self.x_st
582 y1 = self.y_st
b25cb7db 583 x2 = x1 + self.calW + self.restW
b881fc78 584
d14a1e28 585 for i in range(8):
b25cb7db
RD
586 if i == 7:
587 y1 = y1 + self.restH
588
d14a1e28 589 if self.hide_grid is False:
b25cb7db 590 DC.DrawLine((x1, y1), (x2, y1))
b881fc78 591
d14a1e28 592 self.gridy.append(y1)
b881fc78 593
d14a1e28 594 if i == 0:
b25cb7db 595 y1 = y1 + self.weekHdrCellH
d14a1e28 596 else:
b25cb7db
RD
597 y1 = y1 + self.cellH
598
599 def GetColor(self, name):
600 return MakeColor(self.colors[name])
d14a1e28 601
b25cb7db
RD
602 def SetColor(self, name, value):
603 self.colors[name] = MakeColor(value)
d14a1e28
RD
604
605class PrtCalDraw(CalDraw):
606 def InitValues(self):
607 self.rg = {}
608 self.cal_sel = {}
c1ea08d3
RD
609 # start draw border location
610 self.set_cx_st = 1.0
d14a1e28
RD
611 self.set_cy_st = 1.0
612
c1ea08d3
RD
613 # draw offset position
614 self.set_y_mrg = 0.2
d14a1e28
RD
615 self.set_x_mrg = 0.2
616 self.set_y_end = 0.2
617
b881fc78
RD
618 # calculate the dimensions in the center of the drawing area
619 def SetPSize(self, pwidth, pheight):
d14a1e28
RD
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
c1ea08d3 626class Calendar(wx.Window):
b881fc78
RD
627 def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize):
628 wx.Window.__init__(self, parent, id, pos, size)
d14a1e28 629
c1ea08d3 630 # set the calendar control attributes
b25cb7db 631 self.cal = None
d14a1e28 632
d14a1e28 633 self.hide_grid = False
d14a1e28
RD
634 self.hide_title = False
635 self.show_weekend = False
636 self.cal_type = "NORMAL"
b25cb7db
RD
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
d14a1e28
RD
644
645 self.select_list = []
646
b25cb7db 647 self.SetBackgroundColour(MakeColor(self.colors[COLOR_BACKGROUND]))
b881fc78
RD
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)
d14a1e28
RD
652
653 self.sel_key = None # last used by
654 self.sel_lst = [] # highlighted selected days
655
c1ea08d3
RD
656 # default calendar for current month
657 self.SetNow()
d14a1e28
RD
658
659 self.size = None
660 self.set_day = None
661
b881fc78
RD
662 self.Bind(wx.EVT_PAINT, self.OnPaint)
663 self.Bind(wx.EVT_SIZE, self.OnSize)
d14a1e28 664
b25cb7db
RD
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
c1ea08d3 671 # control some of the main calendar attributes
d14a1e28
RD
672
673 def HideTitle(self):
674 self.hide_title = True
675
676 def HideGrid(self):
677 self.hide_grid = True
678
c1ea08d3 679 # determine the calendar rectangle click area and draw a selection
d14a1e28
RD
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
c1ea08d3 686 # tab mouse click events and process
d14a1e28
RD
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):
c1ea08d3
RD
710 # list of highlighted days
711 self.sel_lst = sel
d14a1e28 712
c1ea08d3 713 # get the current date
d14a1e28
RD
714 def SetNow(self):
715 dt = now()
716 self.month = dt.month
717 self.year = dt.year
718 self.day = dt.day
719
c1ea08d3 720 # set the current day
d14a1e28
RD
721 def SetCurrentDay(self):
722 self.SetNow()
723 self.set_day = self.day
724
c1ea08d3 725 # get the date, day, month, year set in calendar
d14a1e28
RD
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
c1ea08d3 739 # set the day, month, and year
d14a1e28
RD
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
c1ea08d3 754 # increment year and month
d14a1e28
RD
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
c1ea08d3 778 # test to see if the selection has a date and create event
d14a1e28
RD
779
780 def TestDay(self, key):
781 try:
b25cb7db 782 self.day = int(self.cal_days[key])
d14a1e28
RD
783 except:
784 return None
b25cb7db 785
d14a1e28
RD
786 if self.day == "":
787 return None
788 else:
b881fc78
RD
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())
d14a1e28
RD
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
c1ea08d3 799 # find the clicked area rectangle
d14a1e28
RD
800
801 def GetDayHit(self, mx, my):
802 for key in self.rg.keys():
803 val = self.rg[key]
b881fc78
RD
804 ms_rect = wx.Rect(mx, my, 1, 1)
805 if wx.IntersectRect(ms_rect, val) is not None:
d14a1e28
RD
806 result = self.TestDay(key)
807 return result
b881fc78 808
d14a1e28
RD
809 return None
810
c1ea08d3 811 # calendar drawing
d14a1e28 812
c1ea08d3
RD
813 def SetWeekColor(self, font_color, week_color):
814 # set font and background color for week title
b25cb7db
RD
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
d14a1e28
RD
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):
c1ea08d3
RD
829 # highlight weekend
830 self.show_weekend = True
d14a1e28
RD
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):
b881fc78 840 DC = wx.PaintDC(self)
d14a1e28
RD
841 self.DoDrawing(DC)
842
843 def DoDrawing(self, DC):
b25cb7db 844 #DC = wx.PaintDC(self)
d14a1e28
RD
845 DC.BeginDrawing()
846
b25cb7db
RD
847 try:
848 cal = self.caldraw
849 except:
850 self.caldraw = CalDraw(self)
851 cal = self.caldraw
d14a1e28 852
d14a1e28 853 cal.hide_grid = self.hide_grid
d14a1e28
RD
854 cal.hide_title = self.hide_title
855 cal.show_weekend = self.show_weekend
856 cal.cal_type = self.cal_type
b25cb7db
RD
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
d14a1e28
RD
861
862 if self.size is None:
863 size = self.GetClientSize()
864 else:
865 size = self.size
866
c1ea08d3 867 # drawing attributes
d14a1e28 868
d14a1e28
RD
869 cal.SetSize(size)
870 cal.SetCal(self.year, self.month)
b881fc78 871
b25cb7db
RD
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
d14a1e28
RD
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()
b25cb7db 883 self.cal_days = cal.GetCal()
d14a1e28
RD
884 self.st_pos = cal.GetOffset()
885 self.ymax = DC.MaxY()
886
887 if self.set_day != None:
888 self.SetDay(self.set_day)
b881fc78 889
d14a1e28
RD
890 DC.EndDrawing()
891
c1ea08d3 892 # draw the selection rectangle
b25cb7db 893 def DrawRect(self, key, fgcolor = 'BLACK', width = 0):
d14a1e28
RD
894 if key == None:
895 return
b881fc78
RD
896
897 DC = wx.ClientDC(self)
d14a1e28
RD
898 DC.BeginDrawing()
899
b881fc78 900 brush = wx.Brush(wx.Colour(0, 0xFF, 0x80), wx.TRANSPARENT)
d14a1e28 901 DC.SetBrush(brush)
b25cb7db
RD
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))
d14a1e28
RD
907
908 rect = self.rg[key]
b25cb7db 909 DC.DrawRectangle((rect.x, rect.y), (rect.width, rect.height))
d14a1e28
RD
910
911 DC.EndDrawing()
912
c1ea08d3 913 # set the day selection
d14a1e28
RD
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
c1ea08d3 921 # clear large selection
b25cb7db 922 self.DrawRect(self.sel_key, self.GetColor(COLOR_BACKGROUND), sel_size)
b881fc78 923
d14a1e28 924 if self.hide_grid is False:
b25cb7db 925 self.DrawRect(self.sel_key, self.GetColor(COLOR_GRID_LINES), sel_size)
d14a1e28 926
b25cb7db 927 self.DrawRect(key, self.GetColor(COLOR_HIGHLIGHT_BACKGROUND), sel_size)
c1ea08d3
RD
928 # store last used by
929 self.sel_key = key
d14a1e28
RD
930 self.select_day = None
931
932 def ClearDsp(self):
933 self.Clear()
b25cb7db
RD
934 def SetMargin(self, xmarg, ymarg):
935 self.set_x_mrg = xmarg
936 self.set_y_mrg = ymarg
937 self.set_y_end = ymarg
d14a1e28 938
b881fc78 939class CalenDlg(wx.Dialog):
d14a1e28 940 def __init__(self, parent, month=None, day = None, year=None):
b881fc78 941 wx.Dialog.__init__(self, parent, -1, "Event Calendar", wx.DefaultPosition, (280, 360))
d14a1e28 942
c1ea08d3
RD
943 # set the calendar and attributes
944 self.calend = Calendar(self, -1, (20, 60), (240, 200))
b881fc78 945
d14a1e28
RD
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
c1ea08d3 958 # get month list from DateTime
d14a1e28
RD
959 monthlist = GetMonthList()
960
c1ea08d3 961 # select the month
b881fc78
RD
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)
d14a1e28 965
c1ea08d3 966 # alternate spin button to control the month
d14a1e28 967 h = self.date.GetSize().height
b881fc78 968 self.m_spin = wx.SpinButton(self, -1, (130, 20), (h*2, h), wx.SP_VERTICAL)
d14a1e28
RD
969 self.m_spin.SetRange(1, 12)
970 self.m_spin.SetValue(start_month)
b881fc78 971 self.Bind(wx.EVT_SPIN, self.OnMonthSpin, self.m_spin)
d14a1e28 972
c1ea08d3 973 # spin button to control the year
b881fc78 974 self.dtext = wx.TextCtrl(self, -1, str(start_year), (160, 20), (60, -1))
d14a1e28
RD
975 h = self.dtext.GetSize().height
976
b881fc78 977 self.y_spin = wx.SpinButton(self, -1, (220, 20), (h*2, h), wx.SP_VERTICAL)
d14a1e28
RD
978 self.y_spin.SetRange(1980, 2010)
979 self.y_spin.SetValue(start_year)
980
b881fc78
RD
981 self.Bind(wx.EVT_SPIN, self.OnYrSpin, self.y_spin)
982 self.Bind(EVT_CALENDAR, self.MouseClick, self.calend)
d14a1e28
RD
983
984 x_pos = 50
985 y_pos = 280
b881fc78 986 but_size = (60, 25)
d14a1e28 987
b881fc78
RD
988 btn = wx.Button(self, -1, ' Ok ', (x_pos, y_pos), but_size)
989 self.Bind(wx.EVT_BUTTON, self.OnOk, btn)
d14a1e28 990
c1ea08d3 991 btn = wx.Button(self, -1, ' Close ', (x_pos + 120, y_pos), but_size)
b881fc78 992 self.Bind(wx.EVT_BUTTON, self.OnCancel, btn)
d14a1e28
RD
993
994 def OnOk(self, event):
b881fc78 995 self.EndModal(wx.ID_OK)
d14a1e28
RD
996
997 def OnCancel(self, event):
b881fc78 998 self.EndModal(wx.ID_CANCEL)
d14a1e28 999
c1ea08d3 1000 # log the mouse clicks
d14a1e28
RD
1001 def MouseClick(self, evt):
1002 self.month = evt.month
c1ea08d3
RD
1003 # result click type and date
1004 self.result = [evt.click, str(evt.day), Month[evt.month], str(evt.year)]
d14a1e28
RD
1005
1006 if evt.click == 'DLEFT':
b881fc78 1007 self.EndModal(wx.ID_OK)
d14a1e28 1008
c1ea08d3 1009 # month and year spin selection routines
d14a1e28
RD
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
c1ea08d3 1030 # set the calendar for highlighted days
d14a1e28
RD
1031
1032 def ResetDisplay(self):
1033 month = self.calend.GetMonth()
1034 self.calend.Refresh()
1035
1fded56b 1036
1fded56b 1037