]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/mdi.cpp
Implement simple Drop, doesn't work under wxMSW (?)
[wxWidgets.git] / src / gtk / mdi.cpp
index 8caf06b92aebd9b4b18b0c31bc27d4b5d20a2e7e..9511b2e22ddba44abddbaf1d8559db0188412a83 100644 (file)
 #ifndef WX_PRECOMP
     #include "wx/intl.h"
     #include "wx/menu.h"
-    #include "wx/dialog.h"
 #endif
 
-#include "wx/notebook.h"
 #include "wx/gtk/private.h"
 
-#include <gtk/gtk.h>
-#include "wx/gtk/win_gtk.h"
-
-//-----------------------------------------------------------------------------
-// constants
-//-----------------------------------------------------------------------------
-
-const int wxMENU_HEIGHT = 27;
-
-//-----------------------------------------------------------------------------
-// globals
-//-----------------------------------------------------------------------------
-
 //-----------------------------------------------------------------------------
 // "switch_page"
 //-----------------------------------------------------------------------------
@@ -54,16 +39,16 @@ gtk_mdi_page_change_callback( GtkNotebook *WXUNUSED(widget),
     {
         wxActivateEvent event1( wxEVT_ACTIVATE, false, child->GetId() );
         event1.SetEventObject( child);
-        child->GetEventHandler()->ProcessEvent( event1 );
+        child->HandleWindowEvent( event1 );
     }
 
     // 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;
 
     wxWindowList::compatibility_iterator node = client_window->GetChildren().GetFirst();
     while ( node )
@@ -86,7 +71,7 @@ gtk_mdi_page_change_callback( GtkNotebook *WXUNUSED(widget),
 
     wxActivateEvent event2( wxEVT_ACTIVATE, true, child->GetId() );
     event2.SetEventObject( child);
-    child->GetEventHandler()->ProcessEvent( event2 );
+    child->HandleWindowEvent( event2 );
 }
 }
 
@@ -99,11 +84,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame,wxFrame)
 void wxMDIParentFrame::Init()
 {
     m_justInserted = false;
-    m_clientWindow = (wxMDIClientWindow *) NULL;
-}
-
-wxMDIParentFrame::~wxMDIParentFrame()
-{
 }
 
 bool wxMDIParentFrame::Create(wxWindow *parent,
@@ -114,36 +94,19 @@ bool wxMDIParentFrame::Create(wxWindow *parent,
                               long style,
                               const wxString& name )
 {
-    wxFrame::Create( parent, id, title, pos, size, style, name );
+    if ( !wxFrame::Create( parent, id, title, pos, size, style, name ) )
+        return false;
 
-    OnCreateClient();
+    m_clientWindow = OnCreateClient();
+    if ( !m_clientWindow->CreateClient(this, GetWindowStyleFlag()) )
+        return false;
 
     return true;
 }
 
-void wxMDIParentFrame::GtkOnSize()
-{
-    wxFrame::GtkOnSize();
-
-    wxMDIChildFrame *child_frame = GetActiveChild();
-    if (!child_frame) return;
-
-    wxMenuBar *menu_bar = child_frame->m_menuBar;
-    if (!menu_bar) return;
-    if (!menu_bar->m_widget) return;
-
-    menu_bar->m_x = 0;
-    menu_bar->m_y = 0;
-    menu_bar->m_width = m_width;
-    menu_bar->m_height = wxMENU_HEIGHT;
-    gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
-                          menu_bar->m_widget,
-                          0, 0, m_width, wxMENU_HEIGHT );
-}
-
 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 */
@@ -160,11 +123,6 @@ void wxMDIParentFrame::OnInternalIdle()
             wxMenuBar *menu_bar = active_child_frame->m_menuBar;
             if (menu_bar)
             {
-                menu_bar->m_width = m_width;
-                menu_bar->m_height = wxMENU_HEIGHT;
-                gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
-                                    menu_bar->m_widget,
-                                    0, 0, m_width, wxMENU_HEIGHT );
                 menu_bar->SetInvokingWindow(active_child_frame);
             }
         }
@@ -191,11 +149,6 @@ void wxMDIParentFrame::OnInternalIdle()
                 {
                     if (menu_bar->Show(true))
                     {
-                        menu_bar->m_width = m_width;
-                        menu_bar->m_height = wxMENU_HEIGHT;
-                        gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
-                                            menu_bar->m_widget,
-                                            0, 0, m_width, wxMENU_HEIGHT );
                         menu_bar->SetInvokingWindow( child_frame );
                     }
                     visible_child_menu = true;
@@ -226,39 +179,54 @@ void wxMDIParentFrame::OnInternalIdle()
         {
             m_frameMenuBar->Show( true );
             m_frameMenuBar->SetInvokingWindow( this );
+        }
+    }
+}
+
+void wxMDIParentFrame::DoGetClientSize(int* width, int* height) const
+{
+    wxFrame::DoGetClientSize(width, height);
 
-            m_frameMenuBar->m_width = m_width;
-            m_frameMenuBar->m_height = wxMENU_HEIGHT;
-            gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
-                                m_frameMenuBar->m_widget,
-                                0, 0, m_width, wxMENU_HEIGHT );
+    if (height)
+    {
+        wxMDIChildFrame* active_child_frame = GetActiveChild();
+        if (active_child_frame)
+        {
+            wxMenuBar* menubar = active_child_frame->m_menuBar;
+            if (menubar && menubar->IsShown())
+            {
+                GtkRequisition req;
+                gtk_widget_size_request(menubar->m_widget, &req);
+                *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;
+    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)
             return child_frame;
@@ -266,18 +234,7 @@ wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
         node = node->GetNext();
     }
 
-    return (wxMDIChildFrame*) NULL;
-}
-
-wxMDIClientWindow *wxMDIParentFrame::GetClientWindow() const
-{
-    return m_clientWindow;
-}
-
-wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
-{
-    m_clientWindow = new wxMDIClientWindow( this );
-    return m_clientWindow;
+    return NULL;
 }
 
 void wxMDIParentFrame::ActivateNext()
