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