X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b25cb7db43121f1f6899b7ebfcd6ccc3806dd0f6..25b3661bd4cb44304418b93c0dee1d0dfb99765c:/wxPython/wx/lib/calendar.py?ds=sidebyside diff --git a/wxPython/wx/lib/calendar.py b/wxPython/wx/lib/calendar.py index 6125518e93..4c8c3b4a48 100644 --- a/wxPython/wx/lib/calendar.py +++ b/wxPython/wx/lib/calendar.py @@ -58,6 +58,20 @@ # Instead set set_x_mrg and set_y_mrg # o Changed default X and Y Margin to 0. # o Added wxCalendar.SetMargin. +# +# 17/03/2004 - Joerg "Adi" Sieker adi@sieker.info +# o Added keyboard navigation to the control. +# Use the cursor keys to navigate through the ages. :) +# The Home key function as go to today +# o select day is now a filled rect instead of just an outline +# +# 15/04/2005 - Joe "shmengie" Brown joebrown@podiatryfl.com +# o Adjusted spin control size/placement (On Windows ctrls were overlapping). +# o Set Ok/Cancel buttons to wx.ID_OK & wx.ID_CANCEL to provide default dialog +# behaviour. +# o If no date has been clicked clicked, OnOk set the result to calend's date, +# important if keyboard only navigation is used. + import wx @@ -117,8 +131,8 @@ def DefaultColors(): colors[COLOR_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT) colors[COLOR_3D_LIGHT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNHIGHLIGHT) colors[COLOR_3D_DARK] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW) - colors[COLOR_HIGHLIGHT_FONT] = 'PINK' - colors[COLOR_HIGHLIGHT_BACKGROUND] = 'RED' + colors[COLOR_HIGHLIGHT_FONT] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT) + colors[COLOR_HIGHLIGHT_BACKGROUND] = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT) return colors # calendar drawing routing @@ -235,11 +249,22 @@ class CalDraw: self.cal_sel[val] = (cfont, cbackgrd) # draw border around the outside of the main display rectangle - def DrawBorder(self, DC): - brush = wx.Brush(MakeColor(self.colors[COLOR_BACKGROUND]), wx.SOLID) - DC.SetBrush(brush) - DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_BORDER]), 1)) + def DrawBorder(self, DC, transparent = False): if self.outer_border is True: + if transparent == False: + brush = wx.Brush(MakeColor(self.colors[COLOR_BACKGROUND]), wx.SOLID) + else: + brush = wx.TRANSPARENT_BRUSH + DC.SetBrush(brush) + DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_BORDER]))) + # full display window area + rect = wx.Rect(self.cx_st, self.cy_st, self.sizew, self.sizeh) + DC.DrawRectangleRect(rect) + + def DrawFocusIndicator(self, DC): + if self.outer_border is True: + DC.SetBrush(wx.TRANSPARENT_BRUSH) + DC.SetPen(wx.Pen(MakeColor(self.colors[COLOR_HIGHLIGHT_BACKGROUND]), style=wx.DOT)) # full display window area rect = wx.Rect(self.cx_st, self.cy_st, self.sizew, self.sizeh) DC.DrawRectangleRect(rect) @@ -275,6 +300,8 @@ class CalDraw: self.cal_days.append(str(i)) i = i + 1 + self.end_pos = start_pos + dim - 1 + return start_pos def SetWeekEnd(self, font_color=None, backgrd = None): @@ -298,6 +325,8 @@ class CalDraw: # get the display rectange list of the day grid def GetRect(self): cnt = 0 + h = 0 + w = 0 for y in self.gridy[1:-1]: if y == self.gridy[-2]: h = h + self.restH @@ -338,7 +367,7 @@ class CalDraw: tw,th = DC.GetTextExtent(month) adjust = self.cx_st + (self.sizew-tw)/2 - DC.DrawText(month, (adjust, self.cy_st + th)) + DC.DrawText(month, adjust, self.cy_st + th) year = str(self.year) tw,th = DC.GetTextExtent(year) @@ -348,7 +377,7 @@ class CalDraw: f = wx.Font(sizef, self.font, wx.NORMAL, self.bold) DC.SetFont(f) - DC.DrawText(year, (self.cx_st + adjust, self.cy_st + th)) + DC.DrawText(year, self.cx_st + adjust, self.cy_st + th) def DrawWeek(self, DC): # draw the week days # increase by 1 to include all gridlines @@ -410,7 +439,7 @@ class CalDraw: else: pen = wx.Pen(MakeColor(self.GetColor(COLOR_BACKGROUND)), 1, wx.SOLID) DC.SetPen(pen) - DC.DrawRectangle( pointXY, pointWH) + DC.DrawRectanglePointSize( pointXY, pointWH) old_pen = DC.GetPen() @@ -419,12 +448,12 @@ class CalDraw: # draw the horizontal hilight startPoint = wx.Point(x + 1 , y + 1) endPoint = wx.Point(x + width - 1, y + 1) - DC.DrawLine(startPoint, endPoint ) + DC.DrawLinePoint(startPoint, endPoint ) # draw the vertical hilight startPoint = wx.Point(x + 1 , y + 1) endPoint = wx.Point(x + 1, y + height - 2) - DC.DrawLine(startPoint, endPoint ) + DC.DrawLinePoint(startPoint, endPoint ) pen = wx.Pen(MakeColor(self.colors[COLOR_3D_DARK]), 1, wx.SOLID) DC.SetPen(pen) @@ -432,25 +461,22 @@ class CalDraw: # draw the horizontal lowlight startPoint = wx.Point(x + 1, y + height - 2) endPoint = wx.Point(x + width - 1, y + height - 2) - DC.DrawLine(startPoint, endPoint ) + DC.DrawLinePoint(startPoint, endPoint ) # draw the vertical lowlight startPoint = wx.Point(x + width - 2 , y + 2) endPoint = wx.Point(x + width - 2, y + height - 2) - DC.DrawLine(startPoint, endPoint ) + DC.DrawLinePoint(startPoint, endPoint ) pen = wx.Pen(MakeColor(self.colors[COLOR_FONT]), 1, wx.SOLID) DC.SetPen(pen) point = (x+diffx, y+diffy) - DC.DrawText(day, point) + DC.DrawTextPoint(day, point) cnt_x = cnt_x + 1 - # draw the day numbers - def DrawNum(self, DC): - f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting - + def _CalcFontSize(self, DC, f): if self.num_auto == True: test_size = self.max_num_size # max size test_day = ' 99 ' @@ -468,13 +494,18 @@ class CalDraw: f.SetPointSize(self.num_size) # set fixed size DC.SetFont(f) + # draw the day numbers + def DrawNum(self, DC): + f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting + self._CalcFontSize(DC, f) + cnt_x = 0 cnt_y = 1 for val in self.cal_days: x = self.gridx[cnt_x] y = self.gridy[cnt_y] - self.DrawDayText(x, y, val, f, DC) + self._DrawDayText(x, y, val, f, DC) if cnt_x < 6: cnt_x = cnt_x + 1 @@ -482,7 +513,8 @@ class CalDraw: cnt_x = 0 cnt_y = cnt_y + 1 - def DrawDayText(self, x, y, text, font, DC): + def _DrawDayText(self, x, y, text, font, DC): + try: num_val = int(text) num_color = self.cal_sel[num_val][0] @@ -512,25 +544,40 @@ class CalDraw: adj_v = adj_v + self.num_indent_vert - DC.DrawText(text, (x+adj_h, y+adj_v)) + DC.DrawTextPoint(text, (x+adj_h, y+adj_v)) + + def DrawDayText(self, DC, key): + f = wx.Font(10, self.font, wx.NORMAL, self.bold) # initial font setting + self._CalcFontSize(DC, f) + + if key > self.end_pos: + key = self.end_pos + + val = self.cal_days[key] + cnt_x = key % 7 + cnt_y = int(key / 7)+1 + x = self.gridx[cnt_x] + y = self.gridy[cnt_y] + self._DrawDayText(x, y, val, f, DC) + # calculate the dimensions in the center of the drawing area def Center(self): borderW = self.x_mrg * 2 borderH = self.y_mrg + self.y_end + self.title_offset - self.cellW = int((self.sizew-borderW)/7) - self.cellH = int((self.sizeh-borderH)/7) + self.cellW = int((self.sizew - borderW)/7) + self.cellH = int((self.sizeh - borderH)/7) self.restW = ((self.sizew - borderW)%7 ) - 1 # week title adjustment - self.weekHdrCellH = int(self.cellH*self.cal_week_scale) + self.weekHdrCellH = int(self.cellH * self.cal_week_scale) # recalculate the cell height exkl. the week header and # subtracting the size - self.cellH = int((self.sizeh-borderH-self.weekHdrCellH)/6) + self.cellH = int((self.sizeh - borderH - self.weekHdrCellH)/6) - self.restH = ((self.sizeh-borderH-self.weekHdrCellH)%6 ) - 1 + self.restH = ((self.sizeh - borderH - self.weekHdrCellH)%6 ) - 1 self.calW = self.cellW * 7 self.calH = self.cellH * 6 + self.weekHdrCellH @@ -550,7 +597,7 @@ class CalDraw: nkey = key + self.st_pos -1 rect = self.rg[nkey] - DC.DrawRectangle((rect.x, rect.y), (rect.width, rect.height)) + DC.DrawRectangleRect(rect) # calculate and draw the grid lines def DrawGrid(self, DC): @@ -572,7 +619,7 @@ class CalDraw: x1 = x1 + self.restW if self.hide_grid is False: - DC.DrawLine((x1, y1), (x1, y2)) + DC.DrawLinePoint((x1, y1), (x1, y2)) self.gridx.append(x1) @@ -587,7 +634,7 @@ class CalDraw: y1 = y1 + self.restH if self.hide_grid is False: - DC.DrawLine((x1, y1), (x2, y1)) + DC.DrawLinePoint((x1, y1), (x2, y1)) self.gridy.append(y1) @@ -623,12 +670,14 @@ class PrtCalDraw(CalDraw): def SetPreview(self, preview): self.preview = preview -class Calendar(wx.Window): - def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize): - wx.Window.__init__(self, parent, id, pos, size) +class Calendar( wx.PyControl ): + def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.Size(200,200), + style= 0, validator=wx.DefaultValidator, + name= "calendar"): + wx.PyControl.__init__(self, parent, id, pos, size, style | wx.WANTS_CHARS, validator, name) + self.hasFocus = False # set the calendar control attributes - self.cal = None self.hide_grid = False self.hide_title = False @@ -649,6 +698,9 @@ class Calendar(wx.Window): self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDEvent) self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightEvent) self.Bind(wx.EVT_RIGHT_DCLICK, self.OnRightDEvent) + self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) + self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.sel_key = None # last used by self.sel_lst = [] # highlighted selected days @@ -661,7 +713,10 @@ class Calendar(wx.Window): self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_SIZE, self.OnSize) - + + def AcceptsFocus(self): + return self.IsShown() and self.IsEnabled() + def GetColor(self, name): return MakeColor(self.colors[name]) @@ -703,6 +758,65 @@ class Calendar(wx.Window): self.click = 'DRIGHT' self.ProcessClick(event) + def OnSetFocus(self, event): + self.hasFocus = True + self.DrawFocusIndicator(True) + + def OnKillFocus(self, event): + self.hasFocus = False + self.DrawFocusIndicator(False) + + def OnKeyDown(self, event): + if not self.hasFocus: + event.Skip() + return + + key_code = event.KeyCode() + + if key_code == wx.WXK_TAB: + forward = not event.ShiftDown() + ne = wx.NavigationKeyEvent() + ne.SetDirection(forward) + ne.SetCurrentFocus(self) + ne.SetEventObject(self) + self.GetParent().GetEventHandler().ProcessEvent(ne) + event.Skip() + return + + delta = None + + if key_code == wx.WXK_UP: + delta = -7 + elif key_code == wx.WXK_DOWN: + delta = 7 + elif key_code == wx.WXK_LEFT: + delta = -1 + elif key_code == wx.WXK_RIGHT: + delta = 1 + elif key_code == wx.WXK_HOME: + curDate = wx.DateTimeFromDMY(int(self.cal_days[self.sel_key]),self.month - 1,self.year) + newDate = wx.DateTime_Now() + ts = newDate - curDate + delta = ts.GetDays() + + if delta <> None: + curDate = wx.DateTimeFromDMY(int(self.cal_days[self.sel_key]),self.month - 1,self.year) + timeSpan = wx.TimeSpan_Days(delta) + newDate = curDate + timeSpan + + if curDate.GetMonth() == newDate.GetMonth(): + self.set_day = newDate.GetDay() + key = self.sel_key + delta + self.SelectDay(key) + else: + self.month = newDate.GetMonth() + 1 + self.year = newDate.GetYear() + self.set_day = newDate.GetDay() + self.sel_key = None + self.DoDrawing(wx.ClientDC(self)) + + event.Skip() + def SetSize(self, set_size): self.size = set_size @@ -890,7 +1004,36 @@ class Calendar(wx.Window): DC.EndDrawing() # draw the selection rectangle - def DrawRect(self, key, fgcolor = 'BLACK', width = 0): + def DrawFocusIndicator(self, draw): + DC = wx.ClientDC(self) + try: + if draw == True: + self.caldraw.DrawFocusIndicator(DC) + else: + self.caldraw.DrawBorder(DC,True) + except: + pass + + def DrawRect(self, key, bgcolor = 'WHITE', fgcolor= 'PINK',width = 0): + if key == None: + return + + DC = wx.ClientDC(self) + DC.BeginDrawing() + + brush = wx.Brush(MakeColor(bgcolor)) + DC.SetBrush(brush) + + DC.SetPen(wx.TRANSPARENT_PEN) + + rect = self.rg[key] + DC.DrawRectangle(rect.x+1, rect.y+1, rect.width-2, rect.height-2) + + self.caldraw.DrawDayText(DC,key) + + DC.EndDrawing() + + def DrawRectOrg(self, key, fgcolor = 'BLACK', width = 0): if key == None: return @@ -906,28 +1049,39 @@ class Calendar(wx.Window): DC.SetPen(wx.Pen(MakeColor(self.GetColor(COLOR_GRID_LINES)), width)) rect = self.rg[key] - DC.DrawRectangle((rect.x, rect.y), (rect.width, rect.height)) + DC.DrawRectangleRect(rect) DC.EndDrawing() # set the day selection def SetDay(self, day): - day = day + self.st_pos - 1 - self.SelectDay(day) + d = day + self.st_pos - 1 + self.SelectDay(d) + def IsDayInWeekend(self, key): + try: + t = Date(self.year, self.month, 1) + + day = self.cal_days[key] + day = int(day) + t.day_of_week + + if day % 7 == 6 or day % 7 == 0: + return True + except: + return False + def SelectDay(self, key): sel_size = 1 # clear large selection - self.DrawRect(self.sel_key, self.GetColor(COLOR_BACKGROUND), sel_size) - - if self.hide_grid is False: - self.DrawRect(self.sel_key, self.GetColor(COLOR_GRID_LINES), sel_size) + + if self.sel_key != None: + (cfont, bgcolor) = self.__GetColorsForDay(self.sel_key) + self.DrawRect(self.sel_key, bgcolor,cfont, sel_size) - self.DrawRect(key, self.GetColor(COLOR_HIGHLIGHT_BACKGROUND), sel_size) + self.DrawRect(key, self.GetColor(COLOR_HIGHLIGHT_BACKGROUND), self.GetColor(COLOR_HIGHLIGHT_FONT), sel_size) # store last used by self.sel_key = key - self.select_day = None def ClearDsp(self): self.Clear() @@ -935,11 +1089,27 @@ class Calendar(wx.Window): self.set_x_mrg = xmarg self.set_y_mrg = ymarg self.set_y_end = ymarg + def __GetColorsForDay(self, key): + cfont = self.GetColor(COLOR_FONT) + bgcolor = self.GetColor(COLOR_BACKGROUND) + + if self.IsDayInWeekend(key) is True and self.show_weekend is True: + cfont = self.GetColor(COLOR_WEEKEND_FONT) + bgcolor = self.GetColor(COLOR_WEEKEND_BACKGROUND) + + try: + dayIdx = int(self.cal_days[key]) + (cfont, bgcolor) = self.caldraw.cal_sel[dayIdx] + except: + pass + + return (cfont, bgcolor) class CalenDlg(wx.Dialog): def __init__(self, parent, month=None, day = None, year=None): wx.Dialog.__init__(self, parent, -1, "Event Calendar", wx.DefaultPosition, (280, 360)) - + self.result = None + # set the calendar and attributes self.calend = Calendar(self, -1, (20, 60), (240, 200)) @@ -965,7 +1135,7 @@ class CalenDlg(wx.Dialog): # alternate spin button to control the month h = self.date.GetSize().height - self.m_spin = wx.SpinButton(self, -1, (130, 20), (h*2, h), wx.SP_VERTICAL) + self.m_spin = wx.SpinButton(self, -1, (115, 20), (h*1.5, h), wx.SP_VERTICAL) self.m_spin.SetRange(1, 12) self.m_spin.SetValue(start_month) self.Bind(wx.EVT_SPIN, self.OnMonthSpin, self.m_spin) @@ -974,7 +1144,7 @@ class CalenDlg(wx.Dialog): self.dtext = wx.TextCtrl(self, -1, str(start_year), (160, 20), (60, -1)) h = self.dtext.GetSize().height - self.y_spin = wx.SpinButton(self, -1, (220, 20), (h*2, h), wx.SP_VERTICAL) + self.y_spin = wx.SpinButton(self, -1, (225, 20), (h*1.5, h), wx.SP_VERTICAL) self.y_spin.SetRange(1980, 2010) self.y_spin.SetValue(start_year) @@ -985,13 +1155,14 @@ class CalenDlg(wx.Dialog): y_pos = 280 but_size = (60, 25) - btn = wx.Button(self, -1, ' Ok ', (x_pos, y_pos), but_size) + btn = wx.Button(self, wx.ID_OK, ' Ok ', (x_pos, y_pos), but_size) self.Bind(wx.EVT_BUTTON, self.OnOk, btn) - btn = wx.Button(self, -1, ' Close ', (x_pos + 120, y_pos), but_size) + btn = wx.Button(self, wx.ID_CANCEL, ' Close ', (x_pos + 120, y_pos), but_size) self.Bind(wx.EVT_BUTTON, self.OnCancel, btn) - def OnOk(self, event): + def OnOk(self, evt): + self.result = ['None', str(self.calend.day), Month[self.calend.month], str(self.calend.year)] self.EndModal(wx.ID_OK) def OnCancel(self, event):