Added Rollover control.

This commit is contained in:
Tomeu Vizoso 2007-02-20 16:38:25 +01:00
parent 5f65056d78
commit f3cf928f31
8 changed files with 272 additions and 65 deletions

View File

@ -21,6 +21,7 @@ import wnck
from view.home.HomeWindow import HomeWindow
from sugar.presence import PresenceService
from sugar.graphics.rollovercontext import RolloverContext
from view.ActivityHost import ActivityHost
from sugar.activity import ActivityFactory
from view.frame.frame import Frame
@ -54,6 +55,8 @@ class Shell(gobject.GObject):
home_model.connect('active-activity-changed',
self._active_activity_changed_cb)
self._rollover_context = RolloverContext()
self._frame = Frame(self)
self._frame.show_and_hide(3)
@ -99,6 +102,9 @@ class Shell(gobject.GObject):
def get_frame(self):
return self._frame
def get_rollover_context(self):
return self._rollover_context
def _join_success_cb(self, handler, activity, activity_ps, activity_id, activity_type):
logging.debug("Joining activity %s (%s)" % (activity_id, activity_type))
activity.join(activity_ps.object_path())

View File

@ -19,24 +19,16 @@ import logging
from sugar.graphics import units
from sugar.graphics.iconcolor import IconColor
from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics.button import Button
from sugar.presence import PresenceService
from sugar import profile
class ActivityItem(CanvasIcon):
class ActivityButton(Button):
def __init__(self, activity):
icon_name = activity.get_icon()
CanvasIcon.__init__(self, icon_name=icon_name,
box_width=units.grid_to_pixels(1),
box_height=units.grid_to_pixels(1),
color=IconColor('white'))
Button.__init__(self, icon_name=activity.get_icon())
self._activity = activity
self._normal_color = self.get_property('color')
self._prelight_color = profile.get_color()
self.connect('motion-notify-event', self._mouse_motion_event_cb)
def _mouse_motion_event_cb(self, item, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
self.set_property('color', self._prelight_color)
@ -46,14 +38,11 @@ class ActivityItem(CanvasIcon):
def get_bundle_id(self):
return self._activity.get_service_name()
class InviteItem(CanvasIcon):
class InviteButton(Button):
def __init__(self, activity, invite):
CanvasIcon.__init__(self, icon_name=activity.get_icon(),
box_width=units.grid_to_pixels(1),
box_height=units.grid_to_pixels(1))
Button.__init__(self, icon_name=activity.get_icon())
self.props.color = activity.get_color()
self._invite = invite
def get_activity_id(self):
@ -104,7 +93,7 @@ class ActivitiesBox(hippo.CanvasBox):
self.add_activity(bundle)
def add_activity(self, activity):
item = ActivityItem(activity)
item = ActivityButton(activity)
item.connect('activated', self._activity_clicked_cb)
self.append(item, 0)
@ -112,7 +101,7 @@ class ActivitiesBox(hippo.CanvasBox):
mesh = self._shell_model.get_mesh()
activity = mesh.get_activity(invite.get_activity_id())
if activity:
item = InviteItem(activity, invite)
item = InviteButton(activity, invite)
item.connect('activated', self._invite_clicked_cb)
self.append(item, 0)

View File

@ -15,65 +15,62 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging
from gettext import gettext as _
import hippo
from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics.rollover import Rollover
from sugar.graphics.menuicon import MenuIcon
from sugar.graphics.menu import Menu
from sugar.graphics.iconcolor import IconColor
from sugar.graphics.button import Button
import sugar
class ActivityMenu(Menu):
class ActivityRollover(Rollover):
ACTION_SHARE = 1
ACTION_CLOSE = 2
def __init__(self, activity_model):
Menu.__init__(self, activity_model.get_title())
Rollover.__init__(self, activity_model.get_title())
if not activity_model.get_shared():
self._add_mesh_action()
self.add_item(ActivityRollover.ACTION_SHARE, _('Share'),
'theme:stock-share-mesh')
self._add_close_action()
self.add_item(ActivityRollover.ACTION_CLOSE, _('Close'),
'theme:stock-close')
def _add_mesh_action(self):
icon = CanvasIcon(icon_name='theme:stock-share-mesh',
color=IconColor('#ffffff,#000000'))
self.add_action(icon, ActivityMenu.ACTION_SHARE)
def _add_close_action(self):
icon = CanvasIcon(icon_name='theme:stock-close',
color=IconColor('#ffffff,#000000'))
self.add_action(icon, ActivityMenu.ACTION_CLOSE)
class ActivityIcon(MenuIcon):
def __init__(self, shell, menu_shell, activity_model):
class ActivityButton(Button):
def __init__(self, shell, activity_model):
self._shell = shell
self._activity_model = activity_model
icon_name = self._activity_model.get_icon_name()
icon_color = self._activity_model.get_icon_color()
MenuIcon.__init__(self, menu_shell, icon_name=icon_name,
color=icon_color)
Button.__init__(self, icon_name=icon_name, color=icon_color)
def create_menu(self):
menu = ActivityMenu(self._activity_model)
menu.connect('action', self._action_cb)
return menu
def _action_cb(self, menu, action):
self.popdown()
def get_rollover(self):
rollover = ActivityRollover(self._activity_model)
#rollover.connect('action', self._action_cb)
return rollover
def get_rollover_context(self):
return self._shell.get_rollover_context()
def _action_cb(self, menu, data):
[action_id, label] = data
# TODO: Wouldn't be better to share/close the activity associated with
# this button instead of asking for the current activity?
activity = self._shell.get_current_activity()
if activity == None:
logging.error('No active activity.')
return
if action == ActivityMenu.ACTION_SHARE:
if action_id == ActivityRollover.ACTION_SHARE:
activity.share()
if action == ActivityMenu.ACTION_CLOSE:
elif action_id == ActivityRollover.ACTION_CLOSE:
activity.close()
class ZoomBox(hippo.CanvasBox):
@ -110,7 +107,7 @@ class ZoomBox(hippo.CanvasBox):
self.remove(self._activity_icon)
if home_activity:
icon = ActivityIcon(self._shell, self._menu_shell, home_activity)
icon = ActivityButton(self._shell, home_activity)
self.append(icon)
self._activity_icon = icon
else:

View File

@ -70,6 +70,12 @@ class Frame:
shell.get_model().connect('notify::state',
self._shell_state_changed_cb)
rollover_context = shell.get_rollover_context()
rollover_context.connect('activated',
self._rollover_context_activated_cb)
rollover_context.connect('deactivated',
self._rollover_context_deactivated_cb)
def _create_top_panel(self):
panel = self._create_panel(hippo.ORIENTATION_HORIZONTAL)
menu_shell = panel.get_menu_shell()
@ -165,6 +171,13 @@ class Frame:
if self._mode != Frame.STICKY and not self._hover_frame:
self._timeline.play('before_slide_out', 'slide_out')
def _rollover_context_activated_cb(self, rollover_context):
self._timeline.goto('slide_in', True)
def _rollover_context_deactivated_cb(self, rollover_context):
if self._mode != Frame.STICKY and not self._hover_frame:
self._timeline.play('before_slide_out', 'slide_out')
def _enter_notify_cb(self, window, event):
self._enter_notify()
logging.debug('Frame._enter_notify_cb ' + str(self._mode))
@ -193,6 +206,7 @@ class Frame:
def _leave_notify(self, panel):
self._hover_frame = False
if not panel.get_menu_shell().is_active() and \
not self._shell.get_rollover_context().is_active() and \
(self._mode == Frame.HIDE_ON_LEAVE or \
self._mode == Frame.AUTOMATIC):
self._timeline.play('before_slide_out', 'slide_out')

View File

@ -23,6 +23,7 @@ import hippo
from canvasicon import CanvasIcon
from iconcolor import IconColor
from sugar.graphics import units
from sugar.graphics.timeline import Timeline
from sugar import profile
STANDARD_SIZE = 0
@ -41,15 +42,20 @@ class Button(hippo.CanvasBox):
gobject.PARAM_READWRITE)
}
def __init__(self, icon_name):
self._normal_color = IconColor('white')
def __init__(self, icon_name, color=None):
if color:
self._normal_color = color
else:
self._normal_color = IconColor('white')
self._prelight_color = profile.get_color()
self._inactive_color = IconColor('#808080,#424242')
self._active = True
self._rollover = None
self._hover_rollover = False
self._icon = CanvasIcon(icon_name=icon_name, cache=True,
color=self._normal_color)
self._connect_signals(self._icon)
hippo.CanvasBox.__init__(self)
@ -57,6 +63,81 @@ class Button(hippo.CanvasBox):
self.append(self._icon, hippo.PACK_EXPAND)
self._timeline = Timeline(self)
self._timeline.add_tag('popup', 6, 6)
self._timeline.add_tag('before_popdown', 7, 7)
self._timeline.add_tag('popdown', 8, 8)
self.connect('motion-notify-event', self._motion_notify_event_cb)
self.connect('button-press-event', self._button_press_event_cb)
def get_rollover(self):
return self._rollover
def get_rollover_context(self):
return None
def do_popup(self, current, n_frames):
if self._rollover:
return
rollover = self.get_rollover()
if not rollover:
return
rollover_context = self.get_rollover_context()
if rollover_context:
rollover_context.popped_up(rollover)
rollover.connect('motion-notify-event',
self._rollover_motion_notify_event_cb)
rollover.connect('action-completed',
self._rollover_action_completed_cb)
context = self._icon.get_context()
#[x, y] = context.translate_to_screen(self._icon)
[x, y] = context.translate_to_widget(self._icon)
# TODO: Any better place to do this?
rollover.props.box_width = max(rollover.props.box_width,
self.get_width_request())
[width, height] = self._icon.get_allocation()
rollover.popup(x, y + height)
self._rollover = rollover
def do_popdown(self, current, frame):
if self._rollover:
self._rollover.popdown()
rollover_context = self.get_rollover_context()
if rollover_context:
rollover_context.popped_down(self._rollover)
self._rollover = None
def popdown(self):
self._timeline.play('popdown', 'popdown')
def _motion_notify_event_cb(self, button, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
self._timeline.play(None, 'popup')
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
if not self._hover_rollover:
self._timeline.play('before_popdown', 'popdown')
def _rollover_motion_notify_event_cb(self, rollover, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
self._hover_rollover = True
self._timeline.play('popup', 'popup')
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
self._hover_rollover = False
self._timeline.play('popdown', 'popdown')
def _rollover_action_completed_cb(self, rollover):
self.popdown()
def _set_size(self, size):
if size == SMALL_SIZE:
self.props.box_width = -1
@ -93,17 +174,6 @@ class Button(hippo.CanvasBox):
else:
return hippo.CanvasBox.get_property(self, pspec)
def _connect_signals(self, item):
item.connect('button-release-event', self._button_release_event_cb)
# TODO: Prelighting is disabled by now. Need to figure how we want it to behave.
#item.connect('motion-notify-event', self._motion_notify_event_cb)
def _button_release_event_cb(self, widget, event):
def _button_press_event_cb(self, widget, event):
if self._active:
self.emit_activated()
def _motion_notify_event_cb(self, widget, event):
if self._active and event.detail == hippo.MOTION_DETAIL_ENTER:
self._icon.props.color = self._prelight_color
elif self._active and event.detail == hippo.MOTION_DETAIL_LEAVE:
self._icon.props.color = self._normal_color

View File

@ -60,7 +60,7 @@ class Menu(hippo.CanvasBox, hippo.CanvasItem):
canvas_text.props.font_desc = font.DEFAULT.get_pango_desc()
box.append(canvas_text)
box.connect('button-press-event', self._button_press_event_cb,
box.connect('button-press-event', self._item_button_press_event_cb,
[action_id, label])
self.append(box)
@ -82,7 +82,7 @@ class Menu(hippo.CanvasBox, hippo.CanvasItem):
self._window.destroy()
self._window = None
def _button_press_event_cb(self, item, event, data):
def _item_button_press_event_cb(self, item, event, data):
self.emit('action', data)
self.hide()
@ -152,8 +152,11 @@ class OptionMenu(hippo.CanvasBox, hippo.CanvasItem):
context = self._round_box.get_context()
#[x, y] = context.translate_to_screen(self._round_box)
[x, y] = context.translate_to_widget(self._round_box)
[width, height] = self._round_box.get_allocation()
# TODO: Any better place to do this?
self._menu.props.box_width = self.get_width_request()
[width, height] = self._round_box.get_allocation()
self._menu.show(x, y + height)
def _menu_action_cb(self, menu, data):

View File

@ -0,0 +1,84 @@
# Copyright (C) 2007, One Laptop Per Child
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import sys
import logging
import gobject
import gtk
import hippo
from sugar.graphics import style
from sugar.graphics.roundbox import RoundBox
from sugar.graphics import button
from sugar.graphics import color
from sugar.graphics import font
from sugar.graphics.canvasicon import CanvasIcon
class Rollover(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'SugarRollover'
__gsignals__ = {
'action-completed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
}
def __init__(self, title):
hippo.CanvasBox.__init__(self)
self.props.background_color = color.MENU_BACKGROUND.get_int()
self.props.border_color = color.MENU_BORDER.get_int()
#TODO: how we should specify the border thickness?
self.props.border = style.separator_thickness
self._window = None
def add_item(self, action_id, label, icon_name=None, icon_color=None):
box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL)
box.props.padding = 5
box.props.spacing = 5
if icon_name:
icon = CanvasIcon(icon_name=icon_name, scale=style.small_icon_scale)
if icon_color:
icon.props.color = icon_color
box.append(icon)
canvas_text = hippo.CanvasText()
canvas_text.props.text = label
canvas_text.props.color = color.LABEL_TEXT.get_int()
canvas_text.props.font_desc = font.DEFAULT.get_pango_desc()
box.append(canvas_text)
box.connect('button-press-event', self._item_button_press_event_cb)
self.append(box)
def add_separator(self):
box = hippo.CanvasBox()
box.props.background_color = color.MENU_SEPARATOR.get_int()
box.props.box_height = style.separator_thickness
self.append(box)
def popup(self, x, y):
if not self._window:
self._window = hippo.CanvasWindow(gtk.WINDOW_POPUP)
self._window.move(x, y)
self._window.set_root(self)
self._window.show()
def popdown(self):
if self._window:
self._window.destroy()
self._window = None
def _item_button_press_event_cb(self, item, event):
self.emit('action-completed')

View File

@ -0,0 +1,44 @@
# Copyright (C) 2007, One Laptop Per Child
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import gobject
import hippo
class RolloverContext(gobject.GObject):
__gtype_name__ = 'SugarRolloverContext'
__gsignals__ = {
'activated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'deactivated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
}
def __init__(self):
self._active_control = None
gobject.GObject.__init__(self)
def popped_up(self, control):
if self._active_control:
self._active_control.popdown()
self._active_control = control
self.emit('activated')
def popped_down(self, control):
if self._active_control == control:
self._active_control = None
self.emit('deactivated')
def is_active(self):
return self._active_control != None