PageRenderTime 45ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/common/framecmn.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 667 lines | 424 code | 127 blank | 116 comment | 64 complexity | 80467c30640e0323dcbea32dcab799ec MD5 | raw file
  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. // declarations
  12. // ============================================================================
  13. // ----------------------------------------------------------------------------
  14. // headers
  15. // ----------------------------------------------------------------------------
  16. // For compilers that support precompilation, includes "wx.h".
  17. #include "wx/wxprec.h"
  18. #ifdef __BORLANDC__
  19. #pragma hdrstop
  20. #endif
  21. #include "wx/frame.h"
  22. #ifndef WX_PRECOMP
  23. #include "wx/menu.h"
  24. #include "wx/menuitem.h"
  25. #include "wx/dcclient.h"
  26. #include "wx/toolbar.h"
  27. #include "wx/statusbr.h"
  28. #endif // WX_PRECOMP
  29. extern WXDLLEXPORT_DATA(const char) wxFrameNameStr[] = "frame";
  30. extern WXDLLEXPORT_DATA(const char) wxStatusLineNameStr[] = "status_line";
  31. // ----------------------------------------------------------------------------
  32. // event table
  33. // ----------------------------------------------------------------------------
  34. #if wxUSE_MENUS && wxUSE_STATUSBAR
  35. BEGIN_EVENT_TABLE(wxFrameBase, wxTopLevelWindow)
  36. EVT_MENU_OPEN(wxFrameBase::OnMenuOpen)
  37. EVT_MENU_CLOSE(wxFrameBase::OnMenuClose)
  38. EVT_MENU_HIGHLIGHT_ALL(wxFrameBase::OnMenuHighlight)
  39. END_EVENT_TABLE()
  40. #endif // wxUSE_MENUS && wxUSE_STATUSBAR
  41. // ============================================================================
  42. // implementation
  43. // ============================================================================
  44. // ----------------------------------------------------------------------------
  45. // XTI
  46. // ----------------------------------------------------------------------------
  47. wxDEFINE_FLAGS( wxFrameStyle )
  48. wxBEGIN_FLAGS( wxFrameStyle )
  49. // new style border flags, we put them first to
  50. // use them for streaming out
  51. wxFLAGS_MEMBER(wxBORDER_SIMPLE)
  52. wxFLAGS_MEMBER(wxBORDER_SUNKEN)
  53. wxFLAGS_MEMBER(wxBORDER_DOUBLE)
  54. wxFLAGS_MEMBER(wxBORDER_RAISED)
  55. wxFLAGS_MEMBER(wxBORDER_STATIC)
  56. wxFLAGS_MEMBER(wxBORDER_NONE)
  57. // old style border flags
  58. wxFLAGS_MEMBER(wxSIMPLE_BORDER)
  59. wxFLAGS_MEMBER(wxSUNKEN_BORDER)
  60. wxFLAGS_MEMBER(wxDOUBLE_BORDER)
  61. wxFLAGS_MEMBER(wxRAISED_BORDER)
  62. wxFLAGS_MEMBER(wxSTATIC_BORDER)
  63. wxFLAGS_MEMBER(wxBORDER)
  64. // standard window styles
  65. wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
  66. wxFLAGS_MEMBER(wxCLIP_CHILDREN)
  67. wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
  68. wxFLAGS_MEMBER(wxWANTS_CHARS)
  69. wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
  70. wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
  71. wxFLAGS_MEMBER(wxVSCROLL)
  72. wxFLAGS_MEMBER(wxHSCROLL)
  73. // frame styles
  74. wxFLAGS_MEMBER(wxSTAY_ON_TOP)
  75. wxFLAGS_MEMBER(wxCAPTION)
  76. #if WXWIN_COMPATIBILITY_2_6
  77. wxFLAGS_MEMBER(wxTHICK_FRAME)
  78. #endif // WXWIN_COMPATIBILITY_2_6
  79. wxFLAGS_MEMBER(wxSYSTEM_MENU)
  80. wxFLAGS_MEMBER(wxRESIZE_BORDER)
  81. #if WXWIN_COMPATIBILITY_2_6
  82. wxFLAGS_MEMBER(wxRESIZE_BOX)
  83. #endif // WXWIN_COMPATIBILITY_2_6
  84. wxFLAGS_MEMBER(wxCLOSE_BOX)
  85. wxFLAGS_MEMBER(wxMAXIMIZE_BOX)
  86. wxFLAGS_MEMBER(wxMINIMIZE_BOX)
  87. wxFLAGS_MEMBER(wxFRAME_TOOL_WINDOW)
  88. wxFLAGS_MEMBER(wxFRAME_FLOAT_ON_PARENT)
  89. wxFLAGS_MEMBER(wxFRAME_SHAPED)
  90. wxEND_FLAGS( wxFrameStyle )
  91. wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxFrame, wxTopLevelWindow, "wx/frame.h")
  92. wxBEGIN_PROPERTIES_TABLE(wxFrame)
  93. wxEVENT_PROPERTY( Menu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEvent)
  94. wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxString(), 0 /*flags*/, \
  95. wxT("Helpstring"), wxT("group"))
  96. wxPROPERTY_FLAGS( WindowStyle, wxFrameStyle, long, SetWindowStyleFlag, \
  97. GetWindowStyleFlag, wxEMPTY_PARAMETER_VALUE, 0 /*flags*/, \
  98. wxT("Helpstring"), wxT("group")) // style
  99. wxPROPERTY( MenuBar, wxMenuBar *, SetMenuBar, GetMenuBar, wxEMPTY_PARAMETER_VALUE, \
  100. 0 /*flags*/, wxT("Helpstring"), wxT("group"))
  101. wxEND_PROPERTIES_TABLE()
  102. wxEMPTY_HANDLERS_TABLE(wxFrame)
  103. wxCONSTRUCTOR_6( wxFrame, wxWindow*, Parent, wxWindowID, Id, wxString, Title, \
  104. wxPoint, Position, wxSize, Size, long, WindowStyle)
  105. // ----------------------------------------------------------------------------
  106. // construction/destruction
  107. // ----------------------------------------------------------------------------
  108. wxFrameBase::wxFrameBase()
  109. {
  110. #if wxUSE_MENUS
  111. m_frameMenuBar = NULL;
  112. #endif // wxUSE_MENUS
  113. #if wxUSE_TOOLBAR
  114. m_frameToolBar = NULL;
  115. #endif // wxUSE_TOOLBAR
  116. #if wxUSE_STATUSBAR
  117. m_frameStatusBar = NULL;
  118. #endif // wxUSE_STATUSBAR
  119. m_statusBarPane = 0;
  120. }
  121. wxFrameBase::~wxFrameBase()
  122. {
  123. // this destructor is required for Darwin
  124. }
  125. wxFrame *wxFrameBase::New(wxWindow *parent,
  126. wxWindowID id,
  127. const wxString& title,
  128. const wxPoint& pos,
  129. const wxSize& size,
  130. long style,
  131. const wxString& name)
  132. {
  133. return new wxFrame(parent, id, title, pos, size, style, name);
  134. }
  135. void wxFrameBase::DeleteAllBars()
  136. {
  137. #if wxUSE_MENUS
  138. wxDELETE(m_frameMenuBar);
  139. #endif // wxUSE_MENUS
  140. #if wxUSE_STATUSBAR
  141. wxDELETE(m_frameStatusBar);
  142. #endif // wxUSE_STATUSBAR
  143. #if wxUSE_TOOLBAR
  144. wxDELETE(m_frameToolBar);
  145. #endif // wxUSE_TOOLBAR
  146. }
  147. bool wxFrameBase::IsOneOfBars(const wxWindow *win) const
  148. {
  149. #if wxUSE_MENUS
  150. if ( win == GetMenuBar() )
  151. return true;
  152. #endif // wxUSE_MENUS
  153. #if wxUSE_STATUSBAR
  154. if ( win == GetStatusBar() )
  155. return true;
  156. #endif // wxUSE_STATUSBAR
  157. #if wxUSE_TOOLBAR
  158. if ( win == GetToolBar() )
  159. return true;
  160. #endif // wxUSE_TOOLBAR
  161. wxUnusedVar(win);
  162. return false;
  163. }
  164. // ----------------------------------------------------------------------------
  165. // wxFrame size management: we exclude the areas taken by menu/status/toolbars
  166. // from the client area, so the client area is what's really available for the
  167. // frame contents
  168. // ----------------------------------------------------------------------------
  169. // get the origin of the client area in the client coordinates
  170. wxPoint wxFrameBase::GetClientAreaOrigin() const
  171. {
  172. wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
  173. #if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__)
  174. wxToolBar *toolbar = GetToolBar();
  175. if ( toolbar && toolbar->IsShown() )
  176. {
  177. int w, h;
  178. toolbar->GetSize(&w, &h);
  179. if ( toolbar->GetWindowStyleFlag() & wxTB_VERTICAL )
  180. {
  181. pt.x += w;
  182. }
  183. else
  184. {
  185. pt.y += h;
  186. }
  187. }
  188. #endif // wxUSE_TOOLBAR
  189. return pt;
  190. }
  191. // ----------------------------------------------------------------------------
  192. // misc
  193. // ----------------------------------------------------------------------------
  194. #if wxUSE_MENUS
  195. bool wxFrameBase::ProcessCommand(int id)
  196. {
  197. wxMenuBar *bar = GetMenuBar();
  198. if ( !bar )
  199. return false;
  200. wxMenuItem *item = bar->FindItem(id);
  201. if ( !item )
  202. return false;
  203. return ProcessCommand(item);
  204. }
  205. bool wxFrameBase::ProcessCommand(wxMenuItem *item)
  206. {
  207. wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, item->GetId());
  208. commandEvent.SetEventObject(this);
  209. if (!item->IsEnabled())
  210. return true;
  211. if ((item->GetKind() == wxITEM_RADIO) && item->IsChecked() )
  212. return true;
  213. if (item->IsCheckable())
  214. {
  215. item->Toggle();
  216. // use the new value
  217. commandEvent.SetInt(item->IsChecked());
  218. }
  219. return HandleWindowEvent(commandEvent);
  220. }
  221. #endif // wxUSE_MENUS
  222. // Do the UI update processing for this window. This is
  223. // provided for the application to call if it wants to
  224. // force a UI update, particularly for the menus and toolbar.
  225. void wxFrameBase::UpdateWindowUI(long flags)
  226. {
  227. wxWindowBase::UpdateWindowUI(flags);
  228. #if wxUSE_TOOLBAR
  229. if (GetToolBar())
  230. GetToolBar()->UpdateWindowUI(flags);
  231. #endif
  232. #if wxUSE_MENUS
  233. if (GetMenuBar())
  234. {
  235. // If coming from an idle event, we only want to update the menus if
  236. // we're in the wxUSE_IDLEMENUUPDATES configuration, otherwise they
  237. // will be update when the menu is opened later
  238. #if !wxUSE_IDLEMENUUPDATES
  239. if ( !(flags & wxUPDATE_UI_FROMIDLE) )
  240. #endif // wxUSE_IDLEMENUUPDATES
  241. DoMenuUpdates();
  242. }
  243. #endif // wxUSE_MENUS
  244. }
  245. // ----------------------------------------------------------------------------
  246. // event handlers for status bar updates from menus
  247. // ----------------------------------------------------------------------------
  248. #if wxUSE_MENUS && wxUSE_STATUSBAR
  249. void wxFrameBase::OnMenuHighlight(wxMenuEvent& event)
  250. {
  251. #if wxUSE_STATUSBAR
  252. (void)ShowMenuHelp(event.GetMenuId());
  253. #endif // wxUSE_STATUSBAR
  254. }
  255. void wxFrameBase::OnMenuOpen(wxMenuEvent& event)
  256. {
  257. #if wxUSE_IDLEMENUUPDATES
  258. wxUnusedVar(event);
  259. #else // !wxUSE_IDLEMENUUPDATES
  260. // as we didn't update the menus from idle time, do it now
  261. DoMenuUpdates(event.GetMenu());
  262. #endif // wxUSE_IDLEMENUUPDATES/!wxUSE_IDLEMENUUPDATES
  263. }
  264. void wxFrameBase::OnMenuClose(wxMenuEvent& WXUNUSED(event))
  265. {
  266. DoGiveHelp(wxEmptyString, false);
  267. }
  268. #endif // wxUSE_MENUS && wxUSE_STATUSBAR
  269. // Implement internal behaviour (menu updating on some platforms)
  270. void wxFrameBase::OnInternalIdle()
  271. {
  272. wxTopLevelWindow::OnInternalIdle();
  273. #if wxUSE_MENUS && wxUSE_IDLEMENUUPDATES
  274. if (wxUpdateUIEvent::CanUpdate(this))
  275. DoMenuUpdates();
  276. #endif
  277. }
  278. // ----------------------------------------------------------------------------
  279. // status bar stuff
  280. // ----------------------------------------------------------------------------
  281. #if wxUSE_STATUSBAR
  282. wxStatusBar* wxFrameBase::CreateStatusBar(int number,
  283. long style,
  284. wxWindowID id,
  285. const wxString& name)
  286. {
  287. // the main status bar can only be created once (or else it should be
  288. // deleted before calling CreateStatusBar() again)
  289. wxCHECK_MSG( !m_frameStatusBar, NULL,
  290. wxT("recreating status bar in wxFrame") );
  291. SetStatusBar(OnCreateStatusBar(number, style, id, name));
  292. return m_frameStatusBar;
  293. }
  294. wxStatusBar *wxFrameBase::OnCreateStatusBar(int number,
  295. long style,
  296. wxWindowID id,
  297. const wxString& name)
  298. {
  299. wxStatusBar *statusBar = new wxStatusBar(this, id, style, name);
  300. statusBar->SetFieldsCount(number);
  301. return statusBar;
  302. }
  303. void wxFrameBase::SetStatusText(const wxString& text, int number)
  304. {
  305. wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
  306. m_frameStatusBar->SetStatusText(text, number);
  307. }
  308. void wxFrameBase::SetStatusWidths(int n, const int widths_field[] )
  309. {
  310. wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set widths for") );
  311. m_frameStatusBar->SetStatusWidths(n, widths_field);
  312. PositionStatusBar();
  313. }
  314. void wxFrameBase::PushStatusText(const wxString& text, int number)
  315. {
  316. wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
  317. m_frameStatusBar->PushStatusText(text, number);
  318. }
  319. void wxFrameBase::PopStatusText(int number)
  320. {
  321. wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
  322. m_frameStatusBar->PopStatusText(number);
  323. }
  324. bool wxFrameBase::ShowMenuHelp(int menuId)
  325. {
  326. #if wxUSE_MENUS
  327. // if no help string found, we will clear the status bar text
  328. //
  329. // NB: wxID_NONE is used for (sub)menus themselves by wxMSW
  330. wxString helpString;
  331. if ( menuId != wxID_SEPARATOR && menuId != wxID_NONE )
  332. {
  333. const wxMenuItem * const item = FindItemInMenuBar(menuId);
  334. if ( item && !item->IsSeparator() )
  335. helpString = item->GetHelp();
  336. // notice that it's ok if we don't find the item because it might
  337. // belong to the popup menu, so don't assert here
  338. }
  339. DoGiveHelp(helpString, true);
  340. return !helpString.empty();
  341. #else // !wxUSE_MENUS
  342. return false;
  343. #endif // wxUSE_MENUS/!wxUSE_MENUS
  344. }
  345. void wxFrameBase::SetStatusBar(wxStatusBar *statBar)
  346. {
  347. bool hadBar = m_frameStatusBar != NULL;
  348. m_frameStatusBar = statBar;
  349. if ( (m_frameStatusBar != NULL) != hadBar )
  350. {
  351. PositionStatusBar();
  352. DoLayout();
  353. }
  354. }
  355. #endif // wxUSE_STATUSBAR
  356. #if wxUSE_MENUS || wxUSE_TOOLBAR
  357. void wxFrameBase::DoGiveHelp(const wxString& help, bool show)
  358. {
  359. #if wxUSE_STATUSBAR
  360. if ( m_statusBarPane < 0 )
  361. {
  362. // status bar messages disabled
  363. return;
  364. }
  365. wxStatusBar *statbar = GetStatusBar();
  366. if ( !statbar )
  367. return;
  368. wxString text;
  369. if ( show )
  370. {
  371. // remember the old status bar text if this is the first time we're
  372. // called since the menu has been opened as we're going to overwrite it
  373. // in our DoGiveHelp() and we want to restore it when the menu is
  374. // closed
  375. //
  376. // note that it would be logical to do this in OnMenuOpen() but under
  377. // MSW we get an EVT_MENU_HIGHLIGHT before EVT_MENU_OPEN, strangely
  378. // enough, and so this doesn't work and instead we use the ugly trick
  379. // with using special m_oldStatusText value as "menu opened" (but it is
  380. // arguably better than adding yet another member variable to wxFrame
  381. // on all platforms)
  382. if ( m_oldStatusText.empty() )
  383. {
  384. m_oldStatusText = statbar->GetStatusText(m_statusBarPane);
  385. if ( m_oldStatusText.empty() )
  386. {
  387. // use special value to prevent us from doing this the next time
  388. m_oldStatusText += wxT('\0');
  389. }
  390. }
  391. m_lastHelpShown =
  392. text = help;
  393. }
  394. else // hide help, restore the original text
  395. {
  396. // clear the last shown help string but remember its value
  397. wxString lastHelpShown;
  398. lastHelpShown.swap(m_lastHelpShown);
  399. // also clear the old status text but remember it too to restore it
  400. // below
  401. text.swap(m_oldStatusText);
  402. if ( statbar->GetStatusText(m_statusBarPane) != lastHelpShown )
  403. {
  404. // if the text was changed with an explicit SetStatusText() call
  405. // from the user code in the meanwhile, do not overwrite it with
  406. // the old status bar contents -- this is almost certainly not what
  407. // the user expects and would be very hard to avoid from user code
  408. return;
  409. }
  410. }
  411. statbar->SetStatusText(text, m_statusBarPane);
  412. #else
  413. wxUnusedVar(help);
  414. wxUnusedVar(show);
  415. #endif // wxUSE_STATUSBAR
  416. }
  417. #endif // wxUSE_MENUS || wxUSE_TOOLBAR
  418. // ----------------------------------------------------------------------------
  419. // toolbar stuff
  420. // ----------------------------------------------------------------------------
  421. #if wxUSE_TOOLBAR
  422. wxToolBar* wxFrameBase::CreateToolBar(long style,
  423. wxWindowID id,
  424. const wxString& name)
  425. {
  426. // the main toolbar can't be recreated (unless it was explicitly deleted
  427. // before)
  428. wxCHECK_MSG( !m_frameToolBar, NULL,
  429. wxT("recreating toolbar in wxFrame") );
  430. if ( style == -1 )
  431. {
  432. // use default style
  433. //
  434. // NB: we don't specify the default value in the method declaration
  435. // because
  436. // a) this allows us to have different defaults for different
  437. // platforms (even if we don't have them right now)
  438. // b) we don't need to include wx/toolbar.h in the header then
  439. style = wxBORDER_NONE | wxTB_HORIZONTAL | wxTB_FLAT;
  440. }
  441. SetToolBar(OnCreateToolBar(style, id, name));
  442. return m_frameToolBar;
  443. }
  444. wxToolBar* wxFrameBase::OnCreateToolBar(long style,
  445. wxWindowID id,
  446. const wxString& name)
  447. {
  448. #if defined(__WXWINCE__) && defined(__POCKETPC__)
  449. return new wxToolMenuBar(this, id,
  450. wxDefaultPosition, wxDefaultSize,
  451. style, name);
  452. #else
  453. return new wxToolBar(this, id,
  454. wxDefaultPosition, wxDefaultSize,
  455. style, name);
  456. #endif
  457. }
  458. void wxFrameBase::SetToolBar(wxToolBar *toolbar)
  459. {
  460. if ( (toolbar != NULL) != (m_frameToolBar != NULL) )
  461. {
  462. // the toolbar visibility must have changed so we need to both position
  463. // the toolbar itself (if it appeared) and to relayout the frame
  464. // contents in any case
  465. if ( toolbar )
  466. {
  467. // we need to assign it to m_frameToolBar for PositionToolBar() to
  468. // do anything
  469. m_frameToolBar = toolbar;
  470. PositionToolBar();
  471. }
  472. //else: tricky: do not reset m_frameToolBar yet as otherwise DoLayout()
  473. // wouldn't recognize the (still existing) toolbar as one of our
  474. // bars and wouldn't layout the single child of the frame correctly
  475. // and this is even more tricky: we want DoLayout() to recognize the
  476. // old toolbar for the purpose of not counting it among our non-bar
  477. // children but we don't want to reserve any more space for it so we
  478. // temporarily hide it
  479. if ( m_frameToolBar )
  480. m_frameToolBar->Hide();
  481. DoLayout();
  482. if ( m_frameToolBar )
  483. m_frameToolBar->Show();
  484. }
  485. // this might have been already done above but it's simpler to just always
  486. // do it unconditionally instead of testing for whether we already did it
  487. m_frameToolBar = toolbar;
  488. }
  489. #endif // wxUSE_TOOLBAR
  490. // ----------------------------------------------------------------------------
  491. // menus
  492. // ----------------------------------------------------------------------------
  493. #if wxUSE_MENUS
  494. // update all menus
  495. void wxFrameBase::DoMenuUpdates(wxMenu* menu)
  496. {
  497. if (menu)
  498. {
  499. wxEvtHandler* source = GetEventHandler();
  500. menu->UpdateUI(source);
  501. }
  502. else
  503. {
  504. wxMenuBar* bar = GetMenuBar();
  505. if (bar != NULL)
  506. bar->UpdateMenus();
  507. }
  508. }
  509. void wxFrameBase::DetachMenuBar()
  510. {
  511. if ( m_frameMenuBar )
  512. {
  513. m_frameMenuBar->Detach();
  514. m_frameMenuBar = NULL;
  515. }
  516. }
  517. void wxFrameBase::AttachMenuBar(wxMenuBar *menubar)
  518. {
  519. if ( menubar )
  520. {
  521. menubar->Attach((wxFrame *)this);
  522. m_frameMenuBar = menubar;
  523. }
  524. }
  525. void wxFrameBase::SetMenuBar(wxMenuBar *menubar)
  526. {
  527. if ( menubar == GetMenuBar() )
  528. {
  529. // nothing to do
  530. return;
  531. }
  532. DetachMenuBar();
  533. this->AttachMenuBar(menubar);
  534. }
  535. wxMenuItem *wxFrameBase::FindItemInMenuBar(int menuId) const
  536. {
  537. const wxMenuBar * const menuBar = GetMenuBar();
  538. return menuBar ? menuBar->FindItem(menuId) : NULL;
  539. }
  540. #endif // wxUSE_MENUS