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