1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mac/classic/mdi.cpp 
   3 // Purpose:     MDI classes 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #include "wx/wxprec.h" 
  19     #include "wx/settings.h" 
  22 #include "wx/mac/private.h" 
  23 #include "wx/mac/uma.h" 
  25 extern wxWindowList wxModelessWindows
; 
  27 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
, wxFrame
) 
  28 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
, wxFrame
) 
  29 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
, wxWindow
) 
  31 BEGIN_EVENT_TABLE(wxMDIParentFrame
, wxFrame
) 
  32   EVT_ACTIVATE(wxMDIParentFrame::OnActivate
) 
  33   EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged
) 
  36 BEGIN_EVENT_TABLE(wxMDIClientWindow
, wxWindow
) 
  37   EVT_SCROLL(wxMDIClientWindow::OnScroll
) 
  40 static const int IDM_WINDOWTILE  
= 4001; 
  41 static const int IDM_WINDOWTILEHOR  
= 4001; 
  42 static const int IDM_WINDOWCASCADE 
= 4002; 
  43 static const int IDM_WINDOWICONS 
= 4003; 
  44 static const int IDM_WINDOWNEXT 
= 4004; 
  45 static const int IDM_WINDOWTILEVERT 
= 4005; 
  46 static const int IDM_WINDOWPREV 
= 4006; 
  48 // This range gives a maximum of 500 MDI children. Should be enough :-) 
  49 static const int wxFIRST_MDI_CHILD 
= 4100; 
  50 static const int wxLAST_MDI_CHILD 
= 4600; 
  52 // Status border dimensions 
  53 static const int wxTHICK_LINE_BORDER 
= 3; 
  57 wxMDIParentFrame::wxMDIParentFrame() 
  59     m_clientWindow 
= NULL
; 
  60     m_currentChild 
= NULL
; 
  61     m_windowMenu 
= (wxMenu
*) NULL
; 
  62     m_parentFrameActive 
