doc++, ménage.
[minwii.git] / src / pgu / gui / layout.py
1 """document layout engine."""
2 class Layout:
3 """the document layout engine
4
5 .widgets -- elements are kept in this list. read-only, use add to add items to it.
6 """
7
8 def __init__(self,rect=None):
9 """initialize the object with the size of the box."""
10 self._widgets = []
11 self.rect = rect
12
13 def add(self,e):
14 """add a document element to the layout.
15
16 a document element may be
17 - a tuple (w,h) if it is a whitespace element
18 - a tuple (0,h) if it is a linebreak element
19 - an integer -1,0,1 if it is a command to start a new block of elements that are aligned either left,center, or right.
20 - an object with a .rect (for size) -- such as a word element
21 - an object with a .rect (for size) and .align -- such as an image element
22 """
23
24 self._widgets.append(e)
25
26
27 def resize(self):
28 """resize the layout
29 this method recalculates the position of all document elements
30 after they have been added to the document. .rect.x,y will be updated for all
31 objects.
32 """
33 self.init()
34 self.widgets = []
35 for e in self._widgets:
36 if type(e) is tuple and e[0] != 0:
37 self.do_space(e)
38 elif type(e) is tuple and e[0] == 0:
39 self.do_br(e[1])
40 elif type(e) is int:
41 self.do_block(align=e)
42 elif hasattr(e,'align'):
43 self.do_align(e)
44 else:
45 self.do_item(e)
46 self.line()
47 self.rect.h = max(self.y,self.left_bottom,self.right_bottom)
48
49 def init(self):
50 self.x,self.y = self.rect.x,self.rect.y
51 self.left = self.rect.left
52 self.right = self.rect.right
53 self.left_bottom = 0
54 self.right_bottom = 0
55 self.y = self.rect.y
56 self.x = self.rect.x
57 self.h = 0
58
59 self.items = []
60 self.align = -1
61
62 def getleft(self):
63 if self.y > self.left_bottom:
64 self.left = self.rect.left
65 return self.left
66
67 def getright(self):
68 if self.y > self.right_bottom:
69 self.right = self.rect.right
70 return self.right
71
72 def do_br(self,h):
73 self.line()
74 self.h = h
75
76 def do_block(self,align=-1):
77 self.line()
78 self.align = align
79
80 def do_align(self,e):
81 align = e.align
82 ox,oy,oh = self.x,self.y,self.h
83 w,h = e.rect.w,e.rect.h
84
85 if align == 0:
86 self.line()
87 self.x = self.rect.left + (self.rect.width-w)/2
88 self.fit = 0
89 elif align == -1:
90 self.line()
91 self.y = max(self.left_bottom,self.y + self.h)
92 self.h = 0
93 self.x = self.rect.left
94 elif align == 1:
95 self.line()
96 self.y = max(self.right_bottom,self.y + self.h)
97 self.h = 0
98 self.x = self.rect.left + (self.rect.width-w)
99
100 e.rect.x,e.rect.y = self.x,self.y
101
102 self.x = self.x + w
103 self.y = self.y
104
105 if align == 0:
106 self.h = max(self.h,h)
107 self.y = self.y + self.h
108 self.x = self.getleft()
109 self.h = 0
110 elif align == -1:
111 self.left = self.x
112 self.left_bottom = self.y + h
113 self.x,self.y,self.h = ox + w,oy,oh
114 elif align == 1:
115 self.right = self.x - w
116 self.right_bottom = self.y + h
117 self.x,self.y,self.h = ox,oy,oh
118
119 self.widgets.append(e)
120
121 def do_space(self,e):
122 w,h = e
123 if self.x+w >= self.getright():
124 self.line()
125 else:
126 self.items.append(e)
127 self.h = max(self.h,h)
128 self.x += w
129
130 def do_item(self,e):
131 w,h = e.rect.w,e.rect.h
132 if self.x+w >= self.getright():
133 self.line()
134 self.items.append(e)
135 self.h = max(self.h,h)
136 self.x += w
137
138 def line(self):
139 x1 = self.getleft()
140 x2 = self.getright()
141 align = self.align
142 y = self.y
143
144 if len(self.items) != 0 and type(self.items[-1]) == tuple:
145 del self.items[-1]
146
147 w = 0
148 for e in self.items:
149 if type(e) == tuple: w += e[0]
150 else: w += e.rect.w
151
152 if align == -1: x = x1
153 elif align == 0:
154 x = x1 + ((x2-x1)-w)/2
155 self.fit = 0
156 elif align == 1: x = x2 - w
157
158 for e in self.items:
159 if type(e) == tuple: x += e[0]
160 else:
161 e.rect.x,e.rect.y = x,y
162 self.widgets.append(e)
163 x += e.rect.w
164
165 self.items = []
166 self.y = self.y + self.h
167 self.x = self.getleft()
168 self.h = 0
169
170
171
172 # vim: set filetype=python sts=4 sw=4 noet si :