[Commits] (alecf) More calendar refactoring to support multi-day events

commits at osafoundation.org commits at osafoundation.org
Fri Apr 1 15:44:37 PST 2005


Commit by: alecf
Modified files:
chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py 1.28 1.29
chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py 1.49 1.50

Log message:
More calendar refactoring to support multi-day events
- create CalendarCanvasItem which manages location for in-place editing, wrapped text drawing, and status bar pen selection
- hide item and bounds members of CanvasItem, because CanvasItems will soon have multiple bounds - use CalendarCanvasItem to abstract access to these members
- add MonthCanvasItem in case we have a month canvas, and factor out Draw() to this method

ViewCVS links:
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py.diff?r1=text&tr1=1.28&r2=text&tr2=1.29
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py.diff?r1=text&tr1=1.49&r2=text&tr2=1.50

Index: chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py
diff -u chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py:1.28 chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py:1.29
--- chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py:1.28	Tue Mar 29 12:59:39 2005
+++ chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py	Fri Apr  1 15:44:35 2005
@@ -1,8 +1,8 @@
 """ Canvas block for displaying item collections
 """
 
-__version__ = "$Revision: 1.28 $"
-__date__ = "$Date: 2005/03/29 20:59:39 $"
+__version__ = "$Revision: 1.29 $"
+__date__ = "$Date: 2005/04/01 23:44:35 $"
 __copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
 __license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -191,8 +191,8 @@
         """
 
         # @@@ scaffolding: resize bounds is the lower 5 pixels
-        self.bounds = bounds
-        self.item = item
+        self._bounds = bounds
+        self._item = item
 
     def isHit(self, point):
         """ Hit testing (used for selection and moving items).
@@ -202,7 +202,7 @@
         @return: True if the point hit the item (includes resize region)
         @rtype: Boolean
         """
-        return self.bounds.Inside(point)
+        return self._bounds.Inside(point)
 
     def isHitResize(self, point):
         """ Hit testing of a resize region.
@@ -216,7 +216,7 @@
         """
         return False
 
-    def getItem(self):
+    def GetItem(self):
         """
         Once we have a hit, give access to the item
         for selection, move, resize, etc.
