]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/frame.cpp
Added chapter on collection and container classes to contents
[wxWidgets.git] / src / gtk / frame.cpp
index 751e7631cb206616ebd347059344bf9ec7b9c731..8773d721d227b679cd7cf877fa8302bd9b7e3807 100644 (file)
 #endif
 #include "wx/dcclient.h"
 
-#include "glib.h"
-#include "gdk/gdk.h"
-#include "gtk/gtk.h"
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+
 #include "wx/gtk/win_gtk.h"
-#include "gdk/gdkkeysyms.h"
-#include "gdk/gdkx.h"
 
 // ----------------------------------------------------------------------------
 // constants
@@ -125,7 +126,8 @@ static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation*
 
         win->m_width = alloc->width;
         win->m_height = alloc->height;
-        win->UpdateSize();
+        win->m_queuedFullRedraw = TRUE;
+        win->GtkUpdateSize();
     }
 }
 
@@ -138,7 +140,7 @@ static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WX
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    if (g_openDialogs == 0)
+    if ((g_openDialogs == 0) && (win->IsEnabled()))
         win->Close();
 
     return TRUE;
@@ -153,7 +155,7 @@ static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *
     if (!win->m_hasVMT) return;
 
     win->m_menuBarDetached = FALSE;
-    win->UpdateSize();
+    win->GtkUpdateSize();
 }
 
 //-----------------------------------------------------------------------------
@@ -165,7 +167,7 @@ static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *
     if (!win->m_hasVMT) return;
 
     win->m_menuBarDetached = TRUE;
-    win->UpdateSize();
+    win->GtkUpdateSize();
 }
 
 #if wxUSE_TOOLBAR
@@ -179,7 +181,7 @@ static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidge
 
     win->m_toolBarDetached = FALSE;
 
-    win->UpdateSize();
+    win->GtkUpdateSize();
 }
 
 //-----------------------------------------------------------------------------
@@ -194,7 +196,7 @@ static void gtk_toolbar_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidge
     if (!win->m_hasVMT) return;
 
     win->m_toolBarDetached = TRUE;
-    win->UpdateSize();
+    win->GtkUpdateSize();
 }
 #endif // wxUSE_TOOLBAR
 
@@ -241,46 +243,50 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *ev
    so we do this directly after realization */
 
 static gint
-gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
+gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxFrame *win )
 {
     if (g_isIdle)
         wxapp_install_idle_handler();
 
-    /* I haven't been able to set the position of
-       the dialog before it is shown, so I set the
-       position in "realize" */
-    gtk_widget_set_uposition( widget, win->m_x, win->m_y );
-
-    /* all this is for Motif Window Manager "hints" and is supposed to be
-       recognized by other WM as well. not tested. */
-    long decor = (long) GDK_DECOR_BORDER;
-    long func = (long) GDK_FUNC_MOVE;
-
-    if ((win->GetWindowStyle() & wxCAPTION) != 0)
-        decor |= GDK_DECOR_TITLE;
-    if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
-    {
-       decor |= GDK_DECOR_MENU;
-       func |= GDK_FUNC_CLOSE;
-    }
-    if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
-    {
-        func |= GDK_FUNC_MINIMIZE;
-        decor |= GDK_DECOR_MINIMIZE;
-    }
-    if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
+    if ((win->m_miniEdge > 0) || (win->HasFlag(wxSIMPLE_BORDER)))
     {
-        func |= GDK_FUNC_MAXIMIZE;
-        decor |= GDK_DECOR_MAXIMIZE;
+        /* This is a mini-frame or a borderless frame. */
+        gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)0 );
+        gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)0 );
     }
