Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar

This commit is contained in:
Bert Freudenberg 2006-10-06 21:11:54 +02:00
commit 41c2ddeb81
38 changed files with 448 additions and 348 deletions

1
.gitignore vendored
View File

@ -45,7 +45,6 @@ config.sub
depcomp
libtool
ltmain.sh
po/ChangeLog
m4/intltool.m4
bindings/globalkeys/globalkeys.c
bindings/gecko/gecko.c

View File

@ -1,4 +1,4 @@
AC_INIT([Sugar],[0.29],[],[sugar])
AC_INIT([Sugar],[0.33],[],[sugar])
AC_PREREQ([2.59])

0
po/ChangeLog Normal file
View File

View File

@ -2,4 +2,4 @@ activities/browser/NavigationToolbar.py
sugar/chat/ChatEditor.py
activities/chat/ChatActivity.py
activities/groupchat/GroupChatActivity.py
shell/FirstTimeDialog.py
shell/view/FirstTimeDialog.py

View File

@ -4,8 +4,6 @@ PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
ACTIVITY_DBUS_OBJECT_PATH = "/org/laptop/Presence/Activities/"
ACTIVITY_DBUS_INTERFACE = "org.laptop.Presence.Activity"
class NotFoundError(Exception):
pass
class ActivityDBusHelper(dbus.service.Object):
def __init__(self, parent, bus_name, object_path):
@ -17,22 +15,16 @@ class ActivityDBusHelper(dbus.service.Object):
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
in_signature="s", out_signature="ao")
def getServicesOfType(self, stype):
services = self._parent.get_services_of_type(stype)
if not services:
raise NotFoundError("Not found")
ret = []
for serv in services:
for serv in self._parent.get_services_of_type(stype):
ret.append(serv.object_path())
return ret
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
in_signature="", out_signature="ao")
def getServices(self):
services = self._parent.get_services()
if not services:
raise NotFoundError("Not found")
ret = []
for serv in services:
for serv in self._parent.get_services():
ret.append(serv.object_path())
return ret
@ -49,11 +41,8 @@ class ActivityDBusHelper(dbus.service.Object):
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
in_signature="", out_signature="ao")
def getJoinedBuddies(self):
buddies = self._parent.get_joined_buddies()
if not buddies:
raise NotFoundError("Not found")
ret = []
for buddy in buddies:
for buddy in self._parent.get_joined_buddies():
ret.append(buddy.object_path())
return ret
@ -119,7 +108,7 @@ class Activity(object):
def get_services_of_type(self, stype):
if self._services.has_key(stype):
return self._services[stype]
return None
return []
def get_joined_buddies(self):
buddies = []

View File

@ -148,27 +148,24 @@ class PresenceServiceDBusHelper(dbus.service.Object):
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
in_signature="", out_signature="ao")
def getServices(self):
services = self._parent.get_services()
ret = []
for serv in services:
for serv in self._parent.get_services():
ret.append(serv.object_path())
return ret
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
in_signature="s", out_signature="ao")
def getServicesOfType(self, stype):
services = self._parent.get_services_of_type(stype)
ret = []
for serv in services:
for serv in self._parent.get_services_of_type(stype):
ret.append(serv.object_path())
return ret
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
in_signature="", out_signature="ao")
def getActivities(self):
activities = self._parent.get_activities()
ret = []
for act in activities:
for act in self._parent.get_activities():
ret.append(act.object_path())
return ret
@ -183,9 +180,8 @@ class PresenceServiceDBusHelper(dbus.service.Object):
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
in_signature="", out_signature="ao")
def getBuddies(self):
buddies = self._parent.get_buddies()
ret = []
for buddy in buddies:
for buddy in self._parent.get_buddies():
ret.append(buddy.object_path())
return ret
@ -260,7 +256,7 @@ class PresenceServiceDBusHelper(dbus.service.Object):
found_serv = serv
break
if not found_serv:
raise NotFoundError("The activity %s was not found." % service_op)
raise NotFoundError("The service %s was not found." % service_op)
return self._parent.unregister_service(found_serv, sender)
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
@ -714,7 +710,7 @@ class PresenceService(object):
raise ValueError("invalid activity id")
owner_nick = self._owner.get_name()
real_name = Service.compose_service_name(owner_nick, activity_id)
if address and isinstance(address, unicode):
if address and not isinstance(address, unicode):
raise ValueError("address must be a unicode string.")
if address == None and stype.endswith('_udp'):
# Use random currently unassigned multicast address

View File

@ -4,7 +4,7 @@ from view.BuddyMenu import BuddyMenu
class BuddyIcon(MenuIcon):
def __init__(self, shell, menu_shell, buddy):
MenuIcon.__init__(self, menu_shell, icon_name='stock-buddy',
color=buddy.get_color(), size=112)
color=buddy.get_color())
self._shell = shell
self._buddy = buddy

View File

