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
;
117 //-----------------------------------------------------------------------------
118 // "child_attached" of tool bar
119 //-----------------------------------------------------------------------------
121 static void gtk_toolbar_attached_callback( GtkWidget
*WXUNUSED(widget
), GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
123 if (!win
->m_hasVMT
) return;
125 win
->m_toolBarDetached
= FALSE
;
130 //-----------------------------------------------------------------------------
131 // "child_detached" of tool bar
132 //-----------------------------------------------------------------------------
134 static void gtk_toolbar_detached_callback( GtkWidget
*widget
, GtkWidget
*WXUNUSED(child
), wxFrame
*win
)
137 wxapp_install_idle_handler();
139 if (!win
->m_hasVMT
) return;
141 win
->m_toolBarDetached
= TRUE
;
145 //-----------------------------------------------------------------------------
147 //-----------------------------------------------------------------------------
149 static gint
gtk_frame_configure_callback( GtkWidget
*WXUNUSED(widget
), GdkEventConfigure
*event
, wxFrame
*win
)
152 wxapp_install_idle_handler();
154 if (!win
->m_hasVMT
) return FALSE
;
159 wxMoveEvent
mevent( wxPoint(win
->m_x
,win
->m_y
), win
->GetId() );
160 mevent
.SetEventObject( win
);
161 win
->GetEventHandler()->ProcessEvent( mevent
);
166 //-----------------------------------------------------------------------------
167 // "realize" from m_widget
168 //-----------------------------------------------------------------------------
170 /* we cannot MWM hints and icons before the widget has been realized,
171 so we do this directly after realization */
174 gtk_frame_realized_callback( GtkWidget
*widget
, wxFrame
*win
)
177 wxapp_install_idle_handler();
179 /* all this is for Motif Window Manager "hints" and is supposed to be
180 recognized by other WM as well. not tested. */
181 long decor
= (long) GDK_DECOR_BORDER
;
182 long func
= (long) GDK_FUNC_MOVE
;
184 if ((win
->GetWindowStyle() & wxCAPTION
) != 0)
185 decor
|= GDK_DECOR_TITLE
;
186 if ((win
->GetWindowStyle() & wxSYSTEM_MENU
) != 0)
188 decor
|= GDK_DECOR_MENU
;
189 func
|= GDK_FUNC_CLOSE
;
191 if ((win
->GetWindowStyle() & wxMINIMIZE_BOX
) != 0)
193 func
|= GDK_FUNC_MINIMIZE
;
194 decor
|= GDK_DECOR_MINIMIZE
;
196 if ((win
->GetWindowStyle() & wxMAXIMIZE_BOX
) != 0)
198 func
|= GDK_FUNC_MAXIMIZE
;
199 decor
|= GDK_DECOR_MAXIMIZE
;
201 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) != 0)
203 func
|= GDK_FUNC_RESIZE
;
204 decor
|= GDK_DECOR_RESIZEH
;
208 gdk_window_set_decorations( win
->m_widget
->window
, (GdkWMDecoration
)decor
);
209 gdk_window_set_functions( win
->m_widget
->window
, (GdkWMFunction
)func
);
211 /* GTK's shrinking/growing policy */
212 if ((win
->GetWindowStyle() & wxRESIZE_BORDER
) == 0)
213 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 0, 0, 1);
215 gtk_window_set_policy(GTK_WINDOW(win
->m_widget
), 1, 1, 1);
218 if (win
->m_icon
!= wxNullIcon
)
220 wxIcon
icon( win
->m_icon
);
221 win
->m_icon
= wxNullIcon
;
222 win
->SetIcon( icon
);
225 /* we set the focus to the child that accepts the focus. this
226 doesn't really have to be done in "realize" but why not? */
227 wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
230 wxWindow
*child
= node
->GetData();
231 if (child
->AcceptsFocus())
237 node
= node
->GetNext();
243 //-----------------------------------------------------------------------------
244 // InsertChild for wxFrame
245 //-----------------------------------------------------------------------------
247 /* Callback for wxFrame. This very strange beast has to be used because
248 * C++ has no virtual methods in a constructor. We have to emulate a
249 * virtual function here as wxWindows requires different ways to insert
250 * a child in container classes. */
252 static void wxInsertChildInFrame( wxFrame
* parent
, wxWindow
* child
)
254 if (!parent
->m_insertInClientArea
)
256 /* these are outside the client area */
257 wxFrame
* frame
= (wxFrame
*) parent
;
258 gtk_myfixed_put( GTK_MYFIXED(frame
->m_mainWidget
),
259 GTK_WIDGET(child
->m_widget
),
265 /* we connect to these events for recalculating the client area
266 space when the toolbar is floating */
267 if (wxIS_KIND_OF(child
,wxToolBar
))
269 wxToolBar
*toolBar
= (wxToolBar
*) child
;
270 if (toolBar
->GetWindowStyle() & wxTB_DOCKABLE
)
272 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_attached",
273 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback
), (gpointer
)parent
);
275 gtk_signal_connect( GTK_OBJECT(toolBar
->m_widget
), "child_detached",
276 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback
), (gpointer
)parent
);
282 /* these are inside the client area */
283 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
284 GTK_WIDGET(child
->m_widget
),
291 /* resize on OnInternalIdle */
292 parent
->UpdateSize();
295 //-----------------------------------------------------------------------------
297 //-----------------------------------------------------------------------------
299 BEGIN_EVENT_TABLE(wxFrame
, wxWindow
)
300 EVT_SIZE(wxFrame::OnSize
)
301 EVT_CLOSE(wxFrame::OnCloseWindow
)
302 EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight
)
305 IMPLEMENT_DYNAMIC_CLASS(wxFrame
,wxWindow
)
309 m_frameMenuBar
= (wxMenuBar
*) NULL
;
310 m_frameStatusBar
= (wxStatusBar
*) NULL
;
311 m_frameToolBar
= (wxToolBar
*) NULL
;
315 m_mainWidget
= (GtkWidget
*) NULL
;
316 m_menuBarDetached
= FALSE
;
317 m_toolBarDetached
= FALSE
;
318 m_insertCallback
= (wxInsertChildFunction
) NULL
;
319 m_insertInClientArea
= TRUE
;
322 wxFrame::wxFrame( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
323 const wxPoint
&pos
, const wxSize
&size
,
324 long style
, const wxString
&name
)
326 m_frameMenuBar
= (wxMenuBar
*) NULL
;
327 m_frameStatusBar
= (wxStatusBar
*) NULL
;
328 m_frameToolBar
= (wxToolBar
*) NULL
;
332 m_mainWidget
= (GtkWidget
*) NULL
;
333 m_menuBarDetached
= FALSE
;
334 m_toolBarDetached
= FALSE
;
335 m_insertCallback
= (wxInsertChildFunction
) NULL
;
336 m_insertInClientArea
= TRUE
;
337 Create( parent
, id
, title
, pos
, size
, style
, name
);
340 bool wxFrame::Create( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
341 const wxPoint
&pos
, const wxSize
&size
,
342 long style
, const wxString
&name
)
344 wxTopLevelWindows
.Append( this );
346 m_needParent
= FALSE
;
348 PreCreation( parent
, id
, pos
, size
, style
, name
);
352 m_insertCallback
= (wxInsertChildFunction
) wxInsertChildInFrame
;
354 GtkWindowType win_type
= GTK_WINDOW_TOPLEVEL
;
355 if (style
& wxSIMPLE_BORDER
) win_type
= GTK_WINDOW_POPUP
;
357 m_widget
= gtk_window_new( win_type
);
360 gtk_window_set_wmclass( GTK_WINDOW(m_widget
), name
.mb_str(), name
.mb_str() );
363 debug_focus_in( m_widget
, _T("wxFrame::m_widget"), name
);
366 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
367 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
369 gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event",
370 GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this );
372 /* m_mainWidget holds the toolbar, the menubar and the client area */
373 m_mainWidget
= gtk_myfixed_new();
374 gtk_widget_show( m_mainWidget
);
375 GTK_WIDGET_UNSET_FLAGS( m_mainWidget
, GTK_CAN_FOCUS
);
376 gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWidget
);
379 debug_focus_in( m_mainWidget
, _T("wxFrame::m_mainWidget"), name
);
382 /* m_wxwindow only represents the client area without toolbar and menubar */
383 m_wxwindow
= gtk_myfixed_new();
384 gtk_widget_show( m_wxwindow
);
385 gtk_container_add( GTK_CONTAINER(m_mainWidget
), m_wxwindow
);
388 debug_focus_in( m_wxwindow
, _T("wxFrame::m_wxwindow"), name
);
391 /* we donm't allow the frame to get the focus as otherwise
392 the frame will grabit at arbitrary fcous changes. */
393 GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
395 if (m_parent
) m_parent
->AddChild( this );
399 /* we cannot set MWM hints and icons before the widget has
400 been realized, so we do this directly after realization */
401 gtk_signal_connect( GTK_OBJECT(m_widget
), "realize",
402 GTK_SIGNAL_FUNC(gtk_frame_realized_callback
), (gpointer
) this );
404 /* the user resized the frame by dragging etc. */
405 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate",
406 GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this );
408 /* the only way to get the window size is to connect to this event */
409 gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event",
410 GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this );
417 m_isBeingDeleted
= TRUE
;
419 if (m_frameMenuBar
) delete m_frameMenuBar
;
420 m_frameMenuBar
= (wxMenuBar
*) NULL
;
422 if (m_frameStatusBar
) delete m_frameStatusBar
;
423 m_frameStatusBar
= (wxStatusBar
*) NULL
;
425 if (m_frameToolBar
) delete m_frameToolBar
;
426 m_frameToolBar
= (wxToolBar
*) NULL
;
428 wxTopLevelWindows
.DeleteObject( this );
430 if (wxTheApp
->GetTopWindow() == this)
431 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
433 if (wxTopLevelWindows
.Number() == 0)
434 wxTheApp
->ExitMainLoop();
437 bool wxFrame::Show( bool show
)
439 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
441 if (show
&& !m_sizeSet
)
443 /* by calling GtkOnSize here, we don't have to call
444 either after showing the frame, which would entail
445 much ugly flicker or from within the size_allocate
446 handler, because GTK 1.1.X forbids that. */
448 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
451 return wxWindow::Show( show
);
454 bool wxFrame::Destroy()
456 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
458 if (!wxPendingDelete
.Member(this)) wxPendingDelete
.Append(this);
463 void wxFrame::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
465 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
467 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
468 wxASSERT_MSG( (m_wxwindow
!= NULL
), _T("invalid frame") );
470 /* avoid recursions */
471 if (m_resizing
) return;
476 int old_width
= m_width
;
477 int old_height
= m_height
;
479 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
481 if (x
!= -1) m_x
= x
;
482 if (y
!= -1) m_y
= y
;
483 if (width
!= -1) m_width
= width
;
484 if (height
!= -1) m_height
= height
;
494 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
496 if (width
== -1) m_width
= 80;
499 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
501 if (height
== -1) m_height
= 26;
504 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
505 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
506 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
507 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
509 if ((m_x
!= -1) || (m_y
!= -1))
511 if ((m_x
!= old_x
) || (m_y
!= old_y
))
513 gtk_widget_set_uposition( m_widget
, m_x
, m_y
);
517 if ((m_width
!= old_width
) || (m_height
!= old_height
))
519 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
520 done either directly before the frame is shown or in idle time
521 so that different calls to SetSize() don't lead to flicker. */
528 void wxFrame::Centre( int direction
)
530 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
535 if ((direction
& wxHORIZONTAL
) == wxHORIZONTAL
) x
= (gdk_screen_width () - m_width
) / 2;
536 if ((direction
& wxVERTICAL
) == wxVERTICAL
) y
= (gdk_screen_height () - m_height
) / 2;
541 void wxFrame::DoGetClientSize( int *width
, int *height
) const
543 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
545 wxWindow::DoGetClientSize( width
, height
);
551 if (!m_menuBarDetached
)
552 (*height
) -= wxMENU_HEIGHT
;
554 (*height
) -= wxPLACE_HOLDER
;
558 if (m_frameStatusBar
) (*height
) -= wxSTATUS_HEIGHT
;
563 if (!m_toolBarDetached
)
566 m_frameToolBar
->GetSize( (int *) NULL
, &y
);
570 (*height
) -= wxPLACE_HOLDER
;
574 (*height
) -= m_miniEdge
*2 + m_miniTitle
;
578 (*width
) -= m_miniEdge
*2;
582 void wxFrame::DoSetClientSize( int width
, int height
)
584 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
589 if (!m_menuBarDetached
)
590 height
+= wxMENU_HEIGHT
;
592 height
+= wxPLACE_HOLDER
;
596 if (m_frameStatusBar
) height
+= wxSTATUS_HEIGHT
;
601 if (!m_toolBarDetached
)
604 m_frameToolBar
->GetSize( (int *) NULL
, &y
);
608 height
+= wxPLACE_HOLDER
;
611 wxWindow::DoSetClientSize( width
+ m_miniEdge
*2, height
+ m_miniEdge
*2 + m_miniTitle
);
614 void wxFrame::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
), int width
, int height
)
616 // due to a bug in gtk, x,y are always 0
620 /* avoid recursions */
621 if (m_resizing
) return;
624 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
625 wxASSERT_MSG( (m_wxwindow
!= NULL
), _T("invalid frame") );
630 /* space occupied by m_frameToolBar and m_frameMenuBar */
631 int client_area_y_offset
= 0;
633 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
634 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
635 set in wxFrame::Create so it is used to check what kind of frame we
636 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
637 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
638 importantly) m_mainWidget */
642 /* check if size is in legal range */
643 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
644 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
645 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
646 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
648 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
649 * menubar, the toolbar and the client area, which is represented by
651 * this hurts in the eye, but I don't want to call SetSize()
652 * because I don't want to call any non-native functions here. */
657 int yy
= m_miniEdge
+ m_miniTitle
;
658 int ww
= m_width
- 2*m_miniEdge
;
659 int hh
= wxMENU_HEIGHT
;
660 if (m_menuBarDetached
) hh
= wxPLACE_HOLDER
;
661 m_frameMenuBar
->m_x
= xx
;
662 m_frameMenuBar
->m_y
= yy
;
663 m_frameMenuBar
->m_width
= ww
;
664 m_frameMenuBar
->m_height
= hh
;
665 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget
),
666 m_frameMenuBar
->m_widget
,
668 client_area_y_offset
+= hh
;
674 int yy
= m_miniEdge
+ m_miniTitle
;
677 if (!m_menuBarDetached
)
680 yy
+= wxPLACE_HOLDER
;
682 int ww
= m_width
- 2*m_miniEdge
;
683 int hh
= m_frameToolBar
->m_height
;
684 if (m_toolBarDetached
) hh
= wxPLACE_HOLDER
;
685 m_frameToolBar
->m_x
= xx
;
686 m_frameToolBar
->m_y
= yy
;
687 /* m_frameToolBar->m_height = hh; don't change the toolbar's height */
688 m_frameToolBar
->m_width
= ww
;
689 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget
),
690 m_frameToolBar
->m_widget
,
692 client_area_y_offset
+= hh
;
695 int client_x
= m_miniEdge
;
696 int client_y
= client_area_y_offset
+ m_miniEdge
+ m_miniTitle
;
697 int client_w
= m_width
- 2*m_miniEdge
;
698 int client_h
= m_height
- client_area_y_offset
- 2*m_miniEdge
- m_miniTitle
;
699 gtk_myfixed_set_size( GTK_MYFIXED(m_mainWidget
),
701 client_x
, client_y
, client_w
, client_h
);
705 /* if there is no m_mainWidget between m_widget and m_wxwindow there
706 is no need to set the size or position of m_wxwindow. */
709 if (m_frameStatusBar
)
711 int xx
= 0 + m_miniEdge
;
712 int yy
= m_height
- wxSTATUS_HEIGHT
- m_miniEdge
- client_area_y_offset
;
713 int ww
= m_width
- 2*m_miniEdge
;
714 int hh
= wxSTATUS_HEIGHT
;
715 m_frameStatusBar
->m_x
= xx
;
716 m_frameStatusBar
->m_y
= yy
;
717 m_frameStatusBar
->m_width
= ww
;
718 m_frameStatusBar
->m_height
= hh
;
719 gtk_myfixed_set_size( GTK_MYFIXED(m_wxwindow
),
720 m_frameStatusBar
->m_widget
,
724 /* we actually set the size of a frame here and no-where else */
725 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
729 /* send size event to frame */
730 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
731 event
.SetEventObject( this );
732 GetEventHandler()->ProcessEvent( event
);
734 /* send size event to status bar */
735 if (m_frameStatusBar
)
737 wxSizeEvent
event2( wxSize(m_frameStatusBar
->m_width
,m_frameStatusBar
->m_height
), m_frameStatusBar
->GetId() );
738 event2
.SetEventObject( m_frameStatusBar
);
739 m_frameStatusBar
->GetEventHandler()->ProcessEvent( event2
);
745 void wxFrame::OnInternalIdle()
747 if (!m_sizeSet
&& GTK_WIDGET_REALIZED(m_wxwindow
))
748 GtkOnSize( m_x
, m_y
, m_width
, m_height
);
752 if (m_frameMenuBar
) m_frameMenuBar
->OnInternalIdle();
753 if (m_frameToolBar
) m_frameToolBar
->OnInternalIdle();
754 if (m_frameStatusBar
) m_frameStatusBar
->OnInternalIdle();
757 void wxFrame::OnCloseWindow( wxCloseEvent
& WXUNUSED(event
) )
762 void wxFrame::OnSize( wxSizeEvent
&WXUNUSED(event
) )
764 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
772 /* do we have exactly one child? */
773 wxWindow
*child
= (wxWindow
*)NULL
;
774 for ( wxNode
*node
= GetChildren().First(); node
; node
= node
->Next() )
776 wxWindow
*win
= (wxWindow
*)node
->Data();
777 if ( !wxIS_KIND_OF(win
,wxFrame
) && !wxIS_KIND_OF(win
,wxDialog
) )
781 /* it's the second one: do nothing */
789 /* no children at all? */
792 /* yes: set it's size to fill all the frame */
793 int client_x
, client_y
;
794 DoGetClientSize( &client_x
, &client_y
);
795 child
->SetSize( 1, 1, client_x
-2, client_y
-2 );
800 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
802 menu
->SetInvokingWindow( win
);
804 #if (GTK_MINOR_VERSION > 0)
805 /* support for native hot keys */
806 gtk_accel_group_attach( menu
->m_accel
, GTK_OBJECT(win
->m_widget
));
809 wxNode
*node
= menu
->GetItems().First();
812 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
813 if (menuitem
->IsSubMenu())
814 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
819 void wxFrame::SetMenuBar( wxMenuBar
*menuBar
)
821 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
822 wxASSERT_MSG( (m_wxwindow
!= NULL
), _T("invalid frame") );
824 m_frameMenuBar
= menuBar
;
828 #if (GTK_MINOR_VERSION > 0) && (GTK_MICRO_VERSION > 0)
829 /* support for native key accelerators indicated by underscroes */
830 gtk_accel_group_attach( m_frameMenuBar
->m_accel
, GTK_OBJECT(m_widget
));
833 wxNode
*node
= m_frameMenuBar
->GetMenus().First();
836 wxMenu
*menu
= (wxMenu
*)node
->Data();
837 SetInvokingWindow( menu
, this );
841 if (m_frameMenuBar
->GetParent() != this)
843 m_frameMenuBar
->SetParent(this);
844 gtk_myfixed_put( GTK_MYFIXED(m_mainWidget
),
845 m_frameMenuBar
->m_widget
,
848 m_frameMenuBar
->m_width
,
849 m_frameMenuBar
->m_height
);
851 if (menuBar
->GetWindowStyle() & wxMB_DOCKABLE
)
853 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_attached",
854 GTK_SIGNAL_FUNC(gtk_menu_attached_callback
), (gpointer
)this );
856 gtk_signal_connect( GTK_OBJECT(menuBar
->m_widget
), "child_detached",
857 GTK_SIGNAL_FUNC(gtk_menu_detached_callback
), (gpointer
)this );
862 /* resize window in OnInternalIdle */
866 wxMenuBar
*wxFrame::GetMenuBar() const
868 return m_frameMenuBar
;
871 void wxFrame::OnMenuHighlight(wxMenuEvent
& event
)
875 // if no help string found, we will clear the status bar text
878 int menuId
= event
.GetMenuId();
881 wxMenuBar
*menuBar
= GetMenuBar();
884 helpString
= menuBar
->GetHelpString(menuId
);
888 SetStatusText(helpString
);
892 wxToolBar
* wxFrame::CreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
894 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
896 wxCHECK_MSG( m_frameToolBar
== NULL
, FALSE
, _T("recreating toolbar in wxFrame") );
898 m_insertInClientArea
= FALSE
;
900 m_frameToolBar
= OnCreateToolBar( style
, id
, name
);
902 if (m_frameToolBar
) GetChildren().DeleteObject( m_frameToolBar
);
904 m_insertInClientArea
= TRUE
;
908 return m_frameToolBar
;
911 wxToolBar
* wxFrame::OnCreateToolBar( long style
, wxWindowID id
, const wxString
& name
)
913 return new wxToolBar( this, id
, wxDefaultPosition
, wxDefaultSize
, style
, name
);
916 wxToolBar
*wxFrame::GetToolBar() const
918 return m_frameToolBar
;
921 wxStatusBar
* wxFrame::CreateStatusBar( int number
, long style
, wxWindowID id
, const wxString
& name
)
923 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
925 wxCHECK_MSG( m_frameStatusBar
== NULL
, FALSE
, _T("recreating status bar in wxFrame") );
927 m_frameStatusBar
= OnCreateStatusBar( number
, style
, id
, name
);
931 return m_frameStatusBar
;
934 wxStatusBar
*wxFrame::OnCreateStatusBar( int number
, long style
, wxWindowID id
, const wxString
& name
)
936 wxStatusBar
*statusBar
= (wxStatusBar
*) NULL
;
938 statusBar
= new wxStatusBar(this, id
, wxPoint(0, 0), wxSize(100, 20), style
, name
);
940 // Set the height according to the font and the border size
941 wxClientDC
dc(statusBar
);
942 dc
.SetFont( statusBar
->GetFont() );
945 dc
.GetTextExtent( "X", &x
, &y
);
947 int height
= (int)( (y
* 1.1) + 2* statusBar
->GetBorderY());
949 statusBar
->SetSize( -1, -1, 100, height
);
951 statusBar
->SetFieldsCount( number
);
955 void wxFrame::Command( int id
)
957 wxCommandEvent
commandEvent(wxEVT_COMMAND_MENU_SELECTED
, id
);
958 commandEvent
.SetInt( id
);
959 commandEvent
.SetEventObject( this );
961 wxMenuBar
*bar
= GetMenuBar();
964 wxMenuItem
*item
= bar
->FindItemForId(id
) ;
965 if (item
&& item
->IsCheckable())
967 bar
->Check(id
,!bar
->Checked(id
)) ;
970 wxEvtHandler
* evtHandler
= GetEventHandler();
972 evtHandler
->ProcessEvent(commandEvent
);
975 void wxFrame::SetStatusText(const wxString
& text
, int number
)
977 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
979 wxCHECK_RET( m_frameStatusBar
!= NULL
, _T("no statusbar to set text for") );
981 m_frameStatusBar
->SetStatusText(text
, number
);
984 void wxFrame::SetStatusWidths(int n
, const int widths_field
[] )
986 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
988 wxCHECK_RET( m_frameStatusBar
!= NULL
, _T("no statusbar to set widths for") );
990 m_frameStatusBar
->SetStatusWidths(n
, widths_field
);
993 wxStatusBar
*wxFrame::GetStatusBar() const
995 return m_frameStatusBar
;
998 void wxFrame::SetTitle( const wxString
&title
)
1000 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
1003 if (m_title
.IsNull()) m_title
= _T("");
1004 gtk_window_set_title( GTK_WINDOW(m_widget
), title
.mbc_str() );
1007 void wxFrame::SetIcon( const wxIcon
&icon
)
1009 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid frame") );
1012 if (!icon
.Ok()) return;
1014 if (!m_widget
->window
) return;
1016 wxMask
*mask
= icon
.GetMask();
1017 GdkBitmap
*bm
= (GdkBitmap
*) NULL
;
1018 if (mask
) bm
= mask
->GetBitmap();
1020 gdk_window_set_icon( m_widget
->window
, (GdkWindow
*) NULL
, icon
.GetPixmap(), bm
);