From fb019bc9f5a93231d9dc63a2f323db6881a048a3 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Mon, 7 May 2007 16:24:41 +0200 Subject: [PATCH] Better spread algorhytm, work in progress --- sugar/graphics/spreadbox.py | 131 ++++++++++++++++++++++++++---------- tests/test-notebook.py | 0 tests/test-snowflake-box.py | 4 ++ 3 files changed, 98 insertions(+), 37 deletions(-) mode change 100644 => 100755 tests/test-notebook.py diff --git a/sugar/graphics/spreadbox.py b/sugar/graphics/spreadbox.py index ff50f71e..f4cf5ea9 100644 --- a/sugar/graphics/spreadbox.py +++ b/sugar/graphics/spreadbox.py @@ -15,67 +15,124 @@ # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. -import random +from array import array +from random import random import hippo -import gtk -from sugar.graphics import units +_X_TILES = 120 +_NUM_TRIALS = 100 -_WIDTH = gtk.gdk.screen_width() -_HEIGHT = gtk.gdk.screen_height() -_CELL_WIDTH = units.grid_to_pixels(1) -_CELL_HEIGHT = units.grid_to_pixels(1) -_GRID_WIDTH = _WIDTH / _CELL_WIDTH -_GRID_HEIGHT = _HEIGHT / _CELL_HEIGHT +class _Grid(object): + def __init__(self, x_tiles, y_tiles, cell_size): + self._array = array('B') + self.x_tiles = x_tiles + self.y_tiles = y_tiles + self.cell_size = cell_size + + for i in range(self.y_tiles * self.x_tiles): + self._array.append(0) + + def __getitem__(self, (row, col)): + return self._array[col + row * self.x_tiles] + + def __setitem__(self, (row, col), value): + self._array[col + row * self.x_tiles] = value + + def compute_weight_at(self, x, y, width, height): + weight = 0 + + for i in range(x, x + width): + for j in range(y, y + height): + weight += self[j, i] + + return weight + + def add_weight_at(self, x, y, width, height): + for i in range(x, x + width): + for j in range(y, y + height): + self[j, i] += 1 + + def remove_weight_at(self, x, y, width, height): + for i in range(x, x + width): + for j in range(y, y + height): + self[j, i] -= 1 class SpreadBox(hippo.CanvasBox, hippo.CanvasItem): __gtype_name__ = 'SugarSpreadBox' def __init__(self, **kwargs): hippo.CanvasBox.__init__(self, **kwargs) - self._grid = [] + self._grid = None self._center = None - - for i in range(0, _GRID_WIDTH * _GRID_HEIGHT): - self._grid.append(None) + self._width = -1 + self._height = -1 def set_center_item(self, item): if self._center: self.remove(self._center) - self._center = item self.append(item, hippo.PACK_FIXED) + self._center = item + + self._layout_center() def add_item(self, item): - start_pos = int(random.random() * len(self._grid)) - - pos = start_pos - while self._grid[pos] != None: - pos = pos + 1 - if pos == len(self._grid): - pos = 0 - elif pos == start_pos: - break - - self._grid[pos] = item - self.append(item, hippo.PACK_FIXED) - - cell_y = int(pos / _GRID_WIDTH) - cell_x = pos - cell_y * _GRID_WIDTH - self.set_position(item, cell_x * _CELL_WIDTH, cell_y * _CELL_HEIGHT) + self._layout_item(item) def remove_item(self, item): - for i in range(0, len(self._grid)): - if self._grid[i] == item: - self._grid[i] = None self.remove(item) + + def _layout_item(self, item): + if not self._grid: + return + + trials = _NUM_TRIALS + placed = False + + while trials > 0 and not placed: + [width, height] = item.get_allocation() + cell_size = self._grid.cell_size + + w = int(width / cell_size) + h = int(height / cell_size) + x = int(random() * (self._grid.x_tiles - w)) + y = int(random() * (self._grid.y_tiles - h)) + + weight = self._grid.compute_weight_at(x, y, w, h) + if weight == 0: + self._grid.add_weight_at(x, y, w, h) + self.set_position(item, cell_size * x, cell_size * y) + placed = True + + trials -= 1 + + def _layout(self): + for item in self.get_children(): + if item != self._center: + self._layout_item(item) + + def _layout_center(self): + if not self._center or not self._grid: + return + [width, height] = self._center.get_allocation() + x = (self._width - width) / 2 + y = (self._height - height) / 2 + self.set_position(self._center, x, y) + def do_allocate(self, width, height, origin_changed): hippo.CanvasBox.do_allocate(self, width, height, origin_changed) - if self._center: - [icon_width, icon_height] = self._center.get_allocation() - self.set_position(self._center, (width - icon_width) / 2, - (height - icon_height) / 2) + if width != self._width or height != self._height: + cell_size = width / _X_TILES + y_tiles = height / cell_size + + self._grid = _Grid(_X_TILES, y_tiles, cell_size) + self._width = width + self._height = height + + self._layout() + + self._layout_center() diff --git a/tests/test-notebook.py b/tests/test-notebook.py old mode 100644 new mode 100755 diff --git a/tests/test-snowflake-box.py b/tests/test-snowflake-box.py index 4164af4f..eb7efb90 100755 --- a/tests/test-snowflake-box.py +++ b/tests/test-snowflake-box.py @@ -54,6 +54,10 @@ canvas = hippo.Canvas() root_box = SpreadBox(background_color=0xe2e2e2ff) canvas.set_root(root_box) +box = SnowflakeBox() +snow_flake = _create_snowflake(box, 0) +root_box.set_center_item(box) + box = SnowflakeBox() snow_flake = _create_snowflake(box, 30) root_box.add_item(box)