[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