@ -1,5 +1,6 @@
import gtk
import gobject
import hippo
from sugar.graphics.menu import Menu
from sugar.graphics.canvasicon import CanvasIcon
@ -22,7 +23,7 @@ class BuddyMenu(Menu):
scaled_pixbuf = pixbuf.scale_simple(_ICON_SIZE, _ICON_SIZE,
gtk.gdk.INTERP_BILINEAR)
del pixbuf
icon_item = hippo.Image(pixbuf=scaled_pixbuf)
icon_item = hippo.CanvasImage(pixbuf=scaled_pixbuf)
Menu.__init__(self, buddy.get_name(), icon_item)

View File

@ -4,10 +4,10 @@ sugardir = $(pkgdatadir)/shell/view
sugar_PYTHON = \
__init__.py \
ActivityHost.py \
BuddyActivityView.py \
ConsoleWindow.py \
FirstTimeDialog.py \
BuddyIcon.py \
BuddyMenu.py \
OverlayWindow.py \
Shell.py
Shell.py \
stylesheet.py

View File

@ -2,6 +2,8 @@ import gtk
import gobject
import wnck
import view.stylesheet
from sugar.graphics import style
from view.home.HomeWindow import HomeWindow
from sugar.presence import PresenceService
from view.ActivityHost import ActivityHost
@ -28,6 +30,8 @@ class Shell(gobject.GObject):
self._hosts = {}
self._screen = wnck.screen_get_default()
style.load_stylesheet(view.stylesheet)
self._key_grabber = KeyGrabber()
self._key_grabber.connect('key-pressed',
self.__global_key_pressed_cb)

View File

@ -10,7 +10,7 @@ class ActivityItem(CanvasIcon):
def __init__(self, activity):
icon_name = activity.get_icon()
CanvasIcon.__init__(self, icon_name=icon_name)
style.apply_stylesheet(self, 'frame-activity-icon')
style.apply_stylesheet(self, 'frame.ActivityIcon')
self._activity = activity
def get_bundle_id(self):

View File

@ -5,6 +5,7 @@ import wnck
from view.frame.ActivitiesBox import ActivitiesBox
from view.frame.ZoomBox import ZoomBox
from view.frame.FriendsBox import FriendsBox
from view.frame.PanelWindow import PanelWindow
from sugar.graphics.timeline import Timeline
from sugar.graphics.menushell import MenuShell
@ -143,10 +144,13 @@ class Frame:
[x, y] = grid.point(1, 0)
bottom_panel.move(box, x, y)
left_panel = self._create_panel(grid, 0, 1, 1, 10)
right_panel = self._create_panel(grid, 15, 1, 1, 10)
box = FriendsBox(self._shell, self._menu_shell)
right_panel.append(box)
left_panel = self._create_panel(grid, 0, 1, 1, 10)
def _create_panel(self, grid, x, y, width, height):
panel = PanelWindow()

View File

@ -1,15 +1,16 @@
import hippo
from sugar.graphics.CanvasIcon import CanvasIcon
from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics.iconcolor import IconColor
from sugar.graphics import style
from sugar.presence import PresenceService
from view.BuddyIcon import BuddyIcon
from model.BuddyModel import BuddyModel
from view.frame.MenuStrategy import MenuStrategy
class RightPanel(hippo.CanvasBox):
class FriendsBox(hippo.CanvasBox):
def __init__(self, shell, menu_shell):
CanvasBox.__init__(self)
hippo.CanvasBox.__init__(self)
self._shell = shell
self._menu_shell = menu_shell
self._activity_ps = None
@ -26,18 +27,18 @@ class RightPanel(hippo.CanvasBox):
def add(self, buddy):
model = BuddyModel(buddy=buddy)
icon = BuddyIcon(self._shell, self._menu_shell, model)
style.apply_stylesheet(icon, 'frame.BuddyIcon')
icon.set_menu_strategy(MenuStrategy())
self.append(icon, 0)
self.append(icon)
self._buddies[buddy.get_name()] = icon
def remove(self, buddy):
i = self.find_child(self._buddies[buddy.get_name()])
self.remove_child(i)
self.remove(self._buddies[buddy.get_name()])
def clear(self):
while (self.get_n_children() > 0):
self.remove_child(0)
for item in self.get_children():
self.remove(item)
self._buddies = {}
def __activity_appeared_cb(self, pservice, activity_ps):

View File

@ -2,7 +2,7 @@ sugardir = $(pkgdatadir)/shell/view/frame
sugar_PYTHON = \
__init__.py \
ActivitiesBox.py \
RightPanel.py \
FriendsBox.py \
PanelWindow.py \
Frame.py \
ZoomBox.py \

View File