@@ -224,7 +224,8 @@
         @return: the item associated with this region on the canvas.
         @rtype: Item
         """
-        return self.item
+        return self._item
+    
 
 class wxCollectionCanvas(wx.ScrolledWindow,
                          DragAndDrop.DropReceiveWidget,
@@ -315,51 +316,7 @@
     def SetDragBox(self, box):
         self._currentDragBox = self._originalDragBox = box
 
-    # Drawing utility -- scaffolding, we'll try using editor/renderers
-    def DrawWrappedText(self, dc, text, rect):
-        # Simple wordwrap, next step is to not overdraw the rect
-        
-        lines = text.splitlines()
-        y = rect.y
-        for line in lines:
-            x = rect.x
-            wrap = 0
-            for word in line.split():
-                width, height = dc.GetTextExtent(word)
-
-                # first see if we want to jump to the next line
-                # (careful not to jump if we're already at the beginning of the line)
-                if (x != rect.x and x + width > rect.x + rect.width):
-                    y += height
-                    x = rect.x
-                
-                # if we're out of vertical space, just return
-                if (y + height > rect.y + rect.height):
-                    return y
-                   
-                # if we wrapped but we still can't fit the word,
-                # just truncate it    
-                if (x == rect.x and width > rect.width):
-                    self.DrawClippedText(dc, word, x, y, rect.width)
-                    y += height
-                    continue
-                
-                dc.DrawText(word, x, y)
-                x += width
-                width, height = dc.GetTextExtent(' ')
-                dc.DrawText(' ', x, y)
-                x += width
-            y += height
-        return y
-
-    def DrawClippedText(self, dc, word, x, y, maxWidth):
-        # keep shortening the word until it fits
-        for i in xrange(len(word), 0, -1):
-            smallWord = word[0:i] # + "..."
-            width, height = dc.GetTextExtent(smallWord)
-            if width <= maxWidth:
-                dc.DrawText(smallWord, x, y)
-                return
+
         
     def DrawCenteredText(self, dc, text, rect):
         textExtent = dc.GetTextExtent(text)
@@ -454,7 +411,7 @@
                         hitBox = box
 
                 if hitBox:
-                    self.OnSelectItem(hitBox.getItem())
+                    self.OnSelectItem(hitBox.GetItem())
                     self.SetDragBox(hitBox)
 
                 # notice drag start whether or not we hit something

Index: chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py
diff -u chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py:1.49 chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py:1.50
--- chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py:1.49	Fri Apr  1 08:57:05 2005
+++ chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py	Fri Apr  1 15:44:35 2005
@@ -1,8 +1,8 @@
 """ Canvas for calendaring blocks
 """
 
-__version__ = "$Revision: 1.49 $"
-__date__ = "$Date: 2005/04/01 16:57:05 $"
+__version__ = "$Revision: 1.50 $"
+__date__ = "$Date: 2005/04/01 23:44:35 $"
 __copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
 __license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -16,19 +16,90 @@
 import osaf.framework.blocks.Block as Block
 import osaf.framework.blocks.calendar.CollectionCanvas as CollectionCanvas
 
-class ColumnarCanvasItem(CollectionCanvas.CanvasItem):
+class CalendarCanvasItem(CollectionCanvas.CanvasItem):
+    """
+    Base class for calendar items. Covers:
+    - editor position & size
+    - text wrapping
+    """
+    def GetEditorPosition(self):
+        return self._bounds.GetPosition()
+        
+    def GetMaxEditorSize(self):
+        return self._bounds.GetSize()
+    
+    def GetStatusPen(self):
+        item = self.GetItem()
+        if (item.transparency == "confirmed"):
+            pen = wx.Pen(wx.BLACK, 3)
+        elif (item.transparency == "fyi"):
+            pen = wx.Pen(wx.LIGHT_GREY, 3)
+        elif (item.transparency == "tentative"):
+            pen = wx.Pen(wx.BLACK, 3, wx.DOT)
+        return pen
+        
+    # Drawing utility -- scaffolding, we'll try using editor/renderers
+    def DrawWrappedText(self, dc, text, rect):
+        # Simple wordwrap, next step is to not overdraw the rect
+        
+        result = []
+        
+        lines = text.splitlines()
+        y = rect.y
+        for line in lines:
+            x = rect.x
+            wrap = 0
+            for word in line.split():
+                width, height = dc.GetTextExtent(word)
+
+                # first see if we want to jump to the next line
+                # (careful not to jump if we're already at the beginning of the line)
+                if (x != rect.x and x + width > rect.x + rect.width):
+                    y += height
+                    x = rect.x
+                
+                # if we're out of vertical space, just return
+                if (y + height > rect.y + rect.height):
+                    return y
+                   
+                # if we wrapped but we still can't fit the word,
+                # just truncate it    
+                if (x == rect.x and width > rect.width):
+                    self.DrawClippedText(dc, word, x, y, rect.width)
+                    y += height
+                    continue
+                
+                dc.DrawText(word, x, y)
+                x += width
+                width, height = dc.GetTextExtent(' ')
+                dc.DrawText(' ', x, y)
+                x += width
+            y += height
+        return y
+
+    def DrawClippedText(self, dc, word, x, y, maxWidth):
+        # keep shortening the word until it fits
+        for i in xrange(len(word), 0, -1):
+            smallWord = word[0:i] # + "..."
+            width, height = dc.GetTextExtent(smallWord)
+            if width <= maxWidth:
+                dc.DrawText(smallWord, x, y)
+                return
+        
+
+class ColumnarCanvasItem(CalendarCanvasItem):
     resizeBufferSize = 5
     RESIZE_MODE_START = 1
     RESIZE_MODE_END = 2
     def __init__(self, *arguments, **keywords):
         super(ColumnarCanvasItem, self).__init__(*arguments, **keywords)
         
-        self._resizeLowBounds = wx.Rect(self.bounds.x,
-                                        self.bounds.y + self.bounds.height - self.resizeBufferSize,
-                                        self.bounds.width, self.resizeBufferSize)
+        self._resizeLowBounds = wx.Rect(self._bounds.x,
+                                        self._bounds.y + self._bounds.height - self.resizeBufferSize,
+                                        self._bounds.width, self.resizeBufferSize)
         
-        self._resizeTopBounds = wx.Rect(self.bounds.x, self.bounds.y,
-                                        self.bounds.width, self.resizeBufferSize)
+        self._resizeTopBounds = wx.Rect(self._bounds.x, self._bounds.y,
+                                        self._bounds.width, self.resizeBufferSize)
 
     def isHitResize(self, point):
         """ Hit testing of a resize region.
@@ -62,8 +133,8 @@
         return None
         
     def Draw(self, dc, brushContainer):
