]> git.saurik.com Git - wxWidgets.git/blob - src/common/framecmn.cpp
tried to fix layout of label-less static box sizers
[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, 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 #include "wx/frame.h"
31 #include "wx/menu.h"
32 #include "wx/menuitem.h"
33 #include "wx/dcclient.h"
34
35 #if wxUSE_TOOLBAR
36 #include "wx/toolbar.h"
37 #endif
38 #if wxUSE_STATUSBAR
39 #include "wx/statusbr.h"
40 #endif
41
42 // ----------------------------------------------------------------------------
43 // event table
44 // ----------------------------------------------------------------------------
45
46 BEGIN_EVENT_TABLE(wxFrameBase, wxWindow)
47 EVT_IDLE(wxFrameBase::OnIdle)
48 EVT_CLOSE(wxFrameBase::OnCloseWindow)
49 EVT_MENU_HIGHLIGHT_ALL(wxFrameBase::OnMenuHighlight)
50 EVT_SIZE(wxFrameBase::OnSize)
51 END_EVENT_TABLE()
52
53 // ============================================================================
54 // implementation
55 // ============================================================================
56
57 // ----------------------------------------------------------------------------
58 // construction/destruction
59 // ----------------------------------------------------------------------------
60
61 wxFrameBase::wxFrameBase()
62 {
63 m_frameMenuBar = NULL;
64
65 #if wxUSE_TOOLBAR
66 m_frameToolBar = NULL;
67 #endif // wxUSE_TOOLBAR
68
69 #if wxUSE_STATUSBAR
70 m_frameStatusBar = NULL;
71 #endif // wxUSE_STATUSBAR
72 }
73
74 bool wxFrameBase::Destroy()
75 {
76 // delayed destruction: the frame will be deleted during the next idle
77 // loop iteration
78 if ( !wxPendingDelete.Member(this) )
79 wxPendingDelete.Append(this);
80
81 return TRUE;
82 }
83
84 wxFrame *wxFrameBase::New(wxWindow *parent,
85 wxWindowID id,
86 const wxString& title,
87 const wxPoint& pos,
88 const wxSize& size,
89 long style,
90 const wxString& name)
91 {
92 return new wxFrame(parent, id, title, pos, size, style, name);
93 }
94
95 void wxFrameBase::DeleteAllBars()
96 {
97 if ( m_frameMenuBar )
98 {
99 delete m_frameMenuBar;
100 m_frameMenuBar = (wxMenuBar *) NULL;
101 }
102
103 #if wxUSE_STATUSBAR
104 if ( m_frameStatusBar )
105 {
106 delete m_frameStatusBar;
107 m_frameStatusBar = (wxStatusBar *) NULL;
108 }
109 #endif // wxUSE_STATUSBAR
110
111 #if wxUSE_TOOLBAR
112 if ( m_frameToolBar )
113 {
114 delete m_frameToolBar;
115 m_frameToolBar = (wxToolBar *) NULL;
116 }
117 #endif // wxUSE_TOOLBAR
118 }
119
120 // ----------------------------------------------------------------------------
121 // wxFrame size management: we exclude the areas taken by menu/status/toolbars
122 // from the client area, so the client area is what's really available for the
123 // frame contents
124 // ----------------------------------------------------------------------------
125
126 // get the origin of the client area in the client coordinates
127 wxPoint wxFrameBase::GetClientAreaOrigin() const
128 {
129 wxPoint pt(0, 0);
130
131 #if wxUSE_TOOLBAR
132 if ( GetToolBar() && GetToolBar()->IsShown() )
133 {
134 int w, h;
135 GetToolBar()->GetSize(& w, & h);
136
137 if ( GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL )
138 {
139 pt.x += w;
140 }
141 else
142 {
143 pt.y += h;
144 }
145 }
146 #endif // wxUSE_TOOLBAR
147
148 return pt;
149 }
150
151 void wxFrameBase::DoScreenToClient(int *x, int *y) const
152 {
153 wxWindow::DoScreenToClient(x, y);
154
155 // We may be faking the client origin.
156 // So a window that's really at (0, 30) may appear
157 // (to wxWin apps) to be at (0, 0).
158 wxPoint pt(GetClientAreaOrigin());
159 *x -= pt.x;
160 *y -= pt.y;
161 }
162
163 void wxFrameBase::DoClientToScreen(int *x, int *y) const
164 {
165 // We may be faking the client origin.
166 // So a window that's really at (0, 30) may appear
167 // (to wxWin apps) to be at (0, 0).
168 wxPoint pt1(GetClientAreaOrigin());
169 *x += pt1.x;
170 *y += pt1.y;
171
172 wxWindow::DoClientToScreen(x, y);
173 }
174
175 // ----------------------------------------------------------------------------
176 // misc
177 // ----------------------------------------------------------------------------
178
179 // make the window modal (all other windows unresponsive)
180 void wxFrameBase::MakeModal(bool modal)
181 {
182 if ( modal )
183 {
184 wxEnableTopLevelWindows(FALSE);
185 Enable(TRUE); // keep this window enabled
186 }
187 else
188 {
189 wxEnableTopLevelWindows(TRUE);
190 }
191 }
192
193 bool wxFrameBase::ProcessCommand(int id)
194 {
195 wxMenuBar *bar = GetMenuBar();
196 if ( !bar )
197 return FALSE;
198
199 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
200 commandEvent.SetEventObject(this);
201
202 wxMenuItem *item = bar->FindItem(id);
203 if ( item && item->IsCheckable() )
204 {
205 item->Toggle();
206
207 // use the new value
208 commandEvent.SetInt(item->IsChecked());
209 }
210
211 return GetEventHandler()->ProcessEvent(commandEvent);
212 }
213
214 // ----------------------------------------------------------------------------
215 // event handlers
216 // ----------------------------------------------------------------------------
217
218 // default resizing behaviour - if only ONE subwindow, resize to fill the
219 // whole client area
220 void wxFrameBase::OnSize(wxSizeEvent& WXUNUSED(event))
221 {
222 // if we're using constraints - do use them
223 #if wxUSE_CONSTRAINTS
224 if ( GetAutoLayout() )
225 {
226 Layout();
227 }
228 else
229 #endif
230 {
231 // do we have _exactly_ one child?
232 wxWindow *child = (wxWindow *)NULL;
233 for ( wxWindowList::Node *node = GetChildren().GetFirst();
234 node;
235 node = node->GetNext() )
236 {
237 wxWindow *win = node->GetData();
238
239 // exclude top level and managed windows (status bar isn't
240 // currently in the children list except under wxMac anyhow, but
241 // it makes no harm to test for it)
242 if ( !win->IsTopLevel()
243 #if wxUSE_STATUSBAR
244 && (win != GetStatusBar())
245 #endif // wxUSE_STATUSBAR
246 #if wxUSE_TOOLBAR
247 && (win != GetToolBar())
248 #endif // wxUSE_TOOLBAR
249 )
250 {
251 if ( child )
252 {
253 return; // it's our second subwindow - nothing to do
254 }
255
256 child = win;
257 }
258 }
259
260 // do we have any children at all?
261 if ( child )
262 {
263 // exactly one child - set it's size to fill the whole frame
264 int clientW, clientH;
265 DoGetClientSize(&clientW, &clientH);
266
267 // for whatever reasons, wxGTK wants to have a small offset - it
268 // probably looks better with it?
269 #ifdef __WXGTK__
270 static const int ofs = 1;
271 #else
272 static const int ofs = 0;
273 #endif
274
275 child->SetSize(ofs, ofs, clientW - 2*ofs, clientH - 2*ofs);
276 }
277 }
278 }
279
280 // The default implementation for the close window event.
281 void wxFrameBase::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
282 {
283 Destroy();
284 }
285
286 void wxFrameBase::OnMenuHighlight(wxMenuEvent& event)
287 {
288 #if wxUSE_STATUSBAR
289 (void)ShowMenuHelp(GetStatusBar(), event.GetMenuId());
290 #endif // wxUSE_STATUSBAR
291 }
292
293 // ----------------------------------------------------------------------------
294 // status bar stuff
295 // ----------------------------------------------------------------------------
296
297 #if wxUSE_STATUSBAR
298
299 wxStatusBar* wxFrameBase::CreateStatusBar(int number,
300 long style,
301 wxWindowID id,
302 const wxString& name)
303 {
304 // the main status bar can only be created once (or else it should be
305 // deleted before calling CreateStatusBar() again)
306 wxCHECK_MSG( !m_frameStatusBar, (wxStatusBar *)NULL,
307 wxT("recreating status bar in wxFrame") );
308
309 m_frameStatusBar = OnCreateStatusBar( number, style, id, name );
310 if ( m_frameStatusBar )
311 PositionStatusBar();
312
313 return m_frameStatusBar;
314 }
315
316 wxStatusBar *wxFrameBase::OnCreateStatusBar(int number,
317 long style,
318 wxWindowID id,
319 const wxString& name)
320 {
321 wxStatusBar *statusBar = new wxStatusBar(this, id, style, name);
322
323 // Set the height according to the font and the border size
324 wxClientDC dc(statusBar);
325 dc.SetFont(statusBar->GetFont());
326
327 wxCoord y;
328 dc.GetTextExtent( "X", NULL, &y );
329
330 int height = (int)( (11*y)/10 + 2*statusBar->GetBorderY());
331
332 statusBar->SetSize( -1, -1, -1, height );
333
334 statusBar->SetFieldsCount(number);
335
336 return statusBar;
337 }
338
339 void wxFrameBase::SetStatusText(const wxString& text, int number)
340 {
341 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") );
342
343 m_frameStatusBar->SetStatusText(text, number);
344 }
345
346 void wxFrameBase::SetStatusWidths(int n, const int widths_field[] )
347 {
348 wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set widths for") );
349
350 m_frameStatusBar->SetStatusWidths(n, widths_field);
351
352 PositionStatusBar();
353 }
354
355 bool wxFrameBase::ShowMenuHelp(wxStatusBar *statbar, int menuId)
356 {
357 if ( !statbar )
358 return FALSE;
359
360 // if no help string found, we will clear the status bar text
361 wxString helpString;
362
363 if ( menuId != wxID_SEPARATOR && menuId != -2 /* wxID_TITLE */ )
364 {
365 wxMenuBar *menuBar = GetMenuBar();
366 if ( menuBar )
367 {
368 // it's ok if we don't find the item because it might belong
369 // to the popup menu
370 wxMenuItem *item = menuBar->FindItem(menuId);
371 if ( item )
372 helpString = item->GetHelp();
373 }
374 }
375
376 // set status text even if the string is empty - this will at least
377 // remove the string from the item which was previously selected
378 statbar->SetStatusText(helpString);
379
380 return !helpString.IsEmpty();
381 }
382
383 #endif // wxUSE_STATUSBAR
384
385 // ----------------------------------------------------------------------------
386 // toolbar stuff
387 // ----------------------------------------------------------------------------
388
389 #if wxUSE_TOOLBAR
390
391 wxToolBar* wxFrameBase::CreateToolBar(long style,
392 wxWindowID id,
393 const wxString& name)
394 {
395 // the main toolbar can't be recreated (unless it was explicitly deeleted
396 // before)
397 wxCHECK_MSG( !m_frameToolBar, (wxToolBar *)NULL,
398 wxT("recreating toolbar in wxFrame") );
399
400 m_frameToolBar = OnCreateToolBar(style, id, name);
401
402 return m_frameToolBar;
403 }
404
405 wxToolBar* wxFrameBase::OnCreateToolBar(long style,
406 wxWindowID id,
407 const wxString& name)
408 {
409 return new wxToolBar(this, id,
410 wxDefaultPosition, wxDefaultSize,
411 style, name);
412 }
413
414 #endif // wxUSE_TOOLBAR
415
416 // ----------------------------------------------------------------------------
417 // Menu UI updating
418 // ----------------------------------------------------------------------------
419
420 void wxFrameBase::OnIdle(wxIdleEvent& WXUNUSED(event) )
421 {
422 DoMenuUpdates();
423 }
424
425 // update all menus
426 void wxFrameBase::DoMenuUpdates()
427 {
428 wxMenuBar* bar = GetMenuBar();
429
430 #ifdef __WXMSW__
431 wxWindow* focusWin = wxFindFocusDescendant((wxWindow*) this);
432 #else
433 wxWindow* focusWin = (wxWindow*) NULL;
434 #endif
435 if ( bar != NULL )
436 {
437 int nCount = bar->GetMenuCount();
438 for (int n = 0; n < nCount; n++)
439 DoMenuUpdates(bar->GetMenu(n), focusWin);
440 }
441 }
442
443 // update a menu and all submenus recursively
444 void wxFrameBase::DoMenuUpdates(wxMenu* menu, wxWindow* focusWin)
445 {
446 wxEvtHandler* evtHandler = focusWin ? focusWin->GetEventHandler() : GetEventHandler();
447 wxMenuItemList::Node* node = menu->GetMenuItems().GetFirst();
448 while (node)
449 {
450 wxMenuItem* item = node->GetData();
451 if ( !item->IsSeparator() )
452 {
453 wxWindowID id = item->GetId();
454 wxUpdateUIEvent event(id);
455 event.SetEventObject( this );
456
457 if (evtHandler->ProcessEvent(event))
458 {
459 if (event.GetSetText())
460 menu->SetLabel(id, event.GetText());
461 if (event.GetSetChecked())
462 menu->Check(id, event.GetChecked());
463 if (event.GetSetEnabled())
464 menu->Enable(id, event.GetEnabled());
465 }
466
467 if (item->GetSubMenu())
468 DoMenuUpdates(item->GetSubMenu(), (wxWindow*) NULL);
469 }
470 node = node->GetNext();
471 }
472 }