@ -1,15 +1,39 @@
import hippo
from sugar.graphics.grid import Grid
class MenuStrategy:
def get_menu_position(self, menu, x, y, width, height):
grid = Grid()
def _get_canvas(self, item):
canvas = item
while (not isinstance(canvas, hippo.Canvas)):
canvas = canvas.get_context()
return canvas
[grid_x1, grid_y1] = grid.fit_point(x, y)
[grid_x2, grid_y2] = grid.fit_point(x + width, y + height)
def _get_item_origin(self, canvas, item):
[x, y] = item.get_context().translate_to_widget(item)
menu_grid_x = grid_x1
menu_grid_y = grid_y2
[origin_x, origin_y] = canvas.window.get_origin()
x += origin_x
y += origin_y
[menu_x, menu_y] = grid.point(menu_grid_x, menu_grid_y)
return [x, y]
def get_menu_position(self, menu, item):
canvas = self._get_canvas(item)
[x, y] = self._get_item_origin(canvas, item)
[width, height] = item.get_allocation()
[canvas_x, canvas_y] = canvas.window.get_origin()
canvas_rect = canvas.get_allocation()
[menu_w, menu_h] = menu.size_request()
menu_x = x
menu_y = y + height
if (menu_x + menu_w > canvas_x) and \
(menu_y < canvas_y + canvas_rect.height):
menu_x = x - menu_w
menu_y = y
return [menu_x, menu_y]

View File

@ -15,11 +15,9 @@ class ActivityMenu(Menu):
Menu.__init__(self, activity_host.get_title())
icon = CanvasIcon(icon_name='stock-share-mesh')
style.apply_stylesheet(icon, 'menu-action-icon')
self.add_action(icon, ActivityMenu.ACTION_SHARE)
icon = CanvasIcon(icon_name='stock-close')
style.apply_stylesheet(icon, 'menu-action-icon')
self.add_action(icon, ActivityMenu.ACTION_CLOSE)
class ActivityIcon(MenuIcon):
@ -61,22 +59,22 @@ class ZoomBox(hippo.CanvasBox):
self._activity_icon = None
icon = CanvasIcon(icon_name='stock-zoom-mesh')
style.apply_stylesheet(icon, 'frame-zoom-icon')
style.apply_stylesheet(icon, 'frame.ZoomIcon')
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_MESH)
self.append(icon)
icon = CanvasIcon(icon_name='stock-zoom-friends')
style.apply_stylesheet(icon, 'frame-zoom-icon')
style.apply_stylesheet(icon, 'frame.ZoomIcon')
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_FRIENDS)
self.append(icon)
icon = CanvasIcon(icon_name='stock-zoom-home')
style.apply_stylesheet(icon, 'frame-zoom-icon')
style.apply_stylesheet(icon, 'frame.ZoomIcon')
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_HOME)
self.append(icon)
icon = CanvasIcon(icon_name='stock-zoom-activity')
style.apply_stylesheet(icon, 'frame-zoom-icon')
style.apply_stylesheet(icon, 'frame.ZoomIcon')
icon.connect('activated', self._level_clicked_cb, sugar.ZOOM_ACTIVITY)
self.append(icon)
@ -89,7 +87,7 @@ class ZoomBox(hippo.CanvasBox):
if activity:
icon = ActivityIcon(self._shell, self._menu_shell, activity)
style.apply_stylesheet(icon, 'frame-zoom-icon')
style.apply_stylesheet(icon, 'frame.ZoomIcon')
self.append(icon, 0)
self._activity_icon = icon
else:

View File

@ -1,13 +1,14 @@
import hippo
import gobject
import BuddyIcon
from view.BuddyIcon import BuddyIcon
from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics import style
from sugar.presence import PresenceService
import conf
class BuddyActivityView(hippo.CanvasBox):
class FriendView(hippo.CanvasBox):
def __init__(self, shell, menu_shell, buddy, **kwargs):
hippo.CanvasBox.__init__(self, **kwargs)
@ -15,10 +16,12 @@ class BuddyActivityView(hippo.CanvasBox):
self._activity_registry = conf.get_activity_registry()
self._buddy = buddy
self._buddy_icon = BuddyIcon.BuddyIcon(shell, menu_shell, buddy)
self._buddy_icon = BuddyIcon(shell, menu_shell, buddy)
style.apply_stylesheet(self._buddy_icon, 'friends.FriendIcon')
self.append(self._buddy_icon)
self._activity_icon = CanvasIcon(size=48)
self._activity_icon = CanvasIcon()
style.apply_stylesheet(self._activity_icon, 'friends.ActivityIcon')
self._activity_icon_visible = False
if self._buddy.is_present():

View File

