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