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