@ -1,22 +1,24 @@
import random
import hippo
import gobject
from sugar.graphics.spreadlayout import SpreadLayout
from sugar.graphics.spreadbox import SpreadBox
from sugar.graphics import style
from view.home.MyIcon import MyIcon
from view.BuddyActivityView import BuddyActivityView
from view.home.FriendView import FriendView
class FriendsBox(hippo.CanvasBox, hippo.CanvasItem):
class FriendsBox(SpreadBox, hippo.CanvasItem):
__gtype_name__ = 'SugarFriendsBox'
def __init__(self, shell, menu_shell):
hippo.CanvasBox.__init__(self, background_color=0xe2e2e2ff)
SpreadBox.__init__(self, background_color=0xe2e2e2ff)
self._shell = shell
self._menu_shell = menu_shell
self._layout = SpreadLayout()
self._friends = {}
self._my_icon = MyIcon(112)
self._my_icon = MyIcon()
style.apply_stylesheet(self._my_icon, 'friends.MyIcon')
self.append(self._my_icon, hippo.PACK_FIXED)
friends = self._shell.get_model().get_friends()
@ -27,9 +29,11 @@ class FriendsBox(hippo.CanvasBox, hippo.CanvasItem):
friends.connect('friend-added', self._friend_added_cb)
friends.connect('friend-removed', self._friend_removed_cb)
gobject.idle_add(self.spread)
def add_friend(self, buddy_info):
icon = BuddyActivityView(self._shell, self._menu_shell, buddy_info)
self.append(icon, hippo.PACK_FIXED)
icon = FriendView(self._shell, self._menu_shell, buddy_info)
self.add(icon)
self._friends[buddy_info.get_name()] = icon
@ -41,9 +45,7 @@ class FriendsBox(hippo.CanvasBox, hippo.CanvasItem):
del self._friends[name]
def do_allocate(self, width, height):
hippo.CanvasBox.do_allocate(self, width, height)
self._layout.layout(self)
SpreadBox.do_allocate(self, width, height)
[icon_width, icon_height] = self._my_icon.get_allocation()
self.move(self._my_icon, (width - icon_width) / 2,

View File

@ -2,6 +2,8 @@ import hippo
from view.home.activitiesdonut import ActivitiesDonut
from view.home.MyIcon import MyIcon
from sugar.graphics.grid import Grid
from sugar.graphics import style
class HomeBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'SugarHomeBox'
@ -10,10 +12,13 @@ class HomeBox(hippo.CanvasBox, hippo.CanvasItem):
hippo.CanvasBox.__init__(self, background_color=0xe2e2e2ff,
yalign=2)
donut = ActivitiesDonut(shell, box_width=300, box_height=300)
grid = Grid()
donut = ActivitiesDonut(shell, box_width=grid.dimension(7),
box_height=grid.dimension(7))
self.append(donut)
self._my_icon = MyIcon(120)
self._my_icon = MyIcon()
style.apply_stylesheet(self._my_icon, 'home.MyIcon')
self.append(self._my_icon, hippo.PACK_FIXED)
def do_allocate(self, width, height):

View File

@ -2,6 +2,7 @@ sugardir = $(pkgdatadir)/shell/view/home
sugar_PYTHON = \
__init__.py \
activitiesdonut.py \
FriendView.py \
FriendsBox.py \
HomeBox.py \
HomeWindow.py \

View File

@ -1,27 +1,27 @@
import random
import hippo
import gobject
from sugar.graphics.spreadlayout import SpreadLayout
from sugar.graphics.spreadbox import SpreadBox
from sugar.graphics.snowflakebox import SnowflakeBox
from sugar.graphics.canvasicon import CanvasIcon
from view.BuddyIcon import BuddyIcon
from sugar.graphics.snowflakelayout import SnowflakeLayout
import conf
class ActivityView(hippo.CanvasBox):
class ActivityView(SnowflakeBox):
def __init__(self, shell, menu_shell, model):
hippo.CanvasBox.__init__(self)
SnowflakeBox.__init__(self)
self._shell = shell
self._model = model
self._layout = SnowflakeLayout()
self._icons = {}
icon = CanvasIcon(icon_name=model.get_icon_name(),
color=model.get_color(), size=80)
icon.connect('activated', self._clicked_cb)
self.append(icon, hippo.PACK_FIXED)
self._layout.set_root(icon)
self.set_root(icon)
def has_buddy_icon(self, name):
return self._icons.has_key(name)
@ -35,25 +35,19 @@ class ActivityView(hippo.CanvasBox):
self.remove(icon)
del self._icons[name]
def get_size_request(self):
size = self._layout.get_size()
return [size, size]
def _clicked_cb(self, item):
registry = conf.get_activity_registry()
default_type = self._model.get_service().get_type()
bundle = registry.get_activity_from_type(default_type)
self._shell.join_activity(bundle.get_id(), self._model.get_id())
class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'SugarMeshBox'
class MeshBox(SpreadBox):
def __init__(self, shell, menu_shell):
hippo.CanvasBox.__init__(self, background_color=0xe2e2e2ff)
SpreadBox.__init__(self, background_color=0xe2e2e2ff)
self._shell = shell
self._menu_shell = menu_shell
self._model = shell.get_model().get_mesh()
self._layout = SpreadLayout()
self._buddies = {}
self._activities = {}
self._buddy_to_activity = {}
@ -71,6 +65,8 @@ class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
self._model.connect('activity-added', self._activity_added_cb)
self._model.connect('activity-removed', self._activity_removed_cb)
gobject.idle_add(self.spread)
def _buddy_added_cb(self, model, buddy_model):
self._add_alone_buddy(buddy_model)
@ -89,7 +85,7 @@ class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
def _add_alone_buddy(self, buddy_model):
icon = BuddyIcon(self._shell, self._menu_shell, buddy_model)
icon.props.size = 80
self.append(icon, hippo.PACK_FIXED)
self.add(icon)
self._buddies[buddy_model.get_name()] = icon
@ -123,7 +119,7 @@ class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
def _add_activity(self, activity_model):
icon = ActivityView(self._shell, self._menu_shell, activity_model)
self.append(icon, hippo.PACK_FIXED)
self.add(icon)
self._activities[activity_model.get_id()] = icon
@ -131,7 +127,3 @@ class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
icon = self._activities[activity_model.get_id()]
self.remove(icon)
del self._activities[activity_model.get_id()]
def do_allocate(self, width, height):
hippo.CanvasBox.do_allocate(self, width, height)
self._layout.layout(self)

View File

@ -1,10 +1,8 @@
from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics.iconcolor import IconColor
import conf
class MyIcon(CanvasIcon):
def __init__(self, size):
def __init__(self):
profile = conf.get_profile()
CanvasIcon.__init__(self, icon_name='stock-buddy',
color=profile.get_color(), size=size)
color=profile.get_color())

