1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   7 // Copyright:   (c) 1998 Robert Roebling, Julian Smart and Markus Holzem 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  12 #pragma implementation "frame.h" 
  16 #include "wx/dialog.h" 
  17 #include "wx/control.h" 
  20 #include "wx/toolbar.h" 
  21 #include "wx/statusbr.h" 
  23 #include "wx/dcclient.h" 
  24 #include "wx/gtk/win_gtk.h" 
  26 //----------------------------------------------------------------------------- 
  28 //----------------------------------------------------------------------------- 
  30 const int wxMENU_HEIGHT    
= 28; 
  31 const int wxSTATUS_HEIGHT  
= 25; 
  33 //----------------------------------------------------------------------------- 
  35 //----------------------------------------------------------------------------- 
  37 extern wxList wxTopLevelWindows
; 
  38 extern wxList wxPendingDelete
; 
  40 //----------------------------------------------------------------------------- 
  42 //----------------------------------------------------------------------------- 
  44 static void gtk_frame_size_callback( GtkWidget 
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxFrame 
*win 
) 
  46   if (!win
->HasVMT()) return; 
  49   printf( "OnFrameResize from " ); 
  50   if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
  51     printf( win->GetClassInfo()->GetClassName() ); 
  55   win
->GtkOnSize( alloc
->x
, alloc
->y
, alloc
->width
, alloc
->height 
); 
  58 //----------------------------------------------------------------------------- 
  60 //----------------------------------------------------------------------------- 
  62 static gint 
gtk_frame_delete_callback( GtkWidget 
*WXUNUSED(widget
), GdkEvent 
*WXUNUSED(event
), wxFrame 
*win 
) 
  65   printf( "OnDelete from " ); 
  66   if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
  67     printf( win->GetClassInfo()->GetClassName() ); 
  76 //----------------------------------------------------------------------------- 
  78 //----------------------------------------------------------------------------- 
  80 static gint 
gtk_frame_configure_callback( GtkWidget 
*WXUNUSED(widget
), GdkEventConfigure 
*event
, wxFrame 
*win 
) 
  82   if (!win
->HasVMT()) return FALSE
; 
  90 //----------------------------------------------------------------------------- 
  92 //----------------------------------------------------------------------------- 
  94 BEGIN_EVENT_TABLE(wxFrame
, wxWindow
) 
  95   EVT_SIZE(wxFrame::OnSize
) 
  96   EVT_CLOSE(wxFrame::OnCloseWindow
) 
  97   EVT_IDLE(wxFrame::OnIdle
) 
 100 IMPLEMENT_DYNAMIC_CLASS(wxFrame
,wxWindow
) 
 104   m_frameMenuBar 
= (wxMenuBar 
*) NULL
; 
 105   m_frameStatusBar 
= (wxStatusBar 
*) NULL
; 
 106   m_frameToolBar 
= (wxToolBar 
*) NULL
; 
 108   m_addPrivateChild 
= FALSE
; 
 109   m_wxwindow 
= (GtkWidget 
*) NULL
; 
 110   m_mainWindow 
= (GtkWidget 
*) NULL
; 
 111   wxTopLevelWindows
.Insert( this ); 
 114 wxFrame::wxFrame( wxWindow 
*parent
, wxWindowID id
, const wxString 
&title
, 
 115       const wxPoint 
&pos
, const wxSize 
&size
, 
 116       long style
, const wxString 
&name 
) 
 118   m_frameMenuBar 
= (wxMenuBar 
*) NULL
; 
 119   m_frameStatusBar 
= (wxStatusBar 
*) NULL
; 
 120   m_frameToolBar 
= (wxToolBar 
*) NULL
; 
 122   m_addPrivateChild 
= FALSE
; 
 123   m_wxwindow 
= (GtkWidget 
*) NULL
; 
 124   m_mainWindow 
= (GtkWidget 
*) NULL
; 
 125   Create( parent
, id
, title
, pos
, size
, style
, name 
); 
 126   wxTopLevelWindows
.Insert( this ); 
 129 bool wxFrame::Create( wxWindow 
*parent
, wxWindowID id
, const wxString 
&title
, 
 130       const wxPoint 
&pos
, const wxSize 
&size
, 
 131       long style
, const wxString 
&name 
) 
 133   m_needParent 
= FALSE
; 
 135   PreCreation( parent
, id
, pos
, size
, style
, name 
); 
 139   m_widget 
