[Commits] (alecf) fix bug 2655 - do drag-scrolling on a timer - reduces excess paints and makes the drag more responsive.

commits at osafoundation.org commits at osafoundation.org
Fri Mar 18 17:31:55 PST 2005


Commit by: alecf
Modified files:
chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py 1.26 1.27
chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py 1.41 1.42

Log message:
fix bug 2655 - do drag-scrolling on a timer - reduces excess paints and makes the drag more responsive.
Also change drag-scrolling to react to just the mouse cursor, rather than the entire event box
also change some constants to use integers rather than strings

Bugzilla links:
http://bugzilla.osafoundation.org/show_bug.cgi?id=2655

ViewCVS links:
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py.diff?r1=text&tr1=1.26&r2=text&tr2=1.27
http://cvs.osafoundation.org/index.cgi/chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py.diff?r1=text&tr1=1.41&r2=text&tr2=1.42

Index: chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py
diff -u chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py:1.26 chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py:1.27
--- chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py:1.26	Thu Mar 17 15:43:07 2005
+++ chandler/parcels/osaf/framework/blocks/calendar/CollectionCanvas.py	Fri Mar 18 17:31:54 2005
@@ -1,8 +1,8 @@
 """ Canvas block for displaying item collections
 """
 
-__version__ = "$Revision: 1.26 $"
-__date__ = "$Date: 2005/03/17 23:43:07 $"
+__version__ = "$Revision: 1.27 $"
+__date__ = "$Date: 2005/03/19 01:31:54 $"
 __copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
 __license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -368,13 +368,6 @@
         middleText = textExtent[0] / 2
         dc.DrawText(text, rect.x + middleRect - middleText, rect.y)
 
-    def GetResizeMode(self):
-        """
-        Helper method for drags
-        @@@ This belongs in CalendarCanvas! resize mode is calendar-specific
-        """
-        return self._originalDragBox.getResizeMode(self._dragStartUnscrolled)
-        
 
     # Mouse movement
 
@@ -405,13 +398,12 @@
         # handle dragging
         if self._isDraggingItem:
             if event.Dragging() and event.LeftIsDown():
+                self._dragCurrentUnscrolled = unscrolledPosition
                 self.OnDraggingItem(unscrolledPosition)
                 
-                # this really should be happening on a timer
-                self.ScrollIntoView(self._currentDragBox.bounds, True, True)
-                
             else: # end the drag
                 self._isDraggingItem = False
+                self._dragCurrentUnscrolled = None
                 self.OnEndDragItem()
                 self.SetDragBox(None)
                 self._dragStart = None
@@ -420,17 +412,12 @@
         # handle resizing
         elif self._isResizingItem:
             if event.Dragging() and event.LeftIsDown():
+                self._dragCurrentUnscrolled = unscrolledPosition
                 self.OnResizingItem(unscrolledPosition)
                 
-                # @@@ resizeMode is calendar-specific
-                resizeRect = self._currentDragBox.bounds
-                resizeMode = self.GetResizeMode()
-                
-                # this really should be happening on a timer
-                self.ScrollIntoView(resizeRect, resizeMode == "TOP", resizeMode == "LOW")
-                
             else: # end the drag
                 self._isResizingItem = False
+                self._dragCurrentUnscrolled = None
                 self.OnEndResizeItem()
                 self.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
                 self._dragStart = None
@@ -486,6 +473,7 @@
                 if (dx > tolerance or dy > tolerance):
                     if self._originalDragBox: 
                         resize = self._originalDragBox.isHitResize(self._dragStartUnscrolled)
+                        self._dragCurrentUnscrolled = self._dragStartUnscrolled
 
                         if resize: # start resizing
                             self._isResizingItem = True
@@ -509,31 +497,20 @@
                         else: # clear out the drag info, avoid creating more items
                             self._dragStart = None
                             self.SetDragBox(None)
