Move the layouts to be box and subclass them.

This commit is contained in:
Marco Pesenti Gritti 2006-10-06 11:11:38 +02:00
parent f216f7bc0a
commit b33a1c141f
7 changed files with 190 additions and 178 deletions

View File

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

View File

@ -1,28 +1,27 @@
import random import random
import hippo 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 sugar.graphics.canvasicon import CanvasIcon
from view.BuddyIcon import BuddyIcon from view.BuddyIcon import BuddyIcon
from sugar.graphics.snowflakelayout import SnowflakeLayout
import conf import conf
class ActivityView(hippo.CanvasBox, hippo.CanvasItem): class ActivityView(SnowflakeBox):
__gtype_name__ = 'SugarActivityView'
def __init__(self, shell, menu_shell, model): def __init__(self, shell, menu_shell, model):
hippo.CanvasBox.__init__(self) SnowflakeBox.__init__(self)
self._shell = shell self._shell = shell
self._model = model self._model = model
self._layout = SnowflakeLayout()
self._icons = {} self._icons = {}
icon = CanvasIcon(icon_name=model.get_icon_name(), icon = CanvasIcon(icon_name=model.get_icon_name(),
color=model.get_color(), size=80) color=model.get_color(), size=80)
icon.connect('activated', self._clicked_cb) icon.connect('activated', self._clicked_cb)
self.append(icon, hippo.PACK_FIXED) self.append(icon, hippo.PACK_FIXED)
self._layout.set_root(icon) self.set_root(icon)
def has_buddy_icon(self, name): def has_buddy_icon(self, name):
return self._icons.has_key(name) return self._icons.has_key(name)
@ -42,19 +41,13 @@ class ActivityView(hippo.CanvasBox, hippo.CanvasItem):
bundle = registry.get_activity_from_type(default_type) bundle = registry.get_activity_from_type(default_type)
self._shell.join_activity(bundle.get_id(), self._model.get_id()) self._shell.join_activity(bundle.get_id(), self._model.get_id())
def do_allocate(self, width, height): class MeshBox(SpreadBox):
hippo.CanvasBox.do_allocate(self, width, height)
self._layout.layout(self)
class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'SugarMeshBox'
def __init__(self, shell, menu_shell): def __init__(self, shell, menu_shell):
hippo.CanvasBox.__init__(self, background_color=0xe2e2e2ff) SpreadBox.__init__(self, background_color=0xe2e2e2ff)
self._shell = shell self._shell = shell
self._menu_shell = menu_shell self._menu_shell = menu_shell
self._model = shell.get_model().get_mesh() self._model = shell.get_model().get_mesh()
self._layout = SpreadLayout()
self._buddies = {} self._buddies = {}
self._activities = {} self._activities = {}
self._buddy_to_activity = {} self._buddy_to_activity = {}
@ -72,6 +65,8 @@ class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
self._model.connect('activity-added', self._activity_added_cb) self._model.connect('activity-added', self._activity_added_cb)
self._model.connect('activity-removed', self._activity_removed_cb) self._model.connect('activity-removed', self._activity_removed_cb)
gobject.idle_add(self.spread)
def _buddy_added_cb(self, model, buddy_model): def _buddy_added_cb(self, model, buddy_model):
self._add_alone_buddy(buddy_model) self._add_alone_buddy(buddy_model)
@ -90,7 +85,7 @@ class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
def _add_alone_buddy(self, buddy_model): def _add_alone_buddy(self, buddy_model):
icon = BuddyIcon(self._shell, self._menu_shell, buddy_model) icon = BuddyIcon(self._shell, self._menu_shell, buddy_model)
icon.props.size = 80 icon.props.size = 80
self.append(icon, hippo.PACK_FIXED) self.add(icon)
self._buddies[buddy_model.get_name()] = icon self._buddies[buddy_model.get_name()] = icon
@ -124,7 +119,7 @@ class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
def _add_activity(self, activity_model): def _add_activity(self, activity_model):
icon = ActivityView(self._shell, self._menu_shell, 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 self._activities[activity_model.get_id()] = icon
@ -132,7 +127,3 @@ class MeshBox(hippo.CanvasBox, hippo.CanvasItem):
icon = self._activities[activity_model.get_id()] icon = self._activities[activity_model.get_id()]
self.remove(icon) self.remove(icon)
del self._activities[activity_model.get_id()] 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

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

View File

@ -0,0 +1,67 @@
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):
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(box.get_children()) > 10):
r += _FLAKE_DISTANCE * (index % 3)
angle = 2 * math.pi / len(box.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):
max_child_size = 0
for child in box.get_children():
[width, height] = child.get_allocation()
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):
return width
def do_allocate(self, width, height):
self._r = _BASE_RADIUS + _CHILDREN_FACTOR * len(box.get_children())
hippo.CanvasBox.do_allocate(self, width, height)
self._cx = self.get_width_request() / 2
self._cy = self.get_height_request() / 2
self._layout_root(box)
index = 0
for child in box.get_children():
self._layout_child(child, index)
index += 1

