1
/////////////////////////////////////////////////////////////////////////////
2
// Name: src/gtk/frame.cpp
4
// Author: Robert Roebling
5
// Id: $Id: frame.cpp 62616 2009-11-11 18:04:09Z PC $
6
// Copyright: (c) 1998 Robert Roebling
7
// Licence: wxWindows licence
8
/////////////////////////////////////////////////////////////////////////////
10
// For compilers that support precompilation, includes "wx.h".
11
#include "wx/wxprec.h"
17
#include "wx/toolbar.h"
18
#include "wx/statusbr.h"
21
#include "wx/gtk/private.h"
22
#include "wx/gtk/win_gtk.h"
24
// ----------------------------------------------------------------------------
26
// ----------------------------------------------------------------------------
28
static const int wxSTATUS_HEIGHT = 25;
29
static const int wxPLACE_HOLDER = 0;
31
// ----------------------------------------------------------------------------
33
// ----------------------------------------------------------------------------
35
IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxTopLevelWindow)
37
// ============================================================================
39
// ============================================================================
41
// ----------------------------------------------------------------------------
43
// ----------------------------------------------------------------------------
45
#if wxUSE_MENUS_NATIVE
47
//-----------------------------------------------------------------------------
48
// "child_attached" of menu bar
49
//-----------------------------------------------------------------------------
52
static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
54
if (!win->m_hasVMT) return;
56
win->m_menuBarDetached = false;
61
//-----------------------------------------------------------------------------
62
// "child_detached" of menu bar
63
//-----------------------------------------------------------------------------
66
static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
69
wxapp_install_idle_handler();
71
if (!win->m_hasVMT) return;
73
// Raise the client area area
74
gdk_window_raise( win->m_wxwindow->window );
76
win->m_menuBarDetached = true;
81
//-----------------------------------------------------------------------------
82
// "size-request" from menubar
83
//-----------------------------------------------------------------------------
86
static void menubar_size_request(GtkWidget* widget, GtkRequisition*, wxFrame* win)
88
g_signal_handlers_disconnect_by_func(
89
widget, (void*)menubar_size_request, win);
90
win->UpdateMenuBarSize();
94
//-----------------------------------------------------------------------------
95
// "style-set" from menubar
96
//-----------------------------------------------------------------------------
99
static void menubar_style_set(GtkWidget* widget, GtkStyle*, wxFrame* win)
101
g_signal_connect(widget, "size-request",
102
G_CALLBACK(menubar_size_request), win);
105
#endif // wxUSE_MENUS_NATIVE
108
//-----------------------------------------------------------------------------
109
// "child_attached" of tool bar
110
//-----------------------------------------------------------------------------
113
static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
115
if (!win->m_hasVMT) return;
117
win->m_toolBarDetached = false;
118
win->GtkUpdateSize();
122
//-----------------------------------------------------------------------------
123
// "child_detached" of tool bar
124
//-----------------------------------------------------------------------------
127
static void gtk_toolbar_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
130
wxapp_install_idle_handler();
132
if (!win->m_hasVMT) return;
134
// Raise the client area area
135
gdk_window_raise( win->m_wxwindow->window );
137
win->m_toolBarDetached = true;
138
win->GtkUpdateSize();
141
#endif // wxUSE_TOOLBAR
144
// ----------------------------------------------------------------------------
146
// ----------------------------------------------------------------------------
148
//-----------------------------------------------------------------------------
149
// InsertChild for wxFrame
150
//-----------------------------------------------------------------------------
152
/* Callback for wxFrame. This very strange beast has to be used because
153
* C++ has no virtual methods in a constructor. We have to emulate a
154
* virtual function here as wxWidgets requires different ways to insert
155
* a child in container classes. */
157
static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
159
wxASSERT( GTK_IS_WIDGET(child->m_widget) );
161
if (!parent->m_insertInClientArea)
163
// These are outside the client area
164
wxFrame* frame = (wxFrame*) parent;
165
gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
166
GTK_WIDGET(child->m_widget),
172
#if wxUSE_TOOLBAR_NATIVE
173
// We connect to these events for recalculating the client area
174
// space when the toolbar is floating
175
if (wxIS_KIND_OF(child,wxToolBar))
177
wxToolBar *toolBar = (wxToolBar*) child;
178
if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
180
g_signal_connect (toolBar->m_widget, "child_attached",
181
G_CALLBACK (gtk_toolbar_attached_callback),
183
g_signal_connect (toolBar->m_widget, "child_detached",
184
G_CALLBACK (gtk_toolbar_detached_callback),
188
#endif // wxUSE_TOOLBAR
192
// These are inside the client area
193
gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
194
GTK_WIDGET(child->m_widget),
202
// ----------------------------------------------------------------------------
204
// ----------------------------------------------------------------------------
208
m_menuBarDetached = false;
209
m_toolBarDetached = false;
213
bool wxFrame::Create( wxWindow *parent,
215
const wxString& title,
217
const wxSize& sizeOrig,
219
const wxString &name )
221
bool rt = wxTopLevelWindow::Create(parent, id, title, pos, sizeOrig,
223
m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
230
m_isBeingDeleted = true;
234
// ----------------------------------------------------------------------------
235
// overridden wxWindow methods
236
// ----------------------------------------------------------------------------
238
void wxFrame::DoGetClientSize( int *width, int *height ) const
240
wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
242
wxTopLevelWindow::DoGetClientSize( width, height );
246
#if wxUSE_MENUS_NATIVE
248
if (m_frameMenuBar && !(m_fsIsShowing && (m_fsSaveFlag & wxFULLSCREEN_NOMENUBAR) != 0))
250
if (!m_menuBarDetached)
251
(*height) -= m_menuBarHeight;
253
(*height) -= wxPLACE_HOLDER;
255
#endif // wxUSE_MENUS_NATIVE
259
if (m_frameStatusBar && m_frameStatusBar->IsShown() &&
260
!(m_fsIsShowing && (m_fsSaveFlag & wxFULLSCREEN_NOSTATUSBAR) != 0))
261
(*height) -= wxSTATUS_HEIGHT;
262
#endif // wxUSE_STATUSBAR
267
if (m_frameToolBar && m_frameToolBar->IsShown())
269
if (m_toolBarDetached)
272
*height -= wxPLACE_HOLDER;
277
m_frameToolBar->GetSize( &x, &y );
278
if ( m_frameToolBar->IsVertical() )
290
#endif // wxUSE_TOOLBAR
292
if (width != NULL && *width < 0)
294
if (height != NULL && *height < 0)
298
void wxFrame::DoSetClientSize( int width, int height )
300
wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
302
#if wxUSE_MENUS_NATIVE
304
if (m_frameMenuBar && !(m_fsIsShowing && (m_fsSaveFlag & wxFULLSCREEN_NOMENUBAR) != 0))
306
if (!m_menuBarDetached)
307
height += m_menuBarHeight;
309
height += wxPLACE_HOLDER;
311
#endif // wxUSE_MENUS_NATIVE
315
if (m_frameStatusBar && m_frameStatusBar->IsShown() &&
316
!(m_fsIsShowing && (m_fsSaveFlag & wxFULLSCREEN_NOSTATUSBAR) != 0))
317
height += wxSTATUS_HEIGHT;
322
if (m_frameToolBar && m_frameToolBar->IsShown())
324
if (m_toolBarDetached)
326
height += wxPLACE_HOLDER;
331
m_frameToolBar->GetSize( &x, &y );
332
if ( m_frameToolBar->IsVertical() )
344
wxTopLevelWindow::DoSetClientSize( width, height );
347
void wxFrame::GtkOnSize()
350
if (m_resizing) return;
353
// this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
354
wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
356
// space occupied by m_frameToolBar and m_frameMenuBar
357
int client_area_x_offset = 0,
358
client_area_y_offset = 0;
360
/* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
361
wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
362
set in wxFrame::Create so it is used to check what kind of frame we
363
have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
364
skip the part which handles m_frameMenuBar, m_frameToolBar and (most
365
importantly) m_mainWidget */
367
int minWidth = GetMinWidth(),
368
minHeight = GetMinHeight(),
369
maxWidth = GetMaxWidth(),
370
maxHeight = GetMaxHeight();
372
if ((minWidth != -1) && (m_width < minWidth)) m_width = minWidth;
373
if ((minHeight != -1) && (m_height < minHeight)) m_height = minHeight;
374
if ((maxWidth != -1) && (m_width > maxWidth)) m_width = maxWidth;
375
if ((maxHeight != -1) && (m_height > maxHeight)) m_height = maxHeight;
380
// Rewrite this terrible code to using GtkVBox
382
// m_mainWidget holds the menubar, the toolbar and the client
383
// area, which is represented by m_wxwindow.
385
#if wxUSE_MENUS_NATIVE
386
if (m_frameMenuBar && !(m_fsIsShowing && (m_fsSaveFlag & wxFULLSCREEN_NOMENUBAR) != 0))
388
if (m_frameMenuBar->IsShown() && !GTK_WIDGET_VISIBLE(m_frameMenuBar->m_widget))
389
gtk_widget_show( m_frameMenuBar->m_widget );
391
int yy = m_miniEdge + m_miniTitle;
392
int ww = m_width - 2*m_miniEdge;
395
int hh = m_menuBarHeight;
396
if (m_menuBarDetached) hh = wxPLACE_HOLDER;
397
m_frameMenuBar->m_x = xx;
398
m_frameMenuBar->m_y = yy;
399
m_frameMenuBar->m_width = ww;
400
m_frameMenuBar->m_height = hh;
401
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
402
m_frameMenuBar->m_widget,
404
client_area_y_offset += hh;
410
if (GTK_WIDGET_VISIBLE(m_frameMenuBar->m_widget))
411
gtk_widget_hide( m_frameMenuBar->m_widget );
414
#endif // wxUSE_MENUS_NATIVE
417
if ((m_frameToolBar) && m_frameToolBar->IsShown() &&
418
(m_frameToolBar->m_widget->parent == m_mainWidget))
421
int yy = m_miniEdge + m_miniTitle;
422
#if wxUSE_MENUS_NATIVE
425
if (!m_menuBarDetached)
426
yy += m_menuBarHeight;
428
yy += wxPLACE_HOLDER;
430
#endif // wxUSE_MENUS_NATIVE
432
m_frameToolBar->m_x = xx;
433
m_frameToolBar->m_y = yy;
435
// don't change the toolbar's reported height/width
437
if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
439
ww = m_toolBarDetached ? wxPLACE_HOLDER
440
: m_frameToolBar->m_width;
441
hh = m_height - 2*m_miniEdge;
443
client_area_x_offset += ww;
445
else if( m_frameToolBar->HasFlag(wxTB_RIGHT) )
448
ww = m_toolBarDetached ? wxPLACE_HOLDER
449
: m_frameToolBar->m_width;
450
xx = GetClientSize().x - 1;
451
hh = m_height - 2*m_miniEdge;
456
else if( m_frameToolBar->GetWindowStyle() & wxTB_BOTTOM )
459
yy = GetClientSize().y;
460
#if wxUSE_MENUS_NATIVE
461
yy += m_menuBarHeight;
462
#endif // wxUSE_MENU_NATIVE
463
m_frameToolBar->m_x = xx;
464
m_frameToolBar->m_y = yy;
465
ww = m_width - 2*m_miniEdge;
466
hh = m_toolBarDetached ? wxPLACE_HOLDER
467
: m_frameToolBar->m_height;
471
ww = m_width - 2*m_miniEdge;
472
hh = m_toolBarDetached ? wxPLACE_HOLDER
473
: m_frameToolBar->m_height;
475
client_area_y_offset += hh;
482
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
483
m_frameToolBar->m_widget,
486
#endif // wxUSE_TOOLBAR
488
int client_x = client_area_x_offset + m_miniEdge;
489
int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
490
int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
491
int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
496
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
498
client_x, client_y, client_w, client_h );
502
// If there is no m_mainWidget between m_widget and m_wxwindow there
503
// is no need to set the size or position of m_wxwindow.
507
if (m_frameStatusBar && m_frameStatusBar->IsShown() &&
508
!(m_fsIsShowing && (m_fsSaveFlag & wxFULLSCREEN_NOSTATUSBAR) != 0))
510
if (!GTK_WIDGET_VISIBLE(m_frameStatusBar->m_widget))
511
gtk_widget_show( m_frameStatusBar->m_widget );
513
int xx = 0 + m_miniEdge;
514
int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
515
int ww = m_width - 2*m_miniEdge;
518
int hh = wxSTATUS_HEIGHT;
519
m_frameStatusBar->m_x = xx;
520
m_frameStatusBar->m_y = yy;
521
m_frameStatusBar->m_width = ww;
522
m_frameStatusBar->m_height = hh;
523
gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
524
m_frameStatusBar->m_widget,
529
if (m_frameStatusBar)
531
if (GTK_WIDGET_VISIBLE(m_frameStatusBar->m_widget))
532
gtk_widget_hide( m_frameStatusBar->m_widget );
535
#endif // wxUSE_STATUSBAR
539
// send size event to frame
540
wxSizeEvent event( wxSize(m_width,m_height), GetId() );
541
event.SetEventObject( this );
542
GetEventHandler()->ProcessEvent( event );
545
// send size event to status bar
546
if (m_frameStatusBar)
548
wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
549
event2.SetEventObject( m_frameStatusBar );
550
m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
552
#endif // wxUSE_STATUSBAR
557
void wxFrame::OnInternalIdle()
559
wxFrameBase::OnInternalIdle();
561
#if wxUSE_MENUS_NATIVE
562
if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
563
#endif // wxUSE_MENUS_NATIVE
565
if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
568
if (m_frameStatusBar)
570
m_frameStatusBar->OnInternalIdle();
572
// There may be controls in the status bar that
573
// need to be updated
574
for ( wxWindowList::compatibility_iterator node = m_frameStatusBar->GetChildren().GetFirst();
576
node = node->GetNext() )
578
wxWindow *child = node->GetData();
579
child->OnInternalIdle();
585
// ----------------------------------------------------------------------------
586
// menu/tool/status bar stuff
587
// ----------------------------------------------------------------------------
589
#if wxUSE_MENUS_NATIVE
591
void wxFrame::DetachMenuBar()
593
wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
594
wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
596
if ( m_frameMenuBar )
598
g_signal_handlers_disconnect_by_func(
599
m_frameMenuBar->m_widget, (void*)menubar_style_set, this);
601
m_frameMenuBar->UnsetInvokingWindow( this );
603
if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
605
g_signal_handlers_disconnect_by_func (m_frameMenuBar->m_widget,
606
(gpointer) gtk_menu_attached_callback,
609
g_signal_handlers_disconnect_by_func (m_frameMenuBar->m_widget,
610
(gpointer) gtk_menu_detached_callback,
614
gtk_widget_ref( m_frameMenuBar->m_widget );
616
gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
619
wxFrameBase::DetachMenuBar();
622
void wxFrame::AttachMenuBar( wxMenuBar *menuBar )
624
wxFrameBase::AttachMenuBar(menuBar);
628
m_frameMenuBar->SetInvokingWindow( this );
630
m_frameMenuBar->SetParent(this);
631
gtk_pizza_put( GTK_PIZZA(m_mainWidget),
632
m_frameMenuBar->m_widget,
635
m_frameMenuBar->m_width,
636
m_frameMenuBar->m_height );
638
if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
640
g_signal_connect (menuBar->m_widget, "child_attached",
641
G_CALLBACK (gtk_menu_attached_callback),
643
g_signal_connect (menuBar->m_widget, "child_detached",
644
G_CALLBACK (gtk_menu_detached_callback),
648
gtk_widget_show( m_frameMenuBar->m_widget );
652
g_signal_connect(menuBar->m_widget, "style-set",
653
G_CALLBACK(menubar_style_set), this);
658
GtkUpdateSize(); // resize window in OnInternalIdle
662
void wxFrame::UpdateMenuBarSize()
666
// this is called after Remove with a NULL m_frameMenuBar
667
if ( m_frameMenuBar )
670
gtk_widget_ensure_style(m_frameMenuBar->m_widget);
671
// have to call class method directly because
672
// "size_request" signal is overridden by wx
673
GTK_WIDGET_GET_CLASS(m_frameMenuBar->m_widget)->size_request(
674
m_frameMenuBar->m_widget, &req);
676
m_menuBarHeight = req.height;
679
// resize window in OnInternalIdle
683
#endif // wxUSE_MENUS_NATIVE
687
wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
689
wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
691
m_insertInClientArea = false;
693
m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
695
m_insertInClientArea = true;
699
return m_frameToolBar;
702
void wxFrame::SetToolBar(wxToolBar *toolbar)
704
bool hadTbar = m_frameToolBar != NULL;
706
wxFrameBase::SetToolBar(toolbar);
708
if ( m_frameToolBar )
710
// insert into toolbar area if not already there
711
if ((m_frameToolBar->m_widget->parent) &&
712
(m_frameToolBar->m_widget->parent != m_mainWidget))
714
GetChildren().DeleteObject( m_frameToolBar );
716
gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
720
else // toolbar unset
722
// still need to update size if it had been there before
730
#endif // wxUSE_TOOLBAR
734
wxStatusBar* wxFrame::CreateStatusBar(int number,
737
const wxString& name)
739
wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
741
// because it will change when toolbar is added
744
return wxFrameBase::CreateStatusBar( number, style, id, name );
747
void wxFrame::SetStatusBar(wxStatusBar *statbar)
749
bool hadStatBar = m_frameStatusBar != NULL;
751
wxFrameBase::SetStatusBar(statbar);
753
if (hadStatBar && !m_frameStatusBar)
757
void wxFrame::PositionStatusBar()
759
if ( !m_frameStatusBar )
764
#endif // wxUSE_STATUSBAR