View File

@ -2,6 +2,7 @@ import hippo
import math
from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics import style
class ActivitiesDonut(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'SugarActivitiesDonut'
@ -28,7 +29,8 @@ class ActivitiesDonut(hippo.CanvasBox, hippo.CanvasItem):
icon_name = activity.get_icon_name()
icon_color = activity.get_icon_color()
icon = CanvasIcon(icon_name=icon_name, color=icon_color, size=75)
icon = CanvasIcon(icon_name=icon_name, color=icon_color)
style.apply_stylesheet(icon, 'ring.ActivityIcon')
icon.connect('activated', self.__activity_icon_clicked_cb, activity)
self.append(icon, hippo.PACK_FIXED)

72
shell/view/stylesheet.py Normal file
View File

@ -0,0 +1,72 @@
import gtk
import hippo
from sugar.graphics.iconcolor import IconColor
_screen_factor = gtk.gdk.screen_width() / 1200.0
_standard_icon_size = int(75.0 * _screen_factor)
_small_icon_size = _standard_icon_size * 0.5
_medium_icon_size = _standard_icon_size * 1.5
_large_icon_size = _standard_icon_size * 2.0
_xlarge_icon_size = _standard_icon_size * 3.0
_space_unit = 9 * _screen_factor
_separator_thickness = 3 * _screen_factor
def _font_description(style, relative_size):
base_size = 18 * _screen_factor
return '%s %dpx' % (style, int(base_size * relative_size))
frame_ActivityIcon = {
'color' : IconColor('white'),
'size' : _standard_icon_size
}
frame_ZoomIcon = {
'size' : _standard_icon_size
}
frame_BuddyIcon = {
'size' : _standard_icon_size
}
menu = {
'background_color' : 0x000000FF,
'spacing' : _space_unit,
'padding' : _space_unit
}
menu_Title = {
'color' : 0xFFFFFFFF,
'font' : _font_description('Bold', 1.2)
}
menu_Separator = {
'background_color' : 0xFFFFFFFF,
'box_height' : _separator_thickness
}
menu_ActionIcon = {
'size' : _standard_icon_size
}
home_MyIcon = {
'size' : _xlarge_icon_size
}
ring_ActivityIcon = {
'size' : _medium_icon_size
}
friends_MyIcon = {
'size' : _large_icon_size
}
friends_FriendIcon = {
'size' : _large_icon_size
}
friends_ActivityIcon = {
'size' : _standard_icon_size
}

View File

@ -8,7 +8,7 @@ sugar_PYTHON = \
menu.py \
menuicon.py \
menushell.py \
snowflakelayout.py \
spreadlayout.py \
snowflakebox.py \
spreadbox.py \
style.py \
timeline.py

View File

@ -1,25 +0,0 @@
import gtk
from sugar.graphics import style
from sugar.graphics.iconcolor import IconColor
if gtk.gdk.screen_width() == 1200:
_medium_icon_size = 75
else:
_medium_icon_size = 50
_stylesheet = {
'color' : IconColor('white'),
'size' : _medium_icon_size
}
style.register_stylesheet('frame-activity-icon', _stylesheet)
_stylesheet = {
'size' : _medium_icon_size
}
style.register_stylesheet('frame-zoom-icon', _stylesheet)
_stylesheet = {
'size' : _medium_icon_size
}
style.register_stylesheet('menu-action-icon', _stylesheet)

View File

@ -14,6 +14,9 @@ class Grid(object):
return [grid_x * self._factor, grid_y * self._factor,
grid_w * self._factor, grid_h * self._factor]
def dimension(self, grid_dimension):
return grid_dimension * self._factor
def fit_point(self, x, y):
return [int(x / self._factor), int(y / self._factor)]

View File

@ -3,6 +3,7 @@ import hippo
import gobject
from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics import style
class Menu(gtk.Window):
__gsignals__ = {
@ -17,11 +18,12 @@ class Menu(gtk.Window):
self.add(canvas)
canvas.show()
self._root = hippo.CanvasBox(background_color=0x000000FF,
spacing=6)
self._root = hippo.CanvasBox()
style.apply_stylesheet(self._root, 'menu')
canvas.set_root(self._root)
text = hippo.CanvasText(text=title, color=0xFFFFFFFF)
text = hippo.CanvasText(text=title)
style.apply_stylesheet(text, 'menu.Title')
self._root.append(text)
if content_box:
@ -29,6 +31,14 @@ class Menu(gtk.Window):
self._root.append(separator)
self._root.append(content_box)
self._action_box = None
def _create_separator(self):
separator = hippo.CanvasBox()
style.apply_stylesheet(separator, 'menu.Separator')
return separator
def _create_action_box(self):
separator = self._create_separator()
self._root.append(separator)
@ -36,13 +46,11 @@ class Menu(gtk.Window):
orientation=hippo.ORIENTATION_HORIZONTAL)
self._root.append(self._action_box)
def _create_separator(self):
separator = hippo.CanvasBox(background_color=0xFFFFFFFF,
border_left=6, border_right=6,
box_height=2)
return separator
def add_action(self, icon, action_id):
if not self._action_box:
self._create_action_box()
style.apply_stylesheet(icon, 'menu.ActionIcon')
icon.connect('activated', self._action_clicked_cb, action_id)
self._action_box.append(icon)

View File

@ -4,8 +4,8 @@ import gobject
from sugar.graphics.canvasicon import CanvasIcon
class _MenuStrategy:
def get_menu_position(self, menu, x1, y1, x2, y2):
return [x1, y1]
def get_menu_position(self, menu, item):
return item.get_context().translate_to_widget(item)
class MenuIcon(CanvasIcon):
def __init__(self, menu_shell, **kwargs):
@ -29,7 +29,7 @@ class MenuIcon(CanvasIcon):
def set_menu_strategy(self, strategy):
self._menu_strategy = strategy
def _popup(self, x1, y1, x2, y2):
def _popup(self):
self.popdown()
self._menu_shell.set_active(None)
@ -41,7 +41,7 @@ class MenuIcon(CanvasIcon):
self._menu_leave_notify_event_cb)
strategy = self._menu_strategy
[x, y] = strategy.get_menu_position(self._menu, x1, y1, x2, y2)
[x, y] = strategy.get_menu_position(self._menu, self)
self._menu.move(x, y)
self._menu.show()
@ -73,11 +73,7 @@ class MenuIcon(CanvasIcon):
def _motion_notify_enter(self):
self._stop_popdown_timeout()
[x, y] = self.get_context().translate_to_widget(self)
[width, height] = self.get_allocation()
self._popup(x, y, width, height)
self._popup()
def _motion_notify_leave(self):
self._start_popdown_timeout()