= gtk_window_new( GTK_WINDOW_TOPLEVEL 
); 
 140   if ((size
.x 
!= -1) && (size
.y 
!= -1)) 
 141     gtk_widget_set_usize( m_widget
, m_width
, m_height 
); 
 142   if ((pos
.x 
!= -1) && (pos
.y 
!= -1)) 
 143     gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 145   gtk_window_set_title( GTK_WINDOW(m_widget
), title 
); 
 146   GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
 148   gtk_widget_set( m_widget
, "GtkWindow::allow_shrink", TRUE
, NULL
); 
 150   gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event", 
 151     GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this ); 
 153   m_mainWindow 
= gtk_myfixed_new(); 
 154   gtk_widget_show( m_mainWindow 
); 
 155   GTK_WIDGET_UNSET_FLAGS( m_mainWindow
, GTK_CAN_FOCUS 
); 
 157   gtk_container_add( GTK_CONTAINER(m_widget
), m_mainWindow 
); 
 158   gtk_widget_set_uposition( m_mainWindow
, 0, 0 ); 
 160   m_wxwindow 
= gtk_myfixed_new(); 
 161   gtk_widget_show( m_wxwindow 
); 
 162   GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
 164   gtk_container_add( GTK_CONTAINER(m_mainWindow
), m_wxwindow 
); 
 166   gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate", 
 167     GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this ); 
 169   gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event", 
 170     GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this ); 
 174   gtk_widget_realize( m_mainWindow 
); 
 181   if (m_frameMenuBar
) delete m_frameMenuBar
; 
 182   if (m_frameStatusBar
) delete m_frameStatusBar
; 
 183   if (m_frameToolBar
) delete m_frameToolBar
; 
 185 //  if (m_mainWindow) gtk_widget_destroy( m_mainWindow ); 
 187   wxTopLevelWindows
.DeleteObject( this ); 
 188   if (wxTopLevelWindows
.Number() == 0) wxTheApp
->ExitMainLoop(); 
 191 bool wxFrame::Show( bool show 
) 
 195     wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
 197     ProcessEvent( event 
); 
 199   return wxWindow::Show( show 
); 
 202 void wxFrame::Enable( bool enable 
) 
 204   wxWindow::Enable( enable 
); 
 205   gtk_widget_set_sensitive( m_mainWindow
, enable 
); 
 208 void wxFrame::OnCloseWindow( wxCloseEvent 
&event 
) 
 210     if ( GetEventHandler()->OnClose() || event
.GetForce()) 
 216 bool wxFrame::Destroy() 
 218   if (!wxPendingDelete
.Member(this)) 
 219     wxPendingDelete
.Append(this); 
 224 void wxFrame::ImplementSetPosition(void) 
 226   if ((m_x 
!= -1) || (m_y 
!= -1)) 
 227      gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 230 void wxFrame::Centre( int direction 
) 
 232   if (direction 
& wxHORIZONTAL 
== wxHORIZONTAL
) m_x 
= (gdk_screen_width () - m_width
) / 2; 
 233   if (direction 
& wxVERTICAL 
== wxVERTICAL
) m_y 
= (gdk_screen_height () - m_height
) / 2; 
 234   ImplementSetPosition(); 
 237 void wxFrame::GetClientSize( int *width
, int *height 
) const 
 239   wxWindow::GetClientSize( width
, height 
); 
 242     if (m_frameMenuBar
) (*height
) -= wxMENU_HEIGHT
; 
 243     if (m_frameStatusBar
) (*height
) -= wxSTATUS_HEIGHT
; 
 247       m_frameToolBar
->GetSize( (int *) NULL
, &y 
); 
 253 void wxFrame::SetClientSize( int const width
, int const height 
) 
 256   if (m_frameMenuBar
) h 
+= wxMENU_HEIGHT
; 
 257   if (m_frameStatusBar
) h 
+= wxSTATUS_HEIGHT
; 
 261     m_frameToolBar
