diff options
author | Tomeu Vizoso <tomeu@tomeuvizoso.net> | 2008-06-16 13:24:22 (GMT) |
---|---|---|
committer | Tomeu Vizoso <tomeu@tomeu-laptop.(none)> | 2008-06-20 10:25:19 (GMT) |
commit | 5965bf1a8d50b3c1cc8a67b0e47f1bf6a14f78ae (patch) | |
tree | 31f16b8f07e62a39c766a4868e80d3f417f076e2 /src | |
parent | 76d353a120463fa5ca5af2cddd5705555b23c0e3 (diff) |
Try harder to resolve collisions in the mesh view.
Diffstat (limited to 'src')
-rw-r--r-- | src/view/home/spreadlayout.py | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/src/view/home/spreadlayout.py b/src/view/home/spreadlayout.py index 0ad350a..23ff587 100644 --- a/src/view/home/spreadlayout.py +++ b/src/view/home/spreadlayout.py @@ -15,7 +15,7 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from numpy import array -from random import random +import random import hippo import gobject @@ -26,6 +26,8 @@ from sugar.graphics import style _PLACE_TRIALS = 20 _MAX_WEIGHT = 255 _CELL_SIZE = 4 +_REFRESH_RATE = 200 +_MAX_COLLISIONS_PER_REFRESH = 20 class _Grid(gobject.GObject): __gsignals__ = { @@ -49,8 +51,8 @@ class _Grid(gobject.GObject): trials = _PLACE_TRIALS weight = _MAX_WEIGHT while trials > 0 and weight: - x = int(random() * (self.width - width)) - y = int(random() * (self.height - height)) + x = int(random.random() * (self.width - width)) + y = int(random.random() * (self.height - height)) rect = gtk.gdk.Rectangle(x, y, width, height) new_weight = self._compute_weight(rect) @@ -76,17 +78,9 @@ class _Grid(gobject.GObject): self._children.append(child) self.add_weight(child.grid_rect) - def _move_child(self, child, new_rect): - self._remove_weight(child.grid_rect) - self.add_weight(new_rect) - - child.grid_rect = new_rect - - self.emit('child-changed', child) - - def _shift_child(self, child): + def _shift_child(self, child, weight): rect = child.grid_rect - weight = self._compute_weight(rect) + new_rects = [] if (rect.x + rect.width < self.width - 1): @@ -105,6 +99,25 @@ class _Grid(gobject.GObject): new_rects.append(gtk.gdk.Rectangle(rect.x, rect.y - 1, rect.width, rect.height)) + if rect.x + rect.width < self.width - 1 and \ + rect.y + rect.height < self.height - 1: + new_rects.append(gtk.gdk.Rectangle(rect.x + 1, rect.y + 1, + rect.width, rect.height)) + + if rect.x - 1 > 0 and rect.y + rect.height < self.height - 1: + new_rects.append(gtk.gdk.Rectangle(rect.x - 1, rect.y + 1, + rect.width, rect.height)) + + if rect.x + rect.width < self.width - 1 and rect.y - 1 > 0: + new_rects.append(gtk.gdk.Rectangle(rect.x + 1, rect.y - 1, + rect.width, rect.height)) + + if rect.x - 1 > 0 and rect.y - 1 > 0: + new_rects.append(gtk.gdk.Rectangle(rect.x - 1, rect.y - 1, + rect.width, rect.height)) + + random.shuffle(new_rects) + best_rect = None for new_rect in new_rects: new_weight = self._compute_weight(new_rect) @@ -113,18 +126,33 @@ class _Grid(gobject.GObject): weight = new_weight if best_rect: - self._move_child(child, best_rect) + child.grid_rect = best_rect + weight = self._shift_child(child, weight) return weight - - def _solve_collisions(self): - for collision in self._collisions[:]: - weight = self._shift_child(collision) - if not weight: - self._collisions.remove(collision) + def __solve_collisions_cb(self): + for i in range(_MAX_COLLISIONS_PER_REFRESH): + collision = self._collisions.pop(0) + + old_rect = collision.grid_rect + self._remove_weight(collision.grid_rect) + weight = self._compute_weight(collision.grid_rect) + weight = self._shift_child(collision, weight) + self.add_weight(collision.grid_rect) + + # TODO: we shouldn't give up the first time we failed to find a + # better position. + if old_rect != collision.grid_rect: + self._detect_collisions(collision) + self.emit('child-changed', collision) + if weight > 0: + self._collisions.append(collision) + + if not self._collisions: + return False - return (len(self._collisions) > 0) + return True def _detect_collisions(self, child): collision_found = False @@ -139,8 +167,9 @@ class _Grid(gobject.GObject): if child not in self._collisions: self._collisions.append(child) -# if len(self._collisions) and not self._collisions_sid: -# self._collisions_sid = gobject.idle_add(self._solve_collisions) + if len(self._collisions) and not self._collisions_sid: + self._collisions_sid = gobject.timeout_add(_REFRESH_RATE, + self.__solve_collisions_cb, priority=gobject.PRIORITY_LOW) def add_weight(self, rect): for i in range(rect.x, rect.x + rect.width): |