1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: MDI classes
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "mdi.h"
16 #include "wx/wxprec.h"
22 #include "wx/settings.h"
25 #include "wx/mac/private.h"
26 #include "wx/mac/uma.h"
28 extern wxWindowList wxModelessWindows
;
30 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame
, wxFrame
)
31 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame
, wxFrame
)
32 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow
, wxWindow
)
34 BEGIN_EVENT_TABLE(wxMDIParentFrame
, wxFrame
)
35 EVT_ACTIVATE(wxMDIParentFrame::OnActivate
)
36 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged
)
39 BEGIN_EVENT_TABLE(wxMDIClientWindow
, wxWindow
)
40 EVT_SCROLL(wxMDIClientWindow::OnScroll
)
43 static const wxChar
*TRACE_MDI
= _T("mdi");
45 static const int IDM_WINDOWTILE
= 4001;
46 static const int IDM_WINDOWTILEHOR
= 4001;
47 static const int IDM_WINDOWCASCADE
= 4002;
48 static const int IDM_WINDOWICONS
= 4003;
49 static const int IDM_WINDOWNEXT
= 4004;
50 static const int IDM_WINDOWTILEVERT
= 4005;
51 static const int IDM_WINDOWPREV
= 4006;
53 // This range gives a maximum of 500 MDI children. Should be enough :-)
54 static const int wxFIRST_MDI_CHILD
= 4100;
55 static const int wxLAST_MDI_CHILD
= 4600;
57 // Status border dimensions
58 static const int wxTHICK_LINE_BORDER
= 3;
62 wxMDIParentFrame::wxMDIParentFrame()
64 m_clientWindow
= NULL
;
65 m_currentChild
= NULL
;
66 m_windowMenu
= (wxMenu
*) NULL
;
67 m_parentFrameActive
= TRUE
;
70 bool wxMDIParentFrame::Create(wxWindow
*parent
,
72 const wxString
& title
,
78 m_clientWindow
= NULL
;
79 m_currentChild
= NULL
;
81 // this style can be used to prevent a window from having the standard MDI
83 if ( style
& wxFRAME_NO_WINDOW_MENU
)
85 m_windowMenu
= (wxMenu
*)NULL
;
86 style
-= wxFRAME_NO_WINDOW_MENU
;
88 else // normal case: we have the window menu, so construct it
90 m_windowMenu
= new wxMenu
;
92 m_windowMenu
->Append(IDM_WINDOWCASCADE
, wxT("&Cascade"));
93 m_windowMenu
->Append(IDM_WINDOWTILEHOR
, wxT("Tile &Horizontally"));
94 m_windowMenu
->Append(IDM_WINDOWTILEVERT
, wxT("Tile &Vertically"));
95 m_windowMenu
->AppendSeparator();
96 m_windowMenu
->Append(IDM_WINDOWICONS
, wxT("&Arrange Icons"));
97 m_windowMenu
->Append(IDM_WINDOWNEXT
, wxT("&Next"));
100 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
) ;
101 m_parentFrameActive
= TRUE
;
108 wxMDIParentFrame::~wxMDIParentFrame()
111 // already deleted by DestroyChildren()
112 m_clientWindow
= NULL
;
118 void wxMDIParentFrame::SetMenuBar(wxMenuBar
*menu_bar
)
120 wxFrame::SetMenuBar( menu_bar
) ;
123 void wxMDIParentFrame::GetRectForTopLevelChildren(int *x
, int *y
, int *w
, int *h
)
132 void wxMDIParentFrame::MacActivate(long timestamp
, bool activating
)
134 wxLogTrace(TRACE_MDI
, wxT("MDI PARENT=%p MacActivate(0x%08lx,%s)"),this,timestamp
,activating
?wxT("ACTIV"):wxT("deact"));
137 if(s_macDeactivateWindow
&& s_macDeactivateWindow
->GetParent()==this)
139 wxLogTrace(TRACE_MDI
, wxT("child had been scheduled for deactivation, rehighlighting"));
140 UMAHighlightAndActivateWindow((WindowRef
)s_macDeactivateWindow
->MacGetWindowRef(), true);
141 wxLogTrace(TRACE_MDI
, wxT("done highliting child"));
142 s_macDeactivateWindow
= NULL
;
144 else if(s_macDeactivateWindow
== this)
146 wxLogTrace(TRACE_MDI
, wxT("Avoided deactivation/activation of this=%p"), this);
147 s_macDeactivateWindow
= NULL
;
149 else // window to deactivate is NULL or is not us or one of our kids
151 // activate kid instead
153 m_currentChild
->MacActivate(timestamp
,activating
);
155 wxFrame::MacActivate(timestamp
,activating
);
160 // We were scheduled for deactivation, and now we do it.
161 if(s_macDeactivateWindow
==this)
163 s_macDeactivateWindow
= NULL
;
165 m_currentChild
->MacActivate(timestamp
,activating
);
166 wxFrame::MacActivate(timestamp
,activating
);
168 else // schedule ourselves for deactivation
170 if(s_macDeactivateWindow
)
171 wxLogTrace(TRACE_MDI
, wxT("window=%p SHOULD have been deactivated, oh well!"),s_macDeactivateWindow
);
172 wxLogTrace(TRACE_MDI
, wxT("Scheduling delayed MDI Parent deactivation"));
173 s_macDeactivateWindow
= this;
178 void wxMDIParentFrame::OnActivate(wxActivateEvent
& event
)
183 // Returns the active MDI child window
184 wxMDIChildFrame
*wxMDIParentFrame::GetActiveChild() const
186 return m_currentChild
;
189 // Create the client window class (don't Create the window,
190 // just return a new class)
191 wxMDIClientWindow
*wxMDIParentFrame::OnCreateClient()
193 m_clientWindow
= new wxMDIClientWindow( this );
194 return m_clientWindow
;
197 // Responds to colour changes, and passes event on to children.
198 void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent
& event
)
202 // Propagate the event to the non-top-level children
203 wxFrame::OnSysColourChanged(event
);
207 void wxMDIParentFrame::Cascade()
212 void wxMDIParentFrame::Tile(wxOrientation
WXUNUSED(orient
))
217 void wxMDIParentFrame::ArrangeIcons()
222 void wxMDIParentFrame::ActivateNext()
227 void wxMDIParentFrame::ActivatePrevious()
232 bool wxMDIParentFrame::Show( bool show
)
234 // don't really show the MDI frame unless it has any children other than
235 // MDI children as it is pretty useless in this case
239 // TODO: check for other children
242 // call the base class version to just update the flag but don't
243 // really make the window visible
244 return wxFrameBase::Show();
248 if ( !wxFrame::Show(show
) )
256 wxMDIChildFrame::wxMDIChildFrame()
260 void wxMDIChildFrame::Init()
264 bool wxMDIChildFrame::Create(wxMDIParentFrame
*parent
,
266 const wxString
& title
,
270 const wxString
& name
)
277 m_windowId
= (int)NewControlId();
279 if (parent
) parent
->AddChild(this);
281 MacCreateRealWindow( title
, pos
, size
, MacRemoveBordersFromStyle(style
) , name
) ;
283 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
));
285 wxModelessWindows
.Append(this);
289 wxMDIChildFrame::~wxMDIChildFrame()
291 wxMDIParentFrame
*mdiparent
= wxDynamicCast(m_parent
, wxMDIParentFrame
);
293 if(mdiparent
->m_currentChild
== this)
294 mdiparent
->m_currentChild
= NULL
;
298 void wxMDIChildFrame::SetMenuBar(wxMenuBar
*menu_bar
)
300 return wxFrame::SetMenuBar( menu_bar
) ;
303 void wxMDIChildFrame::MacActivate(long timestamp
, bool activating
)
305 wxLogTrace(TRACE_MDI
, wxT("MDI child=%p MacActivate(0x%08lx,%s)"),this,timestamp
,activating
?wxT("ACTIV"):wxT("deact"));
306 wxMDIParentFrame
*mdiparent
= wxDynamicCast(m_parent
, wxMDIParentFrame
);
310 if(s_macDeactivateWindow
== m_parent
)
312 wxLogTrace(TRACE_MDI
, wxT("parent had been scheduled for deactivation, rehighlighting"));
313 UMAHighlightAndActivateWindow((WindowRef
)s_macDeactivateWindow
->MacGetWindowRef(), true);
314 wxLogTrace(TRACE_MDI
, wxT("done highliting parent"));
315 s_macDeactivateWindow
= NULL
;
317 else if((mdiparent
->m_currentChild
==this) || !s_macDeactivateWindow
)
318 mdiparent
->wxFrame::MacActivate(timestamp
,activating
);
320 if(mdiparent
->m_currentChild
&& mdiparent
->m_currentChild
!=this)
321 mdiparent
->m_currentChild
->wxFrame::MacActivate(timestamp
,false);
322 mdiparent
->m_currentChild
= this;
324 if(s_macDeactivateWindow
==this)
326 wxLogTrace(TRACE_MDI
, wxT("Avoided deactivation/activation of this=%p"),this);
327 s_macDeactivateWindow
=NULL
;
330 wxFrame::MacActivate(timestamp
, activating
);
334 // We were scheduled for deactivation, and now we do it.
335 if(s_macDeactivateWindow
==this)
337 s_macDeactivateWindow
= NULL
;
338 wxFrame::MacActivate(timestamp
,activating
);
339 if(mdiparent
->m_currentChild
==this)
340 mdiparent
->wxFrame::MacActivate(timestamp
,activating
);
342 else // schedule ourselves for deactivation
344 if(s_macDeactivateWindow
)
345 wxLogTrace(TRACE_MDI
, wxT("window=%p SHOULD have been deactivated, oh well!"),s_macDeactivateWindow
);
346 wxLogTrace(TRACE_MDI
, wxT("Scheduling delayed deactivation"));
347 s_macDeactivateWindow
= this;
353 void wxMDIChildFrame::Maximize()
355 wxFrame::Maximize() ;
358 void wxMDIChildFrame::Restore()
363 void wxMDIChildFrame::Activate()
367 //-----------------------------------------------------------------------------
369 //-----------------------------------------------------------------------------
371 wxMDIClientWindow::wxMDIClientWindow()
375 wxMDIClientWindow::~wxMDIClientWindow()
380 bool wxMDIClientWindow::CreateClient(wxMDIParentFrame
*parent
, long style
)
382 if ( !wxWindow::Create(parent
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, style
))
385 wxModelessWindows
.Append(this);
389 // Get size *available for subwindows* i.e. excluding menu bar.
390 void wxMDIClientWindow::DoGetClientSize(int *x
, int *y
) const
392 wxDisplaySize( x
, y
) ;
395 // Explicitly call default scroll behaviour
396 void wxMDIClientWindow::OnScroll(wxScrollEvent
& event
)