]> git.tdb.fi Git - libs/gltk.git/blob - source/panel.h
Minor refactoring
[libs/gltk.git] / source / panel.h
1 #ifndef MSP_GLTK_PANEL_H_
2 #define MSP_GLTK_PANEL_H_
3
4 #include <msp/core/typeregistry.h>
5 #include "container.h"
6 #include "layout.h"
7 #include "mspgltk_api.h"
8
9 namespace Msp {
10 namespace GLtk {
11
12 /**
13 Panels are containers for other widgets.  Panel styles should have a special
14 part "children" to render the child widgets.  All properties of this part are
15 ignored.
16 */
17 class MSPGLTK_API Panel: public Container
18 {
19 public:
20         class Loader: public DataFile::DerivedObjectLoader<Panel, Widget::Loader>
21         {
22         public:
23                 typedef std::map<std::string, Widget *> WidgetMap;
24
25         protected:
26                 template<typename T>
27                 struct AddChildType
28                 {
29                         void operator()(const std::string &, Loader &) const;
30                 };
31
32                 WidgetMap &wdg_map;
33                 Widget *last_widget;
34
35         public:
36                 Loader(Panel &, WidgetMap &);
37
38         private:
39                 Layout &get_layout();
40                 Widget &get_last_widget();
41                 template<typename T>
42                 void arrangement();
43                 template<typename T>
44                 void child(const std::string &);
45                 void constraint(Layout::ConstraintType, const std::string &);
46                 void expand(bool, bool);
47                 void ghost(bool);
48                 void gravity(int, int);
49                 void grid(std::size_t);
50                 void layout();
51                 template<typename T>
52                 void unnamed_child();
53
54                 friend class Panel;
55         };
56
57 private:
58         template<typename T>
59         class ArrangedLoader: public DataFile::Loader
60         {
61         private:
62                 typename T::Loader arr_loader;
63
64         public:
65                 ArrangedLoader(Loader &, T &);
66         };
67
68 protected:
69         std::vector<Widget *> nav_order;
70         Layout *layout = nullptr;
71
72         static TypeRegistry<Loader::AddChildType, Loader &> widget_registry;
73         static bool widget_registry_init_done;
74
75 public:
76         Panel();
77         virtual ~Panel();
78
79         template<typename T>
80         static void register_child_type(const std::string &);
81
82         const char *get_class() const override { return "panel"; }
83
84         void set_layout(Layout *);
85         Layout *get_layout() { return layout; }
86
87 protected:
88         void autosize_special(const Part &, Geometry &) const override;
89         void render_special(const Part &, GL::Renderer &) const override;
90
91 public:
92         bool navigate(Navigation) override;
93 protected:
94         Widget *find_next_child(int, int, int, int, int) const;
95         static int compute_delta(int, int, int, int, int);
96
97         void on_size_change() override;
98         void on_child_added(Widget &) override;
99         void on_child_removed(Widget &) override;
100 };
101
102
103 template<typename T>
104 void Panel::register_child_type(const std::string &name)
105 {
106         widget_registry.register_type<T>(name);
107 }
108
109
110 template<typename T>
111 void Panel::Loader::child(const std::string &n)
112 {
113         unnamed_child<T>();
114         wdg_map[n] = last_widget;
115 }
116
117 template<typename T>
118 void Panel::Loader::unnamed_child()
119 {
120         RefPtr<T> chl = new T();
121         load_sub(*chl);
122         obj.add(*chl.get());
123         last_widget = chl.release();
124 }
125
126
127 template<typename T>
128 void Panel::Loader::AddChildType<T>::operator()(const std::string &kwd, Loader &ldr) const
129 {
130         ldr.add(kwd, &Loader::child<T>);
131         ldr.add(kwd, &Loader::unnamed_child<T>);
132 }
133
134 } // namespace GLtk
135 } // namespace Msp
136
137 #endif