1 ///////////////////////////////////////////////////////////////////////////// 
   8 // Copyright:   (c) AUTHOR 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "frame.h" 
  17 #include "wx/statusbr.h" 
  18 #include "wx/toolbar.h" 
  19 #include "wx/menuitem.h" 
  21 #include "wx/dcclient.h" 
  22 #include "wx/dialog.h" 
  23 #include "wx/settings.h" 
  26 extern wxList wxModelessWindows
; 
  27 extern wxList wxPendingDelete
; 
  29 #if !USE_SHARED_LIBRARY 
  30 BEGIN_EVENT_TABLE(wxFrame
, wxWindow
) 
  31   EVT_SIZE(wxFrame::OnSize
) 
  32   EVT_ACTIVATE(wxFrame::OnActivate
) 
  33   EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight
) 
  34   EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged
) 
  35   EVT_IDLE(wxFrame::OnIdle
) 
  36   EVT_CLOSE(wxFrame::OnCloseWindow
) 
  39 IMPLEMENT_DYNAMIC_CLASS(wxFrame
, wxWindow
) 
  42 #if wxUSE_NATIVE_STATUSBAR 
  43 bool wxFrame::m_useNativeStatusBar 
= TRUE
; 
  45 bool wxFrame::m_useNativeStatusBar 
= FALSE
; 
  50   m_frameToolBar 
= NULL 
; 
  51   m_frameMenuBar 
= NULL
; 
  52   m_frameStatusBar 
= NULL
; 
  54   m_windowParent 
= NULL
; 
  58 bool wxFrame::Create(wxWindow 
*parent
, 
  60            const wxString
& title
, 
  67     wxTopLevelWindows
.Append(this); 
  70   m_windowStyle 
= style
; 
  71   m_frameMenuBar 
= NULL
; 
  72   m_frameToolBar 
= NULL 
; 
  73   m_frameStatusBar 
= NULL
; 
  75   SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
)); 
  80     m_windowId 
= (int)NewControlId(); 
  82   if (parent
) parent
->AddChild(this); 
  84   wxModelessWindows
.Append(this); 
  86   // TODO: create frame. 
  93   wxTopLevelWindows
.DeleteObject(this); 
  96     delete m_frameStatusBar
; 
  98     delete m_frameMenuBar
; 
 100 /* Check if it's the last top-level window */ 
 102   if (wxTheApp 
&& (wxTopLevelWindows
.Number() == 0)) 
 104     wxTheApp
->SetTopWindow(NULL
); 
 106     if (wxTheApp
->GetExitOnFrameDelete()) 
 108        // TODO signal to the app that we're going to close 
 112   wxModelessWindows
.DeleteObject(this); 
 115 // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc. 
 116 void wxFrame::GetClientSize(int *x
, int *y
) const 
 121 // Set the client size (i.e. leave the calculation of borders etc. 
 123 void wxFrame::SetClientSize(int width
, int height
) 
 128 void wxFrame::GetSize(int *width
, int *height
) const 
 133 void wxFrame::GetPosition(int *x
, int *y
) const 
 138 void wxFrame::SetSize(int x
, int y
, int width
, int height
, int sizeFlags
) 
 143 bool wxFrame::Show(bool show
) 
 149 void wxFrame::Iconize(bool iconize
) 
 154 // Equivalent to maximize/restore in Windows 
 155 void wxFrame::Maximize(bool maximize
) 
 160 bool wxFrame::IsIconized() const 
 166 // Is the frame maximized? 
 167 bool wxFrame::IsMaximized(void) const 
 173 void wxFrame::SetTitle(const wxString
& title
) 
 178 wxString 
wxFrame::GetTitle() const 
 184 void wxFrame::SetIcon(const wxIcon
& icon
) 
 190 wxStatusBar 
*wxFrame::OnCreateStatusBar(int number
, long style
, wxWindowID id
, 
 191     const wxString
& name
) 
 193     wxStatusBar 
*statusBar 
= NULL
; 
 195     statusBar 
