1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
24 #include "wx/dialog.h"
25 #include "wx/control.h"
29 #include "wx/toolbar.h"
32 #include "wx/statusbr.h"
34 #include "wx/dcclient.h"
37 #include "wx/gtk/private.h"
39 #include <gdk/gdkkeysyms.h>
42 #include "wx/gtk/win_gtk.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 const int wxSTATUS_HEIGHT
= 25;
49 const int wxPLACE_HOLDER
= 0;
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 extern void wxapp_install_idle_handler();
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
64 // ============================================================================
66 // ============================================================================
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
72 #if wxUSE_MENUS_NATIVE
74 //-----------------------------------------------------------------------------
75 // "child_attached" of menu bar
76 //-----------------------------------------------------------------------------
79 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
81 if (!win
->m_hasVMT
) return;
83 win
->m_menuBarDetached
= false;
88 //-----------------------------------------------------------------------------
89 // "child_detached" of menu bar
90 //-----------------------------------------------------------------------------
93 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
96 wxapp_install_idle_handler();
98 if (!win
->m_hasVMT
) return;
100 // Raise the client area area
101 gdk_window_raise( win
->m_wxwindow
->window
);
103 win
->m_menuBarDetached
= true;
104 win
->GtkUpdateSize();
108 #endif // wxUSE_MENUS_NATIVE
111 //-----------------------------------------------------------------------------
112 // "child_attached" of tool bar
113 //-----------------------------------------------------------------------------
116 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
118 if (!win
->m_hasVMT
) return;
120 win
->m_toolBarDetached
= false;
121 win
->GtkUpdateSize();
125 //-----------------------------------------------------------------------------
126 // "child_detached" of tool bar
127 //-----------------------------------------------------------------------------
130 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
133 wxapp_install_idle_handler();
135 if (!win
->m_hasVMT
) return;
137 // Raise the client area area
138 gdk_window_raise( win
->m_wxwindow
->window
);
140 win
->m_toolBarDetached
= true;
141 win
->GtkUpdateSize();
144 #endif // wxUSE_TOOLBAR
147 // ----------------------------------------------------------------------------
149 // ----------------------------------------------------------------------------
151 //-----------------------------------------------------------------------------
152 // InsertChild for wxFrame
153 //-----------------------------------------------------------------------------
155 /* Callback for wxFrame. This very strange beast has to be used because
156 * C++ has no virtual methods in a constructor. We have to emulate a
157 * virtual function here as wxWidgets requires different ways to insert
158 * a child in container classes. */
160 static void wxInsertChildInFrame( wxFrame
* parent
, wxWindow
* child
)
162 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
164 if (!parent
->m_insertInClientArea
)
166 // These are outside the client area
167 wxFrame
* frame
= (wxFrame
*) parent
;
168 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
169 GTK_WIDGET(child
->m_widget
),
175 #if wxUSE_TOOLBAR_NATIVE
176 // We connect to these events for recalculating the client area
177 // space when the toolbar is floating
178 if (wxIS_KIND_OF(child
,wxToolBar
))
180 wxToolBar
*toolBar
= (wxToolBar
*) child
;
181 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
183 g_signal_connect (toolBar
->m_widget
, "child_attached",
184 G_CALLBACK (gtk_toolbar_attached_callback
),
186 g_signal_connect (toolBar
->m_widget
, "child_detached",
187 G_CALLBACK (gtk_toolbar_detached_callback
),
191 #endif // wxUSE_TOOLBAR
195 // These are inside the client area
196 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
197 GTK_WIDGET(child
->m_widget
),
204 // Resize on OnInternalIdle
205 parent
->GtkUpdateSize();
208 // ----------------------------------------------------------------------------
210 // ----------------------------------------------------------------------------
214 m_menuBarDetached
= false;
215 m_toolBarDetached
= false;
219 bool wxFrame::Create( wxWindow
*parent
,
221 const wxString
& title
,
223 const wxSize
& sizeOrig
,
225 const wxString
&name
)
227 bool rt
= wxTopLevelWindow::Create(parent
, id
, title
, pos
, sizeOrig
,
229 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
236 m_isBeingDeleted
= true;
240 // ----------------------------------------------------------------------------
241 // overridden wxWindow methods
242 // ----------------------------------------------------------------------------
244 void wxFrame::DoGetClientSize( int *width
, int *height
) const
246 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
248 wxTopLevelWindow::DoGetClientSize( width
, height
);
252 #if wxUSE_MENUS_NATIVE
256 if (!m_menuBarDetached
)
257 (*height
) -= m_menuBarHeight
;
259 (*height
) -= wxPLACE_HOLDER
;
261 #endif // wxUSE_MENUS_NATIVE
265 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
266 (*height
) -= wxSTATUS_HEIGHT
;
267 #endif // wxUSE_STATUSBAR
271 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
273 if (m_toolBarDetached
)
275 *height
-= wxPLACE_HOLDER
;
280 m_frameToolBar
->GetSize( &x
, &y
);
281 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
291 #endif // wxUSE_TOOLBAR
295 void wxFrame::DoSetClientSize( int width
, int height
)
297 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
299 #if wxUSE_MENUS_NATIVE
303 if (!m_menuBarDetached
)
304 height
+= m_menuBarHeight
;
306 height
+= wxPLACE_HOLDER
;
308 #endif // wxUSE_MENUS_NATIVE
312 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
317 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
319 if (m_toolBarDetached
)
321 height
+= wxPLACE_HOLDER
;
326 m_frameToolBar
->GetSize( &x
, &y
);
327 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
339 wxTopLevelWindow::DoSetClientSize( width
, height
);
342 void wxFrame::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
343 int width
, int height
)
345 // due to a bug in gtk, x,y are always 0
350 if (m_resizing
) return;
353 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
354 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
359 // space occupied by m_frameToolBar and m_frameMenuBar
360 int client_area_x_offset
= 0,
361 client_area_y_offset
= 0;
363 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
364 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
365 set in wxFrame::Create so it is used to check what kind of frame we
366 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
367 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
368 importantly) m_mainWidget */
370 int minWidth
= GetMinWidth(),
371 minHeight
= GetMinHeight(),
372 maxWidth
= GetMaxWidth(),
373 maxHeight
= GetMaxHeight();
375 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
376 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
377 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
378 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
383 gint flag
= 0; // GDK_HINT_POS;
384 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
385 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
387 geom
.min_width
= minWidth
;
388 geom
.min_height
= minHeight
;
389 geom
.max_width
= maxWidth
;
390 geom
.max_height
= maxHeight
;
391 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
394 (GdkWindowHints
) flag
);
396 // I revert back to wxGTK's original behaviour. m_mainWidget holds
397 // the menubar, the toolbar and the client area, which is represented
399 // This hurts in the eye, but I don't want to call SetSize()
400 // because I don't want to call any non-native functions here.
402 #if wxUSE_MENUS_NATIVE
406 int yy
= m_miniEdge
+ m_miniTitle
;
407 int ww
= m_width
- 2*m_miniEdge
;
408 int hh
= m_menuBarHeight
;
409 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
410 m_frameMenuBar
->m_x
= xx
;
411 m_frameMenuBar
->m_y
= yy
;
412 m_frameMenuBar
->m_width
= ww
;
413 m_frameMenuBar
->m_height
= hh
;
414 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
415 m_frameMenuBar
->m_widget
,
417 client_area_y_offset
+= hh
;
419 #endif // wxUSE_MENUS_NATIVE
422 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
423 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
426 int yy
= m_miniEdge
+ m_miniTitle
;
427 #if wxUSE_MENUS_NATIVE
430 if (!m_menuBarDetached
)
431 yy
+= m_menuBarHeight
;
433 yy
+= wxPLACE_HOLDER
;
435 #endif // wxUSE_MENUS_NATIVE
437 m_frameToolBar
->m_x
= xx
;
438 m_frameToolBar
->m_y
= yy
;
440 // don't change the toolbar's reported height/width
442 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
444 ww
= m_toolBarDetached
? wxPLACE_HOLDER
445 : m_frameToolBar
->m_width
;
446 hh
= m_height
- 2*m_miniEdge
;
448 client_area_x_offset
+= ww
;
452 ww
= m_width
- 2*m_miniEdge
;
453 hh
= m_toolBarDetached
? wxPLACE_HOLDER
454 : m_frameToolBar
->m_height
;
456 client_area_y_offset
+= hh
;
459 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
460 m_frameToolBar
->m_widget
,
463 #endif // wxUSE_TOOLBAR
465 int client_x
= client_area_x_offset
+ m_miniEdge
;
466 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
467 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
468 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
469 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
471 client_x
, client_y
, client_w
, client_h
);
475 // If there is no m_mainWidget between m_widget and m_wxwindow there
476 // is no need to set the size or position of m_wxwindow.
480 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
482 int xx
= 0 + m_miniEdge
;
483 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
484 int ww
= m_width
- 2*m_miniEdge
;
485 int hh
= wxSTATUS_HEIGHT
;
486 m_frameStatusBar
->m_x
= xx
;
487 m_frameStatusBar
->m_y
= yy
;
488 m_frameStatusBar
->m_width
= ww
;
489 m_frameStatusBar
->m_height
= hh
;
490 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
491 m_frameStatusBar
->m_widget
,
493 if (GTK_WIDGET_DRAWABLE (m_frameStatusBar
->m_widget
))
495 gtk_widget_queue_draw (m_frameStatusBar
->m_widget
);
496 // FIXME: Do we really want to force an immediate redraw?
497 gdk_window_process_updates (m_frameStatusBar
->m_widget
->window
, TRUE
);
500 #endif // wxUSE_STATUSBAR
504 // send size event to frame
505 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
506 event
.SetEventObject( this );
507 GetEventHandler()->ProcessEvent( event
);
510 // send size event to status bar
511 if (m_frameStatusBar
)
513 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
514 event2
.SetEventObject( m_frameStatusBar
);
515 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
517 #endif // wxUSE_STATUSBAR
522 void wxFrame::OnInternalIdle()
524 wxFrameBase::OnInternalIdle();
526 #if wxUSE_MENUS_NATIVE
527 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
528 #endif // wxUSE_MENUS_NATIVE
530 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
533 if (m_frameStatusBar
)
535 m_frameStatusBar
->OnInternalIdle();
537 // There may be controls in the status bar that
538 // need to be updated
539 for ( wxWindowList::compatibility_iterator node
= m_frameStatusBar
->GetChildren().GetFirst();
541 node
= node
->GetNext() )
543 wxWindow
*child
= node
->GetData();
544 child
->OnInternalIdle();
550 // ----------------------------------------------------------------------------
551 // menu/tool/status bar stuff
552 // ----------------------------------------------------------------------------
554 #if wxUSE_MENUS_NATIVE
556 void wxFrame::DetachMenuBar()
558 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
559 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
561 if ( m_frameMenuBar
)
563 m_frameMenuBar
->UnsetInvokingWindow( this );
565 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
567 g_signal_handlers_disconnect_by_func (m_frameMenuBar
->m_widget
,
568 (gpointer
) gtk_menu_attached_callback
,
571 g_signal_handlers_disconnect_by_func (m_frameMenuBar
->m_widget
,
572 (gpointer
) gtk_menu_detached_callback
,
576 gtk_widget_ref( m_frameMenuBar
->m_widget
);
578 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
581 wxFrameBase::DetachMenuBar();
584 void wxFrame::AttachMenuBar( wxMenuBar
*menuBar
)
586 wxFrameBase::AttachMenuBar(menuBar
);
590 m_frameMenuBar
->SetInvokingWindow( this );
592 m_frameMenuBar
->SetParent(this);
593 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
594 m_frameMenuBar
->m_widget
,
597 m_frameMenuBar
->m_width
,
598 m_frameMenuBar
->m_height
);
600 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
602 g_signal_connect (menuBar
->m_widget
, "child_attached",
603 G_CALLBACK (gtk_menu_attached_callback
),
605 g_signal_connect (menuBar
->m_widget
, "child_detached",
606 G_CALLBACK (gtk_menu_detached_callback
),
610 gtk_widget_show( m_frameMenuBar
->m_widget
);
617 GtkUpdateSize(); // resize window in OnInternalIdle
621 void wxFrame::UpdateMenuBarSize()
628 // this is called after Remove with a NULL m_frameMenuBar
629 if ( m_frameMenuBar
)
630 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_frameMenuBar
->m_widget
) )->size_request
)
631 (m_frameMenuBar
->m_widget
, &req
);
633 m_menuBarHeight
= req
.height
;
635 // resize window in OnInternalIdle
640 #endif // wxUSE_MENUS_NATIVE
644 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
646 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
648 m_insertInClientArea
= false;
650 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
652 m_insertInClientArea
= true;
656 return m_frameToolBar
;
659 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
661 bool hadTbar
= m_frameToolBar
!= NULL
;
663 wxFrameBase::SetToolBar(toolbar
);
665 if ( m_frameToolBar
)
667 // insert into toolbar area if not already there
668 if ((m_frameToolBar
->m_widget
->parent
) &&
669 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
671 GetChildren().DeleteObject( m_frameToolBar
);
673 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
677 else // toolbar unset
679 // still need to update size if it had been there before
687 #endif // wxUSE_TOOLBAR
691 wxStatusBar
* wxFrame::CreateStatusBar(int number
,
694 const wxString
& name
)
696 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
698 // because it will change when toolbar is added
701 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
704 void wxFrame::SetStatusBar(wxStatusBar
*statbar
)
706 bool hadStatBar
= m_frameStatusBar
!= NULL
;
708 wxFrameBase::SetStatusBar(statbar
);
710 if (hadStatBar
&& !m_frameStatusBar
)
714 void wxFrame::PositionStatusBar()
716 if ( !m_frameStatusBar
)
721 #endif // wxUSE_STATUSBAR