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" 
  22 #include "wx/gtk/win_gtk.h" 
  24 //----------------------------------------------------------------------------- 
  26 //----------------------------------------------------------------------------- 
  28 const int wxMENU_HEIGHT    
= 27; 
  29 const int wxSTATUS_HEIGHT  
= 25; 
  31 //----------------------------------------------------------------------------- 
  33 //----------------------------------------------------------------------------- 
  35 extern wxList wxTopLevelWindows
; 
  36 extern wxList wxPendingDelete
; 
  38 //----------------------------------------------------------------------------- 
  40 //----------------------------------------------------------------------------- 
  42 static void gtk_frame_size_callback( GtkWidget 
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxFrame 
*win 
) 
  44     if (!win
->HasVMT()) return; 
  47     printf( "OnFrameResize from " ); 
  48     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
  49         printf( win->GetClassInfo()->GetClassName() ); 
  53    if ((win
->m_width 
!= alloc
->width
) || (win
->m_height 
!= alloc
->height
)) 
  55        win
->m_sizeSet 
= FALSE
; 
  56        win
->m_width 
= alloc
->width
; 
  57        win
->m_height 
= alloc
->height
; 
  61 //----------------------------------------------------------------------------- 
  63 //----------------------------------------------------------------------------- 
  65 static gint 
gtk_frame_delete_callback( GtkWidget 
*WXUNUSED(widget
), GdkEvent 
*WXUNUSED(event
), wxFrame 
*win 
) 
  68     printf( "OnDelete from " ); 
  69     if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) 
  70         printf( win->GetClassInfo()->GetClassName() ); 
  79 //----------------------------------------------------------------------------- 
  81 //----------------------------------------------------------------------------- 
  83 static gint 
gtk_frame_configure_callback( GtkWidget 
*WXUNUSED(widget
), GdkEventConfigure 
*event
, wxFrame 
*win 
) 
  85     if (!win
->HasVMT()) return FALSE
; 
  93 //----------------------------------------------------------------------------- 
  95 //----------------------------------------------------------------------------- 
  97 BEGIN_EVENT_TABLE(wxFrame
, wxWindow
) 
  98     EVT_SIZE(wxFrame::OnSize
) 
  99     EVT_CLOSE(wxFrame::OnCloseWindow
) 
 100     EVT_IDLE(wxFrame::OnIdle
) 
 103 IMPLEMENT_DYNAMIC_CLASS(wxFrame
,wxWindow
) 
 107     m_frameMenuBar 
= (wxMenuBar 
*) NULL
; 
 108     m_frameStatusBar 
= (wxStatusBar 
*) NULL
; 
 109     m_frameToolBar 
= (wxToolBar 
*) NULL
; 
 115 wxFrame::wxFrame( wxWindow 
*parent
, wxWindowID id
, const wxString 
&title
, 
 116       const wxPoint 
&pos
, const wxSize 
&size
, 
 117       long style
, const wxString 
&name 
) 
 119     m_frameMenuBar 
= (wxMenuBar 
*) NULL
; 
 120     m_frameStatusBar 
= (wxStatusBar 
*) NULL
; 
 121     m_frameToolBar 
= (wxToolBar 
*) NULL
; 
 125     Create( parent
, id
, title
, pos
, size
, style
, name 
); 
 128 bool wxFrame::Create( wxWindow 
*parent
, wxWindowID id
, const wxString 
&title
, 
 129       const wxPoint 
&pos
, const wxSize 
&size
, 
 130       long style
, const wxString 
&name 
) 
 132     wxTopLevelWindows
.Append( this ); 
 134     m_needParent 
= FALSE
; 
 136     PreCreation( parent
, id
, pos
, size
, style
, name 
); 
 140     GtkWindowType win_type 
= GTK_WINDOW_TOPLEVEL
; 
 141     if (style 
& wxSIMPLE_BORDER
) win_type 
= GTK_WINDOW_POPUP
; 
 143     m_widget 
