]> git.saurik.com Git - wxWidgets.git/blame - src/common/framecmn.cpp
changed FindControl to FindControlUnderMouse and use ControlRef != NULL instead of...
[wxWidgets.git] / src / common / framecmn.cpp
CommitLineData
63fec618 1/////////////////////////////////////////////////////////////////////////////
7c0ea335 2// Name: common/framecmn.cpp
63fec618
VZ
3// Purpose: common (for all platforms) wxFrame functions
4// Author: Julian Smart, Vadim Zeitlin
5// Created: 01/02/97
439b3bf1 6// Id: $Id$
63fec618
VZ
7// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
7c0ea335
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19#ifdef __GNUG__
20 #pragma implementation "framebase.h"
21#endif
22
f701d7ab
JS
23// For compilers that support precompilation, includes "wx.h".
24#include "wx/wxprec.h"
25
26#ifdef __BORLANDC__
7c0ea335 27 #pragma hdrstop
f701d7ab
JS
28#endif
29
1e6feb95
VZ
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
7c0ea335
VZ
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
48BEGIN_EVENT_TABLE(wxFrameBase, wxWindow)
49 EVT_IDLE(wxFrameBase::OnIdle)
50 EVT_CLOSE(wxFrameBase::OnCloseWindow)
51 EVT_MENU_HIGHLIGHT_ALL(wxFrameBase::OnMenuHighlight)
52 EVT_SIZE(wxFrameBase::OnSize)
53END_EVENT_TABLE()
54
55// ============================================================================
56// implementation
57// ============================================================================
58
59// ----------------------------------------------------------------------------
60// construction/destruction
61// ----------------------------------------------------------------------------
62
63wxFrameBase::wxFrameBase()
64{
1e6feb95 65#if wxUSE_MENUS
7c0ea335 66 m_frameMenuBar = NULL;
1e6feb95 67#endif // wxUSE_MENUS
7c0ea335
VZ
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
78bool wxFrameBase::Destroy()
79{
80 // delayed destruction: the frame will be deleted during the next idle
81 // loop iteration
82 if ( !wxPendingDelete.Member(this) )
83 wxPendingDelete.Append(this);
84
85 return TRUE;
86}
87
88wxFrame *wxFrameBase::New(wxWindow *parent,
89 wxWindowID id,
90 const wxString& title,
91 const wxPoint& pos,
92 const wxSize& size,
93 long style,
94 const wxString& name)
95{
96 return new wxFrame(parent, id, title, pos, size, style, name);
97}
98
99void wxFrameBase::DeleteAllBars()
100{
1e6feb95 101#if wxUSE_MENUS
7c0ea335
VZ
102 if ( m_frameMenuBar )
103 {
104 delete m_frameMenuBar;
105 m_frameMenuBar = (wxMenuBar *) NULL;
106 }
1e6feb95 107#endif // wxUSE_MENUS
7c0ea335
VZ
108
109#if wxUSE_STATUSBAR
110 if ( m_frameStatusBar )
111 {
112 delete m_frameStatusBar;
113 m_frameStatusBar = (wxStatusBar *) NULL;
114 }
115#endif // wxUSE_STATUSBAR
116
117#if wxUSE_TOOLBAR
118 if ( m_frameToolBar )
119 {
120 delete m_frameToolBar;
121 m_frameToolBar = (wxToolBar *) NULL;
122 }
123#endif // wxUSE_TOOLBAR
124}
125
1e6feb95
VZ
126bool wxFrameBase::IsOneOfBars(const wxWindow *win) const
127{
128#if wxUSE_MENUS
129 if ( win == GetMenuBar() )
130 return TRUE;
131#endif // wxUSE_MENUS
132
133#if wxUSE_STATUSBAR
134 if ( win == GetStatusBar() )
135 return TRUE;
136#endif // wxUSE_STATUSBAR
137
138#if wxUSE_TOOLBAR
139 if ( win == GetToolBar() )
140 return TRUE;
141#endif // wxUSE_TOOLBAR
142
143 return FALSE;
144}
145
1c4f8f8d
VZ
146// ----------------------------------------------------------------------------
147// wxFrame size management: we exclude the areas taken by menu/status/toolbars
148// from the client area, so the client area is what's really available for the
149// frame contents
150// ----------------------------------------------------------------------------
151
152// get the origin of the client area in the client coordinates
153wxPoint wxFrameBase::GetClientAreaOrigin() const
154{
155 wxPoint pt(0, 0);
156
157#if wxUSE_TOOLBAR
3e0b743f 158 if ( GetToolBar() && GetToolBar()->IsShown() )
1c4f8f8d
VZ
159 {
160 int w, h;
161 GetToolBar()->GetSize(& w, & h);
162
163 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
164 {
165 pt.x += w;
166 }
167 else
168 {
169 pt.y += h;
170 }
171 }
172#endif // wxUSE_TOOLBAR
173
174 return pt;
175}
176
177void wxFrameBase::DoScreenToClient(int *x, int *y) const
178{
179 wxWindow::DoScreenToClient(x, y);
180
181 // We may be faking the client origin.
182 // So a window that's really at (0, 30) may appear
183 // (to wxWin apps) to be at (0, 0).
184 wxPoint pt(GetClientAreaOrigin());
185 *x -= pt.x;
186 *y -= pt.y;
187}
188
189void wxFrameBase::DoClientToScreen(int *x, int *y) const
190{
191 // We may be faking the client origin.
192 // So a window that's really at (0, 30) may appear
193 // (to wxWin apps) to be at (0, 0).
194 wxPoint pt1(GetClientAreaOrigin());
195 *x += pt1.x;
196 *y += pt1.y;
197
198 wxWindow::DoClientToScreen(x, y);
199}
200
7c0ea335
VZ
201// ----------------------------------------------------------------------------
202// misc
203// ----------------------------------------------------------------------------
204
205// make the window modal (all other windows unresponsive)
206void wxFrameBase::MakeModal(bool modal)
207{
208 if ( modal )
209 {
210 wxEnableTopLevelWindows(FALSE);
211 Enable(TRUE); // keep this window enabled
212 }
213 else
214 {
215 wxEnableTopLevelWindows(TRUE);
216 }
217}
218
219bool wxFrameBase::ProcessCommand(int id)
220{
1e6feb95 221#if wxUSE_MENUS
7c0ea335
VZ
222 wxMenuBar *bar = GetMenuBar();
223 if ( !bar )
224 return FALSE;
225
3ca6a5f0
BP
226 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
227 commandEvent.SetEventObject(this);
228
7c0ea335
VZ
229 wxMenuItem *item = bar->FindItem(id);
230 if ( item && item->IsCheckable() )
231 {
232 item->Toggle();
7c0ea335 233
3ca6a5f0
BP
234 // use the new value
235 commandEvent.SetInt(item->IsChecked());
236 }
7c0ea335
VZ
237
238 return GetEventHandler()->ProcessEvent(commandEvent);
1e6feb95
VZ
239#else // !wxUSE_MENUS
240 return FALSE;
241#endif // wxUSE_MENUS/!wxUSE_MENUS
7c0ea335
VZ
242}
243
244// ----------------------------------------------------------------------------
245// event handlers
246// ----------------------------------------------------------------------------
247
248// default resizing behaviour - if only ONE subwindow, resize to fill the
249// whole client area
3ed2e7ce 250void wxFrameBase::OnSize(wxSizeEvent& WXUNUSED(event))
7c0ea335
VZ
251{
252 // if we're using constraints - do use them
253#if wxUSE_CONSTRAINTS
254 if ( GetAutoLayout() )
255 {
256 Layout();
257 }
258 else
1e6feb95 259#endif // wxUSE_CONSTRAINTS
7c0ea335
VZ
260 {
261 // do we have _exactly_ one child?
262 wxWindow *child = (wxWindow *)NULL;
263 for ( wxWindowList::Node *node = GetChildren().GetFirst();
264 node;
265 node = node->GetNext() )
266 {
267 wxWindow *win = node->GetData();
268
269 // exclude top level and managed windows (status bar isn't
270 // currently in the children list except under wxMac anyhow, but
271 // it makes no harm to test for it)
1e6feb95 272 if ( !win->IsTopLevel() && !IsOneOfBars(win) )
7c0ea335
VZ
273 {
274 if ( child )
275 {
276 return; // it's our second subwindow - nothing to do
277 }
278
279 child = win;
280 }
281 }
e6688c3f 282
7c0ea335
VZ
283 // do we have any children at all?
284 if ( child )
285 {
286 // exactly one child - set it's size to fill the whole frame
287 int clientW, clientH;
288 DoGetClientSize(&clientW, &clientH);
289
290 // for whatever reasons, wxGTK wants to have a small offset - it
291 // probably looks better with it?
292#ifdef __WXGTK__
7c0ea335 293 static const int ofs = 1;
405e126c
VZ
294#else
295 static const int ofs = 0;
7c0ea335
VZ
296#endif
297
298 child->SetSize(ofs, ofs, clientW - 2*ofs, clientH - 2*ofs);
299 }
300 }
301}
302
303// The default implementation for the close window event.
3ed2e7ce 304void wxFrameBase::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
7c0ea335
VZ
305{
306 Destroy();
307}
308
309void wxFrameBase::OnMenuHighlight(wxMenuEvent& event)
310{
311#if wxUSE_STATUSBAR
f6bcfd97 312 (void)ShowMenuHelp(GetStatusBar(), event.GetMenuId());
7c0ea335
VZ
313#endif // wxUSE_STATUSBAR
314}
315
3dd9b88a
VZ
316bool wxFrameBase::SendIconizeEvent(bool iconized)
317{
318 wxIconizeEvent event(GetId(), iconized);
319 event.SetEventObject(this);
320
321 return GetEventHandler()->ProcessEvent(event);
322}
323
6522713c
VZ
324void wxFrameBase::OnIdle(wxIdleEvent& WXUNUSED(event) )
325{
326#if wxUSE_MENUS
327 DoMenuUpdates();
328#endif // wxUSE_MENUS
329}
330
7c0ea335
VZ
331// ----------------------------------------------------------------------------
332// status bar stuff
333// ----------------------------------------------------------------------------
334
335#if wxUSE_STATUSBAR
336
337wxStatusBar* wxFrameBase::CreateStatusBar(int number,
338 long style,
339 wxWindowID id,
340 const wxString& name)
341{
342 // the main status bar can only be created once (or else it should be
343 // deleted before calling CreateStatusBar() again)
344 wxCHECK_MSG( !m_frameStatusBar, (wxStatusBar *)NULL,
345 wxT("recreating status bar in wxFrame") );
346
347 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
348 if ( m_frameStatusBar )
349 PositionStatusBar();
350
351 return m_frameStatusBar;
352}
353
354wxStatusBar *wxFrameBase::OnCreateStatusBar(int number,
355 long style,
356 wxWindowID id,
357 const wxString& name)
358{
ed791986 359 wxStatusBar *statusBar = new wxStatusBar(this, id, style, name);
7c0ea335
VZ
360
361 // Set the height according to the font and the border size
362 wxClientDC dc(statusBar);
363 dc.SetFont(statusBar->GetFont());
364
ed791986 365 wxCoord y;
7c0ea335
VZ
366 dc.GetTextExtent( "X", NULL, &y );
367
368 int height = (int)( (11*y)/10 + 2*statusBar->GetBorderY());
369
ed791986 370 statusBar->SetSize( -1, -1, -1, height );
7c0ea335
VZ
371
372 statusBar->SetFieldsCount(number);
373
374 return statusBar;
375}
376
377void wxFrameBase::SetStatusText(const wxString& text, int number)
378{
7c0ea335
VZ
379 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
380
381 m_frameStatusBar->SetStatusText(text, number);
382}
383
384void wxFrameBase::SetStatusWidths(int n, const int widths_field[] )
385{
7c0ea335
VZ
386 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set widths for") );
387
388 m_frameStatusBar->SetStatusWidths(n, widths_field);
389
390 PositionStatusBar();
391}
392
f6bcfd97
BP
393bool wxFrameBase::ShowMenuHelp(wxStatusBar *statbar, int menuId)
394{
3379ed37 395#if wxUSE_MENUS
f6bcfd97
BP
396 if ( !statbar )
397 return FALSE;
398
399 // if no help string found, we will clear the status bar text
400 wxString helpString;
401
402 if ( menuId != wxID_SEPARATOR && menuId != -2 /* wxID_TITLE */ )
403 {
404 wxMenuBar *menuBar = GetMenuBar();
405 if ( menuBar )
406 {
407 // it's ok if we don't find the item because it might belong
408 // to the popup menu
409 wxMenuItem *item = menuBar->FindItem(menuId);
410 if ( item )
411 helpString = item->GetHelp();
412 }
413 }
414
415 // set status text even if the string is empty - this will at least
416 // remove the string from the item which was previously selected
417 statbar->SetStatusText(helpString);
418
419 return !helpString.IsEmpty();
3379ed37
VZ
420#else // !wxUSE_MENUS
421 return FALSE;
422#endif // wxUSE_MENUS/!wxUSE_MENUS
f6bcfd97
BP
423}
424
7c0ea335
VZ
425#endif // wxUSE_STATUSBAR
426
427// ----------------------------------------------------------------------------
428// toolbar stuff
429// ----------------------------------------------------------------------------
430
431#if wxUSE_TOOLBAR
432
433wxToolBar* wxFrameBase::CreateToolBar(long style,
434 wxWindowID id,
435 const wxString& name)
436{
437 // the main toolbar can't be recreated (unless it was explicitly deeleted
438 // before)
439 wxCHECK_MSG( !m_frameToolBar, (wxToolBar *)NULL,
440 wxT("recreating toolbar in wxFrame") );
441
442 m_frameToolBar = OnCreateToolBar(style, id, name);
443
444 return m_frameToolBar;
445}
446
447wxToolBar* wxFrameBase::OnCreateToolBar(long style,
448 wxWindowID id,
449 const wxString& name)
450{
451 return new wxToolBar(this, id,
452 wxDefaultPosition, wxDefaultSize,
453 style, name);
454}
455
456#endif // wxUSE_TOOLBAR
457
458// ----------------------------------------------------------------------------
6522713c 459// menus
7c0ea335
VZ
460// ----------------------------------------------------------------------------
461
1e6feb95
VZ
462#if wxUSE_MENUS
463
63fec618 464// update all menus
7c0ea335 465void wxFrameBase::DoMenuUpdates()
63fec618 466{
54517652 467 wxMenuBar* bar = GetMenuBar();
e702ff0f 468
f0e9f0d3 469#ifdef __WXMSW__
e63fdcd6 470 wxWindow* focusWin = wxFindFocusDescendant((wxWindow*) this);
f0e9f0d3
JS
471#else
472 wxWindow* focusWin = (wxWindow*) NULL;
473#endif
7c0ea335 474 if ( bar != NULL )
54517652
RR
475 {
476 int nCount = bar->GetMenuCount();
477 for (int n = 0; n < nCount; n++)
e63fdcd6 478 DoMenuUpdates(bar->GetMenu(n), focusWin);
54517652 479 }
63fec618
VZ
480}
481
482// update a menu and all submenus recursively
e63fdcd6 483void wxFrameBase::DoMenuUpdates(wxMenu* menu, wxWindow* focusWin)
7c0ea335 484{
e63fdcd6 485 wxEvtHandler* evtHandler = focusWin ? focusWin->GetEventHandler() : GetEventHandler();
7c0ea335
VZ
486 wxMenuItemList::Node* node = menu->GetMenuItems().GetFirst();
487 while (node)
63fec618 488 {
7c0ea335
VZ
489 wxMenuItem* item = node->GetData();
490 if ( !item->IsSeparator() )
491 {
492 wxWindowID id = item->GetId();
493 wxUpdateUIEvent event(id);
494 event.SetEventObject( this );
495
496 if (evtHandler->ProcessEvent(event))
497 {
498 if (event.GetSetText())
499 menu->SetLabel(id, event.GetText());
500 if (event.GetSetChecked())
501 menu->Check(id, event.GetChecked());
502 if (event.GetSetEnabled())
503 menu->Enable(id, event.GetEnabled());
504 }
505
506 if (item->GetSubMenu())
507 DoMenuUpdates(item->GetSubMenu(), (wxWindow*) NULL);
508 }
509 node = node->GetNext();
63fec618 510 }
63fec618 511}
1e6feb95 512
6522713c
VZ
513void wxFrameBase::DetachMenuBar()
514{
515 if ( m_frameMenuBar )
516 {
517 m_frameMenuBar->Detach();
518 m_frameMenuBar = NULL;
519 }
520}
521
522void wxFrameBase::AttachMenuBar(wxMenuBar *menubar)
523{
524 if ( menubar )
525 {
526 m_frameMenuBar = menubar;
527 menubar->Attach((wxFrame *)this);
528 }
529}
530
531void wxFrameBase::SetMenuBar(wxMenuBar *menubar)
532{
533 if ( menubar == GetMenuBar() )
534 {
535 // nothing to do
536 return;
537 }
538
539 DetachMenuBar();
540
541 AttachMenuBar(menubar);
542}
543
1e6feb95 544#endif // wxUSE_MENUS