Fix persistent tree view palettes

A rework of the TreeViewInvoker used by the journal and activity list.

Fixes a persistent journal entry palette that reappears in journal or
home view.  https://bugs.sugarlabs.org/ticket/4918

Also fixes an over-sensitive journal icon; with the journal mostly
empty, rapidly move the mouse from the bottom of the screen into the
lowest icon and then out again.  Before this patch, the palette was
shown.  After this patch, the mouse must rest in the icon.

Changes made:

- override _ensure_palette_exists in parent class Invoker,

- remove reference to MouseSpeedDetector, it is no longer required,

- remove enter and leave events; they are for the TreeView as a whole,
  and are not required,

- properly detect that None is returned by get_path_at_pos, when the
  coordinates are outside the TreeView cells.

Not fixed:

- moving the mouse out of the journal icon invoker does not popdown the
  palette, but it does when moving the mouse out of the activity icon in
  the activity list; so this is a problem beyond the invoker,

Tested on Fedora 18 and Ubuntu 15.10.

Test cases:

- check a click will activate item,

- check a right-click will show palette,

- check a mouse hover will show palette,

- check a brief mouse passing will not show palette,

- check if mouse leaving palette will popdown.
This commit is contained in:
James Cameron 2015-12-21 14:18:28 +11:00
parent b1386665b1
commit 7ba120fe25

View File

