]> git.saurik.com Git - wxWidgets.git/blob - include/wx/compositewin.h
Another attempt to fix wxTextMeasure compilation with VC6.
[wxWidgets.git] / include / wx / compositewin.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/compositewin.h
3 // Purpose: wxCompositeWindow<> declaration
4 // Author: Vadim Zeitlin
5 // Created: 2011-01-02
6 // RCS-ID: $Id$
7 // Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 #ifndef _WX_COMPOSITEWIN_H_
12 #define _WX_COMPOSITEWIN_H_
13
14 #include "wx/window.h"
15 #include "wx/containr.h"
16
17 class WXDLLIMPEXP_FWD_CORE wxToolTip;
18
19 // NB: This is an experimental and, as for now, undocumented class used only by
20 // wxWidgets itself internally. Don't use it in your code until its API is
21 // officially stabilized unless you are ready to change it with the next
22 // wxWidgets release.
23
24 // ----------------------------------------------------------------------------
25 // wxCompositeWindow is a helper for implementing composite windows: to define
26 // a class using subwindows, simply inherit from it specialized with the real
27 // base class name and implement GetCompositeWindowParts() pure virtual method.
28 // ----------------------------------------------------------------------------
29
30 // The template parameter W must be a wxWindow-derived class.
31 template <class W>
32 class wxCompositeWindow : public W
33 {
34 public:
35 typedef W BaseWindowClass;
36
37 // Default ctor doesn't do anything.
38 wxCompositeWindow()
39 {
40 this->Connect
41 (
42 wxEVT_CREATE,
43 wxWindowCreateEventHandler(wxCompositeWindow::OnWindowCreate)
44 );
45
46 }
47
48 #ifndef __VISUALC6__
49 // FIXME-VC6: This compiler can't compile DoSetForAllParts() template function,
50 // it can't determine whether the deduced type should be "T" or "const T&". And
51 // without this function wxCompositeWindow is pretty useless so simply disable
52 // this code for it, this does mean that setting colours/fonts/... for
53 // composite controls won't work in the library compiled with it but so far
54 // this only affects the generic wxDatePickerCtrl which is not used by default
55 // under MSW anyhow so it doesn't seem to be worth it to spend time and uglify
56 // the code to fix it.
57
58 // Override all wxWindow methods which must be forwarded to the composite
59 // window parts.
60
61 // Attribute setters group.
62 //
63 // NB: Unfortunately we can't factor out the call for the setter itself
64 // into DoSetForAllParts() because we can't call the function passed to
65 // it non-virtually and we need to do this to avoid infinite recursion,
66 // so we work around this by calling the method of this object itself
67 // manually in each function.
68 virtual bool SetForegroundColour(const wxColour& colour)
69 {
70 if ( !BaseWindowClass::SetForegroundColour(colour) )
71 return false;
72
73 SetForAllParts(&wxWindowBase::SetForegroundColour, colour);
74
75 return true;
76 }
77
78 virtual bool SetBackgroundColour(const wxColour& colour)
79 {
80 if ( !BaseWindowClass::SetBackgroundColour(colour) )
81 return false;
82
83 SetForAllParts(&wxWindowBase::SetBackgroundColour, colour);
84
85 return true;
86 }
87
88 virtual bool SetFont(const wxFont& font)
89 {
90 if ( !BaseWindowClass::SetFont(font) )
91 return false;
92
93 SetForAllParts(&wxWindowBase::SetFont, font);
94
95 return true;
96 }
97
98 virtual bool SetCursor(const wxCursor& cursor)
99 {
100 if ( !BaseWindowClass::SetCursor(cursor) )
101 return false;
102
103 SetForAllParts(&wxWindowBase::SetCursor, cursor);
104
105 return true;
106 }
107
108 #if wxUSE_TOOLTIPS
109 virtual void DoSetToolTip(wxToolTip *tip)
110 {
111 BaseWindowClass::DoSetToolTip(tip);
112
113 SetForAllParts(&wxWindowBase::CopyToolTip, tip);
114 }
115 #endif // wxUSE_TOOLTIPS
116
117 #endif // !__VISUALC6__
118
119 virtual void SetFocus()
120 {
121 wxSetFocusToChild(this, NULL);
122 }
123
124 private:
125 // Must be implemented by the derived class to return all children to which
126 // the public methods we override should forward to.
127 virtual wxWindowList GetCompositeWindowParts() const = 0;
128
129 void OnWindowCreate(wxWindowCreateEvent& event)
130 {
131 event.Skip();
132
133 // Attach a few event handlers to all parts of the composite window.
134 // This makes the composite window behave more like a simple control
135 // and allows other code (such as wxDataViewCtrl's inline editing
136 // support) to hook into its event processing.
137
138 wxWindow *child = event.GetWindow();
139 if ( child == this )
140 return; // not a child, we don't want to Connect() to ourselves
141
142 // Always capture wxEVT_KILL_FOCUS:
143 child->Connect(wxEVT_KILL_FOCUS,
144 wxFocusEventHandler(wxCompositeWindow::OnKillFocus),
145 NULL, this);
146
147 // Some events should be only handled for non-toplevel children. For
148 // example, we want to close the control in wxDataViewCtrl when Enter
149 // is pressed in the inline editor, but not when it's pressed in a
150 // popup dialog it opens.
151 wxWindow *win = child;
152 while ( win && win != this )
153 {
154 if ( win->IsTopLevel() )
155 return;
156 win = win->GetParent();
157 }
158
159 child->Connect(wxEVT_CHAR,
160 wxKeyEventHandler(wxCompositeWindow::OnChar),
161 NULL, this);
162 }
163
164 void OnChar(wxKeyEvent& event)
165 {
166 if ( !this->ProcessWindowEvent(event) )
167 event.Skip();
168 }
169
170 void OnKillFocus(wxFocusEvent& event)
171 {
172 // Ignore focus changes within the composite control:
173 wxWindow *win = event.GetWindow();
174 while ( win )
175 {
176 if ( win == this )
177 {
178 event.Skip();
179 return;
180 }
181
182 // Note that we don't use IsTopLevel() check here, because we do
183 // want to ignore focus changes going to toplevel window that have
184 // the composite control as its parent; these would typically be
185 // some kind of control's popup window.
186 win = win->GetParent();
187 }
188
189 // The event shouldn't be ignored, forward it to the main control:
190 if ( !this->ProcessWindowEvent(event) )
191 event.Skip();
192 }
193
194 #ifndef __VISUALC6__
195 template <class T>
196 void SetForAllParts(bool (wxWindowBase::*func)(const T&), const T& arg)
197 {
198 DoSetForAllParts<const T&>(func, arg);
199 }
200
201 template <class T>
202 void SetForAllParts(bool (wxWindowBase::*func)(T*), T* arg)
203 {
204 DoSetForAllParts<T*>(func, arg);
205 }
206
207 template <class T>
208 void DoSetForAllParts(bool (wxWindowBase::*func)(T), T arg)
209 {
210 // Simply call the setters for all parts of this composite window.
211 const wxWindowList parts = GetCompositeWindowParts();
212 for ( wxWindowList::const_iterator i = parts.begin();
213 i != parts.end();
214 ++i )
215 {
216 wxWindow * const child = *i;
217
218 // Allow NULL elements in the list, this makes the code of derived
219 // composite controls which may have optionally shown children
220 // simpler and it doesn't cost us much here.
221 if ( child )
222 (child->*func)(arg);
223 }
224 }
225 #endif // !__VISUALC6__
226
227 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxCompositeWindow, W);
228 };
229
230 #endif // _WX_COMPOSITEWIN_H_