| 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 |
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 |
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 |