-                            
-    def ScrollIntoView(self, rect, scrollUp, scrollDown):
-        # scroll the given rectangle into view
-        dy = 0
-        clientSize = self.GetClientSize()
-        
-        # now need to see if the box is outside of the visible area
-        tlPosition = self.CalcScrolledPosition(rect.GetTopLeft())
-        lrPosition = self.CalcScrolledPosition(rect.GetBottomRight())
-        (scrollX, scrollY) = self.CalcUnscrolledPosition(0,0)
 
-        scrolled = False
+    def ScrollIntoView(self, unscrolledPosition):
+        clientSize = self.GetClientSize()
         
         # scrolling up
-        if scrollUp and tlPosition.y < 0:
+        if unscrolledPosition.y < 0:
             # rectangle goes off the top - scroll up
-            dy = tlPosition.y
-            self.ScaledScroll(scrollX, scrollY + dy, buffer=-1)
-            scrolled = True
+            self.ScaledScroll(0, unscrolledPosition.y)
             
         # scrolling down
-        if not scrolled and scrollDown and lrPosition.y > clientSize.y:
+        elif unscrolledPosition.y > clientSize.y:
             # rectangle goes off the bottom - scroll down
-            dy = lrPosition.y - clientSize.y
-            self.ScaledScroll(scrollY, scrollY + dy, buffer=1)
+            dy = unscrolledPosition.y - clientSize.y
+            self.ScaledScroll(0, dy)
                         
     def GrabFocusHack(self):
         pass
@@ -668,7 +645,7 @@
         """
         pass
 
-    def ScaledScroll(self, scrollX, scrollY, buffer=0):
+    def ScaledScroll(self, dx, dy):
         """
         Subclasses should scroll appropriately if they have
         changed the scroll rate with SetScrollRate
@@ -676,6 +653,11 @@
         above, no buffer space, or buffer space below the area being
         made visible
         """
+        (scrollX, scrollY) = self.CalcUnscrolledPosition(0,0)
+        
+        scrollX += dx
+        scrollY += dy
+        
         self.Scroll(scrollX, scrollY)
  
     # selection

Index: chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py
diff -u chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py:1.41 chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py:1.42
--- chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py:1.41	Fri Mar 18 10:35:47 2005
+++ chandler/parcels/osaf/framework/blocks/calendar/CalendarCanvas.py	Fri Mar 18 17:31:54 2005
@@ -1,8 +1,8 @@
 """ Canvas for calendaring blocks
 """
 
-__version__ = "$Revision: 1.41 $"
-__date__ = "$Date: 2005/03/18 18:35:47 $"
+__version__ = "$Revision: 1.42 $"
+__date__ = "$Date: 2005/03/19 01:31:54 $"
 __copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
 __license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -16,15 +16,18 @@
 import osaf.framework.blocks.calendar.CollectionCanvas as CollectionCanvas
 
 class ColumnarCanvasItem(CollectionCanvas.CanvasItem):
+    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 - 5,
-                                        self.bounds.width, 5)
+                                        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, 5)
+                                        self.bounds.width, self.resizeBufferSize)
 
     def isHitResize(self, point):
         """ Hit testing of a resize region.
@@ -38,22 +41,23 @@
                 self._resizeLowBounds.Inside(point))
 
     def getResizeMode(self, point):
-        """ Returns the mode of the resize, either 'TOP' or 'LOW'.
+        """ Returns the mode of the resize, either RESIZE_MODE_START or
+        RESIZE_MODE_END.
 
-        The resize mode is 'TOP' if dragging from the top of the event,
-        and 'LOW' if dragging from the bottom of the event. None indicates
+        The resize mode is RESIZE_MODE_START if dragging from the top of the event,
+        and RESIZE_MODE_END if dragging from the bottom of the event. None indicates
         that we are not resizing at all.
 
         @param point: drag start position in uscrolled coordinates
         @type point: wx.Point
