Handle empty tree
[pysize.git] / ui / char_matrix.py
blobdcd8c2020825ebcb28cc9b66765b0f9c86ac5eef
1 from ui.utils import human_unit, short_string
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 def __init__(self, width, height, tree, selected_item=None):
26 self.width = width
27 self.height = height
28 self.tree = tree
29 self.selected_item = selected_item
30 self.matrix = [[0 for i in xrange(width)] for j in xrange(height)]
31 self._horizontal_line(0, 0, width)
32 self._horizontal_line(0, height - 1, width)
33 self._vertical_line(0, 0, height)
34 self._vertical_line(width - 1, 0, height)
36 if not tree.root:
37 return
39 offset = 0
40 for child in tree.root.get_children():
41 self._draw_boxes(child, 0, offset)
42 offset += child.size
44 def _compose_point(self, x, y, new):
45 self.matrix[y][x] |= new
47 def _horizontal_line(self, x, y, length, mask=0):
48 self._compose_point(x, y, HLINE_START | mask)
49 for i in xrange(x + 1, x + length - 1):
50 self._compose_point(i, y, HLINE | mask)
51 self._compose_point(x + length - 1, y, HLINE_END | mask)
53 def _vertical_line(self, x, y, length, mask=0):
54 self._compose_point(x, y, VLINE_START | mask)
55 for i in xrange(y + 1, y + length - 1):
56 self._compose_point(x, i, VLINE | mask)
57 self._compose_point(x, y + length - 1, VLINE_END | mask)
59 def _draw_string(self, x, y, length, string):
60 print_string = short_string(string.decode('UTF-8'), length)
61 self.matrix[y][x:x+len(print_string)] = print_string
63 def _draw_box(self, x0, x1, y0, y1, item, mask):
64 item.rectangle = (x0, x1, y0, y1)
65 length = x1 - x0
66 if y1 > y0:
67 self._horizontal_line(x0, y0, length + 1, mask)
68 self._horizontal_line(x0, y1, length + 1, mask)
69 self._vertical_line(x0, y0, y1 - y0 + 1, mask)
70 self._vertical_line(x1, y0, y1 - y0 + 1, mask)
72 if item.is_real():
73 if y1 > y0 + 1:
74 self._draw_string(x0+1, (y0+y1)/2, length - 2,
75 item.basename)
76 if y1 > y0 + 2:
77 self._draw_string(x0+1, (y0+y1)/2 + 1, length - 2,
78 human_unit(item.size))
79 else:
80 # For the 'remaining' item, the size is more important than
81 # the dumy name, so we print it instead of the name when there is
82 # room for a single line
83 size_string_y = (y0+y1)/2 + 1
84 if y1 > y0 + 2:
85 self._draw_string(x0+1, (y0+y1)/2, length - 2,
86 item.basename)
87 else:
88 size_string_y -= 1
89 if y1 > y0 + 1:
90 self._draw_string(x0 + 1, size_string_y, length - 2,
91 human_unit(item.size))
93 def _draw_boxes(self, item, depth, offset):
94 x0 = depth * (self.width - 1) / self.tree.height
95 x1 = (depth + 1) * (self.width - 1) / self.tree.height
96 y0 = (self.height - 1) * offset / self.tree.root.size
97 y1 = (self.height - 1) * (offset + item.size) / self.tree.root.size
99 if item == self.selected_item:
100 mask = SELECTED
101 else:
102 mask = 0
104 self._draw_box(x0, x1, y0, y1, item, mask)
105 depth += 1
106 for child in item.get_children():
107 self._draw_boxes(child, depth, offset)
108 offset += child.size