@@ -303,74 +260,40 @@ BEGIN_EVENT_TABLE(wxMDIChildFrame, wxFrame)
     EVT_MENU_HIGHLIGHT_ALL(wxMDIChildFrame::OnMenuHighlight)
 END_EVENT_TABLE()
 
-wxMDIChildFrame::wxMDIChildFrame()
-{
-    m_menuBar = (wxMenuBar *) NULL;
-    m_page = (GtkNotebookPage *) NULL;
-}
-
-wxMDIChildFrame::wxMDIChildFrame( 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 );
-}
-
-wxMDIChildFrame::~wxMDIChildFrame()
+void wxMDIChildFrame::Init()
 {
-    if (m_menuBar)
-        delete m_menuBar;
+    m_menuBar = NULL;
+    m_page = NULL;
 }
 
-bool wxMDIChildFrame::Create( 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_mdiParent = parent;
     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::DoSetClientSize(int width, int height)
-{
-    wxWindow::DoSetClientSize( width, height );
+    return wxWindow::Create(parent->GetClientWindow(), id,
+                            wxDefaultPosition, size,
+                            style, name);
 }
 
-void wxMDIChildFrame::DoGetClientSize( int *width, int *height ) const
+wxMDIChildFrame::~wxMDIChildFrame()
 {
-    wxWindow::DoGetClientSize( width, height );
-}
+    delete m_menuBar;
 
-void wxMDIChildFrame::AddChild( wxWindowBase *child )
-{
-    wxWindow::AddChild(child);
+    // 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);
 }
 
 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;
 
@@ -381,9 +304,18 @@ void wxMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar )
         m_menuBar->SetParent( mdi_frame );
 
         /* insert the invisible menu bar into the _parent_ mdi frame */
-        gtk_pizza_put( GTK_PIZZA(mdi_frame->m_mainWidget),
-                         m_menuBar->m_widget,
-                         0, 0,  mdi_frame->m_width, wxMENU_HEIGHT );
+        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);
     }
 }
 
@@ -392,10 +324,20 @@ wxMenuBar *wxMDIChildFrame::GetMenuBar() const
     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 );
 }
@@ -408,7 +350,7 @@ void wxMDIChildFrame::OnMenuHighlight( wxMenuEvent& event )
 {
 #if wxUSE_STATUSBAR
     wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)m_parent->GetParent();
-    if ( !ShowMenuHelp(mdi_frame->GetStatusBar(), event.GetMenuId()) )
+    if ( !ShowMenuHelp(event.GetMenuId()) )
     {
         // we don't have any help text for this item, but may be the MDI frame
         // does?
@@ -424,90 +366,29 @@ void wxMDIChildFrame::SetTitle( const wxString &title )
 
     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 ) );
 }
 
-//-----------------------------------------------------------------------------
-// "size_allocate"
-//-----------------------------------------------------------------------------
-
-extern "C" {
-static void gtk_page_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxWindow *win )
-{
-    if ((win->m_x == alloc->x) &&
-        (win->m_y == alloc->y) &&
-        (win->m_width == alloc->width) &&
-        (win->m_height == alloc->height) &&
-        (win->m_sizeSet))
-    {
-        return;
-    }
-
-    win->SetSize( alloc->x, alloc->y, alloc->width, alloc->height );
-}
-}
-
-//-----------------------------------------------------------------------------
-// InsertChild callback for wxMDIClientWindow
-//-----------------------------------------------------------------------------
-
-static void wxInsertChildInMDI( wxMDIClientWindow* parent, wxMDIChildFrame* child )
-{
-    wxString s = child->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 );
-
-    g_signal_connect (child->m_widget, "size_allocate",
-                      G_CALLBACK (gtk_page_size_callback), child);
-
-    GtkNotebook *notebook = GTK_NOTEBOOK(parent->m_widget);
-
-    gtk_notebook_append_page( notebook, child->m_widget, label_widget );
-
-    child->m_page = (GtkNotebookPage*) (g_list_last(notebook->children)->data);
-
-    wxMDIParentFrame *parent_frame = (wxMDIParentFrame*) parent->GetParent();
-    parent_frame->m_justInserted = true;
-}
-
 //-----------------------------------------------------------------------------
 // wxMDIClientWindow
 //-----------------------------------------------------------------------------
 
-IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow,wxWindow)
-
-wxMDIClientWindow::wxMDIClientWindow()
-{
-}
-
-wxMDIClientWindow::wxMDIClientWindow( wxMDIParentFrame *parent, long style )
-{
-    CreateClient( parent, style );
-}
-
-wxMDIClientWindow::~wxMDIClientWindow()
-{
+IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
 
-}
-
-bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style )
+bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
 {
-    m_needParent = true;
-
-    m_insertCallback = (wxInsertChildFunction)wxInsertChildInMDI;
-
-    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);
@@ -523,4 +404,24 @@ bool wxMDIClientWindow::CreateClient( wxMDIParentFrame *parent, long style )
     return true;
 }
 
-#endif
+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 );
+
+    child_frame->m_page = (GtkNotebookPage*) (g_list_last(notebook->children)->data);
+
+    wxMDIParentFrame* parent_frame = static_cast<wxMDIParentFrame*>(GetParent());
+    parent_frame->m_justInserted = true;
+}
+
+#endif // wxUSE_MDI