= new wxStatusBar(this, id
, wxPoint(0, 0), wxSize(100, 20), 
 198     // Set the height according to the font and the border size 
 199     wxClientDC 
dc(statusBar
); 
 200     dc
.SetFont(statusBar
->GetFont()); 
 203     dc
.GetTextExtent("X", &x
, &y
); 
 205     int height 
= (int)( (y  
* 1.1) + 2* statusBar
->GetBorderY()); 
 207     statusBar
->SetSize(-1, -1, 100, height
); 
 209     statusBar
->SetFieldsCount(number
); 
 213 wxStatusBar
* wxFrame::CreateStatusBar(int number
, long style
, wxWindowID id
, 
 214     const wxString
& name
) 
 216   // Calling CreateStatusBar twice is an error. 
 217   wxCHECK_MSG( m_frameStatusBar 
== NULL
, FALSE
,  
 218                "recreating status bar in wxFrame" ); 
 220   m_frameStatusBar 
= OnCreateStatusBar(number
, style
, id
, 
 222   if ( m_frameStatusBar 
) 
 225     return m_frameStatusBar
; 
 231 void wxFrame::SetStatusText(const wxString
& text
, int number
) 
 233   wxCHECK_RET( m_frameStatusBar 
!= NULL
, "no statusbar to set text for" ); 
 235   m_frameStatusBar
->SetStatusText(text
, number
); 
 238 void wxFrame::SetStatusWidths(int n
, const int widths_field
[]) 
 240   wxCHECK_RET( m_frameStatusBar 
!= NULL
, "no statusbar to set widths for" ); 
 242   m_frameStatusBar
->SetStatusWidths(n
, widths_field
); 
 246 void wxFrame::PositionStatusBar() 
 249     GetClientSize(&w
, &h
); 
 251     m_frameStatusBar
->GetSize(&sw
, &sh
); 
 253     // Since we wish the status bar to be directly under the client area, 
 254     // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS. 
 255     m_frameStatusBar
->SetSize(0, h
, w
, sh
); 
 258 void wxFrame::SetMenuBar(wxMenuBar 
*menuBar
) 
 262         m_frameMenuBar 
= NULL
; 
 266     m_frameMenuBar 
= menuBar
; 
 273   // Work out max. size 
 274   wxNode 
*node 
= GetChildren().First(); 
 279     // Find a child that's a subwindow, but not a dialog box. 
 280     wxWindow 
*win 
= (wxWindow 
*)node
->Data(); 
 282     if (!win
->IsKindOf(CLASSINFO(wxFrame
)) && 
 283          !win
->IsKindOf(CLASSINFO(wxDialog
))) 
 287       win
->GetSize(&width
, &height
); 
 288       win
->GetPosition(&x
, &y
); 
 290       if ((x 
+ width
) > max_width
) 
 291         max_width 
= x 
+ width
; 
 292       if ((y 
+ height
) > max_height
) 
 293         max_height 
= y 
+ height
; 
 297   SetClientSize(max_width
, max_height
); 
 300 // Responds to colour changes, and passes event on to children. 
 301 void wxFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
) 
 303     SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE
)); 
 306     if ( m_frameStatusBar 
) 
 308         wxSysColourChangedEvent event2
; 
 309         event2
.SetEventObject( m_frameStatusBar 
); 
 310         m_frameStatusBar
