- 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
