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()
class ViewLayout(Layout): def __init__(self): self._grid = None self._width = 0 self._height = 0 def setup(self, allocation, owner_icon, activity_icon=None): if self._grid is not None: if self._width == allocation.width and \ self._height == allocation.height: return self._width = allocation.width self._height = allocation.height 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_request = owner_icon.size_request() owner_width, owner_height = owner_request.width, owner_request.height 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 owner_icon_allocation = Gdk.Rectangle() owner_icon_allocation.x = (width - owner_width) / 2 owner_icon_allocation.y = allocation.y + y owner_icon_allocation.width = owner_width owner_icon_allocation.height = 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) grid_x = int(owner_icon_allocation.x / float(_CELL_SIZE)) grid_y = int(owner_icon_allocation.y / float(_CELL_SIZE)) self._grid.add(owner_icon, owner_grid_width, owner_grid_height, grid_x, grid_y, locked=True) if activity_icon is None: return # Position the current activity below the XO icon # FIXME must ensure we cross into next grid cell here.. activity_request = activity_icon.size_request() activity_icon_allocation = Gdk.Rectangle() activity_icon_allocation.x = (width - activity_request.width) / 2 activity_icon_allocation.y = owner_icon_allocation.y + owner_height activity_icon_allocation.width = activity_request.width activity_icon_allocation.height = activity_request.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(activity_icon_allocation.x / float(_CELL_SIZE)) y = int(activity_icon_allocation.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_icon(self, child, x, y, allocation): pass def move(self, child, x, y, allocation=None): self._grid.move(child, x / _CELL_SIZE, y / _CELL_SIZE, locked=True) child_request = child.size_request() rect = self._grid.get_child_rect(child) child_allocation = Gdk.Rectangle() child_allocation.x = int(round(rect.x * _CELL_SIZE)) child_allocation.y = int(round(rect.y * _CELL_SIZE)) child_allocation.width = child_request.width child_allocation.height = child_request.height child.size_allocate(child_allocation) def _get_child_grid_size(self, child): request = child.size_request() width = math.ceil(request.width / _CELL_SIZE) height = math.ceil(request.height / _CELL_SIZE) return int(width), int(height) def __grid_child_changed_cb(self, grid, child): request = child.size_request() rect = self._grid.get_child_rect(child) child_allocation = Gdk.Rectangle() child_allocation.x = int(round(rect.x * _CELL_SIZE)) child_allocation.y = int(round(rect.y * _CELL_SIZE)) child_allocation.width = request.width child_allocation.height = request.height child.size_allocate(child_allocation)
class RandomActivityLayout(ActivityLayout): """Lay out icons randomly; try to nudge them around to resolve overlaps.""" __gtype_name__ = 'RandomActivityLayout' icon_name = 'view-freeform' """Name of icon used in home view dropdown palette.""" key = 'random-layout' """String used in profile to represent this view.""" # TRANS: label for the freeform layout in the pathway view palette_name = _('Freeform') """String used to identify this layout in home view dropdown palette.""" def __init__(self): ActivityLayout.__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): ActivityLayout.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) def remove(self, icon): self._grid.remove(icon) ActivityLayout.remove(self, icon) def move_icon(self, icon, x, y, locked=False): self._grid.move(icon, x / _CELL_SIZE, y / _CELL_SIZE, locked) ActivityLayout.move_icon(self, icon, x, y, locked) 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(rect.x * _CELL_SIZE, rect.y * _CELL_SIZE, child_width, child_height, origin_changed) def allow_dnd(self): return True
class RandomLayout(FavoritesLayout): """Lay out icons randomly; try to nudge them around to resolve overlaps.""" __gtype_name__ = 'RandomLayout' icon_name = 'view-freeform' """Name of icon used in home view dropdown palette.""" key = 'random-layout' """String used in profile to represent this view.""" # TRANS: label for the freeform layout in the favorites view palette_name = _('Freeform') """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) def remove(self, icon): self._grid.remove(icon) FavoritesLayout.remove(self, icon) 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) 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(rect.x * _CELL_SIZE, rect.y * _CELL_SIZE, child_width, child_height, origin_changed) def allow_dnd(self): return True