Title: [commits] (grant) [16122] [APP] Unit tests for table mouse tracking
Revision
16122
Author
grant
Date
2007-12-12 18:14:44 -0800 (Wed, 12 Dec 2007)

Log Message

[APP] Unit tests for table mouse tracking

Modified Paths

Diff

Modified: branches/rearchitecture/Chandler-Platform/ocap/wxui/table.py (16121 => 16122)

--- branches/rearchitecture/Chandler-Platform/ocap/wxui/table.py	2007-12-13 02:13:05 UTC (rev 16121)
+++ branches/rearchitecture/Chandler-Platform/ocap/wxui/table.py	2007-12-13 02:14:44 UTC (rev 16122)
@@ -497,34 +497,42 @@
         col = self.XToCol(unscrolledX)
         toolTipString = None
         oldOverRowCol = self.overRowCol
+        outsideGrid = (-1 in (row, col))
+        
+        refreshRowCols = set()
+        
+        if outsideGrid:
+            self.overRowCol = None
+            
+        if event.LeftUp():
+            refreshRowCols.add(self.clickRowCol)
+            refreshRowCols.add(oldOverRowCol)
+            
+            if self.clickRowCol == (row, col):
+                self.Table.OnClick(row, col)
+            self.overRowCol = None
+            self.clickRowCol = None
 
-        if -1 in (row, col):
+        elif event.LeftDClick():
+            # Stop hover if we're going to edit
             self.overRowCol = None
 
-        elif event.LeftDown():
+        elif event.LeftDown() and not outsideGrid:
+            refreshRowCols.add(oldOverRowCol)
             if self.Table.CanClick(row, col):
                 self.clickRowCol = self.overRowCol = row, col
                 event.Skip(False) # Gobble the event
-                self.RefreshRect(self.GetRectForCellRange(*self.clickRowCol))
+                refreshRowCols.add(self.clickRowCol)
+                if not gridWindow.HasCapture():
+                    gridWindow.CaptureMouse()
                 self.SetFocus()
             else:
                 self.overRowCol = None
 
-        elif event.LeftUp():
-            if self.clickRowCol == (row, col):
-                self.Table.OnClick(row, col)
-            if self.clickRowCol is not None:
-                self.RefreshRect(self.GetRectForCellRange(*self.clickRowCol))
-            self.overRowCol = None
-
-        elif event.LeftDClick():
-            # Stop hover if we're going to edit
-            self.overRowCol = None
-
         elif self.clickRowCol is not None:
-            if self.overRowCol != (row, col):
+            if not outsideGrid:
                 self.overRowCol = row, col
-                event.Skip(False) # Gobble the event
+            event.Skip(False) # Gobble the event
 
 
         elif not event.LeftIsDown() and (self.overRowCol != row, col):
@@ -534,11 +542,6 @@
             else:
                 self.overRowCol = None
 
-        if event.LeftDown():
-            pass
-            #if blockItem.contents.isItemSelected(item):
-            #    self.setFocus = True
-
         if toolTipString:
             gridWindow.SetToolTipString(toolTipString)
             gridWindow.GetToolTip().Enable(True)
@@ -549,18 +552,16 @@
                 gridWindow.SetToolTip(None)
 
         if self.overRowCol != oldOverRowCol:
-            if oldOverRowCol is not None:
-                self.RefreshRect(self.GetRectForCellRange(*oldOverRowCol))
+            refreshRowCols.add(oldOverRowCol)
+            refreshRowCols.add(self.overRowCol)
 
-            if self.overRowCol is None:
+            if (self.overRowCol, self.clickRowCol) == (None, None):
                 if (gridWindow.HasCapture()):
                     gridWindow.ReleaseMouse()
-                if self.clickRowCol is not None:
-                    clickRowCol = self.clickRowCol
-                    self.clickRowCol = None
-                    self.RefreshRect(self.GetRectForCellRange(*clickRowCol))
-            else:
-                self.RefreshRect(self.GetRectForCellRange(*self.overRowCol))
+
+        for cell in refreshRowCols:
+            if cell is not None:
+                self.RefreshRect(self.GetRectForCellRange(*cell))
             
 
     def OnMouseCaptureLost(self, event):

Modified: branches/rearchitecture/Chandler-Platform/test_table.py (16121 => 16122)

