]> git.saurik.com Git - wxWidgets.git/blob - src/common/framecmn.cpp
1b8448f0adf27772a2e35dd7320563c0de5ba531
[wxWidgets.git] / src / common / framecmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
20 #pragma implementation "framebase.h"
21 #endif
22
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29
30 #ifndef WX_PRECOMP
31 #include "wx/frame.h"
32 #include "wx/menu.h"
33 #include "wx/menuitem.h"
34 #include "wx/dcclient.h"
35 #endif // WX_PRECOMP
36
37 #if wxUSE_TOOLBAR
38 #include "wx/toolbar.h"
39 #endif
40 #if wxUSE_STATUSBAR
41 #include "wx/statusbr.h"
42 #endif
43
44 // ----------------------------------------------------------------------------
45 // event table
46 // ----------------------------------------------------------------------------
47
48 #if wxUSE_MENUS && wxUSE_STATUSBAR
49
50 BEGIN_EVENT_TABLE(wxFrameBase, wxTopLevelWindow)
51 EVT_MENU_OPEN(wxFrameBase::OnMenuOpen)
52 EVT_MENU_CLOSE(wxFrameBase::OnMenuClose)
53
54 EVT_MENU_HIGHLIGHT_ALL(wxFrameBase::OnMenuHighlight)
55 END_EVENT_TABLE()
56
57 #endif // wxUSE_MENUS && wxUSE_STATUSBAR
58
59 // ============================================================================
60 // implementation
61 // ============================================================================
62
63 // ----------------------------------------------------------------------------
64 // construction/destruction
65 // ----------------------------------------------------------------------------
66
67 wxFrameBase::wxFrameBase()
68 {
69 #if wxUSE_MENUS
70 m_frameMenuBar = NULL;
71 #endif // wxUSE_MENUS
72
73 #if wxUSE_TOOLBAR
74 m_frameToolBar = NULL;
75 #endif // wxUSE_TOOLBAR
76
77 #if wxUSE_STATUSBAR
78 m_frameStatusBar = NULL;
79 #endif // wxUSE_STATUSBAR
80
81 m_statusBarPane = 0;
82 }
83
84 wxFrameBase::~wxFrameBase()
85 {
86 // this destructor is required for Darwin
87 }
88
89 wxFrame *wxFrameBase::New(wxWindow *parent,
90 wxWindowID id,
91 const wxString& title,
92 const wxPoint& pos,
93 const wxSize& size,
94 long style,
95 const wxString& name)
96 {
97 return new wxFrame(parent, id, title, pos, size, style, name);
98 }
99
100 void wxFrameBase::DeleteAllBars()
101 {
102 #if wxUSE_MENUS
103 if ( m_frameMenuBar )
104 {
105 delete m_frameMenuBar;
106 m_frameMenuBar = (wxMenuBar *) NULL;
107 }
108 #endif // wxUSE_MENUS
109
110 #if wxUSE_STATUSBAR
111 if ( m_frameStatusBar )
112 {
113 delete m_frameStatusBar;
114 m_frameStatusBar = (wxStatusBar *) NULL;
115 }
116 #endif // wxUSE_STATUSBAR
117
118 #if wxUSE_TOOLBAR
119 if ( m_frameToolBar )
120 {
121 delete m_frameToolBar;
122 m_frameToolBar = (wxToolBar *) NULL;
123 }
124 #endif // wxUSE_TOOLBAR
125 }
126
127 bool wxFrameBase::IsOneOfBars(const wxWindow *win) const
128 {
129 #if wxUSE_MENUS
130 if ( win == GetMenuBar() )
131 return true;
132 #endif // wxUSE_MENUS
133
134 #if wxUSE_STATUSBAR
135 if ( win == GetStatusBar() )
136 return true;
137 #endif // wxUSE_STATUSBAR
138
139 #if wxUSE_TOOLBAR
140 if ( win == GetToolBar() )
141 return true;
142 #endif // wxUSE_TOOLBAR
143
144 return false;
145 }
146
147 // ----------------------------------------------------------------------------
148 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
149 // from the client area, so the client area is what's really available for the
150 // frame contents
151 // ----------------------------------------------------------------------------
152
153 // get the origin of the client area in the client coordinates
154 wxPoint wxFrameBase::GetClientAreaOrigin() const
155 {
156 wxPoint pt = wxTopLevelWindow::GetClientAreaOrigin();
157
158 #if wxUSE_TOOLBAR && !defined(__WXUNIVERSAL__) && \
159 (!defined(__WXWINCE__) || (_WIN32_WCE >= 400 && !defined(WIN32_PLATFORM_PSPC) && !defined(WIN32_PLATFORM_WFSP)))
160 wxToolBar *toolbar = GetToolBar();
161 if ( toolbar && toolbar->IsShown() )
162 {
163 int w, h;
164 toolbar->GetSize(&w, &h);
165
166 if ( toolbar->GetWindowStyleFlag() & wxTB_VERTICAL )
167 {
168 pt.x += w;
169 }
170 else
171 {
172 pt.y += h;
173 }
174 }
175 #endif // wxUSE_TOOLBAR
176
177 #if defined(__WXWINCE__) && defined(WCE_PLATFORM_STANDARDSDK)
178 if (GetMenuBar() && GetMenuBar()->GetCommandBar())
179 {
180 RECT rect;
181 ::GetWindowRect((HWND) GetMenuBar()->GetCommandBar(), &rect);
182 pt.y += (rect.bottom - rect.top);
183 }
184 #endif
185
186 return pt;
187 }
188
189 // ----------------------------------------------------------------------------
190 // misc
191 // ----------------------------------------------------------------------------
192
193 bool wxFrameBase::ProcessCommand(int id)
194 {
195 #if wxUSE_MENUS
196 wxMenuBar *bar = GetMenuBar();
197 if ( !bar )
198 return false;
199
200 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
201 commandEvent.SetEventObject(this);
202
203 wxMenuItem *item = bar->FindItem(id);
204 if (item)
205 {
206 if (!item->IsEnabled())
207 return true;
208
209 if (item->IsCheckable())
210 {
211 item->Toggle();
212
213 // use the new value
214 commandEvent.SetInt(item->IsChecked());
215 }
216 }
217
218 GetEventHandler()->ProcessEvent(commandEvent);
219 return true;
220 #else // !wxUSE_MENUS
221 return false;
222 #endif // wxUSE_MENUS/!wxUSE_MENUS
223 }
224
225 // Do the UI update processing for this window. This is
226 // provided for the application to call if it wants to
227 // force a UI update, particularly for the menus and toolbar.
228 void wxFrameBase::UpdateWindowUI(long flags)
229 {
230 wxWindowBase::UpdateWindowUI(flags);
231
232 #if wxUSE_TOOLBAR
233 if (GetToolBar())
234 GetToolBar()->UpdateWindowUI(flags);
235 #endif
236
237 #if wxUSE_MENUS
238 if (GetMenuBar())
239 {
240 if ((flags & wxUPDATE_UI_FROMIDLE) && !wxUSE_IDLEMENUUPDATES)
241 {
242 // If coming from an idle event, we only
243 // want to update the menus if we're
244 // in the wxUSE_IDLEMENUUPDATES configuration:
245 // so if we're not, do nothing
246 }
247 else
248 DoMenuUpdates();
249 }
250 #endif // wxUSE_MENUS
251 }
252
253 // ----------------------------------------------------------------------------
254 // event handlers for status bar updates from menus
255 // ----------------------------------------------------------------------------
256
257 #if wxUSE_MENUS && wxUSE_STATUSBAR
258
259 void wxFrameBase::OnMenuHighlight(wxMenuEvent& event)
260 {
261 #if wxUSE_STATUSBAR
262 (void)ShowMenuHelp(GetStatusBar(), event.GetMenuId());
263 #endif // wxUSE_STATUSBAR
264 }
265
266 #if !wxUSE_IDLEMENUUPDATES
267 void wxFrameBase::OnMenuOpen(wxMenuEvent& event)
268 #else
269 void wxFrameBase::OnMenuOpen(wxMenuEvent& WXUNUSED(event))
270 #endif
271 {
272 #if !wxUSE_IDLEMENUUPDATES
273 DoMenuUpdates(event.GetMenu());
274 #endif // !wxUSE_IDLEMENUUPDATES
275 }
276
277 void wxFrameBase::OnMenuClose(wxMenuEvent& WXUNUSED(event))
278 {
279 // do we have real status text to restore?
280 if ( m_oldStatusText.length() > 1 || m_oldStatusText[0u] )
281 {
282 if ( m_statusBarPane >= 0 )
283 {
284 wxStatusBar *statbar = GetStatusBar();
285 if ( statbar )
286 statbar->SetStatusText(m_oldStatusText, m_statusBarPane);
287 }
288
289 m_oldStatusText.clear();
290 }
291 }
292
293 #endif // wxUSE_MENUS && wxUSE_STATUSBAR
294
295 // Implement internal behaviour (menu updating on some platforms)
296 void wxFrameBase::OnInternalIdle()
297 {
298 wxTopLevelWindow::OnInternalIdle();
299
300 #if wxUSE_MENUS && wxUSE_IDLEMENUUPDATES
301 if (wxUpdateUIEvent::CanUpdate(this))
302 DoMenuUpdates();
303 #endif
304 }
305
306 // ----------------------------------------------------------------------------
307 // status bar stuff
308 // ----------------------------------------------------------------------------
309
310 #if wxUSE_STATUSBAR
311
312 wxStatusBar* wxFrameBase::CreateStatusBar(int number,
313 long style,
314 wxWindowID id,
315 const wxString& name)
316 {
317 // the main status bar can only be created once (or else it should be
318 // deleted before calling CreateStatusBar() again)
319 wxCHECK_MSG( !m_frameStatusBar, (wxStatusBar *)NULL,
320 wxT("recreating status bar in wxFrame") );
321
322 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
323 if ( m_frameStatusBar )
324 PositionStatusBar();
325
326 return m_frameStatusBar;
327 }
328
329 wxStatusBar *wxFrameBase::OnCreateStatusBar(int number,
330 long style,
331 wxWindowID id,
332 const wxString& name)
333 {
334 wxStatusBar *statusBar = new wxStatusBar(this, id, style, name);
335
336 statusBar->SetFieldsCount(number);
337
338 return statusBar;
339 }
340
341 void wxFrameBase::SetStatusText(const wxString& text, int number)
342 {
343 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
344
345 m_frameStatusBar->SetStatusText(text, number);
346 }
347
348 void wxFrameBase::SetStatusWidths(int n, const int widths_field[] )
349 {
350 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set widths for") );
351
352 m_frameStatusBar->SetStatusWidths(n, widths_field);
353
354 PositionStatusBar();
355 }
356
357 void wxFrameBase::PushStatusText(const wxString& text, int number)
358 {
359 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
360
361 m_frameStatusBar->PushStatusText(text, number);
362 }
363
364 void wxFrameBase::PopStatusText(int number)
365 {
366 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
367
368 m_frameStatusBar->PopStatusText(number);
369 }
370
371 bool wxFrameBase::ShowMenuHelp(wxStatusBar *WXUNUSED(statbar), int menuId)
372 {
373 #if wxUSE_MENUS
374 // if no help string found, we will clear the status bar text
375 wxString helpString;
376 bool show = menuId != wxID_SEPARATOR && menuId != -2 /* wxID_TITLE */;
377
378 if ( show )
379 {
380 wxMenuBar *menuBar = GetMenuBar();
381 if ( menuBar )
382 {
383 // it's ok if we don't find the item because it might belong
384 // to the popup menu
385 wxMenuItem *item = menuBar->FindItem(menuId);
386 if ( item )
387 helpString = item->GetHelp();
388 }
389 }
390
391 DoGiveHelp(helpString, show);
392
393 return !helpString.IsEmpty();
394 #else // !wxUSE_MENUS
395 return false;
396 #endif // wxUSE_MENUS/!wxUSE_MENUS
397 }
398
399 #endif // wxUSE_STATUSBAR
400
401 void wxFrameBase::DoGiveHelp(const wxString& text, bool show)
402 {
403 #if wxUSE_STATUSBAR
404 if ( m_statusBarPane < 0 )
405 {
406 // status bar messages disabled
407 return;
408 }
409
410 wxStatusBar *statbar = GetStatusBar();
411 if ( !statbar )
412 return;
413
414 wxString help;
415 if ( show )
416 help = text;
417
418 // remember the old status bar text if this is the first time we're called
419 // since the menu has been opened as we're going to overwrite it in our
420 // DoGiveHelp() and we want to restore it when the menu is closed
421 //
422 // note that it would be logical to do this in OnMenuOpen() but under MSW
423 // we get an EVT_MENU_HIGHLIGHT before EVT_MENU_OPEN, strangely enough, and
424 // so this doesn't work and instead we use the ugly trick with using
425 // special m_oldStatusText value as "menu opened" (but it is arguably
426 // better than adding yet another member variable to wxFrame on all
427 // platforms)
428 if ( m_oldStatusText.empty() )
429 {
430 m_oldStatusText = statbar->GetStatusText(m_statusBarPane);
431 if ( m_oldStatusText.empty() )
432 {
433 // use special value to prevent us from doing this the next time
434 m_oldStatusText += _T('\0');
435 }
436 }
437
438 statbar->SetStatusText(help, m_statusBarPane);
439 #endif // wxUSE_STATUSBAR
440 }
441
442
443 // ----------------------------------------------------------------------------
444 // toolbar stuff
445 // ----------------------------------------------------------------------------
446
447 #if wxUSE_TOOLBAR
448
449 wxToolBar* wxFrameBase::CreateToolBar(long style,
450 wxWindowID id,
451 const wxString& name)
452 {
453 // the main toolbar can't be recreated (unless it was explicitly deeleted
454 // before)
455 wxCHECK_MSG( !m_frameToolBar, (wxToolBar *)NULL,
456 wxT("recreating toolbar in wxFrame") );
457
458 if ( style == -1 )
459 {
460 // use default style
461 //
462 // NB: we don't specify the default value in the method declaration
463 // because
464 // a) this allows us to have different defaults for different
465 // platforms (even if we don't have them right now)
466 // b) we don't need to include wx/toolbar.h in the header then
467 style = wxBORDER_NONE | wxTB_HORIZONTAL | wxTB_FLAT;
468 }
469
470 m_frameToolBar = OnCreateToolBar(style, id, name);
471
472 return m_frameToolBar;
473 }
474
475 wxToolBar* wxFrameBase::OnCreateToolBar(long style,
476 wxWindowID id,
477 const wxString& name)
478 {
479 return new wxToolBar(this, id,
480 wxDefaultPosition, wxDefaultSize,
481 style, name);
482 }
483
484 #endif // wxUSE_TOOLBAR
485
486 // ----------------------------------------------------------------------------
487 // menus
488 // ----------------------------------------------------------------------------
489
490 #if wxUSE_MENUS
491
492 // update all menus
493 void wxFrameBase::DoMenuUpdates(wxMenu* menu)
494 {
495 wxEvtHandler* source = GetEventHandler();
496 wxMenuBar* bar = GetMenuBar();
497
498 if (menu)
499 menu->UpdateUI(source);
500 else if ( bar != NULL )
501 {
502 int nCount = bar->GetMenuCount();
503 for (int n = 0; n < nCount; n++)
504 bar->GetMenu(n)->UpdateUI(source);
505 }
506 }
507
508 void wxFrameBase::DetachMenuBar()
509 {
510 if ( m_frameMenuBar )
511 {
512 m_frameMenuBar->Detach();
513 m_frameMenuBar = NULL;
514 }
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
526 void wxFrameBase::SetMenuBar(wxMenuBar *menubar)
527 {
528 if ( menubar == GetMenuBar() )
529 {
530 // nothing to do
531 return;
532 }
533
534 DetachMenuBar();
535
536 this->AttachMenuBar(menubar);
537 }
538
539 #endif // wxUSE_MENUS