From fe69dec4ad5b6d117006f9038afad9e4c973814c Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Thu, 14 Sep 2006 13:03:11 +0200 Subject: [PATCH] Implement popup menu for friends --- shell/BuddyPopup.py | 93 ++++++++++++++++++++++++++++++++++++-- shell/home/FriendsGroup.py | 46 +++++++++++++++---- sugar/canvas/Grid.py | 11 ++++- sugar/canvas/IconItem.py | 23 +++++++++- 4 files changed, 158 insertions(+), 15 deletions(-) diff --git a/shell/BuddyPopup.py b/shell/BuddyPopup.py index fac2d27a..bba9bbe8 100644 --- a/shell/BuddyPopup.py +++ b/shell/BuddyPopup.py @@ -1,10 +1,97 @@ import gtk +import goocanvas from sugar.canvas.CanvasBox import CanvasBox +from sugar.canvas.IconItem import IconItem class BuddyPopup(gtk.Window): - def __init__(self, grid) + def __init__(self, shell, grid, friend): gtk.Window.__init__(self, gtk.WINDOW_POPUP) - box = CanvasBox(grid) - + self._shell = shell + self._friend = friend + self._hover = False + self._popdown_on_leave = False + self._width = 20 + self._height = 12 + + canvas = goocanvas.CanvasView() + self.add(canvas) + canvas.show() + + grid.set_constraints(canvas, 0, 0, self._width, self._height) + + model = goocanvas.CanvasModelSimple() + root = model.get_root_item() + + color = friend.get_color() + rect = goocanvas.Rect(fill_color=color.get_fill_color(), + stroke_color=color.get_stroke_color(), + line_width=3) + grid.set_constraints(rect, 0, 0, self._width, self._height) + root.add_child(rect) + + text = goocanvas.Text(text=friend.get_name(), font="Sans bold 14", + fill_color='black', anchor = gtk.ANCHOR_SW) + grid.set_constraints(text, 1, 2, self._width, self._height) + root.add_child(text) + + separator = goocanvas.Path(data='M 15 0 L 185 0', line_width=3, + fill_color='black') + grid.set_constraints(separator, 0, 3) + root.add_child(separator) + + box = CanvasBox(grid, CanvasBox.HORIZONTAL, 1) + grid.set_constraints(box, 0, 3) + + icon = IconItem(icon_name='stock-make-friend') + icon.connect('clicked', self._make_friend_clicked_cb) + box.set_constraints(icon, 3, 3) + box.add_child(icon) + + icon = IconItem(icon_name='stock-chat') + box.set_constraints(icon, 3, 3) + box.add_child(icon) + + icon = IconItem(icon_name='stock-invite') + icon.connect('clicked', self._invite_clicked_cb) + box.set_constraints(icon, 3, 3) + box.add_child(icon) + + root.add_child(box) + + canvas.set_model(model) + + self.connect('enter-notify-event', self._enter_notify_event_cb) + self.connect('leave-notify-event', self._leave_notify_event_cb) + + def _invite_clicked_cb(self, icon): + activity = self._shell.get_current_activity() + buddy = self._friend.get_buddy() + if buddy != None: + activity.invite(buddy) + else: + print 'Friend not online' + + def _make_friend_clicked_cb(self, icon): + pass + + def _enter_notify_event_cb(self, widget, event): + self._hover = True + + def _leave_notify_event_cb(self, widget, event): + self._hover = False + if self._popdown_on_leave: + self.popdown() + + def popdown(self): + if not self._hover: + self.destroy() + else: + self._popdown_on_leave = True + + def get_width(self): + return self._width + + def get_height(self): + return self._height diff --git a/shell/home/FriendsGroup.py b/shell/home/FriendsGroup.py index 170f1442..2ff9a032 100644 --- a/shell/home/FriendsGroup.py +++ b/shell/home/FriendsGroup.py @@ -5,6 +5,8 @@ import goocanvas from sugar.canvas.IconItem import IconItem from home.IconLayout import IconLayout from home.MyIcon import MyIcon +from BuddyPopup import BuddyPopup +from sugar.canvas.Grid import Grid class FriendIcon(IconItem): def __init__(self, friend): @@ -31,19 +33,45 @@ class FriendsGroup(goocanvas.Group): for friend in self._friends: self.add_friend(friend) - friends.connect('friend-added', self.__friend_added_cb) - - def __friend_clicked_cb(self, icon): - activity = self._shell.get_current_activity() - buddy = icon.get_friend().get_buddy() - if buddy != None: - activity.invite(buddy) + friends.connect('friend-added', self._friend_added_cb) def add_friend(self, friend): icon = FriendIcon(friend) - icon.connect('clicked', self.__friend_clicked_cb) + + icon.connect('popup', self._friend_popup_cb) + icon.connect('popdown', self._friend_popdown_cb) + self.add_child(icon) self._icon_layout.add_icon(icon) - def __friend_added_cb(self, data_model, friend): + def _friend_added_cb(self, data_model, friend): self.add_friend(friend) + + def _friend_popup_cb(self, icon, x1, y1, x2, y2): + grid = Grid() + + self._popup = BuddyPopup(self._shell, grid, icon.get_friend()) + + [grid_x1, grid_y1] = grid.convert_from_screen(x1, y1) + [grid_x2, grid_y2] = grid.convert_from_screen(x2, y2) + + if grid_x2 + self._popup.get_width() + 1 > Grid.ROWS: + grid_x = grid_x1 - self._popup.get_width() + 1 + else: + grid_x = grid_x2 - 1 + + grid_y = grid_y1 + + if grid_y < 0: + grid_y = 0 + if grid_y + self._popup.get_width() > Grid.ROWS: + grid_y = Grid.ROWS - self._popup.get_width() + + grid.set_constraints(self._popup, grid_x, grid_y, + self._popup.get_width(), self._popup.get_height()) + + self._popup.show() + + def _friend_popdown_cb(self, friend): + self._popup.popdown() + self._popup = None diff --git a/sugar/canvas/Grid.py b/sugar/canvas/Grid.py index 59d2695e..8d54c79d 100644 --- a/sugar/canvas/Grid.py +++ b/sugar/canvas/Grid.py @@ -4,6 +4,11 @@ import cairo class Grid: COLS = 80.0 + ROWS = 60.0 + + def convert_from_screen(self, x, y): + factor = Grid.COLS / gtk.gdk.screen_width() + return [int(x * factor), int(y * factor)] def set_constraints(self, component, x, y, width=-1, height=-1): if isinstance(component, gtk.Window): @@ -26,12 +31,16 @@ class Grid: matrix.translate(x * scale, y * scale) item.set_transform(matrix) + # FIXME This is really hacky if width > 0 and height > 0: try: item.props.width = width * scale item.props.height = height * scale except: - item.props.size = width * scale + try: + item.props.size = width * scale + except: + pass def _layout_canvas(self, canvas, x, y, width, height): scale = 1200 / Grid.COLS diff --git a/sugar/canvas/IconItem.py b/sugar/canvas/IconItem.py index e0c3b839..8405ba31 100644 --- a/sugar/canvas/IconItem.py +++ b/sugar/canvas/IconItem.py @@ -169,6 +169,10 @@ class IconItem(goocanvas.ItemSimple, goocanvas.Item): __gsignals__ = { 'clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), + 'popup': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([int, int, int, int])), + 'popdown': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])), } __gproperties__ = { @@ -227,8 +231,23 @@ class IconItem(goocanvas.ItemSimple, goocanvas.Item): def do_create_view(self, canvas, parent_view): view = IconView(canvas, parent_view, self) - view.connect('button-press-event', self.__button_press_cb) + view.connect('button-press-event', self._button_press_cb) + view.connect('enter-notify-event', self._enter_notify_event_cb, canvas) + view.connect('leave-notify-event', self._leave_notify_event_cb) return view - def __button_press_cb(self, view, target, event): + def _button_press_cb(self, view, target, event): self.emit('clicked') + + def _enter_notify_event_cb(self, view, target, event, canvas): + [x1, y1] = canvas.convert_to_pixels(view.get_bounds().x1, + view.get_bounds().y1) + [x2, y2] = canvas.convert_to_pixels(view.get_bounds().x2, + view.get_bounds().y2) + self.emit('popup', int(x1), int(y1), int(x2), int(y2)) + + def _popdown(self): + self.emit('popdown') + + def _leave_notify_event_cb(self, view, target, event): + gobject.timeout_add(1000, self._popdown)