Ticket #2235: 0001-add-spiral-to-ring-layout-as-number-of-icons-increas.patch
File 0001-add-spiral-to-ring-layout-as-number-of-icons-increas.patch, 8.8 KB (added by walter, 14 years ago) |
---|
-
src/jarabe/desktop/favoriteslayout.py
From bb4e9ee815df681b74a6c0d4b5dab214eb5895ac Mon Sep 17 00:00:00 2001 From: Walter Bender <walter@sugarlabs.org> Date: Wed, 25 Aug 2010 09:40:52 -0400 Subject: [PATCH] add spiral to ring layout as number of icons increases --- src/jarabe/desktop/favoriteslayout.py | 122 +++++++++++++++++++++++++++++--- 1 files changed, 110 insertions(+), 12 deletions(-) diff --git a/src/jarabe/desktop/favoriteslayout.py b/src/jarabe/desktop/favoriteslayout.py index 160ce0e..8bc0f1f 100644
a b _ICON_SIZES = [style.MEDIUM_ICON_SIZE, style.STANDARD_ICON_SIZE, 198 198 _ICON_SPACING_FACTORS = [1.5, 1.4, 1.3, 1.2, 1.15, 1.1, 1.05, 1.0] 199 199 200 200 201 class RingLayout(FavoritesLayout):201 class BasicRingLayout(FavoritesLayout): 202 202 """Lay out icons in a ring around the XO man.""" 203 203 204 __gtype_name__ = ' RingLayout'204 __gtype_name__ = 'BasicRingLayout' 205 205 icon_name = 'view-radial' 206 206 """Name of icon used in home view dropdown palette.""" 207 key = ' ring-layout'207 key = 'basic-ring-layout' 208 208 """String used in profile to represent this view.""" 209 209 # TRANS: label for the ring layout in the favorites view 210 210 palette_name = _('Ring') … … class RingLayout(FavoritesLayout): 312 312 return 0 313 313 314 314 315 _MIMIMUM_RADIUS_ENCROACHMENT = 0.75 316 _INITIAL_ANGLE = math.pi 317 _SPIRAL_SPACING_FACTORS = [1.5, 1.5, 1.5, 1.4, 1.35, 1.3, 1.25, 1.2] 318 319 320 class RingLayout(BasicRingLayout): 321 """ Variation of Basic Ring that morphs into a spiral as 322 the number of icons increases beyond the capacity of the 323 STANDARD_ICON_SIZE. """ 324 325 __gtype_name__ = 'RingLayout' 326 icon_name = 'view-radial' 327 """Name of icon used in home view dropdown palette.""" 328 key = 'ring-layout' 329 """String used in profile to represent this view.""" 330 331 def __init__(self): 332 BasicRingLayout.__init__(self) 333 self._locked_children = {} 334 self._spiral_mode = False 335 336 def _calculate_radius_and_icon_size(self, children_count): 337 """ Adjust the ring or spiral radius and icon size as needed. """ 338 self._spiral_mode = False 339 # Begin by increasing the radius. 340 distance = style.MEDIUM_ICON_SIZE + style.DEFAULT_SPACING * \ 341 _ICON_SPACING_FACTORS[_ICON_SIZES.index(style.MEDIUM_ICON_SIZE)] 342 radius = max(children_count * distance / (2 * math.pi), _MINIMUM_RADIUS) 343 if radius < _MAXIMUM_RADIUS: 344 return radius, style.MEDIUM_ICON_SIZE 345 346 # Continue by shrinking the icon size. 347 radius = _MAXIMUM_RADIUS 348 distance = radius * (2 * math.pi) / children_count 349 icon_size = int(distance - style.DEFAULT_SPACING * \ 350 _ICON_SPACING_FACTORS[_ICON_SIZES.index(style.STANDARD_ICON_SIZE)]) 351 if icon_size >= style.STANDARD_ICON_SIZE: 352 return radius, icon_size 353 354 # Finally, switch to a spiral. 355 self._spiral_mode = True 356 icon_size = style.STANDARD_ICON_SIZE 357 angle, radius = self._calculate_angle_and_radius(children_count, 358 icon_size) 359 while radius > _MAXIMUM_RADIUS: 360 i = _ICON_SIZES.index(icon_size) 361 if i < len(_ICON_SIZES) - 1: 362 icon_size = _ICON_SIZES[i + 1] 363 angle, radius = self._calculate_angle_and_radius( 364 children_count, icon_size) 365 else: 366 break 367 return radius, icon_size 368 369 def _calculate_position(self, radius, icon_size, icon_index, children_count, 370 sin=math.sin, cos=math.cos): 371 """ Calculate an icon position on a circle or a spiral. """ 372 width, height = self.box.get_allocation() 373 if self._spiral_mode: 374 min_width_, box_width = self.box.get_width_request() 375 min_height_, box_height = self.box.get_height_request(box_width) 376 angle, radius = self._calculate_angle_and_radius(icon_index, 377 icon_size) 378 x, y = self._convert_from_polar_to_cartesian(angle, radius, 379 icon_size, 380 width, height) 381 else: 382 angle = icon_index * (2 * math.pi / children_count) - math.pi / 2 383 x = radius * cos(angle) + (width - icon_size) / 2 384 y = radius * sin(angle) + (height - icon_size - \ 385 (style.GRID_CELL_SIZE / 2)) / 2 386 return x, y 387 388 def _convert_from_polar_to_cartesian(self, angle, radius, icon_size, width, 389 height): 390 """ Convert angle, radius to x, y """ 391 x = int(math.sin(angle) * radius) 392 y = int(math.cos(angle) * radius) 393 x = - x + (width - icon_size) / 2 394 y = y + (height - icon_size - (style.GRID_CELL_SIZE / 2)) / 2 395 return x, y 396 397 def _calculate_angle_and_radius(self, icon_count, icon_size): 398 """ Based on icon_count and icon_size, calculate radius and angle. """ 399 spiral_spacing = _SPIRAL_SPACING_FACTORS[_ICON_SIZES.index(icon_size)] 400 icon_spacing = icon_size + style.DEFAULT_SPACING * \ 401 _ICON_SPACING_FACTORS[_ICON_SIZES.index(icon_size)] 402 angle = _INITIAL_ANGLE 403 radius = _MINIMUM_RADIUS - (icon_size * _MIMIMUM_RADIUS_ENCROACHMENT) 404 for i in range(icon_count): 405 circumference = radius * 2 * math.pi 406 n = circumference / icon_spacing 407 angle += (2 * math.pi / n) 408 radius += (float(icon_spacing) * spiral_spacing / n) 409 return angle, radius 410 411 315 412 _SUNFLOWER_CONSTANT = style.STANDARD_ICON_SIZE * .75 316 413 """Chose a constant such that STANDARD_ICON_SIZE icons are nicely spaced.""" 317 414 … … This is the golden angle: http://en.wikipedia.org/wiki/Golden_angle 337 434 Calculation: math.radians(360) / ( _GOLDEN_RATIO * _GOLDEN_RATIO ) 338 435 """ 339 436 340 class SunflowerLayout( RingLayout):437 class SunflowerLayout(BasicRingLayout): 341 438 """Spiral layout based on Fibonacci ratio in phyllotaxis. 342 439 343 440 See http://algorithmicbotany.org/papers/abop/abop-ch4.pdf … … class SunflowerLayout(RingLayout): 356 453 """String used to identify this layout in home view dropdown palette.""" 357 454 358 455 def __init__(self): 359 RingLayout.__init__(self)456 BasicRingLayout.__init__(self) 360 457 self.skipped_indices = [] 361 458 362 459 def _calculate_radius_and_icon_size(self, children_count): … … class SunflowerLayout(RingLayout): 407 504 408 505 return x, y 409 506 410 class BoxLayout( RingLayout):507 class BoxLayout(BasicRingLayout): 411 508 """Lay out icons in a square around the XO man.""" 412 509 413 510 __gtype_name__ = 'BoxLayout' … … class BoxLayout(RingLayout): 423 520 """String used to identify this layout in home view dropdown palette.""" 424 521 425 522 def __init__(self): 426 RingLayout.__init__(self)523 BasicRingLayout.__init__(self) 427 524 428 525 def _calculate_position(self, radius, icon_size, index, children_count, 429 526 sin=None, cos=None): … … class BoxLayout(RingLayout): 444 541 cos = lambda r: cos_d(math.degrees(r)) 445 542 sin = lambda r: cos_d(math.degrees(r) - 90) 446 543 447 return RingLayout._calculate_position\544 return BasicRingLayout._calculate_position\ 448 545 (self, radius, icon_size, index, children_count, 449 546 sin=sin, cos=cos) 450 547 451 class TriangleLayout( RingLayout):548 class TriangleLayout(BasicRingLayout): 452 549 """Lay out icons in a triangle around the XO man.""" 453 550 454 551 __gtype_name__ = 'TriangleLayout' … … class TriangleLayout(RingLayout): 464 561 """String used to identify this layout in home view dropdown palette.""" 465 562 466 563 def __init__(self): 467 RingLayout.__init__(self)564 BasicRingLayout.__init__(self) 468 565 469 566 def _calculate_radius_and_icon_size(self, children_count): 470 567 # use slightly larger minimum radius than parent, because sides 471 568 # of triangle come awful close to the center. 472 569 radius, icon_size = \ 473 RingLayout._calculate_radius_and_icon_size(self, children_count) 570 BasicRingLayout._calculate_radius_and_icon_size(self, 571 children_count) 474 572 return max(radius, _MINIMUM_RADIUS + style.MEDIUM_ICON_SIZE), icon_size 475 573 476 574 def _calculate_position(self, radius, icon_size, index, children_count, … … class TriangleLayout(RingLayout): 501 599 cos = lambda r: cos_d(math.degrees(r)) 502 600 sin = lambda r: sin_d(math.degrees(r)) 503 601 504 return RingLayout._calculate_position\602 return BasicRingLayout._calculate_position\ 505 603 (self, radius, icon_size, index, children_count, 506 604 sin=sin, cos=cos)