]> git.saurik.com Git - wxWidgets.git/blob - src/generic/panelg.cpp
Added a comment about the 'UpdateWindow' issue in SetScrollBars()
[wxWidgets.git] / src / generic / panelg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: panelg.cpp
3 // Purpose: wxPanel
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "panelg.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/object.h"
25 #include "wx/font.h"
26 #include "wx/colour.h"
27 #include "wx/settings.h"
28 #endif
29
30 #include "wx/generic/panelg.h"
31
32 IMPLEMENT_DYNAMIC_CLASS(wxPanel, wxWindow)
33
34 BEGIN_EVENT_TABLE(wxPanel, wxWindow)
35 EVT_SYS_COLOUR_CHANGED(wxPanel::OnSysColourChanged)
36 EVT_SET_FOCUS(wxPanel::OnFocus)
37 EVT_NAVIGATION_KEY(wxPanel::OnNavigationKey)
38 EVT_SIZE(wxPanel::OnSize)
39 END_EVENT_TABLE()
40
41
42 void wxPanel::Init()
43 {
44 m_winLastFocused = (wxWindow *)NULL;
45 m_btnDefault = (wxButton *)NULL;
46 }
47
48 bool wxPanel::Create(wxWindow *parent, wxWindowID id,
49 const wxPoint& pos,
50 const wxSize& size,
51 long style,
52 const wxString& name)
53 {
54 bool ret = wxWindow::Create(parent, id, pos, size, style, name);
55
56 if ( ret )
57 {
58 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
59 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
60 }
61
62 return ret;
63 }
64
65 void wxPanel::InitDialog(void)
66 {
67 wxInitDialogEvent event(GetId());
68 event.SetEventObject(this);
69 GetEventHandler()->ProcessEvent(event);
70 }
71
72 // Responds to colour changes, and passes event on to children.
73 void wxPanel::OnSysColourChanged(wxSysColourChangedEvent& event)
74 {
75 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
76 Refresh();
77
78 // Propagate the event to the non-top-level children
79 wxWindow::OnSysColourChanged(event);
80 }
81
82 void wxPanel::OnNavigationKey( wxNavigationKeyEvent& event )
83 {
84 // there is not much to do if we have only one child (or not at all)
85 if (GetChildren().GetCount() < 2)
86 {
87 event.Skip();
88 return;
89 }
90
91 // don't process these ones here
92 if (event.IsWindowChange())
93 {
94 event.Skip();
95 return;
96 }
97
98 // Did the event emitter tell us where the last focus was?
99 // wxGTK does this in wxWindow, but wxMSW does not. It is
100 // also done in wxPanel if the event is propagated up.
101 wxWindow *winFocus = event.GetCurrentFocus();
102
103 // Do we know where the focus was ourselves, then?
104 if (!winFocus)
105 winFocus = m_winLastFocused;
106
107 if (!winFocus)
108 winFocus = wxWindow::FindFocus();
109
110 if (!winFocus)
111 {
112 event.Skip();
113 return;
114 }
115
116 wxWindowList::Node *start_node = GetChildren().Find( winFocus );
117 if ( !start_node )
118 start_node = GetChildren().Find( m_winLastFocused );
119 if ( !start_node )
120 start_node = GetChildren().GetFirst();
121
122 wxWindowList::Node *node = event.GetDirection() ? start_node->GetNext()
123 : start_node->GetPrevious();
124
125 while ( node != start_node )
126 {
127 // Have we come to the last or first item on the panel?
128 if ( !node )
129 {
130 // Check if our (may be grand) parent is another panel: if this is
131 // the case, they will know what to do with this navigation key and
132 // so give them the chance to process it instead of looping inside
133 // this panel (normally, the focus will go to the next/previous
134 // item after this panel in the parent panel).
135 wxWindow *focussed_child_of_parent = this;
136 for ( wxWindow *parent = GetParent(); parent; parent = parent->GetParent() )
137 {
138 // we don't want to tab into a different dialog or frame
139 if ( focussed_child_of_parent->IsTopLevel() )
140 break;
141
142 // is the parent a panel?
143 wxPanel *panel = wxDynamicCast(parent, wxPanel);
144 if (panel)
145 {
146 event.SetCurrentFocus( focussed_child_of_parent );
147 if (parent->GetEventHandler()->ProcessEvent( event ))
148 return;
149 }
150
151 focussed_child_of_parent = parent;
152 }
153
154 // no, we are not inside another panel so process this ourself
155 node = event.GetDirection() ? GetChildren().GetFirst()
156 : GetChildren().GetLast();
157
158 continue;
159 }
160
161 wxWindow *child = node->GetData();
162
163 if ( child->AcceptsFocus() )
164 {
165 m_winLastFocused = child; // should be redundant, but it is not
166 child->SetFocus();
167 return;
168 }
169
170 node = event.GetDirection() ? node->GetNext() : node->GetPrevious();
171 }
172
173 // we cycled through all of our children and none of them wanted to accept
174 // focus
175 event.Skip();
176 }
177
178
179 void wxPanel::OnSize(wxSizeEvent& WXUNUSED(event))
180 {
181 #if wxUSE_CONSTRAINTS
182 if (GetAutoLayout())
183 Layout();
184 #endif
185 }
186
187 void wxPanel::SetFocus()
188 {
189 // If the panel gets the focus *by way of getting it set directly*
190 // we move the focus to the first window that can get it.
191
192 wxNode *node = GetChildren().First();
193 while (node)
194 {
195 wxWindow *child = (wxWindow*) node->Data();
196 if (child->AcceptsFocus())
197 {
198 m_winLastFocused = child; // should be redundant, but it is not
199 child->SetFocus();
200 return;
201 }
202 node = node->Next();
203 }
204
205 m_winLastFocused = (wxWindow*) NULL;
206
207 wxWindow::SetFocus();
208 }
209
210 void wxPanel::OnFocus(wxFocusEvent& event)
211 {
212 // If the panel gets the focus *by way of getting clicked on*
213 // we move the focus to either the last window that had the
214 // focus or the first one that can get it.
215
216 if (m_winLastFocused)
217 {
218 // It might happen that the window got reparented or no longer
219 // accepts the focus.
220 if ((m_winLastFocused->GetParent() == this) &&
221 (m_winLastFocused->AcceptsFocus()))
222 {
223 m_winLastFocused->SetFocus();
224 return;
225 }
226 }
227
228 wxNode *node = GetChildren().First();
229 while (node)
230 {
231 wxWindow *child = (wxWindow*) node->Data();
232 if (child->AcceptsFocus())
233 {
234 m_winLastFocused = child; // should be redundant, but it is not
235 child->SetFocus();
236 return;
237 }
238 node = node->Next();
239 }
240
241 m_winLastFocused = (wxWindow*) NULL;
242
243 event.Skip();
244 }