]> git.saurik.com Git - wxWidgets.git/blob - include/wx/containr.h
Patch from Hartwig for wxMac implementation
[wxWidgets.git] / include / wx / containr.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/containr.h
3 // Purpose: wxControlContainer class declration: a "mix-in" class which
4 // implements the TAB navigation between the controls
5 // Author: Vadim Zeitlin
6 // Modified by:
7 // Created: 06.08.01
8 // RCS-ID: $Id$
9 // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
10 // Licence: wxWindows licence
11 ///////////////////////////////////////////////////////////////////////////////
12
13 #ifndef _WX_CONTAINR_H_
14 #define _WX_CONTAINR_H_
15
16 #include "wx/defs.h"
17
18 class WXDLLIMPEXP_FWD_CORE wxWindow;
19 class WXDLLIMPEXP_FWD_CORE wxWindowBase;
20
21 /*
22 Implementation note: wxControlContainer is not a real mix-in but rather
23 a class meant to be aggregated with (and not inherited from). Although
24 logically it should be a mix-in, doing it like this has no advantage from
25 the point of view of the existing code but does have some problems (we'd
26 need to play tricks with event handlers which may be difficult to do
27 safely). The price we pay for this simplicity is the ugly macros below.
28 */
29
30 // ----------------------------------------------------------------------------
31 // wxControlContainerBase: common part used in both native and generic cases
32 // ----------------------------------------------------------------------------
33
34 class WXDLLEXPORT wxControlContainerBase
35 {
36 public:
37 // default ctor, SetContainerWindow() must be called later
38 wxControlContainerBase()
39 {
40 m_winParent = NULL;
41
42 // do accept focus initially, we'll stop doing it if/when any children
43 // are added
44 m_acceptsFocus = true;
45 m_inSetFocus = false;
46 m_winLastFocused = NULL;
47 }
48 virtual ~wxControlContainerBase() {}
49
50 void SetContainerWindow(wxWindow *winParent)
51 {
52 wxASSERT_MSG( !m_winParent, _T("shouldn't be called twice") );
53
54 m_winParent = winParent;
55 }
56
57 // should be called from SetFocus(), returns false if we did nothing with
58 // the focus and the default processing should take place
59 bool DoSetFocus();
60
61 // should be called when we decide that we should [stop] accepting focus
62 void SetCanFocus(bool acceptsFocus);
63
64 // returns whether we should accept focus ourselves or not
65 bool AcceptsFocus() const { return m_acceptsFocus; }
66
67 // returns whether we or one of our children accepts focus: we always do
68 // because if we don't have any focusable children it probably means that
69 // we're not being used as a container at all (think of wxGrid or generic
70 // wxListCtrl) and so should get focus for ourselves
71 bool AcceptsFocusRecursively() const { return true; }
72
73 // call this when the number of children of the window changes
74 //
75 // note that we have any children, this panel (used just as container for
76 // them) shouldn't get focus for itself
77 void UpdateCanFocus() { SetCanFocus(!HasAnyFocusableChildren()); }
78
79 protected:
80 // set the focus to the child which had it the last time
81 virtual bool SetFocusToChild();
82
83 // return true if we have any children accepting focus
84 bool HasAnyFocusableChildren() const;
85
86 // the parent window we manage the children for
87 wxWindow *m_winParent;
88
89 // the child which had the focus last time this panel was activated
90 wxWindow *m_winLastFocused;
91
92 private:
93 // value returned by AcceptsFocus(), should be changed using SetCanFocus()
94 // only
95 bool m_acceptsFocus;
96
97 // a guard against infinite recursion
98 bool m_inSetFocus;
99 };
100
101 // common part of WX_DECLARE_CONTROL_CONTAINER in the native and generic cases,
102 // it should be used in the wxWindow-derived class declaration
103 #define WX_DECLARE_CONTROL_CONTAINER_BASE() \
104 public: \
105 virtual bool AcceptsFocus() const; \
106 virtual bool AcceptsFocusRecursively() const; \
107 virtual void AddChild(wxWindowBase *child); \
108 virtual void RemoveChild(wxWindowBase *child); \
109 virtual void SetFocus(); \
110 void SetFocusIgnoringChildren(); \
111 void AcceptFocus(bool acceptFocus) \
112 { \
113 m_container.SetCanFocus(acceptFocus); \
114 } \
115 \
116 protected: \
117 wxControlContainer m_container
118
119 // this macro must be used in the derived class ctor
120 #define WX_INIT_CONTROL_CONTAINER() \
121 m_container.SetContainerWindow(this)
122
123 // common part of WX_DELEGATE_TO_CONTROL_CONTAINER in the native and generic
124 // cases, must be used in the wxWindow-derived class implementation
125 #define WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
126 void classname::AddChild(wxWindowBase *child) \
127 { \
128 basename::AddChild(child); \
129 \
130 m_container.UpdateCanFocus(); \
131 } \
132 \
133 bool classname::AcceptsFocusRecursively() const \
134 { \
135 return m_container.AcceptsFocusRecursively(); \
136 } \
137 \
138 void classname::SetFocus() \
139 { \
140 if ( !m_container.DoSetFocus() ) \
141 basename::SetFocus(); \
142 } \
143 \
144 bool classname::AcceptsFocus() const \
145 { \
146 return m_container.AcceptsFocus(); \
147 }
148
149
150 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
151
152 // ----------------------------------------------------------------------------
153 // wxControlContainer for native TAB navigation
154 // ----------------------------------------------------------------------------
155
156 // this must be a real class as we forward-declare it elsewhere
157 class WXDLLEXPORT wxControlContainer : public wxControlContainerBase
158 {
159 protected:
160 // set the focus to the child which had it the last time
161 virtual bool SetFocusToChild();
162 };
163
164 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
165
166 #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
167
168 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
169 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
170 \
171 void classname::RemoveChild(wxWindowBase *child) \
172 { \
173 basename::RemoveChild(child); \
174 \
175 m_container.UpdateCanFocus(); \
176 } \
177 \
178 void classname::SetFocusIgnoringChildren() \
179 { \
180 SetFocus(); \
181 }
182
183 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
184
185 class WXDLLIMPEXP_FWD_CORE wxFocusEvent;
186 class WXDLLIMPEXP_FWD_CORE wxNavigationKeyEvent;
187
188 // ----------------------------------------------------------------------------
189 // wxControlContainer for TAB navigation implemented in wx itself
190 // ----------------------------------------------------------------------------
191
192 class WXDLLEXPORT wxControlContainer : public wxControlContainerBase
193 {
194 public:
195 // default ctor, SetContainerWindow() must be called later
196 wxControlContainer();
197
198 // the methods to be called from the window event handlers
199 void HandleOnNavigationKey(wxNavigationKeyEvent& event);
200 void HandleOnFocus(wxFocusEvent& event);
201 void HandleOnWindowDestroy(wxWindowBase *child);
202
203 // called from OnChildFocus() handler, i.e. when one of our (grand)
204 // children gets the focus
205 void SetLastFocus(wxWindow *win);
206
207 protected:
208
209 DECLARE_NO_COPY_CLASS(wxControlContainer)
210 };
211
212 // ----------------------------------------------------------------------------
213 // macros which may be used by the classes wishing to implement TAB navigation
214 // among their children
215 // ----------------------------------------------------------------------------
216
217 // declare the methods to be forwarded
218 #define WX_DECLARE_CONTROL_CONTAINER() \
219 WX_DECLARE_CONTROL_CONTAINER_BASE(); \
220 \
221 public: \
222 void OnNavigationKey(wxNavigationKeyEvent& event); \
223 void OnFocus(wxFocusEvent& event); \
224 virtual void OnChildFocus(wxChildFocusEvent& event)
225
226 // implement the event table entries for wxControlContainer
227 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \
228 EVT_SET_FOCUS(classname::OnFocus) \
229 EVT_CHILD_FOCUS(classname::OnChildFocus) \
230 EVT_NAVIGATION_KEY(classname::OnNavigationKey)
231
232 // implement the methods forwarding to the wxControlContainer
233 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
234 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
235 \
236 void classname::RemoveChild(wxWindowBase *child) \
237 { \
238 m_container.HandleOnWindowDestroy(child); \
239 \
240 basename::RemoveChild(child); \
241 \
242 m_container.UpdateCanFocus(); \
243 } \
244 \
245 void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
246 { \
247 m_container.HandleOnNavigationKey(event); \
248 } \
249 \
250 void classname::SetFocusIgnoringChildren() \
251 { \
252 basename::SetFocus(); \
253 } \
254 \
255 void classname::OnChildFocus(wxChildFocusEvent& event) \
256 { \
257 m_container.SetLastFocus(event.GetWindow()); \
258 } \
259 \
260 void classname::OnFocus(wxFocusEvent& event) \
261 { \
262 m_container.HandleOnFocus(event); \
263 }
264
265 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
266
267 // this function is for wxWidgets internal use only
268 extern bool wxSetFocusToChild(wxWindow *win, wxWindow **child);
269
270 #endif // _WX_CONTAINR_H_