1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
19 #pragma implementation "frame.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"
39 #include <gdk/gdkkeysyms.h>
42 #include "wx/gtk/win_gtk.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 const int wxMENU_HEIGHT
= 27;
49 const int wxSTATUS_HEIGHT
= 25;
50 const int wxPLACE_HOLDER
= 0;
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 extern void wxapp_install_idle_handler();
58 extern int g_openDialogs
;
60 // ----------------------------------------------------------------------------
62 // ----------------------------------------------------------------------------
64 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
66 // ============================================================================
68 // ============================================================================
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 #if wxUSE_MENUS_NATIVE
76 //-----------------------------------------------------------------------------
77 // "child_attached" of menu bar
78 //-----------------------------------------------------------------------------
80 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
82 if (!win
->m_hasVMT
) return;
84 win
->m_menuBarDetached
= FALSE
;
88 //-----------------------------------------------------------------------------
89 // "child_detached" of menu bar
90 //-----------------------------------------------------------------------------
92 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
94 if (!win
->m_hasVMT
) return;
96 win
->m_menuBarDetached
= TRUE
;
100 #endif // wxUSE_MENUS_NATIVE
103 //-----------------------------------------------------------------------------
104 // "child_attached" of tool bar
105 //-----------------------------------------------------------------------------
107 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
109 if (!win
->m_hasVMT
) return;
111 win
->m_toolBarDetached
= FALSE
;
113 win
->GtkUpdateSize();
116 //-----------------------------------------------------------------------------
117 // "child_detached" of tool bar
118 //-----------------------------------------------------------------------------
120 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
123 wxapp_install_idle_handler();
125 if (!win
->m_hasVMT
) return;
127 win
->m_toolBarDetached
= TRUE
;
128 win
->GtkUpdateSize();
130 #endif // wxUSE_TOOLBAR
133 // ----------------------------------------------------------------------------
135 // ----------------------------------------------------------------------------
137 //-----------------------------------------------------------------------------
138 // InsertChild for wxFrame
139 //-----------------------------------------------------------------------------
141 /* Callback for wxFrame. This very strange beast has to be used because
142 * C++ has no virtual methods in a constructor. We have to emulate a
143 * virtual function here as wxWindows requires different ways to insert
144 * a child in container classes. */
146 static void wxInsertChildInFrame( wxFrame
* parent
, wxWindow
* child
)
148 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
150 if (!parent
->m_insertInClientArea
)
152 /* these are outside the client area */
153 wxFrame
* frame
= (wxFrame
*) parent
;
154 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
155 GTK_WIDGET(child
->m_widget
),
161 #if wxUSE_TOOLBAR_NATIVE
162 /* we connect to these events for recalculating the client area
163 space when the toolbar is floating */
164 if (wxIS_KIND_OF(child
,wxToolBar
))
166 wxToolBar
*toolBar
= (wxToolBar
*) child
;
167 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
169 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
170 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
172 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
173 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
176 #endif // wxUSE_TOOLBAR
180 /* these are inside the client area */
181 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
182 GTK_WIDGET(child
->m_widget
),
189 /* resize on OnInternalIdle */
190 parent
->GtkUpdateSize();
193 // ----------------------------------------------------------------------------
195 // ----------------------------------------------------------------------------
199 m_menuBarDetached
= FALSE
;
200 m_toolBarDetached
= FALSE
;
203 bool wxFrame::Create( wxWindow
*parent
,
205 const wxString
& title
,
207 const wxSize
& sizeOrig
,
209 const wxString
&name
)
211 bool rt
= wxTopLevelWindow::Create(parent
, id
, title
, pos
, sizeOrig
,
213 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
219 m_isBeingDeleted
= TRUE
;
223 // ----------------------------------------------------------------------------
224 // overridden wxWindow methods
225 // ----------------------------------------------------------------------------
227 void wxFrame::DoGetClientSize( int *width
, int *height
) const
229 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
231 wxTopLevelWindow::DoGetClientSize( width
, height
);
235 #if wxUSE_MENUS_NATIVE
239 if (!m_menuBarDetached
)
240 (*height
) -= wxMENU_HEIGHT
;
242 (*height
) -= wxPLACE_HOLDER
;
244 #endif // wxUSE_MENUS_NATIVE
248 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
249 (*height
) -= wxSTATUS_HEIGHT
;
250 #endif // wxUSE_STATUSBAR
254 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
256 if (m_toolBarDetached
)
258 *height
-= wxPLACE_HOLDER
;
263 m_frameToolBar
->GetSize( &x
, &y
);
264 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
274 #endif // wxUSE_TOOLBAR
278 void wxFrame::DoSetClientSize( int width
, int height
)
280 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
282 #if wxUSE_MENUS_NATIVE
286 if (!m_menuBarDetached
)
287 height
+= wxMENU_HEIGHT
;
289 height
+= wxPLACE_HOLDER
;
291 #endif // wxUSE_MENUS_NATIVE
295 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
300 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
302 if (m_toolBarDetached
)
304 height
+= wxPLACE_HOLDER
;
309 m_frameToolBar
->GetSize( &x
, &y
);
310 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
322 wxTopLevelWindow::DoSetClientSize( width
, height
);
325 void wxFrame::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
326 int width
, int height
)
328 // due to a bug in gtk, x,y are always 0
332 /* avoid recursions */
333 if (m_resizing
) return;
336 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
337 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
342 /* space occupied by m_frameToolBar and m_frameMenuBar */
343 int client_area_x_offset
= 0,
344 client_area_y_offset
= 0;
346 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
347 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
348 set in wxFrame::Create so it is used to check what kind of frame we
349 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
350 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
351 importantly) m_mainWidget */
353 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
354 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
355 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
356 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
361 gint flag
= 0; // GDK_HINT_POS;
362 if ((m_minWidth
!= -1) || (m_minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
363 if ((m_maxWidth
!= -1) || (m_maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
365 geom
.min_width
= m_minWidth
;
366 geom
.min_height
= m_minHeight
;
367 geom
.max_width
= m_maxWidth
;
368 geom
.max_height
= m_maxHeight
;
369 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
372 (GdkWindowHints
) flag
);
374 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
375 * menubar, the toolbar and the client area, which is represented by
377 * this hurts in the eye, but I don't want to call SetSize()
378 * because I don't want to call any non-native functions here. */
380 #if wxUSE_MENUS_NATIVE
384 int yy
= m_miniEdge
+ m_miniTitle
;
385 int ww
= m_width
- 2*m_miniEdge
;
386 int hh
= wxMENU_HEIGHT
;
387 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
388 m_frameMenuBar
->m_x
= xx
;
389 m_frameMenuBar
->m_y
= yy
;
390 m_frameMenuBar
->m_width
= ww
;
391 m_frameMenuBar
->m_height
= hh
;
392 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
393 m_frameMenuBar
->m_widget
,
395 client_area_y_offset
+= hh
;
397 #endif // wxUSE_MENUS_NATIVE
400 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
401 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
404 int yy
= m_miniEdge
+ m_miniTitle
;
405 #if wxUSE_MENUS_NATIVE
408 if (!m_menuBarDetached
)
411 yy
+= wxPLACE_HOLDER
;
413 #endif // wxUSE_MENUS_NATIVE
415 m_frameToolBar
->m_x
= xx
;
416 m_frameToolBar
->m_y
= yy
;
418 /* don't change the toolbar's reported height/width */
420 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
422 ww
= m_toolBarDetached
? wxPLACE_HOLDER
423 : m_frameToolBar
->m_width
;
424 hh
= m_height
- 2*m_miniEdge
;
426 client_area_x_offset
+= ww
;
430 ww
= m_width
- 2*m_miniEdge
;
431 hh
= m_toolBarDetached
? wxPLACE_HOLDER
432 : m_frameToolBar
->m_height
;
434 client_area_y_offset
+= hh
;
437 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
438 m_frameToolBar
->m_widget
,
441 #endif // wxUSE_TOOLBAR
443 int client_x
= client_area_x_offset
+ m_miniEdge
;
444 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
445 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
446 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
447 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
449 client_x
, client_y
, client_w
, client_h
);
453 /* if there is no m_mainWidget between m_widget and m_wxwindow there
454 is no need to set the size or position of m_wxwindow. */
458 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
460 int xx
= 0 + m_miniEdge
;
461 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
462 int ww
= m_width
- 2*m_miniEdge
;
463 int hh
= wxSTATUS_HEIGHT
;
464 m_frameStatusBar
->m_x
= xx
;
465 m_frameStatusBar
->m_y
= yy
;
466 m_frameStatusBar
->m_width
= ww
;
467 m_frameStatusBar
->m_height
= hh
;
468 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
469 m_frameStatusBar
->m_widget
,
471 gtk_widget_draw( m_frameStatusBar
->m_widget
, (GdkRectangle
*) NULL
);
473 #endif // wxUSE_STATUSBAR
477 // send size event to frame
478 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
479 event
.SetEventObject( this );
480 GetEventHandler()->ProcessEvent( event
);
483 // send size event to status bar
484 if (m_frameStatusBar
)
486 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
487 event2
.SetEventObject( m_frameStatusBar
);
488 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
490 #endif // wxUSE_STATUSBAR
495 void wxFrame::OnInternalIdle()
497 wxTopLevelWindow::OnInternalIdle();
499 #if wxUSE_MENUS_NATIVE
500 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
501 #endif // wxUSE_MENUS_NATIVE
503 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
506 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
510 // ----------------------------------------------------------------------------
511 // menu/tool/status bar stuff
512 // ----------------------------------------------------------------------------
514 #if wxUSE_MENUS_NATIVE
516 void wxFrame::DetachMenuBar()
518 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
519 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
521 if ( m_frameMenuBar
)
523 m_frameMenuBar
->UnsetInvokingWindow( this );
525 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
527 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
528 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
530 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
531 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
534 gtk_widget_ref( m_frameMenuBar
->m_widget
);
536 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
539 wxFrameBase::DetachMenuBar();
542 void wxFrame::AttachMenuBar( wxMenuBar
*menuBar
)
544 wxFrameBase::AttachMenuBar(menuBar
);
548 m_frameMenuBar
->SetInvokingWindow( this );
550 m_frameMenuBar
->SetParent(this);
551 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
552 m_frameMenuBar
->m_widget
,
555 m_frameMenuBar
->m_width
,
556 m_frameMenuBar
->m_height
);
558 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
560 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
561 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
563 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
564 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
567 m_frameMenuBar
->Show( TRUE
);
570 // resize window in OnInternalIdle
574 #endif // wxUSE_MENUS_NATIVE
578 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
580 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
582 m_insertInClientArea
= FALSE
;
584 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
586 m_insertInClientArea
= TRUE
;
590 return m_frameToolBar
;
593 void wxFrame::SetToolBar(wxToolBar
*toolbar
)
595 wxFrameBase::SetToolBar(toolbar
);
599 // insert into toolbar area if not already there
600 if ((m_frameToolBar
->m_widget
->parent
) &&
601 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
603 GetChildren().DeleteObject( m_frameToolBar
);
605 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
611 #endif // wxUSE_TOOLBAR
615 wxStatusBar
* wxFrame::CreateStatusBar(int number
,
618 const wxString
& name
)
620 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
622 // because it will change when toolbar is added
625 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
628 void wxFrame::PositionStatusBar()
630 if ( !m_frameStatusBar
)
635 #endif // wxUSE_STATUSBAR