]> git.tdb.fi Git - libs/gltk.git/blob - source/layout.h
379b468bf3f46efe30b37de4165081f8731e8d83
[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 other
24 along X or Y axis.  These operate on one axis at a time, so a widget could be
25 "right of" another even if they are separated by hundreds of pixels vertically.
26 The widgets will be separated by a spacing value, which is settable on a per-
27 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
49 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                 TARGET_POS = 8,
61                 TARGET_DIM = 16,
62                 SPACING = 32
63         };
64
65 public:
66         enum ConstraintType
67         {
68                 ABOVE = VERTICAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING,
69                 BELOW = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
70                 RIGHT_OF = HORIZONTAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING,
71                 LEFT_OF = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
72                 ALIGN_TOP = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM,
73                 ALIGN_BOTTOM = VERTICAL|SELF_POS|TARGET_POS,
74                 ALIGN_RIGHT = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|TARGET_DIM,
75                 ALIGN_LEFT = HORIZONTAL|SELF_POS|TARGET_POS,
76                 COPY_WIDTH = HORIZONTAL|SELF_DIM|TARGET_DIM,
77                 COPY_HEIGHT = VERTICAL|SELF_DIM|TARGET_DIM
78         };
79
80 protected:
81         struct Slot;
82
83         struct Constraint
84         {
85                 ConstraintType type;
86                 Slot &target;
87
88                 Constraint(ConstraintType, Slot &);
89         };
90
91         struct Packing
92         {
93                 int gravity;
94                 bool expand;
95
96                 Packing();
97         };
98
99         struct Slot: public sigc::trackable
100         {
101                 Layout &layout;
102                 unsigned index;
103                 Widget &widget;
104                 Geometry geom;
105                 std::list<Constraint> constraints;
106                 Packing horiz_pack;
107                 Packing vert_pack;
108
109                 Slot(Layout &, Widget &);
110                 virtual ~Slot() { }
111
112                 void autosize_changed();
113         };
114
115         class LinearProgram;
116         struct Pointers;
117
118         Container *container;
119         std::list<Slot *> slots;
120         Sides margin;
121         unsigned row_spacing;
122         unsigned col_spacing;
123
124         static Pointers pointers[2];
125
126 public:
127         Layout();
128         virtual ~Layout();
129
130         void set_container(Container &);
131         void set_margin(const Sides &);
132         void set_spacing(unsigned);
133         void set_row_spacing(unsigned);
134         void set_column_spacing(unsigned);
135
136         void add_widget(Widget &);
137         void remove_widget(Widget &);
138 protected:
139         virtual Slot *create_slot(Widget &);
140         Slot &get_slot_for_widget(Widget &);
141         static ConstraintType complement(ConstraintType);
142 public:
143         void add_constraint(Widget &, ConstraintType, Widget &);
144         void set_gravity(Widget &, int, int);
145         void set_expand(Widget &, bool, bool);
146
147         void update();
148
149 protected:
150         void find_constraint_group(Slot &, ConstraintType, std::set<Slot *> &);
151         void sort_slots(std::list<Slot *> &, ConstraintType);
152         void solve_constraints(int);
153 };
154
155 } // namespace GLtk
156 } // namespace Msp
157
158 #endif