]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/frame.cpp
* When hiding a wxWindow make sure that none of its subviews are the first
[wxWidgets.git] / src / gtk / frame.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
93763ad5 2// Name: src/gtk/frame.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
a81258be 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling
65571936 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
93763ad5
WS
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
e1bf3ad3 13#include "wx/frame.h"
670f9935
WS
14
15#ifndef WX_PRECOMP
3b3dc801 16 #include "wx/menu.h"
4e3e485b 17 #include "wx/toolbar.h"
7c0ea335 18 #include "wx/statusbr.h"
3304646d 19#endif // WX_PRECOMP
83624f79 20
a1abca32 21#include <gtk/gtk.h>
c801d85f 22
e2f3bc41
VZ
23#if wxUSE_LIBHILDON
24 #include <hildon-widgets/hildon-window.h>
25#endif // wxUSE_LIBHILDON
26
7c0ea335
VZ
27// ----------------------------------------------------------------------------
28// event tables
29// ----------------------------------------------------------------------------
30
0d53fc34 31IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxTopLevelWindow)
2e563988 32
7c0ea335
VZ
33// ============================================================================
34// implementation
35// ============================================================================
36
7c0ea335 37// ----------------------------------------------------------------------------
0d53fc34 38// wxFrame creation
7c0ea335 39// ----------------------------------------------------------------------------
c801d85f 40
0d53fc34 41void wxFrame::Init()
c801d85f 42{
1529bc41 43 m_fsSaveFlag = 0;
362c6693 44}
c801d85f 45
0d53fc34 46bool wxFrame::Create( wxWindow *parent,
7c0ea335 47 wxWindowID id,
ca8bf976
VZ
48 const wxString& title,
49 const wxPoint& pos,
50 const wxSize& sizeOrig,
7c0ea335
VZ
51 long style,
52 const wxString &name )
c801d85f 53{
c821db16 54 return wxFrameBase::Create(parent, id, title, pos, sizeOrig, style, name);
362c6693 55}
c801d85f 56
0d53fc34 57wxFrame::~wxFrame()
c801d85f 58{
91af0895 59 m_isBeingDeleted = true;
7c0ea335 60 DeleteAllBars();
3d0c4d2e
RR
61}
62
7c0ea335
VZ
63// ----------------------------------------------------------------------------
64// overridden wxWindow methods
65// ----------------------------------------------------------------------------
66
0d53fc34 67void wxFrame::DoGetClientSize( int *width, int *height ) const
c801d85f 68{
223d09f6 69 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
7b4c2a06 70
e36a8aff 71 wxFrameBase::DoGetClientSize(width, height);
8bbe427f 72
fb1585ae 73 if (height)
46dc76ba 74 {
75c9da25 75#if wxUSE_MENUS_NATIVE
047ac72b 76 // menu bar
cca410b3 77 if (m_frameMenuBar && m_frameMenuBar->IsShown())
f03fc89f 78 {
cca410b3
PC
79 GtkRequisition req;
80 gtk_widget_size_request(m_frameMenuBar->m_widget, &req);
81 *height -= req.height;
f03fc89f 82 }
75c9da25 83#endif // wxUSE_MENUS_NATIVE
88ac883a 84
dcf924a3 85#if wxUSE_STATUSBAR
047ac72b 86 // status bar
cca410b3
PC
87 if (m_frameStatusBar && m_frameStatusBar->IsShown())
88 *height -= m_frameStatusBar->m_height;
93fa69f8 89#endif // wxUSE_STATUSBAR
c1fa6f52 90 }
88ac883a 91
dcf924a3 92#if wxUSE_TOOLBAR
c1fa6f52 93 // tool bar
cca410b3 94 if (m_frameToolBar && m_frameToolBar->IsShown())
c1fa6f52 95 {
cca410b3
PC
96 GtkRequisition req;
97 gtk_widget_size_request(m_frameToolBar->m_widget, &req);
e36a8aff 98 if (m_frameToolBar->IsVertical())
fb1585ae 99 {
e36a8aff 100 if (width)
cca410b3 101 *width -= req.width;
c1fa6f52
PC
102 }
103 else
104 {
e36a8aff 105 if (height)
cca410b3 106 *height -= req.height;
fb1585ae 107 }
46dc76ba 108 }
c1fa6f52
PC
109#endif // wxUSE_TOOLBAR
110
111 if (width != NULL && *width < 0)
112 *width = 0;
113 if (height != NULL && *height < 0)
114 *height = 0;
362c6693 115}
c801d85f 116
6c309653 117#if wxUSE_MENUS && wxUSE_ACCEL
e41a1b1c
JS
118// Helper for wxCreateAcceleratorTableForMenuBar
119static void wxAddAccelerators(wxList& accelEntries, wxMenu* menu)
120{
121 size_t i;
122 for (i = 0; i < menu->GetMenuItems().GetCount(); i++)
123 {
124 wxMenuItem* item = (wxMenuItem*) menu->GetMenuItems().Item(i)->GetData();
125 if (item->GetSubMenu())
126 {
127 wxAddAccelerators(accelEntries, item->GetSubMenu());
128 }
129 else if (!item->GetItemLabel().IsEmpty())
130 {
131 wxAcceleratorEntry* entry = wxAcceleratorEntry::Create(item->GetItemLabel());
132 if (entry)
133 {
134 entry->Set(entry->GetFlags(), entry->GetKeyCode(), item->GetId());
135 accelEntries.Append((wxObject*) entry);
136 }
137 }
138 }
139}
140
141// Create an accelerator table consisting of all the accelerators
142// from the menubar in the given menus
143static wxAcceleratorTable wxCreateAcceleratorTableForMenuBar(wxMenuBar* menuBar)
144{
145 wxList accelEntries;
146
147 size_t i;
148 for (i = 0; i < menuBar->GetMenuCount(); i++)
149 {
150 wxAddAccelerators(accelEntries, menuBar->GetMenu(i));
151 }
152
153 size_t n = accelEntries.GetCount();
154
155 if (n == 0)
156 return wxAcceleratorTable();
157
158 wxAcceleratorEntry* entries = new wxAcceleratorEntry[n];
159
160 for (i = 0; i < accelEntries.GetCount(); i++)
161 {
162 wxAcceleratorEntry* entry = (wxAcceleratorEntry*) accelEntries.Item(i)->GetData();
163 entries[i] = (*entry);
164 delete entry;
165
166 }
167
168 wxAcceleratorTable table(n, entries);
169 delete[] entries;
170
171 return table;
172}
6c309653 173#endif // wxUSE_MENUS && wxUSE_ACCEL
e41a1b1c 174
1529bc41
PC
175bool wxFrame::ShowFullScreen(bool show, long style)
176{
177 if (!wxFrameBase::ShowFullScreen(show, style))
178 return false;
179
6c309653 180#if wxUSE_MENUS && wxUSE_ACCEL
e41a1b1c
JS
181 if (show && GetMenuBar())
182 {
183 wxAcceleratorTable table(wxCreateAcceleratorTableForMenuBar(GetMenuBar()));
184 if (table.IsOk())
185 SetAcceleratorTable(table);
186 }
6c309653 187#endif // wxUSE_MENUS && wxUSE_ACCEL
e41a1b1c 188
1529bc41 189 wxWindow* const bar[] = {
28fcfbfe
VZ
190#if wxUSE_MENUS
191 m_frameMenuBar,
192#else
193 NULL,
194#endif
195#if wxUSE_TOOLBAR
196 m_frameToolBar,
197#else
198 NULL,
199#endif
200#if wxUSE_STATUSBAR
201 m_frameStatusBar,
202#else
203 NULL,
204#endif
1529bc41
PC
205 };
206 const long fsNoBar[] = {
207 wxFULLSCREEN_NOMENUBAR, wxFULLSCREEN_NOTOOLBAR, wxFULLSCREEN_NOSTATUSBAR
208 };
209 for (int i = 0; i < 3; i++)
210 {
211 if (show)
212 {
213 if (bar[i] && (style & fsNoBar[i]))
214 {
215 if (bar[i]->IsShown())
216 bar[i]->Show(false);
217 else
218 style &= ~fsNoBar[i];
219 }
220 }
221 else
222 {
223 if (bar[i] && (m_fsSaveFlag & fsNoBar[i]))
224 bar[i]->Show(true);
225 }
226 }
227 if (show)
228 m_fsSaveFlag = style;
229
230 return true;
231}
232
0d53fc34 233void wxFrame::OnInternalIdle()
e52f60e6 234{
e39af974 235 wxFrameBase::OnInternalIdle();
88ac883a 236
75c9da25 237#if wxUSE_MENUS_NATIVE
082b2798 238 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
75c9da25 239#endif // wxUSE_MENUS_NATIVE
dcf924a3 240#if wxUSE_TOOLBAR
082b2798 241 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
dcf924a3
RR
242#endif
243#if wxUSE_STATUSBAR
e4edaf5c
JS
244 if (m_frameStatusBar)
245 {
246 m_frameStatusBar->OnInternalIdle();
247
248 // There may be controls in the status bar that
249 // need to be updated
250 for ( wxWindowList::compatibility_iterator node = m_frameStatusBar->GetChildren().GetFirst();
251 node;
252 node = node->GetNext() )
253 {
254 wxWindow *child = node->GetData();
255 child->OnInternalIdle();
256 }
257 }
dcf924a3 258#endif
362c6693 259}
c801d85f 260
7c0ea335
VZ
261// ----------------------------------------------------------------------------
262// menu/tool/status bar stuff
263// ----------------------------------------------------------------------------
c801d85f 264
6522713c 265#if wxUSE_MENUS_NATIVE
1e6feb95 266
0d53fc34 267void wxFrame::DetachMenuBar()
c801d85f 268{
223d09f6
KB
269 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
270 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
8bbe427f 271
6522713c 272 if ( m_frameMenuBar )
186baeb2 273 {
e2f3bc41
VZ
274#if wxUSE_LIBHILDON
275 hildon_window_set_menu(HILDON_WINDOW(m_widget), NULL);
276#else // !wxUSE_LIBHILDON
186baeb2
RR
277 m_frameMenuBar->UnsetInvokingWindow( this );
278
186baeb2 279 gtk_widget_ref( m_frameMenuBar->m_widget );
f283a575
RR
280
281 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
e2f3bc41 282#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON
186baeb2
RR
283 }
284
6522713c 285 wxFrameBase::DetachMenuBar();
cca410b3
PC
286
287 // make sure next size_allocate causes a wxSizeEvent
288 m_oldClientWidth = 0;
6522713c
VZ
289}
290
0d53fc34 291void wxFrame::AttachMenuBar( wxMenuBar *menuBar )
6522713c
VZ
292{
293 wxFrameBase::AttachMenuBar(menuBar);
8bbe427f 294
f5368809 295 if (m_frameMenuBar)
30dea054 296 {
e2f3bc41
VZ
297#if wxUSE_LIBHILDON
298 hildon_window_set_menu(HILDON_WINDOW(m_widget),
299 GTK_MENU(m_frameMenuBar->m_menubar));
300#else // !wxUSE_LIBHILDON
5bd9e519 301 m_frameMenuBar->SetInvokingWindow( this );
8bbe427f 302
186baeb2 303 m_frameMenuBar->SetParent(this);
91af0895 304
cca410b3
PC
305 // menubar goes into top of vbox (m_mainWidget)
306 gtk_box_pack_start(
307 GTK_BOX(m_mainWidget), menuBar->m_widget, false, false, 0);
308 gtk_box_reorder_child(GTK_BOX(m_mainWidget), menuBar->m_widget, 0);
2b5f62a0 309
cca410b3
PC
310 // disconnect wxWindowGTK "size_request" handler,
311 // it interferes with sizing of detached GtkHandleBox
312 gulong handler_id = g_signal_handler_find(
313 menuBar->m_widget,
314 GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA),
315 g_signal_lookup("size_request", GTK_TYPE_WIDGET),
316 0, NULL, NULL, menuBar);
317 if (handler_id != 0)
318 g_signal_handler_disconnect(menuBar->m_widget, handler_id);
2b5f62a0 319
cca410b3
PC
320 // reset size request to allow native sizing to work
321 gtk_widget_set_size_request(menuBar->m_widget, -1, -1);
91af0895 322
cca410b3 323 gtk_widget_show( m_frameMenuBar->m_widget );
e2f3bc41 324#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON
8c70a789 325 }
cca410b3
PC
326 // make sure next size_allocate causes a wxSizeEvent
327 m_oldClientWidth = 0;
1d66b099 328}
6522713c 329#endif // wxUSE_MENUS_NATIVE
1e6feb95 330
88ac883a 331#if wxUSE_TOOLBAR
1e6feb95 332
0d53fc34 333void wxFrame::SetToolBar(wxToolBar *toolbar)
7beba2fc 334{
cca410b3
PC
335 m_frameToolBar = toolbar;
336 if (toolbar)
307f16e8 337 {
cca410b3 338 if (toolbar->IsVertical())
307f16e8 339 {
cca410b3
PC
340 // Vertical toolbar and m_wxwindow go into an hbox, inside the
341 // vbox (m_mainWidget). hbox is created on demand.
342 GtkWidget* hbox = m_wxwindow->parent;
343 if (!GTK_IS_HBOX(hbox))
344 {
345 hbox = gtk_hbox_new(false, 0);
346 gtk_widget_show(hbox);
347 gtk_container_add(GTK_CONTAINER(m_mainWidget), hbox);
348 gtk_widget_reparent(m_wxwindow, hbox);
349 }
350 gtk_widget_reparent(toolbar->m_widget, hbox);
351 gtk_box_set_child_packing(GTK_BOX(hbox),
352 toolbar->m_widget, false, false, 0, GTK_PACK_START);
353
354 int pos = 0; // left
355 if (toolbar->HasFlag(wxTB_RIGHT))
356 pos = 1; // right
357 gtk_box_reorder_child(GTK_BOX(hbox), toolbar->m_widget, pos);
7beba2fc 358 }
cca410b3 359 else
94f14509 360 {
cca410b3
PC
361 // Horizontal toolbar goes into vbox (m_mainWidget)
362 gtk_widget_reparent(toolbar->m_widget, m_mainWidget);
363 gtk_box_set_child_packing(GTK_BOX(m_mainWidget),
364 toolbar->m_widget, false, false, 0, GTK_PACK_START);
365
366 int pos = 0; // top
367 if (m_frameMenuBar)
368 pos = 1; // below menubar
369 if (toolbar->HasFlag(wxTB_BOTTOM))
370 pos += 2; // below client area (m_wxwindow)
371 gtk_box_reorder_child(
372 GTK_BOX(m_mainWidget), toolbar->m_widget, pos);
94f14509 373 }
383144c7 374
cca410b3
PC
375 // disconnect wxWindowGTK "size_request" handler,
376 // it interferes with sizing of detached GtkHandleBox
377 gulong handler_id = g_signal_handler_find(
378 toolbar->m_widget,
379 GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA),
380 g_signal_lookup("size_request", GTK_TYPE_WIDGET),
381 0, NULL, NULL, toolbar);
382 if (handler_id != 0)
383 g_signal_handler_disconnect(toolbar->m_widget, handler_id);
384
385 // reset size request to allow native sizing to work
386 gtk_widget_set_size_request(toolbar->m_widget, -1, -1);
387 }
388 // make sure next size_allocate causes a wxSizeEvent
389 m_oldClientWidth = 0;
307f16e8
RR
390}
391
88ac883a 392#endif // wxUSE_TOOLBAR
46dc76ba 393
88ac883a 394#if wxUSE_STATUSBAR
8bbe427f 395
3851e479
RR
396void wxFrame::SetStatusBar(wxStatusBar *statbar)
397{
cca410b3
PC
398 m_frameStatusBar = statbar;
399 if (statbar)
400 {
401 // statusbar goes into bottom of vbox (m_mainWidget)
402 gtk_widget_reparent(statbar->m_widget, m_mainWidget);
403 gtk_box_set_child_packing(GTK_BOX(m_mainWidget),
404 statbar->m_widget, false, false, 0, GTK_PACK_END);
405 // make sure next size_allocate on statusbar causes a size event
406 statbar->m_oldClientWidth = 0;
407 }
408 // make sure next size_allocate causes a wxSizeEvent
409 m_oldClientWidth = 0;
8febdd39 410}
88ac883a 411#endif // wxUSE_STATUSBAR