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 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 wxDEFINE_FLAGS( wxFrameStyle
)
60 wxBEGIN_FLAGS( wxFrameStyle
)
61 // new style border flags, we put them first to
62 // use them for streaming out
63 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
64 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
65 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
66 wxFLAGS_MEMBER(wxBORDER_RAISED
)
67 wxFLAGS_MEMBER(wxBORDER_STATIC
)
68 wxFLAGS_MEMBER(wxBORDER_NONE
)
70 // old style border flags
71 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
72 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
73 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
74 wxFLAGS_MEMBER(wxRAISED_BORDER
)
75 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
76 wxFLAGS_MEMBER(wxBORDER
)
78 // standard window styles
79 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
80 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
81 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
82 wxFLAGS_MEMBER(wxWANTS_CHARS
)
83 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
84 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
85 wxFLAGS_MEMBER(wxVSCROLL
)
86 wxFLAGS_MEMBER(wxHSCROLL
)
89 wxFLAGS_MEMBER(wxSTAY_ON_TOP
)
90 wxFLAGS_MEMBER(wxCAPTION
)
91 #if WXWIN_COMPATIBILITY_2_6
92 wxFLAGS_MEMBER(wxTHICK_FRAME
)
93 #endif // WXWIN_COMPATIBILITY_2_6
94 wxFLAGS_MEMBER(wxSYSTEM_MENU
)
95 wxFLAGS_MEMBER(wxRESIZE_BORDER
)
96 #if WXWIN_COMPATIBILITY_2_6
97 wxFLAGS_MEMBER(wxRESIZE_BOX
)
98 #endif // WXWIN_COMPATIBILITY_2_6
99 wxFLAGS_MEMBER(wxCLOSE_BOX
)
100 wxFLAGS_MEMBER(wxMAXIMIZE_BOX
)
101 wxFLAGS_MEMBER(wxMINIMIZE_BOX
)
103 wxFLAGS_MEMBER(wxFRAME_TOOL_WINDOW
)
104 wxFLAGS_MEMBER(wxFRAME_FLOAT_ON_PARENT
)
106 wxFLAGS_MEMBER(wxFRAME_SHAPED
)
107 wxEND_FLAGS( wxFrameStyle
)
109 wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxFrame
, wxTopLevelWindow
, "wx/frame.h")
111 wxBEGIN_PROPERTIES_TABLE(wxFrame
)
112 wxEVENT_PROPERTY( Menu
, wxEVT_COMMAND_MENU_SELECTED
, wxCommandEvent
)
114 wxPROPERTY( Title
,wxString
, SetTitle
, GetTitle
, wxString(), 0 /*flags*/, \
115 wxT("Helpstring"), wxT("group"))
116 wxPROPERTY_FLAGS( WindowStyle
, wxFrameStyle
, long, SetWindowStyleFlag
, \
117 GetWindowStyleFlag
, wxEMPTY_PARAMETER_VALUE
, 0 /*flags*/, \
118 wxT("Helpstring"), wxT("group")) // style
119 wxPROPERTY( MenuBar
, wxMenuBar
*, SetMenuBar
, GetMenuBar
, wxEMPTY_PARAMETER_VALUE
, \
120 0 /*flags*/, wxT("Helpstring"), wxT("group"))
121 wxEND_PROPERTIES_TABLE()
123 wxEMPTY_HANDLERS_TABLE(wxFrame
)
125 wxCONSTRUCTOR_6( wxFrame
, wxWindow
*, Parent
, wxWindowID
, Id
, wxString
, Title
, \
126 wxPoint
, Position
, wxSize
, Size
, long, WindowStyle
)
128 // ----------------------------------------------------------------------------
129 // construction/destruction
130 // ----------------------------------------------------------------------------
132 wxFrameBase::wxFrameBase()
135 m_frameMenuBar
= NULL
;
136 #endif // wxUSE_MENUS
139 m_frameToolBar
= NULL
;
140 #endif // wxUSE_TOOLBAR
143 m_frameStatusBar
= NULL
;
144 #endif // wxUSE_STATUSBAR
149 wxFrameBase::~wxFrameBase()
151 // this destructor is required for Darwin
154 wxFrame
*wxFrameBase::New(wxWindow
*parent
,
156 const wxString
& title
,
160 const wxString
& name
)
162 return new wxFrame(parent
, id
, title
, pos
, size
, style
, name
);
165 void wxFrameBase::DeleteAllBars()
168 wxDELETE(m_frameMenuBar
);
169 #endif // wxUSE_MENUS
172 wxDELETE(m_frameStatusBar
);
173 #endif // wxUSE_STATUSBAR
176 wxDELETE(m_frameToolBar
);
177 #endif // wxUSE_TOOLBAR
180 bool wxFrameBase::IsOneOfBars(const wxWindow
*win
) const
183 if ( win
== GetMenuBar() )
185 #endif // wxUSE_MENUS
188 if ( win
== GetStatusBar() )
190 #endif // wxUSE_STATUSBAR
193 if ( win
== GetToolBar() )
195 #endif // wxUSE_TOOLBAR
202 // ----------------------------------------------------------------------------
203 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
204 // from the client area, so the client area is what's really available for the
206 // ----------------------------------------------------------------------------
208 // get the origin of the client area in the client coordinates
209 wxPoint
wxFrameBase::GetClientAreaOrigin() const
211 wxPoint pt
= wxTopLevelWindow::GetClientAreaOrigin();
213 #if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__)
214 wxToolBar
*toolbar
= GetToolBar();
215 if ( toolbar
&& toolbar
->IsShown() )
218 toolbar
->GetSize(&w
, &h
);
220 if ( toolbar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
229 #endif // wxUSE_TOOLBAR
234 // ----------------------------------------------------------------------------
236 // ----------------------------------------------------------------------------
240 bool wxFrameBase::ProcessCommand(int id
)
242 wxMenuBar
*bar
= GetMenuBar();
246 wxMenuItem
*item
= bar
->FindItem(id
);
250 return ProcessCommand(item
);
253 bool wxFrameBase::ProcessCommand(wxMenuItem
*item
)
255 wxCommandEvent
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, item
->GetId());
256 commandEvent
.SetEventObject(this);
258 if (!item
->IsEnabled())
261 if ((item
->GetKind() == wxITEM_RADIO
) && item
->IsChecked() )
264 if (item
->IsCheckable())
269 commandEvent
.SetInt(item
->IsChecked());
272 return HandleWindowEvent(commandEvent
);
275 #endif // wxUSE_MENUS
277 // Do the UI update processing for this window. This is
278 // provided for the application to call if it wants to
279 // force a UI update, particularly for the menus and toolbar.
280 void wxFrameBase::UpdateWindowUI(long flags
)
282 wxWindowBase::UpdateWindowUI(flags
);
286 GetToolBar()->UpdateWindowUI(flags
);
292 // If coming from an idle event, we only want to update the menus if
293 // we're in the wxUSE_IDLEMENUUPDATES configuration, otherwise they
294 // will be update when the menu is opened later
295 #if !wxUSE_IDLEMENUUPDATES
296 if ( !(flags
& wxUPDATE_UI_FROMIDLE
) )
297 #endif // wxUSE_IDLEMENUUPDATES
300 #endif // wxUSE_MENUS
303 // ----------------------------------------------------------------------------
304 // event handlers for status bar updates from menus
305 // ----------------------------------------------------------------------------
307 #if wxUSE_MENUS && wxUSE_STATUSBAR
309 void wxFrameBase::OnMenuHighlight(wxMenuEvent
& event
)
312 (void)ShowMenuHelp(event
.GetMenuId());
313 #endif // wxUSE_STATUSBAR
316 void wxFrameBase::OnMenuOpen(wxMenuEvent
& event
)
318 #if wxUSE_IDLEMENUUPDATES
320 #else // !wxUSE_IDLEMENUUPDATES
321 // as we didn't update the menus from idle time, do it now
322 DoMenuUpdates(event
.GetMenu());
323 #endif // wxUSE_IDLEMENUUPDATES/!wxUSE_IDLEMENUUPDATES
326 void wxFrameBase::OnMenuClose(wxMenuEvent
& WXUNUSED(event
))
328 DoGiveHelp(wxEmptyString
, false);
331 #endif // wxUSE_MENUS && wxUSE_STATUSBAR
333 // Implement internal behaviour (menu updating on some platforms)
334 void wxFrameBase::OnInternalIdle()
336 wxTopLevelWindow::OnInternalIdle();
338 #if wxUSE_MENUS && wxUSE_IDLEMENUUPDATES
339 if (wxUpdateUIEvent::CanUpdate(this))
344 // ----------------------------------------------------------------------------
346 // ----------------------------------------------------------------------------
350 wxStatusBar
* wxFrameBase::CreateStatusBar(int number
,
353 const wxString
& name
)
355 // the main status bar can only be created once (or else it should be
356 // deleted before calling CreateStatusBar() again)
357 wxCHECK_MSG( !m_frameStatusBar
, NULL
,
358 wxT("recreating status bar in wxFrame") );
360 SetStatusBar(OnCreateStatusBar(number
, style
, id
, name
));
362 return m_frameStatusBar
;
365 wxStatusBar
*wxFrameBase::OnCreateStatusBar(int number
,
368 const wxString
& name
)
370 wxStatusBar
*statusBar
= new wxStatusBar(this, id
, style
, name
);
372 statusBar
->SetFieldsCount(number
);
377 void wxFrameBase::SetStatusText(const wxString
& text
, int number
)
379 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set text for") );
381 m_frameStatusBar
->SetStatusText(text
, number
);
384 void wxFrameBase::SetStatusWidths(int n
, const int widths_field
[] )
386 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set widths for") );
388 m_frameStatusBar
->SetStatusWidths(n
, widths_field
);
393 void wxFrameBase::PushStatusText(const wxString
& text
, int number
)
395 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set text for") );
397 m_frameStatusBar
->PushStatusText(text
, number
);
400 void wxFrameBase::PopStatusText(int number
)
402 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set text for") );
404 m_frameStatusBar
->PopStatusText(number
);
407 bool wxFrameBase::ShowMenuHelp(int menuId
)
410 // if no help string found, we will clear the status bar text
412 // NB: wxID_NONE is used for (sub)menus themselves by wxMSW
414 if ( menuId
!= wxID_SEPARATOR
&& menuId
!= wxID_NONE
)
416 const wxMenuItem
* const item
= FindItemInMenuBar(menuId
);
417 if ( item
&& !item
->IsSeparator() )
418 helpString
= item
->GetHelp();
420 // notice that it's ok if we don't find the item because it might
421 // belong to the popup menu, so don't assert here
424 DoGiveHelp(helpString
, true);
426 return !helpString
.empty();
427 #else // !wxUSE_MENUS
429 #endif // wxUSE_MENUS/!wxUSE_MENUS
432 void wxFrameBase::SetStatusBar(wxStatusBar
*statBar
)
434 bool hadBar
= m_frameStatusBar
!= NULL
;
435 m_frameStatusBar
= statBar
;
437 if ( (m_frameStatusBar
!= NULL
) != hadBar
)
445 #endif // wxUSE_STATUSBAR
447 #if wxUSE_MENUS || wxUSE_TOOLBAR
448 void wxFrameBase::DoGiveHelp(const wxString
& help
, bool show
)
451 if ( m_statusBarPane
< 0 )
453 // status bar messages disabled
457 wxStatusBar
*statbar
= GetStatusBar();
464 // remember the old status bar text if this is the first time we're
465 // called since the menu has been opened as we're going to overwrite it
466 // in our DoGiveHelp() and we want to restore it when the menu is
469 // note that it would be logical to do this in OnMenuOpen() but under
470 // MSW we get an EVT_MENU_HIGHLIGHT before EVT_MENU_OPEN, strangely
471 // enough, and so this doesn't work and instead we use the ugly trick
472 // with using special m_oldStatusText value as "menu opened" (but it is
473 // arguably better than adding yet another member variable to wxFrame
475 if ( m_oldStatusText
.empty() )
477 m_oldStatusText
= statbar
->GetStatusText(m_statusBarPane
);
478 if ( m_oldStatusText
.empty() )
480 // use special value to prevent us from doing this the next time
481 m_oldStatusText
+= wxT('\0');
488 else // hide help, restore the original text
490 // clear the last shown help string but remember its value
491 wxString lastHelpShown
;
492 lastHelpShown
.swap(m_lastHelpShown
);
494 // also clear the old status text but remember it too to restore it
496 text
.swap(m_oldStatusText
);
498 if ( statbar
->GetStatusText(m_statusBarPane
) != lastHelpShown
)
500 // if the text was changed with an explicit SetStatusText() call
501 // from the user code in the meanwhile, do not overwrite it with
502 // the old status bar contents -- this is almost certainly not what
503 // the user expects and would be very hard to avoid from user code
508 statbar
->SetStatusText(text
, m_statusBarPane
);
512 #endif // wxUSE_STATUSBAR
514 #endif // wxUSE_MENUS || wxUSE_TOOLBAR
517 // ----------------------------------------------------------------------------
519 // ----------------------------------------------------------------------------
523 wxToolBar
* wxFrameBase::CreateToolBar(long style
,
525 const wxString
& name
)
527 // the main toolbar can't be recreated (unless it was explicitly deleted
529 wxCHECK_MSG( !m_frameToolBar
, NULL
,
530 wxT("recreating toolbar in wxFrame") );
536 // NB: we don't specify the default value in the method declaration
538 // a) this allows us to have different defaults for different
539 // platforms (even if we don't have them right now)
540 // b) we don't need to include wx/toolbar.h in the header then
541 style
= wxBORDER_NONE
| wxTB_HORIZONTAL
| wxTB_FLAT
;
544 SetToolBar(OnCreateToolBar(style
, id
, name
));
546 return m_frameToolBar
;
549 wxToolBar
* wxFrameBase::OnCreateToolBar(long style
,
551 const wxString
& name
)
553 #if defined(__WXWINCE__) && defined(__POCKETPC__)
554 return new wxToolMenuBar(this, id
,
555 wxDefaultPosition
, wxDefaultSize
,
558 return new wxToolBar(this, id
,
559 wxDefaultPosition
, wxDefaultSize
,
564 void wxFrameBase::SetToolBar(wxToolBar
*toolbar
)
566 if ( (toolbar
!= NULL
) != (m_frameToolBar
!= NULL
) )
568 // the toolbar visibility must have changed so we need to both position
569 // the toolbar itself (if it appeared) and to relayout the frame
570 // contents in any case
574 // we need to assign it to m_frameToolBar for PositionToolBar() to
576 m_frameToolBar
= toolbar
;
579 //else: tricky: do not reset m_frameToolBar yet as otherwise DoLayout()
580 // wouldn't recognize the (still existing) toolbar as one of our
581 // bars and wouldn't layout the single child of the frame correctly
584 // and this is even more tricky: we want DoLayout() to recognize the
585 // old toolbar for the purpose of not counting it among our non-bar
586 // children but we don't want to reserve any more space for it so we
587 // temporarily hide it
588 if ( m_frameToolBar
)
589 m_frameToolBar
->Hide();
593 if ( m_frameToolBar
)
594 m_frameToolBar
->Show();
597 // this might have been already done above but it's simpler to just always
598 // do it unconditionally instead of testing for whether we already did it
599 m_frameToolBar
= toolbar
;
602 #endif // wxUSE_TOOLBAR
604 // ----------------------------------------------------------------------------
606 // ----------------------------------------------------------------------------
611 void wxFrameBase::DoMenuUpdates(wxMenu
* menu
)
615 wxEvtHandler
* source
= GetEventHandler();
616 menu
->UpdateUI(source
);
620 wxMenuBar
* bar
= GetMenuBar();
626 void wxFrameBase::DetachMenuBar()
628 if ( m_frameMenuBar
)
630 m_frameMenuBar
->Detach();
631 m_frameMenuBar
= NULL
;
635 void wxFrameBase::AttachMenuBar(wxMenuBar
*menubar
)
639 menubar
->Attach((wxFrame
*)this);
640 m_frameMenuBar
= menubar
;
644 void wxFrameBase::SetMenuBar(wxMenuBar
*menubar
)
646 if ( menubar
== GetMenuBar() )
654 this->AttachMenuBar(menubar
);
657 wxMenuItem
*wxFrameBase::FindItemInMenuBar(int menuId
) const
659 const wxMenuBar
* const menuBar
= GetMenuBar();
661 return menuBar
? menuBar
->FindItem(menuId
) : NULL
;
664 #endif // wxUSE_MENUS