1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/framecmn.cpp
3 // Purpose: common (for all platforms) wxFrame functions
4 // Author: Julian Smart, Vadim Zeitlin
7 // Copyright: (c) 1998 Robert Roebling and Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
30 #include "wx/menuitem.h"
31 #include "wx/dcclient.h"
32 #include "wx/toolbar.h"
33 #include "wx/statusbr.h"
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
40 #if wxUSE_MENUS && wxUSE_STATUSBAR
42 BEGIN_EVENT_TABLE(wxFrameBase
, wxTopLevelWindow
)
43 EVT_MENU_OPEN(wxFrameBase::OnMenuOpen
)
44 EVT_MENU_CLOSE(wxFrameBase::OnMenuClose
)
46 EVT_MENU_HIGHLIGHT_ALL(wxFrameBase::OnMenuHighlight
)
49 #endif // wxUSE_MENUS && wxUSE_STATUSBAR
51 // ============================================================================
53 // ============================================================================
55 // ----------------------------------------------------------------------------
56 // construction/destruction
57 // ----------------------------------------------------------------------------
59 wxFrameBase::wxFrameBase()
62 m_frameMenuBar
= NULL
;
66 m_frameToolBar
= NULL
;
67 #endif // wxUSE_TOOLBAR
70 m_frameStatusBar
= NULL
;
71 #endif // wxUSE_STATUSBAR
76 wxFrameBase::~wxFrameBase()
78 // this destructor is required for Darwin
81 wxFrame
*wxFrameBase::New(wxWindow
*parent
,
83 const wxString
& title
,
89 return new wxFrame(parent
, id
, title
, pos
, size
, style
, name
);
92 void wxFrameBase::DeleteAllBars()
95 wxDELETE(m_frameMenuBar
);
99 wxDELETE(m_frameStatusBar
);
100 #endif // wxUSE_STATUSBAR
103 wxDELETE(m_frameToolBar
);
104 #endif // wxUSE_TOOLBAR
107 bool wxFrameBase::IsOneOfBars(const wxWindow
*win
) const
110 if ( win
== GetMenuBar() )
112 #endif // wxUSE_MENUS
115 if ( win
== GetStatusBar() )
117 #endif // wxUSE_STATUSBAR
120 if ( win
== GetToolBar() )
122 #endif // wxUSE_TOOLBAR
129 // ----------------------------------------------------------------------------
130 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
131 // from the client area, so the client area is what's really available for the
133 // ----------------------------------------------------------------------------
135 // get the origin of the client area in the client coordinates
136 wxPoint
wxFrameBase::GetClientAreaOrigin() const
138 wxPoint pt
= wxTopLevelWindow::GetClientAreaOrigin();
140 #if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__)
141 wxToolBar
*toolbar
= GetToolBar();
142 if ( toolbar
&& toolbar
->IsShown() )
145 toolbar
->GetSize(&w
, &h
);
147 if ( toolbar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
156 #endif // wxUSE_TOOLBAR
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
167 bool wxFrameBase::ProcessCommand(int id
)
169 wxMenuBar
*bar
= GetMenuBar();
173 wxMenuItem
*item
= bar
->FindItem(id
);
177 return ProcessCommand(item
);
180 bool wxFrameBase::ProcessCommand(wxMenuItem
*item
)
182 wxCommandEvent
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, item
->GetId());
183 commandEvent
.SetEventObject(this);
185 if (!item
->IsEnabled())
188 if ((item
->GetKind() == wxITEM_RADIO
) && item
->IsChecked() )
191 if (item
->IsCheckable())
196 commandEvent
.SetInt(item
->IsChecked());
199 return HandleWindowEvent(commandEvent
);
202 #endif // wxUSE_MENUS
204 // Do the UI update processing for this window. This is
205 // provided for the application to call if it wants to
206 // force a UI update, particularly for the menus and toolbar.
207 void wxFrameBase::UpdateWindowUI(long flags
)
209 wxWindowBase::UpdateWindowUI(flags
);
213 GetToolBar()->UpdateWindowUI(flags
);
219 // If coming from an idle event, we only want to update the menus if
220 // we're in the wxUSE_IDLEMENUUPDATES configuration, otherwise they
221 // will be update when the menu is opened later
222 #if !wxUSE_IDLEMENUUPDATES
223 if ( !(flags
& wxUPDATE_UI_FROMIDLE
) )
224 #endif // wxUSE_IDLEMENUUPDATES
227 #endif // wxUSE_MENUS
230 // ----------------------------------------------------------------------------
231 // event handlers for status bar updates from menus
232 // ----------------------------------------------------------------------------
234 #if wxUSE_MENUS && wxUSE_STATUSBAR
236 void wxFrameBase::OnMenuHighlight(wxMenuEvent
& event
)
239 (void)ShowMenuHelp(event
.GetMenuId());
240 #endif // wxUSE_STATUSBAR
243 void wxFrameBase::OnMenuOpen(wxMenuEvent
& event
)
245 #if wxUSE_IDLEMENUUPDATES
247 #else // !wxUSE_IDLEMENUUPDATES
248 // as we didn't update the menus from idle time, do it now
249 DoMenuUpdates(event
.GetMenu());
250 #endif // wxUSE_IDLEMENUUPDATES/!wxUSE_IDLEMENUUPDATES
253 void wxFrameBase::OnMenuClose(wxMenuEvent
& WXUNUSED(event
))
255 DoGiveHelp(wxEmptyString
, false);
258 #endif // wxUSE_MENUS && wxUSE_STATUSBAR
260 // Implement internal behaviour (menu updating on some platforms)
261 void wxFrameBase::OnInternalIdle()
263 wxTopLevelWindow::OnInternalIdle();
265 #if wxUSE_MENUS && wxUSE_IDLEMENUUPDATES
266 if (wxUpdateUIEvent::CanUpdate(this))
271 // ----------------------------------------------------------------------------
273 // ----------------------------------------------------------------------------
277 wxStatusBar
* wxFrameBase::CreateStatusBar(int number
,
280 const wxString
& name
)
282 // the main status bar can only be created once (or else it should be
283 // deleted before calling CreateStatusBar() again)
284 wxCHECK_MSG( !m_frameStatusBar
, NULL
,
285 wxT("recreating status bar in wxFrame") );
287 SetStatusBar(OnCreateStatusBar(number
, style
, id
, name
));
289 return m_frameStatusBar
;
292 wxStatusBar
*wxFrameBase::OnCreateStatusBar(int number
,
295 const wxString
& name
)
297 wxStatusBar
*statusBar
= new wxStatusBar(this, id
, style
, name
);
299 statusBar
->SetFieldsCount(number
);
304 void wxFrameBase::SetStatusText(const wxString
& text
, int number
)
306 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set text for") );
308 m_frameStatusBar
->SetStatusText(text
, number
);
311 void wxFrameBase::SetStatusWidths(int n
, const int widths_field
[] )
313 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set widths for") );
315 m_frameStatusBar
->SetStatusWidths(n
, widths_field
);
320 void wxFrameBase::PushStatusText(const wxString
& text
, int number
)
322 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set text for") );
324 m_frameStatusBar
->PushStatusText(text
, number
);
327 void wxFrameBase::PopStatusText(int number
)
329 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set text for") );
331 m_frameStatusBar
->PopStatusText(number
);
334 bool wxFrameBase::ShowMenuHelp(int menuId
)
337 // if no help string found, we will clear the status bar text
339 // NB: wxID_NONE is used for (sub)menus themselves by wxMSW
341 if ( menuId
!= wxID_SEPARATOR
&& menuId
!= wxID_NONE
)
343 const wxMenuItem
* const item
= FindItemInMenuBar(menuId
);
344 if ( item
&& !item
->IsSeparator() )
345 helpString
= item
->GetHelp();
347 // notice that it's ok if we don't find the item because it might
348 // belong to the popup menu, so don't assert here
351 DoGiveHelp(helpString
, true);
353 return !helpString
.empty();
354 #else // !wxUSE_MENUS
356 #endif // wxUSE_MENUS/!wxUSE_MENUS
359 void wxFrameBase::SetStatusBar(wxStatusBar
*statBar
)
361 bool hadBar
= m_frameStatusBar
!= NULL
;
362 m_frameStatusBar
= statBar
;
364 if ( (m_frameStatusBar
!= NULL
) != hadBar
)
372 #endif // wxUSE_STATUSBAR
374 #if wxUSE_MENUS || wxUSE_TOOLBAR
375 void wxFrameBase::DoGiveHelp(const wxString
& help
, bool show
)
378 if ( m_statusBarPane
< 0 )
380 // status bar messages disabled
384 wxStatusBar
*statbar
= GetStatusBar();
391 // remember the old status bar text if this is the first time we're
392 // called since the menu has been opened as we're going to overwrite it
393 // in our DoGiveHelp() and we want to restore it when the menu is
396 // note that it would be logical to do this in OnMenuOpen() but under
397 // MSW we get an EVT_MENU_HIGHLIGHT before EVT_MENU_OPEN, strangely
398 // enough, and so this doesn't work and instead we use the ugly trick
399 // with using special m_oldStatusText value as "menu opened" (but it is
400 // arguably better than adding yet another member variable to wxFrame
402 if ( m_oldStatusText
.empty() )
404 m_oldStatusText
= statbar
->GetStatusText(m_statusBarPane
);
405 if ( m_oldStatusText
.empty() )
407 // use special value to prevent us from doing this the next time
408 m_oldStatusText
+= wxT('\0');
415 else // hide help, restore the original text
417 // clear the last shown help string but remember its value
418 wxString lastHelpShown
;
419 lastHelpShown
.swap(m_lastHelpShown
);
421 // also clear the old status text but remember it too to restore it
423 text
.swap(m_oldStatusText
);
425 if ( statbar
->GetStatusText(m_statusBarPane
) != lastHelpShown
)
427 // if the text was changed with an explicit SetStatusText() call
428 // from the user code in the meanwhile, do not overwrite it with
429 // the old status bar contents -- this is almost certainly not what
430 // the user expects and would be very hard to avoid from user code
435 statbar
->SetStatusText(text
, m_statusBarPane
);
439 #endif // wxUSE_STATUSBAR
441 #endif // wxUSE_MENUS || wxUSE_TOOLBAR
444 // ----------------------------------------------------------------------------
446 // ----------------------------------------------------------------------------
450 wxToolBar
* wxFrameBase::CreateToolBar(long style
,
452 const wxString
& name
)
454 // the main toolbar can't be recreated (unless it was explicitly deleted
456 wxCHECK_MSG( !m_frameToolBar
, NULL
,
457 wxT("recreating toolbar in wxFrame") );
463 // NB: we don't specify the default value in the method declaration
465 // a) this allows us to have different defaults for different
466 // platforms (even if we don't have them right now)
467 // b) we don't need to include wx/toolbar.h in the header then
468 style
= wxBORDER_NONE
| wxTB_HORIZONTAL
| wxTB_FLAT
;
471 SetToolBar(OnCreateToolBar(style
, id
, name
));
473 return m_frameToolBar
;
476 wxToolBar
* wxFrameBase::OnCreateToolBar(long style
,
478 const wxString
& name
)
480 #if defined(__WXWINCE__) && defined(__POCKETPC__)
481 return new wxToolMenuBar(this, id
,
482 wxDefaultPosition
, wxDefaultSize
,
485 return new wxToolBar(this, id
,
486 wxDefaultPosition
, wxDefaultSize
,
491 void wxFrameBase::SetToolBar(wxToolBar
*toolbar
)
493 if ( (toolbar
!= NULL
) != (m_frameToolBar
!= NULL
) )
495 // the toolbar visibility must have changed so we need to both position
496 // the toolbar itself (if it appeared) and to relayout the frame
497 // contents in any case
501 // we need to assign it to m_frameToolBar for PositionToolBar() to
503 m_frameToolBar
= toolbar
;
506 //else: tricky: do not reset m_frameToolBar yet as otherwise DoLayout()
507 // wouldn't recognize the (still existing) toolbar as one of our
508 // bars and wouldn't layout the single child of the frame correctly
511 // and this is even more tricky: we want DoLayout() to recognize the
512 // old toolbar for the purpose of not counting it among our non-bar
513 // children but we don't want to reserve any more space for it so we
514 // temporarily hide it
515 if ( m_frameToolBar
)
516 m_frameToolBar
->Hide();
520 if ( m_frameToolBar
)
521 m_frameToolBar
->Show();
524 // this might have been already done above but it's simpler to just always
525 // do it unconditionally instead of testing for whether we already did it
526 m_frameToolBar
= toolbar
;
529 #endif // wxUSE_TOOLBAR
531 // ----------------------------------------------------------------------------
533 // ----------------------------------------------------------------------------
538 void wxFrameBase::DoMenuUpdates(wxMenu
* menu
)
542 wxEvtHandler
* source
= GetEventHandler();
543 menu
->UpdateUI(source
);
547 wxMenuBar
* bar
= GetMenuBar();
553 void wxFrameBase::DetachMenuBar()
555 if ( m_frameMenuBar
)
557 m_frameMenuBar
->Detach();
558 m_frameMenuBar
= NULL
;
562 void wxFrameBase::AttachMenuBar(wxMenuBar
*menubar
)
566 menubar
->Attach((wxFrame
*)this);
567 m_frameMenuBar
= menubar
;
571 void wxFrameBase::SetMenuBar(wxMenuBar
*menubar
)
573 if ( menubar
== GetMenuBar() )
581 this->AttachMenuBar(menubar
);
584 wxMenuItem
*wxFrameBase::FindItemInMenuBar(int menuId
) const
586 const wxMenuBar
* const menuBar
= GetMenuBar();
588 return menuBar
? menuBar
->FindItem(menuId
) : NULL
;
591 #endif // wxUSE_MENUS