]> git.saurik.com Git - wxWidgets.git/blob - src/common/framecmn.cpp
Pass focus window to submenu items too (no reason I can think of not to).
[wxWidgets.git] / src / common / framecmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/framecmn.cpp
3 // Purpose: common (for all platforms) wxFrame functions
4 // Author: Julian Smart, Vadim Zeitlin
5 // Created: 01/02/97
6 // Id: $Id$
7 // Copyright: (c) 1998 Robert Roebling and Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #ifdef __GNUG__
20 #pragma implementation "framebase.h"
21 #endif
22
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29
30 #ifndef WX_PRECOMP
31 #include "wx/frame.h"
32 #include "wx/menu.h"
33 #include "wx/menuitem.h"
34 #include "wx/dcclient.h"
35 #endif // WX_PRECOMP
36
37 #if wxUSE_TOOLBAR
38 #include "wx/toolbar.h"
39 #endif
40 #if wxUSE_STATUSBAR
41 #include "wx/statusbr.h"
42 #endif
43
44 // ----------------------------------------------------------------------------
45 // event table
46 // ----------------------------------------------------------------------------
47
48 BEGIN_EVENT_TABLE(wxFrameBase, wxTopLevelWindow)
49 EVT_IDLE(wxFrameBase::OnIdle)
50 EVT_MENU_HIGHLIGHT_ALL(wxFrameBase::OnMenuHighlight)
51 END_EVENT_TABLE()
52
53 // ============================================================================
54 // implementation
55 // ============================================================================
56
57 // ----------------------------------------------------------------------------
58 // construction/destruction
59 // ----------------------------------------------------------------------------
60
61 wxFrameBase::wxFrameBase()
62 {
63 #if wxUSE_MENUS
64 m_frameMenuBar = NULL;
65 #endif // wxUSE_MENUS
66
67 #if wxUSE_TOOLBAR
68 m_frameToolBar = NULL;
69 #endif // wxUSE_TOOLBAR
70
71 #if wxUSE_STATUSBAR
72 m_frameStatusBar = NULL;
73 #endif // wxUSE_STATUSBAR
74
75 m_statusBarPane = 0;
76 }
77
78 wxFrameBase::~wxFrameBase()
79 {
80 // this destructor is required for Darwin
81 }
82
83 wxFrame *wxFrameBase::New(wxWindow *parent,
84 wxWindowID id,
85 const wxString& title,
86 const wxPoint& pos,
87 const wxSize& size,
88 long style,
89 const wxString& name)
90 {
91 return new wxFrame(parent, id, title, pos, size, style, name);
92 }
93
94 void wxFrameBase::DeleteAllBars()
95 {
96 #if wxUSE_MENUS
97 if ( m_frameMenuBar )
98 {
99 delete m_frameMenuBar;
100 m_frameMenuBar = (wxMenuBar *) NULL;
101 }
102 #endif // wxUSE_MENUS
103
104 #if wxUSE_STATUSBAR
105 if ( m_frameStatusBar )
106 {
107 delete m_frameStatusBar;
108 m_frameStatusBar = (wxStatusBar *) NULL;
109 }
110 #endif // wxUSE_STATUSBAR
111
112 #if wxUSE_TOOLBAR
113 if ( m_frameToolBar )
114 {
115 delete m_frameToolBar;
116 m_frameToolBar = (wxToolBar *) NULL;
117 }
118 #endif // wxUSE_TOOLBAR
119 }
120
121 bool wxFrameBase::IsOneOfBars(const wxWindow *win) const
122 {
123 #if wxUSE_MENUS
124 if ( win == GetMenuBar() )
125 return TRUE;
126 #endif // wxUSE_MENUS
127
128 #if wxUSE_STATUSBAR
129 if ( win == GetStatusBar() )
130 return TRUE;
131 #endif // wxUSE_STATUSBAR
132
133 #if wxUSE_TOOLBAR
134 if ( win == GetToolBar() )
135 return TRUE;
136 #endif // wxUSE_TOOLBAR
137
138 return FALSE;
139 }
140
141 // ----------------------------------------------------------------------------
142 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
143 // from the client area, so the client area is what's really available for the
144 // frame contents
145 // ----------------------------------------------------------------------------
146
147 // get the origin of the client area in the client coordinates
148 wxPoint wxFrameBase::GetClientAreaOrigin() const
149 {
150 wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
151
152 #if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__)
153 wxToolBar *toolbar = GetToolBar();
154 if ( toolbar && toolbar->IsShown() )
155 {
156 int w, h;
157 toolbar->GetSize(&w, &h);
158
159 if ( toolbar->GetWindowStyleFlag() & wxTB_VERTICAL )
160 {
161 pt.x += w;
162 }
163 else
164 {
165 pt.y += h;
166 }
167 }
168 #endif // wxUSE_TOOLBAR
169
170 return pt;
171 }
172
173 // ----------------------------------------------------------------------------
174 // misc
175 // ----------------------------------------------------------------------------
176
177 bool wxFrameBase::ProcessCommand(int id)
178 {
179 #if wxUSE_MENUS
180 wxMenuBar *bar = GetMenuBar();
181 if ( !bar )
182 return FALSE;
183
184 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
185 commandEvent.SetEventObject(this);
186
187 wxMenuItem *item = bar->FindItem(id);
188 if (item)
189 {
190 if (!item->IsEnabled())
191 return TRUE;
192
193 if (item->IsCheckable())
194 {
195 item->Toggle();
196
197 // use the new value
198 commandEvent.SetInt(item->IsChecked());
199 }
200 }
201
202 GetEventHandler()->ProcessEvent(commandEvent);
203 return TRUE;
204 #else // !wxUSE_MENUS
205 return FALSE;
206 #endif // wxUSE_MENUS/!wxUSE_MENUS
207 }
208
209 // ----------------------------------------------------------------------------
210 // event handlers
211 // ----------------------------------------------------------------------------
212
213 void wxFrameBase::OnMenuHighlight(wxMenuEvent& event)
214 {
215 #if wxUSE_STATUSBAR
216 (void)ShowMenuHelp(GetStatusBar(), event.GetMenuId());
217 #endif // wxUSE_STATUSBAR
218 }
219
220 void wxFrameBase::OnIdle(wxIdleEvent& WXUNUSED(event) )
221 {
222 #if wxUSE_MENUS
223 DoMenuUpdates();
224 #endif // wxUSE_MENUS
225 }
226
227 // ----------------------------------------------------------------------------
228 // status bar stuff
229 // ----------------------------------------------------------------------------
230
231 #if wxUSE_STATUSBAR
232
233 wxStatusBar* wxFrameBase::CreateStatusBar(int number,
234 long style,
235 wxWindowID id,
236 const wxString& name)
237 {
238 // the main status bar can only be created once (or else it should be
239 // deleted before calling CreateStatusBar() again)
240 wxCHECK_MSG( !m_frameStatusBar, (wxStatusBar *)NULL,
241 wxT("recreating status bar in wxFrame") );
242
243 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
244 if ( m_frameStatusBar )
245 PositionStatusBar();
246
247 return m_frameStatusBar;
248 }
249
250 wxStatusBar *wxFrameBase::OnCreateStatusBar(int number,
251 long style,
252 wxWindowID id,
253 const wxString& name)
254 {
255 wxStatusBar *statusBar = new wxStatusBar(this, id, style, name);
256
257 statusBar->SetFieldsCount(number);
258
259 return statusBar;
260 }
261
262 void wxFrameBase::SetStatusText(const wxString& text, int number)
263 {
264 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
265
266 m_frameStatusBar->SetStatusText(text, number);
267 }
268
269 void wxFrameBase::SetStatusWidths(int n, const int widths_field[] )
270 {
271 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set widths for") );
272
273 m_frameStatusBar->SetStatusWidths(n, widths_field);
274
275 PositionStatusBar();
276 }
277
278 void wxFrameBase::PushStatusText(const wxString& text, int number)
279 {
280 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
281
282 m_frameStatusBar->PushStatusText(text, number);
283 }
284
285 void wxFrameBase::PopStatusText(int number)
286 {
287 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
288
289 m_frameStatusBar->PopStatusText(number);
290 }
291
292 void wxFrameBase::DoGiveHelp(const wxString& text, bool show)
293 {
294 #if wxUSE_STATUSBAR
295 if ( m_statusBarPane < 0 ) return;
296 wxStatusBar* statbar = GetStatusBar();
297 if ( !statbar ) return;
298
299 wxString help = show ? text : wxString();
300 statbar->SetStatusText( help, m_statusBarPane );
301 #endif // wxUSE_STATUSBAR
302 }
303
304 bool wxFrameBase::ShowMenuHelp(wxStatusBar *WXUNUSED(statbar), int menuId)
305 {
306 #if wxUSE_MENUS
307 // if no help string found, we will clear the status bar text
308 wxString helpString;
309 bool show = menuId != wxID_SEPARATOR && menuId != -2 /* wxID_TITLE */;
310
311 if ( show )
312 {
313 wxMenuBar *menuBar = GetMenuBar();
314 if ( menuBar )
315 {
316 // it's ok if we don't find the item because it might belong
317 // to the popup menu
318 wxMenuItem *item = menuBar->FindItem(menuId);
319 if ( item )
320 helpString = item->GetHelp();
321 }
322 }
323
324 DoGiveHelp(helpString, show);
325
326 return !helpString.IsEmpty();
327 #else // !wxUSE_MENUS
328 return FALSE;
329 #endif // wxUSE_MENUS/!wxUSE_MENUS
330 }
331
332 #endif // wxUSE_STATUSBAR
333
334 // ----------------------------------------------------------------------------
335 // toolbar stuff
336 // ----------------------------------------------------------------------------
337
338 #if wxUSE_TOOLBAR
339
340 wxToolBar* wxFrameBase::CreateToolBar(long style,
341 wxWindowID id,
342 const wxString& name)
343 {
344 // the main toolbar can't be recreated (unless it was explicitly deeleted
345 // before)
346 wxCHECK_MSG( !m_frameToolBar, (wxToolBar *)NULL,
347 wxT("recreating toolbar in wxFrame") );
348
349 m_frameToolBar = OnCreateToolBar(style, id, name);
350
351 return m_frameToolBar;
352 }
353
354 wxToolBar* wxFrameBase::OnCreateToolBar(long style,
355 wxWindowID id,
356 const wxString& name)
357 {
358 return new wxToolBar(this, id,
359 wxDefaultPosition, wxDefaultSize,
360 style, name);
361 }
362
363 #endif // wxUSE_TOOLBAR
364
365 // ----------------------------------------------------------------------------
366 // menus
367 // ----------------------------------------------------------------------------
368
369 #if wxUSE_MENUS
370
371 // update all menus
372 void wxFrameBase::DoMenuUpdates()
373 {
374 wxMenuBar* bar = GetMenuBar();
375
376 #ifdef __WXMSW__
377 wxWindow* focusWin = wxFindFocusDescendant((wxWindow*) this);
378 #else
379 wxWindow* focusWin = (wxWindow*) NULL;
380 #endif
381 if ( bar != NULL )
382 {
383 int nCount = bar->GetMenuCount();
384 for (int n = 0; n < nCount; n++)
385 DoMenuUpdates(bar->GetMenu(n), focusWin);
386 }
387 }
388
389 // update a menu and all submenus recursively
390 void wxFrameBase::DoMenuUpdates(wxMenu* menu, wxWindow* focusWin)
391 {
392 wxEvtHandler* evtHandler = focusWin ? focusWin->GetEventHandler() : GetEventHandler();
393 wxMenuItemList::Node* node = menu->GetMenuItems().GetFirst();
394 while (node)
395 {
396 wxMenuItem* item = node->GetData();
397 if ( !item->IsSeparator() )
398 {
399 wxWindowID id = item->GetId();
400 wxUpdateUIEvent event(id);
401 event.SetEventObject( this );
402
403 if (evtHandler->ProcessEvent(event))
404 {
405 if (event.GetSetText())
406 menu->SetLabel(id, event.GetText());
407 if (event.GetSetChecked())
408 menu->Check(id, event.GetChecked());
409 if (event.GetSetEnabled())
410 menu->Enable(id, event.GetEnabled());
411 }
412
413 if (item->GetSubMenu())
414 DoMenuUpdates(item->GetSubMenu(), focusWin);
415 }
416 node = node->GetNext();
417 }
418 }
419
420 void wxFrameBase::DetachMenuBar()
421 {
422 if ( m_frameMenuBar )
423 {
424 m_frameMenuBar->Detach();
425 m_frameMenuBar = NULL;
426 }
427 }
428
429 void wxFrameBase::AttachMenuBar(wxMenuBar *menubar)
430 {
431 if ( menubar )
432 {
433 menubar->Attach((wxFrame *)this);
434 m_frameMenuBar = menubar;
435 }
436 }
437
438 void wxFrameBase::SetMenuBar(wxMenuBar *menubar)
439 {
440 if ( menubar == GetMenuBar() )
441 {
442 // nothing to do
443 return;
444 }
445
446 DetachMenuBar();
447
448 AttachMenuBar(menubar);
449 }
450
451 #endif // wxUSE_MENUS