diff --git a/src/jarabe/desktop/Makefile.am b/src/jarabe/desktop/Makefile.am
index 25fb0b42e9..b36404e048 100644
--- a/src/jarabe/desktop/Makefile.am
+++ b/src/jarabe/desktop/Makefile.am
@@ -14,5 +14,5 @@ sugar_PYTHON = \
networkviews.py \
schoolserver.py \
snowflakelayout.py \
- spreadlayout.py \
- transitionbox.py
+ transitionbox.py \
+ viewcontainer.py
diff --git a/src/jarabe/desktop/favoriteslayout.py b/src/jarabe/desktop/favoriteslayout.py
index 360c147dd9..0f63f95264 100644
--- a/src/jarabe/desktop/favoriteslayout.py
+++ b/src/jarabe/desktop/favoriteslayout.py
@@ -20,9 +20,7 @@
import hashlib
from gettext import gettext as _
-import gobject
import gtk
-import hippo
from sugar.graphics import style
@@ -42,77 +40,134 @@
style.SMALL_ICON_SIZE]
-class FavoritesLayout(gobject.GObject, hippo.CanvasLayout):
- """Base class of the different layout types."""
-
- __gtype_name__ = 'FavoritesLayout'
-
+class Layout(object):
def __init__(self):
- gobject.GObject.__init__(self)
- self.box = None
- self.fixed_positions = {}
+ pass
- def do_set_box(self, box):
- self.box = box
+ def remove(self, child):
+ pass
- def do_get_height_request(self, for_width):
- return 0, gtk.gdk.screen_height() - style.GRID_CELL_SIZE
+ def allocate_children(self, allocation, children):
+ pass
- def do_get_width_request(self):
- return 0, gtk.gdk.screen_width()
- def compare_activities(self, icon_a, icon_b):
- return 0
+class ViewLayout(Layout):
+ def __init__(self):
+ self._grid = None
- def append(self, icon, locked=False):
- if not hasattr(type(icon), 'fixed_position'):
- logging.debug('Icon without fixed_position: %r', icon)
+ def setup(self, allocation, owner_icon, activity_icon=None):
+ if self._grid is not None:
return
-
- icon.props.size = max(icon.props.size, style.STANDARD_ICON_SIZE)
-
- relative_x, relative_y = icon.fixed_position
- if relative_x < 0 or relative_y < 0:
- logging.debug('Icon out of bounds: %r', icon)
+ self._grid = Grid(int(allocation.width / _CELL_SIZE),
+ int(allocation.height / _CELL_SIZE))
+ self._grid.connect('child-changed', self.__grid_child_changed_cb)
+ self._allocate_owner_icon(allocation, owner_icon, activity_icon)
+
+ def _allocate_owner_icon(self, allocation, owner_icon, activity_icon):
+ # add owner icon to the grid, precisely centered on the screen
+ # if not None, add an activity icon directly below the owner icon
+ owner_width, owner_height = owner_icon.size_request()
+ height = allocation.height + allocation.y
+ width = allocation.width
+
+ # Find vertical center point of screen
+ y = height / 2
+
+ # This container may be offset from the top by a certain amount
+ # (e.g. for a toolbar at the top of the screen). Adjust the
+ # center-point for that
+ y -= allocation.y
+
+ # Now subtract half of the owner height. This gives us the y
+ # coordinate for the top of the owner icon.
+ y -= owner_height / 2
+
+ # calculate x coordinate and create allocation
+ x = (width - owner_width) / 2
+ owner_icon_allocation = gtk.gdk.Rectangle(x, allocation.y + y,
+ owner_width, owner_height)
+ owner_icon.size_allocate(owner_icon_allocation)
+
+ # Determine grid coordinates and add to grid
+ owner_grid_width, owner_grid_height = \
+ self._get_child_grid_size(owner_icon)
+ x = int(x / float(_CELL_SIZE))
+ y = int(y / float(_CELL_SIZE))
+ self._grid.add(owner_icon, owner_grid_width, owner_grid_height,
+ x, y, locked=True)
+
+ if activity_icon is None:
return
- min_width_, width = self.box.get_width_request()
- min_height_, height = self.box.get_height_request(width)
- self.fixed_positions[icon] = \
- (int(relative_x * _BASE_SCALE / float(width)),
- int(relative_y * _BASE_SCALE / float(height)))
+ # Position the current activity below the XO icon
+ # FIXME must ensure we cross into next grid cell here..
+ activity_width, activity_height = activity_icon.size_request()
+ x = (width - activity_width) / 2
+ y = owner_icon_allocation.y + owner_height
+ activity_icon_allocation = gtk.gdk.Rectangle(x, y, activity_width,
+ activity_height)
+ activity_icon.size_allocate(activity_icon_allocation)
+
+ # Determine grid coordinates and add to grid
+ activity_grid_width, activity_grid_height = \
+ self._get_child_grid_size(activity_icon)
+ x = int(x / float(_CELL_SIZE))
+ y = int(y / float(_CELL_SIZE))
+ self._grid.add(activity_icon, activity_grid_width,
+ activity_grid_height, x, y, locked=True)
+
+ def allocate_children(self, allocation, children):
+ pass
+
+ def move(self, child, x, y, allocation=None):
+ self._grid.move(child, x / _CELL_SIZE, y / _CELL_SIZE, locked=True)
+ width, height = child.size_request()
+ rect = self._grid.get_child_rect(child)
+ child_allocation = gtk.gdk.Rectangle(int(round(rect.x * _CELL_SIZE)),
+ int(round(rect.y * _CELL_SIZE)),
+ width,
+ height)
+ child.size_allocate(child_allocation)
+
+ def _get_child_grid_size(self, child):
+ width, height = child.size_request()
+ width = math.ceil(width / _CELL_SIZE)
+ height = math.ceil(height / _CELL_SIZE)
+ return int(width), int(height)
- def remove(self, icon):
- if icon in self.fixed_positions:
- del self.fixed_positions[icon]
+ def __grid_child_changed_cb(self, grid, child):
+ width, height = child.size_request()
+ rect = self._grid.get_child_rect(child)
+ child_allocation = gtk.gdk.Rectangle(int(round(rect.x * _CELL_SIZE)),
+ int(round(rect.y * _CELL_SIZE)),
+ width,
+ height)
+ child.size_allocate(child_allocation)
- def move_icon(self, icon, x, y, locked=False):
- if icon not in self.box.get_children():
- raise ValueError('Child not in box.')
- if not (hasattr(icon, 'get_bundle_id') and
- hasattr(icon, 'get_version')):
- logging.debug('Not an activity icon %r', icon)
- return
+class SpreadLayout(ViewLayout):
+ def __init__(self):
+ ViewLayout.__init__(self)
- min_width_, width = self.box.get_width_request()
- min_height_, height = self.box.get_height_request(width)
- registry = bundleregistry.get_registry()
- registry.set_bundle_position(
- icon.get_bundle_id(), icon.get_version(),
- x * width / float(_BASE_SCALE),
- y * height / float(_BASE_SCALE))
- self.fixed_positions[icon] = (x, y)
+ def remove(self, child):
+ if self._grid.is_in_grid(child):
+ self._grid.remove(child)
- def do_allocate(self, x, y, width, height, req_width, req_height,
- origin_changed):
- raise NotImplementedError()
+ def allocate_children(self, allocation, children):
+ for child in children:
+ if not self._grid.is_in_grid(child):
+ width, height = self._get_child_grid_size(child)
+ self._grid.add(child, width, height, None, None, locked=False)
- def allow_dnd(self):
- return False
+ width, height = child.size_request()
+ rect = self._grid.get_child_rect(child)
+ x = int(round(rect.x * _CELL_SIZE))
+ y = int(round(rect.y * _CELL_SIZE)) + allocation.y
+ child_allocation = gtk.gdk.Rectangle(x, y, width, height)
+ child.size_allocate(child_allocation)
-class RandomLayout(FavoritesLayout):
+class RandomLayout(SpreadLayout):
"""Lay out icons randomly; try to nudge them around to resolve overlaps."""
__gtype_name__ = 'RandomLayout'
@@ -128,69 +183,75 @@ class RandomLayout(FavoritesLayout):
"""String used to identify this layout in home view dropdown palette."""
def __init__(self):
- FavoritesLayout.__init__(self)
-
- min_width_, width = self.do_get_width_request()
- min_height_, height = self.do_get_height_request(width)
-
- self._grid = Grid(width / _CELL_SIZE, height / _CELL_SIZE)
- self._grid.connect('child-changed', self.__grid_child_changed_cb)
-
- def __grid_child_changed_cb(self, grid, child):
- child.emit_request_changed()
-
- def append(self, icon, locked=False):
- FavoritesLayout.append(self, icon, locked)
-
- min_width_, child_width = icon.get_width_request()
- min_height_, child_height = icon.get_height_request(child_width)
- min_width_, width = self.box.get_width_request()
- min_height_, height = self.box.get_height_request(width)
-
- if icon in self.fixed_positions:
- x, y = self.fixed_positions[icon]
- x = min(x, width - child_width)
- y = min(y, height - child_height)
- elif hasattr(icon, 'get_bundle_id'):
- name_hash = hashlib.md5(icon.get_bundle_id())
- x = int(name_hash.hexdigest()[:5], 16) % (width - child_width)
- y = int(name_hash.hexdigest()[-5:], 16) % (height - child_height)
- else:
- x = None
- y = None
-
- if x is None or y is None:
- self._grid.add(icon,
- child_width / _CELL_SIZE, child_height / _CELL_SIZE)
- else:
- self._grid.add(icon,
- child_width / _CELL_SIZE, child_height / _CELL_SIZE,
- x / _CELL_SIZE, y / _CELL_SIZE)
+ SpreadLayout.__init__(self)
+ self.fixed_positions = {}
- def remove(self, icon):
- self._grid.remove(icon)
- FavoritesLayout.remove(self, icon)
+ def _add_fixed_position(self, icon, allocation, locked=False):
+ if not hasattr(type(icon), 'fixed_position'):
+ logging.debug('Icon without fixed_position: %r', icon)
+ return
- def move_icon(self, icon, x, y, locked=False):
- self._grid.move(icon, x / _CELL_SIZE, y / _CELL_SIZE, locked)
- FavoritesLayout.move_icon(self, icon, x, y, locked)
+ icon.props.pixel_size = max(icon.props.pixel_size,
+ style.STANDARD_ICON_SIZE)
- def do_allocate(self, x, y, width, height, req_width, req_height,
- origin_changed):
- for child in self.box.get_layout_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)
+ relative_x, relative_y = icon.fixed_position
+ if relative_x < 0 or relative_y < 0:
+ logging.debug('Icon out of bounds: %r', icon)
+ return
- rect = self._grid.get_child_rect(child.item)
- child.allocate(rect.x * _CELL_SIZE,
- rect.y * _CELL_SIZE,
- child_width,
- child_height,
- origin_changed)
+ self.fixed_positions[icon] = \
+ (int(relative_x * _BASE_SCALE / float(allocation.width)),
+ int(relative_y * _BASE_SCALE / float(allocation.height)))
+
+ def allocate_children(self, allocation, children):
+ for child in children:
+ child_width, child_height = child.size_request()
+ if not self._grid.is_in_grid(child):
+ self._add_fixed_position(child, allocation)
+
+ if child in self.fixed_positions:
+ x, y = self.fixed_positions[child]
+ x = min(x, allocation.width - child_width)
+ y = min(y, allocation.height - child_height)
+ elif hasattr(child, 'get_bundle_id'):
+ name_hash = hashlib.md5(child.get_bundle_id())
+ x = int(name_hash.hexdigest()[:5], 16) % \
+ (allocation.width - child_width)
+ y = int(name_hash.hexdigest()[-5:], 16) % \
+ (allocation.height - child_height)
+ else:
+ x = None
+ y = None
+
+ if x is None or y is None:
+ self._grid.add(child, child_width / _CELL_SIZE,
+ child_height / _CELL_SIZE)
+ else:
+ self._grid.add(child, child_width / _CELL_SIZE,
+ child_height / _CELL_SIZE,
+ x / _CELL_SIZE, y / _CELL_SIZE)
+
+ rect = self._grid.get_child_rect(child)
+ x = int(round(rect.x * _CELL_SIZE))
+ y = int(round(rect.y * _CELL_SIZE)) + allocation.y
+ child_allocation = gtk.gdk.Rectangle(x, y,
+ child_width, child_height)
+ child.size_allocate(child_allocation)
+
+ def move_icon(self, child, x, y, allocation):
+ ViewLayout.move(self, child, x, y)
+
+ if not (hasattr(child, 'get_bundle_id') and
+ hasattr(child, 'get_version')):
+ logging.debug('Not an activity icon %r', child)
+ return
- def allow_dnd(self):
- return True
+ registry = bundleregistry.get_registry()
+ registry.set_bundle_position(
+ child.get_bundle_id(), child.get_version(),
+ x * allocation.width / float(_BASE_SCALE),
+ y * allocation.height / float(_BASE_SCALE))
+ self.fixed_positions[child] = (x, y)
_MINIMUM_RADIUS = style.XLARGE_ICON_SIZE / 2 + style.DEFAULT_SPACING + \
@@ -203,7 +264,7 @@ def allow_dnd(self):
_INITIAL_ANGLE = math.pi
-class RingLayout(FavoritesLayout):
+class RingLayout(ViewLayout):
"""Lay out icons in a ring or spiral around the XO man."""
__gtype_name__ = 'RingLayout'
@@ -216,28 +277,9 @@ class RingLayout(FavoritesLayout):
"""String used to identify this layout in home view dropdown palette."""
def __init__(self):
- FavoritesLayout.__init__(self)
- self._locked_children = {}
+ ViewLayout.__init__(self)
self._spiral_mode = False
- def append(self, icon, locked=False):
- FavoritesLayout.append(self, icon, locked)
- if locked:
- child = self.box.find_box_child(icon)
- self._locked_children[child] = (0, 0)
-
- def remove(self, icon):
- child = self.box.find_box_child(icon)
- if child in self._locked_children:
- del self._locked_children[child]
- FavoritesLayout.remove(self, icon)
-
- def move_icon(self, icon, x, y, locked=False):
- FavoritesLayout.move_icon(self, icon, x, y, locked)
- if locked:
- child = self.box.find_box_child(icon)
- self._locked_children[child] = (x, y)
-
def _calculate_radius_and_icon_size(self, children_count):
""" Adjust the ring or spiral radius and icon size as needed. """
self._spiral_mode = False
@@ -270,12 +312,10 @@ def _calculate_radius_and_icon_size(self, children_count):
return radius, icon_size
def _calculate_position(self, radius, icon_size, icon_index,
- children_count, sin=math.sin, cos=math.cos):
+ children_count, width, height,
+ sin=math.sin, cos=math.cos):
""" Calculate an icon position on a circle or a spiral. """
- width, height = self.box.get_allocation()
if self._spiral_mode:
- min_width_, box_width = self.box.get_width_request()
- min_height_, box_height = self.box.get_height_request(box_width)
angle, radius = self._calculate_angle_and_radius(icon_index,
icon_size)
x, y = self._convert_from_polar_to_cartesian(angle, radius,
@@ -286,7 +326,7 @@ def _calculate_position(self, radius, icon_size, icon_index,
x = radius * cos(angle) + (width - icon_size) / 2
y = radius * sin(angle) + (height - icon_size - \
(style.GRID_CELL_SIZE / 2)) / 2
- return x, y
+ return int(x), int(y)
def _convert_from_polar_to_cartesian(self, angle, radius, icon_size, width,
height):
@@ -311,49 +351,27 @@ def _calculate_angle_and_radius(self, icon_count, icon_size):
radius += (float(icon_spacing) * spiral_spacing / n)
return angle, radius
- def _get_children_in_ring(self):
- children_in_ring = [child for child in self.box.get_layout_children() \
- if child not in self._locked_children]
- return children_in_ring
-
- def do_allocate(self, x, y, width, height, req_width, req_height,
- origin_changed):
- children_in_ring = self._get_children_in_ring()
- if children_in_ring:
- radius, icon_size = \
- self._calculate_radius_and_icon_size(len(children_in_ring))
-
- for n in range(len(children_in_ring)):
- child = children_in_ring[n]
-
- x, y = self._calculate_position(radius, icon_size, n,
- len(children_in_ring))
-
- # 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)
+ def allocate_children(self, allocation, children):
+ radius, icon_size = self._calculate_radius_and_icon_size(len(children))
- child.allocate(int(x), int(y), child_width, child_height,
- origin_changed)
- child.item.props.size = icon_size
+ children.sort(self.compare_activities)
+ for n in range(len(children)):
+ child = children[n]
- for child in self._locked_children.keys():
- x, y = self._locked_children[child]
-
- # 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)
-
- if child_width <= 0 or child_height <= 0:
- return
-
- child.allocate(int(x), int(y), child_width, child_height,
- origin_changed)
+ x, y = self._calculate_position(radius, icon_size, n,
+ len(children), allocation.width,
+ allocation.height)
+ child.size_request()
+ child.set_size(icon_size)
+ child_allocation = gtk.gdk.Rectangle(allocation.x + x,
+ allocation.y + y,
+ icon_size, icon_size)
+ child.size_allocate(child_allocation)
def compare_activities(self, icon_a, icon_b):
if hasattr(icon_a, 'installation_time') and \
hasattr(icon_b, 'installation_time'):
- return icon_b.installation_time - icon_a.installation_time
+ return int(icon_b.installation_time - icon_a.installation_time)
else:
return 0
@@ -420,13 +438,11 @@ def adjust_index(self, i):
return i
def _calculate_position(self, radius, icon_size, oindex, children_count,
- sin=math.sin, cos=math.cos):
+ width, height, sin=math.sin, cos=math.cos):
"""Calculate the position of sunflower floret number 'oindex'.
If the result is outside the bounding box, use the next index which
is inside the bounding box."""
- width, height = self.box.get_allocation()
-
while True:
index = self.adjust_index(oindex)
@@ -454,7 +470,7 @@ def _calculate_position(self, radius, icon_size, oindex, children_count,
# try again
continue
- return x, y
+ return int(x), int(y)
class BoxLayout(RingLayout):
@@ -476,7 +492,7 @@ def __init__(self):
RingLayout.__init__(self)
def _calculate_position(self, radius, icon_size, index, children_count,
- sin=None, cos=None):
+ width, height, sin=None, cos=None):
# use "orthogonal" versions of cos and sin in order to square the
# circle and turn the 'ring view' into a 'box view'
@@ -496,8 +512,8 @@ def cos_d(d):
sin = lambda r: cos_d(math.degrees(r) - 90)
return RingLayout._calculate_position(self, radius, icon_size, index,
- children_count, sin=sin,
- cos=cos)
+ children_count, width, height,
+ sin=sin, cos=cos)
class TriangleLayout(RingLayout):
@@ -526,7 +542,7 @@ def _calculate_radius_and_icon_size(self, children_count):
return max(radius, _MINIMUM_RADIUS + style.MEDIUM_ICON_SIZE), icon_size
def _calculate_position(self, radius, icon_size, index, children_count,
- sin=math.sin, cos=math.cos):
+ width, height, sin=math.sin, cos=math.cos):
# tweak cos and sin in order to make the 'ring' into an equilateral
# triangle.
@@ -556,5 +572,5 @@ def sin_d(d):
sin = lambda r: sin_d(math.degrees(r))
return RingLayout._calculate_position(self, radius, icon_size, index,
- children_count, sin=sin,
- cos=cos)
+ children_count, width, height,
+ sin=sin, cos=cos)
diff --git a/src/jarabe/desktop/favoritesview.py b/src/jarabe/desktop/favoritesview.py
index 654f4002b5..35c4053c19 100644
--- a/src/jarabe/desktop/favoritesview.py
+++ b/src/jarabe/desktop/favoritesview.py
@@ -23,10 +23,9 @@
import gconf
import glib
import gtk
-import hippo
from sugar.graphics import style
-from sugar.graphics.icon import Icon, CanvasIcon
+from sugar.graphics.icon import Icon
from sugar.graphics.menuitem import MenuItem
from sugar.graphics.alert import Alert
from sugar.graphics.xocolor import XoColor
@@ -35,9 +34,11 @@
from sugar.datastore import datastore
from jarabe.view.palettes import JournalPalette
-from jarabe.view.palettes import CurrentActivityPalette, ActivityPalette
+from jarabe.view.palettes import CurrentActivityPalette
+from jarabe.view.palettes import ActivityPalette
from jarabe.view.buddyicon import BuddyIcon
from jarabe.view.buddymenu import BuddyMenu
+from jarabe.view.eventicon import EventIcon
from jarabe.model.buddy import get_owner_instance
from jarabe.model import shell
from jarabe.model import bundleregistry
@@ -46,6 +47,7 @@
from jarabe.desktop import schoolserver
from jarabe.desktop.schoolserver import RegisterError
from jarabe.desktop import favoriteslayout
+from jarabe.desktop.viewcontainer import ViewContainer
_logger = logging.getLogger('FavoritesView')
@@ -64,169 +66,127 @@
_favorites_settings = None
-class FavoritesView(hippo.Canvas):
- __gtype_name__ = 'SugarFavoritesView'
+class FavoritesBox(gtk.VBox):
+ __gtype_name__ = 'SugarFavoritesBox'
- def __init__(self, **kwargs):
- logging.debug('STARTUP: Loading the favorites view')
+ def __init__(self):
+ gtk.VBox.__init__(self)
- gobject.GObject.__init__(self, **kwargs)
+ self._view = FavoritesView(self)
+ self.pack_start(self._view)
+ self._view.show()
- # DND stuff
- self._pressed_button = None
- self._press_start_x = None
- self._press_start_y = None
- self._hot_x = None
- self._hot_y = None
- self._last_clicked_icon = None
+ self._alert = None
- self._box = hippo.CanvasBox()
- self._box.props.background_color = style.COLOR_WHITE.get_int()
- self.set_root(self._box)
+ def set_filter(self, query):
+ self._view.set_filter(query)
- self._my_icon = OwnerIcon(style.XLARGE_ICON_SIZE)
- self._my_icon.connect('register-activate', self.__register_activate_cb)
- self._box.append(self._my_icon)
+ def set_resume_mode(self, resume_mode):
+ self._view.set_resume_mode(resume_mode)
- self._current_activity = CurrentActivityIcon()
- self._box.append(self._current_activity)
+ def add_alert(self, alert):
+ if self._alert is not None:
+ self.remove_alert()
+ self._alert = alert
+ self.pack_start(alert, False)
+ self.reorder_child(alert, 0)
- self._layout = None
+ def remove_alert(self):
+ self.remove(self._alert)
self._alert = None
- self._resume_mode = True
- # More DND stuff
- self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
- gtk.gdk.POINTER_MOTION_HINT_MASK)
- self.connect('motion-notify-event', self.__motion_notify_event_cb)
- self.connect('button-press-event', self.__button_press_event_cb)
- self.connect('drag-begin', self.__drag_begin_cb)
- self.connect('drag-motion', self.__drag_motion_cb)
- self.connect('drag-drop', self.__drag_drop_cb)
- self.connect('drag-data-received', self.__drag_data_received_cb)
- gobject.idle_add(self.__connect_to_bundle_registry_cb)
+class FavoritesView(ViewContainer):
+ __gtype_name__ = 'SugarFavoritesView'
+
+ def __init__(self, box):
+ self._box = box
+ self._layout = None
favorites_settings = get_settings()
favorites_settings.changed.connect(self.__settings_changed_cb)
self._set_layout(favorites_settings.layout)
- def set_filter(self, query):
- query = query.strip()
- for icon in self._box.get_children():
- if icon not in [self._my_icon, self._current_activity]:
- activity_name = icon.get_activity_name().lower()
- if activity_name.find(query) > -1:
- icon.alpha = 1.0
- else:
- icon.alpha = 0.33
+ owner_icon = OwnerIcon(style.XLARGE_ICON_SIZE)
+ owner_icon.connect('register-activate', self.__register_activate_cb)
- def __settings_changed_cb(self, **kwargs):
- favorites_settings = get_settings()
- self._set_layout(favorites_settings.layout)
+ current_activity = CurrentActivityIcon()
- def __connect_to_bundle_registry_cb(self):
- registry = bundleregistry.get_registry()
+ ViewContainer.__init__(self, layout=self._layout,
+ owner_icon=owner_icon,
+ activity_icon=current_activity)
- for info in registry:
- if registry.is_bundle_favorite(info.get_bundle_id(),
- info.get_activity_version()):
- self._add_activity(info)
+ self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
+ gtk.gdk.POINTER_MOTION_HINT_MASK)
+ self.drag_dest_set(0, [], 0)
+ self.connect('drag-motion', self.__drag_motion_cb)
+ self.connect('drag-drop', self.__drag_drop_cb)
+ self.connect('drag-data-received', self.__drag_data_received_cb)
- registry.connect('bundle-added', self.__activity_added_cb)
- registry.connect('bundle-removed', self.__activity_removed_cb)
- registry.connect('bundle-changed', self.__activity_changed_cb)
+ self._dragging = False
+ self._pressed_button = None
+ self._press_start_x = 0
+ self._press_start_y = 0
+ self._hot_x = None
+ self._hot_y = None
+ self._last_clicked_icon = None
- def _add_activity(self, activity_info):
- if activity_info.get_bundle_id() == 'org.laptop.JournalActivity':
- return
- icon = ActivityIcon(activity_info)
- icon.props.size = style.STANDARD_ICON_SIZE
- icon.set_resume_mode(self._resume_mode)
- self._box.insert_sorted(icon, 0, self._layout.compare_activities)
- self._layout.append(icon)
+ self._alert = None
+ self._resume_mode = True
- def __activity_added_cb(self, activity_registry, activity_info):
- registry = bundleregistry.get_registry()
- if registry.is_bundle_favorite(activity_info.get_bundle_id(),
- activity_info.get_activity_version()):
- self._add_activity(activity_info)
+ gobject.idle_add(self.__connect_to_bundle_registry_cb)
- def _find_activity_icon(self, bundle_id, version):
- for icon in self._box.get_children():
- if isinstance(icon, ActivityIcon) and \
- icon.bundle_id == bundle_id and icon.version == version:
- return icon
- return None
+ def __settings_changed_cb(self, **kwargs):
+ favorites_settings = get_settings()
+ layout_set = self._set_layout(favorites_settings.layout)
+ if layout_set:
+ self.set_layout(self._layout)
+ registry = bundleregistry.get_registry()
+ for info in registry:
+ if registry.is_bundle_favorite(info.get_bundle_id(),
+ info.get_activity_version()):
+ self._add_activity(info)
- def __activity_removed_cb(self, activity_registry, activity_info):
- icon = self._find_activity_icon(activity_info.get_bundle_id(),
- activity_info.get_activity_version())
- if icon is not None:
- self._layout.remove(icon)
- self._box.remove(icon)
+ def _set_layout(self, layout):
+ if layout not in LAYOUT_MAP:
+ logging.warn('Unknown favorites layout: %r', layout)
+ layout = favoriteslayout.RingLayout.key
+ assert layout in LAYOUT_MAP
- def __activity_changed_cb(self, activity_registry, activity_info):
- if activity_info.get_bundle_id() == 'org.laptop.JournalActivity':
- return
- icon = self._find_activity_icon(activity_info.get_bundle_id(),
- activity_info.get_activity_version())
- if icon is not None:
- self._box.remove(icon)
+ if type(self._layout) == LAYOUT_MAP[layout]:
+ return False
- registry = bundleregistry.get_registry()
- if registry.is_bundle_favorite(activity_info.get_bundle_id(),
- activity_info.get_activity_version()):
- self._add_activity(activity_info)
+ self._layout = LAYOUT_MAP[layout]()
+ return True
- def do_size_allocate(self, allocation):
- width = allocation.width
- height = allocation.height
+ layout = property(None, _set_layout)
- min_w_, my_icon_width = self._my_icon.get_width_request()
- min_h_, my_icon_height = self._my_icon.get_height_request(
- my_icon_width)
- x = (width - my_icon_width) / 2
- y = (height - my_icon_height - style.GRID_CELL_SIZE) / 2
- self._layout.move_icon(self._my_icon, x, y, locked=True)
-
- min_w_, icon_width = self._current_activity.get_width_request()
- min_h_, icon_height = \
- self._current_activity.get_height_request(icon_width)
- x = (width - icon_width) / 2
- y = (height - my_icon_height - style.GRID_CELL_SIZE) / 2 + \
- my_icon_height + style.DEFAULT_PADDING
- self._layout.move_icon(self._current_activity, x, y, locked=True)
-
- hippo.Canvas.do_size_allocate(self, allocation)
-
- # TODO: Dnd methods. This should be merged somehow inside hippo-canvas.
- def __button_press_event_cb(self, widget, event):
- if event.button == 1 and event.type == gtk.gdk.BUTTON_PRESS:
- self._last_clicked_icon = self._get_icon_at_coords(event.x,
- event.y)
- if self._last_clicked_icon is not None:
- self._pressed_button = event.button
- self._press_start_x = event.x
- self._press_start_y = event.y
+ def do_add(self, child):
+ if child != self._owner_icon and child != self._activity_icon:
+ self._children.append(child)
+ child.connect('button-press-event', self.__button_press_cb)
+ child.connect('button-release-event', self.__button_release_cb)
+ child.connect('motion-notify-event', self.__motion_notify_event_cb)
+ child.connect('drag-begin', self.__drag_begin_cb)
+ if child.flags() & gtk.REALIZED:
+ child.set_parent_window(self.get_parent_window())
+ child.set_parent(self)
+
+ def __button_release_cb(self, widget, event):
+ if self._dragging:
+ return True
+ else:
+ return False
+ def __button_press_cb(self, widget, event):
+ if event.button == 1 and event.type == gtk.gdk.BUTTON_PRESS:
+ self._last_clicked_icon = widget
+ self._pressed_button = event.button
+ self._press_start_x = event.x
+ self._press_start_y = event.y
return False
- def _get_icon_at_coords(self, x, y):
- for icon in self._box.get_children():
- icon_x, icon_y = icon.get_context().translate_to_widget(icon)
- icon_width, icon_height = icon.get_allocation()
-
- if (x >= icon_x) and (x <= icon_x + icon_width) and \
- (y >= icon_y) and (y <= icon_y + icon_height) and \
- isinstance(icon, ActivityIcon):
- return icon
- return None
-
def __motion_notify_event_cb(self, widget, event):
- if not self._pressed_button:
- return False
-
# if the mouse button is not pressed, no drag should occurr
if not event.state & gtk.gdk.BUTTON1_MASK:
self._pressed_button = None
@@ -242,6 +202,7 @@ def __motion_notify_event_cb(self, widget, event):
int(self._press_start_y),
int(x),
int(y)):
+ self._dragging = True
context_ = widget.drag_begin([_ICON_DND_TARGET],
gtk.gdk.ACTION_MOVE,
1,
@@ -249,9 +210,7 @@ def __motion_notify_event_cb(self, widget, event):
return False
def __drag_begin_cb(self, widget, context):
- icon_file_name = self._last_clicked_icon.props.file_name
- # TODO: we should get the pixbuf from the widget, so it has colors, etc
- pixbuf = gtk.gdk.pixbuf_new_from_file(icon_file_name)
+ pixbuf = gtk.gdk.pixbuf_new_from_file(widget.props.file_name)
self._hot_x = pixbuf.props.width / 2
self._hot_y = pixbuf.props.height / 2
@@ -267,9 +226,9 @@ def __drag_motion_cb(self, widget, context, x, y, time):
def __drag_drop_cb(self, widget, context, x, y, time):
if self._last_clicked_icon is not None:
self.drag_get_data(context, _ICON_DND_TARGET[0])
-
self._layout.move_icon(self._last_clicked_icon,
- x - self._hot_x, y - self._hot_y)
+ x - self._hot_x, y - self._hot_y,
+ self.get_allocation())
self._pressed_button = None
self._press_start_x = None
@@ -277,6 +236,7 @@ def __drag_drop_cb(self, widget, context, x, y, time):
self._hot_x = None
self._hot_y = None
self._last_clicked_icon = None
+ self._dragging = False
return True
else:
@@ -286,49 +246,68 @@ def __drag_data_received_cb(self, widget, context, x, y, selection_data,
info, time):
context.drop_finish(success=True, time=time)
- def _set_layout(self, layout):
- if layout not in LAYOUT_MAP:
- logging.warn('Unknown favorites layout: %r', layout)
- layout = favoriteslayout.RingLayout.key
- assert layout in LAYOUT_MAP
+ def __connect_to_bundle_registry_cb(self):
+ registry = bundleregistry.get_registry()
- if type(self._layout) == LAYOUT_MAP[layout]:
- return
+ for info in registry:
+ if registry.is_bundle_favorite(info.get_bundle_id(),
+ info.get_activity_version()):
+ self._add_activity(info)
- self._layout = LAYOUT_MAP[layout]()
- self._box.set_layout(self._layout)
+ registry.connect('bundle-added', self.__activity_added_cb)
+ registry.connect('bundle-removed', self.__activity_removed_cb)
+ registry.connect('bundle-changed', self.__activity_changed_cb)
- #TODO: compatibility hack while sort() gets added to the hippo python
- # bindings
- if hasattr(self._box, 'sort'):
- self._box.sort(self._layout.compare_activities)
+ def _add_activity(self, activity_info):
+ if activity_info.get_bundle_id() == 'org.laptop.JournalActivity':
+ return
+ icon = ActivityIcon(activity_info)
+ icon.props.pixel_size = style.STANDARD_ICON_SIZE
+ #icon.set_resume_mode(self._resume_mode)
+ self.add(icon)
+ icon.show()
- for icon in self._box.get_children():
- if icon not in [self._my_icon, self._current_activity]:
- self._layout.append(icon)
+ def __activity_added_cb(self, activity_registry, activity_info):
+ registry = bundleregistry.get_registry()
+ if registry.is_bundle_favorite(activity_info.get_bundle_id(),
+ activity_info.get_activity_version()):
+ self._add_activity(activity_info)
- self._layout.append(self._my_icon, locked=True)
- self._layout.append(self._current_activity, locked=True)
+ def __activity_removed_cb(self, activity_registry, activity_info):
+ icon = self._find_activity_icon(activity_info.get_bundle_id(),
+ activity_info.get_activity_version())
+ if icon is not None:
+ self.remove(icon)
- if self._layout.allow_dnd():
- self.drag_source_set(0, [], 0)
- self.drag_dest_set(0, [], 0)
- else:
- self.drag_source_unset()
- self.drag_dest_unset()
+ 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
- layout = property(None, _set_layout)
+ def __activity_changed_cb(self, activity_registry, activity_info):
+ if activity_info.get_bundle_id() == 'org.laptop.JournalActivity':
+ return
+ icon = self._find_activity_icon(activity_info.get_bundle_id(),
+ activity_info.get_activity_version())
+ if icon is not None:
+ self.remove(icon)
- def add_alert(self, alert):
- if self._alert is not None:
- self.remove_alert()
- alert.set_size_request(gtk.gdk.screen_width(), -1)
- self._alert = hippo.CanvasWidget(widget=alert)
- self._box.append(self._alert, hippo.PACK_FIXED)
+ registry = bundleregistry.get_registry()
+ if registry.is_bundle_favorite(activity_info.get_bundle_id(),
+ activity_info.get_activity_version()):
+ self._add_activity(activity_info)
- def remove_alert(self):
- self._box.remove(self._alert)
- self._alert = None
+ def set_filter(self, query):
+ query = query.strip()
+ for icon in self.get_children():
+ if icon not in [self._owner_icon, self._activity_icon]:
+ activity_name = icon.get_activity_name().lower()
+ if activity_name.find(query) > -1:
+ icon.alpha = 1.0
+ else:
+ icon.alpha = 0.33
def __register_activate_cb(self, icon):
alert = Alert()
@@ -341,41 +320,43 @@ def __register_activate_cb(self, icon):
alert.props.title = _('Registration Successful')
alert.props.msg = _('You are now registered ' \
'with your school server.')
- self._my_icon.set_registered()
+ self._owner_icon.set_registered()
ok_icon = Icon(icon_name='dialog-ok')
alert.add_button(gtk.RESPONSE_OK, _('Ok'), ok_icon)
- self.add_alert(alert)
+ self._box.add_alert(alert)
alert.connect('response', self.__register_alert_response_cb)
def __register_alert_response_cb(self, alert, response_id):
- self.remove_alert()
+ self._box.remove_alert()
def set_resume_mode(self, resume_mode):
self._resume_mode = resume_mode
- for icon in self._box.get_children():
+ for icon in self.get_children():
if hasattr(icon, 'set_resume_mode'):
icon.set_resume_mode(self._resume_mode)
-class ActivityIcon(CanvasIcon):
+class ActivityIcon(EventIcon):
__gtype_name__ = 'SugarFavoriteActivityIcon'
_BORDER_WIDTH = style.zoom(3)
_MAX_RESUME_ENTRIES = 5
def __init__(self, activity_info):
- CanvasIcon.__init__(self, cache=True,
- file_name=activity_info.get_icon())
+ EventIcon.__init__(self, cache=True,
+ file_name=activity_info.get_icon())
self._activity_info = activity_info
self._journal_entries = []
self._hovering = False
self._resume_mode = True
- self.connect('hovering-changed', self.__hovering_changed_event_cb)
- self.connect('button-release-event', self.__button_release_event_cb)
+ self.connect('enter-notify-event', self.__enter_notify_event_cb)
+ self.connect('leave-notify-event', self.__leave_notify_event_cb)
+ self.connect_after('button-release-event',
+ self.__button_release_event_cb)
datastore.updated.connect(self.__datastore_listener_updated_cb)
datastore.deleted.connect(self.__datastore_listener_deleted_cb)
@@ -443,45 +424,47 @@ def __palette_activate_cb(self, palette):
def __palette_entry_activate_cb(self, palette, metadata):
self._resume(metadata)
- def __hovering_changed_event_cb(self, icon, hovering):
- self._hovering = hovering
- self.emit_paint_needed(0, 0, -1, -1)
+ def __enter_notify_event_cb(self, icon, event):
+ self._hovering = True
+ self.queue_draw()
+
+ def __leave_notify_event_cb(self, icon, event):
+ self._hovering = False
+ self.queue_draw()
+
+ def do_expose_event(self, event):
+ EventIcon.do_expose_event(self, event)
- def do_paint_above_children(self, cr, damaged_box):
if not self._hovering:
return
- width, height = self.get_allocation()
+ allocation = self.get_allocation()
+ width = allocation.width
+ height = allocation.height
- x = ActivityIcon._BORDER_WIDTH / 2.0
- y = ActivityIcon._BORDER_WIDTH / 2.0
+ x = allocation.x + ActivityIcon._BORDER_WIDTH / 2.0
+ y = allocation.y + ActivityIcon._BORDER_WIDTH / 2.0
width -= ActivityIcon._BORDER_WIDTH
height -= ActivityIcon._BORDER_WIDTH
radius = width / 10.0
+ cr = self.window.cairo_create()
cr.move_to(x + radius, y)
cr.arc(x + width - radius, y + radius, radius, math.pi * 1.5,
math.pi * 2.0)
- cr.arc(x + width - radius, x + height - radius, radius, 0,
+ cr.arc(x + width - radius, y + height - radius, radius, 0,
math.pi * 0.5)
cr.arc(x + radius, y + height - radius, radius, math.pi * 0.5, math.pi)
cr.arc(x + radius, y + radius, radius, math.pi, math.pi * 1.5)
- color = style.COLOR_SELECTION_GREY.get_int()
- hippo.cairo_set_source_rgba32(cr, color)
+ cr.set_source_color(style.COLOR_SELECTION_GREY.get_gdk_color())
cr.set_line_width(ActivityIcon._BORDER_WIDTH)
cr.stroke()
- def do_get_content_height_request(self, for_width):
- height, height = CanvasIcon.do_get_content_height_request(self,
- for_width)
- height += ActivityIcon._BORDER_WIDTH * 2
- return height, height
-
- def do_get_content_width_request(self):
- width, width = CanvasIcon.do_get_content_width_request(self)
- width += ActivityIcon._BORDER_WIDTH * 2
- return width, width
+ def do_size_request(self, req):
+ EventIcon.do_size_request(self, req)
+ req.height += ActivityIcon._BORDER_WIDTH * 2
+ req.width += ActivityIcon._BORDER_WIDTH * 2
def __button_release_event_cb(self, icon, event):
self._activate()
@@ -575,9 +558,10 @@ def __resume_entry_cb(self, menu_item, entry):
self.emit('entry-activate', entry)
-class CurrentActivityIcon(CanvasIcon, hippo.CanvasItem):
+class CurrentActivityIcon(EventIcon):
def __init__(self):
- CanvasIcon.__init__(self, cache=True)
+ EventIcon.__init__(self, icon_name='activity-journal',
+ pixel_size=style.STANDARD_ICON_SIZE, cache=True)
self._home_model = shell.get_model()
self._home_activity = self._home_model.get_active_activity()
@@ -587,7 +571,8 @@ def __init__(self):
self._home_model.connect('active-activity-changed',
self.__active_activity_changed_cb)
- self.connect('button-release-event', self.__button_release_event_cb)
+ self.connect_after('button-release-event',
+ self.__button_release_event_cb)
def __button_release_event_cb(self, icon, event):
window = self._home_model.get_active_activity().get_window()
@@ -596,7 +581,7 @@ def __button_release_event_cb(self, icon, event):
def _update(self):
self.props.file_name = self._home_activity.get_icon_path()
self.props.xo_color = self._home_activity.get_icon_color()
- self.props.size = style.STANDARD_ICON_SIZE
+ self.props.pixel_size = style.STANDARD_ICON_SIZE
if self.palette is not None:
self.palette.destroy()
@@ -623,7 +608,7 @@ class OwnerIcon(BuddyIcon):
}
def __init__(self, size):
- BuddyIcon.__init__(self, buddy=get_owner_instance(), size=size)
+ BuddyIcon.__init__(self, buddy=get_owner_instance(), pixel_size=size)
self.palette_invoker.cache_palette = True
@@ -652,9 +637,6 @@ def create_palette(self):
return palette
- def get_toplevel(self):
- return hippo.get_canvas_for_item(self).get_toplevel()
-
def __register_activate_cb(self, menuitem):
self.emit('register-activate')
diff --git a/src/jarabe/desktop/friendview.py b/src/jarabe/desktop/friendview.py
index 8dab35f519..01c2b71202 100644
--- a/src/jarabe/desktop/friendview.py
+++ b/src/jarabe/desktop/friendview.py
@@ -15,27 +15,30 @@
# 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 gtk
-from sugar.graphics.icon import CanvasIcon
from sugar.graphics import style
from jarabe.view.buddyicon import BuddyIcon
+from jarabe.view.eventicon import EventIcon
from jarabe.model import bundleregistry
-class FriendView(hippo.CanvasBox):
+class FriendView(gtk.VBox):
def __init__(self, buddy, **kwargs):
- hippo.CanvasBox.__init__(self, **kwargs)
+ gtk.VBox.__init__(self)
+
+ # round icon sizes to an even number so that it can be accurately
+ # centered in a larger bounding box also of even dimensions
+ size = style.LARGE_ICON_SIZE & ~1
self._buddy = buddy
self._buddy_icon = BuddyIcon(buddy)
- self._buddy_icon.props.size = style.LARGE_ICON_SIZE
- self.append(self._buddy_icon)
-
- self._activity_icon = CanvasIcon(size=style.LARGE_ICON_SIZE)
- self._activity_icon_visible = False
+ self._buddy_icon.props.pixel_size = size
+ self.add(self._buddy_icon)
+ self._buddy_icon.show()
+ self._activity_icon = EventIcon(pixel_size=size)
self._update_activity()
self._buddy.connect('notify::current-activity',
@@ -51,9 +54,9 @@ def _get_new_icon_name(self, ps_activity):
return None
def _remove_activity_icon(self):
- if self._activity_icon_visible:
+ if self._activity_icon.get_visible():
+ self._activity_icon.hide()
self.remove(self._activity_icon)
- self._activity_icon_visible = False
def __buddy_notify_current_activity_cb(self, buddy, pspec):
self._update_activity()
@@ -70,9 +73,9 @@ def _update_activity(self):
if name:
self._activity_icon.props.file_name = name
self._activity_icon.props.xo_color = self._buddy.props.color
- if not self._activity_icon_visible:
- self.append(self._activity_icon, hippo.PACK_EXPAND)
- self._activity_icon_visible = True
+ if not self._activity_icon.get_visible():
+ self.add(self._activity_icon)
+ self._activity_icon.show()
else:
self._remove_activity_icon()
diff --git a/src/jarabe/desktop/grid.py b/src/jarabe/desktop/grid.py
index eab403335c..65b33b230a 100644
--- a/src/jarabe/desktop/grid.py
+++ b/src/jarabe/desktop/grid.py
@@ -75,6 +75,9 @@ def add(self, child, width, height, x=None, y=None, locked=False):
if weight > 0:
self._detect_collisions(child)
+ def is_in_grid(self, child):
+ return child in self._children
+
def remove(self, child):
self._children.remove(child)
self.remove_weight(self._child_rects[child])
diff --git a/src/jarabe/desktop/groupbox.py b/src/jarabe/desktop/groupbox.py
index ed8f8ae79a..4fcd6c22ba 100644
--- a/src/jarabe/desktop/groupbox.py
+++ b/src/jarabe/desktop/groupbox.py
@@ -16,47 +16,40 @@
import logging
-import gobject
-import hippo
import gconf
from sugar.graphics import style
-from sugar.graphics.icon import CanvasIcon
from sugar.graphics.xocolor import XoColor
from jarabe.view.buddymenu import BuddyMenu
+from jarabe.view.eventicon import EventIcon
from jarabe.model.buddy import get_owner_instance
from jarabe.model import friends
from jarabe.desktop.friendview import FriendView
-from jarabe.desktop.spreadlayout import SpreadLayout
+from jarabe.desktop.viewcontainer import ViewContainer
+from jarabe.desktop.favoriteslayout import SpreadLayout
-class GroupBox(hippo.Canvas):
+class GroupBox(ViewContainer):
__gtype_name__ = 'SugarGroupBox'
def __init__(self):
logging.debug('STARTUP: Loading the group view')
- gobject.GObject.__init__(self)
-
- self._box = hippo.CanvasBox()
- self._box.props.background_color = style.COLOR_WHITE.get_int()
- self.set_root(self._box)
-
- self._friends = {}
-
- self._layout = SpreadLayout()
- self._box.set_layout(self._layout)
+ layout = SpreadLayout()
client = gconf.client_get_default()
color = XoColor(client.get_string('/desktop/sugar/user/color'))
+ owner_icon = EventIcon(icon_name='computer-xo', cache=True,
+ xo_color=color)
+ # Round off icon size to an even number to ensure that the icon
+ # is placed evenly in the grid
+ owner_icon.props.pixel_size = style.LARGE_ICON_SIZE & ~1
+ owner_icon.set_palette(BuddyMenu(get_owner_instance()))
- self._owner_icon = CanvasIcon(icon_name='computer-xo', cache=True,
- xo_color=color)
- self._owner_icon.props.size = style.LARGE_ICON_SIZE
+ ViewContainer.__init__(self, layout, owner_icon)
- self._owner_icon.set_palette(BuddyMenu(get_owner_instance()))
- self._layout.add(self._owner_icon)
+ self._friends = {}
friends_model = friends.get_model()
@@ -68,27 +61,15 @@ def __init__(self):
def add_friend(self, buddy_info):
icon = FriendView(buddy_info)
- self._layout.add(icon)
-
+ self.add(icon)
self._friends[buddy_info.get_key()] = icon
+ icon.show()
def _friend_added_cb(self, data_model, buddy_info):
self.add_friend(buddy_info)
def _friend_removed_cb(self, data_model, key):
icon = self._friends[key]
- self._layout.remove(icon)
+ self.remove(icon)
del self._friends[key]
icon.destroy()
-
- def do_size_allocate(self, allocation):
- width = allocation.width
- height = allocation.height
-
- min_w_, icon_width = self._owner_icon.get_width_request()
- min_h_, icon_height = self._owner_icon.get_height_request(icon_width)
- x = (width - icon_width) / 2
- y = (height - icon_height) / 2
- self._layout.move(self._owner_icon, x, y)
-
- hippo.Canvas.do_size_allocate(self, allocation)
diff --git a/src/jarabe/desktop/homebox.py b/src/jarabe/desktop/homebox.py
index 2ee6ae7d30..33c69658d7 100644
--- a/src/jarabe/desktop/homebox.py
+++ b/src/jarabe/desktop/homebox.py
@@ -45,7 +45,7 @@ def __init__(self):
gobject.GObject.__init__(self)
- self._favorites_view = favoritesview.FavoritesView()
+ self._favorites_box = favoritesview.FavoritesBox()
self._list_view = ActivitiesList()
self._toolbar = HomeToolbar()
@@ -78,14 +78,14 @@ def show_software_updates_alert(self):
if self._list_view in self.get_children():
self._list_view.add_alert(alert)
else:
- self._favorites_view.add_alert(alert)
+ self._favorites_box.add_alert(alert)
alert.connect('response', self.__software_update_response_cb)
def __software_update_response_cb(self, alert, response_id):
if self._list_view in self.get_children():
self._list_view.remove_alert()
else:
- self._favorites_view.remove_alert()
+ self._favorites_box.remove_alert()
if response_id != gtk.RESPONSE_REJECT:
update_trigger_file = os.path.expanduser('~/.sugar-update')
@@ -106,7 +106,7 @@ def __software_update_response_cb(self, alert, response_id):
def __toolbar_query_changed_cb(self, toolbar, query):
self._query = query.lower()
self._list_view.set_filter(self._query)
- self._favorites_view.set_filter(self._query)
+ self._favorites_box.set_filter(self._query)
def __toolbar_view_changed_cb(self, toolbar, view):
self._set_view(view)
@@ -116,12 +116,12 @@ def _set_view(self, view):
if self._list_view in self.get_children():
self.remove(self._list_view)
- if self._favorites_view not in self.get_children():
- self.add(self._favorites_view)
- self._favorites_view.show()
+ if self._favorites_box not in self.get_children():
+ self.add(self._favorites_box)
+ self._favorites_box.show()
elif view == _LIST_VIEW:
- if self._favorites_view in self.get_children():
- self.remove(self._favorites_view)
+ if self._favorites_box in self.get_children():
+ self.remove(self._favorites_box)
if self._list_view not in self.get_children():
self.add(self._list_view)
@@ -146,10 +146,10 @@ def focus_search_entry(self):
self._toolbar.search_entry.grab_focus()
def set_resume_mode(self, resume_mode):
- self._favorites_view.set_resume_mode(resume_mode)
+ self._favorites_box.set_resume_mode(resume_mode)
if resume_mode and self._query != '':
self._list_view.set_filter(self._query)
- self._favorites_view.set_filter(self._query)
+ self._favorites_box.set_filter(self._query)
class HomeToolbar(gtk.Toolbar):
diff --git a/src/jarabe/desktop/homewindow.py b/src/jarabe/desktop/homewindow.py
index 07deff7937..a5536c0e4e 100644
--- a/src/jarabe/desktop/homewindow.py
+++ b/src/jarabe/desktop/homewindow.py
@@ -57,6 +57,8 @@ def __init__(self):
self.realize()
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DESKTOP)
+ self.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_WHITE.get_gdk_color())
self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)
self.connect('visibility-notify-event',
diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py
index 20dc4138d2..1de37796df 100644
--- a/src/jarabe/desktop/meshbox.py
+++ b/src/jarabe/desktop/meshbox.py
@@ -21,26 +21,29 @@
import logging
import dbus
-import hippo
import glib
import gobject
import gtk
import gconf
-from sugar.graphics.icon import CanvasIcon, Icon
+from sugar.graphics.icon import Icon
from sugar.graphics import style
from sugar.graphics import palette
from sugar.graphics import iconentry
from sugar.graphics.menuitem import MenuItem
+from sugar.graphics.xocolor import XoColor
+from jarabe.desktop.snowflakelayout import SnowflakeLayout
from jarabe.model import neighborhood
from jarabe.model.buddy import get_owner_instance
from jarabe.view.buddyicon import BuddyIcon
-from jarabe.desktop.snowflakelayout import SnowflakeLayout
-from jarabe.desktop.spreadlayout import SpreadLayout
+from jarabe.view.buddymenu import BuddyMenu
+from jarabe.view.eventicon import EventIcon
from jarabe.desktop.networkviews import WirelessNetworkView
from jarabe.desktop.networkviews import OlpcMeshView
from jarabe.desktop.networkviews import SugarAdhocView
+from jarabe.desktop.viewcontainer import ViewContainer
+from jarabe.desktop.favoriteslayout import SpreadLayout
from jarabe.model import network
from jarabe.model.network import AccessPoint
from jarabe.model.olpcmesh import OlpcMeshManager
@@ -55,14 +58,13 @@
_FILTERED_ALPHA = 0.33
-class _ActivityIcon(CanvasIcon):
+class _ActivityIcon(EventIcon):
def __init__(self, model, file_name, xo_color,
size=style.STANDARD_ICON_SIZE):
- CanvasIcon.__init__(self, file_name=file_name,
- xo_color=xo_color,
- size=size)
+ EventIcon.__init__(self, file_name=file_name,
+ xo_color=xo_color, pixel_size=size)
self._model = model
- self.connect('activated', self._clicked_cb)
+ self.connect('button-release-event', self._button_release_cb)
def create_palette(self):
primary_text = glib.markup_escape_text(self._model.bundle.get_name())
@@ -91,15 +93,18 @@ def create_palette(self):
return p
+ def _button_release_cb(self, widget, event):
+ return self._clicked_cb(item=None)
+
def _clicked_cb(self, item):
bundle = self._model.get_bundle()
misc.launch(bundle, activity_id=self._model.activity_id,
color=self._model.get_color())
-class ActivityView(hippo.CanvasBox):
+class ActivityView(SnowflakeLayout):
def __init__(self, model):
- hippo.CanvasBox.__init__(self)
+ SnowflakeLayout.__init__(self)
self._model = model
self._model.connect('current-buddy-added', self.__buddy_added_cb)
@@ -107,11 +112,9 @@ def __init__(self, model):
self._icons = {}
- self._layout = SnowflakeLayout()
- self.set_layout(self._layout)
-
self._icon = self._create_icon()
- self._layout.add(self._icon, center=True)
+ self._icon.show()
+ self.add_icon(self._icon, center=True)
self._icon.palette_invoker.cache_palette = False
@@ -134,11 +137,13 @@ def __buddy_added_cb(self, activity, buddy):
def _add_buddy(self, buddy):
icon = BuddyIcon(buddy, style.STANDARD_ICON_SIZE)
self._icons[buddy.props.key] = icon
- self._layout.add(icon)
+ self.add_icon(icon)
+ icon.show()
def __buddy_removed_cb(self, activity, buddy):
icon = self._icons[buddy.props.key]
del self._icons[buddy.props.key]
+ self.remove(icon)
icon.destroy()
def set_filter(self, query):
@@ -401,13 +406,32 @@ def __properties_changed_cb(self, properties):
self._box.add_adhoc_networks(device)
+class MeshContainer(ViewContainer):
+ __gtype_name__ = 'SugarMeshContainer'
+
+ def __init__(self):
+
+ layout = SpreadLayout()
+
+ client = gconf.client_get_default()
+ color = XoColor(client.get_string('/desktop/sugar/user/color'))
+ owner_icon = EventIcon(icon_name='computer-xo', cache=True,
+ xo_color=color)
+ # Round off icon size to an even number to ensure that the icon
+ # is placed evenly in the grid
+ owner_icon.props.pixel_size = style.STANDARD_ICON_SIZE & ~1
+ owner_icon.set_palette(BuddyMenu(get_owner_instance()))
+
+ ViewContainer.__init__(self, layout, owner_icon)
+
+
class MeshBox(gtk.VBox):
__gtype_name__ = 'SugarMeshBox'
def __init__(self):
logging.debug('STARTUP: Loading the mesh view')
- gobject.GObject.__init__(self)
+ gtk.VBox.__init__(self)
self.wireless_networks = {}
self._adhoc_manager = None
@@ -420,23 +444,15 @@ def __init__(self):
self._buddy_to_activity = {}
self._suspended = True
self._query = ''
- self._owner_icon = None
self._toolbar = MeshToolbar()
self._toolbar.connect('query-changed', self._toolbar_query_changed_cb)
self.pack_start(self._toolbar, expand=False)
self._toolbar.show()
- canvas = hippo.Canvas()
- self.add(canvas)
- canvas.show()
-
- self._layout_box = hippo.CanvasBox( \
- background_color=style.COLOR_WHITE.get_int())
- canvas.set_root(self._layout_box)
-
- self._layout = SpreadLayout()
- self._layout_box.set_layout(self._layout)
+ self._mesh_container = MeshContainer()
+ self.add(self._mesh_container)
+ self._mesh_container.show()
for buddy_model in self._model.get_buddies():
self._add_buddy(buddy_model)
@@ -453,18 +469,6 @@ def __init__(self):
netmgr_observer = NetworkManagerObserver(self)
netmgr_observer.listen()
- def do_size_allocate(self, allocation):
- width = allocation.width
- height = allocation.height
-
- min_w_, icon_width = self._owner_icon.get_width_request()
- min_h_, icon_height = self._owner_icon.get_height_request(icon_width)
- x = (width - icon_width) / 2
- y = (height - icon_height) / 2 - style.GRID_CELL_SIZE
- self._layout.move(self._owner_icon, x, y)
-
- gtk.VBox.do_size_allocate(self, allocation)
-
def _buddy_added_cb(self, model, buddy_model):
self._add_buddy(buddy_model)
@@ -482,10 +486,11 @@ def _add_buddy(self, buddy_model):
self.__buddy_notify_current_activity_cb)
if buddy_model.props.current_activity is not None:
return
- icon = BuddyIcon(buddy_model)
if buddy_model.is_owner():
- self._owner_icon = icon
- self._layout.add(icon)
+ return
+ icon = BuddyIcon(buddy_model)
+ self._mesh_container.add(icon)
+ icon.show()
if hasattr(icon, 'set_filter'):
icon.set_filter(self._query)
@@ -495,9 +500,8 @@ def _add_buddy(self, buddy_model):
def _remove_buddy(self, buddy_model):
logging.debug('MeshBox._remove_buddy')
icon = self._buddies[buddy_model.props.key]
- self._layout.remove(icon)
+ self._mesh_container.remove(icon)
del self._buddies[buddy_model.props.key]
- icon.destroy()
def __buddy_notify_current_activity_cb(self, buddy_model, pspec):
logging.debug('MeshBox.__buddy_notify_current_activity_cb %s',
@@ -510,7 +514,8 @@ def __buddy_notify_current_activity_cb(self, buddy_model, pspec):
def _add_activity(self, activity_model):
icon = ActivityView(activity_model)
- self._layout.add(icon)
+ self._mesh_container.add(icon)
+ icon.show()
if hasattr(icon, 'set_filter'):
icon.set_filter(self._query)
@@ -519,9 +524,8 @@ def _add_activity(self, activity_model):
def _remove_activity(self, activity_model):
icon = self._activities[activity_model.activity_id]
- self._layout.remove(icon)
+ self._mesh_container.remove(icon)
del self._activities[activity_model.activity_id]
- icon.destroy()
# add AP to its corresponding network icon on the desktop,
# creating one if it doesn't already exist
@@ -533,7 +537,8 @@ def _add_ap_to_network(self, ap):
# this is a new network
icon = WirelessNetworkView(ap)
self.wireless_networks[hash_value] = icon
- self._layout.add(icon)
+ self._mesh_container.add(icon)
+ icon.show()
if hasattr(icon, 'set_filter'):
icon.set_filter(self._query)
@@ -541,7 +546,7 @@ def _remove_net_if_empty(self, net, hash_value):
# remove a network if it has no APs left
if net.num_aps() == 0:
net.disconnect()
- self._layout.remove(net)
+ self._mesh_container.remove(net)
del self.wireless_networks[hash_value]
def _ap_props_changed_cb(self, ap, old_hash_value):
@@ -619,18 +624,20 @@ def add_adhoc_networks(self, device):
def remove_adhoc_networks(self):
for icon in self._adhoc_networks:
- self._layout.remove(icon)
+ self._mesh_container.remove(icon)
self._adhoc_networks = []
self._adhoc_manager.stop_listening()
def _add_adhoc_network_icon(self, channel):
icon = SugarAdhocView(channel)
- self._layout.add(icon)
+ self._mesh_container.add(icon)
+ icon.show()
self._adhoc_networks.append(icon)
def _add_olpc_mesh_icon(self, mesh_mgr, channel):
icon = OlpcMeshView(mesh_mgr, channel)
- self._layout.add(icon)
+ self._mesh_container.add(icon)
+ icon.show()
self._mesh.append(icon)
def enable_olpc_mesh(self, mesh_device):
@@ -648,13 +655,13 @@ def enable_olpc_mesh(self, mesh_device):
logging.debug('removing OLPC mesh IBSS')
net.remove_all_aps()
net.disconnect()
- self._layout.remove(net)
+ self._mesh_container.remove(net)
del self.wireless_networks[hash_value]
def disable_olpc_mesh(self, mesh_device):
for icon in self._mesh:
icon.disconnect()
- self._layout.remove(icon)
+ self._mesh_container.remove(icon)
self._mesh = []
def suspend(self):
@@ -671,7 +678,7 @@ def resume(self):
def _toolbar_query_changed_cb(self, toolbar, query):
self._query = query.lower()
- for icon in self._layout_box.get_children():
+ for icon in self._mesh_container.get_children():
if hasattr(icon, 'set_filter'):
icon.set_filter(self._query)
diff --git a/src/jarabe/desktop/networkviews.py b/src/jarabe/desktop/networkviews.py
index f42bfed839..d2531bf567 100644
--- a/src/jarabe/desktop/networkviews.py
+++ b/src/jarabe/desktop/networkviews.py
@@ -33,7 +33,7 @@
from sugar.util import unique_id
from sugar import profile
-from jarabe.view.pulsingicon import CanvasPulsingIcon
+from jarabe.view.pulsingicon import EventPulsingIcon
from jarabe.desktop import keydialog
from jarabe.model import network
from jarabe.model.network import Settings
@@ -48,10 +48,10 @@
_FILTERED_ALPHA = 0.33
-class WirelessNetworkView(CanvasPulsingIcon):
+class WirelessNetworkView(EventPulsingIcon):
def __init__(self, initial_ap):
- CanvasPulsingIcon.__init__(self, size=style.STANDARD_ICON_SIZE,
- cache=True)
+ EventPulsingIcon.__init__(self, pixel_size=style.STANDARD_ICON_SIZE,
+ cache=True)
self._bus = dbus.SystemBus()
self._access_points = {initial_ap.model.object_path: initial_ap}
self._active_ap = None
@@ -255,9 +255,9 @@ def _update_color(self):
self.props.base_color = self._color
if self._filtered:
self.props.pulsing = False
- self.alpha = _FILTERED_ALPHA
+ self.props.alpha = _FILTERED_ALPHA
else:
- self.alpha = 1.0
+ self.props.alpha = 1.0
def _disconnect_activate_cb(self, item):
ap_paths = self._access_points.keys()
@@ -436,7 +436,7 @@ def disconnect(self):
dbus_interface=network.NM_WIRELESS_IFACE)
-class SugarAdhocView(CanvasPulsingIcon):
+class SugarAdhocView(EventPulsingIcon):
"""To mimic the mesh behavior on devices where mesh hardware is
not available we support the creation of an Ad-hoc network on
three channels 1, 6, 11. This is the class for an icon
@@ -448,9 +448,10 @@ class SugarAdhocView(CanvasPulsingIcon):
_NAME = 'Ad-hoc Network '
def __init__(self, channel):
- CanvasPulsingIcon.__init__(self,
- icon_name=self._ICON_NAME + str(channel),
- size=style.STANDARD_ICON_SIZE, cache=True)
+ EventPulsingIcon.__init__(self,
+ icon_name=self._ICON_NAME + str(channel),
+ pixel_size=style.STANDARD_ICON_SIZE,
+ cache=True)
self._bus = dbus.SystemBus()
self._channel = channel
self._disconnect_item = None
@@ -572,10 +573,11 @@ def set_filter(self, query):
self._update_color()
-class OlpcMeshView(CanvasPulsingIcon):
+class OlpcMeshView(EventPulsingIcon):
def __init__(self, mesh_mgr, channel):
- CanvasPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME,
- size=style.STANDARD_ICON_SIZE, cache=True)
+ EventPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME,
+ pixel_size=style.STANDARD_ICON_SIZE,
+ cache=True)
self._bus = dbus.SystemBus()
self._channel = channel
self._mesh_mgr = mesh_mgr
diff --git a/src/jarabe/desktop/snowflakelayout.py b/src/jarabe/desktop/snowflakelayout.py
index e4963ba9f8..25cae76586 100644
--- a/src/jarabe/desktop/snowflakelayout.py
+++ b/src/jarabe/desktop/snowflakelayout.py
@@ -16,8 +16,7 @@
import math
-import gobject
-import hippo
+import gtk
from sugar.graphics import style
@@ -26,54 +25,71 @@
_CHILDREN_FACTOR = style.zoom(3)
-class SnowflakeLayout(gobject.GObject, hippo.CanvasLayout):
+class SnowflakeLayout(gtk.Container):
__gtype_name__ = 'SugarSnowflakeLayout'
def __init__(self):
- gobject.GObject.__init__(self)
+ gtk.Container.__init__(self)
+ self.set_has_window(False)
self._nflakes = 0
- self._box = None
-
- def add(self, child, center=False):
+ self._children = {}
+
+ def do_realize(self):
+ # FIXME what is this for?
+ self.set_flags(gtk.REALIZED)
+ self.set_window(self.get_parent_window())
+ self.style.attach(self.window)
+ for child in self._children.keys():
+ child.set_parent_window(self.get_parent_window())
+ self.queue_resize()
+
+ def do_add(self, child):
+ if child.flags() & gtk.REALIZED:
+ child.set_parent_window(self.get_parent_window())
+ child.set_parent(self)
+
+ def do_forall(self, include_internals, callback, data):
+ for child in self._children.keys():
+ callback(child, data)
+
+ def do_remove(self, child):
+ child.unparent()
+
+ def add_icon(self, child, center=False):
if not center:
self._nflakes += 1
- self._box.append(child)
-
- box_child = self._box.find_box_child(child)
- box_child.is_center = center
+ self._children[child] = center
+ self.add(child)
def remove(self, child):
- box_child = self._box.find_box_child(child)
- if not box_child.is_center:
- self._nflakes -= 1
-
- self._box.remove(child)
+ if not child in self._children:
+ return
- def do_set_box(self, box):
- self._box = box
+ if not self._children[child]: # not centered
+ self._nflakes -= 1
- def do_get_height_request(self, for_width):
- size = self._calculate_size()
- return (size, size)
+ del self._children[child]
+ self.remove(child)
- def do_get_width_request(self):
+ def do_size_request(self, requisition):
size = self._calculate_size()
- return (size, size)
+ requisition.width = size
+ requisition.height = size
- def do_allocate(self, x, y, width, height,
- req_width, req_height, origin_changed):
+ def do_size_allocate(self, allocation):
r = self._get_radius()
index = 0
- for child in self._box.get_layout_children():
- min_width, child_width = child.get_width_request()
- min_height, child_height = child.get_height_request(child_width)
+ for child, centered in self._children.items():
+ child_width, child_height = child.size_request()
+ rect = gtk.gdk.Rectangle(0, 0, child_width, child_height)
- if child.is_center:
- child.allocate(x + (width - child_width) / 2,
- y + (height - child_height) / 2,
- child_width, child_height, origin_changed)
+ width = allocation.width - child_width
+ height = allocation.height - child_height
+ if centered:
+ rect.x = allocation.x + width / 2
+ rect.y = allocation.y + height / 2
else:
angle = 2 * math.pi * index / self._nflakes
@@ -83,29 +99,26 @@ def do_allocate(self, x, y, width, height,
dx = math.cos(angle) * r
dy = math.sin(angle) * r
- child_x = int(x + (width - child_width) / 2 + dx)
- child_y = int(y + (height - child_height) / 2 + dy)
-
- child.allocate(child_x, child_y, child_width,
- child_height, origin_changed)
+ rect.x = int(allocation.x + width / 2 + dx)
+ rect.y = int(allocation.y + height / 2 + dy)
index += 1
+ child.size_allocate(rect)
+
def _get_radius(self):
radius = int(_BASE_DISTANCE + _CHILDREN_FACTOR * self._nflakes)
- for child in self._box.get_layout_children():
- if child.is_center:
- [min_w, child_w] = child.get_width_request()
- [min_h, child_h] = child.get_height_request(child_w)
+ for child, centered in self._children.items():
+ if centered:
+ child_w, child_h = child.size_request()
radius += max(child_w, child_h) / 2
return radius
def _calculate_size(self):
thickness = 0
- for child in self._box.get_layout_children():
- [min_width, child_width] = child.get_width_request()
- [min_height, child_height] = child.get_height_request(child_width)
- thickness = max(thickness, max(child_width, child_height))
+ for child in self._children.keys():
+ width, height = child.size_request()
+ thickness = max(thickness, max(width, height))
return self._get_radius() * 2 + thickness
diff --git a/src/jarabe/desktop/spreadlayout.py b/src/jarabe/desktop/spreadlayout.py
deleted file mode 100644
index b5c623e492..0000000000
--- a/src/jarabe/desktop/spreadlayout.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# 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 math
-
-import hippo
-import gobject
-import gtk
-
-from sugar.graphics import style
-
-from jarabe.desktop.grid import Grid
-
-
-_CELL_SIZE = 4.0
-
-
-class SpreadLayout(gobject.GObject, hippo.CanvasLayout):
- __gtype_name__ = 'SugarSpreadLayout'
-
- def __init__(self):
- gobject.GObject.__init__(self)
- self._box = None
-
- min_width, width = self.do_get_width_request()
- min_height, height = self.do_get_height_request(width)
-
- self._grid = Grid(int(width / _CELL_SIZE), int(height / _CELL_SIZE))
- self._grid.connect('child-changed', self._grid_child_changed_cb)
-
- def add(self, child):
- self._box.append(child)
-
- width, height = self._get_child_grid_size(child)
- self._grid.add(child, width, height)
-
- def remove(self, child):
- self._grid.remove(child)
- self._box.remove(child)
-
- def move(self, child, x, y):
- self._grid.move(child, x / _CELL_SIZE, y / _CELL_SIZE, locked=True)
-
- 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 do_allocate(self, x, y, width, height,
- req_width, req_height, origin_changed):
- for child in self._box.get_layout_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)
-
- rect = self._grid.get_child_rect(child.item)
- child.allocate(int(round(rect.x * _CELL_SIZE)),
- int(round(rect.y * _CELL_SIZE)),
- child_width,
- child_height,
- origin_changed)
-
- def _get_child_grid_size(self, child):
- min_width, width = child.get_width_request()
- min_height, height = child.get_height_request(width)
- width = math.ceil(width / _CELL_SIZE)
- height = math.ceil(height / _CELL_SIZE)
-
- return int(width), int(height)
-
- def _grid_child_changed_cb(self, grid, child):
- child.emit_request_changed()
diff --git a/src/jarabe/desktop/transitionbox.py b/src/jarabe/desktop/transitionbox.py
index fd2112c90c..54a70de088 100644
--- a/src/jarabe/desktop/transitionbox.py
+++ b/src/jarabe/desktop/transitionbox.py
@@ -14,7 +14,6 @@
# 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
@@ -34,37 +33,10 @@ def __init__(self, icon, start_size, end_size):
def next_frame(self, current):
d = (self.end_size - self.start_size) * current
- self._icon.props.size = int(self.start_size + d)
+ self._icon.props.pixel_size = int(self.start_size + d)
-class _Layout(gobject.GObject, hippo.CanvasLayout):
- __gtype_name__ = 'SugarTransitionBoxLayout'
-
- 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, 0
-
- def do_get_width_request(self):
- return 0, 0
-
- def do_allocate(self, x, y, width, height,
- req_width, req_height, origin_changed):
- for child in self._box.get_layout_children():
- min_width, child_width = child.get_width_request()
- min_height, child_height = child.get_height_request(child_width)
-
- child.allocate(x + (width - child_width) / 2,
- y + (height - child_height) / 2,
- child_width, child_height, origin_changed)
-
-
-class TransitionBox(hippo.Canvas):
+class TransitionBox(BuddyIcon):
__gtype_name__ = 'SugarTransitionBox'
__gsignals__ = {
@@ -72,18 +44,8 @@ class TransitionBox(hippo.Canvas):
}
def __init__(self):
- gobject.GObject.__init__(self)
-
- self._box = hippo.CanvasBox()
- self._box.props.background_color = style.COLOR_WHITE.get_int()
- self.set_root(self._box)
-
- self._layout = _Layout()
- self._box.set_layout(self._layout)
-
- self._my_icon = BuddyIcon(buddy=get_owner_instance(),
- size=style.XLARGE_ICON_SIZE)
- self._box.append(self._my_icon)
+ BuddyIcon.__init__(self, buddy=get_owner_instance(),
+ pixel_size=style.XLARGE_ICON_SIZE)
self._animator = animator.Animator(0.3)
self._animator.connect('completed', self._animation_completed_cb)
@@ -92,8 +54,6 @@ def _animation_completed_cb(self, anim):
self.emit('completed')
def start_transition(self, start_size, end_size):
- self._my_icon.props.size = start_size
-
self._animator.remove_all()
- self._animator.add(_Animation(self._my_icon, start_size, end_size))
+ self._animator.add(_Animation(self, start_size, end_size))
self._animator.start()
diff --git a/src/jarabe/desktop/viewcontainer.py b/src/jarabe/desktop/viewcontainer.py
new file mode 100644
index 0000000000..1c76fb1a73
--- /dev/null
+++ b/src/jarabe/desktop/viewcontainer.py
@@ -0,0 +1,82 @@
+# Copyright (C) 2011-2012 One Laptop Per Child
+# Copyright (C) 2010 Tomeu Vizoso
+# Copyright (C) 2011 Walter Bender
+# Copyright (C) 2011 Raul Gutierrez Segales
+#
+# 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 gtk
+
+
+class ViewContainer(gtk.Container):
+ __gtype_name__ = 'SugarViewContainer'
+
+ def __init__(self, layout, owner_icon, activity_icon=None, **kwargs):
+ gtk.Container.__init__(self, **kwargs)
+ self.set_has_window(False)
+
+ self._activity_icon = None
+ self._owner_icon = None
+ self._layout = None
+
+ self._children = []
+ self.set_layout(layout)
+
+ if owner_icon:
+ self._owner_icon = owner_icon
+ self.add(self._owner_icon)
+ self._owner_icon.show()
+
+ if activity_icon:
+ self._activity_icon = activity_icon
+ self.add(self._activity_icon)
+ self._activity_icon.show()
+
+ def do_add(self, child):
+ if child != self._owner_icon and child != self._activity_icon:
+ self._children.append(child)
+ if child.flags() & gtk.REALIZED:
+ child.set_parent_window(self.get_parent_window())
+ child.set_parent(self)
+
+ def do_remove(self, child):
+ was_visible = child.get_visible()
+ if child in self._children:
+ self._children.remove(child)
+ child.unparent()
+ self._layout.remove(child)
+ if was_visible and self.get_visible():
+ self.queue_resize()
+
+ def do_size_allocate(self, allocation):
+ self.allocation = allocation
+ if self._owner_icon:
+ self._layout.setup(allocation, self._owner_icon,
+ self._activity_icon)
+
+ self._layout.allocate_children(allocation, self._children)
+
+ def do_forall(self, include_internals, callback, callback_data):
+ for child in self._children:
+ callback(child, callback_data)
+ if self._owner_icon:
+ callback(self._owner_icon, callback_data)
+ if self._activity_icon:
+ callback(self._activity_icon, callback_data)
+
+ def set_layout(self, layout):
+ for child in self.get_children():
+ self.remove(child)
+ self._layout = layout
diff --git a/src/jarabe/journal/detailview.py b/src/jarabe/journal/detailview.py
index aa8c039812..628af015ad 100644
--- a/src/jarabe/journal/detailview.py
+++ b/src/jarabe/journal/detailview.py
@@ -19,10 +19,9 @@
import gobject
import gtk
-import hippo
from sugar.graphics import style
-from sugar.graphics.icon import CanvasIcon
+from sugar.graphics.icon import Icon
from jarabe.journal.expandedentry import ExpandedEntry
from jarabe.journal import model
@@ -39,21 +38,15 @@ def __init__(self, **kwargs):
self._metadata = None
self._expanded_entry = None
- canvas = hippo.Canvas()
-
- self._root = hippo.CanvasBox()
- self._root.props.background_color = style.COLOR_PANEL_GREY.get_int()
- canvas.set_root(self._root)
+ gobject.GObject.__init__(self, **kwargs)
+ gtk.VBox.__init__(self)
back_bar = BackBar()
back_bar.connect('button-release-event',
self.__back_bar_release_event_cb)
- self._root.append(back_bar)
-
- gobject.GObject.__init__(self, **kwargs)
+ self.pack_start(back_bar, expand=False)
- self.pack_start(canvas)
- canvas.show()
+ self.show_all()
def _fav_icon_activated_cb(self, fav_icon):
keep = not self._expanded_entry.get_keep()
@@ -67,8 +60,9 @@ def __back_bar_release_event_cb(self, back_bar, event):
def _update_view(self):
if self._expanded_entry is None:
self._expanded_entry = ExpandedEntry()
- self._root.append(self._expanded_entry, hippo.PACK_EXPAND)
+ self.pack_start(self._expanded_entry)
self._expanded_entry.set_metadata(self._metadata)
+ self.show_all()
def refresh(self):
logging.debug('DetailView.refresh')
@@ -86,34 +80,37 @@ def set_metadata(self, metadata):
type=object, getter=get_metadata, setter=set_metadata)
-class BackBar(hippo.CanvasBox):
+class BackBar(gtk.EventBox):
def __init__(self):
- hippo.CanvasBox.__init__(self,
- orientation=hippo.ORIENTATION_HORIZONTAL,
- border=style.LINE_WIDTH,
- background_color=style.COLOR_PANEL_GREY.get_int(),
- border_color=style.COLOR_SELECTION_GREY.get_int(),
- padding=style.DEFAULT_PADDING,
- padding_left=style.DEFAULT_SPACING,
- spacing=style.DEFAULT_SPACING)
-
- icon = CanvasIcon(icon_name='go-previous',
- size=style.SMALL_ICON_SIZE,
- fill_color=style.COLOR_TOOLBAR_GREY.get_svg())
- self.append(icon)
-
- label = hippo.CanvasText(text=_('Back'),
- font_desc=style.FONT_NORMAL.get_pango_desc())
- self.append(label)
+ gtk.EventBox.__init__(self)
+ self.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_PANEL_GREY.get_gdk_color())
+ hbox = gtk.HBox(spacing=style.DEFAULT_PADDING)
+ hbox.set_border_width(style.DEFAULT_PADDING)
+ icon = Icon(icon_name='go-previous', icon_size=gtk.ICON_SIZE_MENU,
+ fill_color=style.COLOR_TOOLBAR_GREY.get_svg())
+ hbox.pack_start(icon, False, False)
+
+ label = gtk.Label()
+ label.set_text(_('Back'))
+ halign = gtk.Alignment(0, 0.5, 0, 1)
+ halign.add(label)
+ hbox.pack_start(halign, True, True)
+ hbox.show()
+ self.add(hbox)
if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
- self.reverse()
+ hbox.reverse()
+
+ self.connect('enter-notify-event', self.__enter_notify_event_cb)
+ self.connect('leave-notify-event', self.__leave_notify_event_cb)
- self.connect('motion-notify-event', self.__motion_notify_event_cb)
+ def __enter_notify_event_cb(self, box, event):
+ box.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_SELECTION_GREY.get_gdk_color())
+ return False
- def __motion_notify_event_cb(self, box, event):
- if event.detail == hippo.MOTION_DETAIL_ENTER:
- box.props.background_color = style.COLOR_SELECTION_GREY.get_int()
- elif event.detail == hippo.MOTION_DETAIL_LEAVE:
- box.props.background_color = style.COLOR_PANEL_GREY.get_int()
+ def __leave_notify_event_cb(self, box, event):
+ box.modify_bg(gtk.STATE_NORMAL,
+ style.COLOR_PANEL_GREY.get_gdk_color())
return False
diff --git a/src/jarabe/journal/expandedentry.py b/src/jarabe/journal/expandedentry.py
index 03f8cd13a4..e0c603fd31 100644
--- a/src/jarabe/journal/expandedentry.py
+++ b/src/jarabe/journal/expandedentry.py
@@ -20,7 +20,6 @@
import time
import os
-import hippo
import cairo
import gobject
import glib
@@ -28,158 +27,144 @@
import simplejson
from sugar.graphics import style
-from sugar.graphics.icon import CanvasIcon
from sugar.graphics.xocolor import XoColor
-from sugar.graphics.canvastextview import CanvasTextView
from sugar.util import format_size
from jarabe.journal.keepicon import KeepIcon
from jarabe.journal.palettes import ObjectPalette, BuddyPalette
from jarabe.journal import misc
from jarabe.journal import model
+from jarabe.view.eventicon import EventIcon
-class Separator(hippo.CanvasBox, hippo.CanvasItem):
+class Separator(gtk.VBox):
def __init__(self, orientation):
- hippo.CanvasBox.__init__(self,
- background_color=style.COLOR_PANEL_GREY.get_int())
-
- if orientation == hippo.ORIENTATION_VERTICAL:
- self.props.box_width = style.LINE_WIDTH
- else:
- self.props.box_height = style.LINE_WIDTH
+ gtk.VBox.__init__(self,
+ background_color=style.COLOR_PANEL_GREY.get_gdk_color())
-class BuddyList(hippo.CanvasBox):
+class BuddyList(gtk.Alignment):
def __init__(self, buddies):
- hippo.CanvasBox.__init__(self, xalign=hippo.ALIGNMENT_START,
- orientation=hippo.ORIENTATION_HORIZONTAL)
+ gtk.Alignment.__init__(self, 0, 0, 0, 0)
+ hbox = gtk.HBox()
for buddy in buddies:
nick_, color = buddy
- hbox = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL)
- icon = CanvasIcon(icon_name='computer-xo',
- xo_color=XoColor(color),
- size=style.STANDARD_ICON_SIZE)
+ icon = EventIcon(icon_name='computer-xo',
+ xo_color=XoColor(color),
+ pixel_size=style.STANDARD_ICON_SIZE)
icon.set_palette(BuddyPalette(buddy))
- hbox.append(icon)
- self.append(hbox)
+ hbox.pack_start(icon)
+ self.add(hbox)
-class ExpandedEntry(hippo.CanvasBox):
+class ExpandedEntry(gtk.EventBox):
def __init__(self):
- hippo.CanvasBox.__init__(self)
- self.props.orientation = hippo.ORIENTATION_VERTICAL
- self.props.background_color = style.COLOR_WHITE.get_int()
- self.props.padding_top = style.DEFAULT_SPACING * 3
+ gtk.EventBox.__init__(self)
+ self._vbox = gtk.VBox()
+ self.add(self._vbox)
self._metadata = None
self._update_title_sid = None
- # Create header
- header = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL,
- padding=style.DEFAULT_PADDING,
- padding_right=style.GRID_CELL_SIZE,
- spacing=style.DEFAULT_SPACING)
- self.append(header)
-
- # Create two column body
+ self.modify_bg(gtk.STATE_NORMAL, style.COLOR_WHITE.get_gdk_color())
- body = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL,
- spacing=style.DEFAULT_SPACING * 3,
- padding_left=style.GRID_CELL_SIZE,
- padding_right=style.GRID_CELL_SIZE,
- padding_top=style.DEFAULT_SPACING * 3)
+ # Create a header
+ header = gtk.HBox()
+ self._vbox.pack_start(header, False, False, style.DEFAULT_SPACING * 2)
- self.append(body, hippo.PACK_EXPAND)
+ # Create a two-column body
+ body_box = gtk.EventBox()
+ body_box.set_border_width(style.DEFAULT_SPACING)
+ body_box.modify_bg(gtk.STATE_NORMAL, style.COLOR_WHITE.get_gdk_color())
+ self._vbox.pack_start(body_box)
+ body = gtk.HBox()
+ body_box.add(body)
- first_column = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL,
- spacing=style.DEFAULT_SPACING)
- body.append(first_column)
+ first_column = gtk.VBox()
+ body.pack_start(first_column, False, False, style.DEFAULT_SPACING)
- second_column = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL,
- spacing=style.DEFAULT_SPACING)
- body.append(second_column, hippo.PACK_EXPAND)
+ second_column = gtk.VBox()
+ body.pack_start(second_column)
# Header
-
self._keep_icon = self._create_keep_icon()
- header.append(self._keep_icon)
+ header.pack_start(self._keep_icon, False, False, style.DEFAULT_SPACING)
self._icon = None
- self._icon_box = hippo.CanvasBox()
- header.append(self._icon_box)
+ self._icon_box = gtk.HBox()
+ header.pack_start(self._icon_box, False, False, style.DEFAULT_SPACING)
self._title = self._create_title()
- header.append(self._title, hippo.PACK_EXPAND)
+ header.pack_start(self._title)
# TODO: create a version list popup instead of a date label
self._date = self._create_date()
- header.append(self._date)
+ header.pack_start(self._date, False, False, style.DEFAULT_SPACING)
if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
header.reverse()
- # First column
-
- self._preview_box = hippo.CanvasBox()
- first_column.append(self._preview_box)
+ # First body column
+ self._preview_box = gtk.Frame()
+ first_column.pack_start(self._preview_box, expand=False)
- self._technical_box = hippo.CanvasBox()
- first_column.append(self._technical_box)
-
- # Second column
+ self._technical_box = gtk.VBox()
+ first_column.pack_start(self._technical_box)
+ # Second body column
description_box, self._description = self._create_description()
- second_column.append(description_box)
+ second_column.pack_start(description_box, True, True,
+ style.DEFAULT_SPACING)
tags_box, self._tags = self._create_tags()
- second_column.append(tags_box)
+ second_column.pack_start(tags_box, True, True,
+ style.DEFAULT_SPACING)
+
+ self._buddy_list = gtk.VBox()
+ second_column.pack_start(self._buddy_list)
- self._buddy_list = hippo.CanvasBox()
- second_column.append(self._buddy_list)
+ self.show_all()
def set_metadata(self, metadata):
if self._metadata == metadata:
return
self._metadata = metadata
- self._keep_icon.keep = (str(metadata.get('keep', 0)) == '1')
+ self._keep_icon.set_active(int(metadata.get('keep', 0)) == 1)
self._icon = self._create_icon()
- self._icon_box.clear()
- self._icon_box.append(self._icon)
-
- self._date.props.text = misc.get_date(metadata)
+ self._icon_box.foreach(self._icon_box.remove)
+ self._icon_box.pack_start(self._icon, False, False)
- title = self._title.props.widget
- title.props.text = metadata.get('title', _('Untitled'))
- title.props.editable = model.is_editable(metadata)
+ self._date.set_text(misc.get_date(metadata))
- self._preview_box.clear()
- self._preview_box.append(self._create_preview())
+ self._title.set_text(metadata.get('title', _('Untitled')))
- self._technical_box.clear()
- self._technical_box.append(self._create_technical())
+ if self._preview_box.get_child():
+ self._preview_box.remove(self._preview_box.get_child())
+ self._preview_box.add(self._create_preview())
- self._buddy_list.clear()
- self._buddy_list.append(self._create_buddy_list())
+ self._technical_box.foreach(self._technical_box.remove)
+ self._technical_box.pack_start(self._create_technical(),
+ False, False, style.DEFAULT_SPACING)
- description = self._description.text_view_widget
- description.props.buffer.props.text = metadata.get('description', '')
- description.props.editable = model.is_editable(metadata)
+ self._buddy_list.foreach(self._buddy_list.remove)
+ self._buddy_list.pack_start(self._create_buddy_list(), False, False,
+ style.DEFAULT_SPACING)
- tags = self._tags.text_view_widget
- tags.props.buffer.props.text = metadata.get('tags', '')
- tags.props.editable = model.is_editable(metadata)
+ description = metadata.get('description', '')
+ self._description.get_buffer().set_text(description)
+ tags = metadata.get('tags', '')
+ self._tags.get_buffer().set_text(tags)
def _create_keep_icon(self):
- keep_icon = KeepIcon(False)
- keep_icon.connect('activated', self._keep_icon_activated_cb)
+ keep_icon = KeepIcon()
+ keep_icon.connect('toggled', self._keep_icon_toggled_cb)
return keep_icon
def _create_icon(self):
- icon = CanvasIcon(file_name=misc.get_icon_name(self._metadata))
+ icon = EventIcon(file_name=misc.get_icon_name(self._metadata))
icon.connect_after('button-release-event',
self._icon_button_release_event_cb)
@@ -202,17 +187,17 @@ def _create_title(self):
entry.modify_bg(gtk.STATE_INSENSITIVE, bg_color)
entry.modify_base(gtk.STATE_INSENSITIVE, bg_color)
- return hippo.CanvasWidget(widget=entry)
+ return entry
def _create_date(self):
- date = hippo.CanvasText(xalign=hippo.ALIGNMENT_START,
- font_desc=style.FONT_NORMAL.get_pango_desc())
+ date = gtk.Label()
return date
def _create_preview(self):
width = style.zoom(320)
height = style.zoom(240)
- box = hippo.CanvasBox()
+ box = gtk.EventBox()
+ box.modify_bg(gtk.STATE_NORMAL, style.COLOR_WHITE.get_gdk_color())
if len(self._metadata.get('preview', '')) > 4:
if self._metadata['preview'][1:4] == 'PNG':
@@ -225,7 +210,17 @@ def _create_preview(self):
png_file = StringIO.StringIO(preview_data)
try:
+ # Load image and scale to dimensions
surface = cairo.ImageSurface.create_from_png(png_file)
+ png_width = surface.get_width()
+ png_height = surface.get_height()
+ pixmap = gtk.gdk.Pixmap(None, png_width, png_height, 24)
+ cr = pixmap.cairo_create()
+ cr.set_source_surface(surface, 0, 0)
+ cr.scale(width / png_width, height / png_height)
+ cr.paint()
+
+ im = gtk.image_new_from_pixmap(pixmap, None)
has_preview = True
except Exception:
logging.exception('Error while loading the preview')
@@ -234,50 +229,35 @@ def _create_preview(self):
has_preview = False
if has_preview:
- preview_box = hippo.CanvasImage(image=surface,
- border=style.LINE_WIDTH,
- border_color=style.COLOR_BUTTON_GREY.get_int(),
- xalign=hippo.ALIGNMENT_CENTER,
- yalign=hippo.ALIGNMENT_CENTER,
- scale_width=width,
- scale_height=height)
+ box.add(im)
else:
- preview_box = hippo.CanvasText(text=_('No preview'),
- font_desc=style.FONT_NORMAL.get_pango_desc(),
- xalign=hippo.ALIGNMENT_CENTER,
- yalign=hippo.ALIGNMENT_CENTER,
- border=style.LINE_WIDTH,
- border_color=style.COLOR_BUTTON_GREY.get_int(),
- color=style.COLOR_BUTTON_GREY.get_int(),
- box_width=width,
- box_height=height)
- preview_box.connect_after('button-release-event',
- self._preview_box_button_release_event_cb)
- box.append(preview_box)
+ label = gtk.Label()
+ label.set_text(_('No preview'))
+ label.set_size_request(width, height)
+ box.add(label)
+
+ box.connect_after('button-release-event',
+ self._preview_box_button_release_event_cb)
return box
def _create_technical(self):
- vbox = hippo.CanvasBox()
+ vbox = gtk.VBox()
vbox.props.spacing = style.DEFAULT_SPACING
- lines = [
- _('Kind: %s') % (self._metadata.get('mime_type') or _('Unknown'),),
- _('Date: %s') % (self._format_date(),),
- _('Size: %s') % (format_size(int(self._metadata.get('filesize',
- model.get_file_size(self._metadata['uid']))))),
- ]
-
- for line in lines:
- text = hippo.CanvasText(text=line,
- font_desc=style.FONT_NORMAL.get_pango_desc())
- text.props.color = style.COLOR_BUTTON_GREY.get_int()
-
- if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
- text.props.xalign = hippo.ALIGNMENT_END
- else:
- text.props.xalign = hippo.ALIGNMENT_START
-
- vbox.append(text)
+ label = \
+ _('Kind: %s') % (self._metadata.get('mime_type') or \
+ _('Unknown'),) + '\n' + \
+ _('Date: %s') % (self._format_date(),) + '\n' + \
+ _('Size: %s') % (format_size(int(self._metadata.get(
+ 'filesize',
+ model.get_file_size(self._metadata['uid'])))))
+
+ text = gtk.Label()
+ text.set_markup('%s' % (
+ style.COLOR_BUTTON_GREY.get_html(), label))
+ halign = gtk.Alignment(0, 0, 0, 0)
+ halign.add(text)
+ vbox.pack_start(halign, False, False, 0)
return vbox
@@ -295,76 +275,55 @@ def _format_date(self):
def _create_buddy_list(self):
- vbox = hippo.CanvasBox()
+ vbox = gtk.VBox()
vbox.props.spacing = style.DEFAULT_SPACING
- text = hippo.CanvasText(text=_('Participants:'),
- font_desc=style.FONT_NORMAL.get_pango_desc())
- text.props.color = style.COLOR_BUTTON_GREY.get_int()
-
- if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
- text.props.xalign = hippo.ALIGNMENT_END
- else:
- text.props.xalign = hippo.ALIGNMENT_START
-
- vbox.append(text)
+ text = gtk.Label()
+ text.set_markup('%s' % (
+ style.COLOR_BUTTON_GREY.get_html(), _('Participants:')))
+ halign = gtk.Alignment(0, 0, 0, 0)
+ halign.add(text)
+ vbox.pack_start(halign, False, False, 0)
if self._metadata.get('buddies'):
buddies = simplejson.loads(self._metadata['buddies']).values()
- vbox.append(BuddyList(buddies))
+ vbox.pack_start(BuddyList(buddies), False, False, 0)
return vbox
else:
return vbox
- def _create_description(self):
- vbox = hippo.CanvasBox()
+ def _create_scrollable(self, label):
+ vbox = gtk.VBox()
vbox.props.spacing = style.DEFAULT_SPACING
- text = hippo.CanvasText(text=_('Description:'),
- font_desc=style.FONT_NORMAL.get_pango_desc())
- text.props.color = style.COLOR_BUTTON_GREY.get_int()
+ text = gtk.Label()
+ text.set_markup('%s' % (
+ style.COLOR_BUTTON_GREY.get_html(), label))
- if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
- text.props.xalign = hippo.ALIGNMENT_END
- else:
- text.props.xalign = hippo.ALIGNMENT_START
+ halign = gtk.Alignment(0, 0, 0, 0)
+ halign.add(text)
+ vbox.pack_start(halign, False, False, 0)
- vbox.append(text)
+ scrolled_window = gtk.ScrolledWindow()
+ scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+ scrolled_window.set_border_width(style.LINE_WIDTH)
+ text_buffer = gtk.TextBuffer()
+ text_view = gtk.TextView(text_buffer)
+ text_view.set_left_margin(style.DEFAULT_PADDING)
+ text_view.set_wrap_mode(gtk.WRAP_WORD_CHAR)
+ scrolled_window.add_with_viewport(text_view)
+ vbox.pack_start(scrolled_window)
- text_view = CanvasTextView('',
- box_height=style.GRID_CELL_SIZE * 2)
- vbox.append(text_view, hippo.PACK_EXPAND)
-
- text_view.text_view_widget.props.accepts_tab = False
- text_view.text_view_widget.connect('focus-out-event',
- self._description_focus_out_event_cb)
+ # text_view.text_view_widget.connect('focus-out-event',
+ # self._description_focus_out_event_cb)
return vbox, text_view
- def _create_tags(self):
- vbox = hippo.CanvasBox()
- vbox.props.spacing = style.DEFAULT_SPACING
-
- text = hippo.CanvasText(text=_('Tags:'),
- font_desc=style.FONT_NORMAL.get_pango_desc())
- text.props.color = style.COLOR_BUTTON_GREY.get_int()
-
- if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL:
- text.props.xalign = hippo.ALIGNMENT_END
- else:
- text.props.xalign = hippo.ALIGNMENT_START
-
- vbox.append(text)
-
- text_view = CanvasTextView('',
- box_height=style.GRID_CELL_SIZE * 2)
- vbox.append(text_view, hippo.PACK_EXPAND)
-
- text_view.text_view_widget.props.accepts_tab = False
- text_view.text_view_widget.connect('focus-out-event',
- self._tags_focus_out_event_cb)
+ def _create_description(self):
+ return self._create_scrollable(_('Description:'))
- return vbox, text_view
+ def _create_tags(self):
+ return self._create_scrollable(_('Tags:'))
def _title_notify_text_cb(self, entry, pspec):
if not self._update_title_sid:
@@ -385,7 +344,7 @@ def _update_entry(self, needs_update=False):
return
old_title = self._metadata.get('title', None)
- new_title = self._title.props.widget.props.text
+ new_title = self._title.get_text()
if old_title != new_title:
label = glib.markup_escape_text(new_title)
self._icon.palette.props.primary_text = label
@@ -393,15 +352,18 @@ def _update_entry(self, needs_update=False):
self._metadata['title_set_by_user'] = '1'
needs_update = True
+ bounds = self._tags.get_buffer().get_bounds()
old_tags = self._metadata.get('tags', None)
- new_tags = self._tags.text_view_widget.props.buffer.props.text
+ new_tags = self._tags.get_buffer().get_text(bounds[0], bounds[1])
+
if old_tags != new_tags:
self._metadata['tags'] = new_tags
needs_update = True
+ bounds = self._description.get_buffer().get_bounds()
old_description = self._metadata.get('description', None)
- new_description = \
- self._description.text_view_widget.props.buffer.props.text
+ new_description = self._description.get_buffer().get_text(
+ bounds[0], bounds[1])
if old_description != new_description:
self._metadata['description'] = new_description
needs_update = True
@@ -418,16 +380,12 @@ def _update_entry(self, needs_update=False):
self._update_title_sid = None
- def get_keep(self):
- return (str(self._metadata.get('keep', 0)) == '1')
-
- def _keep_icon_activated_cb(self, keep_icon):
- if self.get_keep():
- self._metadata['keep'] = 0
- else:
+ def _keep_icon_toggled_cb(self, keep_icon):
+ if keep_icon.get_active():
self._metadata['keep'] = 1
+ else:
+ self._metadata['keep'] = 0
self._update_entry(needs_update=True)
- keep_icon.props.keep = self.get_keep()
def _icon_button_release_event_cb(self, button, event):
logging.debug('_icon_button_release_event_cb')
diff --git a/src/jarabe/journal/keepicon.py b/src/jarabe/journal/keepicon.py
index 5bc299bca9..85b1728de7 100644
--- a/src/jarabe/journal/keepicon.py
+++ b/src/jarabe/journal/keepicon.py
@@ -14,51 +14,42 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-import gobject
-import hippo
+import gtk
import gconf
+import logging
-from sugar.graphics.icon import CanvasIcon
+from sugar.graphics.icon import Icon
from sugar.graphics import style
from sugar.graphics.xocolor import XoColor
-class KeepIcon(CanvasIcon):
- def __init__(self, keep):
- CanvasIcon.__init__(self, icon_name='emblem-favorite',
- box_width=style.GRID_CELL_SIZE * 3 / 5,
- size=style.SMALL_ICON_SIZE)
- self.connect('motion-notify-event', self.__motion_notify_event_cb)
+class KeepIcon(gtk.ToggleButton):
+ def __init__(self):
+ gtk.ToggleButton.__init__(self)
+ self.set_relief(gtk.RELIEF_NONE)
+ self.set_focus_on_click(False)
- self._keep = None
- self.set_keep(keep)
+ self._icon = Icon(icon_name='emblem-favorite',
+ pixel_size=style.SMALL_ICON_SIZE)
+ self.set_image(self._icon)
+ self.connect('toggled', self.__toggled_cb)
+ self.connect('leave-notify-event', self.__leave_notify_event_cb)
+ self.connect('enter-notify-event', self.__enter_notify_event_cb)
- def set_keep(self, keep):
- if keep == self._keep:
- return
-
- self._keep = keep
- if keep:
+ def __toggled_cb(self, widget):
+ if self.get_active():
client = gconf.client_get_default()
color = XoColor(client.get_string('/desktop/sugar/user/color'))
- self.props.xo_color = color
+ self._icon.props.xo_color = color
+ logging.debug('KEEPICON: setting xo_color')
else:
- self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg()
- self.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
-
- def get_keep(self):
- return self._keep
+ self._icon.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg()
+ self._icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
- keep = gobject.property(type=int, default=0, getter=get_keep,
- setter=set_keep)
+ def __enter_notify_event_cb(self, icon, event):
+ if not self.get_active():
+ self._icon.props.fill_color = style.COLOR_BUTTON_GREY.get_svg()
- def __motion_notify_event_cb(self, icon, event):
- if not self._keep:
- if event.detail == hippo.MOTION_DETAIL_ENTER:
- client = gconf.client_get_default()
- prelit_color = XoColor(client.get_string('/desktop/sugar/user/color'))
- icon.props.stroke_color = prelit_color.get_stroke_color()
- icon.props.fill_color = prelit_color.get_fill_color()
- elif event.detail == hippo.MOTION_DETAIL_LEAVE:
- icon.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg()
- icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
+ def __leave_notify_event_cb(self, icon, event):
+ if not self.get_active():
+ self._icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
diff --git a/src/jarabe/journal/listview.py b/src/jarabe/journal/listview.py
index 57836f250d..f6a867f0ec 100644
--- a/src/jarabe/journal/listview.py
+++ b/src/jarabe/journal/listview.py
@@ -18,14 +18,14 @@
from gettext import gettext as _
import time
+import glib
import gobject
import gtk
-import hippo
import gconf
import pango
from sugar.graphics import style
-from sugar.graphics.icon import CanvasIcon, Icon, CellRendererIcon
+from sugar.graphics.icon import Icon, CellRendererIcon
from sugar.graphics.xocolor import XoColor
from sugar import util
@@ -33,6 +33,7 @@
from jarabe.journal.palettes import ObjectPalette, BuddyPalette
from jarabe.journal import model
from jarabe.journal import misc
+from jarabe.view.eventicon import EventIcon
UPDATE_INTERVAL = 300
@@ -370,38 +371,33 @@ def _stop_progress_bar(self):
self._progress_bar = None
def _show_message(self, message, show_clear_query=False):
- canvas = hippo.Canvas()
+ box = gtk.VBox()
self.remove(self.child)
- self.add(canvas)
- canvas.show()
-
- box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL,
- background_color=style.COLOR_WHITE.get_int(),
- yalign=hippo.ALIGNMENT_CENTER,
- spacing=style.DEFAULT_SPACING,
- padding_bottom=style.GRID_CELL_SIZE)
- canvas.set_root(box)
-
- icon = CanvasIcon(size=style.LARGE_ICON_SIZE,
- icon_name='activity-journal',
- stroke_color=style.COLOR_BUTTON_GREY.get_svg(),
- fill_color=style.COLOR_TRANSPARENT.get_svg())
- box.append(icon)
-
- text = hippo.CanvasText(text=message,
- xalign=hippo.ALIGNMENT_CENTER,
- font_desc=style.FONT_BOLD.get_pango_desc(),
- color=style.COLOR_BUTTON_GREY.get_int())
- box.append(text)
+
+ alignment = gtk.Alignment(0.5, 0.5, 0.1, 0.1)
+ self.add(alignment)
+
+ icon = EventIcon(pixel_size=style.LARGE_ICON_SIZE,
+ icon_name='activity-journal',
+ stroke_color=style.COLOR_BUTTON_GREY.get_svg(),
+ fill_color=style.COLOR_TRANSPARENT.get_svg())
+ box.pack_start(icon, expand=True, fill=False)
+
+ label = gtk.Label()
+ color = style.COLOR_BUTTON_GREY.get_html()
+ label.set_markup('%s' % ( \
+ color, glib.markup_escape_text(message)))
+ box.pack_start(label, expand=True, fill=False)
if show_clear_query:
button = gtk.Button(label=_('Clear search'))
button.connect('clicked', self.__clear_button_clicked_cb)
button.props.image = Icon(icon_name='dialog-cancel',
icon_size=gtk.ICON_SIZE_BUTTON)
- canvas_button = hippo.CanvasWidget(widget=button,
- xalign=hippo.ALIGNMENT_CENTER)
- box.append(canvas_button)
+ box.pack_start(button, expand=True, fill=False)
+
+ alignment.add(box)
+ alignment.show_all()
def __clear_button_clicked_cb(self, button):
self.emit('clear-clicked')
diff --git a/src/jarabe/view/buddyicon.py b/src/jarabe/view/buddyicon.py
index e0e8b3fea3..663bd9221c 100644
--- a/src/jarabe/view/buddyicon.py
+++ b/src/jarabe/view/buddyicon.py
@@ -14,17 +14,19 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-from sugar.graphics.icon import CanvasIcon
from sugar.graphics import style
from jarabe.view.buddymenu import BuddyMenu
+from jarabe.view.eventicon import EventIcon
+
_FILTERED_ALPHA = 0.33
-class BuddyIcon(CanvasIcon):
- def __init__(self, buddy, size=style.STANDARD_ICON_SIZE):
- CanvasIcon.__init__(self, icon_name='computer-xo', size=size)
+class BuddyIcon(EventIcon):
+ def __init__(self, buddy, pixel_size=style.STANDARD_ICON_SIZE):
+ EventIcon.__init__(self, icon_name='computer-xo',
+ pixel_size=pixel_size)
self._filtered = False
self._buddy = buddy
diff --git a/src/jarabe/view/pulsingicon.py b/src/jarabe/view/pulsingicon.py
index 9a98a80e41..39e0babd76 100644
--- a/src/jarabe/view/pulsingicon.py
+++ b/src/jarabe/view/pulsingicon.py
@@ -18,9 +18,12 @@
import gobject
-from sugar.graphics.icon import Icon, CanvasIcon
+from sugar.graphics.icon import Icon
from sugar.graphics import style
+from jarabe.view.eventicon import EventIcon
+
+
_INTERVAL = 100
_STEP = math.pi / 10 # must be a fraction of pi, for clean caching
_MINIMAL_ALPHA_VALUE = 0.33
@@ -169,8 +172,8 @@ def __destroy_cb(self, icon):
self._palette.destroy()
-class CanvasPulsingIcon(CanvasIcon):
- __gtype_name__ = 'SugarCanvasPulsingIcon'
+class EventPulsingIcon(EventIcon):
+ __gtype_name__ = 'SugarEventPulsingIcon'
def __init__(self, **kwargs):
self._pulser = Pulser(self)
@@ -179,7 +182,7 @@ def __init__(self, **kwargs):
self._paused = False
self._pulsing = False
- CanvasIcon.__init__(self, **kwargs)
+ EventIcon.__init__(self, **kwargs)
self.connect('destroy', self.__destroy_cb)