= gtk_window_new( win_type 
); 
 146         debug_focus_in( m_widget
, "wxFrame::m_widget", name 
); 
 149     if ((size
.x 
!= -1) && (size
.y 
!= -1)) 
 150         gtk_widget_set_usize( m_widget
, m_width
, m_height 
); 
 151     if ((pos
.x 
!= -1) && (pos
.y 
!= -1)) 
 152         gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 154     gtk_window_set_title( GTK_WINDOW(m_widget
), title 
); 
 155     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
 157     gtk_widget_set( m_widget
, "GtkWindow::allow_shrink", TRUE
, NULL 
); 
 159     gtk_signal_connect( GTK_OBJECT(m_widget
), "delete_event", 
 160         GTK_SIGNAL_FUNC(gtk_frame_delete_callback
), (gpointer
)this ); 
 162     m_wxwindow 
= gtk_myfixed_new(); 
 163     gtk_widget_show( m_wxwindow 
); 
 164     GTK_WIDGET_UNSET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
 167         debug_focus_in( m_wxwindow
, "wxFrame::m_wxwindow", name 
); 
 170     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
 172     gtk_signal_connect( GTK_OBJECT(m_widget
), "size_allocate", 
 173         GTK_SIGNAL_FUNC(gtk_frame_size_callback
), (gpointer
)this ); 
 175     gtk_signal_connect( GTK_OBJECT(m_widget
), "configure_event", 
 176         GTK_SIGNAL_FUNC(gtk_frame_configure_callback
), (gpointer
)this ); 
 178     if (m_parent
) m_parent
->AddChild( this ); 
 187     if (m_frameMenuBar
) delete m_frameMenuBar
; 
 188     if (m_frameStatusBar
) delete m_frameStatusBar
; 
 189     if (m_frameToolBar
) delete m_frameToolBar
; 
 191     wxTopLevelWindows
.DeleteObject( this ); 
 192     if (wxTopLevelWindows
.Number() == 0) wxTheApp
->ExitMainLoop(); 
 195 bool wxFrame::Show( bool show 
) 
 197     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 199     if (show 
&& !m_sizeSet
) 
 201   // by calling GtkOnSize here, we don't have to call 
 202   // either after showing the frame, which would entail 
 203   // much ugly flicker nor from within the size_allocate 
 204   // handler, because GTK 1.1.X forbids that. 
 206         GtkOnSize( m_x
, m_y
, m_width
, m_height 
); 
 209     return wxWindow::Show( show 
); 
 212 void wxFrame::OnCloseWindow( wxCloseEvent 
&event 
) 
 214     if (GetEventHandler()->OnClose() || event
.GetForce()) this->Destroy(); 
 217 bool wxFrame::Destroy() 
 219     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 221     if (!wxPendingDelete
.Member(this)) wxPendingDelete
.Append(this); 
 226 wxPoint 
wxFrame::GetClientAreaOrigin() const 
 228     wxPoint 
pt( m_miniEdge
, m_miniEdge 
+ m_miniTitle 
); 
 232         m_frameMenuBar
->GetSize( (int*)NULL
, &h 
); 
 238         m_frameToolBar
->GetSize( (int*)NULL
, &h 
); 
 244 void wxFrame::SetSize( int x
, int y
, int width
, int height
, int sizeFlags 
) 
 246     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid window" ); 
 248     // Don't do anything for children of wxMDIChildFrame 
 249     if (!m_wxwindow
) return; 
 251     if (m_resizing
) return; // I don't like recursions 
 256     int old_width 
= m_width
; 
 257     int old_height 