-        @return: resize mode, 'TOP', 'LOW' or None
+        @return: resize mode, RESIZE_MODE_START, RESIZE_MODE_END or None
         @rtype: string or None
         """
         
         if self._resizeTopBounds.Inside(point):
-            return "TOP"
+            return self.RESIZE_MODE_START
         if self._resizeLowBounds.Inside(point):
-            return "LOW"
+            return self.RESIZE_MODE_END
         return None
 
 
@@ -77,6 +81,17 @@
         self.blockItem.postDateChanged()
         self.wxSynchronizeWidget()
 
+class ClosureTimer(wx.Timer):
+    """
+    Helper class because targets may need to recieve multiple different timers
+    """
+    def __init__(self, callback, *args, **kwargs):
+        super(ClosureTimer, self).__init__(*args, **kwargs)
+        self._callback = callback
+        
+    def Notify(self):
+        self._callback()
+
 class CalendarBlock(CollectionCanvas.CollectionBlock):
     """ Abstract block used as base Kind for Calendar related blocks.
 
@@ -638,8 +653,19 @@
         self.SetScrollRate(0, self._scrollYRate)
         self.Scroll(0, (40*7)/self._scrollYRate)
 
-    def ScaledScroll(self, scrollX, scrollY, buffer=0):
-        self.Scroll(scrollX, (scrollY / self._scrollYRate) + buffer)
+    def ScaledScroll(self, dx, dy):
+        (scrollX, scrollY) = self.CalcUnscrolledPosition(0,0)
+        scrollX += dx
+        scrollY += dy
+        
+        # rounding ensures we scroll at least one unit
+        if dy < 0:
+            rounding = -self._scrollYRate
+        else:
+            rounding = self._scrollYRate
+
+        scaledY = (scrollY // self._scrollYRate) + rounding
+        self.Scroll(scrollX, scaledY)
         
     def _doDrawingCalculations(self):
         # @@@ magic numbers
@@ -849,6 +875,15 @@
             view.commit()
         return None
     
+    def OnBeginResizeItem(self):
+        self._lastUnscrolledPosition = self._dragStartUnscrolled
+        self.StartDragTimer()
+        pass
+        
+    def OnEndResizeItem(self):
+        self.StopDragTimer()
+        pass
+        
     def OnResizingItem(self, unscrolledPosition):
         newTime = self.getDateTimeFromPosition(unscrolledPosition)
         item = self._currentDragBox.getItem()
@@ -857,16 +892,39 @@
         
         # make sure we're changing by at least delta, and 
         # staying on the same day (we don't support resizing across days yet)
-        if (resizeMode == "LOW" and 
+        if (resizeMode == ColumnarCanvasItem.RESIZE_MODE_END and 
             newTime > (item.startTime + delta) and
             item.startTime.day == newTime.day):
             item.endTime = newTime
-        elif (resizeMode == "TOP" and 
+        elif (resizeMode == ColumnarCanvasItem.RESIZE_MODE_START and 
               newTime < (item.endTime - delta) and
               item.endTime.day == newTime.day):
             item.startTime = newTime
         self.Refresh()
     
+    def OnDragTimer(self):
+        """
+        This timer goes off while we're dragging/resizing
+        """
+        scrolledPosition = self.CalcScrolledPosition(self._dragCurrentUnscrolled)
+        self.ScrollIntoView(scrolledPosition)
+    
+    def StartDragTimer(self):
+        self.scrollTimer = ClosureTimer(self.OnDragTimer)
+        self.scrollTimer.Start(100, wx.TIMER_CONTINUOUS)
+    
+    def StopDragTimer(self):
+        self.scrollTimer.Stop()
+        self.scrollTimer = None
+        
+    def OnBeginDragItem(self):
+        self.StartDragTimer()
+        pass
+        
+    def OnEndDragItem(self):
+        self.StopDragTimer()
+        pass
+        
     def OnDraggingItem(self, unscrolledPosition):
         # at the start of the drag, the mouse was somewhere inside the
         # dragbox, but not necessarily exactly at x,y
@@ -884,6 +942,12 @@
             item.ChangeStart(newTime)
             self.Refresh()
 
+    def GetResizeMode(self):
+        """
+        Helper method for drags
+        """
+        return self._originalDragBox.getResizeMode(self._dragStartUnscrolled)
+        
     def getDateTimeFromPosition(self, position):
         # bound the position by the available space that the user 
         # can see/scroll to



More information about the Commits mailing list