Attached,with launchbox.py included.

- Eben

On Sun, May 18, 2008 at 6:50 AM, Tomeu Vizoso <[EMAIL PROTECTED]> wrote:
> On Thu, May 15, 2008 at 10:23 PM, Eben Eliason <[EMAIL PROTECTED]> wrote:
>> On Thu, May 15, 2008 at 4:16 PM, Marco Pesenti Gritti
>> <[EMAIL PROTECTED]> wrote:
>>> On Thu, May 15, 2008 at 10:03 PM, Eben Eliason <[EMAIL PROTECTED]> wrote:
>>>> how do we get the patch into the rpm without actually pushing the
>>>> changes to git master?  In any case, I know little about how any of
>>>> these steps work. What does your suggestion imply I need to do myself
>>>> to make this happen?
>>>
>>> Nope, but you will need someone to make an rpm for you in any case.
>>
>> OK, so can I be off the hook on this, and assume that you or someone
>> else will apply the patch and make the rpm?  It would be great to see
>> it in a build before the weekend so we can make sure it operates well
>> enough before the demos on Tuesday.
>>
>>> Would you actually prefer to run it only on a few specific laptops? I
>>> was thinking that developers community feedback (through joyride)
>>> would be also valuable here.
>>
>> No, I agree that it would be better to have more people try it.
>
> Hi Eben,
>
> I think that the last patch doesn't include the launchbox.py file. Can
> you make a new one with this file? I intend to do the rpms today.
>
> Regards,
>
> Tomeu
>
From 43804b1eb465e41ba7f94a9caddea510a3d6825b Mon Sep 17 00:00:00 2001
From: Eben Eliason <[EMAIL PROTECTED]>
Date: Sat, 10 May 2008 15:15:48 -0400
Subject: [PATCH] New activity launch feedback

This is a first pass which provides a mostly complete
demo of the new activity launching feedback design.  It
also greatly cleans up the code, both eliminating the
now unused "pending activity" throughout, and re-factoring
the signals regarding activity launch (and failure) between
the model and the view.

Future changes need to be made to fully support the new
approach within the view itself, rather than tiptoeing
around the model to present the desired effect.
---
 src/model/homemodel.py           |   62 ++++++++++-----------------
 src/model/shellmodel.py          |    1 +
 src/shellservice.py              |    4 +-
 src/view/Shell.py                |   47 +++++++++++----------
 src/view/frame/activitiestray.py |   33 ++++++++------
 src/view/frame/friendstray.py    |    8 ++--
 src/view/frame/zoomtoolbar.py    |    4 +-
 src/view/home/HomeWindow.py      |   23 +++++++++-
 src/view/home/activitieslist.py  |    6 ++-
 src/view/home/activitiesring.py  |   15 ++++---
 src/view/home/launchbox.py       |   86 ++++++++++++++++++++++++++++++++++++++
 11 files changed, 196 insertions(+), 93 deletions(-)
 create mode 100644 src/view/home/launchbox.py

diff --git a/src/model/homemodel.py b/src/model/homemodel.py
index 5538f84..3601cd8 100644
--- a/src/model/homemodel.py
+++ b/src/model/homemodel.py
@@ -42,7 +42,13 @@ class HomeModel(gobject.GObject):
         'activity-added':          (gobject.SIGNAL_RUN_FIRST,
                                     gobject.TYPE_NONE, 
                                    ([gobject.TYPE_PYOBJECT])),
