1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk1/frame.cpp
4 // Author: Robert Roebling
5 // Copyright: (c) 1998 Robert Roebling
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
9 // For compilers that support precompilation, includes "wx.h".
10 #include "wx/wxprec.h"
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
24 #include "wx/dcclient.h"
26 #include "wx/dialog.h"
27 #include "wx/control.h"
28 #include "wx/toolbar.h"
29 #include "wx/statusbr.h"
33 #include "wx/gtk1/private.h"
35 #include <gdk/gdkkeysyms.h>
38 #include "wx/gtk1/win_gtk.h"
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
44 const int wxSTATUS_HEIGHT
= 25;
45 const int wxPLACE_HOLDER
= 0;
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 extern void wxapp_install_idle_handler();
54 // ----------------------------------------------------------------------------
56 // ----------------------------------------------------------------------------
58 // ============================================================================
60 // ============================================================================
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 #if wxUSE_MENUS_NATIVE
68 //-----------------------------------------------------------------------------
69 // "child_attached" of menu bar
70 //-----------------------------------------------------------------------------
73 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
75 if (!win
->m_hasVMT
) return;
77 win
->m_menuBarDetached
= false;
82 //-----------------------------------------------------------------------------
83 // "child_detached" of menu bar
84 //-----------------------------------------------------------------------------
87 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
90 wxapp_install_idle_handler();
92 if (!win
->m_hasVMT
) return;
94 // Raise the client area area
95 gdk_window_raise( win
->m_wxwindow
->window
);
97 win
->m_menuBarDetached
= true;
102 #endif // wxUSE_MENUS_NATIVE
105 //-----------------------------------------------------------------------------
106 // "child_attached" of tool bar
107 //-----------------------------------------------------------------------------
110 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
112 if (!win
->m_hasVMT
) return;
114 win
->m_toolBarDetached
= false;
115 win
->GtkUpdateSize();
119 //-----------------------------------------------------------------------------
120 // "child_detached" of tool bar
121 //-----------------------------------------------------------------------------
124 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
127 wxapp_install_idle_handler();
129 if (!win
->m_hasVMT
) return;
131 // Raise the client area area
132 gdk_window_raise( win
->m_wxwindow
->window
);
134 win
->m_toolBarDetached
= true;
135 win
->GtkUpdateSize();
138 #endif // wxUSE_TOOLBAR
141 // ----------------------------------------------------------------------------
143 // ----------------------------------------------------------------------------
145 //-----------------------------------------------------------------------------
146 // InsertChild for wxFrame
147 //-----------------------------------------------------------------------------
149 /* Callback for wxFrame. This very strange beast has to be used because
150 * C++ has no virtual methods in a constructor. We have to emulate a
151 * virtual function here as wxWidgets requires different ways to insert
152 * a child in container classes. */
154 static void wxInsertChildInFrame( wxFrame
* parent
, wxWindow
* child
)
156 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
158 if (!parent
->m_insertInClientArea
)
160 // These are outside the client area
161 wxFrame
* frame
= (wxFrame
*) parent
;
162 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
163 GTK_WIDGET(child
->m_widget
),
169 #if wxUSE_TOOLBAR_NATIVE
170 // We connect to these events for recalculating the client area
171 // space when the toolbar is floating
172 if (wxIS_KIND_OF(child
,wxToolBar
))
174 wxToolBar
*toolBar
= (wxToolBar
*) child
;
175 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
177 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
178 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
180 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
181 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
184 #endif // wxUSE_TOOLBAR
188 // These are inside the client area
189 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
190 GTK_WIDGET(child
->m_widget
),
197 // Resize on OnInternalIdle
198 parent
->GtkUpdateSize();
201 // ----------------------------------------------------------------------------
203 // ----------------------------------------------------------------------------
207 m_menuBarDetached
= false;
208 m_toolBarDetached
= false;
212 bool wxFrame::Create( wxWindow
*parent
,
214 const wxString
& title
,
216 const wxSize
& sizeOrig
,
218 const wxString
&name
)
220 bool rt
= wxTopLevelWindow::Create(parent
, id
, title
, pos
, sizeOrig
,
222 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
234 // ----------------------------------------------------------------------------
235 // overridden wxWindow methods
236 // ----------------------------------------------------------------------------
238 void wxFrame::DoGetClientSize( int *width
, int *height
) const
240 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
242 wxTopLevelWindow::DoGetClientSize( width
, height
);
246 #if wxUSE_MENUS_NATIVE
250 if (!m_menuBarDetached
)
251 (*height
) -= m_menuBarHeight
;
253 (*height
) -= wxPLACE_HOLDER
;
255 #endif // wxUSE_MENUS_NATIVE
259 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
260 (*height
) -= wxSTATUS_HEIGHT
;
261 #endif // wxUSE_STATUSBAR
265 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
267 if (m_toolBarDetached
)
269 *height
-= wxPLACE_HOLDER
;
274 m_frameToolBar
->GetSize( &x
, &y
);
275 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
285 #endif // wxUSE_TOOLBAR
289 void wxFrame::DoSetClientSize( int width
, int height
)
291 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
293 #if wxUSE_MENUS_NATIVE
297 if (!m_menuBarDetached
)
298 height
+= m_menuBarHeight
;
300 height
+= wxPLACE_HOLDER
;
302 #endif // wxUSE_MENUS_NATIVE
306 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
311 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
313 if (m_toolBarDetached
)
315 height
+= wxPLACE_HOLDER
;
320 m_frameToolBar
->GetSize( &x
, &y
);
321 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
333 wxTopLevelWindow::DoSetClientSize( width
, height
);
336 void wxFrame::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
337 int width
, int height
)
339 // due to a bug in gtk, x,y are always 0
344 if (m_resizing
) return;
347 // this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow
348 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
353 // space occupied by m_frameToolBar and m_frameMenuBar
354 int client_area_x_offset
= 0,
355 client_area_y_offset
= 0;
357 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
358 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
359 set in wxFrame::Create so it is used to check what kind of frame we
360 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
361 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
362 importantly) m_mainWidget */
364 int minWidth
= GetMinWidth(),
365 minHeight
= GetMinHeight(),
366 maxWidth
= GetMaxWidth(),
367 maxHeight
= GetMaxHeight();
369 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
370 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
371 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
372 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
377 gint flag
= 0; // GDK_HINT_POS;
378 if ((minWidth
!= -1) || (minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
379 if ((maxWidth
!= -1) || (maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
381 geom
.min_width
= minWidth
;
382 geom
.min_height
= minHeight
;
383 geom
.max_width
= maxWidth
;
384 geom
.max_height
= maxHeight
;
385 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
388 (GdkWindowHints
) flag
);
390 // I revert back to wxGTK's original behaviour. m_mainWidget holds
391 // the menubar, the toolbar and the client area, which is represented
393 // This hurts in the eye, but I don't want to call SetSize()
394 // because I don't want to call any non-native functions here.
396 #if wxUSE_MENUS_NATIVE
400 int yy
= m_miniEdge
+ m_miniTitle
;
401 int ww
= m_width
- 2*m_miniEdge
;
402 int hh
= m_menuBarHeight
;
403 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
404 m_frameMenuBar
->m_x
= xx
;
405 m_frameMenuBar
->m_y
= yy
;
406 m_frameMenuBar
->m_width
= ww
;
407 m_frameMenuBar
->m_height
= hh
;
408 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
409 m_frameMenuBar
->m_widget
,
411 client_area_y_offset
+= hh
;
413 #endif // wxUSE_MENUS_NATIVE
416 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
417 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
420 int yy
= m_miniEdge
+ m_miniTitle
;
421 #if wxUSE_MENUS_NATIVE
424 if (!m_menuBarDetached
)
425 yy
+= m_menuBarHeight
;
427 yy
+= wxPLACE_HOLDER
;
429 #endif // wxUSE_MENUS_NATIVE
431 m_frameToolBar
->m_x
= xx
;
432 m_frameToolBar
->m_y
= yy
;
434 // don't change the toolbar's reported height/width
436 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
438 ww
= m_toolBarDetached
? wxPLACE_HOLDER
439 : m_frameToolBar
->m_width
;
440 hh
= m_height
- 2*m_miniEdge
;
442 client_area_x_offset
+= ww
;
446 ww
= m_width
- 2*m_miniEdge
;
447 hh
= m_toolBarDetached
? wxPLACE_HOLDER
448 : m_frameToolBar
->m_height
;
450 client_area_y_offset
+= hh
;
453 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
454 m_frameToolBar
->m_widget
,
457 #endif // wxUSE_TOOLBAR
459 int client_x
= client_area_x_offset
+ m_miniEdge
;
460 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
461 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
462 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
463 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
465 client_x
, client_y
, client_w
, client_h
);
469 // If there is no m_mainWidget between m_widget and m_wxwindow there
470 // is no need to set the size or position of m_wxwindow.
474 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
476 int xx
= 0 + m_miniEdge
;
477 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
478 int ww
= m_width
- 2*m_miniEdge
;
479 int hh
= wxSTATUS_HEIGHT
;
480 m_frameStatusBar
->m_x
= xx
;
481 m_frameStatusBar
->m_y
= yy
;
482 m_frameStatusBar
->m_width
= ww
;
483 m_frameStatusBar
->m_height
= hh
;
484 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
485 m_frameStatusBar
->m_widget
,
487 gtk_widget_draw( m_frameStatusBar
->m_widget
, NULL
);
489 #endif // wxUSE_STATUSBAR
493 // send size event to frame
494 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
495 event
.SetEventObject( this );
496 HandleWindowEvent( event
);
499 // send size event to status bar
500 if (m_frameStatusBar
)
502 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
503 event2
.SetEventObject( m_frameStatusBar
);
504 m_frameStatusBar
->HandleWindowEvent( event2
);
506 #endif // wxUSE_STATUSBAR
511 void wxFrame::OnInternalIdle()
513 wxFrameBase::OnInternalIdle();
515 #if wxUSE_MENUS_NATIVE
516 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
517 #endif // wxUSE_MENUS_NATIVE
519 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
522 if (m_frameStatusBar
)
524 m_frameStatusBar
->OnInternalIdle();
526 // There may be controls in the status bar that
527 // need to be updated
528 for ( wxWindowList::compatibility_iterator node
= m_frameStatusBar
->GetChildren().GetFirst();
530 node
= node
->GetNext() )
532 wxWindow
*child
= node
->GetData();
533 child
->OnInternalIdle();
539 // ----------------------------------------------------------------------------
540 // menu/tool/status bar stuff
541 // ----------------------------------------------------------------------------
543 #if wxUSE_MENUS_NATIVE
545 void wxFrame::DetachMenuBar()
547 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
548 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
550 if ( m_frameMenuBar
)
552 m_frameMenuBar
->Attach( this );
554 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
556 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
557 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
559 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
560 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
563 gtk_widget_ref( m_frameMenuBar
->m_widget
);
565 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
568 wxFrameBase::DetachMenuBar();
571 void wxFrame::AttachMenuBar( wxMenuBar
*menuBar
)
573 wxFrameBase::AttachMenuBar(menuBar
);
577 m_frameMenuBar
->SetParent(this);
578 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
579 m_frameMenuBar
->m_widget
,
582 m_frameMenuBar
->m_width
,
583 m_frameMenuBar
->m_height
);
585 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
587 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
588 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
590 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
591 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
594 gtk_widget_show( m_frameMenuBar
->m_widget
);
601 GtkUpdateSize(); // resize window in OnInternalIdle
605 void wxFrame::UpdateMenuBarSize()
612 // this is called after Remove with a NULL m_frameMenuBar
613 if ( m_frameMenuBar
)
614 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_frameMenuBar
->m_widget
) )->size_request
)
615 (m_frameMenuBar
->m_widget
, &req
);
617 m_menuBarHeight
= req
.height
;
619 // resize window in OnInternalIdle
624 #endif // wxUSE_MENUS_NATIVE
628 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
630 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
632 m_insertInClientArea
= false;
634 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
636 m_insertInClientArea
= true;
640 return m_frameToolBar
;
643 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
645 bool hadTbar
= m_frameToolBar
!= NULL
;
647 wxFrameBase::SetToolBar(toolbar
);
649 if ( m_frameToolBar
)
651 // insert into toolbar area if not already there
652 if ((m_frameToolBar
->m_widget
->parent
) &&
653 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
655 GetChildren().DeleteObject( m_frameToolBar
);
657 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
661 else // toolbar unset
663 // still need to update size if it had been there before
671 #endif // wxUSE_TOOLBAR
675 wxStatusBar
* wxFrame::CreateStatusBar(int number
,
678 const wxString
& name
)
680 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
682 // because it will change when toolbar is added
685 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
688 void wxFrame::SetStatusBar(wxStatusBar
*statbar
)
690 bool hadStatBar
= m_frameStatusBar
!= NULL
;
692 wxFrameBase::SetStatusBar(statbar
);
694 if (hadStatBar
&& !m_frameStatusBar
)
698 void wxFrame::PositionStatusBar()
700 if ( !m_frameStatusBar
)
705 #endif // wxUSE_STATUSBAR