View File

@ -1,61 +0,0 @@
import math
import cairo
class SnowflakeLayout:
_BASE_RADIUS = 65
_CHILDREN_FACTOR = 1
_FLAKE_DISTANCE = 6
def __init__(self):
self._root = None
self._r = 0
def set_root(self, icon):
self._root = icon
def _layout_root(self, box):
[width, height] = self._root.get_allocation()
x = self._cx - (width / 2)
y = self._cy - (height / 2)
box.move(self._root, int(x), int(y))
def _layout_child(self, box, child, index):
r = self._r
if (len(box.get_children()) > 10):
r += SnowflakeLayout._FLAKE_DISTANCE * (index % 3)
angle = 2 * math.pi / len(box.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)
box.move(child, int(x), int(y))
def get_size(self, box):
max_child_size = 0
for child in box.get_children():
[width, height] = child.get_allocation()
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, box):
self._r = SnowflakeLayout._BASE_RADIUS + \
SnowflakeLayout._CHILDREN_FACTOR * len(box.get_children())
size = self.get_size(box)
self._cx = size / 2
self._cy = size / 2
self._layout_root(box)
index = 0
for child in box.get_children():
self._layout_child(box, 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
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, item_h] = icon.get_allocation()
[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):
stable = True
for icon1 in self.get_children():
vx = 0
vy = 0
[x, y] = self.get_position(icon1)
for icon2 in self.get_children():
if icon1 != icon2:
distance = self._get_distance(icon1, icon2)
if distance <= _DISTANCE_THRESHOLD:
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, new_y] = self._clamp_position(icon1, new_x, new_y)
self.move(icon1, new_x, new_y)
return stable
def do_allocate(self, width, height):
hippo.CanvasBox.do_allocate(self, width, height)
tries = 10
stable = self._spread_icons()
while not stable and tries > 0:
stable = self._spread_icons()
tries -= 1

View File

@ -1,86 +0,0 @@
import random
import math
import cairo
_DISTANCE_THRESHOLD = 120.0
class SpreadLayout:
def __init__(self):
pass
def _get_distance(self, box, icon1, icon2):
[icon1_x, icon1_y] = box.get_position(icon1)
[icon2_x, icon2_y] = box.get_position(icon2)
a = icon1_x - icon2_x
b = icon1_y - icon2_y
return math.sqrt(a * a + b * b)
def _get_repulsion(self, box, icon1, icon2):
[icon1_x, icon1_y] = box.get_position(icon1)
[icon2_x, icon2_y] = box.get_position(icon2)
f_x = icon1_x - icon2_x
f_y = icon1_y - icon2_y
return [f_x, f_y]
def _clamp_position(self, box, icon, x, y):
x = max(0, x)
y = max(0, y)
[item_w, item_h] = icon.get_allocation()
[box_w, box_h] = box.get_allocation()
x = min(box_w - item_w, x)
y = min(box_h - item_h, y)
return [x, y]
def _spread_icons(self, box):
stable = True
for icon1 in box.get_children():
vx = 0
vy = 0
[x, y] = box.get_position(icon1)
for icon2 in box.get_children():
if icon1 != icon2:
distance = self._get_distance(box, icon1, icon2)
if distance <= _DISTANCE_THRESHOLD:
stable = False
[f_x, f_y] = self._get_repulsion(box, icon1, icon2)
vx += f_x
vy += f_y
new_x = x + vx
new_y = y + vy
[new_x, new_y] = self._clamp_position(box, icon1, new_x, new_y)
box.move(icon1, new_x, new_y)
return stable
def layout(self, box):
[width, height] = box.get_allocation()
for item in box.get_children():
[item_w, item_h] = item.get_allocation()
x = int(random.random() * width)
y = int(random.random() * height)
[x, y] = self._clamp_position(box, item, x, y)
box.move(item, x, y)
tries = 10
stable = self._spread_icons(box)
while not stable and tries > 0:
stable = self._spread_icons(box)
tries -= 1