diff options
author | Tomeu Vizoso <tomeu@tomeuvizoso.net> | 2008-04-02 12:43:08 (GMT) |
---|---|---|
committer | Tomeu Vizoso <tomeu@tomeuvizoso.net> | 2008-04-02 12:43:08 (GMT) |
commit | e79aea7e6bb84d5a24c2566592fa17693e042c4b (patch) | |
tree | 009d72ab9c20c140079dc3d7c7cb221d5779a3ba /src/view/home/activitiesring.py | |
parent | ce379c6e75e78b62ad6a45cdc2dd03b32bb0a62d (diff) |
New activities ring.
Diffstat (limited to 'src/view/home/activitiesring.py')
-rw-r--r-- | src/view/home/activitiesring.py | 272 |
1 files changed, 256 insertions, 16 deletions
diff --git a/src/view/home/activitiesring.py b/src/view/home/activitiesring.py index 5967623..4566823 100644 --- a/src/view/home/activitiesring.py +++ b/src/view/home/activitiesring.py @@ -20,6 +20,7 @@ import logging import signal from gettext import gettext as _ import re +import math import gobject import gtk @@ -29,9 +30,14 @@ import dbus from hardware import hardwaremanager from sugar.graphics import style from sugar.graphics.palette import Palette +from sugar.graphics.icon import Icon, CanvasIcon +from sugar.graphics.xocolor import XoColor +from sugar.graphics.menuitem import MenuItem from sugar.profile import get_profile from sugar import env +from sugar import activity +from view.palettes import JournalPalette, CurrentActivityPalette from view.home.MyIcon import MyIcon from model.shellmodel import ShellModel from hardware import schoolserver @@ -42,15 +48,57 @@ class ActivitiesRing(hippo.CanvasBox, hippo.CanvasItem): __gtype_name__ = 'SugarActivitiesRing' def __init__(self, shell): - hippo.CanvasBox.__init__(self, background_color=0xe2e2e2ff) + hippo.CanvasBox.__init__(self, background_color=style.COLOR_WHITE.get_int()) - shell_model = shell.get_model() + self._shell = shell + shell.get_model().connect('notify::state', self._shell_state_changed_cb) self._my_icon = _MyIcon(shell, style.XLARGE_ICON_SIZE) self.append(self._my_icon, hippo.PACK_FIXED) - shell_model.connect('notify::state', - self._shell_state_changed_cb) + self._current_activity = CurrentActivityIcon(shell) + self.append(self._current_activity, hippo.PACK_FIXED) + + self.set_layout(RingLayout()) + + registry = activity.get_registry() + registry.get_activities_async(reply_handler=self._get_activities_cb) + registry.connect('activity-added', self.__activity_added_cb) + registry.connect('activity-removed', self.__activity_removed_cb) + registry.connect('activity-changed', self.__activity_changed_cb) + + def _get_activities_cb(self, activity_list): + for info in activity_list: + if info.favorite and info.bundle_id != "org.laptop.JournalActivity": + self.append(ActivityIcon(self._shell, info)) + + def __activity_added_cb(self, activity_registry, activity_info): + if activity_info.favorite and \ + activity_info.bundle_id != "org.laptop.JournalActivity": + self.append(ActivityIcon(self._shell, activity_info)) + + def _find_activity_icon(self, bundle_id, version): + for icon in self.get_children(): + if isinstance(icon, ActivityIcon) and \ + icon.bundle_id == bundle_id and icon.version == version: + return icon + return None + + def __activity_removed_cb(self, activity_registry, activity_info): + icon = self._find_activity_icon(activity_info.bundle_id, + activity_info.version) + if icon is not None: + self.remove(icon) + + def __activity_changed_cb(self, activity_registry, activity_info): + if activity_info.bundle_id == "org.laptop.JournalActivity": + return + icon = self._find_activity_icon(activity_info.bundle_id, + activity_info.version) + if icon is not None and not activity_info.favorite: + self.remove(icon) + elif icon is None and activity_info.favorite: + self.append(ActivityIcon(self._shell, activity_info)) def _shell_state_changed_cb(self, model, pspec): # FIXME implement this @@ -60,13 +108,194 @@ class ActivitiesRing(hippo.CanvasBox, hippo.CanvasItem): def do_allocate(self, width, height, origin_changed): hippo.CanvasBox.do_allocate(self, width, height, origin_changed) - [icon_width, icon_height] = self._my_icon.get_allocation() - self.set_position(self._my_icon, (width - icon_width) / 2, - (height - icon_height) / 2) + [my_icon_width, my_icon_height] = self._my_icon.get_allocation() + x = (width - my_icon_width) / 2 + y = (height - my_icon_height - style.GRID_CELL_SIZE) / 2 + self.set_position(self._my_icon, x, y) + + [icon_width, icon_height] = self._current_activity.get_allocation() + x = (width - icon_width) / 2 + y = (height + my_icon_height + style.DEFAULT_PADDING - style.GRID_CELL_SIZE) / 2 + self.set_position(self._current_activity, x, y) def enable_xo_palette(self): self._my_icon.enable_palette() +class ActivityIcon(CanvasIcon): + def __init__(self, shell, activity_info): + CanvasIcon.__init__(self, cache=True, file_name=activity_info.icon) + self._shell = shell + self._activity_info = activity_info + self.set_palette(ActivityPalette(shell, activity_info)) + self.connect('hovering-changed', self.__hovering_changed_event_cb) + self.connect('button-release-event', self.__button_release_event_cb) + + self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg() + self.props.fill_color = style.COLOR_TRANSPARENT.get_svg() + + def __hovering_changed_event_cb(self, icon, event): + if event: + self.props.xo_color = get_profile().color + else: + self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg() + self.props.fill_color = style.COLOR_TRANSPARENT.get_svg() + + def __button_release_event_cb(self, icon, event): + self._shell.start_activity(self._activity_info.bundle_id) + + def get_bundle_id(self): + return self._activity_info.bundle_id + bundle_id = property(get_bundle_id, None) + + def get_version(self): + return self._activity_info.version + version = property(get_version, None) + +class ActivityPalette(Palette): + def __init__(self, shell, activity_info): + activity_icon = Icon(file=activity_info.icon, + xo_color=get_profile().color, + icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) + + Palette.__init__(self, None, None, primary_text=activity_info.name, + icon=activity_icon) + + self._shell = shell + self._activity_info = activity_info + + menu_item = MenuItem(_('Start'), 'activity-start') + menu_item.connect('activate', self.__start_activate_cb) + self.menu.append(menu_item) + menu_item.show() + + menu_item = MenuItem(_('Start with'), 'activity-start') + menu_item.props.sensitive = False + #menu_item.connect('activate', self.__start_with_activate_cb) + self.menu.append(menu_item) + menu_item.show() + + def __start_activate_cb(self, menu_item): + self._shell.start_activity(self._activity_info.bundle_id) + +class CurrentActivityIcon(CanvasIcon, hippo.CanvasItem): + def __init__(self, shell): + CanvasIcon.__init__(self, cache=True) + self._home_model = shell.get_model().get_home() + + if self._home_model.get_pending_activity() is not None: + self._update(self._home_model.get_pending_activity()) + + self._home_model.connect('pending-activity-changed', + self.__pending_activity_changed_cb) + + self.connect('button-release-event', self.__button_release_event_cb) + + def __button_release_event_cb(self, icon, event): + self._home_model.get_pending_activity().get_window().activate(1) + + def _update(self, home_activity): + _logger.debug('CurrentActivityIcon._update') + self.props.file_name = home_activity.get_icon_path() + self.props.xo_color = home_activity.get_icon_color() + self.props.size = style.STANDARD_ICON_SIZE + + if home_activity.get_type() == "org.laptop.JournalActivity": + palette = JournalPalette(self, home_activity) + else: + palette = CurrentActivityPalette(self, home_activity) + self.set_palette(palette) + + def __pending_activity_changed_cb(self, home_model, home_activity): + self._update(home_activity) + +class RingLayout(gobject.GObject, hippo.CanvasLayout): + __gtype_name__ = 'SugarRingLayout' + def __init__(self): + gobject.GObject.__init__(self) + self._box = None + + def do_set_box(self, box): + self._box = box + + def do_get_height_request(self, for_width): + return 0, gtk.gdk.screen_height() - style.GRID_CELL_SIZE + + def do_get_width_request(self): + return 0, gtk.gdk.screen_width() + + def _calculate_radius_and_icon_size(self, children_count): + minimum_radius = style.XLARGE_ICON_SIZE / 2 + style.DEFAULT_SPACING + \ + style.STANDARD_ICON_SIZE * 2 + maximum_radius = (gtk.gdk.screen_height() - style.GRID_CELL_SIZE) / 2 - \ + style.STANDARD_ICON_SIZE - style.DEFAULT_SPACING + angle = 2 * math.pi / children_count + + _logger.debug('minimum_radius %r maximum_radius %r angle %r' % \ + (minimum_radius, maximum_radius, angle)) + + # what's the radius required without downscaling? + distance = style.STANDARD_ICON_SIZE + style.DEFAULT_SPACING + icon_size = style.STANDARD_ICON_SIZE + + if children_count == 1: + radius = 0 + else: + radius = math.sqrt(distance ** 2 / + (math.sin(angle) ** 2 + (math.cos(angle) - 1) ** 2)) + + _logger.debug('radius 1 %r' % radius) + + if radius < minimum_radius: + # we can upscale, if we want + icon_size += style.STANDARD_ICON_SIZE * \ + (0.5 * (minimum_radius - radius)/minimum_radius) + radius = minimum_radius + elif radius > maximum_radius: + radius = maximum_radius + # need to downscale. what's the icon size required? + distance = math.sqrt((radius * math.sin(angle)) ** 2 + \ + (radius * (math.cos(angle) - 1)) ** 2) + icon_size = distance - style.DEFAULT_SPACING + + _logger.debug('radius 2 %r icon_size %r' % (radius, icon_size)) + + return radius, icon_size + + def _calculate_position(self, radius, icon_size, index, children_count): + width, height = self._box.get_allocation() + angle = index * (2 * math.pi / children_count) - math.pi/2 + x = radius * math.cos(angle) + (width - icon_size) / 2 + y = radius * math.sin(angle) + (height - icon_size - style.GRID_CELL_SIZE) / 2 + return x, y + + def do_allocate(self, x, y, width, height, req_width, req_height, + origin_changed): + _logger.debug('RingLayout.do_allocate: %r %r %r %r %r %r %r' % (x, y, + width, height, req_width, req_height, origin_changed)) + + children = self._box.get_layout_children() + if not children: + return + + radius, icon_size = self._calculate_radius_and_icon_size(len(children)) + + for n in range(len(children)): + child = children[n] + # TODO: We get here a glib warning and I don't know why. + child.item.props.size = icon_size + + x, y = self._calculate_position(radius, icon_size, n, len(children)) + + # We need to always get requests to not confuse hippo + min_w, child_width = child.get_width_request() + min_h, child_height = child.get_height_request(child_width) + + child.allocate(int(x), + int(y), + child_width, + child_height, + origin_changed) + class _MyIcon(MyIcon): def __init__(self, shell, scale): MyIcon.__init__(self, scale) @@ -76,29 +305,40 @@ class _MyIcon(MyIcon): self._profile = get_profile() def enable_palette(self): - palette = Palette(self._profile.nick_name) + palette_icon = Icon(icon_name='computer-xo', + icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR, + xo_color=self._profile.color) + palette = Palette(self._profile.nick_name, + #secondary_text='Sample secondary label', + icon=palette_icon) + + item = MenuItem(_('About this XO')) + + icon = Icon(icon_name='computer-xo', icon_size=gtk.ICON_SIZE_MENU, + xo_color=self._profile.color) + item.set_image(icon) + icon.show() + + item.connect('activate', self._about_activate_cb) + palette.menu.append(item) + item.show() - item = gtk.MenuItem(_('Reboot')) + item = MenuItem(_('Restart'), 'system-restart') item.connect('activate', self._reboot_activate_cb) palette.menu.append(item) item.show() - item = gtk.MenuItem(_('Shutdown')) + item = MenuItem(_('Shutdown'), 'system-shutdown') item.connect('activate', self._shutdown_activate_cb) palette.menu.append(item) item.show() if not self._profile.is_registered(): - item = gtk.MenuItem(_('Register')) + item = MenuItem(_('Register'), 'media-record') item.connect('activate', self._register_activate_cb) palette.menu.append(item) item.show() - item = gtk.MenuItem(_('About this XO')) - item.connect('activate', self._about_activate_cb) - palette.menu.append(item) - item.show() - self.set_palette(palette) def _reboot_activate_cb(self, menuitem): |