-    if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
+    else
     {
-       func |= GDK_FUNC_RESIZE;
-       decor |= GDK_DECOR_RESIZEH;
-    }
+        /* All this is for Motif Window Manager "hints" and is supposed to be
+           recognized by other WM as well. Not tested. */
+        long decor = (long) GDK_DECOR_BORDER;
+        long func = (long) GDK_FUNC_MOVE;
+
+        if ((win->GetWindowStyle() & wxCAPTION) != 0)
+            decor |= GDK_DECOR_TITLE;
+        if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
+        {
+            decor |= GDK_DECOR_MENU;
+            func |= GDK_FUNC_CLOSE;
+        }
+        if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
+        {
+            func |= GDK_FUNC_MINIMIZE;
+            decor |= GDK_DECOR_MINIMIZE;
+        }
+        if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
+        {
+            func |= GDK_FUNC_MAXIMIZE;
+            decor |= GDK_DECOR_MAXIMIZE;
+        }
+        if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
+        {
+           func |= GDK_FUNC_RESIZE;
+           decor |= GDK_DECOR_RESIZEH;
+        }
 
-    gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
-    gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
+        gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
+        gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
+    }
 
     /* GTK's shrinking/growing policy */
     if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0)
@@ -288,19 +294,6 @@ gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
     else
         gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
 
-    /* set size hints */
-    gint flag = 0; // GDK_HINT_POS;
-    if ((win->GetMinWidth() != -1) || (win->GetMinHeight() != -1)) flag |= GDK_HINT_MIN_SIZE;
-    if ((win->GetMaxWidth() != -1) || (win->GetMaxHeight() != -1)) flag |= GDK_HINT_MAX_SIZE;
-    if (flag)
-    {
-        gdk_window_set_hints( win->m_widget->window,
-                              win->m_x, win->m_y,
-                              win->GetMinWidth(), win->GetMinHeight(),
-                              win->GetMaxWidth(), win->GetMaxHeight(),
-                              flag );
-    }
-
     /* reset the icon */
     wxIcon iconOld = win->GetIcon();
     if ( iconOld != wxNullIcon )
@@ -356,7 +349,7 @@ static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
                          child->m_width,
                          child->m_height );
 
-#if wxUSE_TOOLBAR
+#if wxUSE_TOOLBAR_NATIVE
         /* we connect to these events for recalculating the client area
            space when the toolbar is floating */
         if (wxIS_KIND_OF(child,wxToolBar))
@@ -385,7 +378,7 @@ static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
     }
 
     /* resize on OnInternalIdle */
-    parent->UpdateSize();
+    parent->GtkUpdateSize();
 }
 
 // ----------------------------------------------------------------------------
@@ -401,7 +394,6 @@ void wxFrame::Init()
     m_menuBarDetached = FALSE;
     m_toolBarDetached = FALSE;
     m_insertInClientArea = TRUE;
-    m_isFrame = TRUE;
 }
 
 bool wxFrame::Create( wxWindow *parent,
@@ -428,10 +420,12 @@ bool wxFrame::Create( wxWindow *parent,
     m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
 
     GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
-    if (style & wxSIMPLE_BORDER) win_type = GTK_WINDOW_POPUP;
 
     m_widget = gtk_window_new( win_type );
 
+    if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget)))
+        gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
+
     if (!name.IsEmpty())
         gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
 
@@ -476,6 +470,10 @@ bool wxFrame::Create( wxWindow *parent,
 
     PostCreation();
 
+    if ((m_x != -1) || (m_y != -1))
+        gtk_widget_set_uposition( m_widget, m_x, m_y );
+    gtk_widget_set_usize( m_widget, m_width, m_height );
+
     /*  we cannot set MWM hints and icons before the widget has
         been realized, so we do this directly after realization */
     gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
@@ -503,8 +501,11 @@ wxFrame::~wxFrame()
     if (wxTheApp->GetTopWindow() == this)
         wxTheApp->SetTopWindow( (wxWindow*) NULL );
 
-    if (wxTopLevelWindows.Number() == 0)
+    if ((wxTopLevelWindows.Number() == 0) &&
+        (wxTheApp->GetExitOnFrameDelete()))
+    {
         wxTheApp->ExitMainLoop();
+    }
 }
 
 // ----------------------------------------------------------------------------
