Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/sugar/graphics/spreadbox.py
blob: 6e96e532c4d04bdf1a28369f9359a28a914e8b38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import random
import math

import cairo
import hippo

_DISTANCE_THRESHOLD = 120.0

class SpreadBox(hippo.CanvasBox, hippo.CanvasItem):
	__gtype_name__ = 'SugarSpreadBox'

	def __init__(self, **kwargs):
		hippo.CanvasBox.__init__(self, **kwargs)

		self._items_to_position = []
		self._spread_on_add = False
		self._stable = False

	def add(self, item):
		self._items_to_position.append(item)
		self.append(item, hippo.PACK_FIXED)

	def _get_distance(self, icon1, icon2):
		[icon1_x, icon1_y] = self.get_position(icon1)
		[icon2_x, icon2_y] = self.get_position(icon2)

		a = icon1_x - icon2_x
		b = icon1_y - icon2_y

		return math.sqrt(a * a  + b * b)

	def _get_repulsion(self, icon1, icon2):
		[icon1_x, icon1_y] = self.get_position(icon1)
		[icon2_x, icon2_y] = self.get_position(icon2)

		f_x = icon1_x - icon2_x
		f_y = icon1_y - icon2_y

		return [f_x, f_y]

	def _clamp_position(self, icon, x, y):
		x = max(0, x)
		y = max(0, y)

		[item_w, item_h] = icon.get_request()
		[box_w, box_h] = self.get_allocation()

		x = min(box_w - item_w, x)
		y = min(box_h - item_h, y)

		return [x, y]

	def _spread_icons(self):
		self._stable = True

		for icon1 in self.get_children():
			vx = 0
			vy = 0

			for icon2 in self.get_children():
				if icon1 != icon2:
					distance = self._get_distance(icon1, icon2)
					if distance <= _DISTANCE_THRESHOLD:
						self._stable = False
						[f_x, f_y] = self._get_repulsion(icon1, icon2)
						vx += f_x
						vy += f_y

			if vx != 0 or vy != 0:
				[x, y] = self.get_position(icon1)
				new_x = x + vx
				new_y = y + vy

				[new_x, new_y] = self._clamp_position(icon1, new_x, new_y)

				self.move(icon1, new_x, new_y)

	def do_allocate(self, width, height):
		hippo.CanvasBox.do_allocate(self, width, height)

		for item in self._items_to_position:
			[item_w, item_h] = item.get_request()

			x = int(random.random() * width - item_w)
			y = int(random.random() * height - item_h)

			[x, y] = self._clamp_position(item, x, y)
			self.move(item, x, y)

		self._items_to_position = []

		tries = 10
		self._spread_icons()
		while not self._stable and tries > 0:
			self._spread_icons()
			tries -= 1