]> git.tdb.fi Git - libs/gltk.git/blob - source/panel.h
Rework how widget ownership works in Container
[libs/gltk.git] / source / panel.h
1 #ifndef MSP_GLTK_PANEL_H_
2 #define MSP_GLTK_PANEL_H_
3
4 #include <memory>
5 #include <msp/core/typeregistry.h>
6 #include "container.h"
7 #include "layout.h"
8 #include "mspgltk_api.h"
9
10 namespace Msp {
11 namespace GLtk {
12
13 /**
14 Panels are containers for other widgets.  Panel styles should have a special
15 part "children" to render the child widgets.  All properties of this part are
16 ignored.
17 */
18 class MSPGLTK_API Panel: public Container
19 {
20 public:
21         class Loader: public DataFile::DerivedObjectLoader<Panel, Widget::Loader>
22         {
23         public:
24                 typedef std::map<std::string, Widget *> WidgetMap;
25
26         protected:
27                 template<typename T>
28                 struct AddChildType
29                 {
30                         void operator()(const std::string &, Loader &) const;
31                 };
32
33                 WidgetMap &wdg_map;
34                 Widget *last_widget;
35
36         public:
37                 Loader(Panel &, WidgetMap &);
38
39         private:
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         std::unique_ptr<Layout> layout;
71
72         static TypeRegistry<Loader::AddChildType, Loader &> widget_registry;
73         static bool widget_registry_init_done;
74
75 public:
76         Panel();
77
78         template<typename T>
79         static void register_child_type(const std::string &);
80
81         const char *get_class() const override { return "panel"; }
82
83         Layout &get_or_create_layout();
84
85 protected:
86         void autosize_special(const Part &, Geometry &) const override;
87         void render_special(const Part &, GL::Renderer &) const override;
88
89 public:
90         bool navigate(Navigation) override;
91 protected:
92         Widget *find_next_child(int, int, int, int, int) const;
93         static int compute_delta(int, int, int, int, int);
94
95         void on_size_change() override;
96         void on_child_added(Widget &) override;
97         void on_child_removed(Widget &) override;
98 };
99
100
101 template<typename T>
102 void Panel::register_child_type(const std::string &name)
103 {
104         widget_registry.register_type<T>(name);
105 }
106
107
108 template<typename T>
109 void Panel::Loader::child(const std::string &n)
110 {
111         unnamed_child<T>();
112         wdg_map[n] = last_widget;
113 }
114
115 template<typename T>
116 void Panel::Loader::unnamed_child()
117 {
118         std::unique_ptr<T> chl = std::make_unique<T>();
119         load_sub(*chl);
120         Widget *wdg = chl.get();
121         obj.add(move(chl));
122         last_widget = wdg;
123 }
124
125
126 template<typename T>
127 void Panel::Loader::AddChildType<T>::operator()(const std::string &kwd, Loader &ldr) const
128 {
129         ldr.add(kwd, &Loader::child<T>);
130         ldr.add(kwd, &Loader::unnamed_child<T>);
131 }
132
133 } // namespace GLtk
134 } // namespace Msp
135
136 #endif