]> git.tdb.fi Git - libs/gltk.git/blob - source/layout.h
Replace the derived layout classes with a more flexible design
[libs/gltk.git] / source / layout.h
1 #ifndef MSP_GLTK_LAYOUT_H_
2 #define MSP_GLTK_LAYOUT_H_
3
4 #include <list>
5 #include <set>
6 #include <sigc++/trackable.h>
7 #include "geometry.h"
8
9 namespace Msp {
10 namespace GLtk {
11
12 class Arrangement;
13 class Container;
14 class Widget;
15
16 /**
17 Positions Widgets inside a Container.
18
19 A layout operates on constraints, which are used to form a linear program that
20 is then solved to obtain positions and dimensions that fulfill the constraints.
21 There are three kinds of constraints available: ordering, alignment and
22 dimension matching.
23
24 Ordering constraints specify that the widgets should be placed next to each
25 other along X or Y axis.  These operate on one axis at a time, so a widget
26 could be "right of" another even if they are separated by hundreds of pixels
27 vertically.  The widgets will be separated by a spacing value, which is
28 settable on a per-layout basis.
29
30 Alignment constraints make the corresponding edges of two widgets be on the
31 same line.  These are incompatible with ordering constraints, so only one or
32 the other should be used between any pair of widgets for the same axis.
33
34 Dimension matching constraints force the two widgets to have the same dimension
35 along the relevant axis.
36
37 In addition to constraints, there are some other properties that can be set on
38 widgets to determine how they are laid out.  Gravity affects which edge of the
39 container the widget should be placed at.  This is a relatively weak hint and
40 will be overridden by many other things.  Margins can also be specified to
41 prevent widgets from getting too close to the container's edges.
42
43 Usually widgets are made as small as their content allows.  Setting the expand
44 flag for a widget causes it to use as much space as possible.  If multiple co-
45 dependent widgets have the expand flag set, the results are currently
46 undefined.
47
48 Since specifiyng constraints manually can be quite tedious, an Arrangement
49 interface is provided to automatically arrange widgets.  See classes Row,
50 Column and Grid for some commonly used arrangements.
51 */
52 class Layout
53 {
54 private:
55         enum
56         {
57                 HORIZONTAL = 0,
58                 VERTICAL = 1,
59                 SELF_POS = 2,
60                 SELF_DIM = 4,
61                 SELF_MASK = 6,
62                 TARGET_POS = 8,
63                 TARGET_DIM = 16,
64                 TARGET_MASK = 24,
65                 SPACING = 32,
66                 SLACK = 64
67         };
68
69 public:
70         enum ConstraintType
71         {
72                 ABOVE = VERTICAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING,
73                 BELOW = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
74                 RIGHT_OF = HORIZONTAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING,
75                 LEFT_OF = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
76                 FAR_ABOVE = VERTICAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING|SLACK,
77                 FAR_BELOW = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING|SLACK,
78                 FAR_RIGHT_OF = HORIZONTAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING|SLACK,
79                 FAR_LEFT_OF = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING|SLACK,
80                 ALIGN_TOP = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM,
81                 ALIGN_BOTTOM = VERTICAL|SELF_POS|TARGET_POS,
82                 ALIGN_RIGHT = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM,
83                 ALIGN_LEFT = HORIZONTAL|SELF_POS|TARGET_POS,
84                 COPY_WIDTH = HORIZONTAL|SELF_DIM|TARGET_DIM,
85                 COPY_HEIGHT = VERTICAL|SELF_DIM|TARGET_DIM
86         };
87
88 private:
89         struct Slot;
90
91         struct Constraint
92         {
93                 ConstraintType type;
94                 Slot &target;
95                 int spacing;
96
97                 Constraint(ConstraintType, Slot &);
98         };
99
100         struct Packing
101         {
102                 int gravity;
103                 bool expand;
104
105                 Packing();
106         };
107
108         struct Slot: public sigc::trackable
109         {
110                 Layout &layout;
111                 int index;
112                 Widget &widget;
113                 Geometry autosize_geom;
114                 Geometry geom;
115                 std::list<Constraint> constraints;
116                 Packing horiz_pack;
117                 Packing vert_pack;
118
119                 Slot(Layout &, Widget &);
120
121                 void autosize_changed();
122                 void visibility_changed(bool);
123         };
124
125         enum SolveMode
126         {
127                 UPDATE,
128                 AUTOSIZE
129         };
130
131         class LinearProgram;
132         struct Pointers;
133
134         Container *container;
135         std::list<Slot *> slots;
136         unsigned n_active_slots;
137         unsigned n_slack_constraints[2];
138         Sides margin;
139         unsigned row_spacing;
140         unsigned col_spacing;
141         Geometry autosize_geom;
142         std::list<Arrangement *> arrangement_stack;
143
144         static Pointers pointers[2];
145
146 public:
147         Layout();
148         ~Layout();
149
150         void set_container(Container &);
151         void set_margin(const Sides &);
152
153         /** Sets the default spacing between widgets in bothg directions. */
154         void set_spacing(unsigned);
155
156         /** Sets the default vertical spacing between widgets.  Affects the ABOVE
157         and BELOW constraints. */
158         void set_row_spacing(unsigned);
159
160         /** Sets the default horizontal spacing between widgets.  Affects the
161         LEFT_OF and RIGHT_OF constraints. */
162         void set_column_spacing(unsigned);
163
164         void push_arrangement(Arrangement &);
165         Arrangement *get_arrangement() const;
166         void pop_arrangement(Arrangement &);
167
168         void add_widget(Widget &);
169         void remove_widget(Widget &);
170 private:
171         void update_slot_indices();
172         Slot &get_slot_for_widget(Widget &);
173         static ConstraintType complement(ConstraintType);
174         void create_constraint(Widget &, ConstraintType, Widget &, int);
175
176 public:
177         /** Adds a constraint between two widgets. */
178         void add_constraint(Widget &src, ConstraintType type, Widget &tgt);
179
180         /** Adds a constraint between two widgets, overriding the default spacing.
181         Not all constraint types use a spacing. */
182         void add_constraint(Widget &src, ConstraintType type, Widget &tgt, unsigned);
183
184         void set_gravity(Widget &, int, int);
185         void set_expand(Widget &, bool, bool);
186
187         void update();
188         void autosize();
189
190 private:
191         void solve_constraints(int, SolveMode);
192 };
193
194 } // namespace GLtk
195 } // namespace Msp
196
197 #endif