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 #ifndef __WXUNIVERSAL__
65 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxTopLevelWindow
)
68 // ============================================================================
70 // ============================================================================
72 // ----------------------------------------------------------------------------
74 // ----------------------------------------------------------------------------
76 #if wxUSE_MENUS_NATIVE
78 //-----------------------------------------------------------------------------
79 // "child_attached" of menu bar
80 //-----------------------------------------------------------------------------
82 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
84 if (!win
->m_hasVMT
) return;
86 win
->m_menuBarDetached
= FALSE
;
90 //-----------------------------------------------------------------------------
91 // "child_detached" of menu bar
92 //-----------------------------------------------------------------------------
94 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
96 if (!win
->m_hasVMT
) return;
98 win
->m_menuBarDetached
= TRUE
;
102 #endif // wxUSE_MENUS_NATIVE
105 //-----------------------------------------------------------------------------
106 // "child_attached" of tool bar
107 //-----------------------------------------------------------------------------
109 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
111 if (!win
->m_hasVMT
) return;
113 win
->m_toolBarDetached
= FALSE
;
115 win
->GtkUpdateSize();
118 //-----------------------------------------------------------------------------
119 // "child_detached" of tool bar
120 //-----------------------------------------------------------------------------
122 static void gtk_toolbar_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrameGTK
*win
)
125 wxapp_install_idle_handler();
127 if (!win
->m_hasVMT
) return;
129 win
->m_toolBarDetached
= TRUE
;
130 win
->GtkUpdateSize();
132 #endif // wxUSE_TOOLBAR
135 // ----------------------------------------------------------------------------
137 // ----------------------------------------------------------------------------
139 //-----------------------------------------------------------------------------
140 // InsertChild for wxFrameGTK
141 //-----------------------------------------------------------------------------
143 /* Callback for wxFrameGTK. This very strange beast has to be used because
144 * C++ has no virtual methods in a constructor. We have to emulate a
145 * virtual function here as wxWindows requires different ways to insert
146 * a child in container classes. */
148 static void wxInsertChildInFrame( wxFrameGTK
* parent
, wxWindow
* child
)
150 wxASSERT( GTK_IS_WIDGET(child
->m_widget
) );
152 if (!parent
->m_insertInClientArea
)
154 /* these are outside the client area */
155 wxFrameGTK
* frame
= (wxFrameGTK
*) parent
;
156 gtk_pizza_put( GTK_PIZZA(frame
->m_mainWidget
),
157 GTK_WIDGET(child
->m_widget
),
163 #if wxUSE_TOOLBAR_NATIVE
164 /* we connect to these events for recalculating the client area
165 space when the toolbar is floating */
166 if (wxIS_KIND_OF(child
,wxToolBar
))
168 wxToolBar
*toolBar
= (wxToolBar
*) child
;
169 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
171 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
172 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
174 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
175 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
178 #endif // wxUSE_TOOLBAR
182 /* these are inside the client area */
183 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
184 GTK_WIDGET(child
->m_widget
),
191 /* resize on OnInternalIdle */
192 parent
->GtkUpdateSize();
195 // ----------------------------------------------------------------------------
196 // wxFrameGTK creation
197 // ----------------------------------------------------------------------------
199 void wxFrameGTK::Init()
201 m_menuBarDetached
= FALSE
;
202 m_toolBarDetached
= FALSE
;
205 bool wxFrameGTK::Create( wxWindow
*parent
,
207 const wxString
& title
,
209 const wxSize
& sizeOrig
,
211 const wxString
&name
)
213 bool rt
= wxTopLevelWindow::Create(parent
, id
, title
, pos
, sizeOrig
,
215 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
219 wxFrameGTK::~wxFrameGTK()
221 m_isBeingDeleted
= TRUE
;
225 // ----------------------------------------------------------------------------
226 // overridden wxWindow methods
227 // ----------------------------------------------------------------------------
229 void wxFrameGTK::DoGetClientSize( int *width
, int *height
) const
231 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
233 wxTopLevelWindow::DoGetClientSize( width
, height
);
237 #if wxUSE_MENUS_NATIVE
241 if (!m_menuBarDetached
)
242 (*height
) -= wxMENU_HEIGHT
;
244 (*height
) -= wxPLACE_HOLDER
;
246 #endif // wxUSE_MENUS_NATIVE
250 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
251 (*height
) -= wxSTATUS_HEIGHT
;
252 #endif // wxUSE_STATUSBAR
256 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
258 if (m_toolBarDetached
)
260 *height
-= wxPLACE_HOLDER
;
265 m_frameToolBar
->GetSize( &x
, &y
);
266 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
276 #endif // wxUSE_TOOLBAR
280 void wxFrameGTK::DoSetClientSize( int width
, int height
)
282 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
284 #if wxUSE_MENUS_NATIVE
288 if (!m_menuBarDetached
)
289 height
+= wxMENU_HEIGHT
;
291 height
+= wxPLACE_HOLDER
;
293 #endif // wxUSE_MENUS_NATIVE
297 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown()) height
+= wxSTATUS_HEIGHT
;
302 if (m_frameToolBar
&& m_frameToolBar
->IsShown())
304 if (m_toolBarDetached
)
306 height
+= wxPLACE_HOLDER
;
311 m_frameToolBar
->GetSize( &x
, &y
);
312 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
324 wxTopLevelWindow::DoSetClientSize( width
, height
);
327 void wxFrameGTK::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
),
328 int width
, int height
)
330 // due to a bug in gtk, x,y are always 0
334 /* avoid recursions */
335 if (m_resizing
) return;
338 /* this shouldn't happen: wxFrameGTK, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
339 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
344 /* space occupied by m_frameToolBar and m_frameMenuBar */
345 int client_area_x_offset
= 0,
346 client_area_y_offset
= 0;
348 /* wxMDIChildFrame derives from wxFrameGTK but it _is_ a wxWindow as it uses
349 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
350 set in wxFrameGTK::Create so it is used to check what kind of frame we
351 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
352 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
353 importantly) m_mainWidget */
355 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
356 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
357 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
358 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
363 gint flag
= 0; // GDK_HINT_POS;
364 if ((m_minWidth
!= -1) || (m_minHeight
!= -1)) flag
|= GDK_HINT_MIN_SIZE
;
365 if ((m_maxWidth
!= -1) || (m_maxHeight
!= -1)) flag
|= GDK_HINT_MAX_SIZE
;
367 geom
.min_width
= m_minWidth
;
368 geom
.min_height
= m_minHeight
;
369 geom
.max_width
= m_maxWidth
;
370 geom
.max_height
= m_maxHeight
;
371 gtk_window_set_geometry_hints( GTK_WINDOW(m_widget
),
374 (GdkWindowHints
) flag
);
376 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
377 * menubar, the toolbar and the client area, which is represented by
379 * this hurts in the eye, but I don't want to call SetSize()
380 * because I don't want to call any non-native functions here. */
382 #if wxUSE_MENUS_NATIVE
386 int yy
= m_miniEdge
+ m_miniTitle
;
387 int ww
= m_width
- 2*m_miniEdge
;
388 int hh
= wxMENU_HEIGHT
;
389 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
390 m_frameMenuBar
->m_x
= xx
;
391 m_frameMenuBar
->m_y
= yy
;
392 m_frameMenuBar
->m_width
= ww
;
393 m_frameMenuBar
->m_height
= hh
;
394 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
395 m_frameMenuBar
->m_widget
,
397 client_area_y_offset
+= hh
;
399 #endif // wxUSE_MENUS_NATIVE
402 if ((m_frameToolBar
) && m_frameToolBar
->IsShown() &&
403 (m_frameToolBar
->m_widget
->parent
== m_mainWidget
))
406 int yy
= m_miniEdge
+ m_miniTitle
;
407 #if wxUSE_MENUS_NATIVE
410 if (!m_menuBarDetached
)
413 yy
+= wxPLACE_HOLDER
;
415 #endif // wxUSE_MENUS_NATIVE
417 m_frameToolBar
->m_x
= xx
;
418 m_frameToolBar
->m_y
= yy
;
420 /* don't change the toolbar's reported height/width */
422 if ( m_frameToolBar
->GetWindowStyle() & wxTB_VERTICAL
)
424 ww
= m_toolBarDetached
? wxPLACE_HOLDER
425 : m_frameToolBar
->m_width
;
426 hh
= m_height
- 2*m_miniEdge
;
428 client_area_x_offset
+= ww
;
432 ww
= m_width
- 2*m_miniEdge
;
433 hh
= m_toolBarDetached
? wxPLACE_HOLDER
434 : m_frameToolBar
->m_height
;
436 client_area_y_offset
+= hh
;
439 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
440 m_frameToolBar
->m_widget
,
443 #endif // wxUSE_TOOLBAR
445 int client_x
= client_area_x_offset
+ m_miniEdge
;
446 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
447 int client_w
= m_width
- client_area_x_offset
- 2*m_miniEdge
;
448 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
449 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget
),
451 client_x
, client_y
, client_w
, client_h
);
455 /* if there is no m_mainWidget between m_widget and m_wxwindow there
456 is no need to set the size or position of m_wxwindow. */
460 if (m_frameStatusBar
&& m_frameStatusBar
->IsShown())
462 int xx
= 0 + m_miniEdge
;
463 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
464 int ww
= m_width
- 2*m_miniEdge
;
465 int hh
= wxSTATUS_HEIGHT
;
466 m_frameStatusBar
->m_x
= xx
;
467 m_frameStatusBar
->m_y
= yy
;
468 m_frameStatusBar
->m_width
= ww
;
469 m_frameStatusBar
->m_height
= hh
;
470 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow
),
471 m_frameStatusBar
->m_widget
,
473 gtk_widget_draw( m_frameStatusBar
->m_widget
, (GdkRectangle
*) NULL
);
475 #endif // wxUSE_STATUSBAR
479 // send size event to frame
480 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
481 event
.SetEventObject( this );
482 GetEventHandler()->ProcessEvent( event
);
485 // send size event to status bar
486 if (m_frameStatusBar
)
488 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
489 event2
.SetEventObject( m_frameStatusBar
);
490 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
492 #endif // wxUSE_STATUSBAR
497 void wxFrameGTK::OnInternalIdle()
499 wxTopLevelWindow::OnInternalIdle();
501 #if wxUSE_MENUS_NATIVE
502 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
503 #endif // wxUSE_MENUS_NATIVE
505 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
508 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
512 // ----------------------------------------------------------------------------
513 // menu/tool/status bar stuff
514 // ----------------------------------------------------------------------------
516 #if wxUSE_MENUS_NATIVE
518 void wxFrameGTK::DetachMenuBar()
520 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
521 wxASSERT_MSG( (m_wxwindow
!= NULL
), wxT("invalid frame") );
523 if ( m_frameMenuBar
)
525 m_frameMenuBar
->UnsetInvokingWindow( this );
527 if (m_frameMenuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
529 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
530 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
532 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar
->m_widget
),
533 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
536 gtk_container_remove( GTK_CONTAINER(m_mainWidget
), m_frameMenuBar
->m_widget
);
537 gtk_widget_ref( m_frameMenuBar
->m_widget
);
538 gtk_widget_unparent( m_frameMenuBar
->m_widget
);
541 wxFrameBase::DetachMenuBar();
544 void wxFrameGTK::AttachMenuBar( wxMenuBar
*menuBar
)
546 wxFrameBase::AttachMenuBar(menuBar
);
550 m_frameMenuBar
->SetInvokingWindow( this );
552 m_frameMenuBar
->SetParent(this);
553 gtk_pizza_put( GTK_PIZZA(m_mainWidget
),
554 m_frameMenuBar
->m_widget
,
557 m_frameMenuBar
->m_width
,
558 m_frameMenuBar
->m_height
);
560 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
562 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
563 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
565 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
566 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
569 m_frameMenuBar
->Show( TRUE
);
572 /* resize window in OnInternalIdle */
576 #endif // wxUSE_MENUS_NATIVE
580 wxToolBar
* wxFrameGTK::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
582 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
584 m_insertInClientArea
= FALSE
;
586 m_frameToolBar
= wxFrameBase::CreateToolBar( style
, id
, name
);
588 m_insertInClientArea
= TRUE
;
592 return m_frameToolBar
;
595 void wxFrameGTK::SetToolBar(wxToolBar
*toolbar
)
597 wxFrameBase::SetToolBar(toolbar
);
601 /* insert into toolbar area if not already there */
602 if ((m_frameToolBar
->m_widget
->parent
) &&
603 (m_frameToolBar
->m_widget
->parent
!= m_mainWidget
))
605 GetChildren().DeleteObject( m_frameToolBar
);
607 gtk_widget_reparent( m_frameToolBar
->m_widget
, m_mainWidget
);
613 #endif // wxUSE_TOOLBAR
617 wxStatusBar
* wxFrameGTK::CreateStatusBar(int number
,
620 const wxString
& name
)
622 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid frame") );
624 // because it will change when toolbar is added
627 return wxFrameBase::CreateStatusBar( number
, style
, id
, name
);
630 void wxFrameGTK::PositionStatusBar()
632 if ( !m_frameStatusBar
)
637 #endif // wxUSE_STATUSBAR