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