]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/frame.cpp
tidy up
[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#include "wx/gtk/win_gtk.h"
23
24// ----------------------------------------------------------------------------
25// constants
26// ----------------------------------------------------------------------------
27
28static const int wxSTATUS_HEIGHT = 25;
29static const int wxPLACE_HOLDER = 0;
30
31// ----------------------------------------------------------------------------
32// event tables
33// ----------------------------------------------------------------------------
34
35IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxTopLevelWindow)
36
37// ============================================================================
38// implementation
39// ============================================================================
40
41// ----------------------------------------------------------------------------
42// GTK callbacks
43// ----------------------------------------------------------------------------
44
45#if wxUSE_MENUS_NATIVE
46
47//-----------------------------------------------------------------------------
48// "child_attached" of menu bar
49//-----------------------------------------------------------------------------
50
51extern "C" {
52static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
53{
54 if (!win->m_hasVMT) return;
55
56 win->m_menuBarDetached = false;
57 win->GtkUpdateSize();
58}
59}
60
61//-----------------------------------------------------------------------------
62// "child_detached" of menu bar
63//-----------------------------------------------------------------------------
64
65extern "C" {
66static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
67{
68 if (!win->m_hasVMT) return;
69
70 // Raise the client area area
71 gdk_window_raise( win->m_wxwindow->window );
72
73 win->m_menuBarDetached = true;
74 win->GtkUpdateSize();
75}
76}
77
78#endif // wxUSE_MENUS_NATIVE
79
80#if wxUSE_TOOLBAR
81//-----------------------------------------------------------------------------
82// "child_attached" of tool bar
83//-----------------------------------------------------------------------------
84
85extern "C" {
86static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
87{
88 if (!win->m_hasVMT) return;
89
90 win->m_toolBarDetached = false;
91 win->GtkUpdateSize();
92}
93}
94
95//-----------------------------------------------------------------------------
96// "child_detached" of tool bar
97//-----------------------------------------------------------------------------
98
99extern "C" {
100static void gtk_toolbar_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
101{
102 if (!win->m_hasVMT) return;
103
104 // Raise the client area area
105 gdk_window_raise( win->m_wxwindow->window );
106
107 win->m_toolBarDetached = true;
108 win->GtkUpdateSize();
109}
110}
111#endif // wxUSE_TOOLBAR
112
113
114// ----------------------------------------------------------------------------
115// wxFrame itself
116// ----------------------------------------------------------------------------
117
118//-----------------------------------------------------------------------------
119// InsertChild for wxFrame
120//-----------------------------------------------------------------------------
121
122/* Callback for wxFrame. This very strange beast has to be used because
123 * C++ has no virtual methods in a constructor. We have to emulate a
124 * virtual function here as wxWidgets requires different ways to insert
125 * a child in container classes. */
126
127static void wxInsertChildInFrame(wxWindow* parent, wxWindow* child)
128{
129 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
130
131 // These are outside the client area
132 wxFrame* frame = wx_static_cast(wxFrame*, parent);
133 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
134 child->m_widget,
135 child->m_x,
136 child->m_y,
137 child->m_width,
138 child->m_height );
139
140#if wxUSE_TOOLBAR_NATIVE
141 // We connect to these events for recalculating the client area
142 // space when the toolbar is floating
143 if (wxIS_KIND_OF(child,wxToolBar))
144 {
145 if (child->HasFlag(wxTB_DOCKABLE))
146 {
147 g_signal_connect (child->m_widget, "child_attached",
148 G_CALLBACK (gtk_toolbar_attached_callback),
149 parent);
150 g_signal_connect (child->m_widget, "child_detached",
151 G_CALLBACK (gtk_toolbar_detached_callback),
152 parent);
153 }
154 }
155#endif // wxUSE_TOOLBAR
156}
157
158// ----------------------------------------------------------------------------
159// wxFrame creation
160// ----------------------------------------------------------------------------
161
162void wxFrame::Init()
163{
164 m_menuBarDetached = false;
165 m_toolBarDetached = false;
166 m_menuBarHeight = 2;
167 m_fsSaveFlag = 0;
168}
169
170bool wxFrame::Create( wxWindow *parent,
171 wxWindowID id,
172 const wxString& title,
173 const wxPoint& pos,
174 const wxSize& sizeOrig,
175 long style,
176 const wxString &name )
177{
178 return wxFrameBase::Create(parent, id, title, pos, sizeOrig, style, name);
179}
180
181wxFrame::~wxFrame()
182{
183 m_isBeingDeleted = true;
184 DeleteAllBars();
185}
186
187// ----------------------------------------------------------------------------
188// overridden wxWindow methods
189// ----------------------------------------------------------------------------
190
191void wxFrame::DoGetClientSize( int *width, int *height ) const
192{
193 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
194
195 wxFrameBase::DoGetClientSize(width, height);
196
197 if (height)
198 {
199#if wxUSE_MENUS_NATIVE
200 // menu bar
201 if (m_frameMenuBar &&
202 GTK_WIDGET_VISIBLE(m_frameMenuBar->m_widget) && !m_menuBarDetached)
203 {
204 *height -= m_menuBarHeight;
205 }
206#endif // wxUSE_MENUS_NATIVE
207
208#if wxUSE_STATUSBAR
209 // status bar
210 if (m_frameStatusBar && GTK_WIDGET_VISIBLE(m_frameStatusBar->m_widget))
211 *height -= wxSTATUS_HEIGHT;
212#endif // wxUSE_STATUSBAR
213 }
214
215#if wxUSE_TOOLBAR
216 // tool bar
217 if (m_frameToolBar &&
218 GTK_WIDGET_VISIBLE(m_frameToolBar->m_widget) && !m_toolBarDetached)
219 {
220 if (m_frameToolBar->IsVertical())
221 {
222 if (width)
223 *width -= m_frameToolBar->GetSize().x;
224 }
225 else
226 {
227 if (height)
228 *height -= m_frameToolBar->GetSize().y;
229 }
230 }
231#endif // wxUSE_TOOLBAR
232
233 if (width != NULL && *width < 0)
234 *width = 0;
235 if (height != NULL && *height < 0)
236 *height = 0;
237}
238
239bool wxFrame::ShowFullScreen(bool show, long style)
240{
241 if (!wxFrameBase::ShowFullScreen(show, style))
242 return false;
243
244 wxWindow* const bar[] = {
245 m_frameMenuBar, m_frameToolBar, m_frameStatusBar
246 };
247 const long fsNoBar[] = {
248 wxFULLSCREEN_NOMENUBAR, wxFULLSCREEN_NOTOOLBAR, wxFULLSCREEN_NOSTATUSBAR
249 };
250 for (int i = 0; i < 3; i++)
251 {
252 if (show)
253 {
254 if (bar[i] && (style & fsNoBar[i]))
255 {
256 if (bar[i]->IsShown())
257 bar[i]->Show(false);
258 else
259 style &= ~fsNoBar[i];
260 }
261 }
262 else
263 {
264 if (bar[i] && (m_fsSaveFlag & fsNoBar[i]))
265 bar[i]->Show(true);
266 }
267 }
268 if (show)
269 m_fsSaveFlag = style;
270
271 return true;
272}
273
274void wxFrame::GtkOnSize()
275{
276 // avoid recursions
277 if (m_resizing) return;
278 m_resizing = true;
279
280 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
281 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
282
283 // space occupied by m_frameToolBar and m_frameMenuBar
284 int client_area_x_offset = 0,
285 client_area_y_offset = 0;
286
287 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
288 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
289 set in wxFrame::Create so it is used to check what kind of frame we
290 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
291 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
292 importantly) m_mainWidget */
293
294 ConstrainSize();
295
296 if (m_mainWidget)
297 {
298 // TODO
299 // Rewrite this terrible code to using GtkVBox
300
301 // m_mainWidget holds the menubar, the toolbar and the client
302 // area, which is represented by m_wxwindow.
303
304#if wxUSE_MENUS_NATIVE
305 if (m_frameMenuBar && m_frameMenuBar->IsShown())
306 {
307 int xx = m_miniEdge;
308 int yy = m_miniEdge + m_miniTitle;
309 int ww = m_width - 2*m_miniEdge;
310 if (ww < 0)
311 ww = 0;
312 int hh = m_menuBarHeight;
313 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
314 m_frameMenuBar->m_x = xx;
315 m_frameMenuBar->m_y = yy;
316 m_frameMenuBar->m_width = ww;
317 m_frameMenuBar->m_height = hh;
318 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
319 m_frameMenuBar->m_widget,
320 xx, yy, ww, hh );
321 client_area_y_offset += hh;
322 }
323#endif // wxUSE_MENUS_NATIVE
324
325#if wxUSE_TOOLBAR
326 if ((m_frameToolBar) && m_frameToolBar->IsShown() &&
327 (m_frameToolBar->m_widget->parent == m_mainWidget))
328 {
329 int xx = m_miniEdge;
330 int yy = m_miniEdge + m_miniTitle;
331#if wxUSE_MENUS_NATIVE
332 if (m_frameMenuBar)
333 {
334 if (!m_menuBarDetached)
335 yy += m_menuBarHeight;
336 else
337 yy += wxPLACE_HOLDER;
338 }
339#endif // wxUSE_MENUS_NATIVE
340
341 m_frameToolBar->m_x = xx;
342 m_frameToolBar->m_y = yy;
343
344 // don't change the toolbar's reported height/width
345 int ww, hh;
346 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
347 {
348 ww = m_toolBarDetached ? wxPLACE_HOLDER
349 : m_frameToolBar->m_width;
350 hh = m_height - 2*m_miniEdge;
351
352 client_area_x_offset += ww;
353 }
354 else if( m_frameToolBar->HasFlag(wxTB_RIGHT) )
355 {
356 yy += 2;
357 ww = m_toolBarDetached ? wxPLACE_HOLDER
358 : m_frameToolBar->m_width;
359 xx = GetClientSize().x - 1;
360 hh = m_height - 2*m_miniEdge;
361 if( hh < 0 )
362 hh = 0;
363
364 }
365 else if( m_frameToolBar->GetWindowStyle() & wxTB_BOTTOM )
366 {
367 xx = m_miniEdge;
368 yy = GetClientSize().y;
369#if wxUSE_MENUS_NATIVE
370 yy += m_menuBarHeight;
371#endif // wxUSE_MENU_NATIVE
372 m_frameToolBar->m_x = xx;
373 m_frameToolBar->m_y = yy;
374 ww = m_width - 2*m_miniEdge;
375 hh = m_toolBarDetached ? wxPLACE_HOLDER
376 : m_frameToolBar->m_height;
377 }
378 else
379 {
380 ww = m_width - 2*m_miniEdge;
381 hh = m_toolBarDetached ? wxPLACE_HOLDER
382 : m_frameToolBar->m_height;
383
384 client_area_y_offset += hh;
385 }
386
387 if (ww < 0)
388 ww = 0;
389 if (hh < 0)
390 hh = 0;
391 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
392 m_frameToolBar->m_widget,
393 xx, yy, ww, hh );
394 }
395#endif // wxUSE_TOOLBAR
396
397 int client_x = client_area_x_offset + m_miniEdge;
398 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
399 int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
400 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
401 if (client_w < 0)
402 client_w = 0;
403 if (client_h < 0)
404 client_h = 0;
405 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
406 m_wxwindow,
407 client_x, client_y, client_w, client_h );
408 }
409 else
410 {
411 // If there is no m_mainWidget between m_widget and m_wxwindow there
412 // is no need to set the size or position of m_wxwindow.
413 }
414
415#if wxUSE_STATUSBAR
416 if (m_frameStatusBar && m_frameStatusBar->IsShown())
417 {
418 int xx = 0 + m_miniEdge;
419 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
420 int ww = m_width - 2*m_miniEdge;
421 if (ww < 0)
422 ww = 0;
423 int hh = wxSTATUS_HEIGHT;
424 m_frameStatusBar->m_x = xx;
425 m_frameStatusBar->m_y = yy;
426 m_frameStatusBar->m_width = ww;
427 m_frameStatusBar->m_height = hh;
428 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
429 m_frameStatusBar->m_widget,
430 xx, yy, ww, hh );
431 }
432#endif // wxUSE_STATUSBAR
433
434 m_sizeSet = true;
435
436 // send size event to frame
437 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
438 event.SetEventObject( this );
439 GetEventHandler()->ProcessEvent( event );
440
441#if wxUSE_STATUSBAR
442 // send size event to status bar
443 if (m_frameStatusBar)
444 {
445 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
446 event2.SetEventObject( m_frameStatusBar );
447 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
448 }
449#endif // wxUSE_STATUSBAR
450
451 m_resizing = false;
452}
453
454void wxFrame::OnInternalIdle()
455{
456 wxFrameBase::OnInternalIdle();
457
458#if wxUSE_MENUS_NATIVE
459 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
460#endif // wxUSE_MENUS_NATIVE
461#if wxUSE_TOOLBAR
462 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
463#endif
464#if wxUSE_STATUSBAR
465 if (m_frameStatusBar)
466 {
467 m_frameStatusBar->OnInternalIdle();
468
469 // There may be controls in the status bar that
470 // need to be updated
471 for ( wxWindowList::compatibility_iterator node = m_frameStatusBar->GetChildren().GetFirst();
472 node;
473 node = node->GetNext() )
474 {
475 wxWindow *child = node->GetData();
476 child->OnInternalIdle();
477 }
478 }
479#endif
480}
481
482// ----------------------------------------------------------------------------
483// menu/tool/status bar stuff
484// ----------------------------------------------------------------------------
485
486#if wxUSE_MENUS_NATIVE
487
488void wxFrame::DetachMenuBar()
489{
490 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
491 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
492
493 if ( m_frameMenuBar )
494 {
495 m_frameMenuBar->UnsetInvokingWindow( this );
496
497 if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
498 {
499 g_signal_handlers_disconnect_by_func (m_frameMenuBar->m_widget,
500 (gpointer) gtk_menu_attached_callback,
501 this);
502
503 g_signal_handlers_disconnect_by_func (m_frameMenuBar->m_widget,
504 (gpointer) gtk_menu_detached_callback,
505 this);
506 }
507
508 gtk_widget_ref( m_frameMenuBar->m_widget );
509
510 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
511 }
512
513 wxFrameBase::DetachMenuBar();
514}
515
516void wxFrame::AttachMenuBar( wxMenuBar *menuBar )
517{
518 wxFrameBase::AttachMenuBar(menuBar);
519
520 if (m_frameMenuBar)
521 {
522 m_frameMenuBar->SetInvokingWindow( this );
523
524 m_frameMenuBar->SetParent(this);
525 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
526 m_frameMenuBar->m_widget,
527 m_frameMenuBar->m_x,
528 m_frameMenuBar->m_y,
529 m_frameMenuBar->m_width,
530 m_frameMenuBar->m_height );
531
532 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
533 {
534 g_signal_connect (menuBar->m_widget, "child_attached",
535 G_CALLBACK (gtk_menu_attached_callback),
536 this);
537 g_signal_connect (menuBar->m_widget, "child_detached",
538 G_CALLBACK (gtk_menu_detached_callback),
539 this);
540 }
541
542 gtk_widget_show( m_frameMenuBar->m_widget );
543
544 UpdateMenuBarSize();
545 }
546 else
547 {
548 m_menuBarHeight = 2;
549 GtkUpdateSize(); // resize window in OnInternalIdle
550 }
551}
552
553void wxFrame::UpdateMenuBarSize()
554{
555 m_menuBarHeight = 2;
556
557 // this is called after Remove with a NULL m_frameMenuBar
558 if ( m_frameMenuBar )
559 {
560 GtkRequisition req;
561 gtk_widget_ensure_style(m_frameMenuBar->m_widget);
562 // have to call class method directly because
563 // "size_request" signal is overridden by wx
564 GTK_WIDGET_GET_CLASS(m_frameMenuBar->m_widget)->size_request(
565 m_frameMenuBar->m_widget, &req);
566
567 m_menuBarHeight = req.height;
568 }
569
570 // resize window in OnInternalIdle
571 GtkUpdateSize();
572}
573
574#endif // wxUSE_MENUS_NATIVE
575
576#if wxUSE_TOOLBAR
577
578wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
579{
580 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
581
582 InsertChildFunction save = m_insertCallback;
583 m_insertCallback = wxInsertChildInFrame;
584 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
585 m_insertCallback = save;
586
587 GtkUpdateSize();
588
589 return m_frameToolBar;
590}
591
592void wxFrame::SetToolBar(wxToolBar *toolbar)
593{
594 bool hadTbar = m_frameToolBar != NULL;
595
596 wxFrameBase::SetToolBar(toolbar);
597
598 if ( m_frameToolBar )
599 {
600 // insert into toolbar area if not already there
601 if ((m_frameToolBar->m_widget->parent) &&
602 (m_frameToolBar->m_widget->parent != m_mainWidget))
603 {
604 GetChildren().DeleteObject( m_frameToolBar );
605
606 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
607 GtkUpdateSize();
608 }
609 }
610 else // toolbar unset
611 {
612 // still need to update size if it had been there before
613 if ( hadTbar )
614 {
615 GtkUpdateSize();
616 }
617 }
618}
619
620#endif // wxUSE_TOOLBAR
621
622#if wxUSE_STATUSBAR
623
624wxStatusBar* wxFrame::CreateStatusBar(int number,
625 long style,
626 wxWindowID id,
627 const wxString& name)
628{
629 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
630
631 // because it will change when toolbar is added
632 GtkUpdateSize();
633
634 return wxFrameBase::CreateStatusBar( number, style, id, name );
635}
636
637void wxFrame::SetStatusBar(wxStatusBar *statbar)
638{
639 bool hadStatBar = m_frameStatusBar != NULL;
640
641 wxFrameBase::SetStatusBar(statbar);
642
643 if (hadStatBar && !m_frameStatusBar)
644 GtkUpdateSize();
645}
646
647void wxFrame::PositionStatusBar()
648{
649 if ( !m_frameStatusBar )
650 return;
651
652 GtkUpdateSize();
653}
654#endif // wxUSE_STATUSBAR