@@ -528,6 +529,11 @@ bool wxFrame::Show( bool show )
     return wxWindow::Show( show );
 }
 
+void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
+{
+    wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
+}
+
 void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
 {
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
@@ -588,6 +594,8 @@ void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
 
     if ((m_width != old_width) || (m_height != old_height))
     {
+        gtk_widget_set_usize( m_widget, m_width, m_height );
+
         /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
            done either directly before the frame is shown or in idle time
            so that different calls to SetSize() don't lead to flicker. */
@@ -616,29 +624,38 @@ void wxFrame::DoGetClientSize( int *width, int *height ) const
 #if wxUSE_STATUSBAR
         /* status bar */
         if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
-#endif
+#endif // wxUSE_STATUSBAR
 
 #if wxUSE_TOOLBAR
         /* tool bar */
         if (m_frameToolBar)
         {
-            if (!m_toolBarDetached)
+            if (m_toolBarDetached)
             {
-                int y = 0;
-                m_frameToolBar->GetSize( (int *) NULL, &y );
-                (*height) -= y;
+                *height -= wxPLACE_HOLDER;
             }
             else
-                (*height) -= wxPLACE_HOLDER;
+            {
+                int x, y;
+                m_frameToolBar->GetSize( &x, &y );
+                if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
+                {
+                    *width -= x;
+                }
+                else
+                {
+                    *height -= y;
+                }
+            }
         }
-#endif
+#endif // wxUSE_TOOLBAR
 
         /* mini edge */
-        (*height) -= m_miniEdge*2 + m_miniTitle;
+        *height -= m_miniEdge*2 + m_miniTitle;
     }
     if (width)
     {
-        (*width) -= m_miniEdge*2;
+        *width -= m_miniEdge*2;
     }
 }
 
@@ -664,14 +681,23 @@ void wxFrame::DoSetClientSize( int width, int height )
         /* tool bar */
         if (m_frameToolBar)
         {
-            if (!m_toolBarDetached)
+            if (m_toolBarDetached)
             {
-                int y = 0;
-                m_frameToolBar->GetSize( (int *) NULL, &y );
-                height += y;
+                height += wxPLACE_HOLDER;
             }
             else
-                height += wxPLACE_HOLDER;
+            {
+                int x, y;
+                m_frameToolBar->GetSize( &x, &y );
+                if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
+                {
+                    width += x;
+                }
+                else
+                {
+                    height += y;
+                }
+            }
         }
 #endif
 
@@ -696,7 +722,8 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
     m_height = height;
 
     /* space occupied by m_frameToolBar and m_frameMenuBar */
-    int client_area_y_offset = 0;
+    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
@@ -705,13 +732,26 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
        skip the part which handles m_frameMenuBar, m_frameToolBar and (most
        importantly) m_mainWidget */
 
+    if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
+    if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
+    if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
+    if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
+
     if (m_mainWidget)
     {
-        /* check if size is in legal range */
-        if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
-        if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
-        if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
-        if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
+        /* set size hints */
+        gint flag = 0; // GDK_HINT_POS;
+        if ((m_minWidth != -1) || (m_minHeight != -1)) flag |= GDK_HINT_MIN_SIZE;
+        if ((m_maxWidth != -1) || (m_maxHeight != -1)) flag |= GDK_HINT_MAX_SIZE;
+        GdkGeometry geom;
+        geom.min_width = m_minWidth;
+        geom.min_height = m_minHeight;
+        geom.max_width = m_maxWidth;
+        geom.max_height = m_maxHeight;
+        gtk_window_set_geometry_hints( GTK_WINDOW(m_widget),
+                                       (GtkWidget*) NULL,
+                                       &geom,
+                                       (GdkWindowHints) flag );
 
         /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
          * menubar, the toolbar and the client area, which is represented by
@@ -749,23 +789,38 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
                 else
                     yy += wxPLACE_HOLDER;
             }
