git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58246 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
413 lines
12 KiB
C++
413 lines
12 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/gtk/frame.cpp
|
|
// Purpose:
|
|
// Author: Robert Roebling
|
|
// Id: $Id$
|
|
// Copyright: (c) 1998 Robert Roebling
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#include "wx/frame.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/menu.h"
|
|
#include "wx/toolbar.h"
|
|
#include "wx/statusbr.h"
|
|
#endif // WX_PRECOMP
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#if wxUSE_LIBHILDON
|
|
#include <hildon-widgets/hildon-window.h>
|
|
#endif // wxUSE_LIBHILDON
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// event tables
|
|
// ----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxTopLevelWindow)
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxFrame creation
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void wxFrame::Init()
|
|
{
|
|
m_fsSaveFlag = 0;
|
|
}
|
|
|
|
bool wxFrame::Create( wxWindow *parent,
|
|
wxWindowID id,
|
|
const wxString& title,
|
|
const wxPoint& pos,
|
|
const wxSize& sizeOrig,
|
|
long style,
|
|
const wxString &name )
|
|
{
|
|
return wxFrameBase::Create(parent, id, title, pos, sizeOrig, style, name);
|
|
}
|
|
|
|
wxFrame::~wxFrame()
|
|
{
|
|
SendDestroyEvent();
|
|
|
|
DeleteAllBars();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// overridden wxWindow methods
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void wxFrame::DoGetClientSize( int *width, int *height ) const
|
|
{
|
|
wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
|
|
|
|
wxFrameBase::DoGetClientSize(width, height);
|
|
|
|
if (height)
|
|
{
|
|
#if wxUSE_MENUS_NATIVE
|
|
// menu bar
|
|
if (m_frameMenuBar && m_frameMenuBar->IsShown())
|
|
{
|
|
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 && m_frameStatusBar->IsShown())
|
|
*height -= m_frameStatusBar->m_height;
|
|
#endif // wxUSE_STATUSBAR
|
|
}
|
|
|
|
#if wxUSE_TOOLBAR
|
|
// tool bar
|
|
if (m_frameToolBar && m_frameToolBar->IsShown())
|
|
{
|
|
GtkRequisition req;
|
|
gtk_widget_size_request(m_frameToolBar->m_widget, &req);
|
|
if (m_frameToolBar->IsVertical())
|
|
{
|
|
if (width)
|
|
*width -= req.width;
|
|
}
|
|
else
|
|
{
|
|
if (height)
|
|
*height -= req.height;
|
|
}
|
|
}
|
|
#endif // wxUSE_TOOLBAR
|
|
|
|
if (width != NULL && *width < 0)
|
|
*width = 0;
|
|
if (height != NULL && *height < 0)
|
|
*height = 0;
|
|
}
|
|
|
|
#if wxUSE_MENUS && wxUSE_ACCEL
|
|
// Helper for wxCreateAcceleratorTableForMenuBar
|
|
static void wxAddAccelerators(wxList& accelEntries, wxMenu* menu)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < menu->GetMenuItems().GetCount(); i++)
|
|
{
|
|
wxMenuItem* item = (wxMenuItem*) menu->GetMenuItems().Item(i)->GetData();
|
|
if (item->GetSubMenu())
|
|
{
|
|
wxAddAccelerators(accelEntries, item->GetSubMenu());
|
|
}
|
|
else if (!item->GetItemLabel().IsEmpty())
|
|
{
|
|
wxAcceleratorEntry* entry = wxAcceleratorEntry::Create(item->GetItemLabel());
|
|
if (entry)
|
|
{
|
|
entry->Set(entry->GetFlags(), entry->GetKeyCode(), item->GetId());
|
|
accelEntries.Append((wxObject*) entry);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create an accelerator table consisting of all the accelerators
|
|
// from the menubar in the given menus
|
|
static wxAcceleratorTable wxCreateAcceleratorTableForMenuBar(wxMenuBar* menuBar)
|
|
{
|
|
wxList accelEntries;
|
|
|
|
size_t i;
|
|
for (i = 0; i < menuBar->GetMenuCount(); i++)
|
|
{
|
|
wxAddAccelerators(accelEntries, menuBar->GetMenu(i));
|
|
}
|
|
|
|
size_t n = accelEntries.GetCount();
|
|
|
|
if (n == 0)
|
|
return wxAcceleratorTable();
|
|
|
|
wxAcceleratorEntry* entries = new wxAcceleratorEntry[n];
|
|
|
|
for (i = 0; i < accelEntries.GetCount(); i++)
|
|
{
|
|
wxAcceleratorEntry* entry = (wxAcceleratorEntry*) accelEntries.Item(i)->GetData();
|
|
entries[i] = (*entry);
|
|
delete entry;
|
|
|
|
}
|
|
|
|
wxAcceleratorTable table(n, entries);
|
|
delete[] entries;
|
|
|
|
return table;
|
|
}
|
|
#endif // wxUSE_MENUS && wxUSE_ACCEL
|
|
|
|
bool wxFrame::ShowFullScreen(bool show, long style)
|
|
{
|
|
if (!wxFrameBase::ShowFullScreen(show, style))
|
|
return false;
|
|
|
|
#if wxUSE_MENUS && wxUSE_ACCEL
|
|
if (show && GetMenuBar())
|
|
{
|
|
wxAcceleratorTable table(wxCreateAcceleratorTableForMenuBar(GetMenuBar()));
|
|
if (table.IsOk())
|
|
SetAcceleratorTable(table);
|
|
}
|
|
#endif // wxUSE_MENUS && wxUSE_ACCEL
|
|
|
|
wxWindow* const bar[] = {
|
|
#if wxUSE_MENUS
|
|
m_frameMenuBar,
|
|
#else
|
|
NULL,
|
|
#endif
|
|
#if wxUSE_TOOLBAR
|
|
m_frameToolBar,
|
|
#else
|
|
NULL,
|
|
#endif
|
|
#if wxUSE_STATUSBAR
|
|
m_frameStatusBar,
|
|
#else
|
|
NULL,
|
|
#endif
|
|
};
|
|
const long fsNoBar[] = {
|
|
wxFULLSCREEN_NOMENUBAR, wxFULLSCREEN_NOTOOLBAR, wxFULLSCREEN_NOSTATUSBAR
|
|
};
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
if (show)
|
|
{
|
|
if (bar[i] && (style & fsNoBar[i]))
|
|
{
|
|
if (bar[i]->IsShown())
|
|
bar[i]->Show(false);
|
|
else
|
|
style &= ~fsNoBar[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bar[i] && (m_fsSaveFlag & fsNoBar[i]))
|
|
bar[i]->Show(true);
|
|
}
|
|
}
|
|
if (show)
|
|
m_fsSaveFlag = style;
|
|
|
|
return true;
|
|
}
|
|
|
|
void wxFrame::OnInternalIdle()
|
|
{
|
|
wxFrameBase::OnInternalIdle();
|
|
|
|
#if wxUSE_MENUS_NATIVE
|
|
if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
|
|
#endif // wxUSE_MENUS_NATIVE
|
|
#if wxUSE_TOOLBAR
|
|
if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
|
|
#endif
|
|
#if wxUSE_STATUSBAR
|
|
if (m_frameStatusBar)
|
|
{
|
|
m_frameStatusBar->OnInternalIdle();
|
|
|
|
// There may be controls in the status bar that
|
|
// need to be updated
|
|
for ( wxWindowList::compatibility_iterator node = m_frameStatusBar->GetChildren().GetFirst();
|
|
node;
|
|
node = node->GetNext() )
|
|
{
|
|
wxWindow *child = node->GetData();
|
|
child->OnInternalIdle();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// menu/tool/status bar stuff
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#if wxUSE_MENUS_NATIVE
|
|
|
|
void wxFrame::DetachMenuBar()
|
|
{
|
|
wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
|
|
wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
|
|
|
|
if ( m_frameMenuBar )
|
|
{
|
|
#if wxUSE_LIBHILDON
|
|
hildon_window_set_menu(HILDON_WINDOW(m_widget), NULL);
|
|
#else // !wxUSE_LIBHILDON
|
|
m_frameMenuBar->UnsetInvokingWindow( this );
|
|
|
|
gtk_widget_ref( m_frameMenuBar->m_widget );
|
|
|
|
gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
|
|
#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON
|
|
}
|
|
|
|
wxFrameBase::DetachMenuBar();
|
|
|
|
// make sure next size_allocate causes a wxSizeEvent
|
|
m_oldClientWidth = 0;
|
|
}
|
|
|
|
void wxFrame::AttachMenuBar( wxMenuBar *menuBar )
|
|
{
|
|
wxFrameBase::AttachMenuBar(menuBar);
|
|
|
|
if (m_frameMenuBar)
|
|
{
|
|
#if wxUSE_LIBHILDON
|
|
hildon_window_set_menu(HILDON_WINDOW(m_widget),
|
|
GTK_MENU(m_frameMenuBar->m_menubar));
|
|
#else // !wxUSE_LIBHILDON
|
|
m_frameMenuBar->SetInvokingWindow( this );
|
|
|
|
m_frameMenuBar->SetParent(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 );
|
|
#endif // wxUSE_LIBHILDON/!wxUSE_LIBHILDON
|
|
}
|
|
// make sure next size_allocate causes a wxSizeEvent
|
|
m_oldClientWidth = 0;
|
|
}
|
|
#endif // wxUSE_MENUS_NATIVE
|
|
|
|
#if wxUSE_TOOLBAR
|
|
|
|
void wxFrame::SetToolBar(wxToolBar *toolbar)
|
|
{
|
|
m_frameToolBar = toolbar;
|
|
if (toolbar)
|
|
{
|
|
if (toolbar->IsVertical())
|
|
{
|
|
// 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);
|
|
|
|
int pos = 0; // left
|
|
if (toolbar->HasFlag(wxTB_RIGHT))
|
|
pos = 1; // right
|
|
gtk_box_reorder_child(GTK_BOX(hbox), toolbar->m_widget, pos);
|
|
}
|
|
else
|
|
{
|
|
// 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);
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
// make sure next size_allocate causes a wxSizeEvent
|
|
m_oldClientWidth = 0;
|
|
}
|
|
|
|
#endif // wxUSE_TOOLBAR
|
|
|
|
#if wxUSE_STATUSBAR
|
|
|
|
void wxFrame::SetStatusBar(wxStatusBar *statbar)
|
|
{
|
|
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
|