196 | | _ICON_SPACING_FACTORS = [1.5, 1.4, 1.3, 1.2, 1.1, 1.0] |
197 | | _SPIRAL_SPACING_FACTORS = [1.5, 1.5, 1.5, 1.4, 1.3, 1.2] |
198 | | _MIMIMUM_RADIUS_ENCROACHMENT = 0.75 |
199 | | _INITIAL_ANGLE = math.pi |
| 190 | _INTERMEDIATE_C = (style.STANDARD_ICON_SIZE + style.SMALL_ICON_SIZE) / 2 |
| 191 | _INTERMEDIATE_A = (style.STANDARD_ICON_SIZE * 2 + _INTERMEDIATE_C) / 3 |
| 192 | _INTERMEDIATE_E = (_INTERMEDIATE_C + style.SMALL_ICON_SIZE * 2) / 3 |
| 193 | _INTERMEDIATE_B = (_INTERMEDIATE_A + _INTERMEDIATE_C) / 2 |
| 194 | _INTERMEDIATE_D = (_INTERMEDIATE_C + _INTERMEDIATE_E) / 2 |
| 195 | _ICON_SIZES = [style.MEDIUM_ICON_SIZE, style.STANDARD_ICON_SIZE, |
| 196 | _INTERMEDIATE_A, _INTERMEDIATE_B, _INTERMEDIATE_C, |
| 197 | _INTERMEDIATE_D, _INTERMEDIATE_E, style.SMALL_ICON_SIZE] |
| 198 | _ICON_SPACING_FACTORS = [1.5, 1.4, 1.3, 1.2, 1.15, 1.1, 1.05, 1.0] |
246 | | distance = style.STANDARD_ICON_SIZE + style.DEFAULT_SPACING * \ |
247 | | _ICON_SPACING_FACTORS[_ICON_SIZES.index(style.STANDARD_ICON_SIZE)] |
248 | | radius = max(children_count * distance / (2 * math.pi), _MINIMUM_RADIUS) |
249 | | if radius < _MAXIMUM_RADIUS: |
250 | | return radius, style.STANDARD_ICON_SIZE |
251 | | |
252 | | self._spiral_mode = True |
253 | | icon_size = style.STANDARD_ICON_SIZE |
254 | | angle, radius = self._calculate_angle_and_radius(children_count, |
255 | | icon_size) |
256 | | while radius > _MAXIMUM_RADIUS: |
257 | | i = _ICON_SIZES.index(icon_size) |
258 | | if i < len(_ICON_SIZES) - 1: |
259 | | icon_size = _ICON_SIZES[i + 1] |
260 | | angle, radius = self._calculate_angle_and_radius( |
261 | | children_count, icon_size) |
262 | | else: |
263 | | break |
| 244 | # Continue by shrinking the icon size to STANDARD_ICON_SIZE. |
| 245 | radius = _MAXIMUM_RADIUS |
| 246 | distance = radius * (2 * math.pi) / children_count |
| 247 | icon_size = int(distance - style.DEFAULT_SPACING * \ |
| 248 | _ICON_SPACING_FACTORS[_ICON_SIZES.index(style.STANDARD_ICON_SIZE)]) |
| 249 | if icon_size >= style.STANDARD_ICON_SIZE: |
| 250 | return radius, icon_size |
| 251 | |
| 252 | # Continue by shrinking the icon size to SMALL_ICON_SIZE. |
| 253 | icon_size = max(int(distance - style.DEFAULT_SPACING * \ |
| 254 | _ICON_SPACING_FACTORS[_ICON_SIZES.index( |
| 255 | style.SMALL_ICON_SIZE)]), style.SMALL_ICON_SIZE) |
270 | | if self._spiral_mode: |
271 | | min_width_, box_width = self.box.get_width_request() |
272 | | min_height_, box_height = self.box.get_height_request(box_width) |
273 | | angle, radius = self._calculate_angle_and_radius(icon_index, |
274 | | icon_size) |
275 | | x, y = self._convert_from_polar_to_cartesian(angle, radius, |
276 | | icon_size, |
277 | | width, height) |
278 | | else: |
279 | | angle = icon_index * (2 * math.pi / children_count) - math.pi / 2 |
280 | | x = radius * cos(angle) + (width - icon_size) / 2 |
281 | | y = radius * sin(angle) + (height - icon_size - \ |
| 262 | angle = icon_index * (2 * math.pi / children_count) - math.pi / 2 |
| 263 | x = radius * cos(angle) + (width - icon_size) / 2 |
| 264 | y = radius * sin(angle) + (height - icon_size - \ |
285 | | def _convert_from_polar_to_cartesian(self, angle, radius, icon_size, width, |
286 | | height): |
287 | | """ Convert angle, radius to x, y """ |
288 | | x = int(math.sin(angle) * radius) |
289 | | y = int(math.cos(angle) * radius) |
290 | | x = - x + (width - icon_size) / 2 |
291 | | y = y + (height - icon_size - (style.GRID_CELL_SIZE / 2)) / 2 |
292 | | return x, y |
293 | | |
294 | | def _calculate_angle_and_radius(self, icon_count, icon_size): |
295 | | """ Based on icon_count and icon_size, calculate radius and angle. """ |
296 | | spiral_spacing = _SPIRAL_SPACING_FACTORS[_ICON_SIZES.index(icon_size)] |
297 | | icon_spacing = icon_size + style.DEFAULT_SPACING * \ |
298 | | _ICON_SPACING_FACTORS[_ICON_SIZES.index(icon_size)] |
299 | | angle = _INITIAL_ANGLE |
300 | | radius = _MINIMUM_RADIUS - (icon_size * _MIMIMUM_RADIUS_ENCROACHMENT) |
301 | | for i in range(icon_count): |
302 | | circumference = radius * 2 * math.pi |
303 | | n = circumference / icon_spacing |
304 | | angle += (2 * math.pi / n) |
305 | | radius += (float(icon_spacing) * spiral_spacing / n) |
306 | | return angle, radius |
307 | | |