]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/framecmn.cpp
compilation fixes - wxGTK compiles but not links
[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, Julian Smart and Markus Holzem
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19#ifdef __GNUG__
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
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{
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
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{
101#if wxUSE_MENUS
102 if ( m_frameMenuBar )
103 {
104 delete m_frameMenuBar;
105 m_frameMenuBar = (wxMenuBar *) NULL;
106 }
107#endif // wxUSE_MENUS
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
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
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
158 if ( GetToolBar() && GetToolBar()->IsShown() )
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
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{
221#if wxUSE_MENUS
222 wxMenuBar *bar = GetMenuBar();
223 if ( !bar )
224 return FALSE;
225
226 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
227 commandEvent.SetEventObject(this);
228
229 wxMenuItem *item = bar->FindItem(id);
230 if ( item && item->IsCheckable() )
231 {
232 item->Toggle();
233
234 // use the new value
235 commandEvent.SetInt(item->IsChecked());
236 }
237
238 return GetEventHandler()->ProcessEvent(commandEvent);
239#else // !wxUSE_MENUS
240 return FALSE;
241#endif // wxUSE_MENUS/!wxUSE_MENUS
242}
243
244// ----------------------------------------------------------------------------
245// event handlers
246// ----------------------------------------------------------------------------
247
248// default resizing behaviour - if only ONE subwindow, resize to fill the
249// whole client area
250void wxFrameBase::OnSize(wxSizeEvent& WXUNUSED(event))
251{
252 // if we're using constraints - do use them
253#if wxUSE_CONSTRAINTS
254 if ( GetAutoLayout() )
255 {
256 Layout();
257 }
258 else
259#endif // wxUSE_CONSTRAINTS
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)
272 if ( !win->IsTopLevel() && !IsOneOfBars(win) )
273 {
274 if ( child )
275 {
276 return; // it's our second subwindow - nothing to do
277 }
278
279 child = win;
280 }
281 }
282
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__
293 static const int ofs = 1;
294#else
295 static const int ofs = 0;
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.
304void wxFrameBase::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
305{
306 Destroy();
307}
308
309void wxFrameBase::OnMenuHighlight(wxMenuEvent& event)
310{
311#if wxUSE_STATUSBAR
312 (void)ShowMenuHelp(GetStatusBar(), event.GetMenuId());
313#endif // wxUSE_STATUSBAR
314}
315
316bool wxFrameBase::SendIconizeEvent(bool iconized)
317{
318 wxIconizeEvent event(GetId(), iconized);
319 event.SetEventObject(this);
320
321 return GetEventHandler()->ProcessEvent(event);
322}
323
324// ----------------------------------------------------------------------------
325// status bar stuff
326// ----------------------------------------------------------------------------
327
328#if wxUSE_STATUSBAR
329
330wxStatusBar* wxFrameBase::CreateStatusBar(int number,
331 long style,
332 wxWindowID id,
333 const wxString& name)
334{
335 // the main status bar can only be created once (or else it should be
336 // deleted before calling CreateStatusBar() again)
337 wxCHECK_MSG( !m_frameStatusBar, (wxStatusBar *)NULL,
338 wxT("recreating status bar in wxFrame") );
339
340 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
341 if ( m_frameStatusBar )
342 PositionStatusBar();
343
344 return m_frameStatusBar;
345}
346
347wxStatusBar *wxFrameBase::OnCreateStatusBar(int number,
348 long style,
349 wxWindowID id,
350 const wxString& name)
351{
352 wxStatusBar *statusBar = new wxStatusBar(this, id, style, name);
353
354 // Set the height according to the font and the border size
355 wxClientDC dc(statusBar);
356 dc.SetFont(statusBar->GetFont());
357
358 wxCoord y;
359 dc.GetTextExtent( "X", NULL, &y );
360
361 int height = (int)( (11*y)/10 + 2*statusBar->GetBorderY());
362
363 statusBar->SetSize( -1, -1, -1, height );
364
365 statusBar->SetFieldsCount(number);
366
367 return statusBar;
368}
369
370void wxFrameBase::SetStatusText(const wxString& text, int number)
371{
372 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
373
374 m_frameStatusBar->SetStatusText(text, number);
375}
376
377void wxFrameBase::SetStatusWidths(int n, const int widths_field[] )
378{
379 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set widths for") );
380
381 m_frameStatusBar->SetStatusWidths(n, widths_field);
382
383 PositionStatusBar();
384}
385
386bool wxFrameBase::ShowMenuHelp(wxStatusBar *statbar, int menuId)
387{
388 if ( !statbar )
389 return FALSE;
390
391 // if no help string found, we will clear the status bar text
392 wxString helpString;
393
394 if ( menuId != wxID_SEPARATOR && menuId != -2 /* wxID_TITLE */ )
395 {
396 wxMenuBar *menuBar = GetMenuBar();
397 if ( menuBar )
398 {
399 // it's ok if we don't find the item because it might belong
400 // to the popup menu
401 wxMenuItem *item = menuBar->FindItem(menuId);
402 if ( item )
403 helpString = item->GetHelp();
404 }
405 }
406
407 // set status text even if the string is empty - this will at least
408 // remove the string from the item which was previously selected
409 statbar->SetStatusText(helpString);
410
411 return !helpString.IsEmpty();
412}
413
414#endif // wxUSE_STATUSBAR
415
416// ----------------------------------------------------------------------------
417// toolbar stuff
418// ----------------------------------------------------------------------------
419
420#if wxUSE_TOOLBAR
421
422wxToolBar* wxFrameBase::CreateToolBar(long style,
423 wxWindowID id,
424 const wxString& name)
425{
426 // the main toolbar can't be recreated (unless it was explicitly deeleted
427 // before)
428 wxCHECK_MSG( !m_frameToolBar, (wxToolBar *)NULL,
429 wxT("recreating toolbar in wxFrame") );
430
431 m_frameToolBar = OnCreateToolBar(style, id, name);
432
433 return m_frameToolBar;
434}
435
436wxToolBar* wxFrameBase::OnCreateToolBar(long style,
437 wxWindowID id,
438 const wxString& name)
439{
440 return new wxToolBar(this, id,
441 wxDefaultPosition, wxDefaultSize,
442 style, name);
443}
444
445#endif // wxUSE_TOOLBAR
446
447// ----------------------------------------------------------------------------
448// Menu UI updating
449// ----------------------------------------------------------------------------
450
451void wxFrameBase::OnIdle(wxIdleEvent& WXUNUSED(event) )
452{
453#if wxUSE_MENUS
454 DoMenuUpdates();
455#endif // wxUSE_MENUS
456}
457
458#if wxUSE_MENUS
459
460// update all menus
461void wxFrameBase::DoMenuUpdates()
462{
463 wxMenuBar* bar = GetMenuBar();
464
465#ifdef __WXMSW__
466 wxWindow* focusWin = wxFindFocusDescendant((wxWindow*) this);
467#else
468 wxWindow* focusWin = (wxWindow*) NULL;
469#endif
470 if ( bar != NULL )
471 {
472 int nCount = bar->GetMenuCount();
473 for (int n = 0; n < nCount; n++)
474 DoMenuUpdates(bar->GetMenu(n), focusWin);
475 }
476}
477
478// update a menu and all submenus recursively
479void wxFrameBase::DoMenuUpdates(wxMenu* menu, wxWindow* focusWin)
480{
481 wxEvtHandler* evtHandler = focusWin ? focusWin->GetEventHandler() : GetEventHandler();
482 wxMenuItemList::Node* node = menu->GetMenuItems().GetFirst();
483 while (node)
484 {
485 wxMenuItem* item = node->GetData();
486 if ( !item->IsSeparator() )
487 {
488 wxWindowID id = item->GetId();
489 wxUpdateUIEvent event(id);
490 event.SetEventObject( this );
491
492 if (evtHandler->ProcessEvent(event))
493 {
494 if (event.GetSetText())
495 menu->SetLabel(id, event.GetText());
496 if (event.GetSetChecked())
497 menu->Check(id, event.GetChecked());
498 if (event.GetSetEnabled())
499 menu->Enable(id, event.GetEnabled());
500 }
501
502 if (item->GetSubMenu())
503 DoMenuUpdates(item->GetSubMenu(), (wxWindow*) NULL);
504 }
505 node = node->GetNext();
506 }
507}
508
509#endif // wxUSE_MENUS