]>
Commit | Line | Data |
---|---|---|
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 | #ifndef __WXGTK__ | |
59 | SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE)); | |
60 | SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT)); | |
61 | #endif | |
62 | } | |
63 | ||
64 | return ret; | |
65 | } | |
66 | ||
67 | void wxPanel::InitDialog(void) | |
68 | { | |
69 | wxInitDialogEvent event(GetId()); | |
70 | event.SetEventObject(this); | |
71 | GetEventHandler()->ProcessEvent(event); | |
72 | } | |
73 | ||
74 | // Responds to colour changes, and passes event on to children. | |
75 | void wxPanel::OnSysColourChanged(wxSysColourChangedEvent& event) | |
76 | { | |
77 | SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE)); | |
78 | Refresh(); | |
79 | ||
80 | // Propagate the event to the non-top-level children | |
81 | wxWindow::OnSysColourChanged(event); | |
82 | } | |
83 | ||
84 | void wxPanel::OnNavigationKey( wxNavigationKeyEvent& event ) | |
85 | { | |
86 | // there is not much to do if we have only one child (or not at all) | |
87 | if (GetChildren().GetCount() < 2) | |
88 | { | |
89 | event.Skip(); | |
90 | return; | |
91 | } | |
92 | ||
93 | // don't process these ones here | |
94 | if (event.IsWindowChange()) | |
95 | { | |
96 | event.Skip(); | |
97 | return; | |
98 | } | |
99 | ||
100 | // Did the event emitter tell us where the last focus was? | |
101 | // wxGTK does this in wxWindow, but wxMSW does not. It is | |
102 | // also done in wxPanel if the event is propagated up. | |
103 | wxWindow *winFocus = event.GetCurrentFocus(); | |
104 | ||
105 | // Do we know where the focus was ourselves, then? | |
106 | if (!winFocus) | |
107 | winFocus = m_winLastFocused; | |
108 | ||
109 | if (!winFocus) | |
110 | winFocus = wxWindow::FindFocus(); | |
111 | ||
112 | if (!winFocus) | |
113 | { | |
114 | event.Skip(); | |
115 | return; | |
116 | } | |
117 | ||
118 | wxWindowList::Node *start_node = GetChildren().Find( winFocus ); | |
119 | if ( !start_node ) | |
120 | start_node = GetChildren().Find( m_winLastFocused ); | |
121 | if ( !start_node ) | |
122 | start_node = GetChildren().GetFirst(); | |
123 | ||
124 | wxWindowList::Node *node = event.GetDirection() ? start_node->GetNext() | |
125 | : start_node->GetPrevious(); | |
126 | ||
127 | while ( node != start_node ) | |
128 | { | |
129 | // Have we come to the last or first item on the panel? | |
130 | if ( !node ) | |
131 | { | |
132 | // Check if our (may be grand) parent is another panel: if this is | |
133 | // the case, they will know what to do with this navigation key and | |
134 | // so give them the chance to process it instead of looping inside | |
135 | // this panel (normally, the focus will go to the next/previous | |
136 | // item after this panel in the parent panel). | |
137 | wxWindow *focussed_child_of_parent = this; | |
138 | for ( wxWindow *parent = GetParent(); parent; parent = parent->GetParent() ) | |
139 | { | |
140 | // we don't want to tab into a different dialog or frame | |
141 | if ( focussed_child_of_parent->IsTopLevel() ) | |
142 | break; | |
143 | ||
144 | // is the parent a panel? | |
145 | wxPanel *panel = wxDynamicCast(parent, wxPanel); | |
146 | if (panel) | |
147 | { | |
148 | event.SetCurrentFocus( focussed_child_of_parent ); | |
149 | if (parent->GetEventHandler()->ProcessEvent( event )) | |
150 | return; | |
151 | } | |
152 | ||
153 | focussed_child_of_parent = parent; | |
154 | } | |
155 | ||
156 | // no, we are not inside another panel so process this ourself | |
157 | node = event.GetDirection() ? GetChildren().GetFirst() | |
158 | : GetChildren().GetLast(); | |
159 | ||
160 | continue; | |
161 | } | |
162 | ||
163 | wxWindow *child = node->GetData(); | |
164 | ||
165 | if ( child->AcceptsFocus() ) | |
166 | { | |
167 | m_winLastFocused = child; // should be redundant, but it is not | |
168 | child->SetFocus(); | |
169 | return; | |
170 | } | |
171 | ||
172 | node = event.GetDirection() ? node->GetNext() : node->GetPrevious(); | |
173 | } | |
174 | ||
175 | // we cycled through all of our children and none of them wanted to accept | |
176 | // focus | |
177 | event.Skip(); | |
178 | } | |
179 | ||
180 | ||
181 | void wxPanel::OnSize(wxSizeEvent& WXUNUSED(event)) | |
182 | { | |
183 | #if wxUSE_CONSTRAINTS | |
184 | if (GetAutoLayout()) Layout(); | |
185 | #endif | |
186 | } | |
187 | ||
188 | void wxPanel::SetFocus() | |
189 | { | |
190 | // If the panel gets the focus *by way of getting it set directly* | |
191 | // we move the focus to the first window that can get it. | |
192 | ||
193 | wxNode *node = GetChildren().First(); | |
194 | while (node) | |
195 | { | |
196 | wxWindow *child = (wxWindow*) node->Data(); | |
197 | if (child->AcceptsFocus()) | |
198 | { | |
199 | m_winLastFocused = child; // should be redundant, but it is not | |
200 | child->SetFocus(); | |
201 | return; | |
202 | } | |
203 | node = node->Next(); | |
204 | } | |
205 | ||
206 | m_winLastFocused = (wxWindow*) NULL; | |
207 | ||
208 | wxWindow::SetFocus(); | |
209 | } | |
210 | ||
211 | void wxPanel::OnFocus(wxFocusEvent& event) | |
212 | { | |
213 | // If the panel gets the focus *by way of getting clicked on* | |
214 | // we move the focus to either the last window that had the | |
215 | // focus or the first one that can get it. | |
216 | ||
217 | if (m_winLastFocused) | |
218 | { | |
219 | // It might happen that the window got reparented or no longer | |
220 | // accepts the focus. | |
221 | if ((m_winLastFocused->GetParent() == this) && | |
222 | (m_winLastFocused->AcceptsFocus())) | |
223 | { | |
224 | m_winLastFocused->SetFocus(); | |
225 | return; | |
226 | } | |
227 | } | |
228 | ||
229 | wxNode *node = GetChildren().First(); | |
230 | while (node) | |
231 | { | |
232 | wxWindow *child = (wxWindow*) node->Data(); | |
233 | if (child->AcceptsFocus()) | |
234 | { | |
235 | m_winLastFocused = child; // should be redundant, but it is not | |
236 | child->SetFocus(); | |
237 | return; | |
238 | } | |
239 | node = node->Next(); | |
240 | } | |
241 | ||
242 | m_winLastFocused = (wxWindow*) NULL; | |
243 | ||
244 | event.Skip(); | |
245 | } |