No multi import
[pysize.git] / ui / char_matrix.py
blob0db9a4272d4e0534b85b8e54155a1d607554cc03
1 from ui.utils import human_unit, short_string
3 # A character is composed of 9 positions
4 # 012
5 # 345
6 # 678
8 # 9: selection bit
10 # Example :
11 # '+' = 1, 3, 4, 5, 7 = (1<<1) + (1<<3) + (1<<4) + (1<<5) + (1<<7) = 186
13 HLINE_START = (1<<4) + (1<<5)
14 HLINE_END = (1<<3) + (1<<4)
15 HLINE = HLINE_START | HLINE_END
17 VLINE_START = (1<<4) + (1<<7)
18 VLINE_END = (1<<1) + (1<<4)
19 VLINE = VLINE_START | VLINE_END
21 MASK = (1<<9) - 1
22 SELECTED = 1<<9
24 class CharMatrix:
25 """A 2D array of characters."""
26 def __init__(self, width, height, tree, selected_item=None):
27 self.width = width
28 self.height = height
29 self.tree = tree
30 self.selected_item = selected_item
31 self.matrix = [[0 for i in xrange(width)] for j in xrange(height)]
32 self._horizontal_line(0, 0, width)
33 self._horizontal_line(0, height - 1, width)
34 self._vertical_line(0, 0, height)
35 self._vertical_line(width - 1, 0, height)
37 if not tree.root:
38 return
40 offset = 0
41 for child in tree.root.get_children():
42 self._draw_boxes(child, 0, offset)
43 offset += child.size
45 def _compose_point(self, x, y, new):
46 self.matrix[y][x] |= new
48 def _horizontal_line(self, x, y, length, mask=0):
49 self._compose_point(x, y, HLINE_START | mask)
50 for i in xrange(x + 1, x + length - 1):
51 self._compose_point(i, y, HLINE | mask)
52 self._compose_point(x + length - 1, y, HLINE_END | mask)
54 def _vertical_line(self, x, y, length, mask=0):
55 self._compose_point(x, y, VLINE_START | mask)
56 for i in xrange(y + 1, y + length - 1):
57 self._compose_point(x, i, VLINE | mask)
58 self._compose_point(x, y + length - 1, VLINE_END | mask)
60 def _draw_string(self, x, y, length, string):
61 print_string = short_string(string.decode('UTF-8'), length)
62 self.matrix[y][x:x+len(print_string)] = print_string
64 def _draw_box(self, x0, x1, y0, y1, item, mask):
65 item.rectangle = (x0, x1, y0, y1)
66 length = x1 - x0
67 if y1 > y0:
68 self._horizontal_line(x0, y0, length + 1, mask)
69 self._horizontal_line(x0, y1, length + 1, mask)
70 self._vertical_line(x0, y0, y1 - y0 + 1, mask)
71 self._vertical_line(x1, y0, y1 - y0 + 1, mask)
73 if item.is_real():
74 if y1 > y0 + 1:
75 self._draw_string(x0+1, (y0+y1)/2, length - 2,
76 item.get_name())
77 if y1 > y0 + 2:
78 self._draw_string(x0+1, (y0+y1)/2 + 1, length - 2,
79 human_unit(item.size))
80 else:
81 # For the 'remaining' item, the size is more important than
82 # the dumy name, so we print it instead of the name when there is
83 # room for a single line
84 size_string_y = (y0+y1)/2 + 1
85 if y1 > y0 + 2:
86 self._draw_string(x0+1, (y0+y1)/2, length - 2,
87 item.get_name())
88 else:
89 size_string_y -= 1
90 if y1 > y0 + 1:
91 self._draw_string(x0 + 1, size_string_y, length - 2,
92 human_unit(item.size))
94 def _draw_boxes(self, item, depth, offset):
95 x0 = depth * (self.width - 1) / self.tree.height
96 x1 = (depth + 1) * (self.width - 1) / self.tree.height
97 y0 = (self.height - 1) * offset / self.tree.root.size
98 y1 = (self.height - 1) * (offset + item.size) / self.tree.root.size
100 if item is self.selected_item:
101 mask = SELECTED
102 else:
103 mask = 0
105 self._draw_box(x0, x1, y0, y1, item, mask)
106 depth += 1
107 for child in item.get_children():
108 self._draw_boxes(child, depth, offset)
109 offset += child.size