- Revision
- 15938
- Author
- jeffrey
- Date
- 2007-11-28 13:31:21 -0800 (Wed, 28 Nov 2007)
Log Message
[APP] Fix calendar drawing on the Mac. The Mac's default matrix
flips the Y axis, so when creating matrices to transform rects
explicitly set their initial state to the identity matrix.
flips the Y axis, so when creating matrices to transform rects
explicitly set their initial state to the identity matrix.
Modified Paths
Diff
Modified: branches/rearchitecture/Chandler-Platform/ocap/wxui/calendar.py (15937 => 15938)
--- branches/rearchitecture/Chandler-Platform/ocap/wxui/calendar.py 2007-11-28 21:30:52 UTC (rev 15937) +++ branches/rearchitecture/Chandler-Platform/ocap/wxui/calendar.py 2007-11-28 21:31:21 UTC (rev 15938) @@ -69,7 +69,13 @@ gradient_left = wx.Color(0, 63, 127), gradient_right = wx.Color(0, 102, 204), ) - + +if wx.Platform == '__WXMSW__': + DEFAULT_FONT_SIZE = 8 +else: + DEFAULT_FONT_SIZE = 9 + + class Event(InitializeSlots): __slots__ = ('id', 'title', 'start', 'duration', 'color', 'swatch_colors') def __cmp__(self, other): @@ -109,9 +115,9 @@ self.start = event.start if self.end is None or event.end > self.end: self.end = event.end - + bisect.insort(self.event_list, event) - + for level in self.levels: for level_event in level: if event.overlaps(level_event): @@ -172,7 +178,7 @@ class Calendar(wx.ScrolledWindow): def __init__(self, time_formatter=None, *arguments, **keywords): super(Calendar, self).__init__ (*arguments, **keywords) - + self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None) @@ -183,43 +189,42 @@ self.matrix = None self.hour_height = BASE_HOUR_HEIGHT self.margin_right = wx.SystemSettings_GetMetric(wx.SYS_VSCROLL_X) - + self.business_start = 9 self.business_end = 17 # CreateMeasuringContext has the wrong SWIG directive applied as of 11/2007, # so this won't work #measure = wx.GraphicsContext.CreateMeasuringContext() measure = wx.GraphicsContext.Create(self) - - self.legend_font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) + + self.legend_font = wx.Font(DEFAULT_FONT_SIZE, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) self.legend_font_height = font_height(measure, self.legend_font) self.legend_strings = [str(i) for i in range(1,13)] * 2 - self.time_font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) + self.time_font = wx.Font(DEFAULT_FONT_SIZE, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) self.time_font_height = font_height(measure, self.time_font) - + self.title_font = self.legend_font self.title_font_height = font_height(measure, self.title_font) self.range_start = None self.range_mode = 'week' - + if time_formatter is None: self.time_formatter = default_time_formatter else: self.time_formatter = time_formatter - + # caching self.draw_from_cache = False self._buffer = None - def Refresh(self, *args): """ Set a flag so we know if the paint event is happening because of a programatic call to Refresh, or if it is a 'natural' refresh due to things like scrolling or the window being damaged by another window. - + """ self.draw_from_cache = False super(Calendar, self).Refresh(*args) @@ -265,13 +270,15 @@ gc = wx.GraphicsContext.Create(dc) width, height = self.GetSize() - gc.PushState() - gc.Translate(MARGIN_LEFT, 0) - gc.Scale((width - MARGIN_LEFT - self.margin_right)/BASE_WIDTH, - self.hour_height/BASE_HOUR_HEIGHT) + self.matrix = gc.GetTransform() - gc.PopState() - + # create a matrix to transform rectangles with. The Mac default transform is a y-flip, + # so explicitly set the initial matrix + self.matrix.Set(1,0,0,1,0,0) + self.matrix.Translate(MARGIN_LEFT, 0) + self.matrix.Scale((width - MARGIN_LEFT - self.margin_right)/BASE_WIDTH, + self.hour_height/BASE_HOUR_HEIGHT) + self.DrawBackground(gc) for day in self.days: @@ -299,15 +306,15 @@ else: rect.Inset(depth/(max_depth - 1)*BASE_DAY_WIDTH*0.2, 0, 0, 0) rect.width = BASE_DAY_WIDTH * 0.8 - + rect = TransformRect(self.matrix, rect) rect.Inset(HALO_WIDTH, HALO_WIDTH) line_height = self.title_font_height min_height = 2*TEXT_Y_MARGIN + line_height if rect.height < min_height: - rect.SetBottom(min(self.hour_height * 24, rect.y + min_height)) - + rect.SetBottom(min(self.hour_height * 24 - 1, rect.y + min_height)) + if column == 0 and depth == 0: # don't let the halo overlap the legend border by too much rect.Inset(.5, 0, 0, 0) @@ -317,19 +324,18 @@ truncate |= wx.TOP if event.end > end: truncate |= wx.BOTTOM - + if event.start < start: # continuation lozenge, just draw a small-radius lozenge DrawFilledLozenge(gc, rect, SMALL_RADIUS, truncate = truncate) - + # draw one line? Draw time? Draw title on first line? # Room for how many swatches (min 2)? - + if event.start >= start: radius = SMALL_RADIUS if rect.height != min_height else min_height/2 - print radius, event.id DrawFilledLozenge(gc, rect, radius, truncate = truncate) - + time_height = (TEXT_Y_MARGIN + TIME_BOTTOM_MARGIN + self.time_font_height) @@ -352,20 +358,19 @@ gc.SetFont(self.title_font, DefaultColors.text) # need to wrap text DrawWrappedText(gc, event.title, rect) - + gc.ResetClip() - def DrawBackground(self, gc): gc.SetPen(wx.Pen(MINOR_LINE_COLOR)) path = self.GetDayLinePath(gc) path.AddPath(self.GetHalfHourLinePath(gc)) gc.StrokePath(path) - + gc.SetPen(wx.Pen(MAJOR_LINE_COLOR)) path = (self.GetHourLinePath(gc)) gc.StrokePath(path) - + self.DrawLegend(gc) def GetDayLinePath(self, gc): @@ -400,7 +405,7 @@ """ Draw legend hours for a timed canvas. Draw a thick line separating the legend from the calendar, with business hours shaded differently. - + """ light_pen = wx.Pen(MAJOR_LINE_COLOR, LEGEND_BORDER_WIDTH) dark_pen = wx.Pen(LEGEND_COLOR, LEGEND_BORDER_WIDTH) @@ -413,15 +418,16 @@ # a pixel light_pen.SetCap(wx.CAP_PROJECTING) dark_pen.SetCap( wx.CAP_PROJECTING) - + # adjust matrix for the extra right hand side of the pen matrix = gc.GetTransform() + matrix.Set(1,0,0,1,0,0) matrix.Translate( (1 - LEGEND_BORDER_WIDTH) / 2, 0) matrix.Concat(self.matrix) - + main_line_start = matrix.TransformPoint(0, 1) main_line_end = matrix.TransformPoint(0, BOTTOM_EDGE - 1) - + business_line_start = 0, self.business_start*BASE_HOUR_HEIGHT + 1 business_line_start = matrix.TransformPoint(*business_line_start) @@ -437,7 +443,7 @@ # draw the legend text gc.SetFont(self.legend_font, LEGEND_COLOR) x, real_hour_height = matrix.TransformPoint(0, BASE_HOUR_HEIGHT) - + for hour, text in enumerate(self.legend_strings[:-1]): hour += 1 width, height = gc.GetTextExtent(text) @@ -470,19 +476,19 @@ self.range_mode = range_mode if self.range_start is not None: self.SetRange(self, self.range_start) - + def ChangeEvent(self, id, **kw): """ Create an event for id or adjust an existing one, adjust ordering of lozenge clusters the event appears in. - + """ if not self.events.has_key(id): self.events[id] = Event(id=id) event = self.events[id] for key, value in kw.iteritems(): setattr(event, key, value) - + for day in self.days: if event.overlaps(day): day.change(event) @@ -490,7 +496,7 @@ elif event in day.event_list: day.remove(event) self.Refresh(False) - + def RemoveEvent(self, id): """Remove an event from the events displayed.""" pass @@ -517,7 +523,7 @@ def GetLozengePath(gc, rect, truncate, radius): """ Return a rounded rectangle path with certain edges truncated (not rounded). - + truncate should be a bitfield of any combination of wx.RIGHT, wx.TOP, wx.LEFT, and wx.BOTTOM. @@ -527,15 +533,15 @@ if not truncate: path.AddRoundedRectangle(x, y, width, height, radius) return path - + corners = wx.Rect2D(*rect) adjust = wx.Point2D(0, radius) - + start = corners.GetRightTop() if not (truncate & (wx.RIGHT | wx.TOP)): start += adjust path.MoveToPoint(start) - + edge_vectors = {wx.LEFT | wx.TOP : corners.GetLeftTop(), wx.RIGHT | wx.TOP : corners.GetRightTop(), wx.LEFT | wx.BOTTOM : corners.GetLeftBottom(), @@ -556,7 +562,7 @@ adjust.SetPolarCoordinates(90*(i - 2), radius) point += adjust path.AddArc(point, radius, radians(i*90), radians((i + 1)*90)) - + return path def TransformRect(matrix, rect):
_______________________________________________ Commits mailing list [email protected] http://lists.osafoundation.org/mailman/listinfo/commits