= true; 
  65 bool wxMDIParentFrame::Create(wxWindow 
*parent
, 
  67                               const wxString
& title
, 
  73     m_clientWindow 
= NULL
; 
  74     m_currentChild 
= NULL
; 
  76     // this style can be used to prevent a window from having the standard MDI 
  78     if ( style 
& wxFRAME_NO_WINDOW_MENU 
) 
  80         m_windowMenu 
= (wxMenu 
*)NULL
; 
  81         style 
-= wxFRAME_NO_WINDOW_MENU 
; 
  83     else // normal case: we have the window menu, so construct it 
  85         m_windowMenu 
= new wxMenu
; 
  87         m_windowMenu
->Append(IDM_WINDOWCASCADE
, wxT("&Cascade")); 
  88         m_windowMenu
->Append(IDM_WINDOWTILEHOR
, wxT("Tile &Horizontally")); 
  89         m_windowMenu
->Append(IDM_WINDOWTILEVERT
, wxT("Tile &Vertically")); 
  90         m_windowMenu
->AppendSeparator(); 
  91         m_windowMenu
->Append(IDM_WINDOWICONS
, wxT("&Arrange Icons")); 
  92         m_windowMenu
->Append(IDM_WINDOWNEXT
, wxT("&Next")); 
  95     wxFrame::Create( parent 
, id 
, title 
, pos 
, size 
, style 
, name 
) ; 
  96     m_parentFrameActive 
= true; 
 103 wxMDIParentFrame::~wxMDIParentFrame() 
 106     // already delete by DestroyChildren() 
 108     m_frameToolBar 
= NULL
; 
 111     m_frameStatusBar 
= NULL
; 
 113     m_clientWindow 
= NULL 
; 
 118         m_windowMenu 
= (wxMenu
*) NULL
; 
 121     if ( m_clientWindow 
) 
 123         delete m_clientWindow
; 
 124         m_clientWindow 
= NULL 
; 
 129 void wxMDIParentFrame::SetMenuBar(wxMenuBar 
*menu_bar
) 
 131     wxFrame::SetMenuBar( menu_bar 
) ; 
 134 void wxMDIParentFrame::MacActivate(long timestamp
, bool activating
) 
 136     wxLogDebug(wxT("MDI PARENT=%p MacActivate(0x%08lx,%s)"),this,timestamp
,activating
?wxT("ACTIV"):wxT("deact")); 
 139         if(s_macDeactivateWindow 
&& s_macDeactivateWindow
->GetParent()==this) 
 141             wxLogDebug(wxT("child had been scheduled for deactivation, rehighlighting")); 
 142             UMAHighlightAndActivateWindow((WindowRef
)s_macDeactivateWindow
->MacGetWindowRef(), true); 
 143             wxLogDebug(wxT("done highliting child")); 
 144             s_macDeactivateWindow 
= NULL
; 
 146         else if(s_macDeactivateWindow 
== this) 
 148             wxLogDebug(wxT("Avoided deactivation/activation of this=%p"), this); 
 149             s_macDeactivateWindow 
= NULL
; 
 151         else // window to deactivate is NULL or is not us or one of our kids 
 153             // activate kid instead 
 155                 m_currentChild
->MacActivate(timestamp
,activating
); 
 157                 wxFrame::MacActivate(timestamp
,activating
); 
 162         // We were scheduled for deactivation, and now we do it. 
 163         if(s_macDeactivateWindow
==this) 
 165             s_macDeactivateWindow 
= NULL
; 
 167                 m_currentChild
->MacActivate(timestamp
,activating
); 
 168             wxFrame::MacActivate(timestamp
,activating
); 
 170         else // schedule ourselves for deactivation 
 172             if(s_macDeactivateWindow
) 
 173                 wxLogDebug(wxT("window=%p SHOULD have been deactivated, oh well!"),s_macDeactivateWindow
); 
 174             wxLogDebug(wxT("Scheduling delayed MDI Parent deactivation")); 
 175             s_macDeactivateWindow 
= this; 
 180 void wxMDIParentFrame::OnActivate(wxActivateEvent
& event
) 
 185 // Returns the active MDI child window 
 186 wxMDIChildFrame 
*wxMDIParentFrame::GetActiveChild() const 
 188     return m_currentChild 
; 
 191 // Create the client window class (don't Create the window, 
 192 // just return a new class) 
 193 wxMDIClientWindow 
*wxMDIParentFrame::OnCreateClient() 
 195     m_clientWindow 
= new wxMDIClientWindow( this ); 
 196     return m_clientWindow
; 
 199 // Responds to colour changes, and passes event on to children. 
 200 void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
) 
 204     // Propagate the event to the non-top-level children 
 205     wxFrame::OnSysColourChanged(event
); 
 209 void wxMDIParentFrame::Cascade() 
 214 void wxMDIParentFrame::Tile(wxOrientation 
WXUNUSED(orient
)) 
 219 void wxMDIParentFrame::ArrangeIcons() 
 224 void wxMDIParentFrame::ActivateNext() 
 229 void wxMDIParentFrame::ActivatePrevious() 
 236 wxMDIChildFrame::wxMDIChildFrame() 
 240 void wxMDIChildFrame::Init() 
 244 bool wxMDIChildFrame::Create(wxMDIParentFrame 
*parent
, 
 246                              const wxString
& title
, 
 250                              const wxString
& name
) 
 254     if ( id 
!= wxID_ANY 
) 
 257         m_windowId 
= (int)NewControlId(); 
 259     if (parent
) parent
->AddChild(this); 
 261     MacCreateRealWindow( title
, pos 
, size 
, MacRemoveBordersFromStyle(style
) , name 
) ; 
 263     m_macWindowBackgroundTheme 
= kThemeBrushDocumentWindowBackground 
; 
 264     SetThemeWindowBackground( (WindowRef
) m_macWindow 
, m_macWindowBackgroundTheme 
, false ) ; 
 266     wxModelessWindows
.Append(this); 
 270 wxMDIChildFrame::~wxMDIChildFrame() 
 272     wxMDIParentFrame 