->GetSize( (int *) NULL
, &y 
); 
 264   wxWindow::SetClientSize( width
, h 
); 
 267 void wxFrame::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
), int width
, int height 
) 
 269   // due to a bug in gtk, x,y are always 0 
 273   if ((m_height 
== height
) && (m_width 
== width
) && 
 275   if (!m_mainWindow
) return; 
 276   if (!m_wxwindow
) return; 
 280   if ((m_minWidth 
!= -1) && (m_width 
< m_minWidth
)) m_width 
= m_minWidth
; 
 281   if ((m_minHeight 
!= -1) && (m_height 
< m_minHeight
)) m_height 
= m_minHeight
; 
 282   if ((m_maxWidth 
!= -1) && (m_width 
> m_maxWidth
)) m_width 
= m_minWidth
; 
 283   if ((m_maxHeight 
!= -1) && (m_height 
> m_maxHeight
)) m_height 
= m_minHeight
; 
 285   gtk_widget_set_usize( m_widget
, width
, height 
); 
 289   int main_height 
= height
; 
 290   int main_width 
= width
; 
 292   // This emulates Windows behaviour: 
 293   // The menu bar is part of the main window, but the status bar 
 294   // is on the implementation side in the client area. The 
 295   // function GetClientSize returns the size of the client area 
 296   // minus the status bar height. Under wxGTK, the main window 
 297   // is represented by m_mainWindow. The menubar is inserted 
 298   // into m_mainWindow whereas the statusbar is insertes into 
 299   // m_wxwindow just like any other window. 
 302 //  gtk_widget_set_usize( m_mainWindow, width, height ); 
 306     main_y 
= wxMENU_HEIGHT
; 
 307     main_height 
-= wxMENU_HEIGHT
; 
 310   int toolbar_height 
= 0; 
 311   if (m_frameToolBar
) m_frameToolBar
->GetSize( (int *) NULL
, &toolbar_height 
); 
 313   main_y 
+= toolbar_height
; 
 314   main_height 
-= toolbar_height
; 
 316   gtk_myfixed_move( GTK_MYFIXED(m_mainWindow
), m_wxwindow
, main_x
, main_y 
); 
 317   gtk_widget_set_usize( m_wxwindow
, main_width
, main_height 
); 
 321     gtk_myfixed_move( GTK_MYFIXED(m_mainWindow
), m_frameMenuBar
->m_widget
, 1, 1 ); 
 322     gtk_widget_set_usize( m_frameMenuBar
->m_widget
, width
-2, wxMENU_HEIGHT
-2 ); 
 327     gtk_myfixed_move( GTK_MYFIXED(m_mainWindow
), m_frameToolBar
->m_widget
, 1, wxMENU_HEIGHT 
); 
 328     gtk_widget_set_usize( m_frameToolBar
->m_widget
, width
-2, toolbar_height 
); 
 331   if (m_frameStatusBar
) 
 333     m_frameStatusBar
->SetSize( 0, main_height
-wxSTATUS_HEIGHT
, width
, wxSTATUS_HEIGHT 
); 
 338   wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
 339   event
.SetEventObject( this ); 
 340   ProcessEvent( event 
); 
 343 void wxFrame::OnSize( wxSizeEvent 
&WXUNUSED(event
) ) 
 345   if ( GetAutoLayout() ) 
 348     // no child: go out ! 
 349     if (!GetChildren()->First()) 
 352     // do we have exactly one child? 
 353     wxWindow 
*child 
= (wxWindow 
*) NULL
; 
 354     for(wxNode 
*node 
= GetChildren()->First(); node
; node 
= node
->Next()) 
 356       wxWindow 
*win 
= (wxWindow 
*)node
->Data(); 
 357       if (!IS_KIND_OF(win
,wxFrame
) && !IS_KIND_OF(win
,wxDialog
) 
 358 #if 0  // not in m_children anyway 
 359           && (win 
!= m_frameMenuBar
) && 
 360              (win 
!= m_frameToolBar
) && 
 361              (win 
!= m_frameStatusBar
) 
 365         if ( child 
)  // it's the second one: do nothing 
 372     // yes: set it's size to fill all the frame 
 373     int client_x
, client_y
; 
 374     GetClientSize(&client_x
, &client_y
); 
 375     child
->SetSize( 1, 1, client_x
-2, client_y
); 
 379 void wxFrame::AddChild( wxWindow 
*child 
) 
 381   // wxFrame and wxDialog as children aren't placed into the parents 
 383   if (IS_KIND_OF(child
,wxMDIChildFrame
)) wxFAIL_MSG( "wxFrame::AddChild error.\n" ); 
 385   if ( IS_KIND_OF(child
,wxFrame
) || IS_KIND_OF(child
,wxDialog
)) 
 387     m_children
.Append( child 
); 
 389     if ((child
->m_x 
!= -1) && (child
->m_y 
!= -1)) 
 390       gtk_widget_set_uposition( child
->m_widget
, child
->m_x
, child
->m_y 
); 
 395   if (m_addPrivateChild
) 
 397     gtk_myfixed_put( GTK_MYFIXED(m_mainWindow
), child
->m_widget
, child
->m_x
, child
->m_y 
); 
 399     gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height 
); 
 403     m_children
.Append( child 
); 
 406       gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), child
->m_widget
, child
->m_x
, child
->m_y 
); 
 408     gtk_widget_set_usize( child
->m_widget
, child
->m_width
, child
->m_height 
); 
 412 static void SetInvokingWindow( wxMenu 
*menu
, wxWindow 
*win 
) 
 414   menu
->SetInvokingWindow( win 
); 
 415   wxNode 
