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