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