--- branches/rearchitecture/Chandler-Platform/test_table.py	2007-12-13 02:13:05 UTC (rev 16121)
+++ branches/rearchitecture/Chandler-Platform/test_table.py	2007-12-13 02:14:44 UTC (rev 16122)
@@ -151,7 +151,408 @@
         Check that drawing an icon in non mouse-down mode doesn't advance
         value.
         """
-        """Check that drawing an icon in mouse-down mode advances value"""
         mock = self.mocker.patch(self.renderer, table.IconRenderer)
         mocker.expect(mock.advanceValue("Woo!")).result("Woo!").count(0)
         self.doDrawingTest((3, 1), None, (3, 1), True, "rolloverselected")
+
+class MouseEventsTestCase(mocker.MockerTestCase):
+
+    def setUp(self):
+        super(MouseEventsTestCase, self).setUp()
+
+        # This unfortunate construction seems necessary because I couldn't
+        # find a way to mock the Table constructor, and actually calling into
+        # wx will cause bad things to happen here.
+        # [grant]
+        class Booger(object): pass
+        fauxTable = Booger(); fauxTable.__class__ = table.Table
+
+        # Set up mock objects for the table, presentation and gridWindow
+        self.view = self.mocker.patch(fauxTable)
+        self.presentation = self.mocker.mock(table.TablePresentation)
+        self.gridWindow = self.mocker.mock(wx.Window)
+        
+        # And hook them up so that various accessing attributes/methods
+        # can be called as many times as necessary.
+        self.expect(self.view.GetTable()).result(self.presentation).count(0, None)
+        self.expect(self.view.Table).result(self.presentation).count(0, None)
+        self.expect(self.presentation.GetView()).result(self.view).count(0, None)
+        self.expect(self.presentation.Table).result(self.view).count(0, None)
+        self.expect(self.view.GetGridWindow()).result(self.gridWindow).count(0, None)
+
+
+    def setUpEvent(self, cell, point=(100, 3), unscrolled=(55, 21), **kw):
+        event = self.mocker.mock(wx.MouseEvent)
+        
+        self.expect(event.GetX()).result(point[0]).count(0, None)
+        self.expect(event.GetY()).result(point[1]).count(0, None)
+        self.expect(self.view.CalcUnscrolledPosition(point[0], point[1])).result(unscrolled).count(0, None)
+
+        self.expect(self.view.YToRow(unscrolled[1])).result(cell[0]).count(0, None)
+        self.expect(self.view.XToCol(unscrolled[0])).result(cell[1]).count(0, None)
+
+        for method in ('LeftDown', 'LeftUp', 'LeftDClick', 'LeftIsDown'):
+            value = kw.get(method, False)
+            self.expect(getattr(event, method)()).result(value).count(0, None)
+        
+        # Pass OnMouseEvents thru to the underlying method, since that's the
+        # code we're actually trying to test :)
+        self.expect(self.view.OnMouseEvents(event)).passthrough()
+
+        # We also pass through the overRowCol and clickRowCol attributes,
+        # since we are setting those up manually, and testing that OnMouseEvents
+        # sets them correctly.
+        self.expect(self.view.overRowCol).passthrough().count(0, None)
+        self.expect(self.view.clickRowCol).passthrough().count(0, None)
+        
+        return event
+
+    def expectCellRefresh(self, row, col):
+        mockRect = self.mocker.mock(wx.Rect)
+        self.expect(self.view.GetRectForCellRange(row, col)).result(mockRect)
+        self.expect(self.view.RefreshRect(mockRect)).result(None)        
+
+    def testClickDisabled(self):
+        """
+        Test that when clicking in a cell, where the presentation returns
+        CanClick --> False, no processing results.
+        """
+        event = self.setUpEvent((4, 4), LeftDown=True, LeftIsDown=True)
+
+        self.expect(event.Skip()).result(None)
+        self.expect(self.presentation.CanClick(4, 4)).result(False)
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+        
+        self.mocker.replay()
+        self.view.OnMouseEvents(event)
+        
+        self.failUnlessIs(self.view.overRowCol, None)
+        self.failUnlessIs(self.view.clickRowCol, None)
+
+    def testClickEnabled(self):
+        """
+        Test that when clicking in a cell, where the presentation returns
+        CanClick --> True, overRowCol and clickRowCol are updated appropriately.
+        """
+        event = self.setUpEvent((1, 3), LeftDown=True, LeftIsDown=True)
+
+        self.expect(self.presentation.CanClick(1, 3)).result(True)
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+        # We expect a call to event.Skip(False), since we're exclusively
+        # handling this click
+        self.mocker.before(
+            self.expect(event.Skip()).result(None),
+            self.expect(event.Skip(False)).result(None),
+        )
+
+        # Also, we should be refreshing the rect corresponding to this cell
+        self.expectCellRefresh(1, 3)
+        
+        # Expect the code to capture the mouse
+        self.expect(self.gridWindow.HasCapture()).result(False)
+        self.expect(self.gridWindow.CaptureMouse()).result(True)
+        # Lastly, the click should set focus
+        self.expect(self.view.SetFocus()).result(None)
+        
+        self.mocker.replay()
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have been correctly changed.
+        self.failUnlessEqual(self.view.overRowCol, (1, 3))
+        self.failUnlessEqual(self.view.clickRowCol, (1, 3))
+
+    def testClickOutsideX(self):
+        """
+        Test that if the a click outside the grid is handled,
+        no processing occurs.
+        """
+        event = self.setUpEvent((-1, 3), LeftDown=True, LeftIsDown=True)
+        self.expect(event.Skip()).result(None)
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+        self.mocker.replay()
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have been correctly changed.
+        self.failUnlessEqual(self.view.overRowCol, None)
+        self.failUnlessEqual(self.view.clickRowCol, None)
+
+    def testTrackOutsideGrid(self):
+        """
+        Test of moving the mouse to outside the grid, after a click in a cell
+        """
+        event = self.setUpEvent((3, -1), LeftIsDown=True)
+        self.mocker.order(
+            self.expect(event.Skip()).result(None),
+            self.expect(event.Skip(False)).result(None),
+        )
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+        # Also, we should be refreshing the rect corresponding to the click cell
+        self.expectCellRefresh(2, 0)
+
+        self.mocker.replay()
+
+        self.view.overRowCol = self.view.clickRowCol = (2, 0)
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have been correctly changed.
+        self.failUnlessEqual(self.view.overRowCol, None)
+        self.failUnlessEqual(self.view.clickRowCol, (2, 0))
+
+    def testClickOutsideY(self):
+        """
+        Test that if the a click outside the grid is handled,
+        no processing occurs.
+        """
+        event = self.setUpEvent((0, -1), LeftDown=True, LeftIsDown=True)
+        self.expect(event.Skip()).result(None)
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+        self.mocker.replay()
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have been correctly changed.
+        self.failUnlessEqual(self.view.overRowCol, None)
+        self.failUnlessEqual(self.view.clickRowCol, None)
+
+    def testTrackDisabled(self):
+        """
+        Test that if the presentation returns False to TrackMouse() in a cell,
+        no processing occurs.
+        """
+        event = self.setUpEvent((0, 0))
+
+        self.expect(event.Skip()).result(None)
+        self.expect(self.presentation.TrackMouse(0, 0)).result(False)
+        self.expect(self.presentation.GetToolTipString(0, 0)).result(None)
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+        self.mocker.replay()
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have been correctly changed.
+        self.failUnlessEqual(self.view.overRowCol, None)
+        self.failUnlessEqual(self.view.clickRowCol, None)
+
+
+    def testTrackEnabled(self):
+        """
+        Test that if the presentation returns True to TrackMouse() in a cell,
+        overRowCol is updated accordingly.
+        """
+        event = self.setUpEvent((11, 9))
+
+        self.expect(event.Skip()).result(None)
+        self.expect(self.presentation.TrackMouse(11, 9)).result(True)
+        self.expect(self.presentation.GetToolTipString(11, 9)).result(None)
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+        # Also, we should be refreshing the rect corresponding to this cell
+        self.expectCellRefresh(11, 9)
+        
+        # Lastly, the click should not set focus
+        self.expect(self.view.SetFocus()).result(None).count(0)
+        
+        self.mocker.replay()
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have been correctly changed.
+        self.failUnlessEqual(self.view.overRowCol, (11, 9))
+        self.failUnlessEqual(self.view.clickRowCol, None)
+
+    def testTrackOutsideClick(self):
+        """
+        Test that if you have clicked inside one cell, and then move the mouse
+        outside that cell, that overRowCol is updated accordingly.
+        """
+        event = self.setUpEvent((0, 7), LeftIsDown=True)
+        
+        self.mocker.before(
+            self.expect(event.Skip()).result(None),
+            # We expect a call to event.Skip(False), since we're exclusively
+            # handling the click already
+            self.expect(event.Skip(False)).result(None),
+        )
+            
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+
+        # We should be refreshing the rects corresponding to the
+        # clicked cell ....
+        self.expectCellRefresh(1, 6)
+
+        # ... and the tracked cell
+        self.expectCellRefresh(0, 7)
+        
+        # Lastly, the tracking should not set focus
+        self.expect(self.view.SetFocus()).result(None).count(0)
+        
+        self.mocker.replay()
+        self.view.overRowCol = self.view.clickRowCol = (1, 6)
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have not been changed.
+        self.failUnlessEqual(self.view.overRowCol, (0, 7))
+        self.failUnlessEqual(self.view.clickRowCol, (1, 6))
+
+    def testTrackInsideClick(self):
+        """
+        Test of moving the mouse around inside a clicked cell.
+        """
+        event = self.setUpEvent((0, 7), LeftIsDown=True)
+
+        self.mocker.before(
+            self.expect(event.Skip()).result(None),
+            # We expect a call to event.Skip(False), since we're exclusively
+            # handling the click already
+            self.expect(event.Skip(False)).result(None),
+        )
+            
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+
+        # Lastly, the tracking should not set focus
+        self.expect(self.view.SetFocus()).result(None).count(0)
+        
+        self.mocker.replay()
+        self.view.overRowCol = self.view.clickRowCol = (0, 7)
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have not been changed.
+        self.failUnlessEqual(self.view.overRowCol, (0, 7))
+        self.failUnlessEqual(self.view.clickRowCol, (0, 7))
+
+    def testTrackChangingCell(self):
+        """
+        Test of moving the mouse from one tracked cell to another.
+        """
+        event = self.setUpEvent((0, 7))
+        
+        self.expect(event.Skip()).result(None)
+        self.expect(self.presentation.TrackMouse(0, 7)).result(True)
+        self.expect(self.presentation.GetToolTipString(0, 7)).result(None)
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+        # We should be refreshing the rect corresponding to the old
+        # "over" cell
+        self.expectCellRefresh(1, 6)
+        
+        # ... as well as the new
+        self.expectCellRefresh(0, 7)
+        
+        # Lastly, the click should not set focus
+        self.expect(self.view.SetFocus()).result(None).count(0)
+        
+        self.mocker.replay()
+        
+        self.view.overRowCol = (1, 6)
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have not been changed.
+        self.failUnlessEqual(self.view.overRowCol, (0, 7))
+        self.failUnlessEqual(self.view.clickRowCol, None)
+
+    def testMouseUpOutside(self):
+        """
+        Test that mouse up outside the clicked cell resets all state
+        appropriately.
+        """
+        event = self.setUpEvent((1, 0), LeftUp=True)
+
+        self.expect(self.gridWindow.HasCapture()).result(True).count(0, None)
+        self.expect(self.gridWindow.ReleaseMouse()).result(None).count(0, None)
+
+        self.expect(event.Skip()).result(None)
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+        # Also, we should be refreshing the rect corresponding to the
+        # original clicked cell
+        self.expectCellRefresh(1, 1)
+        
+        # Lastly, the click should not set focus
+        self.expect(self.view.SetFocus()).result(None).count(0)
+        
+        self.mocker.replay()
+        
+        self.view.overRowCol = self.view.clickRowCol = (1, 1)
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have been reset.
+        self.failUnlessEqual(self.view.overRowCol, None)
+        self.failUnlessEqual(self.view.clickRowCol, None)
+
+    def testMouseUpOutsideGrid(self):
+        """
+        Test that mouse up outside the clicked cell resets all state
+        appropriately.
+        """
+        event = self.setUpEvent((-1, 0), LeftUp=True)
+
+        self.expect(self.gridWindow.HasCapture()).result(True).count(0, None)
+        self.expect(self.gridWindow.ReleaseMouse()).result(None).count(0, None)
+
+        self.expect(event.Skip()).result(None),
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+
+        # Also, we should be refreshing the rect corresponding to the
+        # original clicked cell
+        self.expectCellRefresh(10, 0)
+        
+        # Lastly, the click should not set focus
+        self.expect(self.view.SetFocus()).result(None).count(0)
+        
+        self.mocker.replay()
+        
+        self.view.overRowCol = self.view.clickRowCol = (10, 0)
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have been reset.
+        self.failUnlessEqual(self.view.overRowCol, None)
+        self.failUnlessEqual(self.view.clickRowCol, None)
+
+    def testMouseUpInside(self):
+        """
+        Test that mouse up inside the clicked cell triggers the appropriate
+        OnClick() call, etc.
+        """
+        event = self.setUpEvent((0, 7), LeftUp=True)
+
+        self.expect(self.gridWindow.HasCapture()).result(True).count(0, None)
+        self.expect(self.gridWindow.ReleaseMouse()).result(None).count(0, None)
+
+        self.expect(event.Skip()).result(None)
+        self.expect(self.gridWindow.GetToolTip()).result(None)
+        
+        # The mouseUp should lead to the presentation's OnClick() being
+        # called (exactly once)
+        self.expect(self.presentation.OnClick(0, 7)).result(None)
+
+        # Also, we should be refreshing the rect corresponding to this cell
+        self.expectCellRefresh(0, 7)
+
+        # Lastly, the mouse-up should not set focus
+        self.expect(self.view.SetFocus()).result(None).count(0)
+        
+        self.mocker.replay()
+        
+        self.view.overRowCol = self.view.clickRowCol = (0, 7)
+        self.view.OnMouseEvents(event)
+
+        # As post-conditions, we make sure our view's over/click values
+        # have (correctly) been reset.
+        self.failUnlessEqual(self.view.overRowCol, None)
+        self.failUnlessEqual(self.view.clickRowCol, None)
+




_______________________________________________
Commits mailing list
[email protected]
http://lists.osafoundation.org/mailman/listinfo/commits

Reply via email to