]>
git.saurik.com Git - wxWidgets.git/blob - 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
6 // Copyright: (c) 1998 Robert Roebling and Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // For compilers that support precompilation, includes "wx.h".
19 #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 extern WXDLLEXPORT_DATA(const char) wxFrameNameStr
[] = "frame";
37 extern WXDLLEXPORT_DATA(const char) wxStatusLineNameStr
[] = "status_line";
39 // ----------------------------------------------------------------------------
41 // ----------------------------------------------------------------------------
46 BEGIN_EVENT_TABLE(wxFrameBase
, wxTopLevelWindow
)
47 EVT_MENU_OPEN(wxFrameBase::OnMenuOpen
)
48 EVT_MENU_CLOSE(wxFrameBase::OnMenuClose
)
50 EVT_MENU_HIGHLIGHT_ALL(wxFrameBase::OnMenuHighlight
)
52 #endif // wxUSE_STATUSBAR
55 bool wxFrameBase::ShouldUpdateMenuFromIdle()
57 // Usually this is determined at compile time and is determined by whether
58 // the platform supports wxEVT_MENU_OPEN, however in wxGTK we need to also
59 // check if we're using the global menu bar as we don't get EVT_MENU_OPEN
60 // for it and need to fall back to idle time updating even if normally
61 // wxUSE_IDLEMENUUPDATES is set to 0 for wxGTK.
63 if ( wxApp::GTKIsUsingGlobalMenu() )
67 return wxUSE_IDLEMENUUPDATES
!= 0;
72 // ============================================================================
74 // ============================================================================
76 // ----------------------------------------------------------------------------
78 // ----------------------------------------------------------------------------
80 wxDEFINE_FLAGS( wxFrameStyle
)
81 wxBEGIN_FLAGS( wxFrameStyle
)
82 // new style border flags, we put them first to
83 // use them for streaming out
84 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
85 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
86 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
87 wxFLAGS_MEMBER(wxBORDER_RAISED
)
88 wxFLAGS_MEMBER(wxBORDER_STATIC
)
89 wxFLAGS_MEMBER(wxBORDER_NONE
)
91 // old style border flags
92 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
93 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
94 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
95 wxFLAGS_MEMBER(wxRAISED_BORDER
)
96 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
97 wxFLAGS_MEMBER(wxBORDER
)
99 // standard window styles
100 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
101 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
102 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
103 wxFLAGS_MEMBER(wxWANTS_CHARS
)
104 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
105 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
106 wxFLAGS_MEMBER(wxVSCROLL
)
107 wxFLAGS_MEMBER(wxHSCROLL
)
110 wxFLAGS_MEMBER(wxSTAY_ON_TOP
)
111 wxFLAGS_MEMBER(wxCAPTION
)
112 #if WXWIN_COMPATIBILITY_2_6
113 wxFLAGS_MEMBER(wxTHICK_FRAME
)
114 #endif // WXWIN_COMPATIBILITY_2_6
115 wxFLAGS_MEMBER(wxSYSTEM_MENU
)
116 wxFLAGS_MEMBER(wxRESIZE_BORDER
)
117 #if WXWIN_COMPATIBILITY_2_6
118 wxFLAGS_MEMBER(wxRESIZE_BOX
)
119 #endif // WXWIN_COMPATIBILITY_2_6
120 wxFLAGS_MEMBER(wxCLOSE_BOX
)
121 wxFLAGS_MEMBER(wxMAXIMIZE_BOX
)
122 wxFLAGS_MEMBER(wxMINIMIZE_BOX
)
124 wxFLAGS_MEMBER(wxFRAME_TOOL_WINDOW
)
125 wxFLAGS_MEMBER(wxFRAME_FLOAT_ON_PARENT
)
127 wxFLAGS_MEMBER(wxFRAME_SHAPED
)
128 wxEND_FLAGS( wxFrameStyle
)
130 wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxFrame
, wxTopLevelWindow
, "wx/frame.h")
132 wxBEGIN_PROPERTIES_TABLE(wxFrame
)
133 wxEVENT_PROPERTY( Menu
, wxEVT_MENU
, wxCommandEvent
)
135 wxPROPERTY( Title
,wxString
, SetTitle
, GetTitle
, wxString(), 0 /*flags*/, \
136 wxT("Helpstring"), wxT("group"))
137 wxPROPERTY_FLAGS( WindowStyle
, wxFrameStyle
, long, SetWindowStyleFlag
, \
138 GetWindowStyleFlag
, wxEMPTY_PARAMETER_VALUE
, 0 /*flags*/, \
139 wxT("Helpstring"), wxT("group")) // style
141 wxPROPERTY( MenuBar
, wxMenuBar
*, SetMenuBar
, GetMenuBar
, wxEMPTY_PARAMETER_VALUE
, \
142 0 /*flags*/, wxT("Helpstring"), wxT("group"))
144 wxEND_PROPERTIES_TABLE()
146 wxEMPTY_HANDLERS_TABLE(wxFrame
)
148 wxCONSTRUCTOR_6( wxFrame
, wxWindow
*, Parent
, wxWindowID
, Id
, wxString
, Title
, \
149 wxPoint
, Position
, wxSize
, Size
, long, WindowStyle
)
151 // ----------------------------------------------------------------------------
152 // construction/destruction
153 // ----------------------------------------------------------------------------
155 wxFrameBase::wxFrameBase()
158 m_frameMenuBar
= NULL
;
159 #endif // wxUSE_MENUS
162 m_frameToolBar
= NULL
;
163 #endif // wxUSE_TOOLBAR
166 m_frameStatusBar
= NULL
;
167 #endif // wxUSE_STATUSBAR
172 wxFrameBase::~wxFrameBase()
174 // this destructor is required for Darwin
177 wxFrame
*wxFrameBase::New(wxWindow
*parent
,
179 const wxString
& title
,
183 const wxString
& name
)
185 return new wxFrame(parent
, id
, title
, pos
, size
, style
, name
);
188 void wxFrameBase::DeleteAllBars()
191 wxDELETE(m_frameMenuBar
);
192 #endif // wxUSE_MENUS
195 wxDELETE(m_frameStatusBar
);
196 #endif // wxUSE_STATUSBAR
199 wxDELETE(m_frameToolBar
);
200 #endif // wxUSE_TOOLBAR
203 bool wxFrameBase::IsOneOfBars(const wxWindow
*win
) const
206 if ( win
== GetMenuBar() )
208 #endif // wxUSE_MENUS
211 if ( win
== GetStatusBar() )
213 #endif // wxUSE_STATUSBAR
216 if ( win
== GetToolBar() )
218 #endif // wxUSE_TOOLBAR
225 // ----------------------------------------------------------------------------
226 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
227 // from the client area, so the client area is what's really available for the
229 // ----------------------------------------------------------------------------
231 // get the origin of the client area in the client coordinates
232 wxPoint
wxFrameBase::GetClientAreaOrigin() const
234 wxPoint pt
= wxTopLevelWindow::GetClientAreaOrigin();
236 #if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__)
237 wxToolBar
*toolbar
= GetToolBar();
238 if ( toolbar
&& toolbar
->IsShown() )
241 toolbar
->GetSize(&w
, &h
);
243 if ( toolbar
->GetWindowStyleFlag() & wxTB_VERTICAL
)
252 #endif // wxUSE_TOOLBAR
257 // ----------------------------------------------------------------------------
259 // ----------------------------------------------------------------------------
263 bool wxFrameBase::ProcessCommand(int id
)
265 wxMenuItem
* const item
= FindItemInMenuBar(id
);
269 return ProcessCommand(item
);
272 bool wxFrameBase::ProcessCommand(wxMenuItem
*item
)
274 wxCHECK_MSG( item
, false, wxS("Menu item can't be NULL") );
276 if (!item
->IsEnabled())
279 if ((item
->GetKind() == wxITEM_RADIO
) && item
->IsChecked() )
283 if (item
->IsCheckable())
288 checked
= item
->IsChecked();
290 else // Uncheckable item.
295 wxMenu
* const menu
= item
->GetMenu();
296 wxCHECK_MSG( menu
, false, wxS("Menu item should be attached to a menu") );
298 return menu
->SendEvent(item
->GetId(), checked
);
301 #endif // wxUSE_MENUS
303 // Do the UI update processing for this window. This is
304 // provided for the application to call if it wants to
305 // force a UI update, particularly for the menus and toolbar.
306 void wxFrameBase::UpdateWindowUI(long flags
)
308 wxWindowBase::UpdateWindowUI(flags
);
312 GetToolBar()->UpdateWindowUI(flags
);
318 // If coming from an idle event, we only want to update the menus if
319 // we're in the wxUSE_IDLEMENUUPDATES configuration, otherwise they
320 // will be update when the menu is opened later
321 if ( !(flags
& wxUPDATE_UI_FROMIDLE
) || ShouldUpdateMenuFromIdle() )
324 #endif // wxUSE_MENUS
327 // ----------------------------------------------------------------------------
328 // event handlers for status bar updates from menus
329 // ----------------------------------------------------------------------------
331 #if wxUSE_MENUS && wxUSE_STATUSBAR
333 void wxFrameBase::OnMenuHighlight(wxMenuEvent
& event
)
336 (void)ShowMenuHelp(event
.GetMenuId());
337 #endif // wxUSE_STATUSBAR
340 void wxFrameBase::OnMenuOpen(wxMenuEvent
& event
)
342 if ( !ShouldUpdateMenuFromIdle() )
344 // as we didn't update the menus from idle time, do it now
345 DoMenuUpdates(event
.GetMenu());
349 void wxFrameBase::OnMenuClose(wxMenuEvent
& WXUNUSED(event
))
351 DoGiveHelp(wxEmptyString
, false);
354 #endif // wxUSE_MENUS && wxUSE_STATUSBAR
356 // Implement internal behaviour (menu updating on some platforms)
357 void wxFrameBase::OnInternalIdle()
359 wxTopLevelWindow::OnInternalIdle();
362 if ( ShouldUpdateMenuFromIdle() && wxUpdateUIEvent::CanUpdate(this) )
367 // ----------------------------------------------------------------------------
369 // ----------------------------------------------------------------------------
373 wxStatusBar
* wxFrameBase::CreateStatusBar(int number
,
376 const wxString
& name
)
378 // the main status bar can only be created once (or else it should be
379 // deleted before calling CreateStatusBar() again)
380 wxCHECK_MSG( !m_frameStatusBar
, NULL
,
381 wxT("recreating status bar in wxFrame") );
383 SetStatusBar(OnCreateStatusBar(number
, style
, id
, name
));
385 return m_frameStatusBar
;
388 wxStatusBar
*wxFrameBase::OnCreateStatusBar(int number
,
391 const wxString
& name
)
393 wxStatusBar
*statusBar
= new wxStatusBar(this, id
, style
, name
);
395 statusBar
->SetFieldsCount(number
);
400 void wxFrameBase::SetStatusText(const wxString
& text
, int number
)
402 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set text for") );
404 m_frameStatusBar
->SetStatusText(text
, number
);
407 void wxFrameBase::SetStatusWidths(int n
, const int widths_field
[] )
409 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set widths for") );
411 m_frameStatusBar
->SetStatusWidths(n
, widths_field
);
416 void wxFrameBase::PushStatusText(const wxString
& text
, int number
)
418 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set text for") );
420 m_frameStatusBar
->PushStatusText(text
, number
);
423 void wxFrameBase::PopStatusText(int number
)
425 wxCHECK_RET( m_frameStatusBar
!= NULL
, wxT("no statusbar to set text for") );
427 m_frameStatusBar
->PopStatusText(number
);
430 bool wxFrameBase::ShowMenuHelp(int menuId
)
433 // if no help string found, we will clear the status bar text
435 // NB: wxID_NONE is used for (sub)menus themselves by wxMSW
437 if ( menuId
!= wxID_SEPARATOR
&& menuId
!= wxID_NONE
)
439 const wxMenuItem
* const item
= FindItemInMenuBar(menuId
);
440 if ( item
&& !item
->IsSeparator() )
441 helpString
= item
->GetHelp();
443 // notice that it's ok if we don't find the item because it might
444 // belong to the popup menu, so don't assert here
447 DoGiveHelp(helpString
, true);
449 return !helpString
.empty();
450 #else // !wxUSE_MENUS
452 #endif // wxUSE_MENUS/!wxUSE_MENUS
455 void wxFrameBase::SetStatusBar(wxStatusBar
*statBar
)
457 bool hadBar
= m_frameStatusBar
!= NULL
;
458 m_frameStatusBar
= statBar
;
460 if ( (m_frameStatusBar
!= NULL
) != hadBar
)
468 #endif // wxUSE_STATUSBAR
470 #if wxUSE_MENUS || wxUSE_TOOLBAR
471 void wxFrameBase::DoGiveHelp(const wxString
& help
, bool show
)
474 if ( m_statusBarPane
< 0 )
476 // status bar messages disabled
480 wxStatusBar
*statbar
= GetStatusBar();
487 // remember the old status bar text if this is the first time we're
488 // called since the menu has been opened as we're going to overwrite it
489 // in our DoGiveHelp() and we want to restore it when the menu is
492 // note that it would be logical to do this in OnMenuOpen() but under
493 // MSW we get an EVT_MENU_HIGHLIGHT before EVT_MENU_OPEN, strangely
494 // enough, and so this doesn't work and instead we use the ugly trick
495 // with using special m_oldStatusText value as "menu opened" (but it is
496 // arguably better than adding yet another member variable to wxFrame
498 if ( m_oldStatusText
.empty() )
500 m_oldStatusText
= statbar
->GetStatusText(m_statusBarPane
);
501 if ( m_oldStatusText
.empty() )
503 // use special value to prevent us from doing this the next time
504 m_oldStatusText
+= wxT('\0');
511 else // hide help, restore the original text
513 // clear the last shown help string but remember its value
514 wxString lastHelpShown
;
515 lastHelpShown
.swap(m_lastHelpShown
);
517 // also clear the old status text but remember it too to restore it
519 text
.swap(m_oldStatusText
);
521 if ( statbar
->GetStatusText(m_statusBarPane
) != lastHelpShown
)
523 // if the text was changed with an explicit SetStatusText() call
524 // from the user code in the meanwhile, do not overwrite it with
525 // the old status bar contents -- this is almost certainly not what
526 // the user expects and would be very hard to avoid from user code
531 statbar
->SetStatusText(text
, m_statusBarPane
);
535 #endif // wxUSE_STATUSBAR
537 #endif // wxUSE_MENUS || wxUSE_TOOLBAR
540 // ----------------------------------------------------------------------------
542 // ----------------------------------------------------------------------------
546 wxToolBar
* wxFrameBase::CreateToolBar(long style
,
548 const wxString
& name
)
550 // the main toolbar can't be recreated (unless it was explicitly deleted
552 wxCHECK_MSG( !m_frameToolBar
, NULL
,
553 wxT("recreating toolbar in wxFrame") );
559 // NB: we don't specify the default value in the method declaration
561 // a) this allows us to have different defaults for different
562 // platforms (even if we don't have them right now)
563 // b) we don't need to include wx/toolbar.h in the header then
564 style
= wxTB_DEFAULT_STYLE
;
567 SetToolBar(OnCreateToolBar(style
, id
, name
));
569 return m_frameToolBar
;
572 wxToolBar
* wxFrameBase::OnCreateToolBar(long style
,
574 const wxString
& name
)
576 #if defined(__WXWINCE__) && defined(__POCKETPC__)
577 return new wxToolMenuBar(this, id
,
578 wxDefaultPosition
, wxDefaultSize
,
581 return new wxToolBar(this, id
,
582 wxDefaultPosition
, wxDefaultSize
,
587 void wxFrameBase::SetToolBar(wxToolBar
*toolbar
)
589 if ( (toolbar
!= NULL
) != (m_frameToolBar
!= NULL
) )
591 // the toolbar visibility must have changed so we need to both position
592 // the toolbar itself (if it appeared) and to relayout the frame
593 // contents in any case
597 // we need to assign it to m_frameToolBar for PositionToolBar() to
599 m_frameToolBar
= toolbar
;
602 //else: tricky: do not reset m_frameToolBar yet as otherwise DoLayout()
603 // wouldn't recognize the (still existing) toolbar as one of our
604 // bars and wouldn't layout the single child of the frame correctly
607 // and this is even more tricky: we want DoLayout() to recognize the
608 // old toolbar for the purpose of not counting it among our non-bar
609 // children but we don't want to reserve any more space for it so we
610 // temporarily hide it
611 if ( m_frameToolBar
)
612 m_frameToolBar
->Hide();
616 if ( m_frameToolBar
)
617 m_frameToolBar
->Show();
620 // this might have been already done above but it's simpler to just always
621 // do it unconditionally instead of testing for whether we already did it
622 m_frameToolBar
= toolbar
;
625 #endif // wxUSE_TOOLBAR
627 // ----------------------------------------------------------------------------
629 // ----------------------------------------------------------------------------
634 void wxFrameBase::DoMenuUpdates(wxMenu
* menu
)
638 wxEvtHandler
* source
= GetEventHandler();
639 menu
->UpdateUI(source
);
643 wxMenuBar
* bar
= GetMenuBar();
649 void wxFrameBase::DetachMenuBar()
651 if ( m_frameMenuBar
)
653 m_frameMenuBar
->Detach();
654 m_frameMenuBar
= NULL
;
658 void wxFrameBase::AttachMenuBar(wxMenuBar
*menubar
)
662 menubar
->Attach((wxFrame
*)this);
663 m_frameMenuBar
= menubar
;
667 void wxFrameBase::SetMenuBar(wxMenuBar
*menubar
)
669 if ( menubar
== GetMenuBar() )
677 this->AttachMenuBar(menubar
);
680 wxMenuItem
*wxFrameBase::FindItemInMenuBar(int menuId
) const
682 const wxMenuBar
* const menuBar
= GetMenuBar();
684 return menuBar
? menuBar
->FindItem(menuId
) : NULL
;
687 #endif // wxUSE_MENUS