*node 
= menu
->m_items
.First(); 
 418     wxMenuItem 
*menuitem 
= (wxMenuItem
*)node
->Data(); 
 419     if (menuitem
->IsSubMenu()) 
 420       SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
 425 void wxFrame::SetMenuBar( wxMenuBar 
*menuBar 
) 
 427   m_frameMenuBar 
= menuBar
; 
 431     wxNode 
*node 
= m_frameMenuBar
->m_menus
.First(); 
 434       wxMenu 
*menu 
= (wxMenu
*)node
->Data(); 
 435       SetInvokingWindow( menu
, this ); 
 439     if (m_frameMenuBar
->m_parent 
!= this) 
 441       m_frameMenuBar
->m_parent 
= this; 
 442       gtk_myfixed_put( GTK_MYFIXED(m_mainWindow
), 
 443         m_frameMenuBar
->m_widget
, m_frameMenuBar
->m_x
, m_frameMenuBar
->m_y 
); 
 448 wxMenuBar 
*wxFrame::GetMenuBar(void) const 
 450   return m_frameMenuBar
; 
 453 wxToolBar
* wxFrame::CreateToolBar(long style
, wxWindowID id
, const wxString
& name
) 
 455   wxCHECK_MSG( m_frameToolBar 
== NULL
, FALSE
, "recreating toolbar in wxFrame" ); 
 457   m_addPrivateChild 
= TRUE
; 
 458   m_frameToolBar 
= OnCreateToolBar( style
, id
, name 
); 
 459   m_addPrivateChild 
= FALSE
; 
 461   return m_frameToolBar
; 
 464 wxToolBar
* wxFrame::OnCreateToolBar( long style
, wxWindowID id
, const wxString
& name 
) 
 466   return new wxToolBar( this, id
, wxDefaultPosition
, wxDefaultSize
, style
, name 
); 
 469 wxToolBar 
*wxFrame::GetToolBar(void) const  
 471   return m_frameToolBar
;  
 474 wxStatusBar
* wxFrame::CreateStatusBar( int number
, long style
, wxWindowID id
, const wxString
& name 
) 
 476   wxCHECK_MSG( m_frameStatusBar 
== NULL
, FALSE
, "recreating status bar in wxFrame" ); 
 478   m_frameStatusBar 
= OnCreateStatusBar( number
, style
, id
, name 
); 
 480   return m_frameStatusBar
; 
 483 wxStatusBar 
*wxFrame::OnCreateStatusBar( int number
, long style
, wxWindowID id
, const wxString
& name 
) 
 485   wxStatusBar 
*statusBar 
= (wxStatusBar 
*) NULL
; 
 487   statusBar 
= new wxStatusBar(this, id
, wxPoint(0, 0), wxSize(100, 20), style
, name
); 
 489   // Set the height according to the font and the border size 
 490   wxClientDC 
dc(statusBar
); 
 491   dc
.SetFont( *statusBar
->GetFont() ); 
 494   dc
.GetTextExtent( "X", &x
, &y 
); 
 496   int height 
= (int)( (y  
* 1.1) + 2* statusBar
->GetBorderY()); 
 498   statusBar
->SetSize( -1, -1, 100, height 
); 
 500   statusBar
->SetFieldsCount( number 
); 
 504 void wxFrame::SetStatusText(const wxString
& text
, int number
) 
 506   wxCHECK_RET( m_frameStatusBar 
!= NULL
, "no statusbar to set text for" ); 
 508   m_frameStatusBar
->SetStatusText(text
, number
); 
 511 void wxFrame::SetStatusWidths(int n
, const int widths_field
[] ) 
 513   wxCHECK_RET( m_frameStatusBar 
!= NULL
, "no statusbar to set widths for" ); 
 515   m_frameStatusBar
->SetStatusWidths(n
, widths_field
); 
 518 wxStatusBar 
*wxFrame::GetStatusBar(void) const 
 520   return m_frameStatusBar
; 
 523 void wxFrame::SetTitle( const wxString 
&title 
) 
 526   if (m_title
.IsNull()) m_title 
= ""; 
 527   gtk_window_set_title( GTK_WINDOW(m_widget
), title 
); 
 530 void wxFrame::SetIcon( const wxIcon 
&icon 
) 
 533   if (!icon
.Ok()) return; 
 535   wxMask 
*mask 
= icon
.GetMask(); 
 536   GdkBitmap 
*bm 
= (GdkBitmap 
*) NULL
; 
 537   if (mask
) bm 
= mask
->GetBitmap(); 
 539   gdk_window_set_icon( m_widget
->window
, (GdkWindow 
*) NULL
, icon
.GetPixmap(), bm 
);