Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2010-08-16 19:55:47 (GMT)
committer Walter Bender <walter@sugarlabs.org>2010-08-16 19:55:47 (GMT)
commit163d91ba9859d82db6c83c63350c9ae126d2f186 (patch)
treeb6511af23293e1e2ee6336fa846d749417f6b782
parent950f451aa2b8cc52b52448c2653b219c8b4d91ae (diff)
adding spiral extension to Ring View
-rw-r--r--src/jarabe/desktop/favoriteslayout.py98
1 files changed, 79 insertions, 19 deletions
diff --git a/src/jarabe/desktop/favoriteslayout.py b/src/jarabe/desktop/favoriteslayout.py
index 85e1b59..d0c1dbd 100644
--- a/src/jarabe/desktop/favoriteslayout.py
+++ b/src/jarabe/desktop/favoriteslayout.py
@@ -1,4 +1,5 @@
# Copyright (C) 2008 One Laptop Per Child
+# Copyright (C) 2010 Sugar Labs
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -32,6 +33,13 @@ _logger = logging.getLogger('FavoritesLayout')
_CELL_SIZE = 4
_BASE_SCALE = 1000
+_INTERMEDIATE_B = (style.STANDARD_ICON_SIZE + style.SMALL_ICON_SIZE) / 2
+_INTERMEDIATE_A = (style.STANDARD_ICON_SIZE + _INTERMEDIATE_B) / 2
+_INTERMEDIATE_C = (_INTERMEDIATE_B + style.SMALL_ICON_SIZE) / 2
+_ICON_SIZES = [style.MEDIUM_ICON_SIZE, style.STANDARD_ICON_SIZE,
+ _INTERMEDIATE_A, _INTERMEDIATE_B, _INTERMEDIATE_C,
+ style.SMALL_ICON_SIZE]
+
class FavoritesLayout(gobject.GObject, hippo.CanvasLayout):
"""Base class of the different layout types."""
@@ -185,6 +193,42 @@ _MINIMUM_RADIUS = style.XLARGE_ICON_SIZE / 2 + style.DEFAULT_SPACING + \
style.STANDARD_ICON_SIZE * 2
_MAXIMUM_RADIUS = (gtk.gdk.screen_height() - style.GRID_CELL_SIZE) / 2 - \
style.STANDARD_ICON_SIZE - style.DEFAULT_SPACING
+_ICON_SPACING_FACTOR = [1.5, 1.4, 1.3, 1.2, 1.1, 1.0]
+_SPIRAL_SPACING_FACTOR = [1.5, 1.5, 1.5, 1.4, 1.3, 1.2]
+_MIMIMUM_RADIUS_ENCROACHMENT = 0.75
+_INITIAL_ANGLE = math.pi
+
+
+def _convert_from_polar_to_cartesian(angle, radius, icon_size, width, height):
+ """ Convert angle, radius to x, y """
+ x = -math.sin(angle) * radius
+ y = math.cos(angle) * radius
+ x = int(x) + (width - icon_size) / 2
+ y = int(y) + (height - icon_size - (style.GRID_CELL_SIZE / 2) ) / 2
+ return x, y
+
+
+def _calculate_angle_and_radius(icon_count, icon_size):
+ """ Based upon icon_count and icon_size, calculate radius and angle. """
+ spiral_spacing_factor = _SPIRAL_SPACING_FACTOR[_ICON_SIZES.index(icon_size)]
+ icon_spacing_factor = _ICON_SPACING_FACTOR[_ICON_SIZES.index(icon_size)]
+ icon_size += icon_spacing_factor * style.DEFAULT_SPACING
+ angle = _INITIAL_ANGLE
+ radius = _MINIMUM_RADIUS - (icon_size * _MIMIMUM_RADIUS_ENCROACHMENT)
+ for i in range(icon_count):
+ angle, radius = _increment_angle_and_radius(angle, radius, icon_size,
+ spiral_spacing_factor)
+ return angle, radius
+
+
+def _increment_angle_and_radius(angle, radius, icon_size, spacing_factor):
+ """ Increment the angle and radius of the spiral. """
+ circumference = radius * 2 * math.pi
+ n = circumference / icon_size
+ return angle + (2 * math.pi / n), \
+ radius + (float(icon_size) * spacing_factor / n)
+
+
class RingLayout(FavoritesLayout):
"""Lay out icons in a ring around the XO man."""
@@ -201,6 +245,7 @@ class RingLayout(FavoritesLayout):
def __init__(self):
FavoritesLayout.__init__(self)
self._locked_children = {}
+ self._spiral = False
def append(self, icon, locked=False):
FavoritesLayout.append(self, icon, locked)
@@ -221,31 +266,46 @@ class RingLayout(FavoritesLayout):
self._locked_children[child] = (x, y)
def _calculate_radius_and_icon_size(self, children_count):
- # what's the radius required without downscaling?
+ """ Adjust the ring or spiral radius and icon size as needed. """
+ self._spiral = False
+ distance = style.MEDIUM_ICON_SIZE + style.DEFAULT_SPACING
+ radius = max(children_count * distance / (2 * math.pi), _MINIMUM_RADIUS)
+ if radius < _MAXIMUM_RADIUS:
+ return radius, style.MEDIUM_ICON_SIZE
+
distance = style.STANDARD_ICON_SIZE + style.DEFAULT_SPACING
+ radius = max(children_count * distance / (2 * math.pi), _MINIMUM_RADIUS)
+ if radius < _MAXIMUM_RADIUS:
+ return radius, style.STANDARD_ICON_SIZE
+
+ self._spiral = True
icon_size = style.STANDARD_ICON_SIZE
- # circumference is 2*pi*r; we want this to be at least
- # 'children_count * distance'
- radius = children_count * distance / (2 * math.pi)
- # limit computed radius to reasonable bounds.
- radius = max(radius, _MINIMUM_RADIUS)
- radius = min(radius, _MAXIMUM_RADIUS)
- # recompute icon size from limited radius
- if children_count > 0:
- icon_size = (2 * math.pi * radius / children_count) \
- - style.DEFAULT_SPACING
- # limit adjusted icon size.
- icon_size = max(icon_size, style.SMALL_ICON_SIZE)
- icon_size = min(icon_size, style.MEDIUM_ICON_SIZE)
+ angle, radius = _calculate_angle_and_radius(children_count, icon_size)
+ while radius > _MAXIMUM_RADIUS:
+ i = _ICON_SIZES.index(icon_size)
+ if i < len(_ICON_SIZES) - 1:
+ icon_size = _ICON_SIZES[i + 1]
+ angle, radius = _calculate_angle_and_radius(children_count,
+ icon_size)
+ else:
+ break
return radius, icon_size
- def _calculate_position(self, radius, icon_size, index, children_count,
+ def _calculate_position(self, radius, icon_size, icon_index, children_count,
sin=math.sin, cos=math.cos):
+ """ Calculate an icon position on a circle or a spiral. """
width, height = self.box.get_allocation()
- angle = index * (2 * math.pi / children_count) - math.pi / 2
- x = radius * cos(angle) + (width - icon_size) / 2
- y = radius * sin(angle) + (height - icon_size -
- (style.GRID_CELL_SIZE/2) ) / 2
+ if self._spiral:
+ min_width_, box_width = self.box.get_width_request()
+ min_height_, box_height = self.box.get_height_request(box_width)
+ angle, radius = _calculate_angle_and_radius(icon_index, icon_size)
+ x, y = _convert_from_polar_to_cartesian(angle, radius,
+ icon_size, width, height)
+ else:
+ angle = icon_index * (2 * math.pi / children_count) - math.pi / 2
+ x = radius * cos(angle) + (width - icon_size) / 2
+ y = radius * sin(angle) + (height - icon_size - \
+ (style.GRID_CELL_SIZE/2) ) / 2
return x, y
def _get_children_in_ring(self):