= m_height
; 
 259     if ((sizeFlags 
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
) 
 261         if (x 
!= -1) m_x 
= x
; 
 262         if (y 
!= -1) m_y 
= y
; 
 263         if (width 
!= -1) m_width 
= width
; 
 264         if (height 
!= -1) m_height 
= height
; 
 274     if ((sizeFlags 
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
) 
 276         if (width 
== -1) m_width 
= 80; 
 279     if ((sizeFlags 
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
) 
 281        if (height 
== -1) m_height 
= 26; 
 284     if ((m_minWidth 
!= -1) && (m_width 
< m_minWidth
)) m_width 
= m_minWidth
; 
 285     if ((m_minHeight 
!= -1) && (m_height 
< m_minHeight
)) m_height 
= m_minHeight
; 
 286     if ((m_maxWidth 
!= -1) && (m_width 
> m_maxWidth
)) m_width 
= m_minWidth
; 
 287     if ((m_maxHeight 
!= -1) && (m_height 
> m_maxHeight
)) m_height 
= m_minHeight
; 
 289     if ((m_x 
!= -1) || (m_y 
!= -1)) 
 291         if ((m_x 
!= old_x
) || (m_y 
!= old_y
)) 
 292             gtk_widget_set_uposition( m_widget
, m_x
, m_y 
); 
 295     if ((m_width 
!= old_width
) || (m_height 
!= old_height
)) 
 297         gtk_widget_set_usize( m_widget
, m_width
, m_height 
); 
 300     wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
 301     event
.SetEventObject( this ); 
 302     GetEventHandler()->ProcessEvent( event 
); 
 307 void wxFrame::SetSize( int width
, int height 
) 
 309     SetSize( -1, -1, width
, height
, wxSIZE_USE_EXISTING 
); 
 312 void wxFrame::Centre( int direction 
) 
 314     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 319     if (direction 
& wxHORIZONTAL 
== wxHORIZONTAL
) x 
= (gdk_screen_width () - m_width
) / 2; 
 320     if (direction 
& wxVERTICAL 
== wxVERTICAL
) y 
= (gdk_screen_height () - m_height
) / 2; 
 325 void wxFrame::GetClientSize( int *width
, int *height 
) const 
 327     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 329     wxWindow::GetClientSize( width
, height 
); 
 332         if (m_frameMenuBar
) (*height
) -= wxMENU_HEIGHT
; 
 333         if (m_frameStatusBar
) (*height
) -= wxSTATUS_HEIGHT
; 
 337             m_frameToolBar
->GetSize( (int *) NULL
, &y 
); 
 340         (*height
) -= m_miniEdge
*2 + m_miniTitle
; 
 344         (*width
) -= m_miniEdge
*2; 
 348 void wxFrame::SetClientSize( int const width
, int const height 
) 
 350     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 353     if (m_frameMenuBar
) h 
+= wxMENU_HEIGHT
; 
 354     if (m_frameStatusBar
) h 
+= wxSTATUS_HEIGHT
; 
 358         m_frameToolBar
->GetSize( (int *) NULL
, &y 
); 
 361     wxWindow::SetClientSize( width 
+ m_miniEdge
*2, h  
+ m_miniEdge
*2 + m_miniTitle 
); 
 364 void wxFrame::GtkOnSize( int WXUNUSED(x
), int WXUNUSED(y
), int width
, int height 
) 
 366     // due to a bug in gtk, x,y are always 0 
 370     if (m_resizing
) return; 
 373     if (!m_wxwindow
) return; 
 378     if ((m_minWidth 
!= -1) && (m_width 
< m_minWidth
)) m_width 
= m_minWidth
; 
 379     if ((m_minHeight 
!= -1) && (m_height 
< m_minHeight
)) m_height 
= m_minHeight
; 
 380     if ((m_maxWidth 
!= -1) && (m_width 
> m_maxWidth
)) m_width 
= m_minWidth
; 
 381     if ((m_maxHeight 
!= -1) && (m_height 
> m_maxHeight
)) m_height 
= m_minHeight
; 
 383     gtk_widget_set_usize( m_widget
, m_width
, m_height 
); 
 385     // this emulates the new wxMSW behaviour of placing all 
 386     // frame-subwindows (menu, toolbar..) on one native window 
 387         // OK, this hurts in the eye, but I don't want to call SetSize() 
 388         // because I don't want to call any non-native functions here. 
 393   int yy 
= m_miniEdge 
+ m_miniTitle
; 
 394   int ww 
= m_width  
- 2*m_miniEdge
; 
 395   int hh 
= wxMENU_HEIGHT
; 
 396         m_frameMenuBar
->m_x 
= xx
; 
 397         m_frameMenuBar
->m_y 
= yy
; 
 398         m_frameMenuBar
->m_width 
= ww
; 
 399         m_frameMenuBar
->m_height 
= hh
; 
 401         gtk_myfixed_move( GTK_MYFIXED(m_wxwindow
), m_frameMenuBar
->m_widget
, xx
, yy 
); 
 402         gtk_widget_set_usize( m_frameMenuBar
->m_widget
, ww
, hh 
); 
 408   int yy 
= m_miniEdge 
+ m_miniTitle
; 
 409         if (m_frameMenuBar
) yy 
+= wxMENU_HEIGHT
; 
 410   int ww 
= m_width 
- 2*m_miniEdge
; 
 411         int hh 
= m_frameToolBar
->m_height
; 
 413         m_frameToolBar
->m_x 
= xx
; 
 414         m_frameToolBar
->m_y 
= yy
; 
 415         m_frameToolBar
->m_height 
= hh
; 
 416         m_frameToolBar
->m_width 
= ww
; 
 418         gtk_myfixed_move( GTK_MYFIXED(m_wxwindow
), m_frameToolBar
->m_widget
, xx
, yy 
); 
 419         gtk_widget_set_usize( m_frameToolBar
->m_widget
, ww
, hh 
); 
 422     if (m_frameStatusBar
) 
 424         int xx 
= 0 + m_miniEdge
; 
 425   int yy 
= m_height 
- wxSTATUS_HEIGHT 
- m_miniEdge
; 
 426   int ww 
= m_width 
- 2*m_miniEdge
; 
 427   int hh 
= wxSTATUS_HEIGHT
; 
 429         m_frameStatusBar
->m_x 
= xx
; 
 430         m_frameStatusBar
->m_y 
= yy
; 
 431         m_frameStatusBar
->m_width 
= ww
; 
 432         m_frameStatusBar
->m_height 
= hh
; 
 434         gtk_myfixed_move( GTK_MYFIXED(m_wxwindow
), m_frameStatusBar
->m_widget
, xx
, yy 
); 
 435         gtk_widget_set_usize( m_frameStatusBar
->m_widget
, ww
, hh 
); 
 440     wxSizeEvent 
event( wxSize(m_width
,m_height
), GetId() ); 
 441     event
.SetEventObject( this ); 
 442     GetEventHandler()->ProcessEvent( event 
); 
 447 void wxFrame::OnIdle(wxIdleEvent
& WXUNUSED(event
) ) 
 450         GtkOnSize( m_x
, m_y
, m_width
, m_height 
); 
 455 void wxFrame::OnSize( wxSizeEvent 
&WXUNUSED(event
) ) 
 457     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 465         // no child: go out ! 
 466         if (!GetChildren().First()) return; 
 468         // do we have exactly one child? 
 469         wxWindow 
*child 
= (wxWindow 
*) NULL
; 
 470         for(wxNode 
*node 
= GetChildren().First(); node
; node 
= node
->Next()) 
 472             wxWindow 
*win 
= (wxWindow 
*)node
->Data(); 
 473             if (!wxIS_KIND_OF(win
,wxFrame
) && !wxIS_KIND_OF(win
,wxDialog
) 
 474 #if 0  // not in m_children anyway ? 
 475               && (win 
!= m_frameMenuBar
) && 
 476               (win 
!= m_frameToolBar
) && 
 477               (win 
!= m_frameStatusBar
) 
 481           // it's the second one: do nothing 
 487         // yes: set it's size to fill all the frame 
 488         int client_x
, client_y
; 
 489         GetClientSize( &client_x
, &client_y 
); 
 490         child
->SetSize( 1, 1, client_x
-2, client_y
-2 ); 
 494 static void SetInvokingWindow( wxMenu 
*menu
, wxWindow 
*win 
) 
 496     menu
->SetInvokingWindow( win 
); 
 497     wxNode 
*node 
= menu
->m_items
.First(); 
 500         wxMenuItem 
*menuitem 
= (wxMenuItem
*)node
->Data(); 
 501         if (menuitem
->IsSubMenu()) 
 502             SetInvokingWindow( menuitem
->GetSubMenu(), win 
); 
 507 void wxFrame::SetMenuBar( wxMenuBar 
*menuBar 
) 
 509     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 510     wxASSERT_MSG( (m_wxwindow 
!= NULL
), "invalid frame" ); 
 512     m_frameMenuBar 
= menuBar
; 
 516         wxNode 
*node 
= m_frameMenuBar
->m_menus
.First(); 
 519             wxMenu 
*menu 
= (wxMenu
*)node
->Data(); 
 520             SetInvokingWindow( menu
, this ); 
 524         if (m_frameMenuBar
->m_parent 
!= this) 
 526             m_frameMenuBar
->m_parent 
= this; 
 527             gtk_myfixed_put( GTK_MYFIXED(m_wxwindow
), 
 528                 m_frameMenuBar
->m_widget
, m_frameMenuBar
->m_x
, m_frameMenuBar
->m_y 
); 
 532     if (m_sizeSet
) GtkOnSize( m_x
, m_y
, m_width
, m_height 
); 
 535 wxMenuBar 
*wxFrame::GetMenuBar() const 
 537     return m_frameMenuBar
; 
 540 wxToolBar
* wxFrame::CreateToolBar(long style
, wxWindowID id
, const wxString
& name
) 
 542     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 544     wxCHECK_MSG( m_frameToolBar 
== NULL
, FALSE
, "recreating toolbar in wxFrame" ); 
 546     m_frameToolBar 
= OnCreateToolBar( style
, id
, name 
); 
 548     GetChildren().DeleteObject( m_frameToolBar 
); 
 550     if (m_sizeSet
) GtkOnSize( m_x
, m_y
, m_width
, m_height 
); 
 552     return m_frameToolBar
; 
 555 wxToolBar
* wxFrame::OnCreateToolBar( long style
, wxWindowID id
, const wxString
& name 
) 
 557     return new wxToolBar( this, id
, wxDefaultPosition
, wxDefaultSize
, style
, name 
); 
 560 wxToolBar 
*wxFrame::GetToolBar() const 
 562     return m_frameToolBar
; 
 565 wxStatusBar
* wxFrame::CreateStatusBar( int number
, long style
, wxWindowID id
, const wxString
& name 
) 
 567     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 569     wxCHECK_MSG( m_frameStatusBar 
== NULL
, FALSE
, "recreating status bar in wxFrame" ); 
 571     m_frameStatusBar 
= OnCreateStatusBar( number
, style
, id
, name 
); 
 573     if (m_sizeSet
) GtkOnSize( m_x
, m_y
, m_width
, m_height 
); 
 575     return m_frameStatusBar
; 
 578 wxStatusBar 
*wxFrame::OnCreateStatusBar( int number
, long style
, wxWindowID id
, const wxString
& name 
) 
 580     wxStatusBar 
*statusBar 
= (wxStatusBar 
*) NULL
; 
 582     statusBar 
= new wxStatusBar(this, id
, wxPoint(0, 0), wxSize(100, 20), style
, name
); 
 584     // Set the height according to the font and the border size 
 585     wxClientDC 
dc(statusBar
); 
 586     dc
.SetFont( statusBar
->GetFont() ); 
 589     dc
.GetTextExtent( "X", &x
, &y 
); 
 591     int height 
= (int)( (y  
* 1.1) + 2* statusBar
->GetBorderY()); 
 593     statusBar
->SetSize( -1, -1, 100, height 
); 
 595     statusBar
->SetFieldsCount( number 
); 
 599 void wxFrame::SetStatusText(const wxString
& text
, int number
) 
 601     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 603     wxCHECK_RET( m_frameStatusBar 
!= NULL
, "no statusbar to set text for" ); 
 605     m_frameStatusBar
->SetStatusText(text
, number
); 
 608 void wxFrame::SetStatusWidths(int n
, const int widths_field
[] ) 
 610     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 612     wxCHECK_RET( m_frameStatusBar 
!= NULL
, "no statusbar to set widths for" ); 
 614     m_frameStatusBar
->SetStatusWidths(n
, widths_field
); 
 617 wxStatusBar 
*wxFrame::GetStatusBar() const 
 619     return m_frameStatusBar
; 
 622 void wxFrame::SetTitle( const wxString 
&title 
) 
 624     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 627     if (m_title
.IsNull()) m_title 
= ""; 
 628     gtk_window_set_title( GTK_WINDOW(m_widget
), title 
); 
 631 void wxFrame::SetIcon( const wxIcon 
&icon 
) 
 633     wxASSERT_MSG( (m_widget 
!= NULL
), "invalid frame" ); 
 636     if (!icon
.Ok()) return; 
 638     wxMask 
*mask 
= icon
.GetMask(); 
 639     GdkBitmap 
*bm 
= (GdkBitmap 
*) NULL
; 
 640     if (mask
) bm 
= mask
->GetBitmap(); 
 642     gdk_window_set_icon( m_widget
->window
, (GdkWindow 
*) NULL
, icon
.GetPixmap(), bm 
);