*mdiparent 
= wxDynamicCast(m_parent
, wxMDIParentFrame
); 
 274     if(mdiparent
->m_currentChild 
== this) 
 275         mdiparent
->m_currentChild 
= NULL
; 
 277     // already delete by DestroyChildren() 
 279     m_frameToolBar 
= NULL
; 
 282     m_frameStatusBar 
= NULL
; 
 286 void wxMDIChildFrame::SetMenuBar(wxMenuBar 
*menu_bar
) 
 288     return wxFrame::SetMenuBar( menu_bar 
) ; 
 291 void wxMDIChildFrame::MacActivate(long timestamp
, bool activating
) 
 293     wxLogDebug(wxT("MDI child=%p  MacActivate(0x%08lx,%s)"),this,timestamp
,activating
?wxT("ACTIV"):wxT("deact")); 
 294     wxMDIParentFrame 
*mdiparent 
= wxDynamicCast(m_parent
, wxMDIParentFrame
); 
 298         if(s_macDeactivateWindow 
== m_parent
) 
 300             wxLogDebug(wxT("parent had been scheduled for deactivation, rehighlighting")); 
 301             UMAHighlightAndActivateWindow((WindowRef
)s_macDeactivateWindow
->MacGetWindowRef(), true); 
 302             wxLogDebug(wxT("done highliting parent")); 
 303             s_macDeactivateWindow 
= NULL
; 
 305         else if((mdiparent
->m_currentChild
==this) || !s_macDeactivateWindow
) 
 306             mdiparent
->wxFrame::MacActivate(timestamp
,activating
); 
 308         if(mdiparent
->m_currentChild 
&& mdiparent
->m_currentChild
!=this) 
 309             mdiparent
->m_currentChild
->wxFrame::MacActivate(timestamp
,false); 
 310         mdiparent
->m_currentChild 
= this; 
 312         if(s_macDeactivateWindow
==this) 
 314             wxLogDebug(wxT("Avoided deactivation/activation of this=%p"),this); 
 315             s_macDeactivateWindow
=NULL
; 
 318             wxFrame::MacActivate(timestamp
, activating
); 
 322         // We were scheduled for deactivation, and now we do it. 
 323         if(s_macDeactivateWindow
==this) 
 325             s_macDeactivateWindow 
= NULL
; 
 326             wxFrame::MacActivate(timestamp
,activating
); 
 327             if(mdiparent
->m_currentChild
==this) 
 328                 mdiparent
->wxFrame::MacActivate(timestamp
,activating
); 
 330         else // schedule ourselves for deactivation 
 332             if(s_macDeactivateWindow
) 
 333                 wxLogDebug(wxT("window=%p SHOULD have been deactivated, oh well!"),s_macDeactivateWindow
); 
 334             wxLogDebug(wxT("Scheduling delayed deactivation")); 
 335             s_macDeactivateWindow 
= this; 
 341 void wxMDIChildFrame::Maximize() 
 343     wxFrame::Maximize() ; 
 346 void wxMDIChildFrame::Restore() 
 351 void wxMDIChildFrame::Activate() 
 355 //----------------------------------------------------------------------------- 
 357 //----------------------------------------------------------------------------- 
 359 wxMDIClientWindow::wxMDIClientWindow() 
 363 wxMDIClientWindow::~wxMDIClientWindow() 
 368 bool wxMDIClientWindow::CreateClient(wxMDIParentFrame 
*parent
, long style
) 
 371     m_windowId 
= (int)NewControlId(); 
 375         parent
->AddChild(this); 
 377     m_backgroundColour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
); 
 379     wxModelessWindows
.Append(this); 
 383 // Get size *available for subwindows* i.e. excluding menu bar. 
 384 void wxMDIClientWindow::DoGetClientSize(int *x
, int *y
) const 
 386     wxDisplaySize( x 
, y 
) ; 
 389 // Explicitly call default scroll behaviour 
 390 void wxMDIClientWindow::OnScroll(wxScrollEvent
& event
)