Ticket #2143: 0001-more-spacing-fine-tuning.patch

File 0001-more-spacing-fine-tuning.patch, 7.9 KB (added by walter, 14 years ago)

Mre finetuning of the spiral spacing

  • src/jarabe/desktop/favoriteslayout.py

    From 5d9f8906d0392821a2c14e4d5a0f0fc0727fc835 Mon Sep 17 00:00:00 2001
    From: Walter Bender <walter@sugarlabs.org>
    Date: Mon, 9 Aug 2010 16:07:33 -0400
    Subject: [PATCH] more spacing fine-tuning
    
    ---
     src/jarabe/desktop/favoriteslayout.py |  117 +++++++++++++++++++++++++++-----
     1 files changed, 98 insertions(+), 19 deletions(-)
    
    diff --git a/src/jarabe/desktop/favoriteslayout.py b/src/jarabe/desktop/favoriteslayout.py
    index 85e1b59..14c1d68 100644
    a b  
    11# Copyright (C) 2008 One Laptop Per Child
     2# Copyright (C) 2010 Sugar Labs
    23#
    34# This program is free software; you can redistribute it and/or modify
    45# it under the terms of the GNU General Public License as published by
    _logger = logging.getLogger('FavoritesLayout') 
    3233
    3334_CELL_SIZE = 4
    3435_BASE_SCALE = 1000
     36_INTERMEDIATE_B = (style.STANDARD_ICON_SIZE + style.SMALL_ICON_SIZE) / 2
     37_INTERMEDIATE_A = (style.STANDARD_ICON_SIZE + _INTERMEDIATE_B) / 2
     38_INTERMEDIATE_C = (_INTERMEDIATE_B + style.SMALL_ICON_SIZE) / 2
     39
    3540
    3641class FavoritesLayout(gobject.GObject, hippo.CanvasLayout):
    3742    """Base class of the different layout types."""
    _MINIMUM_RADIUS = style.XLARGE_ICON_SIZE / 2 + style.DEFAULT_SPACING + \ 
    185190        style.STANDARD_ICON_SIZE * 2
    186191_MAXIMUM_RADIUS = (gtk.gdk.screen_height() - style.GRID_CELL_SIZE) / 2 - \
    187192        style.STANDARD_ICON_SIZE - style.DEFAULT_SPACING
     193_ICON_SIZES = [style.MEDIUM_ICON_SIZE, style.STANDARD_ICON_SIZE,
     194               _INTERMEDIATE_A, _INTERMEDIATE_B, _INTERMEDIATE_C,
     195               style.SMALL_ICON_SIZE]
     196_ICON_SPACING_FACTOR = [1.5, 1.4, 1.3, 1.2, 1.1, 1.0]
     197_SPIRAL_SPACING_FACTOR = [1.5, 1.5, 1.5, 1.4, 1.3, 1.2]
     198_MIMIMUM_RADIUS_ENCROACHMENT = 0.75
    188199
    189200class RingLayout(FavoritesLayout):
    190201    """Lay out icons in a ring around the XO man."""
    class RingLayout(FavoritesLayout): 
    201212    def __init__(self):
    202213        FavoritesLayout.__init__(self)
    203214        self._locked_children = {}
     215        self._spiral = False
     216        self._radius = _MINIMUM_RADIUS
     217        self._orientation = math.pi
     218        self._icon_size = style.MEDIUM_ICON_SIZE
     219        self._icon_spacing_factor = _ICON_SPACING_FACTOR[0]
     220        self._spiral_spacing_factor = _SPIRAL_SPACING_FACTOR[0]
     221        self._count = -1
    204222
    205223    def append(self, icon, locked=False):
    206224        FavoritesLayout.append(self, icon, locked)
    class RingLayout(FavoritesLayout): 
    221239            self._locked_children[child] = (x, y)
    222240
    223241    def _calculate_radius_and_icon_size(self, children_count):
    224         # what's the radius required without downscaling?
    225         distance = style.STANDARD_ICON_SIZE + style.DEFAULT_SPACING
    226         icon_size = style.STANDARD_ICON_SIZE
    227         # circumference is 2*pi*r; we want this to be at least
    228         # 'children_count * distance'
     242        """ Determine if we are drawing a ring with MEDIUM- or STANDARD-size
     243        icons or a spiral with STANDARD-, INTERMEDIATE-, or SMALL-size
     244        icons."""
     245        self._spiral = True
     246        distance = style.MEDIUM_ICON_SIZE + style.DEFAULT_SPACING
    229247        radius = children_count * distance / (2 * math.pi)
    230         # limit computed radius to reasonable bounds.
    231248        radius = max(radius, _MINIMUM_RADIUS)
    232         radius = min(radius, _MAXIMUM_RADIUS)
    233         # recompute icon size from limited radius
    234         if children_count > 0:
    235             icon_size = (2 * math.pi * radius / children_count) \
    236                         - style.DEFAULT_SPACING
    237         # limit adjusted icon size.
    238         icon_size = max(icon_size, style.SMALL_ICON_SIZE)
    239         icon_size = min(icon_size, style.MEDIUM_ICON_SIZE)
    240         return radius, icon_size
     249        if radius < _MAXIMUM_RADIUS:
     250            self._spiral = False
     251            self._icon_size = style.MEDIUM_ICON_SIZE
     252        if self._spiral:
     253            distance = style.STANDARD_ICON_SIZE + style.DEFAULT_SPACING
     254            radius = children_count * distance / (2 * math.pi)
     255            radius = max(radius, _MINIMUM_RADIUS)
     256            if radius < _MAXIMUM_RADIUS:
     257                self._spiral = False
     258                self._icon_size = style.STANDARD_ICON_SIZE
     259            else:
     260                self._spiral = True
     261                radius = _MINIMUM_RADIUS - \
     262                    (self._icon_size * _MIMIMUM_RADIUS_ENCROACHMENT)
     263
     264        # If there are fewer children, try increasing icon_size.
     265        if self._count > children_count:
     266            i = _ICON_SIZES.index(self._icon_size)
     267            if i > 0:
     268                self._icon_size = _ICON_SIZES[i - 1]
     269                self._icon_spacing_factor = _ICON_SPACING_FACTOR[i - 1]
     270                self._spiral_spacing_factor = _SPIRAL_SPACING_FACTOR[i - 1]
     271        self._count = children_count
     272
     273        # If the radius exceeds the minimun, try decreasing icon_size.
     274        if self._radius > _MAXIMUM_RADIUS:
     275            i = _ICON_SIZES.index(self._icon_size)
     276            if i < len(_ICON_SIZES) - 1:
     277                self._icon_size = _ICON_SIZES[i + 1]
     278                self._icon_spacing_factor = _ICON_SPACING_FACTOR[i + 1]
     279                self._spiral_spacing_factor = _SPIRAL_SPACING_FACTOR[i + 1]
     280
     281        return radius, self._icon_size
     282
     283    def _calculate_xy(self, icon_size, width, height):
     284        """ Convert r, o to x, y """
     285        x = -math.sin(self._orientation) * self._radius
     286        y = math.cos(self._orientation) * self._radius
     287        self._calculate_new_radius_orientation(icon_size + \
     288                             self._icon_spacing_factor * style.DEFAULT_SPACING)
     289
     290        x = int(x) + (width - icon_size) / 2
     291        y = int(y) + (height - icon_size - (style.GRID_CELL_SIZE / 2) ) / 2
     292        return x, y
     293
     294    def _calculate_new_radius_orientation(self, icon_size):
     295        """ Based upon current radius, calculate new increments """
     296        circumference = self._radius * 2 * math.pi
     297        n = circumference / icon_size
     298        self._orientation += 2 * math.pi / n
     299        self._radius += float(icon_size * self._spiral_spacing_factor) / n
    241300
    242301    def _calculate_position(self, radius, icon_size, index, children_count,
    243302                            sin=math.sin, cos=math.cos):
     303        """ Try fitting a circle or a spiral """
    244304        width, height = self.box.get_allocation()
    245         angle = index * (2 * math.pi / children_count) - math.pi / 2
    246         x = radius * cos(angle) + (width - icon_size) / 2
    247         y = radius * sin(angle) + (height - icon_size -
    248                                    (style.GRID_CELL_SIZE/2) ) / 2
     305        if not self._spiral:
     306            angle = index * (2 * math.pi / children_count) - math.pi / 2
     307            x = radius * cos(angle) + (width - icon_size) / 2
     308            y = radius * sin(angle) + (height - icon_size - \
     309                                       (style.GRID_CELL_SIZE/2) ) / 2
     310        else:
     311            min_width_, box_width = self.box.get_width_request()
     312            min_height_, box_height = self.box.get_height_request(box_width)
     313            if index == 0:
     314                self._radius = _MINIMUM_RADIUS - \
     315                    (self._icon_size * _MIMIMUM_RADIUS_ENCROACHMENT)
     316                self._orientation = math.pi
     317            x, y = self._calculate_xy(icon_size, width, height)
     318            # If we are off the screen, keep going...
     319            while x < min_width_ or x > box_width - icon_size or \
     320                    y < min_height_ or y > box_height - icon_size:
     321                x, y = self._calculate_xy(icon_size, width, height)
     322                # If we run past a corner, we will never return, so break
     323                if (x < min_height_ and \
     324                        (y < min_width_ or y > box_height - icon_size)) or \
     325                        (x > box_width - icon_size and \
     326                             (y < min_width_ or y > box_height - icon_size)):
     327                    break
    249328        return x, y
    250329
    251330    def _get_children_in_ring(self):