-            int ww = m_width - 2*m_miniEdge;
-            int hh = m_frameToolBar->m_height;
-            if (m_toolBarDetached) hh = wxPLACE_HOLDER;
+
             m_frameToolBar->m_x = xx;
             m_frameToolBar->m_y = yy;
-            /* m_frameToolBar->m_height = hh;   don't change the toolbar's reported size
-               m_frameToolBar->m_width = ww; */
+
+            /* 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 = m_height - 2*m_miniEdge;
+
+                client_area_x_offset += ww;
+            }
+            else
+            {
+                ww = m_width - 2*m_miniEdge;
+                hh = m_toolBarDetached ? wxPLACE_HOLDER
+                                       : m_frameToolBar->m_height;
+
+                client_area_y_offset += hh;
+            }
+
             gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
                                   m_frameToolBar->m_widget,
                                   xx, yy, ww, hh );
-            client_area_y_offset += hh;
         }
-#endif
+#endif // wxUSE_TOOLBAR
 
-        int client_x = m_miniEdge;
+        int client_x = client_area_x_offset + m_miniEdge;
         int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
-        int client_w = m_width - 2*m_miniEdge;
+        int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
         int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
         gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
                               m_wxwindow,
@@ -791,12 +846,10 @@ void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
         gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
                             m_frameStatusBar->m_widget,
                             xx, yy, ww, hh );
+        gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL );
     }
 #endif
 
-    /* we actually set the size of a frame here and no-where else */
-    gtk_widget_set_usize( m_widget, m_width, m_height );
-
     m_sizeSet = TRUE;
 
     // send size event to frame
@@ -855,33 +908,51 @@ void wxFrame::SetMenuBar( wxMenuBar *menuBar )
     wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
     wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
 
+    if (menuBar == m_frameMenuBar)
+        return;
+
+    if (m_frameMenuBar)
+    {
+        m_frameMenuBar->UnsetInvokingWindow( this );
+
+        if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
+        {
+            gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
+                GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
+
+            gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
+                GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
+        }
+
+        gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
+        gtk_widget_ref( m_frameMenuBar->m_widget );
+        gtk_widget_unparent( m_frameMenuBar->m_widget );
+    }
+
     m_frameMenuBar = menuBar;
 
     if (m_frameMenuBar)
     {
         m_frameMenuBar->SetInvokingWindow( this );
 
-        if (m_frameMenuBar->GetParent() != this)
-        {
-            m_frameMenuBar->SetParent(this);
-            gtk_pizza_put( GTK_PIZZA(m_mainWidget),
+        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)
-            {
-                gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
-                    GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
-
-                gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
-                    GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
-            }
+        if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
+        {
+            gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
+                GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
 
-            m_frameMenuBar->Show( TRUE );
+            gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
+                GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
         }
+
+        m_frameMenuBar->Show( TRUE );
     }
 
     /* resize window in OnInternalIdle */
@@ -897,9 +968,6 @@ wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& na
 
     m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
 
-    if (m_frameToolBar)
-        GetChildren().DeleteObject( m_frameToolBar );
-
     m_insertInClientArea = TRUE;
 
     m_sizeSet = FALSE;
@@ -920,7 +988,7 @@ void wxFrame::SetToolBar(wxToolBar *toolbar)
             GetChildren().DeleteObject( m_frameToolBar );
 
             gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
-            UpdateSize();
+            GtkUpdateSize();
         }
     }
 }
@@ -942,6 +1010,13 @@ wxStatusBar* wxFrame::CreateStatusBar(int number,
     return wxFrameBase::CreateStatusBar( number, style, id, name );
 }
 
+void wxFrame::PositionStatusBar()
+{
+    if ( !m_frameStatusBar )
+        return;
+
+    m_sizeSet = FALSE;
+}
 #endif // wxUSE_STATUSBAR
 
 // ----------------------------------------------------------------------------