@ -1411,15 +1411,12 @@ class TreeViewInvoker(Invoker):
self._tree_view = None self._tree_view = None
self._motion_hid = None self._motion_hid = None
self._leave_hid = None
self._release_hid = None self._release_hid = None
self._long_pressed_hid = None self._long_pressed_hid = None
self._position_hint = self.AT_CURSOR self._position_hint = self.AT_CURSOR
self._long_pressed_controller = SugarGestures.LongPressController() self._long_pressed_controller = SugarGestures.LongPressController()
self._mouse_detector = MouseSpeedDetector(200, 5)
self._tree_view = None self._tree_view = None
self._path = None self._path = None
self._column = None self._column = None
@ -1431,10 +1428,6 @@ class TreeViewInvoker(Invoker):
self._motion_hid = tree_view.connect('motion-notify-event', self._motion_hid = tree_view.connect('motion-notify-event',
self.__motion_notify_event_cb) self.__motion_notify_event_cb)
self._enter_hid = tree_view.connect('enter-notify-event',
self.__enter_notify_event_cb)
self._leave_hid = tree_view.connect('leave-notify-event',
self.__leave_notify_event_cb)
self._release_hid = tree_view.connect('button-release-event', self._release_hid = tree_view.connect('button-release-event',
self.__button_release_event_cb) self.__button_release_event_cb)
self._long_pressed_hid = self._long_pressed_controller.connect( self._long_pressed_hid = self._long_pressed_controller.connect(
@ -1443,19 +1436,14 @@ class TreeViewInvoker(Invoker):
tree_view, tree_view,
SugarGestures.EventControllerFlags.NONE) SugarGestures.EventControllerFlags.NONE)
self._mouse_detector.connect('motion-slow', self.__mouse_slow_cb)
self._mouse_detector.parent = tree_view
Invoker.attach(self, tree_view) Invoker.attach(self, tree_view)
def detach(self): def detach(self):
Invoker.detach(self) Invoker.detach(self)
self._tree_view.disconnect(self._motion_hid) self._tree_view.disconnect(self._motion_hid)
self._tree_view.disconnect(self._enter_hid)
self._tree_view.disconnect(self._leave_hid)
self._tree_view.disconnect(self._release_hid) self._tree_view.disconnect(self._release_hid)
self._long_pressed_controller.detach(self._tree_view) self._long_pressed_controller.detach(self._tree_view)
self._long_pressed_controller.disconnect(self._long_pressed_hid) self._long_pressed_controller.disconnect(self._long_pressed_hid)
self._mouse_detector.disconnect_by_func(self.__mouse_slow_cb)
def get_rect(self): def get_rect(self):
return self._tree_view.get_background_area(self._path, self._column) return self._tree_view.get_background_area(self._path, self._column)
@ -1464,9 +1452,15 @@ class TreeViewInvoker(Invoker):
return self._tree_view.get_toplevel() return self._tree_view.get_toplevel()
def __motion_notify_event_cb(self, widget, event): def __motion_notify_event_cb(self, widget, event):
try: here = self._tree_view.get_path_at_pos(int(event.x), int(event.y))
path, column, x_, y_ = self._tree_view.get_path_at_pos( if here is None:
int(event.x), int(event.y)) if self._path is not None:
self.notify_mouse_leave()
self._path = None
self._column = None
return
path, column, x_, y_ = here
if path != self._path or column != self._column: if path != self._path or column != self._column:
self._redraw_cell(self._path, self._column) self._redraw_cell(self._path, self._column)
self._redraw_cell(path, column) self._redraw_cell(path, column)
@ -1478,11 +1472,7 @@ class TreeViewInvoker(Invoker):
self.palette.popdown(immediate=True) self.palette.popdown(immediate=True)
self.palette = None self.palette = None
self._mouse_detector.start() self.notify_mouse_enter()
except TypeError:
# tree_view.get_path_at_pos() fail if x,y poition is over
# a empty area
pass
def _redraw_cell(self, path, column): def _redraw_cell(self, path, column):
area = self._tree_view.get_background_area(path, column) area = self._tree_view.get_background_area(path, column)
@ -1490,15 +1480,12 @@ class TreeViewInvoker(Invoker):
self._tree_view.convert_bin_window_to_widget_coords(area.x, area.y) self._tree_view.convert_bin_window_to_widget_coords(area.x, area.y)
self._tree_view.queue_draw_area(x, y, area.width, area.height) self._tree_view.queue_draw_area(x, y, area.width, area.height)
def __enter_notify_event_cb(self, widget, event):
self._mouse_detector.start()
def __leave_notify_event_cb(self, widget, event):
self._mouse_detector.stop()
def __button_release_event_cb(self, widget, event): def __button_release_event_cb(self, widget, event):
x, y = int(event.x), int(event.y) x, y = int(event.x), int(event.y)
path, column, cell_x, cell_y = self._tree_view.get_path_at_pos(x, y) here = self._tree_view.get_path_at_pos(x, y)
if here is None:
return False
path, column, cell_x, cell_y = here
self._path = path self._path = path
self._column = column self._column = column
if event.button == 1: if event.button == 1:
@ -1512,10 +1499,9 @@ class TreeViewInvoker(Invoker):
cellrenderer.emit('clicked', path) cellrenderer.emit('clicked', path)
# So the treeview receives it and knows a drag isn't going on # So the treeview receives it and knows a drag isn't going on
return False return False
if event.button == 3: elif event.button == 3:
# right mouse button # right mouse button
self._mouse_detector.stop() self._ensure_palette_exists()
self._change_palette()
self.notify_right_click(event.x_root, event.y_root) self.notify_right_click(event.x_root, event.y_root)
return True return True
else: else:
@ -1525,15 +1511,10 @@ class TreeViewInvoker(Invoker):
path, column, x_, y_ = self._tree_view.get_path_at_pos(x, y) path, column, x_, y_ = self._tree_view.get_path_at_pos(x, y)
self._path = path self._path = path
self._column = column self._column = column
self._change_palette() self._ensure_palette_exists()
self.notify_right_click(x, y) self.notify_right_click(x, y)
def __mouse_slow_cb(self, widget): def _ensure_palette_exists(self):
self._mouse_detector.stop()
self._change_palette()
self.emit('mouse-enter')
def _change_palette(self):
if hasattr(self._tree_view, 'create_palette'): if hasattr(self._tree_view, 'create_palette'):
self.palette = self._tree_view.create_palette( self.palette = self._tree_view.create_palette(
self._path, self._column) self._path, self._column)