]> git.tdb.fi Git - libs/gltk.git/blob - source/layout.h
Add some classes for automatically creating basic layouts
[libs/gltk.git] / source / layout.h
1 /* $Id$
2
3 This file is part of libmspgltk
4 Copyright © 2011  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #ifndef MSP_GLTK_LAYOUT_H_
9 #define MSP_GLTK_LAYOUT_H_
10
11 #include <list>
12 #include <set>
13 #include <sigc++/trackable.h>
14 #include "geometry.h"
15
16 namespace Msp {
17 namespace GLtk {
18
19 class Container;
20 class Widget;
21
22 /**
23 Positions Widgets inside a Container.
24
25 A layout operates on constraints, which are used to form a linear program that
26 is then solved to obtain positions and dimensions that fulfill the constraints.
27 There are three kinds of constraints available: ordering, alignment and
28 dimension matching.
29
30 Ordering constraints specify that the widgets should be placed next to other
31 along X or Y axis.  These operate on one axis at a time, so a widget could be
32 "right of" another even if they are separated by hundreds of pixels vertically.
33 The widgets will be separated by a spacing value, which is settable on a per-
34 layout basis.
35
36 Alignment constraints make the corresponding edges of two widgets be on the
37 same line.  These are incompatible with ordering constraints, so only one or
38 the other should be used between any pair of widgets for the same axis.
39
40 Dimension matching constraints force the two widgets to have the same dimension
41 along the relevant axis.
42
43 In addition to constraints, there are some other properties that can be set on
44 widgets to determine how they are laid out.  Gravity affects which edge of the
45 container the widget should be placed at.  This is a relatively weak hint and
46 will be overridden by many other things.  Margins can also be specified to
47 prevent widgets from getting too close to the container's edges.
48
49 Usually widgets are made as small as their content allows.  Setting the expand
50 flag for a widget causes it to use as much space as possible.  If multiple co-
51 dependent widgets have the expand flag set, the results are currently
52 undefined.
53
54 Since specifiyng constraints manually can be quite tedious, there are some
55 derived Layout classes that implement common positioning patterns.  See
56 MixedRows and Grid.
57 */
58 class Layout
59 {
60 private:
61         enum
62         {
63                 HORIZONTAL = 0,
64                 VERTICAL = 1,
65                 SELF_POS = 2,
66                 SELF_DIM = 4,
67                 TARGET_POS = 8,
68                 TARGET_DIM = 16,
69                 SPACING = 32
70         };
71
72 public:
73         enum ConstraintType
74         {
75                 ABOVE = VERTICAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING,
76                 BELOW = VERTICAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
77                 RIGHT_OF = HORIZONTAL|SELF_POS|TARGET_POS|TARGET_DIM|SPACING,
78                 LEFT_OF = HORIZONTAL|SELF_POS|SELF_DIM|TARGET_POS|SPACING,
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
95                 Constraint(ConstraintType, Slot &);
96         };
97
98         struct Packing
99         {
100                 int gravity;
101                 bool expand;
102
103                 Packing();
104         };
105
106         struct Slot: public sigc::trackable
107         {
108                 Layout &layout;
109                 unsigned index;
110                 Widget &widget;
111                 Geometry geom;
112                 std::list<Constraint> constraints;
113                 Packing horiz_pack;
114                 Packing vert_pack;
115
116                 Slot(Layout &, Widget &);
117                 virtual ~Slot() { }
118
119                 void autosize_changed();
120         };
121
122         class LinearProgram;
123         struct Pointers;
124
125         Container *container;
126         std::list<Slot *> slots;
127         Sides margin;
128         unsigned row_spacing;
129         unsigned col_spacing;
130
131         static Pointers pointers[2];
132
133 public:
134         Layout();
135         virtual ~Layout();
136
137         void set_container(Container &);
138         void set_margin(const Sides &);
139         void set_spacing(unsigned);
140         void set_row_spacing(unsigned);
141         void set_column_spacing(unsigned);
142
143         void add_widget(Widget &);
144         void remove_widget(Widget &);
145 protected:
146         virtual Slot *create_slot(Widget &);
147         Slot &get_slot_for_widget(Widget &);
148         static ConstraintType complement(ConstraintType);
149 public:
150         void add_constraint(Widget &, ConstraintType, Widget &);
151         void set_gravity(Widget &, int, int);
152         void set_expand(Widget &, bool, bool);
153
154         void update();
155
156 protected:
157         void find_constraint_group(Slot &, ConstraintType, std::set<Slot *> &);
158         void sort_slots(std::list<Slot *> &, ConstraintType);
159         void solve_constraints(int);
160 };
161
162 } // namespace GLtk
163 } // namespace Msp
164
165 #endif