OSX regrouping
[wxWidgets.git] / src / common / framecmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/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 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #include "wx/frame.h"
27
28 #ifndef WX_PRECOMP
29 #include "wx/menu.h"
30 #include "wx/menuitem.h"
31 #include "wx/dcclient.h"
32 #include "wx/toolbar.h"
33 #include "wx/statusbr.h"
34 #endif // WX_PRECOMP
35
36 // ----------------------------------------------------------------------------
37 // event table
38 // ----------------------------------------------------------------------------
39
40 #if wxUSE_MENUS && wxUSE_STATUSBAR
41
42 BEGIN_EVENT_TABLE(wxFrameBase, wxTopLevelWindow)
43 EVT_MENU_OPEN(wxFrameBase::OnMenuOpen)
44 EVT_MENU_CLOSE(wxFrameBase::OnMenuClose)
45
46 EVT_MENU_HIGHLIGHT_ALL(wxFrameBase::OnMenuHighlight)
47 END_EVENT_TABLE()
48
49 #endif // wxUSE_MENUS && wxUSE_STATUSBAR
50
51 // ============================================================================
52 // implementation
53 // ============================================================================
54
55 // ----------------------------------------------------------------------------
56 // construction/destruction
57 // ----------------------------------------------------------------------------
58
59 wxFrameBase::wxFrameBase()
60 {
61 #if wxUSE_MENUS
62 m_frameMenuBar = NULL;
63 #endif // wxUSE_MENUS
64
65 #if wxUSE_TOOLBAR
66 m_frameToolBar = NULL;
67 #endif // wxUSE_TOOLBAR
68
69 #if wxUSE_STATUSBAR
70 m_frameStatusBar = NULL;
71 #endif // wxUSE_STATUSBAR
72
73 m_statusBarPane = 0;
74 }
75
76 wxFrameBase::~wxFrameBase()
77 {
78 // this destructor is required for Darwin
79 }
80
81 wxFrame *wxFrameBase::New(wxWindow *parent,
82 wxWindowID id,
83 const wxString& title,
84 const wxPoint& pos,
85 const wxSize& size,
86 long style,
87 const wxString& name)
88 {
89 return new wxFrame(parent, id, title, pos, size, style, name);
90 }
91
92 void wxFrameBase::DeleteAllBars()
93 {
94 #if wxUSE_MENUS
95 if ( m_frameMenuBar )
96 {
97 delete m_frameMenuBar;
98 m_frameMenuBar = (wxMenuBar *) NULL;
99 }
100 #endif // wxUSE_MENUS
101
102 #if wxUSE_STATUSBAR
103 if ( m_frameStatusBar )
104 {
105 delete m_frameStatusBar;
106 m_frameStatusBar = (wxStatusBar *) NULL;
107 }
108 #endif // wxUSE_STATUSBAR
109
110 #if wxUSE_TOOLBAR
111 if ( m_frameToolBar )
112 {
113 delete m_frameToolBar;
114 m_frameToolBar = (wxToolBar *) NULL;
115 }
116 #endif // wxUSE_TOOLBAR
117 }
118
119 bool wxFrameBase::IsOneOfBars(const wxWindow *win) const
120 {
121 #if wxUSE_MENUS
122 if ( win == GetMenuBar() )
123 return true;
124 #endif // wxUSE_MENUS
125
126 #if wxUSE_STATUSBAR
127 if ( win == GetStatusBar() )
128 return true;
129 #endif // wxUSE_STATUSBAR
130
131 #if wxUSE_TOOLBAR
132 if ( win == GetToolBar() )
133 return true;
134 #endif // wxUSE_TOOLBAR
135
136 wxUnusedVar(win);
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 #if wxUSE_MENUS
178
179 bool wxFrameBase::ProcessCommand(int id)
180 {
181 wxMenuBar *bar = GetMenuBar();
182 if ( !bar )
183 return false;
184
185 wxMenuItem *item = bar->FindItem(id);
186 if ( !item )
187 return false;
188
189 return ProcessCommand(item);
190 }
191
192 bool wxFrameBase::ProcessCommand(wxMenuItem *item)
193 {
194 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, item->GetId());
195 commandEvent.SetEventObject(this);
196
197 if (!item->IsEnabled())
198 return true;
199
200 if ((item->GetKind() == wxITEM_RADIO) && item->IsChecked() )
201 return true;
202
203 if (item->IsCheckable())
204 {
205 item->Toggle();
206
207 // use the new value
208 commandEvent.SetInt(item->IsChecked());
209 }
210
211 return HandleWindowEvent(commandEvent);
212 }
213
214 #endif // wxUSE_MENUS
215
216 // Do the UI update processing for this window. This is
217 // provided for the application to call if it wants to
218 // force a UI update, particularly for the menus and toolbar.
219 void wxFrameBase::UpdateWindowUI(long flags)
220 {
221 wxWindowBase::UpdateWindowUI(flags);
222
223 #if wxUSE_TOOLBAR
224 if (GetToolBar())
225 GetToolBar()->UpdateWindowUI(flags);
226 #endif
227
228 #if wxUSE_MENUS
229 if (GetMenuBar())
230 {
231 if ((flags & wxUPDATE_UI_FROMIDLE) && !wxUSE_IDLEMENUUPDATES)
232 {
233 // If coming from an idle event, we only
234 // want to update the menus if we're
235 // in the wxUSE_IDLEMENUUPDATES configuration:
236 // so if we're not, do nothing
237 }
238 else
239 DoMenuUpdates();
240 }
241 #endif // wxUSE_MENUS
242 }
243
244 // ----------------------------------------------------------------------------
245 // event handlers for status bar updates from menus
246 // ----------------------------------------------------------------------------
247
248 #if wxUSE_MENUS && wxUSE_STATUSBAR
249
250 void wxFrameBase::OnMenuHighlight(wxMenuEvent& event)
251 {
252 #if wxUSE_STATUSBAR
253 (void)ShowMenuHelp(event.GetMenuId());
254 #endif // wxUSE_STATUSBAR
255 }
256
257 #if !wxUSE_IDLEMENUUPDATES
258 void wxFrameBase::OnMenuOpen(wxMenuEvent& event)
259 #else
260 void wxFrameBase::OnMenuOpen(wxMenuEvent& WXUNUSED(event))
261 #endif
262 {
263 #if !wxUSE_IDLEMENUUPDATES
264 DoMenuUpdates(event.GetMenu());
265 #endif // !wxUSE_IDLEMENUUPDATES
266 }
267
268 void wxFrameBase::OnMenuClose(wxMenuEvent& WXUNUSED(event))
269 {
270 DoGiveHelp(wxEmptyString, false);
271 }
272
273 #endif // wxUSE_MENUS && wxUSE_STATUSBAR
274
275 // Implement internal behaviour (menu updating on some platforms)
276 void wxFrameBase::OnInternalIdle()
277 {
278 wxTopLevelWindow::OnInternalIdle();
279
280 #if wxUSE_MENUS && wxUSE_IDLEMENUUPDATES
281 if (wxUpdateUIEvent::CanUpdate(this))
282 DoMenuUpdates();
283 #endif
284 }
285
286 // ----------------------------------------------------------------------------
287 // status bar stuff
288 // ----------------------------------------------------------------------------
289
290 #if wxUSE_STATUSBAR
291
292 wxStatusBar* wxFrameBase::CreateStatusBar(int number,
293 long style,
294 wxWindowID id,
295 const wxString& name)
296 {
297 // the main status bar can only be created once (or else it should be
298 // deleted before calling CreateStatusBar() again)
299 wxCHECK_MSG( !m_frameStatusBar, (wxStatusBar *)NULL,
300 wxT("recreating status bar in wxFrame") );
301
302 SetStatusBar(OnCreateStatusBar(number, style, id, name));
303
304 return m_frameStatusBar;
305 }
306
307 wxStatusBar *wxFrameBase::OnCreateStatusBar(int number,
308 long style,
309 wxWindowID id,
310 const wxString& name)
311 {
312 wxStatusBar *statusBar = new wxStatusBar(this, id, style, name);
313
314 statusBar->SetFieldsCount(number);
315
316 return statusBar;
317 }
318
319 void wxFrameBase::SetStatusText(const wxString& text, int number)
320 {
321 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
322
323 m_frameStatusBar->SetStatusText(text, number);
324 }
325
326 void wxFrameBase::SetStatusWidths(int n, const int widths_field[] )
327 {
328 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set widths for") );
329
330 m_frameStatusBar->SetStatusWidths(n, widths_field);
331
332 PositionStatusBar();
333 }
334
335 void wxFrameBase::PushStatusText(const wxString& text, int number)
336 {
337 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
338
339 m_frameStatusBar->PushStatusText(text, number);
340 }
341
342 void wxFrameBase::PopStatusText(int number)
343 {
344 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
345
346 m_frameStatusBar->PopStatusText(number);
347 }
348
349 bool wxFrameBase::ShowMenuHelp(int menuId)
350 {
351 #if wxUSE_MENUS
352 // if no help string found, we will clear the status bar text
353 wxString helpString;
354 if ( menuId != wxID_SEPARATOR && menuId != -3 /* wxID_TITLE */ )
355 {
356 const wxMenuItem * const item = FindItemInMenuBar(menuId);
357 if ( item && !item->IsSeparator() )
358 helpString = item->GetHelp();
359
360 // notice that it's ok if we don't find the item because it might
361 // belong to the popup menu, so don't assert here
362 }
363
364 DoGiveHelp(helpString, true);
365
366 return !helpString.empty();
367 #else // !wxUSE_MENUS
368 return false;
369 #endif // wxUSE_MENUS/!wxUSE_MENUS
370 }
371
372 void wxFrameBase::SetStatusBar(wxStatusBar *statBar)
373 {
374 bool hadBar = m_frameStatusBar != NULL;
375 m_frameStatusBar = statBar;
376
377 if ( (m_frameStatusBar != NULL) != hadBar )
378 {
379 PositionStatusBar();
380
381 DoLayout();
382 }
383 }
384
385 #endif // wxUSE_STATUSBAR
386
387 #if wxUSE_MENUS || wxUSE_TOOLBAR
388 void wxFrameBase::DoGiveHelp(const wxString& help, bool show)
389 {
390 #if wxUSE_STATUSBAR
391 if ( m_statusBarPane < 0 )
392 {
393 // status bar messages disabled
394 return;
395 }
396
397 wxStatusBar *statbar = GetStatusBar();
398 if ( !statbar )
399 return;
400
401 wxString text;
402 if ( show )
403 {
404 // remember the old status bar text if this is the first time we're
405 // called since the menu has been opened as we're going to overwrite it
406 // in our DoGiveHelp() and we want to restore it when the menu is
407 // closed
408 //
409 // note that it would be logical to do this in OnMenuOpen() but under
410 // MSW we get an EVT_MENU_HIGHLIGHT before EVT_MENU_OPEN, strangely
411 // enough, and so this doesn't work and instead we use the ugly trick
412 // with using special m_oldStatusText value as "menu opened" (but it is
413 // arguably better than adding yet another member variable to wxFrame
414 // on all platforms)
415 if ( m_oldStatusText.empty() )
416 {
417 m_oldStatusText = statbar->GetStatusText(m_statusBarPane);
418 if ( m_oldStatusText.empty() )
419 {
420 // use special value to prevent us from doing this the next time
421 m_oldStatusText += _T('\0');
422 }
423 }
424
425 text = help;
426 }
427 else // hide help, restore the original text
428 {
429 text = m_oldStatusText;
430 m_oldStatusText.clear();
431 }
432
433 statbar->SetStatusText(text, m_statusBarPane);
434 #else
435 wxUnusedVar(help);
436 wxUnusedVar(show);
437 #endif // wxUSE_STATUSBAR
438 }
439 #endif // wxUSE_MENUS || wxUSE_TOOLBAR
440
441
442 // ----------------------------------------------------------------------------
443 // toolbar stuff
444 // ----------------------------------------------------------------------------
445
446 #if wxUSE_TOOLBAR
447
448 wxToolBar* wxFrameBase::CreateToolBar(long style,
449 wxWindowID id,
450 const wxString& name)
451 {
452 // the main toolbar can't be recreated (unless it was explicitly deleted
453 // before)
454 wxCHECK_MSG( !m_frameToolBar, (wxToolBar *)NULL,
455 wxT("recreating toolbar in wxFrame") );
456
457 if ( style == -1 )
458 {
459 // use default style
460 //
461 // NB: we don't specify the default value in the method declaration
462 // because
463 // a) this allows us to have different defaults for different
464 // platforms (even if we don't have them right now)
465 // b) we don't need to include wx/toolbar.h in the header then
466 style = wxBORDER_NONE | wxTB_HORIZONTAL | wxTB_FLAT;
467 }
468
469 SetToolBar(OnCreateToolBar(style, id, name));
470
471 return m_frameToolBar;
472 }
473
474 wxToolBar* wxFrameBase::OnCreateToolBar(long style,
475 wxWindowID id,
476 const wxString& name)
477 {
478 #if defined(__WXWINCE__) && defined(__POCKETPC__)
479 return new wxToolMenuBar(this, id,
480 wxDefaultPosition, wxDefaultSize,
481 style, name);
482 #else
483 return new wxToolBar(this, id,
484 wxDefaultPosition, wxDefaultSize,
485 style, name);
486 #endif
487 }
488
489 void wxFrameBase::SetToolBar(wxToolBar *toolbar)
490 {
491 bool hadBar = m_frameToolBar != NULL;
492 m_frameToolBar = toolbar;
493
494 if ( (m_frameToolBar != NULL) != hadBar )
495 {
496 PositionToolBar();
497
498 DoLayout();
499 }
500 }
501
502 #endif // wxUSE_TOOLBAR
503
504 // ----------------------------------------------------------------------------
505 // menus
506 // ----------------------------------------------------------------------------
507
508 #if wxUSE_MENUS
509
510 // update all menus
511 void wxFrameBase::DoMenuUpdates(wxMenu* menu)
512 {
513 if (menu)
514 {
515 wxEvtHandler* source = GetEventHandler();
516 menu->UpdateUI(source);
517 }
518 else
519 {
520 wxMenuBar* bar = GetMenuBar();
521 if (bar != NULL)
522 bar->UpdateMenus();
523 }
524 }
525
526 void wxFrameBase::DetachMenuBar()
527 {
528 if ( m_frameMenuBar )
529 {
530 m_frameMenuBar->Detach();
531 m_frameMenuBar = NULL;
532 }
533 }
534
535 void wxFrameBase::AttachMenuBar(wxMenuBar *menubar)
536 {
537 if ( menubar )
538 {
539 menubar->Attach((wxFrame *)this);
540 m_frameMenuBar = menubar;
541 }
542 }
543
544 void wxFrameBase::SetMenuBar(wxMenuBar *menubar)
545 {
546 if ( menubar == GetMenuBar() )
547 {
548 // nothing to do
549 return;
550 }
551
552 DetachMenuBar();
553
554 this->AttachMenuBar(menubar);
555 }
556
557 const wxMenuItem *wxFrameBase::FindItemInMenuBar(int menuId) const
558 {
559 const wxMenuBar * const menuBar = GetMenuBar();
560
561 return menuBar ? menuBar->FindItem(menuId) : NULL;
562 }
563
564 #endif // wxUSE_MENUS