Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGary Martin <gary@garycmartin.com>2012-10-11 03:17:04 (GMT)
committer Santiago Rodriguez <santi@trisquel.info>2012-10-22 16:04:13 (GMT)
commit4e57ae78ca8826497dc3ad52ca33903e0e50b903 (patch)
tree128644b6fa93638740cd3c82adafb865d819d725
parent21fcd272cd3d3aac300b0ab70b6484b8438de7a5 (diff)
Improve circle and spiral layout favourite view to improve touch interaction - SL #4025
The original controls provided for RingLayout did not allow clean enough control of the circle and spiral icon layout. The global arrays of hard coded icon spacing at discrete icon size steps has now been replaced with a continuous function that will much more smoothly layout from 0 up to a large number of activities (a wider range of testing and comparison with previous behaviour was done with up to 55 activities). The layout now make better use of the available canvas space using larger icons, smaller steps between icon sizes, and larger circle/spiral arrangements to try and maximise both icon hit target size and provide enough space between icons to minimise target miss press errors. This patch switches from fixed intermadiate sizes (the removed _INTERMEDIATE_* constants) to dynamic intermadiate sizes. Signed-off-by: Gary Martin <gary@garycmartin.com> Signed-off-by: Manuel QuiƱones <manuq@laptop.org> Acked-by: Simon Schampijer <simon@laptop.org>
-rw-r--r--src/jarabe/desktop/favoriteslayout.py80
1 files changed, 43 insertions, 37 deletions
diff --git a/src/jarabe/desktop/favoriteslayout.py b/src/jarabe/desktop/favoriteslayout.py
index 3c9be8b..5f3b560 100644
--- a/src/jarabe/desktop/favoriteslayout.py
+++ b/src/jarabe/desktop/favoriteslayout.py
@@ -33,12 +33,6 @@ _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 Layout(object):
@@ -279,13 +273,14 @@ class RandomLayout(SpreadLayout):
self.fixed_positions[child] = (x, y)
-_MINIMUM_RADIUS = style.XLARGE_ICON_SIZE / 2 + style.DEFAULT_SPACING + \
- style.STANDARD_ICON_SIZE * 2
+_MINIMUM_RADIUS = style.XLARGE_ICON_SIZE / 2 + style.DEFAULT_SPACING
_MAXIMUM_RADIUS = (Gdk.Screen.height() - style.GRID_CELL_SIZE) / 2 - \
- style.STANDARD_ICON_SIZE - style.DEFAULT_SPACING
-_ICON_SPACING_FACTORS = [1.5, 1.4, 1.3, 1.2, 1.1, 1.0]
-_SPIRAL_SPACING_FACTORS = [1.5, 1.5, 1.5, 1.4, 1.3, 1.2]
-_MIMIMUM_RADIUS_ENCROACHMENT = 0.75
+ style.DEFAULT_SPACING
+_RING_SPACING_FACTOR = 0.95
+_SPIRAL_SPACING_FACTOR = 0.75
+_RADIUS_GROWTH_FACTOR = 1.25
+_MIMIMUM_RADIUS_PADDING_FACTOR = 0.85
+_MAXIMUM_RADIUS_PADDING_FACTOR = 1.25
_INITIAL_ANGLE = math.pi
@@ -308,32 +303,31 @@ class RingLayout(ViewLayout):
def _calculate_radius_and_icon_size(self, children_count):
""" Adjust the ring or spiral radius and icon size as needed. """
self._spiral_mode = False
- distance = style.MEDIUM_ICON_SIZE + style.DEFAULT_SPACING * \
- _ICON_SPACING_FACTORS[_ICON_SIZES.index(style.MEDIUM_ICON_SIZE)]
- 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 * \
- _ICON_SPACING_FACTORS[_ICON_SIZES.index(style.STANDARD_ICON_SIZE)]
- radius = max(children_count * distance / (2 * math.pi),
- _MINIMUM_RADIUS)
- if radius < _MAXIMUM_RADIUS:
- return radius, style.STANDARD_ICON_SIZE
- self._spiral_mode = True
- icon_size = style.STANDARD_ICON_SIZE
+ icon_size = style.MEDIUM_ICON_SIZE
angle_, radius = self._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]
+ if radius <= self._calculate_maximum_radius(icon_size):
+ return radius, icon_size
+ while radius > self._calculate_maximum_radius(icon_size):
+ icon_size -= 1
+ if icon_size <= style.STANDARD_ICON_SIZE:
+ break
+ else:
angle_, radius = self._calculate_angle_and_radius(
children_count, icon_size)
- else:
+ if radius <= self._calculate_maximum_radius(icon_size):
+ return radius, icon_size
+
+ self._spiral_mode = True
+ icon_size = style.MEDIUM_ICON_SIZE
+ while radius > self._calculate_maximum_radius(icon_size):
+ if icon_size < style.SMALL_ICON_SIZE:
break
+ else:
+ angle_, radius = self._calculate_angle_and_radius(
+ children_count, icon_size)
+ icon_size -= 1
return radius, icon_size
def _calculate_position(self, radius, icon_size, icon_index,
@@ -362,18 +356,30 @@ class RingLayout(ViewLayout):
y = y + (height - icon_size - (style.GRID_CELL_SIZE / 2)) / 2
return x, y
+ def _calculate_maximum_radius(self, icon_size):
+ """ Return the maximum radius including encroachment. """
+ return _MAXIMUM_RADIUS - (icon_size * _MAXIMUM_RADIUS_PADDING_FACTOR)
+
def _calculate_angle_and_radius(self, icon_count, icon_size):
""" Based on icon_count and icon_size, calculate radius and angle. """
- spiral_spacing = _SPIRAL_SPACING_FACTORS[_ICON_SIZES.index(icon_size)]
- icon_spacing = icon_size + style.DEFAULT_SPACING * \
- _ICON_SPACING_FACTORS[_ICON_SIZES.index(icon_size)]
+ if self._spiral_mode:
+ _icon_spacing_factor = _SPIRAL_SPACING_FACTOR
+ else:
+ _icon_spacing_factor = _RING_SPACING_FACTOR
+
+ # The diagonal width of an icon is used to help stabilise the
+ # spacing of icons across a wide range of circle and spiral
+ # layout sizes:
+ icon_spacing = math.sqrt(icon_size ** 2 * 2) * _icon_spacing_factor + \
+ style.DEFAULT_SPACING
angle = _INITIAL_ANGLE
- radius = _MINIMUM_RADIUS - (icon_size * _MIMIMUM_RADIUS_ENCROACHMENT)
+ radius = _MINIMUM_RADIUS + (icon_spacing *
+ _MIMIMUM_RADIUS_PADDING_FACTOR)
for i_ in range(icon_count):
circumference = radius * 2 * math.pi
n = circumference / icon_spacing
angle += (2 * math.pi / n)
- radius += (float(icon_spacing) * spiral_spacing / n)
+ radius += (float(icon_spacing) * _RADIUS_GROWTH_FACTOR / n)
return angle, radius
def allocate_children(self, allocation, children):