// Name: src/gtk/mdi.cpp
// Purpose:
// Author: Robert Roebling
-// Id: $Id$
// Copyright: (c) 1998 Robert Roebling
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
extern "C" {
static void
-gtk_mdi_page_change_callback( GtkNotebook *WXUNUSED(widget),
- GtkNotebookPage *page,
- gint WXUNUSED(page_num),
- wxMDIParentFrame *parent )
+switch_page(GtkNotebook* widget, GtkNotebookPage*, guint page_num, wxMDIParentFrame* parent)
{
// send deactivate event to old child
// send activate event to new child
- wxMDIClientWindow *client_window = parent->GetClientWindow();
- if (!client_window)
+ wxMDIClientWindowBase *client_window = parent->GetClientWindow();
+ if ( !client_window )
return;
- child = (wxMDIChildFrame*) NULL;
+ child = NULL;
+ GtkWidget* page = gtk_notebook_get_nth_page(widget, page_num);
wxWindowList::compatibility_iterator node = client_window->GetChildren().GetFirst();
while ( node )
// child_frame can be NULL when this is called from dtor, probably
// because g_signal_connect (m_widget, "switch_page", (see below)
// isn't deleted early enough
- if ( child_frame && child_frame->m_page == page )
+ if (child_frame && child_frame->m_widget == page)
{
child = child_frame;
break;
void wxMDIParentFrame::Init()
{
m_justInserted = false;
- m_clientWindow = (wxMDIClientWindow *) NULL;
-}
-
-wxMDIParentFrame::~wxMDIParentFrame()
-{
}
bool wxMDIParentFrame::Create(wxWindow *parent,
return false;
m_clientWindow = OnCreateClient();
+ if ( !m_clientWindow->CreateClient(this, GetWindowStyleFlag()) )
+ return false;
- return m_clientWindow != NULL;
+ return true;
}
void wxMDIParentFrame::OnInternalIdle()
{
- /* if a an MDI child window has just been inserted
+ /* if a MDI child window has just been inserted
it has to be brought to the top in idle time. we
simply set the last notebook page active as new
pages can only be appended at the end */
if (m_justInserted)
{
GtkNotebook *notebook = GTK_NOTEBOOK(m_clientWindow->m_widget);
- gtk_notebook_set_current_page( notebook, g_list_length( notebook->children ) - 1 );
+ gtk_notebook_set_current_page(notebook, -1);
/* need to set the menubar of the child */
wxMDIChildFrame *active_child_frame = GetActiveChild();
wxMenuBar *menu_bar = active_child_frame->m_menuBar;
if (menu_bar)
{
- menu_bar->SetInvokingWindow(active_child_frame);
+ menu_bar->Attach(active_child_frame);
}
}
m_justInserted = false;
{
if (menu_bar->Show(true))
{
- menu_bar->SetInvokingWindow( child_frame );
+ // Attach() asserts if we call it for an already
+ // attached menu bar so don't do it if we're already
+ // associated with this frame (it would be nice to get
+ // rid of this check and ensure that this doesn't
+ // happen...)
+ if ( menu_bar->GetFrame() != child_frame )
+ menu_bar->Attach( child_frame );
}
visible_child_menu = true;
}
{
if (menu_bar->Show(false))
{
- menu_bar->UnsetInvokingWindow( child_frame );
+ menu_bar->Detach();
}
}
}
if (visible_child_menu)
{
m_frameMenuBar->Show( false );
- m_frameMenuBar->UnsetInvokingWindow( this );
+ m_frameMenuBar->Detach();
}
else
{
m_frameMenuBar->Show( true );
- m_frameMenuBar->SetInvokingWindow( this );
+ m_frameMenuBar->Attach( this );
}
}
}
{
wxFrame::DoGetClientSize(width, height);
- if (height)
+ if (!m_useCachedClientSize && height)
{
wxMDIChildFrame* active_child_frame = GetActiveChild();
if (active_child_frame)
if (menubar && menubar->IsShown())
{
GtkRequisition req;
- gtk_widget_size_request(menubar->m_widget, &req);
+ gtk_widget_get_preferred_height(menubar->m_widget, NULL, &req.height);
*height -= req.height;
if (*height < 0) *height = 0;
}
wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
{
- if (!m_clientWindow) return (wxMDIChildFrame*) NULL;
+ if (!m_clientWindow) return NULL;
GtkNotebook *notebook = GTK_NOTEBOOK(m_clientWindow->m_widget);
- if (!notebook) return (wxMDIChildFrame*) NULL;
+ if (!notebook) return NULL;
gint i = gtk_notebook_get_current_page( notebook );
- if (i < 0) return (wxMDIChildFrame*) NULL;
+ if (i < 0) return NULL;
- GtkNotebookPage* page = (GtkNotebookPage*) (g_list_nth(notebook->children,i)->data);
- if (!page) return (wxMDIChildFrame*) NULL;
+ GtkWidget* page = gtk_notebook_get_nth_page(notebook, i);
+ if (!page) return NULL;
wxWindowList::compatibility_iterator node = m_clientWindow->GetChildren().GetFirst();
while (node)
{
if ( wxPendingDelete.Member(node->GetData()) )
- return (wxMDIChildFrame*) NULL;
+ return NULL;
wxMDIChildFrame *child_frame = wxDynamicCast( node->GetData(), wxMDIChildFrame );
if (!child_frame)
- return (wxMDIChildFrame*) NULL;
+ return NULL;
- if (child_frame->m_page == page)
+ if (child_frame->m_widget == page)
return child_frame;
node = node->GetNext();
}
- return (wxMDIChildFrame*) NULL;
-}
-
-wxMDIClientWindow *wxMDIParentFrame::GetClientWindow() const
-{
- return m_clientWindow;
-}
-
-wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
-{
- return new wxMDIClientWindow( this );
+ return NULL;
}
void wxMDIParentFrame::ActivateNext()
EVT_MENU_HIGHLIGHT_ALL(wxMDIChildFrame::OnMenuHighlight)
END_EVENT_TABLE()
-wxMDIChildFrame::wxMDIChildFrame()
+void wxMDIChildFrame::Init()
{
- m_menuBar = (wxMenuBar *) NULL;
- m_page = (GtkNotebookPage *) NULL;
+ m_menuBar = NULL;
}
-wxMDIChildFrame::wxMDIChildFrame( wxMDIParentFrame *parent,
- wxWindowID id, const wxString& title,
- const wxPoint& WXUNUSED(pos), const wxSize& size,
- long style, const wxString& name )
+bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
+ wxWindowID id,
+ const wxString& title,
+ const wxPoint& WXUNUSED(pos),
+ const wxSize& size,
+ long style,
+ const wxString& name)
{
- m_menuBar = (wxMenuBar *) NULL;
- m_page = (GtkNotebookPage *) NULL;
- Create( parent, id, title, wxDefaultPosition, size, style, name );
+ m_mdiParent = parent;
+ m_title = title;
+
+ return wxWindow::Create(parent->GetClientWindow(), id,
+ wxDefaultPosition, size,
+ style, name);
}
wxMDIChildFrame::~wxMDIChildFrame()
{
- if (m_menuBar)
- delete m_menuBar;
+ delete m_menuBar;
// wxMDIClientWindow does not get redrawn properly after last child is removed
if (m_parent && m_parent->GetChildren().size() <= 1)
gtk_widget_queue_draw(m_parent->m_widget);
}
-bool wxMDIChildFrame::Create( wxMDIParentFrame *parent,
- wxWindowID id, const wxString& title,
- const wxPoint& WXUNUSED(pos), const wxSize& size,
- long style, const wxString& name )
+void wxMDIChildFrame::GTKHandleRealized()
{
- m_title = title;
-
- return wxWindow::Create( parent->GetClientWindow(), id, wxDefaultPosition, size, style, name );
-}
-
-bool wxMDIChildFrame::Destroy()
-{
- // delayed destruction: the frame will be deleted during
- // the next idle loop iteration.
- // I'm not sure if delayed destruction really makes so
- // much sense for MDI child frames, actually, but hiding
- // it doesn't make any sense.
- if ( !wxPendingDelete.Member(this) )
- wxPendingDelete.Append(this);
-
- return true;
-}
-
-void wxMDIChildFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
-{
- wxWindow::DoSetSize( x, y, width, height, sizeFlags );
-}
-
-void wxMDIChildFrame::AddChild( wxWindowBase *child )
-{
- wxWindow::AddChild(child);
+ // since m_widget is not a GtkWindow, must bypass wxTopLevelWindowGTK
+ wxTopLevelWindowBase::GTKHandleRealized();
}
void wxMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar )
{
- wxASSERT_MSG( m_menuBar == NULL, wxT("Only one menubar allowed") );
+ wxASSERT_MSG( m_menuBar == NULL, "Only one menubar allowed" );
m_menuBar = menu_bar;
m_menuBar->Show(false);
gtk_box_pack_start(GTK_BOX(mdi_frame->m_mainWidget), m_menuBar->m_widget, false, false, 0);
gtk_box_reorder_child(GTK_BOX(mdi_frame->m_mainWidget), m_menuBar->m_widget, 0);
-
- gulong handler_id = g_signal_handler_find(
- m_menuBar->m_widget,
- GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA),
- g_signal_lookup("size_request", GTK_TYPE_WIDGET),
- 0, NULL, NULL, m_menuBar);
- if (handler_id != 0)
- g_signal_handler_disconnect(m_menuBar->m_widget, handler_id);
gtk_widget_set_size_request(m_menuBar->m_widget, -1, -1);
}
}
return m_menuBar;
}
+GtkNotebook *wxMDIChildFrame::GTKGetNotebook() const
+{
+ wxMDIClientWindow * const
+ client = wxStaticCast(GetParent(), wxMDIClientWindow);
+ wxCHECK( client, NULL );
+
+ return GTK_NOTEBOOK(client->m_widget);
+}
+
void wxMDIChildFrame::Activate()
{
- wxMDIParentFrame* parent = (wxMDIParentFrame*) GetParent();
- GtkNotebook* notebook = GTK_NOTEBOOK(parent->m_widget);
+ GtkNotebook * const notebook = GTKGetNotebook();
+ wxCHECK_RET( notebook, "no parent notebook?" );
+
gint pageno = gtk_notebook_page_num( notebook, m_widget );
gtk_notebook_set_current_page( notebook, pageno );
}
m_title = title;
- wxMDIParentFrame* parent = (wxMDIParentFrame*) GetParent();
- GtkNotebook* notebook = GTK_NOTEBOOK(parent->m_widget);
+ GtkNotebook * const notebook = GTKGetNotebook();
+ wxCHECK_RET( notebook, "no parent notebook?" );
gtk_notebook_set_tab_label_text(notebook, m_widget, wxGTK_CONV( title ) );
}
-void wxMDIClientWindow::AddChildGTK(wxWindowGTK* child)
-{
- wxMDIChildFrame* child_frame = static_cast<wxMDIChildFrame*>(child);
- wxString s = child_frame->GetTitle();
- if (s.IsNull()) s = _("MDI child");
-
- GtkWidget *label_widget = gtk_label_new( s.mbc_str() );
- gtk_misc_set_alignment( GTK_MISC(label_widget), 0.0, 0.5 );
-
- GtkNotebook* notebook = GTK_NOTEBOOK(m_widget);
-
- gtk_notebook_append_page( notebook, child->m_widget, label_widget );
-
- child_frame->m_page = (GtkNotebookPage*) (g_list_last(notebook->children)->data);
-
- wxMDIParentFrame* parent_frame = static_cast<wxMDIParentFrame*>(GetParent());
- parent_frame->m_justInserted = true;
-}
-
//-----------------------------------------------------------------------------
// wxMDIClientWindow
//-----------------------------------------------------------------------------
-IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
-
-wxMDIClientWindow::wxMDIClientWindow()
-{
-}
-
-wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame *parent, long style )
-{
- CreateClient( parent, style );
-}
+IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
wxMDIClientWindow::~wxMDIClientWindow()
{
-
+ // disconnect our handler because our ~wxWindow (which is going to be called
+ // after this dtor) will call DestroyChildren(); in turns our children
+ // ~wxWindow dtors will call wxWindow::Show(false) and this will generate
+ // a call to gtk_mdi_page_change_callback with an invalid parent
+ // (because gtk_mdi_page_change_callback expects a wxMDIClientWindow but
+ // at that point of the dtor chain we are a simple wxWindow!)
+ g_signal_handlers_disconnect_by_func(m_widget, (void*)switch_page, GetParent());
}
-bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style )
+bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
{
- if (!PreCreation( parent, wxDefaultPosition, wxDefaultSize ) ||
- !CreateBase( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style, wxDefaultValidator, wxT("wxMDIClientWindow") ))
+ if ( !PreCreation( parent, wxDefaultPosition, wxDefaultSize ) ||
+ !CreateBase( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
+ style, wxDefaultValidator, "wxMDIClientWindow" ))
{
- wxFAIL_MSG( wxT("wxMDIClientWindow creation failed") );
+ wxFAIL_MSG( "wxMDIClientWindow creation failed" );
return false;
}
m_widget = gtk_notebook_new();
g_object_ref(m_widget);
- g_signal_connect (m_widget, "switch_page",
- G_CALLBACK (gtk_mdi_page_change_callback), parent);
+ g_signal_connect(m_widget, "switch_page", G_CALLBACK(switch_page), parent);
gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget), 1 );
return true;
}
+void wxMDIClientWindow::AddChildGTK(wxWindowGTK* child)
+{
+ wxMDIChildFrame* child_frame = static_cast<wxMDIChildFrame*>(child);
+ wxString s = child_frame->GetTitle();
+ if ( s.empty() )
+ s = _("MDI child");
+
+ GtkWidget *label_widget = gtk_label_new( s.mbc_str() );
+ gtk_misc_set_alignment( GTK_MISC(label_widget), 0.0, 0.5 );
+
+ GtkNotebook* notebook = GTK_NOTEBOOK(m_widget);
+
+ gtk_notebook_append_page( notebook, child->m_widget, label_widget );
+
+ wxMDIParentFrame* parent_frame = static_cast<wxMDIParentFrame*>(GetParent());
+ parent_frame->m_justInserted = true;
+}
+
#endif // wxUSE_MDI