-        item = self.item
-        itemRect = self.bounds
+        item = self._item
+        itemRect = self._bounds
         time = item.startTime
 
         # Draw one event
@@ -72,12 +143,7 @@
         dc.SetPen(brushContainer.selectionPen)
         dc.DrawRoundedRectangleRect(itemRect, radius=10)
 
-        if (item.transparency == "confirmed"):
-            pen = wx.Pen(wx.BLACK, 3)
-        elif (item.transparency == "fyi"):
-            pen = wx.Pen(wx.LIGHT_GREY, 3)
-        elif (item.transparency == "tentative"):
-            pen = wx.Pen(wx.BLACK, 3, wx.DOT)
+        pen = self.GetStatusPen()
 
         pen.SetCap(wx.CAP_BUTT)
         dc.SetPen(pen)
@@ -96,34 +162,23 @@
         # only draw time if there is room
         te = dc.GetFullTextExtent(timeString, brushContainer.smallBoldFont)        
         (timeWidth, timeHeight) = te[0], te[1]
-        if (timeHeight < itemRect.height/3):
+        if (timeHeight < itemRect.height/2):
             dc.SetFont(brushContainer.smallBoldFont)
-            y = brushContainer.DrawWrappedText(dc, timeString, timeRect)
+            y = self.DrawWrappedText(dc, timeString, timeRect)
         
         textRect = wx.Rect(x, y, width, itemRect.height - (y - itemRect.y))
 
         dc.SetFont(brushContainer.smallFont)
-        brushContainer.DrawWrappedText(dc, item.displayName, textRect)
+        self.DrawWrappedText(dc, item.displayName, textRect)
         
 
-class HeaderCanvasItem(CollectionCanvas.CanvasItem):
-    def Draw(self, dc, isSelected, brushContainer):
-        item = self.item
-        itemRect = self.bounds
+class HeaderCanvasItem(CalendarCanvasItem):
+    def Draw(self, dc, brushContainer):
+        item = self._item
+        itemRect = self._bounds
                 
-        # draw selection rectangle, if any
-        if (isSelected):
-            dc.SetBrush(brushContainer.selectionBrush)
-            dc.SetPen(brushContainer.selectionPen)
-            dc.DrawRectangleRect(itemRect)
-        
         # draw little rectangle to the left of the item
-        if (item.transparency == "confirmed"):
-            pen = wx.Pen(wx.BLACK, 3)
-        elif (item.transparency == "fyi"):
-            pen = wx.Pen(wx.LIGHT_GREY, 3)
-        elif (item.transparency == "tentative"):
-            pen = wx.Pen(wx.BLACK, 3, wx.DOT)
+        pen = self.GetStatusPen()
         
         pen.SetCap(wx.CAP_BUTT)
         dc.SetPen(pen)
@@ -133,9 +188,18 @@
         # Shift text
         itemRect.x = itemRect.x + 6
         itemRect.width = itemRect.width - 6
-        # @@@ hack, this should be abstracted somehow
-        brushContainer.DrawWrappedText(dc, item.displayName, itemRect)
-    
+        self.DrawWrappedText(dc, item.displayName, itemRect)
+
+# hacky - might not work, but we don't even have a month canvas working right now
+class MonthCanvasItem(CalendarCanvasItem):
+    def Draw(self, dc, isSelected):
+        if (self.blockItem.selection is item):
+            dc.SetPen(wx.BLACK_PEN)
+            dc.SetBrush(wx.WHITE_BRUSH)
+            dc.DrawRectangleRect(itemRect)
+            
+        self.DrawWrappedText(dc, self.GetItem().displayName, itemRect)
+        
 
 class CalendarEventHandler(object):
 
@@ -563,10 +627,15 @@
             self.canvasItemList.append(canvasItem)
             
             # keep track of the current drag/resize box
-            if self._currentDragBox and self._currentDragBox.item == item:
+            if self._currentDragBox and self._currentDragBox.GetItem() == item:
                 self._currentDragBox = canvasItem
 
-            canvasItem.Draw(dc, self.parent.blockItem.selection is item, self)
+            if (self.parent.blockItem.selection is item):
+                dc.SetBrush(self.selectionBrush)
+                dc.SetPen(self.selectionPen)
+                dc.DrawRectangleRect(itemRect)
+                
+            canvasItem.Draw(dc, self)
             
             y += h
             
@@ -595,7 +664,7 @@
             return
         
         newTime = self.getDateTimeFromPosition(unscrolledPosition)
