1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "frame.h"
15 #include "wx/dialog.h"
16 #include "wx/control.h"
19 #include "wx/toolbar.h"
20 #include "wx/statusbr.h"
21 #include "wx/dcclient.h"
26 #include "wx/gtk/win_gtk.h"
27 #include "gdk/gdkkeysyms.h"
29 //-----------------------------------------------------------------------------
31 //-----------------------------------------------------------------------------
33 const int wxMENU_HEIGHT
= 27;
34 const int wxSTATUS_HEIGHT
= 25;
35 const int wxPLACE_HOLDER
= 0;
37 //-----------------------------------------------------------------------------
39 //-----------------------------------------------------------------------------
41 extern void wxapp_install_idle_handler();
44 //-----------------------------------------------------------------------------
46 //-----------------------------------------------------------------------------
48 extern wxList wxPendingDelete
;
50 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
56 extern void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
);
60 //-----------------------------------------------------------------------------
62 //-----------------------------------------------------------------------------
64 static void gtk_frame_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxFrame
*win
)
67 wxapp_install_idle_handler();
69 if (!win
->m_hasVMT
) return;
71 if ((win
->m_width
!= alloc
->width
) || (win
->m_height
!= alloc
->height
))
73 win
->m_width
= alloc
->width
;
74 win
->m_height
= alloc
->height
;
79 //-----------------------------------------------------------------------------
81 //-----------------------------------------------------------------------------
83 static gint
gtk_frame_delete_callback( GtkWidget
*WXUNUSED(widget
), GdkEvent
*WXUNUSED(event
), wxFrame
*win
)
86 wxapp_install_idle_handler();
93 //-----------------------------------------------------------------------------
94 // "child_attached" of menu bar
95 //-----------------------------------------------------------------------------
97 static void gtk_menu_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
99 if (!win
->m_hasVMT
) return;
101 win
->m_menuBarDetached
= FALSE
;
105 //-----------------------------------------------------------------------------
106 // "child_detached" of menu bar
107 //-----------------------------------------------------------------------------
109 static void gtk_menu_detached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
111 if (!win
->m_hasVMT
) return;
113 win
->m_menuBarDetached
= TRUE
;
118 //-----------------------------------------------------------------------------
119 // "child_attached" of tool bar
120 //-----------------------------------------------------------------------------
122 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
124 if (!win
->m_hasVMT
) return;
126 win
->m_toolBarDetached
= FALSE
;
131 //-----------------------------------------------------------------------------
132 // "child_detached" of tool bar
133 //-----------------------------------------------------------------------------
135 static void gtk_toolbar_detached_callback( GtkWidget
*widget
, GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
138 wxapp_install_idle_handler();
140 if (!win
->m_hasVMT
) return;
142 win
->m_toolBarDetached
= TRUE
;
145 #endif // wxUSE_TOOLBAR
147 //-----------------------------------------------------------------------------
149 //-----------------------------------------------------------------------------
151 static gint
gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*WXUNUSED(event
), wxFrame
*win
)
154 wxapp_install_idle_handler();
156 if (!win
->m_hasVMT
) return FALSE
;
160 gdk_window_get_root_origin( win
->m_widget
->window
, &x
, &y
);
165 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
166 mevent
.SetEventObject( win
);
167 win
->GetEventHandler()->ProcessEvent( mevent
);
172 //-----------------------------------------------------------------------------
173 // "realize" from m_widget
174 //-----------------------------------------------------------------------------
176 /* we cannot MWM hints and icons before the widget has been realized,
177 so we do this directly after realization */
180 gtk_frame_realized_callback( GtkWidget
*widget
, wxFrame
*win
)
183 wxapp_install_idle_handler();
185 /* all this is for Motif Window Manager "hints" and is supposed to be
186 recognized by other WM as well. not tested. */
187 long decor
= (long) GDK_DECOR_BORDER
;
188 long func
= (long) GDK_FUNC_MOVE
;
190 if ((win
->GetWindowStyle() & wxCAPTION
) != 0)
191 decor
|= GDK_DECOR_TITLE
;
192 if ((win
->GetWindowStyle() & wxSYSTEM_MENU
) != 0)
194 decor
|= GDK_DECOR_MENU
;
195 func
|= GDK_FUNC_CLOSE
;
197 if ((win
->GetWindowStyle() & wxMINIMIZE_BOX
) != 0)
199 func
|= GDK_FUNC_MINIMIZE
;
200 decor
|= GDK_DECOR_MINIMIZE
;
202 if ((win
->GetWindowStyle() & wxMAXIMIZE_BOX
) != 0)
204 func
|= GDK_FUNC_MAXIMIZE
;
205 decor
|= GDK_DECOR_MAXIMIZE
;
207 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) != 0)
209 func
|= GDK_FUNC_RESIZE
;
210 decor
|= GDK_DECOR_RESIZEH
;
214 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)decor
);
215 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)func
);
217 /* GTK's shrinking/growing policy */
218 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) == 0)
219 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
221 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
224 if (win
->m_icon
!= wxNullIcon
)
226 wxIcon
icon( win
->m_icon
);
227 win
->m_icon
= wxNullIcon
;
228 win
->SetIcon( icon
);
231 /* we set the focus to the child that accepts the focus. this
232 doesn't really have to be done in "realize" but why not? */
233 wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
236 wxWindow
*child
= node
->GetData();
237 if (child
->AcceptsFocus())
243 node
= node
->GetNext();
249 //-----------------------------------------------------------------------------
250 // InsertChild for wxFrame
251 //-----------------------------------------------------------------------------
253 /* Callback for wxFrame. This very strange beast has to be used because
254 * C++ has no virtual methods in a constructor. We have to emulate a
255 * virtual function here as wxWindows requires different ways to insert
256 * a child in container classes. */
258 static void wxInsertChildInFrame( wxFrame
* parent
, wxWindow
* child
)
260 if (!parent
->m_insertInClientArea
)
262 /* these are outside the client area */
263 wxFrame
* frame
= (wxFrame
*) parent
;
264 gtk_myfixed_put( GTK_MYFIXED(frame
->m_mainWidget
),
265 GTK_WIDGET(child
->m_widget
),
272 /* we connect to these events for recalculating the client area
273 space when the toolbar is floating */
274 if (wxIS_KIND_OF(child
,wxToolBar
))
276 wxToolBar
*toolBar
= (wxToolBar
*) child
;
277 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
279 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
280 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
282 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
283 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
286 #endif // wxUSE_TOOLBAR
290 /* these are inside the client area */
291 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
292 GTK_WIDGET(child
->m_widget
),
299 /* resize on OnInternalIdle */
300 parent
->UpdateSize();
303 //-----------------------------------------------------------------------------
305 //-----------------------------------------------------------------------------
307 BEGIN_EVENT_TABLE(wxFrame
, wxWindow
)
308 EVT_SIZE(wxFrame::OnSize
)
309 EVT_CLOSE(wxFrame::OnCloseWindow
)
310 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight
)
313 IMPLEMENT_DYNAMIC_CLASS(wxFrame
,wxWindow
)
317 m_frameMenuBar
= (wxMenuBar
*) NULL
;
319 m_frameStatusBar
= (wxStatusBar
*) NULL
;
320 #endif // wxUSE_STATUSBAR
322 m_frameToolBar
= (wxToolBar
*) NULL
;
323 #endif // wxUSE_TOOLBAR
327 m_mainWidget
= (GtkWidget
*) NULL
;
328 m_menuBarDetached
= FALSE
;
329 m_toolBarDetached
= FALSE
;
330 m_insertInClientArea
= TRUE
;
333 wxFrame::wxFrame( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
334 const wxPoint
&pos
, const wxSize
&size
,
335 long style
, const wxString
&name
)
339 Create( parent
, id
, title
, pos
, size
, style
, name
);
342 bool wxFrame::Create( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
343 const wxPoint
&pos
, const wxSize
&size
,
344 long style
, const wxString
&name
)
346 wxTopLevelWindows
.Append( this );
348 m_needParent
= FALSE
;
350 PreCreation( parent
, id
, pos
, size
, style
, name
);
354 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
356 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
357 if (style
& wxSIMPLE_BORDER
) win_type
= GTK_WINDOW_POPUP
;
359 m_widget
= gtk_window_new( win_type
);
362 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), name
.mb_str(), name
.mb_str() );
365 debug_focus_in( m_widget
, _T("wxFrame::m_widget"), name
);
368 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
369 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
371 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
372 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
374 /* m_mainWidget holds the toolbar, the menubar and the client area */
375 m_mainWidget
= gtk_myfixed_new();
376 gtk_widget_show( m_mainWidget
);
377 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
378 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
381 debug_focus_in( m_mainWidget
, _T("wxFrame::m_mainWidget"), name
);
384 /* m_wxwindow only represents the client area without toolbar and menubar */
385 m_wxwindow
= gtk_myfixed_new();
386 gtk_widget_show( m_wxwindow
);
387 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
390 debug_focus_in( m_wxwindow
, _T("wxFrame::m_wxwindow"), name
);
393 /* we donm't allow the frame to get the focus as otherwise
394 the frame will grabit at arbitrary fcous changes. */
395 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
397 if (m_parent
) m_parent
->AddChild( this );
401 /* we cannot set MWM hints and icons before the widget has
402 been realized, so we do this directly after realization */
403 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
404 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
406 /* the user resized the frame by dragging etc. */
407 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
408 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
410 /* the only way to get the window size is to connect to this event */
411 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
412 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
419 m_isBeingDeleted
= TRUE
;
421 if (m_frameMenuBar
) delete m_frameMenuBar
;
422 m_frameMenuBar
= (wxMenuBar
*) NULL
;
425 if (m_frameStatusBar
) delete m_frameStatusBar
;
426 m_frameStatusBar
= (wxStatusBar
*) NULL
;
427 #endif // wxUSE_STATUSBAR
430 if (m_frameToolBar
) delete m_frameToolBar
;
431 m_frameToolBar
= (wxToolBar
*) NULL
;
432 #endif // wxUSE_TOOLBAR
434 wxTopLevelWindows
.DeleteObject( this );
436 if (wxTheApp
->GetTopWindow() == this)
437 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
439 if (wxTopLevelWindows
.Number() == 0)
440 wxTheApp
->ExitMainLoop();
443 bool wxFrame::Show( bool show
)
445 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
447 if (show
&& !m_sizeSet
)
449 /* by calling GtkOnSize here, we don't have to call
450 either after showing the frame, which would entail
451 much ugly flicker or from within the size_allocate
452 handler, because GTK 1.1.X forbids that. */
454 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
457 return wxWindow::Show( show
);
460 bool wxFrame::Destroy()
462 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
464 if (!wxPendingDelete
.Member(this)) wxPendingDelete
.Append(this);
469 void wxFrame::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
471 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
473 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
474 wxASSERT_MSG( (m_wxwindow
!= NULL
), _T("invalid frame") );
476 /* avoid recursions */
477 if (m_resizing
) return;
482 int old_width
= m_width
;
483 int old_height
= m_height
;
485 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
487 if (x
!= -1) m_x
= x
;
488 if (y
!= -1) m_y
= y
;
489 if (width
!= -1) m_width
= width
;
490 if (height
!= -1) m_height
= height
;
500 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
502 if (width
== -1) m_width
= 80;
505 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
507 if (height
== -1) m_height
= 26;
510 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
511 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
512 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
513 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
515 if ((m_x
!= -1) || (m_y
!= -1))
517 if ((m_x
!= old_x
) || (m_y
!= old_y
))
519 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
523 if ((m_width
!= old_width
) || (m_height
!= old_height
))
525 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
526 done either directly before the frame is shown or in idle time
527 so that different calls to SetSize() don't lead to flicker. */
534 void wxFrame::Centre( int direction
)
536 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
541 if ((direction
& wxHORIZONTAL
) == wxHORIZONTAL
) x
= (gdk_screen_width () - m_width
) / 2;
542 if ((direction
& wxVERTICAL
) == wxVERTICAL
) y
= (gdk_screen_height () - m_height
) / 2;
547 void wxFrame::DoGetClientSize( int *width
, int *height
) const
549 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
551 wxWindow::DoGetClientSize( width
, height
);
557 if (!m_menuBarDetached
)
558 (*height
) -= wxMENU_HEIGHT
;
560 (*height
) -= wxPLACE_HOLDER
;
564 if (m_frameStatusBar
) (*height
) -= wxSTATUS_HEIGHT
;
569 if (!m_toolBarDetached
)
572 m_frameToolBar
->GetSize( (int *) NULL
, &y
);
576 (*height
) -= wxPLACE_HOLDER
;
580 (*height
) -= m_miniEdge
*2 + m_miniTitle
;
584 (*width
) -= m_miniEdge
*2;
588 void wxFrame::DoSetClientSize( int width
, int height
)
590 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
595 if (!m_menuBarDetached
)
596 height
+= wxMENU_HEIGHT
;
598 height
+= wxPLACE_HOLDER
;
602 if (m_frameStatusBar
) height
+= wxSTATUS_HEIGHT
;
607 if (!m_toolBarDetached
)
610 m_frameToolBar
->GetSize( (int *) NULL
, &y
);
614 height
+= wxPLACE_HOLDER
;
617 wxWindow::DoSetClientSize( width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
);
620 void wxFrame::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
), int width
, int height
)
622 // due to a bug in gtk, x,y are always 0
626 /* avoid recursions */
627 if (m_resizing
) return;
630 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
631 wxASSERT_MSG( (m_wxwindow
!= NULL
), _T("invalid frame") );
636 /* space occupied by m_frameToolBar and m_frameMenuBar */
637 int client_area_y_offset
= 0;
639 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
640 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
641 set in wxFrame::Create so it is used to check what kind of frame we
642 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
643 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
644 importantly) m_mainWidget */
648 /* check if size is in legal range */
649 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
650 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
651 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
652 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
654 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
655 * menubar, the toolbar and the client area, which is represented by
657 * this hurts in the eye, but I don't want to call SetSize()
658 * because I don't want to call any non-native functions here. */
663 int yy
= m_miniEdge
+ m_miniTitle
;
664 int ww
= m_width
- 2*m_miniEdge
;
665 int hh
= wxMENU_HEIGHT
;
666 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
667 m_frameMenuBar
->m_x
= xx
;
668 m_frameMenuBar
->m_y
= yy
;
669 m_frameMenuBar
->m_width
= ww
;
670 m_frameMenuBar
->m_height
= hh
;
671 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget
),
672 m_frameMenuBar
->m_widget
,
674 client_area_y_offset
+= hh
;
680 int yy
= m_miniEdge
+ m_miniTitle
;
683 if (!m_menuBarDetached
)
686 yy
+= wxPLACE_HOLDER
;
688 int ww
= m_width
- 2*m_miniEdge
;
689 int hh
= m_frameToolBar
->m_height
;
690 if (m_toolBarDetached
) hh
= wxPLACE_HOLDER
;
691 m_frameToolBar
->m_x
= xx
;
692 m_frameToolBar
->m_y
= yy
;
693 /* m_frameToolBar->m_height = hh; don't change the toolbar's height */
694 m_frameToolBar
->m_width
= ww
;
695 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget
),
696 m_frameToolBar
->m_widget
,
698 client_area_y_offset
+= hh
;
701 int client_x
= m_miniEdge
;
702 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
703 int client_w
= m_width
- 2*m_miniEdge
;
704 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
705 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget
),
707 client_x
, client_y
, client_w
, client_h
);
711 /* if there is no m_mainWidget between m_widget and m_wxwindow there
712 is no need to set the size or position of m_wxwindow. */
715 if (m_frameStatusBar
)
717 int xx
= 0 + m_miniEdge
;
718 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
719 int ww
= m_width
- 2*m_miniEdge
;
720 int hh
= wxSTATUS_HEIGHT
;
721 m_frameStatusBar
->m_x
= xx
;
722 m_frameStatusBar
->m_y
= yy
;
723 m_frameStatusBar
->m_width
= ww
;
724 m_frameStatusBar
->m_height
= hh
;
725 gtk_myfixed_set_size( GTK_MYFIXED(m_wxwindow
),
726 m_frameStatusBar
->m_widget
,
730 /* we actually set the size of a frame here and no-where else */
731 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
735 /* send size event to frame */
736 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
737 event
.SetEventObject( this );
738 GetEventHandler()->ProcessEvent( event
);
740 /* send size event to status bar */
741 if (m_frameStatusBar
)
743 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
744 event2
.SetEventObject( m_frameStatusBar
);
745 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
751 void wxFrame::MakeModal( bool modal
)
754 gtk_grab_add( m_widget
);
756 gtk_grab_remove( m_widget
);
759 void wxFrame::OnInternalIdle()
761 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
762 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
766 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
767 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
768 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
771 void wxFrame::OnCloseWindow( wxCloseEvent
& WXUNUSED(event
) )
776 void wxFrame::OnSize( wxSizeEvent
&WXUNUSED(event
) )
778 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
780 #if wxUSE_CONSTRAINTS
786 #endif // wxUSE_CONSTRAINTS
788 /* do we have exactly one child? */
789 wxWindow
*child
= (wxWindow
*)NULL
;
790 for ( wxNode
*node
= GetChildren().First(); node
; node
= node
->Next() )
792 wxWindow
*win
= (wxWindow
*)node
->Data();
793 if ( !wxIS_KIND_OF(win
,wxFrame
) && !wxIS_KIND_OF(win
,wxDialog
) )
797 /* it's the second one: do nothing */
805 /* no children at all? */
808 /* yes: set it's size to fill all the frame */
809 int client_x
, client_y
;
810 DoGetClientSize( &client_x
, &client_y
);
811 child
->SetSize( 1, 1, client_x
-2, client_y
-2 );
816 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
818 menu
->SetInvokingWindow( win
);
820 #if (GTK_MINOR_VERSION > 0)
821 /* support for native hot keys */
822 gtk_accel_group_attach( menu
->m_accel
, GTK_OBJECT(win
->m_widget
));
825 wxNode
*node
= menu
->GetItems().First();
828 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
829 if (menuitem
->IsSubMenu())
830 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
835 void wxFrame::SetMenuBar( wxMenuBar
*menuBar
)
837 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
838 wxASSERT_MSG( (m_wxwindow
!= NULL
), _T("invalid frame") );
840 m_frameMenuBar
= menuBar
;
844 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
845 /* support for native key accelerators indicated by underscroes */
846 gtk_accel_group_attach( m_frameMenuBar
->m_accel
, GTK_OBJECT(m_widget
));
849 wxNode
*node
= m_frameMenuBar
->GetMenus().First();
852 wxMenu
*menu
= (wxMenu
*)node
->Data();
853 SetInvokingWindow( menu
, this );
857 if (m_frameMenuBar
->GetParent() != this)
859 m_frameMenuBar
->SetParent(this);
860 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget
),
861 m_frameMenuBar
->m_widget
,
864 m_frameMenuBar
->m_width
,
865 m_frameMenuBar
->m_height
);
867 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
869 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
870 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
872 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
873 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
878 /* resize window in OnInternalIdle */
882 wxMenuBar
*wxFrame::GetMenuBar() const
884 return m_frameMenuBar
;
887 void wxFrame::OnMenuHighlight(wxMenuEvent
& event
)
892 // if no help string found, we will clear the status bar text
895 int menuId
= event
.GetMenuId();
898 wxMenuBar
*menuBar
= GetMenuBar();
901 helpString
= menuBar
->GetHelpString(menuId
);
905 SetStatusText(helpString
);
907 #endif // wxUSE_STATUSBAR
911 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
913 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
915 wxCHECK_MSG( m_frameToolBar
== NULL
, FALSE
, _T("recreating toolbar in wxFrame") );
917 m_insertInClientArea
= FALSE
;
919 m_frameToolBar
= OnCreateToolBar( style
, id
, name
);
921 if (m_frameToolBar
) GetChildren().DeleteObject( m_frameToolBar
);
923 m_insertInClientArea
= TRUE
;
927 return m_frameToolBar
;
930 wxToolBar
* wxFrame::OnCreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
932 return new wxToolBar( this, id
, wxDefaultPosition
, wxDefaultSize
, style
, name
);
935 wxToolBar
*wxFrame::GetToolBar() const
937 return m_frameToolBar
;
939 #endif // wxUSE_TOOLBAR
942 wxStatusBar
* wxFrame::CreateStatusBar( int number
, long style
, wxWindowID id
, const wxString
& name
)
944 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
946 wxCHECK_MSG( m_frameStatusBar
== NULL
, FALSE
, _T("recreating status bar in wxFrame") );
948 m_frameStatusBar
= OnCreateStatusBar( number
, style
, id
, name
);
952 return m_frameStatusBar
;
955 wxStatusBar
*wxFrame::OnCreateStatusBar( int number
, long style
, wxWindowID id
, const wxString
& name
)
957 wxStatusBar
*statusBar
= (wxStatusBar
*) NULL
;
959 statusBar
= new wxStatusBar(this, id
, wxPoint(0, 0), wxSize(100, 20), style
, name
);
961 // Set the height according to the font and the border size
962 wxClientDC
dc(statusBar
);
963 dc
.SetFont( statusBar
->GetFont() );
966 dc
.GetTextExtent( "X", &x
, &y
);
968 int height
= (int)( (y
* 1.1) + 2* statusBar
->GetBorderY());
970 statusBar
->SetSize( -1, -1, 100, height
);
972 statusBar
->SetFieldsCount( number
);
976 wxStatusBar
*wxFrame::GetStatusBar() const
978 return m_frameStatusBar
;
981 void wxFrame::SetStatusText(const wxString
& text
, int number
)
983 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
985 wxCHECK_RET( m_frameStatusBar
!= NULL
, _T("no statusbar to set text for") );
987 m_frameStatusBar
->SetStatusText(text
, number
);
990 void wxFrame::SetStatusWidths(int n
, const int widths_field
[] )
992 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
994 wxCHECK_RET( m_frameStatusBar
!= NULL
, _T("no statusbar to set widths for") );
996 m_frameStatusBar
->SetStatusWidths(n
, widths_field
);
998 #endif // wxUSE_STATUSBAR
1000 void wxFrame::Command( int id
)
1002 wxCommandEvent
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, id
);
1003 commandEvent
.SetInt( id
);
1004 commandEvent
.SetEventObject( this );
1006 wxMenuBar
*bar
= GetMenuBar();
1009 wxMenuItem
*item
= bar
->FindItemForId(id
) ;
1010 if (item
&& item
->IsCheckable())
1012 bar
->Check(id
,!bar
->Checked(id
)) ;
1015 wxEvtHandler
* evtHandler
= GetEventHandler();
1017 evtHandler
->ProcessEvent(commandEvent
);
1020 void wxFrame::SetTitle( const wxString
&title
)
1022 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
1025 if (m_title
.IsNull()) m_title
= _T("");
1026 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
1029 void wxFrame::SetIcon( const wxIcon
&icon
)
1031 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
1034 if (!icon
.Ok()) return;
1036 if (!m_widget
->window
) return;
1038 wxMask
*mask
= icon
.GetMask();
1039 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1040 if (mask
) bm
= mask
->GetBitmap();
1042 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);