->ProcessEvent(event2
); 
 313     // Propagate the event to the non-top-level children 
 314     wxWindow::OnSysColourChanged(event
); 
 317 // Default resizing behaviour - if only ONE subwindow, 
 318 // resize to client rectangle size 
 319 void wxFrame::OnSize(wxSizeEvent
& event
) 
 321   // if we're using constraints - do use them 
 322   #if wxUSE_CONSTRAINTS 
 323     if ( GetAutoLayout() ) { 
 329   // do we have _exactly_ one child? 
 330   wxWindow 
*child 
= NULL
; 
 331   for ( wxNode 
*node 
= GetChildren().First(); node
; node 
= node
->Next() ) 
 333     wxWindow 
*win 
= (wxWindow 
*)node
->Data(); 
 334     if ( !win
->IsKindOf(CLASSINFO(wxFrame
))  && 
 335          !win
->IsKindOf(CLASSINFO(wxDialog
)) &&  
 336          (win 
!= GetStatusBar()) && 
 337          (win 
!= GetToolBar()) ) 
 340         return;     // it's our second subwindow - nothing to do 
 346     // we have exactly one child - set it's size to fill the whole frame 
 347     int clientW
, clientH
; 
 348     GetClientSize(&clientW
, &clientH
); 
 353     child
->SetSize(x
, y
, clientW
, clientH
); 
 357 // Default activation behaviour - set the focus for the first child 
 359 void wxFrame::OnActivate(wxActivateEvent
& event
) 
 361   for(wxNode 
*node 
= GetChildren().First(); node
; node 
= node
->Next()) 
 363     // Find a child that's a subwindow, but not a dialog box. 
 364     wxWindow 
*child 
= (wxWindow 
*)node
->Data(); 
 365     if (!child
->IsKindOf(CLASSINFO(wxFrame
)) && 
 366          !child
->IsKindOf(CLASSINFO(wxDialog
))) 
 374 // The default implementation for the close window event. 
 375 void wxFrame::OnCloseWindow(wxCloseEvent
& event
) 
 380 // Destroy the window (delayed, if a managed window) 
 381 bool wxFrame::Destroy() 
 383   if (!wxPendingDelete
.Member(this)) 
 384     wxPendingDelete
.Append(this); 
 388 // Default menu selection behaviour - display a help string 
 389 void wxFrame::OnMenuHighlight(wxMenuEvent
& event
) 
 393     if (event
.GetMenuId() == -1) 
 397       wxMenuBar 
*menuBar 
= GetMenuBar(); 
 400         wxString 
helpString(menuBar
->GetHelpString(event
.GetMenuId())); 
 401         if (helpString 
!= "") 
 402           SetStatusText(helpString
); 
 408 wxMenuBar 
*wxFrame::GetMenuBar() const 
 410   return m_frameMenuBar
; 
 413 void wxFrame::Centre(int direction
) 
 415   int display_width
, display_height
, width
, height
, x
, y
; 
 416   wxDisplaySize(&display_width
, &display_height
); 
 418   GetSize(&width
, &height
); 
 421   if (direction 
& wxHORIZONTAL
) 
 422     x 
= (int)((display_width 
- width
)/2); 
 423   if (direction 
& wxVERTICAL
) 
 424     y 
= (int)((display_height 
- height
)/2); 
 426   SetSize(x
, y
, width
, height
); 
 429 // Call this to simulate a menu command 
 430 void wxFrame::Command(int id
) 
 435 void wxFrame::ProcessCommand(int id
) 
 437   wxCommandEvent 
commandEvent(wxEVENT_TYPE_MENU_COMMAND
, id
); 
 438   commandEvent
.SetInt( id 
); 
 439   commandEvent
.SetEventObject( this ); 
 441   wxMenuBar 
*bar 
= GetMenuBar() ; 
 445 /* TODO: check the menu item if required 
 446   wxMenuItem *item = bar->FindItemForId(id) ; 
 447   if (item && item->IsCheckable()) 
 449     bar->Check(id,!bar->Checked(id)) ; 
 453   // Process events starting with the window with the focus, if any. 
 454   wxWindow
* focusWin 
= wxFindFocusDescendant(this); 
 456   wxEvtHandler
* evtHandler 
= focusWin 
? focusWin
->GetEventHandler() : GetEventHandler(); 
 458   evtHandler
->ProcessEvent(commandEvent
); 
 461 // Checks if there is a toolbar, and returns the first free client position 
 462 wxPoint 
wxFrame::GetClientAreaOrigin() const 
 468         GetToolBar()->GetSize(& w
, & h
); 
 470         if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
) 
 482 void wxFrame::ScreenToClient(int *x
, int *y
) const 
 484     wxWindow::ScreenToClient(x
, y
); 
 486     // We may be faking the client origin. 
 487     // So a window that's really at (0, 30) may appear 
 488     // (to wxWin apps) to be at (0, 0). 
 489     wxPoint 
pt(GetClientAreaOrigin()); 
 494 void wxFrame::ClientToScreen(int *x
, int *y
) const 
 496     // We may be faking the client origin. 
 497     // So a window that's really at (0, 30) may appear 
 498     // (to wxWin apps) to be at (0, 0). 
 499     wxPoint 
pt1(GetClientAreaOrigin()); 
 503     wxWindow::ClientToScreen(x
, y
); 
 506 wxToolBar
* wxFrame::CreateToolBar(long style
, wxWindowID id
, const wxString
& name
) 
 508     wxCHECK_MSG( m_frameToolBar 
== NULL
, FALSE
, 
 509                "recreating toolbar in wxFrame" ); 
 511     wxToolBar
* toolBar 
= OnCreateToolBar(style
, id
, name
); 
 524 wxToolBar
* wxFrame::OnCreateToolBar(long style
, wxWindowID id
, const wxString
& name
) 
 526     return new wxToolBar(this, id
, wxDefaultPosition
, wxDefaultSize
, style
, name
); 
 529 void wxFrame::PositionToolBar() 
 533     // TODO: we actually need to use the low-level client size, before 
 534     // the toolbar/status bar were added. 
 535     // So DEFINITELY replace the line below with something appropriate. 
 537     GetClientSize(& cw
, &ch
); 
 539     if ( GetStatusBar() ) 
 541       int statusX
, statusY
; 
 542       GetStatusBar()->GetClientSize(&statusX
, &statusY
); 
 549         GetToolBar()->GetSize(& tw
, & th
); 
 551         if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL
) 
 553             // Use the 'real' position. wxSIZE_NO_ADJUSTMENTS 
 554             // means, pretend we don't have toolbar/status bar, so we 
 555             // have the original client size. 
 556             GetToolBar()->SetSize(0, 0, tw
, ch
, wxSIZE_NO_ADJUSTMENTS
); 
 560             // Use the 'real' position 
 561             GetToolBar()->SetSize(0, 0, cw
, th
, wxSIZE_NO_ADJUSTMENTS
);