View File

@ -0,0 +1,71 @@
import math
import cairo
import hippo
_BASE_RADIUS = 65
_CHILDREN_FACTOR = 1
_FLAKE_DISTANCE = 6
class SnowflakeBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'SugarSnowflakeBox'
def __init__(self, **kwargs):
hippo.CanvasBox.__init__(self, **kwargs)
self._root = None
self._r = 0
def set_root(self, icon):
self._root = icon
def _layout_root(self):
[width, height] = self._root.get_allocation()
x = self._cx - (width / 2)
y = self._cy - (height / 2)
self.move(self._root, int(x), int(y))
def _layout_child(self, child, index):
r = self._r
if (len(self.get_children()) > 10):
r += _FLAKE_DISTANCE * (index % 3)
angle = 2 * math.pi / len(self.get_children()) * index
[width, height] = child.get_allocation()
x = self._cx + math.cos(angle) * r - (width / 2)
y = self._cy + math.sin(angle) * r - (height / 2)
self.move(child, int(x), int(y))
def do_get_width_request(self):
hippo.CanvasBox.do_get_width_request(self)
max_child_size = 0
for child in self.get_children():
width = child.get_width_request()
height = child.get_height_request(width)
max_child_size = max (max_child_size, width)
max_child_size = max (max_child_size, height)
return self._r * 2 + max_child_size + _FLAKE_DISTANCE * 2
def do_get_height_request(self, width):
hippo.CanvasBox.do_get_height_request(self, width)
return width
def do_allocate(self, width, height):
hippo.CanvasBox.do_allocate(self, width, height)
self._cx = width / 2
self._cy = height / 2
self._r = _BASE_RADIUS + _CHILDREN_FACTOR * len(self.get_children())
self._layout_root()
index = 0
for child in self.get_children():
if child != self._root:
self._layout_child(child, index)
index += 1

View File