-        'activity-started':         (gobject.SIGNAL_RUN_FIRST,
+        'activity-started':        (gobject.SIGNAL_RUN_FIRST,
+                                    gobject.TYPE_NONE, 
+                                   ([gobject.TYPE_PYOBJECT])),
+        'activity-launched':       (gobject.SIGNAL_RUN_FIRST,
+                                    gobject.TYPE_NONE, 
+                                   ([gobject.TYPE_PYOBJECT])),
+        'activity-launch-failed':  (gobject.SIGNAL_RUN_FIRST,
                                     gobject.TYPE_NONE, 
                                    ([gobject.TYPE_PYOBJECT])),
         'activity-removed':        (gobject.SIGNAL_RUN_FIRST,
@@ -51,9 +57,6 @@ class HomeModel(gobject.GObject):
         'active-activity-changed': (gobject.SIGNAL_RUN_FIRST,
                                     gobject.TYPE_NONE,
                                    ([gobject.TYPE_PYOBJECT])),
-        'pending-activity-changed': (gobject.SIGNAL_RUN_FIRST,
-                                     gobject.TYPE_NONE,
-                                     ([gobject.TYPE_PYOBJECT]))
     }
     
     def __init__(self):
@@ -61,7 +64,6 @@ class HomeModel(gobject.GObject):
 
         self._activities = []
         self._active_activity = None
-        self._pending_activity = None
 
         screen = wnck.screen_get_default()
         screen.connect('window-opened', self._window_opened_cb)
@@ -78,7 +80,7 @@ class HomeModel(gobject.GObject):
 
     def get_previous_activity(self):
         activities = self._get_activities_with_window()
-        i = activities.index(self._pending_activity)
+        i = activities.index(self._active_activity)
         if len(activities) == 0:
             return None
         elif i - 1 >= 0:
@@ -88,7 +90,7 @@ class HomeModel(gobject.GObject):
 
     def get_next_activity(self):
         activities = self._get_activities_with_window()
-        i = activities.index(self._pending_activity)
+        i = activities.index(self._active_activity)
         if len(activities) == 0:
             return None
         elif i + 1 < len(activities):
@@ -96,25 +98,6 @@ class HomeModel(gobject.GObject):
         else:
             return activities[0]
 
-    def get_pending_activity(self):
-        """Returns the activity that would be seen in the Activity zoom level
-
-        In the Home (or Neighborhood or Groups) zoom level, this
-        indicates the activity that would become active if the user
-        switched to the Activity zoom level. (In the Activity zoom
-        level, this just returns the currently-active activity.)
-        Unlike get_active_activity(), this never returns None as long
-        as there is any activity running.
-        """
-        return self._pending_activity
-
-    def _set_pending_activity(self, home_activity):
-        if self._pending_activity == home_activity:
-            return
-
-        self._pending_activity = home_activity
-        self.emit('pending-activity-changed', self._pending_activity)
-
     def get_active_activity(self):
         """Returns the activity that the user is currently working in
 
@@ -183,8 +166,8 @@ class HomeModel(gobject.GObject):
             home_activity.props.launching = False
             self.emit('activity-started', home_activity)
 
-            if self._pending_activity is None:
-                self._set_pending_activity(home_activity)
+            if self._active_activity is None:
+                self._set_active_activity(home_activity)
 
     def _window_closed_cb(self, screen, window):
         if window.get_window_type() == wnck.WINDOW_NORMAL:
@@ -219,7 +202,6 @@ class HomeModel(gobject.GObject):
 
         act = self._get_activity_by_xid(window.get_xid())
         if act is not None:
-            self._set_pending_activity(act)
             self._set_active_activity(act)
 
     def _add_activity(self, home_activity):
@@ -228,20 +210,17 @@ class HomeModel(gobject.GObject):
 
     def _remove_activity(self, home_activity):
         if home_activity == self._active_activity:
-            self._set_active_activity(None)
-
-        if home_activity == self._pending_activity:
-            # Figure out the new _pending_activity
+            # Figure out the new _active_activity
             windows = wnck.screen_get_default().get_windows_stacked()
             windows.reverse()
             for window in windows:
                 new_activity = self._get_activity_by_xid(window.get_xid())
                 if new_activity is not None:
-                    self._set_pending_activity(new_activity)
+                    self._set_active_activity(new_activity)
                     break
             else:
                 logging.error('No activities are running')
-                self._set_pending_activity(None)
+                self._set_active_activity(None)
 
         self.emit('activity-removed', home_activity)
         self._activities.remove(home_activity)
@@ -253,13 +232,13 @@ class HomeModel(gobject.GObject):
         else:
             logging.error('Model for window %d does not exist.' % xid)
 
-    def notify_activity_launch(self, activity_id, service_name):
+    def notify_activity_launch(self, bundle_id, activity_id):
         registry = activity.get_registry()
-        activity_info = registry.get_activity(service_name)
+        activity_info = registry.get_activity(bundle_id)
         if not activity_info:
             raise ValueError("Activity service name '%s'" \
                              " was not found in the bundle registry."
-                             % service_name)
+                             % bundle_id)
         home_activity = HomeActivity(activity_info, activity_id)
         home_activity.props.launching = True
         self._add_activity(home_activity)
@@ -268,7 +247,9 @@ class HomeModel(gobject.GObject):
         # Now just check whether an activity has a window after ~90sec
         gobject.timeout_add(90000, self._check_activity_launched, activity_id)
 
-    def notify_activity_launch_failed(self, activity_id):
+        self.emit('activity-launched', home_activity)
+
+    def notify_launch_failure(self, activity_id):
         home_activity = self._get_activity_by_id(activity_id)
         if home_activity:
             logging.debug("Activity %s (%s) launch failed" % \
@@ -278,11 +259,12 @@ class HomeModel(gobject.GObject):
         else:
             logging.error('Model for activity id %s does not exist.'
                           % activity_id)
+        self.emit('activity-laynch-failed', home_activity)
 
     def _check_activity_launched(self, activity_id):
         home_activity = self._get_activity_by_id(activity_id)
         if home_activity and home_activity.props.launching:
             logging.debug('Activity %s still launching, assuming it failed...'
                           % activity_id)
-            self.notify_activity_launch_failed(activity_id)
+            self.notify_launch_failure(activity_id)
         return False
diff --git a/src/model/shellmodel.py b/src/model/shellmodel.py
index c2ec2e4..e19397b 100644
--- a/src/model/shellmodel.py
+++ b/src/model/shellmodel.py
@@ -33,6 +33,7 @@ class ShellModel(gobject.GObject):
     ZOOM_FRIENDS = 1
     ZOOM_HOME = 2
     ZOOM_ACTIVITY = 3
+    ZOOM_LAUNCH = 4
 
     __gproperties__ = {
         'state'      : (int, None, None,
diff --git a/src/shellservice.py b/src/shellservice.py
index 3d90779..006a79a 100644
--- a/src/shellservice.py
+++ b/src/shellservice.py
@@ -79,12 +79,12 @@ class ShellService(dbus.service.Object):
     @dbus.service.method(_DBUS_SHELL_IFACE,
                          in_signature="ss", out_signature="")
     def NotifyLaunch(self, bundle_id, activity_id):
-        self._shell.notify_launch(bundle_id, activity_id)
+        self._home_model.notify_launch(bundle_id, activity_id)
 
     @dbus.service.method(_DBUS_SHELL_IFACE,
                          in_signature="s", out_signature="")
     def NotifyLaunchFailure(self, activity_id):
-        self._shell.notify_launch_failure(activity_id)
+        self._home_model.notify_launch_failure(activity_id)
 
     @dbus.service.signal(_DBUS_OWNER_IFACE, signature="s")
     def ColorChanged(self, color):
diff --git a/src/view/Shell.py b/src/view/Shell.py
index f45923d..b3329ab 100644
--- a/src/view/Shell.py
+++ b/src/view/Shell.py
@@ -56,7 +56,6 @@ class Shell(gobject.GObject):
         self._hosts = {}
         self._screen = wnck.screen_get_default()
         self._current_host = None
-        self._pending_host = None
         self._screen_rotation = 0
 
         self._key_handler = KeyHandler()
@@ -68,11 +67,12 @@ class Shell(gobject.GObject):
 
         home_model = self._model.get_home()
         home_model.connect('activity-started', self._activity_started_cb)
+        home_model.connect('activity-launched', self._activity_launched_cb)
+        home_model.connect('activity-launch-failed',
+                           self._activity_launch_failed_cb)
         home_model.connect('activity-removed', self._activity_removed_cb)
         home_model.connect('active-activity-changed',
                            self._active_activity_changed_cb)
-        home_model.connect('pending-activity-changed',
-                           self._pending_activity_changed_cb)
 
         gobject.idle_add(self._start_journal_idle)
 
@@ -101,6 +101,16 @@ class Shell(gobject.GObject):
         if home_activity.get_type() in self._activities_starting:
             self._activities_starting.remove(home_activity.get_type())
 
+    def _activity_launched_cb(self, home_model, home_activity):
+        # Zoom in for launch feedback, except for Journal
+        if home_activity.get_type() != 'org.laptop.JournalActivity':
+            self._home_window.set_launching_activity(home_activity)
+            self.set_zoom_level(shellmodel.ShellModel.ZOOM_LAUNCH)
+
+    def _activity_launch_failed_cb(self, home_model, home_activity):
+        # TODO: Add failure alert; just zoom home for now
+        self.set_zoom_level(shellmodel.ShellModel.ZOOM_HOME)
+
     def _activity_removed_cb(self, home_model, home_activity):
         if home_activity.get_type() in self._activities_starting:
             self._activities_starting.remove(home_activity.get_type())
@@ -110,7 +120,7 @@ class Shell(gobject.GObject):
             del self._hosts[xid]
 
     def _active_activity_changed_cb(self, home_model, home_activity):
-        if home_activity:
+        if home_activity: #and home_activity.get_xid() is not None:
             host = self._hosts[home_activity.get_xid()]
         else:
             host = None
@@ -120,11 +130,8 @@ class Shell(gobject.GObject):
 
         self._current_host = host
 
-    def _pending_activity_changed_cb(self, home_model, home_activity):
-        if home_activity:
-            self._pending_host = self._hosts[home_activity.get_xid()]
-        else:
-            self._pending_host = None
+        #if home_activity.get_xid() is None:
+        #    self.set_launching_activity(home_activity)
 
     def get_model(self):
         return self._model
@@ -150,17 +157,6 @@ class Shell(gobject.GObject):
         handle = ActivityHandle(activity_id)
         activityfactory.create(bundle_id, handle)
 
-    def notify_launch(self, bundle_id, activity_id):
-        # Zoom to Home for launch feedback
-        self.set_zoom_level(shellmodel.ShellModel.ZOOM_HOME)
-
-        home_model = self._model.get_home()
-        home_model.notify_activity_launch(activity_id, bundle_id)
-
-    def notify_launch_failure(self, activity_id):
-        home_model = self._model.get_home()
-        home_model.notify_activity_launch_failed(activity_id)
-
     def start_activity(self, activity_type):
         if activity_type in self._activities_starting:
             logging.debug("This activity is still launching.")
@@ -185,6 +181,11 @@ class Shell(gobject.GObject):
                 except dbus.DBusException, e:
                     logging.debug('Error raised by TakeScreenshot(): %s', e)
 
+    def set_launching_activity(self, home_activity):
+        zoom = self._model.get_zoom_level() < shellmodel.ShellModel.ZOOM_ACTIVITY
+        self._home_window.set_launching_activity(home_activity, zoom)
+        self.set_zoom_level(shellmodel.ShellModel.ZOOM_LAUNCH)
+
     def set_zoom_level(self, level):
         if level == self._model.get_zoom_level():
             return
@@ -192,9 +193,11 @@ class Shell(gobject.GObject):
         self.take_activity_screenshot()
 
         if level == shellmodel.ShellModel.ZOOM_ACTIVITY:
-            if self._pending_host is not None:
-                self._pending_host.present()
+            if self._current_host is not None:
+                self._current_host.present()
             self._screen.toggle_showing_desktop(False)
+            self._model.set_zoom_level(level)
+            self._home_window.set_zoom_level(level)
         else:
             self._model.set_zoom_level(level)
             self._screen.toggle_showing_desktop(True)
diff --git a/src/view/frame/activitiestray.py b/src/view/frame/activitiestray.py
index 3958f20..834d193 100644
--- a/src/view/frame/activitiestray.py
+++ b/src/view/frame/activitiestray.py
@@ -66,24 +66,24 @@ class ActivityButton(RadioToolButton):
             self._notify_launching_hid = home_activity.connect( \
                     'notify::launching', self.__notify_launching_cb)
 
-            self._notif_icon = NotificationIcon()
-            self._notif_icon.props.xo_color = home_activity.get_icon_color()
-            if home_activity.get_icon_path():
-                icon_path = home_activity.get_icon_path()
-                self._notif_icon.props.icon_filename = icon_path
-            else:
-                self._notif_icon.props.icon_name = 'image-missing'
-            view.frame.frame.get_instance().add_notification(self._notif_icon)
+            #self._notif_icon = NotificationIcon()
+            #self._notif_icon.props.xo_color = home_activity.get_icon_color()
+            #if home_activity.get_icon_path():
+            #    icon_path = home_activity.get_icon_path()
+            #    self._notif_icon.props.icon_filename = icon_path
+            #else:
+            #    self._notif_icon.props.icon_name = 'image-missing'
+            #view.frame.frame.get_instance().add_notification(self._notif_icon)
         else:
             self._notify_launching_hid = None
             self._notif_icon = None
 
     def __notify_launching_cb(self, home_activity, pspec):
         if not home_activity.props.launching:
-            if self._notif_icon is not None:
-                frame = view.frame.frame.get_instance()
-                frame.remove_notification(self._notif_icon)
-                self._notif_icon = None
+            #if self._notif_icon is not None:
+            #    frame = view.frame.frame.get_instance()
+            #    frame.remove_notification(self._notif_icon)
+            #    self._notif_icon = None
             self._icon.props.pulsing = False
             home_activity.disconnect(self._notify_launching_hid)
 
@@ -189,7 +189,7 @@ class ActivitiesTray(HTray):
         self._home_model = shellmodel.get_instance().get_home()
         self._home_model.connect('activity-added', self.__activity_added_cb)
         self._home_model.connect('activity-removed', self.__activity_removed_cb)
-        self._home_model.connect('pending-activity-changed',
+        self._home_model.connect('active-activity-changed',
                                  self.__activity_changed_cb)
 
         self._invites = shellmodel.get_instance().get_invites()
@@ -210,6 +210,7 @@ class ActivitiesTray(HTray):
         self._buttons[home_activity.get_activity_id()] = button
         button.connect('clicked', self.__activity_clicked_cb, home_activity)
         button.show()
+        button.set_active(True)
 
     def __activity_removed_cb(self, home_model, home_activity):
         logging.debug('__activity_removed_cb: %r' % home_activity)
@@ -225,7 +226,11 @@ class ActivitiesTray(HTray):
     def __activity_clicked_cb(self, button, home_activity):
         if button.props.active:
             logging.debug('ActivitiesTray.__activity_clicked_cb')
-            home_activity.get_window().activate(1)
+            if home_activity.get_window() is not None:
+                home_activity.get_window().activate(1)
+            else:
+                shell = view.Shell.get_instance()
+                shell.set_launching_activity(home_activity)
 
     def __invite_clicked_cb(self, icon, invite):
         self._invites.remove_invite(invite)
diff --git a/src/view/frame/friendstray.py b/src/view/frame/friendstray.py
index 86decaa..2cb1a66 100644
--- a/src/view/frame/friendstray.py
+++ b/src/view/frame/friendstray.py
@@ -54,8 +54,8 @@ class FriendsTray(VTray):
                 reply_handler=self._get_activities_cb)
 
         home_model = shellmodel.get_instance().get_home()
-        home_model.connect('pending-activity-changed',
-                           self._pending_activity_changed_cb)
+        home_model.connect('active-activity-changed',
+                           self._active_activity_changed_cb)
 
     def _get_activities_cb(self, activities_list):
         for act in activities_list:
@@ -117,8 +117,8 @@ class FriendsTray(VTray):
             self._left_hid = activity_ps.connect(
                             'buddy-left', self.__buddy_left_cb)
             
-    def _pending_activity_changed_cb(self, home_model, home_activity):
-        if home_activity is None:        
+    def _active_activity_changed_cb(self, home_model, home_activity):
+        if home_activity is None:
             return
 
         activity_id = home_activity.get_activity_id()
diff --git a/src/view/frame/zoomtoolbar.py b/src/view/frame/zoomtoolbar.py
index 946feac..9e1d2e6 100644
--- a/src/view/frame/zoomtoolbar.py
+++ b/src/view/frame/zoomtoolbar.py
@@ -64,6 +64,7 @@ class ZoomToolbar(gtk.Toolbar):
     def __level_clicked_cb(self, button, level):
         if not button.get_active():
             return
+        # TODO: switch to ZOOM_LAUNCH instead if selected activity is launching
         if shellmodel.get_instance().props.zoom_level != level:
             view.Shell.get_instance().set_zoom_level(level)
 
@@ -78,7 +79,8 @@ class ZoomToolbar(gtk.Toolbar):
             self._groups_button.props.active = True
         elif new_level == shellmodel.ShellModel.ZOOM_HOME:
             self._home_button.props.active = True
-        elif new_level == shellmodel.ShellModel.ZOOM_ACTIVITY:
+        elif new_level == shellmodel.ShellModel.ZOOM_ACTIVITY or \
+             new_level == shellmodel.ShellModel.ZOOM_LAUNCH:
             self._activity_button.props.active = True
         else:
             raise ValueError('Invalid zoom level: %r' % (new_level))
diff --git a/src/view/home/HomeWindow.py b/src/view/home/HomeWindow.py
index 7e0a0c5..fdee55f 100644
--- a/src/view/home/HomeWindow.py
+++ b/src/view/home/HomeWindow.py
@@ -24,12 +24,14 @@ from view.home.MeshBox import MeshBox
 from view.home.HomeBox import HomeBox
 from view.home.FriendsBox import FriendsBox
 from view.home.transitionbox import TransitionBox
+from view.home.launchbox import LaunchBox
 from model.shellmodel import ShellModel
 
 _HOME_PAGE       = 0
 _FRIENDS_PAGE    = 1
 _MESH_PAGE       = 2
 _TRANSITION_PAGE = 3
+_LAUNCH_PAGE     = 4
 
 class HomeWindow(gtk.Window):
     def __init__(self):
@@ -65,6 +67,7 @@ class HomeWindow(gtk.Window):
         self._friends_box = FriendsBox()
         self._mesh_box = MeshBox()
         self._transition_box = TransitionBox()
+        self._launch_box = LaunchBox()
 
         self._activate_view()
         self._canvas.set_root(self._home_box)
@@ -98,12 +101,16 @@ class HomeWindow(gtk.Window):
             self._home_box.suspend()
         elif self._level == ShellModel.ZOOM_MESH:
             self._mesh_box.suspend()
+        elif self._level == ShellModel.ZOOM_LAUNCH:
+            self._launch_box.suspend()
 
     def _activate_view(self):
         if self._level == ShellModel.ZOOM_HOME:
             self._home_box.resume()
         elif self._level == ShellModel.ZOOM_MESH:
             self._mesh_box.resume()
+        elif self._level == ShellModel.ZOOM_LAUNCH:
+            self._launch_box.resume()
 
     def _visibility_notify_event_cb(self, window, event):
         if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED:
@@ -111,11 +118,18 @@ class HomeWindow(gtk.Window):
         else:
             self._activate_view()
 
+    def set_launching_activity(self, home_activity, zoom=True):
+        self._launch_box.set_activity(home_activity, zoom)
+
     def set_zoom_level(self, level):
         self._deactivate_view()
         self._level = level
         self._activate_view()
     
+        if level == ShellModel.ZOOM_LAUNCH:
+            self._canvas.set_root(self._launch_box)
+            return
+
         self._canvas.set_root(self._transition_box)
 
         if level == ShellModel.ZOOM_HOME:
@@ -124,9 +138,12 @@ class HomeWindow(gtk.Window):
             size = style.LARGE_ICON_SIZE
         elif level == ShellModel.ZOOM_MESH:
             size = style.STANDARD_ICON_SIZE
-            
-        self._transition_box.set_size(size)
-    
+        elif level == ShellModel.ZOOM_ACTIVITY:
+            size = style.XLARGE_ICON_SIZE
+ 
+        if size is not None:
+            self._transition_box.set_size(size)
+
     def _transition_completed_cb(self, transition_box):
         if self._level == ShellModel.ZOOM_HOME:
             self._canvas.set_root(self._home_box)
diff --git a/src/view/home/activitieslist.py b/src/view/home/activitieslist.py
index f638738..3c5463f 100644
--- a/src/view/home/activitieslist.py
+++ b/src/view/home/activitieslist.py
@@ -91,7 +91,8 @@ class ActivityEntry(hippo.CanvasBox, hippo.CanvasItem):
                 file_name=activity_info.icon,
                 stroke_color=style.COLOR_BUTTON_GREY.get_svg(),
                 fill_color=style.COLOR_TRANSPARENT.get_svg())
-        self.icon.set_palette(ActivityPalette(activity_info))
+        self._palette = ActivityPalette(activity_info)
+        self.icon.set_palette(self._palette)
         self.icon.connect('hovering-changed',
                           self.__icon_hovering_changed_event_cb)
         self.icon.connect('button-release-event',
@@ -140,6 +141,9 @@ class ActivityEntry(hippo.CanvasBox, hippo.CanvasItem):
 
     def __icon_button_release_event_cb(self, icon, event):
         view.Shell.get_instance().start_activity(self._bundle_id)
+        self.icon.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg()
+        self.icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
+        self._palette.hide()
 
     def get_bundle_id(self):
         return self._bundle_id
diff --git a/src/view/home/activitiesring.py b/src/view/home/activitiesring.py
index 6a4b22d..f9f5f32 100644
--- a/src/view/home/activitiesring.py
+++ b/src/view/home/activitiesring.py
@@ -145,6 +145,9 @@ class ActivityIcon(CanvasIcon):
 
     def __button_release_event_cb(self, icon, event):
         view.Shell.get_instance().start_activity(self._activity_info.bundle_id)
+        self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg()
+        self.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
+        self._palette.hide()
 
     def get_bundle_id(self):
         return self._activity_info.bundle_id
@@ -160,16 +163,16 @@ class CurrentActivityIcon(CanvasIcon, hippo.CanvasItem):
         CanvasIcon.__init__(self, cache=True)
         self._home_model = shellmodel.get_instance().get_home()
 
-        if self._home_model.get_pending_activity() is not None:
-            self._update(self._home_model.get_pending_activity())
+        if self._home_model.get_active_activity() is not None:
+            self._update(self._home_model.get_active_activity())
 
-        self._home_model.connect('pending-activity-changed',
-                self.__pending_activity_changed_cb)
+        self._home_model.connect('active-activity-changed',
+                self.__active_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)
+        self._home_model.get_active_activity().get_window().activate(1)
 
     def _update(self, home_activity):
         _logger.debug('CurrentActivityIcon._update')
@@ -183,7 +186,7 @@ class CurrentActivityIcon(CanvasIcon, hippo.CanvasItem):
             palette = CurrentActivityPalette(home_activity)
         self.set_palette(palette)
 
-    def __pending_activity_changed_cb(self, home_model, home_activity):
+    def __active_activity_changed_cb(self, home_model, home_activity):
         self._update(home_activity)
 
 class RingLayout(gobject.GObject, hippo.CanvasLayout):
diff --git a/src/view/home/launchbox.py b/src/view/home/launchbox.py
new file mode 100644
index 0000000..546fa80
--- /dev/null
+++ b/src/view/home/launchbox.py
@@ -0,0 +1,86 @@
+# Copyright (C) 2007, Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+import hippo
+import gobject
+
+from sugar.graphics import style
+from sugar.graphics import animator
+from sugar.graphics.xocolor import XoColor
+
+from view.pulsingicon import CanvasPulsingIcon
+
+class LaunchBox(hippo.CanvasBox):
+    def __init__(self):
+        hippo.CanvasBox.__init__(self, 
+                                 background_color=style.COLOR_WHITE.get_int())
+
+        self._suspended = True
+
+        self._activity_icon = CanvasPulsingIcon()
+        self._activity_icon.props.base_color = \
+            XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
+                               style.COLOR_TRANSPARENT.get_svg()))
+
+        vbox = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL)
+        vbox.append(self._activity_icon, hippo.PACK_EXPAND)
+        self.append(vbox, hippo.PACK_EXPAND)
+
+        self._animator = animator.Animator(0.3)
+        #self._animator.connect('completed', self._animation_completed_cb)
+
+    # We could initiate pulsing after the zoom, if it has caching benefits
+    #def _animation_completed_cb(self, anim):
+    #    self._activity_icon.props.pulsing = True
+
+    def set_activity(self, home_activity, zoom=False):
+        self._activity_icon.props.file_name = home_activity.get_icon_path()
+        self._activity_icon.props.pulse_color = home_activity.get_icon_color()
+        if zoom:
+            self._zoom_in()
+
+    def _zoom_in(self):
+        self._activity_icon.props.size = style.STANDARD_ICON_SIZE
+
+        self._animator.remove_all()
+        self._animator.add(_Animation(self._activity_icon,
+                                      style.STANDARD_ICON_SIZE,
+                                      style.XLARGE_ICON_SIZE))
+        self._animator.start()
+        self._activity_icon.props.pulsing = True
+
+    def suspend(self):
+        if not self._suspended:
+            self._suspended = True
+            self._activity_icon.props.paused = True
+
+    def resume(self):
+        if self._suspended:
+            self._suspended = False
+            self._activity_icon.props.paused = True
+
+
+class _Animation(animator.Animation):
+    def __init__(self, icon, start_size, end_size):
+        animator.Animation.__init__(self, 0.0, 1.0)
+
+        self._icon = icon
+        self.start_size = start_size
+        self.end_size = end_size
+
+    def next_frame(self, current):
+        d = (self.end_size - self.start_size) * current
+        self._icon.props.size = self.start_size + d
-- 
1.5.3.3

_______________________________________________
Sugar mailing list
Sugar@lists.laptop.org
http://lists.laptop.org/listinfo/sugar

Reply via email to