]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/calendar.py
a4e2ed352e38bc4600bba6aff97d9d29c66ad580
[wxWidgets.git] / wxPython / wxPython / lib / calendar.py
1 #----------------------------------------------------------------------------
2 # Name: calendar.py
3 # Purpose: Calendar display control
4 #
5 # Author: Lorne White (email: lwhite1@planet.eon.net)
6 #
7 # Created:
8 # Version 0.6 2000/03/30
9 # Licence: wxWindows license
10 #----------------------------------------------------------------------------
11
12 from wxPython.wx import *
13
14 from CDate import *
15 import string, time
16
17
18 CalDays = [6, 0, 1, 2, 3, 4, 5]
19 AbrWeekday = {6:"Sun", 0:"Mon", 1:"Tue", 2:"Wed", 3:"Thu", 4:"Fri", 5:"Sat"}
20 _MIDSIZE = 160
21
22 BusCalDays = [0, 1, 2, 3, 4, 5, 6]
23
24 # calendar drawing routing
25
26 class CalDraw:
27 def __init__(self, parent):
28 self.pwidth = 1
29 self.pheight = 1
30 try:
31 self.scale = parent.scale
32 except:
33 self.scale = 1
34
35 self.DefParms()
36
37 def DefParms(self):
38 self.grid_color = 'BLACK' # grid and selection colors
39 self.back_color = 'WHITE'
40 self.sel_color = 'RED'
41
42 self.high_color = 'LIGHT BLUE'
43 self.border_color = 'BLACK'
44 self.week_color = 'LIGHT GREY'
45
46 self.week_font_color = 'BLACK' # font colors
47 self.day_font_color = 'BLACK'
48
49 self.font = wxSWISS
50 self.bold = wxNORMAL
51
52 self.hide_title = FALSE
53 self.hide_grid = FALSE
54 self.outer_border = TRUE
55
56 self.title_offset = 0
57 self.cal_week_scale = 0.7
58 self.show_weekend = FALSE
59 self.cal_type = "NORMAL"
60
61 def SetWeekColor(self, font_color, week_color): # set font and background color for week title
62 self.week_font_color = font_color
63 self.week_color = week_color
64
65 def SetSize(self, size):
66 self.set_sizew = size.width
67 self.set_sizeh = size.height
68
69 def InitValues(self): # default dimensions of various elements of the calendar
70 self.rg = {}
71 self.cal_sel = {}
72 self.set_cy_st = 0 # start position
73 self.set_cx_st = 0
74
75 self.set_y_mrg = 15 # start of vertical draw default
76 self.set_x_mrg = 10
77 self.set_y_end = 10
78
79 def SetPos(self, xpos, ypos):
80 self.set_cx_st = xpos
81 self.set_cy_st = ypos
82
83 def SetMarg(self, xmarg, ymarg):
84 self.set_x_st = xmarg
85 self.set_y_st = ymarg
86 self.set_y_end = ymarg
87
88 def InitScale(self): # scale position values
89 self.sizew = self.set_sizew * self.pwidth
90 self.sizeh = self.set_sizeh * self.pheight
91
92 self.cx_st = self.set_cx_st * self.pwidth # draw start position
93 self.cy_st = self.set_cy_st * self.pheight
94
95 self.x_mrg = self.set_x_mrg * self.pwidth # calendar draw margins
96 self.y_mrg = self.set_y_mrg * self.pheight
97 self.y_end = self.set_y_end * self.pheight
98
99 def DrawCal(self, DC, sel_lst=[]):
100 self.DC = DC
101 self.InitScale()
102
103 self.DrawBorder()
104 if self.hide_title is FALSE:
105 self.DrawMonth()
106
107 self.Center()
108
109 self.DrawGrid()
110 self.GetRect()
111
112 if self.show_weekend is TRUE: # highlight weekend dates
113 self.SetWeekEnd()
114
115 self.AddSelect(sel_lst) # overrides the weekend highlight
116
117 self.DrawSel() # highlighted days
118 self.DrawWeek()
119 self.DrawNum()
120
121 def AddSelect(self, list, cfont=None, cbackgrd = None):
122 if cfont is None:
123 cfont = self.sel_color # font digit color
124 if cbackgrd is None:
125 cbackgrd = self.high_color # select background color
126
127 for val in list:
128 self.cal_sel[val] = (cfont, cbackgrd)
129
130 def DrawBorder(self): # draw border around the outside of the main display rectangle
131 brush = wxBrush(wxNamedColour(self.back_color), wxSOLID)
132 self.DC.SetBrush(brush)
133 self.DC.SetPen(wxPen(wxNamedColour(self.border_color), 1))
134
135 if self.outer_border is TRUE:
136 rect = wxRect(self.cx_st, self.cy_st, self.sizew, self.sizeh) # full display window area
137 self.DC.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
138
139 def DrawNumVal(self):
140 self.DrawNum()
141
142 # calculate the calendar days and offset position
143
144 def SetCal(self, year, month):
145 self.InitValues() # reset initial values
146
147 self.year = year
148 self.month = month
149
150 day = 1
151 t = Date(year, month, day)
152 dow = self.dow = t.day_of_week # start day in month
153 dim = self.dim = t.days_in_month # number of days in month
154 if self.cal_type == "NORMAL":
155 start_pos = dow+1
156 else:
157 start_pos = dow
158
159 self.st_pos = start_pos
160
161 self.cal = []
162 for i in range(start_pos):
163 self.cal.append('')
164 i = 1
165 while i <= dim:
166 self.cal.append(str(i))
167 i = i + 1
168 return start_pos
169
170 def SetWeekEnd(self, font_color='BLACK', backgrd = 'LIGHT GREY'):
171 date = 6 - int(self.dow) # start day of first saturday
172 while date <= self.dim:
173 self.cal_sel[date] = (font_color, backgrd) # Saturday
174 date = date + 1
175 if date <= self.dim:
176 self.cal_sel[date] = (font_color, backgrd) # Sunday
177 date = date + 6
178 else:
179 date = date + 7
180
181 def GetRect(self): # get the display rectange list of the day grid
182 cnt = 0
183 for y in self.gridy[1:-1]:
184 for x in self.gridx[:-1]:
185 rect = wxRect(x, y, self.dl_w, self.dl_h) # create rect region
186 self.rg[cnt] = rect
187 cnt = cnt + 1
188 return self.rg
189
190 def GetCal(self):
191 return self.cal
192
193 def GetOffset(self):
194 return self.st_pos
195
196 def DrawMonth(self): # month and year title
197 month = Month[self.month]
198
199 sizef = 11
200 if self.sizeh < _MIDSIZE:
201 sizef = 10
202
203 f = wxFont(sizef, self.font, wxNORMAL, self.bold)
204 self.DC.SetFont(f)
205
206 tw,th = self.DC.GetTextExtent(month)
207 adjust = self.cx_st + (self.sizew-tw)/2
208 self.DC.DrawText(month, adjust, self.cy_st + th)
209
210 year = str(self.year)
211 tw,th = self.DC.GetTextExtent(year)
212 adjust = self.sizew - tw - self.x_mrg
213
214 self.title_offset = th * 2
215
216 f = wxFont(sizef, self.font, wxNORMAL, self.bold)
217 self.DC.SetFont(f)
218 self.DC.DrawText(year, self.cx_st + adjust, self.cy_st + th)
219
220 def DrawWeek(self): # draw the week days
221 sizef = 8
222 if self.sizeh < _MIDSIZE:
223 sizef = 7
224
225 f = wxFont(sizef, self.font, wxNORMAL, self.bold)
226 self.DC.SetFont(f)
227 self.DC.SetTextForeground(wxNamedColour(self.week_font_color))
228
229 cnt_x = 0
230 cnt_y = 0
231 width = self.gridx[1]-self.gridx[0]
232 height = self.gridy[1] - self.gridy[0]
233
234 rect_w = self.gridx[7]-self.gridx[0]
235
236 brush = wxBrush(wxNamedColour(self.week_color), wxSOLID)
237 self.DC.SetBrush(brush)
238 # self.DC.DrawRectangle(self.gridx[0], self.gridy[0], rect_w+1, height)
239
240 if self.cal_type == "NORMAL":
241 cal_days = CalDays
242 else:
243 cal_days = BusCalDays
244
245 for val in cal_days:
246 day = AbrWeekday[val]
247 if self.sizew < 200:
248 day = day[0]
249 dw,dh = self.DC.GetTextExtent(day)
250 diffx = (width-dw)/2
251 diffy = (height-dh)/2
252
253 x = self.gridx[cnt_x]
254 y = self.gridy[cnt_y]
255 self.DC.DrawRectangle(self.gridx[cnt_x], self.gridy[0], width+1, height)
256 self.DC.DrawText(day, x+diffx, y+diffy)
257 cnt_x = cnt_x + 1
258
259
260 def DrawNum(self): # draw the day numbers
261 sizef = 10
262 if self.sizeh < _MIDSIZE:
263 sizef = 8
264 f = wxFont(sizef, self.font, wxNORMAL, self.bold)
265
266 cnt_x = 0
267 cnt_y = 1
268 for val in self.cal:
269 x = self.gridx[cnt_x]
270 y = self.gridy[cnt_y]
271
272 try:
273 num_val = int(val)
274 num_color = self.cal_sel[num_val][0]
275 except:
276 num_color = self.day_font_color
277
278 self.DC.SetTextForeground(wxNamedColour(num_color))
279 self.DC.SetFont(f)
280
281 self.DC.DrawText(val, x+5, y+5)
282 if cnt_x < 6:
283 cnt_x = cnt_x + 1
284 else:
285 cnt_x = 0
286 cnt_y = cnt_y + 1
287
288 def Center(self): # calculate the dimensions in the center of the drawing area
289 bdw = self.x_mrg * 2
290 bdh = self.y_mrg + self.y_end + self.title_offset
291
292 self.dl_w = int((self.sizew-bdw)/7)
293 self.dl_h = int((self.sizeh-bdh)/7)
294
295 self.dl_th = int(self.dl_h*self.cal_week_scale) # week title adjustment
296 self.cwidth = self.dl_w * 7
297 self.cheight = self.dl_h * 6 + self.dl_th
298
299 def DrawSel(self): # highlighted selected days
300 for key in self.cal_sel.keys():
301 sel_color = self.cal_sel[key][1]
302 brush = wxBrush(wxNamedColour(sel_color), wxSOLID)
303 self.DC.SetBrush(brush)
304
305 if self.hide_grid is FALSE:
306 self.DC.SetPen(wxPen(wxNamedColour(self.grid_color), 0))
307 else:
308 self.DC.SetPen(wxPen(wxNamedColour(self.back_color), 0))
309 nkey = key + self.st_pos -1
310 rect = self.rg[nkey]
311 self.DC.DrawRectangle(rect.x, rect.y, rect.width+1, rect.height+1)
312
313 def DrawGrid(self): # calculate and draw the grid lines
314 self.DC.SetPen(wxPen(wxNamedColour(self.grid_color), 0))
315
316 self.gridx = []
317 self.gridy = []
318
319 self.x_st = self.cx_st + self.x_mrg
320 self.y_st = self.cy_st + self.y_mrg + self.title_offset # start postion of draw
321
322 x1 = self.x_st
323 y1 = self.y_st
324
325 y2 = y1 + self.cheight
326 for i in range(8):
327 if self.hide_grid is FALSE:
328 self.DC.DrawLine(x1, y1, x1, y2)
329 self.gridx.append(x1)
330 x1 = x1 + self.dl_w
331
332 x1 = self.x_st
333 y1 = self.y_st
334
335 x2 = x1 + self.cwidth
336 for i in range(8):
337 if self.hide_grid is FALSE:
338 self.DC.DrawLine(x1, y1, x2, y1)
339 self.gridy.append(y1)
340 if i == 0:
341 y1 = y1 + self.dl_th
342 else:
343 y1 = y1 + self.dl_h
344
345
346 class PrtCalDraw(CalDraw):
347 def InitValues(self):
348 self.rg = {}
349 self.cal_sel = {}
350 self.set_cx_st = 1.0 # start draw border location
351 self.set_cy_st = 1.0
352
353 self.set_y_mrg = 0.2 # draw offset position
354 self.set_x_mrg = 0.2
355 self.set_y_end = 0.2
356
357 def SetPSize(self, pwidth, pheight): # calculate the dimensions in the center of the drawing area
358 self.pwidth = int(pwidth)/self.scale
359 self.pheight = int(pheight)/self.scale
360
361 def SetPreview(self, preview):
362 self.preview = preview
363
364 class wxCalendar(wxWindow):
365 def __init__(self, parent, id, pos=wxDefaultPosition, size=wxDefaultSize):
366 wxWindow.__init__(self, parent, id, pos, size)
367
368 # set the calendar control attributes
369
370 self.grid_color = 'BLACK'
371 self.back_color = 'WHITE'
372 self.hide_grid = FALSE
373 self.sel_color = 'RED'
374 self.hide_title = FALSE
375 self.show_weekend = FALSE
376 self.cal_type = "NORMAL"
377
378 self.week_color = 'LIGHT GREY'
379 self.week_font_color = 'BLACK' # font colors
380
381 self.select_list = []
382
383 self.SetBackgroundColour(wxNamedColor(self.back_color))
384 self.Connect(-1, -1, wxEVT_LEFT_DOWN, self.OnLeftEvent)
385 self.Connect(-1, -1, wxEVT_LEFT_DCLICK, self.OnLeftDEvent)
386 self.Connect(-1, -1, wxEVT_RIGHT_DOWN, self.OnRightEvent)
387 self.Connect(-1, -1, wxEVT_RIGHT_DCLICK, self.OnRightDEvent)
388
389 self.sel_key = None # last used by
390 self.sel_lst = [] # highlighted selected days
391
392 self.SetNow() # default calendar for current month
393
394 self.size = None
395 self.set_day = None
396
397 EVT_PAINT(self, self.OnPaint)
398
399
400 # control some of the main calendar attributes
401
402 def HideTitle(self):
403 self.hide_title = TRUE
404
405 def HideGrid(self):
406 self.hide_grid = TRUE
407
408 # determine the calendar rectangle click area and draw a selection
409
410 def ProcessClick(self, event):
411 self.x, self.y = event.GetX(), event.GetY()
412 key = self.GetDayHit(self.x, self.y)
413 self.SelectDay(key)
414
415 # tab mouse click events and process
416
417 def OnLeftEvent(self, event):
418 self.click = 'LEFT'
419 self.ProcessClick(event)
420
421 def OnLeftDEvent(self, event):
422 self.click = 'DLEFT'
423 self.ProcessClick(event)
424
425 def OnRightEvent(self, event):
426 self.click = 'RIGHT'
427 self.ProcessClick(event)
428
429 def OnRightDEvent(self, event):
430 self.click = 'DRIGHT'
431 self.ProcessClick(event)
432
433 def SetSize(self, set_size):
434 self.size = set_size
435
436 def SetSelDay(self, sel):
437 self.sel_lst = sel # list of highlighted days
438
439 # get the current date
440
441 def SetNow(self):
442 dt = now()
443 self.month = dt.month
444 self.year = dt.year
445 self.day = dt.day
446
447 # set the current day
448
449 def SetCurrentDay(self):
450 self.SetNow()
451 self.set_day = self.day
452
453 # get the date, day, month, year set in calendar
454
455 def GetDate(self):
456 return self.day, self.month, self.year
457
458 def GetDay(self):
459 return self.day
460
461 def GetMonth(self):
462 return self.month
463
464 def GetYear(self):
465 return self.year
466
467 # set the day, month, and year
468
469 def SetDayValue(self, day):
470 self.set_day = day
471
472 def SetMonth(self, month):
473 if month >= 1 and month <= 12:
474 self.month = month
475 else:
476 self.month = 1
477 self.set_day = None
478
479 def SetYear(self, year):
480 self.year = year
481
482 # increment year and month
483
484 def IncYear(self):
485 self.year = self.year + 1
486 self.set_day = None
487
488 def DecYear(self):
489 self.year = self.year - 1
490 self.set_day = None
491
492 def IncMonth(self):
493 self.month = self.month + 1
494 if self.month > 12:
495 self.month = 1
496 self.year = self.year + 1
497 self.set_day = None
498
499 def DecMonth(self):
500 self.month = self.month - 1
501 if self.month < 1:
502 self.month = 12
503 self.year = self.year - 1
504 self.set_day = None
505
506 # test to see if the selection has a date and create event
507
508 def TestDay(self, key):
509 try:
510 self.day = int(self.cal[key])
511 except:
512 return None
513 if self.day == "":
514 return None
515 else:
516 evt = wxPyCommandEvent(2100, self.GetId())
517 evt.click, evt.day, evt.month, evt.year = self.click, self.day, self.month, self.year
518 self.GetEventHandler().ProcessEvent(evt)
519
520 self.set_day = self.day
521 return key
522
523 # find the clicked area rectangle
524
525 def GetDayHit(self, mx, my):
526 for key in self.rg.keys():
527 val = self.rg[key]
528 ms_rect = wxRect(mx, my, 1, 1)
529 if wxIntersectRect(ms_rect, val) is not None:
530 result = self.TestDay(key)
531 return result
532 return None
533
534 # calendar drawing
535
536 def SetWeekColor(self, font_color, week_color): # set font and background color for week title
537 self.week_font_color = font_color
538 self.week_color = week_color
539
540 def AddSelect(self, list, font_color, back_color):
541 list_val = [list, font_color, back_color]
542 self.select_list.append(list_val)
543
544 def ShowWeekEnd(self):
545 self.show_weekend = TRUE # highlight weekend
546
547 def SetBusType(self):
548 self.cal_type = "BUS"
549
550 def OnPaint(self, event):
551 DC = wxPaintDC(self)
552 self.DoDrawing(DC)
553
554 def DoDrawing(self, DC):
555 DC = wxPaintDC(self)
556 DC.BeginDrawing()
557
558 self.cal = cal = CalDraw(self)
559
560 cal.grid_color = self.grid_color
561 cal.back_color = self.back_color
562 cal.hide_grid = self.hide_grid
563 cal.grid_color = self.grid_color
564 cal.hide_title = self.hide_title
565 cal.show_weekend = self.show_weekend
566 cal.cal_type = self.cal_type
567
568 if self.size is None:
569 size = self.GetClientSize()
570 else:
571 size = self.size
572
573 # drawing attributes
574
575 cal.week_font_color = self.week_font_color
576 cal.week_color = self.week_color
577
578 cal.SetSize(size)
579 cal.SetCal(self.year, self.month)
580 for val in self.select_list:
581 cal.AddSelect(val[0], val[1], val[2])
582
583 cal.DrawCal(DC, self.sel_lst)
584
585 self.rg = cal.GetRect()
586 self.cal = cal.GetCal()
587 self.st_pos = cal.GetOffset()
588 self.ymax = DC.MaxY()
589
590 if self.set_day != None:
591 self.SetDay(self.set_day)
592 DC.EndDrawing()
593
594 # draw the selection rectangle
595
596 def DrawRect(self, key, color = 'BLACK', width = 0):
597 if key == None:
598 return
599 DC = wxClientDC(self)
600 DC.BeginDrawing()
601
602 brush = wxBrush(wxColour(0, 0xFF, 0x80), wxTRANSPARENT)
603 DC.SetBrush(brush)
604 DC.SetPen(wxPen(wxNamedColour(color), width))
605
606 rect = self.rg[key]
607 DC.DrawRectangle(rect.x, rect.y, rect.width+1, rect.height+1)
608
609 DC.EndDrawing()
610
611 # set the day selection
612
613 def SetDay(self, day):
614 day = day + self.st_pos - 1
615 self.SelectDay(day)
616
617 def SelectDay(self, key):
618 sel_size = 1
619 self.DrawRect(self.sel_key, self.back_color, sel_size) # clear large selection
620 if self.hide_grid is FALSE:
621 self.DrawRect(self.sel_key, self.grid_color)
622
623 self.DrawRect(key, self.sel_color, sel_size)
624 self.sel_key = key # store last used by
625 self.select_day = None
626
627 def ClearDsp(self):
628 self.Clear()
629
630