@ -1,71 +0,0 @@
import math
import cairo
class SnowflakeLayout:
_BASE_RADIUS = 65
_CHILDREN_FACTOR = 1
_FLAKE_DISTANCE = 6
def __init__(self):
self._root = None
self._children = []
self._r = 0
def set_root(self, icon):
self._root = icon
def add_child(self, icon):
self._children.append(icon)
self._layout()
def remove_child(self, icon):
self._children.remove(icon)
self._layout()
def _layout_root(self):
[width, height] = self._root.get_size_request()
matrix = cairo.Matrix(1, 0, 0, 1, 0, 0)
matrix.translate(self._cx - (width / 2), self._cy - (height / 2))
self._root.set_transform(matrix)
def _layout_child(self, child, index):
r = self._r
if (len(self._children) > 10):
r += SnowflakeLayout._FLAKE_DISTANCE * (index % 3)
angle = 2 * math.pi / len(self._children) * index
[width, height] = child.get_size_request()
x = self._cx + math.cos(angle) * r - (width / 2)
y = self._cy + math.sin(angle) * r - (height / 2)
matrix = cairo.Matrix(1, 0, 0, 1, 0, 0)
matrix.translate(x, y)
child.set_transform(matrix)
def get_size(self):
max_child_size = 0
for child in self._children:
[width, height] = child.get_size_request()
max_child_size = max (max_child_size, width)
max_child_size = max (max_child_size, height)
return self._r * 2 + max_child_size + \
SnowflakeLayout._FLAKE_DISTANCE * 2
def _layout(self):
self._r = SnowflakeLayout._BASE_RADIUS + \
SnowflakeLayout._CHILDREN_FACTOR * len(self._children)
size = self.get_size()
self._cx = size / 2
self._cy = size / 2
self._layout_root()
index = 0
for child in self._children:
self._layout_child(child, index)
index += 1

101
sugar/graphics/spreadbox.py Normal file
View File

@ -0,0 +1,101 @@
import random
import math
import cairo
import hippo
_DISTANCE_THRESHOLD = 120.0
class SpreadBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'SugarSpreadBox'
def __init__(self, **kwargs):
hippo.CanvasBox.__init__(self, **kwargs)
self._items_to_position = []
self._spread_on_add = False
self._stable = False
def add(self, item):
self._items_to_position.append(item)
self.append(item, hippo.PACK_FIXED)
if self._spread_on_add:
self.spread()
def spread(self):
self._spread_on_add = True
[width, height] = self.get_allocation()
for item in self._items_to_position:
x = int(random.random() * width)
y = int(random.random() * height)
[x, y] = self._clamp_position(item, x, y)
self.move(item, x, y)
self._items_to_position = []
def _get_distance(self, icon1, icon2):
[icon1_x, icon1_y] = self.get_position(icon1)
[icon2_x, icon2_y] = self.get_position(icon2)
a = icon1_x - icon2_x
b = icon1_y - icon2_y
return math.sqrt(a * a + b * b)
def _get_repulsion(self, icon1, icon2):
[icon1_x, icon1_y] = self.get_position(icon1)
[icon2_x, icon2_y] = self.get_position(icon2)
f_x = icon1_x - icon2_x
f_y = icon1_y - icon2_y
return [f_x, f_y]
def _clamp_position(self, icon, x, y):
x = max(0, x)
y = max(0, y)
item_w = icon.get_width_request()
item_h = icon.get_height_request(item_w)
[box_w, box_h] = self.get_allocation()
x = min(box_w - item_w, x)
y = min(box_h - item_h, y)
return [x, y]
def _spread_icons(self):
self._stable = True
for icon1 in self.get_children():
vx = 0
vy = 0
for icon2 in self.get_children():
if icon1 != icon2:
distance = self._get_distance(icon1, icon2)
if distance <= _DISTANCE_THRESHOLD:
self._stable = False
[f_x, f_y] = self._get_repulsion(icon1, icon2)
vx += f_x
vy += f_y
if vx != 0 or vy != 0:
[x, y] = self.get_position(icon1)
new_x = x + vx
new_y = y + vy
[new_x, new_y] = self._clamp_position(icon1, new_x, new_y)
self.move(icon1, new_x, new_y)
def do_allocate(self, width, height):
hippo.CanvasBox.do_allocate(self, width, height)
tries = 10
self._spread_icons()
while not self._stable and tries > 0:
self._spread_icons()
tries -= 1

View File

