/
guiwidgetprivate.h
139 lines (118 loc) · 3.83 KB
/
guiwidgetprivate.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/** @file guiwidgetprivate.h Template for GUI widget private implementation.
*
* @authors Copyright (c) 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* LGPL: http://www.gnu.org/licenses/lgpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/
#ifndef LIBAPPFW_GUIWIDGETPRIVATE_H
#define LIBAPPFW_GUIWIDGETPRIVATE_H
#include <de/libdeng2.h>
#include "../GuiRootWidget"
namespace de {
class Style;
/**
* Base class for GuiWidget-derived widgets' private implementation. Provides
* easy access to the root widget and shared GL resources. This should be used
* as the base class for private implementations if GL resources are being
* used (i.e., glInit() and glDeinit() are being called).
*
* Use DENG_GUI_PIMPL() instead of the DENG2_PIMPL() macro.
*
* Note that GuiWidgetPrivate automatically observes the root widget's atlas
* content repositioning, so derived private implementations can just override
* the observer method if necessary.
*/
template <typename PublicType>
class GuiWidgetPrivate : public Private<PublicType>,
DENG2_OBSERVES(Atlas, Reposition)
{
public:
typedef GuiWidgetPrivate<PublicType> Base; // shadows Private<>::Base
public:
GuiWidgetPrivate(PublicType &i)
: Private<PublicType>(i),
_observingAtlas(0)
{}
GuiWidgetPrivate(PublicType *i)
: Private<PublicType>(i),
_observingAtlas(0)
{}
virtual ~GuiWidgetPrivate()
{
if(_observingAtlas)
{
_observingAtlas->audienceForReposition() -= this;
}
/**
* Ensure that the derived's class's glDeinit() method has been
* called before the private class instance is destroyed. At least
* classes that have GuiWidget as the immediate parent class need to
* call deinitialize() in their destructors.
*
* @see GuiWidget::destroy()
*/
DENG2_ASSERT(!Base::self.isInitialized());
}
void observeRootAtlas() const
{
if(!_observingAtlas)
{
// Automatically start observing the root atlas.
_observingAtlas = &root().atlas();
_observingAtlas->audienceForReposition() += this;
}
}
bool hasRoot() const
{
return Base::self.hasRoot();
}
GuiRootWidget &root() const
{
DENG2_ASSERT(hasRoot());
return Base::self.root();
}
AtlasTexture &atlas() const
{
observeRootAtlas();
return root().atlas();
}
GLUniform &uAtlas() const
{
observeRootAtlas();
return root().uAtlas();
}
GLShaderBank &shaders() const
{
return root().shaders();
}
Style const &style() const
{
return Base::self.style();
}
void atlasContentRepositioned(Atlas &atlas)
{
if(_observingAtlas == &atlas)
{
// Make sure the new texture coordinates get used by the widget.
Base::self.requestGeometry();
}
}
private:
mutable Atlas *_observingAtlas;
};
#define DENG_GUI_PIMPL(ClassName) \
typedef ClassName Public; \
struct ClassName::Instance : public de::GuiWidgetPrivate<ClassName>
} // namespace de
#endif // LIBAPPFW_GUIWIDGETPRIVATE_H