-        item = self._currentDragBox.getItem()
+        item = self._currentDragBox.GetItem()
         if (newTime.absdate != item.startTime.absdate):
             item.ChangeStart(DateTime.DateTime(newTime.year, newTime.month,
                                                newTime.day,
@@ -604,10 +673,10 @@
             self.Refresh()
 
     def OnEditItem(self, box):
-        position = box.bounds.GetPosition()
-        size = box.bounds.GetSize()
+        position = box.GetEditorPosition()
+        size = box.GetMaxEditorSize()
 
-        self.editor.SetItem(box.getItem(), position, size, size.height)
+        self.editor.SetItem(box.GetItem(), position, size, size.height)
 
     def OnDayColumnSelect(self, event):
         """
@@ -806,7 +875,7 @@
             self.canvasItemList.append(canvasItem)
 
             # keep track of the current drag/resize box
-            if self._currentDragBox and self._currentDragBox.item == item:
+            if self._currentDragBox and self._currentDragBox.GetItem() == item:
                 self._currentDragBox = canvasItem                
                 
             # save the selected box to be drawn last
@@ -823,13 +892,13 @@
     # handle mouse related actions: move, resize, create, select
 
     def OnEditItem(self, box):
-        position = self.CalcScrolledPosition(box.bounds.GetPosition())
-        size = box.bounds.GetSize()
+        position = self.CalcScrolledPosition(box.GetEditorPosition())
+        size = box.GetMaxEditorSize()
 
         textPos = wx.Point(position.x + 8, position.y + 15)
         textSize = wx.Size(size.width - 13, size.height - 20)
 
-        self.editor.SetItem(box.getItem(), textPos, textSize, self.smallFont.GetPointSize()) 
+        self.editor.SetItem(box.GetItem(), textPos, textSize, self.smallFont.GetPointSize()) 
 
     def OnCreateItem(self, unscrolledPosition, createOnDrag):
         if createOnDrag:
@@ -867,7 +936,7 @@
         
     def OnResizingItem(self, unscrolledPosition):
         newTime = self.getDateTimeFromPosition(unscrolledPosition)
-        item = self._currentDragBox.getItem()
+        item = self._currentDragBox.GetItem()
         resizeMode = self.GetResizeMode()
         delta = DateTime.DateTimeDelta(0, 0, 15)
         
@@ -912,11 +981,14 @@
         #
         # so account for the original offset within the ORIGINAL dragbox so the 
         # mouse cursor stays in the same place relative to the original box
-        dy = (self._dragStartUnscrolled.y - self._originalDragBox.bounds.y)
+        
+        # @@@ Weird - we need to figure out where the original drag started
+        (boxX,boxY) = self._originalDragBox.GetEditorPosition()
+        dy = (self._dragStartUnscrolled.y - boxY)
         position = wx.Point(unscrolledPosition.x, unscrolledPosition.y - dy)
         
         newTime = self.getDateTimeFromPosition(position)
-        item = self._currentDragBox.getItem()
+        item = self._currentDragBox.GetItem()
         if ((newTime.absdate != item.startTime.absdate) or
             (newTime.hour != item.startTime.hour) or
             (newTime.minute != item.startTime.minute)):
@@ -1186,15 +1258,10 @@
             self.canvasItemList.append(canvasItem)
 
             # keep track of the current drag/resize box
-            if self._currentDragBox and self._currentDragBox.item == item:
+            if self._currentDragBox and self._currentDragBox.GetItem() == item:
                 self._currentDragBox = canvasItem
                 
-            if (self.blockItem.selection is item):
-                dc.SetPen(wx.BLACK_PEN)
-                dc.SetBrush(wx.WHITE_BRUSH)
-                dc.DrawRectangleRect(itemRect)
-                
-            self.DrawWrappedText(dc, item.displayName, itemRect)
+            canvasItem.Draw(dc, itemRect, self.blockItem.selection is item)
             y += h
 
     def DrawWeekday(self, dc, weekday, rect):
@@ -1228,7 +1295,7 @@
 
     def OnDraggingItem(self, unscrolledPosition):
         newTime = self.getDateTimeFromPosition(unscrolledPosition)
-        item = self._currentDragBox.getItem()
+        item = self._currentDragBox.GetItem()
         if (newTime.absdate != item.startTime.absdate):
             item.ChangeStart(DateTime.DateTime(newTime.year, newTime.month,
                                                newTime.day,



More information about the Commits mailing list