]> git.tdb.fi Git - libs/gltk.git/blob - source/layout.h
Smarter way of complementing constraint types
[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         };
66
67 public:
68         enum ConstraintType
69         {
70                 ABOVE = VERTICAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING,
71                 BELOW = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
72                 RIGHT_OF = HORIZONTAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING,
73                 LEFT_OF = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
74                 ALIGN_TOP = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM,
75                 ALIGN_BOTTOM = VERTICAL|SELF_POS|TARGET_POS,
76                 ALIGN_RIGHT = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM,
77                 ALIGN_LEFT = HORIZONTAL|SELF_POS|TARGET_POS,
78                 COPY_WIDTH = HORIZONTAL|SELF_DIM|TARGET_DIM,
79                 COPY_HEIGHT = VERTICAL|SELF_DIM|TARGET_DIM
80         };
81
82 protected:
83         struct Slot;
84
85         struct Constraint
86         {
87                 ConstraintType type;
88                 Slot &target;
89                 int spacing;
90
91                 Constraint(ConstraintType, Slot &);
92         };
93
94         struct Packing
95         {
96                 int gravity;
97                 bool expand;
98
99                 Packing();
100         };
101
102         struct Slot: public sigc::trackable
103         {
104                 Layout &layout;
105                 int index;
106                 Widget &widget;
107                 Geometry autosize_geom;
108                 Geometry geom;
109                 std::list<Constraint> constraints;
110                 Packing horiz_pack;
111                 Packing vert_pack;
112
113                 Slot(Layout &, Widget &);
114                 virtual ~Slot() { }
115
116                 void autosize_changed();
117                 void visibility_changed(bool);
118         };
119
120         enum SolveMode
121         {
122                 UPDATE,
123                 AUTOSIZE
124         };
125
126         class LinearProgram;
127         struct Pointers;
128
129         Container *container;
130         std::list<Slot *> slots;
131         unsigned n_active_slots;
132         Sides margin;
133         unsigned row_spacing;
134         unsigned col_spacing;
135         Geometry autosize_geom;
136
137         static Pointers pointers[2];
138
139 public:
140         Layout();
141         virtual ~Layout();
142
143         void set_container(Container &);
144         void set_margin(const Sides &);
145
146         /** Sets the default spacing between widgets in bothg directions. */
147         void set_spacing(unsigned);
148
149         /** Sets the default vertical spacing between widgets.  Affects the ABOVE
150         and BELOW constraints. */
151         void set_row_spacing(unsigned);
152
153         /** Sets the default horizontal spacing between widgets.  Affects the
154         LEFT_OF and RIGHT_OF constraints. */
155         void set_column_spacing(unsigned);
156
157         void add_widget(Widget &);
158         void remove_widget(Widget &);
159 protected:
160         virtual Slot *create_slot(Widget &);
161         void update_slot_indices();
162         Slot &get_slot_for_widget(Widget &);
163         static ConstraintType complement(ConstraintType);
164         void create_constraint(Widget &, ConstraintType, Widget &, int);
165
166 public:
167         /** Adds a constraint between two widgets. */
168         void add_constraint(Widget &src, ConstraintType type, Widget &tgt);
169
170         /** Adds a constraint between two widgets, overriding the default spacing.
171         Not all constraint types use a spacing. */
172         void add_constraint(Widget &src, ConstraintType type, Widget &tgt, unsigned);
173
174         void set_gravity(Widget &, int, int);
175         void set_expand(Widget &, bool, bool);
176
177         void update();
178         void autosize();
179
180 protected:
181         void solve_constraints(int, SolveMode);
182 };
183
184 } // namespace GLtk
185 } // namespace Msp
186
187 #endif