@ -1,76 +0,0 @@
import random
import math
import cairo
class SpreadLayout:
DISTANCE_THRESHOLD = 120.0
def __init__(self):
pass
def _get_distance(self, icon1, icon2):
[icon1_x, icon1_y] = self._constraints[icon1]
[icon2_x, icon2_y] = self._constraints[icon2]
a = icon1_x - icon2_x
b = icon1_y - icon2_y
return math.sqrt(a * a + b * b)
def _get_repulsion(self, icon1, icon2):
[icon1_x, icon1_y] = self._constraints[icon1]
[icon2_x, icon2_y] = self._constraints[icon2]
f_x = icon1_x - icon2_x
f_y = icon1_y - icon2_y
return [f_x, f_y]
def _spread_icons(self):
self._stable = True
for icon1 in self._icons:
vx = 0
vy = 0
[x, y] = self._constraints[icon1]
for icon2 in self._icons:
if icon1 != icon2:
distance = self._get_distance(icon1, icon2)
if distance <= IconLayout.DISTANCE_THRESHOLD:
self._stable = False
[f_x, f_y] = self._get_repulsion(icon1, icon2)
vx += f_x
vy += f_y
new_x = x + vx
new_y = y + vy
new_x = max(self._x1, new_x)
new_y = max(self._y1, new_y)
[width, height] = icon1.get_size_request()
new_x = min(self._x2 - width, new_x)
new_y = min(self._y2 - height, new_y)
self._constraints[icon1] = [new_x, new_y]
matrix = cairo.Matrix(1, 0, 0, 1, 0, 0)
matrix.translate(new_x - (width / 2), new_y - (height / 2))
icon1.set_transform(matrix)
def update(self):
tries = 10
self._spread_icons()
while not self._stable and tries > 0:
self._spread_icons()
tries -= 1
def layout(self, box):
[width, height] = box.get_allocation()
for item in box.get_children():
x = int(random.random() * width)
y = int(random.random() * height)
box.move(item, x, y)

View File

@ -1,5 +1,12 @@
_styles = {}
def load_stylesheet(module):
for objname in dir(module):
if not objname.startswith('_'):
obj = getattr(module, objname)
if isinstance(obj, dict):
register_stylesheet(objname.replace('_', '.'), obj)
def register_stylesheet(name, style):
_styles[name] = style

View File

@ -12,6 +12,8 @@ if dbus.version < (0, 70, 0):
import gobject
from sugar import env
__queue = None
CONSOLE_BUS_NAME = 'org.laptop.Sugar.Console'
@ -121,7 +123,9 @@ def start(console_id, console = None):
root_logger = logging.getLogger('')
root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(Handler(queue))
fileh = logging.FileHandler('/tmp/sugar.log')
log_file = os.path.join(env.get_profile_path(), 'sugar.log')
fileh = logging.FileHandler(log_file)
fileh.setFormatter(logging.Formatter("""[%(asctime)s] %(message)s"""))
root_logger.addHandler(fileh)

View File

@ -9,6 +9,7 @@ class MatchboxProcess(Process):
options = '-kbdconfig %s ' % kbd_config
options += '-use_titlebar no '
options += '-theme olpc '
command = 'matchbox-window-manager %s ' % options
Process.__init__(self, command)

View File

@ -1,55 +0,0 @@
#!/usr/bin/python
import pygtk
pygtk.require('2.0')
import gobject
from sugar.session.UITestSession import UITestSession
session = UITestSession()
session.start()
import sys
import random
import gtk
import goocanvas
from view.home.IconLayout import IconLayout
from sugar.graphics import IconColor
from sugar.graphics.IconItem import IconItem
from sugar.graphics.CanvasView import CanvasView
from sugar.graphics.Grid import Grid
def _create_icon():
color = IconColor.IconColor()
icon = IconItem(size=125, color=color,
icon_name='stock-buddy')
root.add_child(icon)
icon_layout.add_icon(icon)
return (root.get_n_children() < 20)
window = gtk.Window()
window.connect("destroy", lambda w: gtk.main_quit())
window.show()
canvas = CanvasView()
canvas.show()
window.add(canvas)
canvas_model = goocanvas.CanvasModelSimple()
root = canvas_model.get_root_item()
item = goocanvas.Rect(x=0, y=0, width=1200, height=900,
line_width=0.0, fill_color='#e2e2e2')
root.add_child(item)
icon_layout = IconLayout(Grid())
gobject.timeout_add(500, _create_icon)
canvas.set_model(canvas_model)
gtk.main()

45
tests/test-spread-box.py Executable file
View File

@ -0,0 +1,45 @@
#!/usr/bin/python
import pygtk
pygtk.require('2.0')
import gobject
from sugar.session.UITestSession import UITestSession
session = UITestSession()
session.start()
import sys
import random
import gtk
import hippo
from sugar.graphics.spreadbox import SpreadBox
from sugar.graphics.iconcolor import IconColor
from sugar.graphics.canvasicon import CanvasIcon
def _create_icon():
color = IconColor()
icon = CanvasIcon(size=100, color=color,
icon_name='stock-buddy')
box.add(icon)
return (len(box.get_children()) < 20)
window = gtk.Window()
window.connect("destroy", lambda w: gtk.main_quit())
window.show()
canvas = hippo.Canvas()
box = SpreadBox(background_color=0xe2e2e2ff)
canvas.set_root(box)
box.spread()
canvas.show()
window.add(canvas)
gobject.timeout_add(500, _create_icon)
gtk.main()