Use a GtkVBox to do TLW layout. Rework some of the remaining sizing code.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49406 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Paul Cornett
2007-10-24 18:07:24 +00:00
parent a2d3826500
commit cca410b336
16 changed files with 343 additions and 900 deletions

View File

@@ -19,14 +19,6 @@
#endif // WX_PRECOMP
#include <gtk/gtk.h>
#include "wx/gtk/win_gtk.h"
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
static const int wxSTATUS_HEIGHT = 25;
static const int wxPLACE_HOLDER = 0;
// ----------------------------------------------------------------------------
// event tables
@@ -38,87 +30,12 @@ IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxTopLevelWindow)
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// GTK callbacks
// ----------------------------------------------------------------------------
#if wxUSE_MENUS_NATIVE
//-----------------------------------------------------------------------------
// "child_attached" of menu bar
//-----------------------------------------------------------------------------
extern "C" {
static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
{
if (!win->m_hasVMT) return;
win->m_menuBarDetached = false;
win->GtkUpdateSize();
}
}
//-----------------------------------------------------------------------------
// "child_detached" of menu bar
//-----------------------------------------------------------------------------
extern "C" {
static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
{
if (!win->m_hasVMT) return;
// Raise the client area area
gdk_window_raise( win->m_wxwindow->window );
win->m_menuBarDetached = true;
win->GtkUpdateSize();
}
}
#endif // wxUSE_MENUS_NATIVE
#if wxUSE_TOOLBAR
//-----------------------------------------------------------------------------
// "child_attached" of tool bar
//-----------------------------------------------------------------------------
extern "C" {
static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
{
if (!win->m_hasVMT) return;
win->m_toolBarDetached = false;
win->GtkUpdateSize();
}
}
//-----------------------------------------------------------------------------
// "child_detached" of tool bar
//-----------------------------------------------------------------------------
extern "C" {
static void gtk_toolbar_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
{
if (!win->m_hasVMT) return;
// Raise the client area area
gdk_window_raise( win->m_wxwindow->window );
win->m_toolBarDetached = true;
win->GtkUpdateSize();
}
}
#endif // wxUSE_TOOLBAR
// ----------------------------------------------------------------------------
// wxFrame creation
// ----------------------------------------------------------------------------
void wxFrame::Init()
{
m_menuBarDetached = false;
m_toolBarDetached = false;
m_menuBarHeight = 2;
m_fsSaveFlag = 0;
}
@@ -153,33 +70,36 @@ void wxFrame::DoGetClientSize( int *width, int *height ) const
{
#if wxUSE_MENUS_NATIVE
// menu bar
if (HasVisibleMenubar() && !m_menuBarDetached)
if (m_frameMenuBar && m_frameMenuBar->IsShown())
{
*height -= m_menuBarHeight;
GtkRequisition req;
gtk_widget_size_request(m_frameMenuBar->m_widget, &req);
*height -= req.height;
}
#endif // wxUSE_MENUS_NATIVE
#if wxUSE_STATUSBAR
// status bar
if (m_frameStatusBar && GTK_WIDGET_VISIBLE(m_frameStatusBar->m_widget))
*height -= wxSTATUS_HEIGHT;
if (m_frameStatusBar && m_frameStatusBar->IsShown())
*height -= m_frameStatusBar->m_height;
#endif // wxUSE_STATUSBAR
}
#if wxUSE_TOOLBAR
// tool bar
if (m_frameToolBar &&
GTK_WIDGET_VISIBLE(m_frameToolBar->m_widget) && !m_toolBarDetached)
if (m_frameToolBar && m_frameToolBar->IsShown())
{
GtkRequisition req;
gtk_widget_size_request(m_frameToolBar->m_widget, &req);
if (m_frameToolBar->IsVertical())
{
if (width)
*width -= m_frameToolBar->GetSize().x;
*width -= req.width;
}
else
{
if (height)
*height -= m_frameToolBar->GetSize().y;
*height -= req.height;
}
}
#endif // wxUSE_TOOLBAR
@@ -239,188 +159,6 @@ bool wxFrame::ShowFullScreen(bool show, long style)
return true;
}
void wxFrame::GtkOnSize()
{
// avoid recursions
if (m_resizing) return;
m_resizing = true;
// this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
// space occupied by m_frameToolBar and m_frameMenuBar
int client_area_x_offset = 0,
client_area_y_offset = 0;
/* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
set in wxFrame::Create so it is used to check what kind of frame we
have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
skip the part which handles m_frameMenuBar, m_frameToolBar and (most
importantly) m_mainWidget */
ConstrainSize();
int width, height;
GTKDoGetSize(&width, &height);
if (m_mainWidget)
{
// TODO
// Rewrite this terrible code to using GtkVBox
// m_mainWidget holds the menubar, the toolbar and the client
// area, which is represented by m_wxwindow.
#if wxUSE_MENUS_NATIVE
int menubarHeight = 0;
#endif
#if wxUSE_MENUS_NATIVE
if (HasVisibleMenubar())
{
int xx = m_miniEdge;
int yy = m_miniEdge + m_miniTitle;
int ww = width - 2*m_miniEdge;
if (ww < 0)
ww = 0;
menubarHeight = m_menuBarHeight;
if (m_menuBarDetached) menubarHeight = wxPLACE_HOLDER;
m_frameMenuBar->m_x = xx;
m_frameMenuBar->m_y = yy;
m_frameMenuBar->m_width = ww;
m_frameMenuBar->m_height = menubarHeight;
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
m_frameMenuBar->m_widget,
xx, yy, ww, menubarHeight);
client_area_y_offset += menubarHeight;
}
#endif // wxUSE_MENUS_NATIVE
#if wxUSE_TOOLBAR
if ((m_frameToolBar) && m_frameToolBar->IsShown() &&
(m_frameToolBar->m_widget->parent == m_mainWidget))
{
int xx = m_miniEdge;
int yy = m_miniEdge + m_miniTitle
#if wxUSE_MENUS_NATIVE
+ menubarHeight
#endif
;
m_frameToolBar->m_x = xx;
m_frameToolBar->m_y = yy;
// don't change the toolbar's reported height/width
int ww, hh;
if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
{
ww = m_toolBarDetached ? wxPLACE_HOLDER
: m_frameToolBar->m_width;
hh = height - 2*m_miniEdge;
client_area_x_offset += ww;
}
else if( m_frameToolBar->HasFlag(wxTB_RIGHT) )
{
yy += 2;
ww = m_toolBarDetached ? wxPLACE_HOLDER
: m_frameToolBar->m_width;
xx = GetClientSize().x - 1;
hh = height - 2*m_miniEdge;
if( hh < 0 )
hh = 0;
}
else if( m_frameToolBar->GetWindowStyle() & wxTB_BOTTOM )
{
xx = m_miniEdge;
yy = GetClientSize().y;
#if wxUSE_MENUS_NATIVE
yy += m_menuBarHeight;
#endif // wxUSE_MENUS_NATIVE
m_frameToolBar->m_x = xx;
m_frameToolBar->m_y = yy;
ww = width - 2*m_miniEdge;
hh = m_toolBarDetached ? wxPLACE_HOLDER
: m_frameToolBar->m_height;
}
else
{
ww = width - 2*m_miniEdge;
hh = m_toolBarDetached ? wxPLACE_HOLDER
: m_frameToolBar->m_height;
client_area_y_offset += hh;
}
if (ww < 0)
ww = 0;
if (hh < 0)
hh = 0;
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
m_frameToolBar->m_widget,
xx, yy, ww, hh );
}
#endif // wxUSE_TOOLBAR
int client_x = client_area_x_offset + m_miniEdge;
int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
int client_w = width - client_area_x_offset - 2*m_miniEdge;
int client_h = height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
if (client_w < 0)
client_w = 0;
if (client_h < 0)
client_h = 0;
gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
m_wxwindow,
client_x, client_y, client_w, client_h );
}
else
{
// If there is no m_mainWidget between m_widget and m_wxwindow there
// is no need to set the size or position of m_wxwindow.
}
#if wxUSE_STATUSBAR
if (m_frameStatusBar && m_frameStatusBar->IsShown())
{
int xx = 0 + m_miniEdge;
int yy = height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
int ww = width - 2*m_miniEdge;
if (ww < 0)
ww = 0;
int hh = wxSTATUS_HEIGHT;
m_frameStatusBar->m_x = xx;
m_frameStatusBar->m_y = yy;
m_frameStatusBar->m_width = ww;
m_frameStatusBar->m_height = hh;
gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
m_frameStatusBar->m_widget,
xx, yy, ww, hh );
}
#endif // wxUSE_STATUSBAR
m_sizeSet = true;
// send size event to frame
wxSizeEvent event( wxSize(m_width,m_height), GetId() );
event.SetEventObject( this );
GetEventHandler()->ProcessEvent( event );
#if wxUSE_STATUSBAR
// send size event to status bar
if (m_frameStatusBar)
{
wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
event2.SetEventObject( m_frameStatusBar );
m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
}
#endif // wxUSE_STATUSBAR
m_resizing = false;
}
void wxFrame::OnInternalIdle()
{
wxFrameBase::OnInternalIdle();
@@ -464,23 +202,15 @@ void wxFrame::DetachMenuBar()
{
m_frameMenuBar->UnsetInvokingWindow( this );
if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
{
g_signal_handlers_disconnect_by_func (m_frameMenuBar->m_widget,
(gpointer) gtk_menu_attached_callback,
this);
g_signal_handlers_disconnect_by_func (m_frameMenuBar->m_widget,
(gpointer) gtk_menu_detached_callback,
this);
}
gtk_widget_ref( m_frameMenuBar->m_widget );
gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
}
wxFrameBase::DetachMenuBar();
// make sure next size_allocate causes a wxSizeEvent
m_oldClientWidth = 0;
}
void wxFrame::AttachMenuBar( wxMenuBar *menuBar )
@@ -492,58 +222,29 @@ void wxFrame::AttachMenuBar( wxMenuBar *menuBar )
m_frameMenuBar->SetInvokingWindow( this );
m_frameMenuBar->SetParent(this);
gtk_pizza_put( GTK_PIZZA(m_mainWidget),
m_frameMenuBar->m_widget,
m_frameMenuBar->m_x,
m_frameMenuBar->m_y,
m_frameMenuBar->m_width,
m_frameMenuBar->m_height );
if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
{
g_signal_connect (menuBar->m_widget, "child_attached",
G_CALLBACK (gtk_menu_attached_callback),
this);
g_signal_connect (menuBar->m_widget, "child_detached",
G_CALLBACK (gtk_menu_detached_callback),
this);
}
// menubar goes into top of vbox (m_mainWidget)
gtk_box_pack_start(
GTK_BOX(m_mainWidget), menuBar->m_widget, false, false, 0);
gtk_box_reorder_child(GTK_BOX(m_mainWidget), menuBar->m_widget, 0);
// disconnect wxWindowGTK "size_request" handler,
// it interferes with sizing of detached GtkHandleBox
gulong handler_id = g_signal_handler_find(
menuBar->m_widget,
GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA),
g_signal_lookup("size_request", GTK_TYPE_WIDGET),
0, NULL, NULL, menuBar);
if (handler_id != 0)
g_signal_handler_disconnect(menuBar->m_widget, handler_id);
// reset size request to allow native sizing to work
gtk_widget_set_size_request(menuBar->m_widget, -1, -1);
gtk_widget_show( m_frameMenuBar->m_widget );
UpdateMenuBarSize();
}
else
{
m_menuBarHeight = 2;
GtkUpdateSize(); // resize window in OnInternalIdle
}
}
void wxFrame::UpdateMenuBarSize()
{
m_menuBarHeight = 2;
// this is called after Remove with a NULL m_frameMenuBar
if ( m_frameMenuBar )
{
GtkRequisition req;
gtk_widget_ensure_style(m_frameMenuBar->m_widget);
// have to call class method directly because
// "size_request" signal is overridden by wx
GTK_WIDGET_GET_CLASS(m_frameMenuBar->m_widget)->size_request(
m_frameMenuBar->m_widget, &req);
m_menuBarHeight = req.height;
}
// resize window in OnInternalIdle
GtkUpdateSize();
}
bool wxFrame::HasVisibleMenubar() const
{
return m_frameMenuBar && m_frameMenuBar->IsShown();
// make sure next size_allocate causes a wxSizeEvent
m_oldClientWidth = 0;
}
#endif // wxUSE_MENUS_NATIVE
@@ -551,30 +252,61 @@ bool wxFrame::HasVisibleMenubar() const
void wxFrame::SetToolBar(wxToolBar *toolbar)
{
wxFrameBase::SetToolBar(toolbar);
if ( m_frameToolBar )
m_frameToolBar = toolbar;
if (toolbar)
{
// insert into toolbar area if not already there
if ((m_frameToolBar->m_widget->parent) &&
(m_frameToolBar->m_widget->parent != m_mainWidget))
if (toolbar->IsVertical())
{
GetChildren().DeleteObject( m_frameToolBar );
// Vertical toolbar and m_wxwindow go into an hbox, inside the
// vbox (m_mainWidget). hbox is created on demand.
GtkWidget* hbox = m_wxwindow->parent;
if (!GTK_IS_HBOX(hbox))
{
hbox = gtk_hbox_new(false, 0);
gtk_widget_show(hbox);
gtk_container_add(GTK_CONTAINER(m_mainWidget), hbox);
gtk_widget_reparent(m_wxwindow, hbox);
}
gtk_widget_reparent(toolbar->m_widget, hbox);
gtk_box_set_child_packing(GTK_BOX(hbox),
toolbar->m_widget, false, false, 0, GTK_PACK_START);
gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
int pos = 0; // left
if (toolbar->HasFlag(wxTB_RIGHT))
pos = 1; // right
gtk_box_reorder_child(GTK_BOX(hbox), toolbar->m_widget, pos);
}
#if wxUSE_TOOLBAR_NATIVE
if (m_frameToolBar->HasFlag(wxTB_DOCKABLE))
else
{
g_signal_connect(m_frameToolBar->m_widget, "child_attached",
G_CALLBACK(gtk_toolbar_attached_callback), this);
g_signal_connect(m_frameToolBar->m_widget, "child_detached",
G_CALLBACK(gtk_toolbar_detached_callback), this);
// Horizontal toolbar goes into vbox (m_mainWidget)
gtk_widget_reparent(toolbar->m_widget, m_mainWidget);
gtk_box_set_child_packing(GTK_BOX(m_mainWidget),
toolbar->m_widget, false, false, 0, GTK_PACK_START);
int pos = 0; // top
if (m_frameMenuBar)
pos = 1; // below menubar
if (toolbar->HasFlag(wxTB_BOTTOM))
pos += 2; // below client area (m_wxwindow)
gtk_box_reorder_child(
GTK_BOX(m_mainWidget), toolbar->m_widget, pos);
}
#endif // wxUSE_TOOLBAR_NATIVE
// disconnect wxWindowGTK "size_request" handler,
// it interferes with sizing of detached GtkHandleBox
gulong handler_id = g_signal_handler_find(
toolbar->m_widget,
GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA),
g_signal_lookup("size_request", GTK_TYPE_WIDGET),
0, NULL, NULL, toolbar);
if (handler_id != 0)
g_signal_handler_disconnect(toolbar->m_widget, handler_id);
// reset size request to allow native sizing to work
gtk_widget_set_size_request(toolbar->m_widget, -1, -1);
}
GtkUpdateSize();
// make sure next size_allocate causes a wxSizeEvent
m_oldClientWidth = 0;
}
#endif // wxUSE_TOOLBAR
@@ -583,7 +315,17 @@ void wxFrame::SetToolBar(wxToolBar *toolbar)
void wxFrame::SetStatusBar(wxStatusBar *statbar)
{
wxFrameBase::SetStatusBar(statbar);
GtkUpdateSize();
m_frameStatusBar = statbar;
if (statbar)
{
// statusbar goes into bottom of vbox (m_mainWidget)
gtk_widget_reparent(statbar->m_widget, m_mainWidget);
gtk_box_set_child_packing(GTK_BOX(m_mainWidget),
statbar->m_widget, false, false, 0, GTK_PACK_END);
// make sure next size_allocate on statusbar causes a size event
statbar->m_oldClientWidth = 0;
}
// make sure next size_allocate causes a wxSizeEvent
m_oldClientWidth = 0;
}
#endif // wxUSE_STATUSBAR