]> git.saurik.com Git - wxWidgets.git/blame - include/wx/compositewin.h
Dramatically optimise inserting many items in wxGenericListCtrl.
[wxWidgets.git] / include / wx / compositewin.h
CommitLineData
a9e41db7
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: wx/compositewin.h
3// Purpose: wxCompositeWindow<> declaration
4// Author: Vadim Zeitlin
5// Created: 2011-01-02
84ba6659 6// RCS-ID: $Id$
a9e41db7
VZ
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"
31af22fa 15#include "wx/containr.h"
a9e41db7 16
84ba6659
VZ
17class WXDLLIMPEXP_FWD_CORE wxToolTip;
18
a9e41db7
VZ
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.
31template <class W>
32class wxCompositeWindow : public W
33{
34public:
35 typedef W BaseWindowClass;
36
37 // Default ctor doesn't do anything.
31af22fa
VS
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.
a9e41db7
VZ
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
84ba6659 73 SetForAllParts(&wxWindowBase::SetForegroundColour, colour);
a9e41db7
VZ
74
75 return true;
76 }
77
78 virtual bool SetBackgroundColour(const wxColour& colour)
79 {
80 if ( !BaseWindowClass::SetBackgroundColour(colour) )
81 return false;
82
84ba6659 83 SetForAllParts(&wxWindowBase::SetBackgroundColour, colour);
a9e41db7
VZ
84
85 return true;
86 }
87
88 virtual bool SetFont(const wxFont& font)
89 {
90 if ( !BaseWindowClass::SetFont(font) )
91 return false;
92
84ba6659 93 SetForAllParts(&wxWindowBase::SetFont, font);
a9e41db7
VZ
94
95 return true;
96 }
97
98 virtual bool SetCursor(const wxCursor& cursor)
99 {
100 if ( !BaseWindowClass::SetCursor(cursor) )
101 return false;
102
84ba6659 103 SetForAllParts(&wxWindowBase::SetCursor, cursor);
a9e41db7
VZ
104
105 return true;
106 }
107
84ba6659
VZ
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
31af22fa
VS
117#endif // !__VISUALC6__
118
119 virtual void SetFocus()
120 {
121 wxSetFocusToChild(this, NULL);
122 }
123
a9e41db7
VZ
124private:
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
31af22fa
VS
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__
a9e41db7 195 template <class T>
84ba6659
VZ
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)
a9e41db7
VZ
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
162e221f
VZ
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);
a9e41db7
VZ
223 }
224 }
31af22fa 225#endif // !__VISUALC6__
a9e41db7
VZ
226
227 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxCompositeWindow, W);
228};
229
230#endif // _WX_COMPOSITEWIN_H_