1 from .layout import Layout |
1 from .layout import Layout |
2 |
2 |
3 |
3 |
4 class FixedLayout(Layout): |
4 class FixedLayout(Layout): |
5 |
5 |
6 """Widgets are placed on fixed position as specified in `sizereq`. |
6 """Widgets are placed on fixed position as specified in hints. |
7 |
7 |
8 Align hints (kwargs to :meth:`add`): |
8 Position can be relative to any side or center of parent widget. |
9 * halign = 'left' (default) | 'right' | 'fill' | 'center' |
|
10 * valign = 'top' (default) | 'bottom' | 'fill' | 'center' |
|
11 |
9 |
12 """ |
10 """ |
13 |
11 |
14 def __init__(self): |
12 def __init__(self): |
15 Layout.__init__(self) |
13 Layout.__init__(self) |
16 self._widget_hints = {} # Widget : (halign, valign) |
14 self._widget_hints = {} # Widget : (left, top, right, bottom, xrel, yrel) |
17 |
15 |
18 def add(self, widget, *args, **kwargs): |
16 def add(self, widget, left=None, top=None, right=None, bottom=None, |
|
17 center=None, fill=None): |
|
18 """Add widget to layout. |
|
19 |
|
20 Place hints: |
|
21 * left, right, top, bottom = None | <num> ; <num> >= 0 |
|
22 - Fix Widget position to parent sides. |
|
23 - If both left and right (or top and bottom) are set, the widget |
|
24 will be stretched to fill full area minus specified space. |
|
25 * center, fill = None | 'x' | 'y' | 'xy' |
|
26 - Center widget in x, y or both axes. |
|
27 - Fill is shortcut for setting both positions in same axis. |
|
28 |
|
29 """ |
19 Layout.add(self, widget) |
30 Layout.add(self, widget) |
20 assert len(args) == 0, \ |
31 # Internally, coordinate relation is marked as: |
21 "FixedLayout does not support positional hint args: %s" % args |
32 # '+': from left or top |
22 assert all(key in ('halign', 'valign') for key in kwargs.keys()), \ |
33 # '-': from right or bottom |
23 "Unsupported hints: %s" % tuple(kwargs.keys()) |
34 # 'C': from center |
24 halign = kwargs.get('halign', 'left') |
35 # 'F': from both sides (fill) |
25 valign = kwargs.get('valign', 'top') |
36 xrel, yrel = '+', '+' |
26 self._widget_hints[widget] = (halign, valign) |
37 fill, center = fill or '', center or '' |
|
38 if left is None and right is not None: |
|
39 xrel = '-' |
|
40 if top is None and bottom is not None: |
|
41 yrel = '-' |
|
42 if 'x' in center: |
|
43 xrel = 'C' |
|
44 if 'y' in center: |
|
45 yrel = 'C' |
|
46 if 'x' in fill: |
|
47 xrel = 'F' |
|
48 if 'y' in fill: |
|
49 yrel = 'F' |
|
50 self._widget_hints[widget] = (left or 0, top or 0, |
|
51 right or 0, bottom or 0, |
|
52 xrel, yrel) |
27 |
53 |
28 def update(self, w, h): |
54 def update(self, w, h): |
29 for widget in self._managed_widgets: |
55 for widget in self._managed_widgets: |
30 halign, valign = self._widget_hints[widget] |
56 left, top, right, bottom, xrel, yrel = self._widget_hints[widget] |
31 px, py = widget.posreq |
|
32 sw, sh = widget.sizereq |
57 sw, sh = widget.sizereq |
33 if halign == 'right': px = w - px |
58 ox, oy = 0, 0 # origin |
34 if valign == 'bottom': py = h - py |
59 if xrel == '-': |
35 if halign == 'fill': px = 0; sw = w |
60 ox = w - sw |
36 if valign == 'fill': py = 0; sh = h |
61 if yrel == '-': |
37 if halign == 'center': px = (w - sw) // 2 |
62 oy = h - sh |
38 if valign == 'center': py = (h - sh) // 2 |
63 if xrel == 'C': |
|
64 ox = (w - sw) // 2 |
|
65 if yrel == 'C': |
|
66 oy = (h - sh) // 2 |
|
67 px = ox + left - right |
|
68 py = oy + top - bottom |
|
69 if xrel == 'F': |
|
70 px = left |
|
71 sw = w - left - right |
|
72 if yrel == 'F': |
|
73 py = top |
|
74 sh = h - top - bottom |
39 widget.resize(sw, sh) |
75 widget.resize(sw, sh) |
40 widget.pos.update(px, py) |
76 widget.pos.update(px, py) |