]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/mdi.cpp
fix for -Wundef warning
[wxWidgets.git] / src / mac / carbon / mdi.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: mdi.cpp
3// Purpose: MDI classes
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
65571936 9// Licence: wxWindows licence
e9576ca5
SC
10/////////////////////////////////////////////////////////////////////////////
11
3d1a4878 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
e9576ca5
SC
13#pragma implementation "mdi.h"
14#endif
15
3d1a4878
SC
16#include "wx/wxprec.h"
17
179e085f
RN
18#if wxUSE_MDI
19
e9576ca5
SC
20#include "wx/mdi.h"
21#include "wx/menu.h"
22#include "wx/settings.h"
70024cfb 23#include "wx/log.h"
e9576ca5 24
76a5e5d2 25#include "wx/mac/private.h"
70024cfb 26#include "wx/mac/uma.h"
76a5e5d2 27
fe08e597 28extern wxWindowList wxModelessWindows;
e9576ca5 29
e9576ca5
SC
30IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame)
31IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
32IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
33
34BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
e9576ca5
SC
35 EVT_ACTIVATE(wxMDIParentFrame::OnActivate)
36 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
37END_EVENT_TABLE()
38
39BEGIN_EVENT_TABLE(wxMDIClientWindow, wxWindow)
40 EVT_SCROLL(wxMDIClientWindow::OnScroll)
41END_EVENT_TABLE()
42
fd8278bf
VZ
43static const wxChar *TRACE_MDI = _T("mdi");
44
0a67a93b
SC
45static const int IDM_WINDOWTILE = 4001;
46static const int IDM_WINDOWTILEHOR = 4001;
47static const int IDM_WINDOWCASCADE = 4002;
48static const int IDM_WINDOWICONS = 4003;
49static const int IDM_WINDOWNEXT = 4004;
50static const int IDM_WINDOWTILEVERT = 4005;
4f3b37fd 51static const int IDM_WINDOWPREV = 4006;
0a67a93b
SC
52
53// This range gives a maximum of 500 MDI children. Should be enough :-)
54static const int wxFIRST_MDI_CHILD = 4100;
55static const int wxLAST_MDI_CHILD = 4600;
56
57// Status border dimensions
58static const int wxTHICK_LINE_BORDER = 3;
59
a57ac1c4 60// ----------------------------------------------------------------------------
e9576ca5 61// Parent frame
a57ac1c4 62// ----------------------------------------------------------------------------
e9576ca5 63
a57ac1c4 64void wxMDIParentFrame::Init()
e9576ca5 65{
0a67a93b
SC
66 m_clientWindow = NULL;
67 m_currentChild = NULL;
68 m_windowMenu = (wxMenu*) NULL;
a57ac1c4
VZ
69 m_parentFrameActive = true;
70 m_shouldBeShown = false;
e9576ca5
SC
71}
72
73bool wxMDIParentFrame::Create(wxWindow *parent,
a57ac1c4
VZ
74 wxWindowID id,
75 const wxString& title,
76 const wxPoint& pos,
77 const wxSize& size,
78 long style,
79 const wxString& name)
e9576ca5 80{
e40298d5
JS
81 // this style can be used to prevent a window from having the standard MDI
82 // "Window" menu
83 if ( style & wxFRAME_NO_WINDOW_MENU )
84 {
85 m_windowMenu = (wxMenu *)NULL;
86 style -= wxFRAME_NO_WINDOW_MENU ;
87 }
88 else // normal case: we have the window menu, so construct it
89 {
90 m_windowMenu = new wxMenu;
0a67a93b 91
e40298d5
JS
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"));
98 }
99
70024cfb 100 wxFrame::Create( parent , id , title , pos , size , style , name ) ;
a57ac1c4 101 m_parentFrameActive = true;
e40298d5
JS
102
103 OnCreateClient();
104
a57ac1c4 105 return true;
e9576ca5
SC
106}
107
108wxMDIParentFrame::~wxMDIParentFrame()
109{
0a67a93b 110 DestroyChildren();
ea3cdc4f 111 // already deleted by DestroyChildren()
0a67a93b 112 m_clientWindow = NULL ;
e40298d5 113
ea3cdc4f 114 delete m_windowMenu;
e9576ca5
SC
115}
116
0a67a93b 117
e9576ca5
SC
118void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar)
119{
e40298d5 120 wxFrame::SetMenuBar( menu_bar ) ;
e9576ca5
SC
121}
122
0bba37f5
DE
123void wxMDIParentFrame::GetRectForTopLevelChildren(int *x, int *y, int *w, int *h)
124{
125 if(x)
126 *x = 0;
127 if(y)
128 *y = 0;
129 wxDisplaySize(w,h);
130}
131
a57ac1c4
VZ
132void wxMDIParentFrame::AddChild(wxWindowBase *child)
133{
134 if ( !m_currentChild )
135 {
136 m_currentChild = wxDynamicCast(child, wxMDIChildFrame);
137
138 if ( m_currentChild && IsShown() && ShouldBeVisible() )
139 {
140 }
141 }
142
143 wxFrame::AddChild(child);
144}
145
146void wxMDIParentFrame::RemoveChild(wxWindowBase *child)
147{
148 if ( child == m_currentChild )
149 {
150 // the current child isn't active any more, try to find another one
151 m_currentChild = NULL;
152
153 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
154 node;
155 node = node->GetNext() )
156 {
157 wxMDIChildFrame *
158 childCur = wxDynamicCast(node->GetData(), wxMDIChildFrame);
159 if ( childCur != child )
160 {
161 m_currentChild = childCur;
162 break;
163 }
164 }
165 }
166
167 wxFrame::RemoveChild(child);
168
169 // if there are no more children left we need to show the frame if we
170 // hadn't shown it before because there were active children and it was
171 // useless (note that we have to do it after fully removing the child, i.e.
172 // after calling the base class RemoveChild() as otherwise we risk to touch
173 // pointer to the child being deleted)
174 if ( !m_currentChild && m_shouldBeShown && !IsShown() )
175 {
176 // we have to show it, but at least move it out of sight and make it of
177 // smallest possible size (unfortunately (0, 0) doesn't work so that it
178 // doesn't appear in expose
179 SetSize(-10000, -10000, 1, 1);
180 Show();
181 }
182}
183
70024cfb 184void wxMDIParentFrame::MacActivate(long timestamp, bool activating)
e9576ca5 185{
fd8278bf 186 wxLogTrace(TRACE_MDI, wxT("MDI PARENT=%p MacActivate(0x%08lx,%s)"),this,timestamp,activating?wxT("ACTIV"):wxT("deact"));
70024cfb 187 if(activating)
e40298d5 188 {
70024cfb
DE
189 if(s_macDeactivateWindow && s_macDeactivateWindow->GetParent()==this)
190 {
fd8278bf 191 wxLogTrace(TRACE_MDI, wxT("child had been scheduled for deactivation, rehighlighting"));
70024cfb 192 UMAHighlightAndActivateWindow((WindowRef)s_macDeactivateWindow->MacGetWindowRef(), true);
fd8278bf 193 wxLogTrace(TRACE_MDI, wxT("done highliting child"));
70024cfb
DE
194 s_macDeactivateWindow = NULL;
195 }
196 else if(s_macDeactivateWindow == this)
197 {
fd8278bf 198 wxLogTrace(TRACE_MDI, wxT("Avoided deactivation/activation of this=%p"), this);
70024cfb
DE
199 s_macDeactivateWindow = NULL;
200 }
201 else // window to deactivate is NULL or is not us or one of our kids
202 {
203 // activate kid instead
204 if(m_currentChild)
205 m_currentChild->MacActivate(timestamp,activating);
206 else
207 wxFrame::MacActivate(timestamp,activating);
208 }
e40298d5 209 }
70024cfb 210 else
e40298d5 211 {
70024cfb
DE
212 // We were scheduled for deactivation, and now we do it.
213 if(s_macDeactivateWindow==this)
e40298d5 214 {
70024cfb
DE
215 s_macDeactivateWindow = NULL;
216 if(m_currentChild)
217 m_currentChild->MacActivate(timestamp,activating);
218 wxFrame::MacActivate(timestamp,activating);
219 }
220 else // schedule ourselves for deactivation
221 {
222 if(s_macDeactivateWindow)
fd8278bf
VZ
223 wxLogTrace(TRACE_MDI, wxT("window=%p SHOULD have been deactivated, oh well!"),s_macDeactivateWindow);
224 wxLogTrace(TRACE_MDI, wxT("Scheduling delayed MDI Parent deactivation"));
70024cfb 225 s_macDeactivateWindow = this;
e40298d5 226 }
e40298d5 227 }
e9576ca5
SC
228}
229
70024cfb
DE
230void wxMDIParentFrame::OnActivate(wxActivateEvent& event)
231{
232 event.Skip();
233}
234
e9576ca5
SC
235// Returns the active MDI child window
236wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
237{
e40298d5 238 return m_currentChild ;
e9576ca5
SC
239}
240
241// Create the client window class (don't Create the window,
242// just return a new class)
243wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
244{
0a67a93b
SC
245 m_clientWindow = new wxMDIClientWindow( this );
246 return m_clientWindow;
e9576ca5
SC
247}
248
249// Responds to colour changes, and passes event on to children.
250void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
251{
252 // TODO
e40298d5 253
e9576ca5
SC
254 // Propagate the event to the non-top-level children
255 wxFrame::OnSysColourChanged(event);
256}
257
258// MDI operations
259void wxMDIParentFrame::Cascade()
260{
261 // TODO
262}
263
0d97c090 264void wxMDIParentFrame::Tile(wxOrientation WXUNUSED(orient))
e9576ca5
SC
265{
266 // TODO
267}
268
269void wxMDIParentFrame::ArrangeIcons()
270{
271 // TODO
272}
273
274void wxMDIParentFrame::ActivateNext()
275{
276 // TODO
277}
278
279void wxMDIParentFrame::ActivatePrevious()
280{
281 // TODO
282}
283
a57ac1c4
VZ
284bool wxMDIParentFrame::ShouldBeVisible() const
285{
286 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
287 node;
288 node = node->GetNext() )
289 {
290 if ( !wxDynamicCast(node->GetData(), wxMDIChildFrame)
291#if wxUSE_STATUSBAR
292 && node->GetData() != GetStatusBar()
293#endif // wxUSE_STATUSBAR
294 && node->GetData() != GetClientWindow() )
295 {
296 // if we have a non-MDI child, do remain visible so that it could
297 // be used
298 return true;
299 }
300 }
301
302 return false;
303}
304
29e92efb
VZ
305bool wxMDIParentFrame::Show( bool show )
306{
a57ac1c4
VZ
307 m_shouldBeShown = false;
308
29e92efb
VZ
309 // don't really show the MDI frame unless it has any children other than
310 // MDI children as it is pretty useless in this case
507ad426 311
29e92efb
VZ
312 if ( show )
313 {
a57ac1c4 314 if ( !ShouldBeVisible() && m_currentChild )
4a60e3f0 315 {
a57ac1c4
VZ
316 // don't make the window visible now but remember that we should
317 // have had done it
318 m_shouldBeShown = true;
319 return false;
4a60e3f0 320 }
29e92efb
VZ
321 }
322
a57ac1c4 323 return wxFrame::Show(show);
29e92efb
VZ
324}
325
a57ac1c4 326// ----------------------------------------------------------------------------
e9576ca5 327// Child frame
a57ac1c4 328// ----------------------------------------------------------------------------
e9576ca5
SC
329
330wxMDIChildFrame::wxMDIChildFrame()
0a67a93b
SC
331{
332 Init() ;
333}
334void wxMDIChildFrame::Init()
e9576ca5
SC
335{
336}
337
338bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
e40298d5
JS
339 wxWindowID id,
340 const wxString& title,
341 const wxPoint& pos,
342 const wxSize& size,
343 long style,
344 const wxString& name)
e9576ca5
SC
345{
346 SetName(name);
e40298d5 347
e9576ca5
SC
348 if ( id > -1 )
349 m_windowId = id;
350 else
351 m_windowId = (int)NewControlId();
e40298d5 352
e9576ca5 353 if (parent) parent->AddChild(this);
e40298d5
JS
354
355 MacCreateRealWindow( title, pos , size , MacRemoveBordersFromStyle(style) , name ) ;
356
facd6764
SC
357 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
358
e9576ca5 359 wxModelessWindows.Append(this);
a57ac1c4 360 return false;
e9576ca5
SC
361}
362
363wxMDIChildFrame::~wxMDIChildFrame()
364{
0a67a93b 365 DestroyChildren();
e9576ca5
SC
366}
367
368void wxMDIChildFrame::SetMenuBar(wxMenuBar *menu_bar)
369{
e40298d5 370 return wxFrame::SetMenuBar( menu_bar ) ;
e9576ca5
SC
371}
372
70024cfb
DE
373void wxMDIChildFrame::MacActivate(long timestamp, bool activating)
374{
fd8278bf 375 wxLogTrace(TRACE_MDI, wxT("MDI child=%p MacActivate(0x%08lx,%s)"),this,timestamp,activating?wxT("ACTIV"):wxT("deact"));
70024cfb
DE
376 wxMDIParentFrame *mdiparent = wxDynamicCast(m_parent, wxMDIParentFrame);
377 wxASSERT(mdiparent);
378 if(activating)
379 {
380 if(s_macDeactivateWindow == m_parent)
381 {
fd8278bf 382 wxLogTrace(TRACE_MDI, wxT("parent had been scheduled for deactivation, rehighlighting"));
70024cfb 383 UMAHighlightAndActivateWindow((WindowRef)s_macDeactivateWindow->MacGetWindowRef(), true);
fd8278bf 384 wxLogTrace(TRACE_MDI, wxT("done highliting parent"));
70024cfb
DE
385 s_macDeactivateWindow = NULL;
386 }
387 else if((mdiparent->m_currentChild==this) || !s_macDeactivateWindow)
388 mdiparent->wxFrame::MacActivate(timestamp,activating);
389
390 if(mdiparent->m_currentChild && mdiparent->m_currentChild!=this)
391 mdiparent->m_currentChild->wxFrame::MacActivate(timestamp,false);
392 mdiparent->m_currentChild = this;
393
394 if(s_macDeactivateWindow==this)
395 {
fd8278bf 396 wxLogTrace(TRACE_MDI, wxT("Avoided deactivation/activation of this=%p"),this);
70024cfb
DE
397 s_macDeactivateWindow=NULL;
398 }
399 else
400 wxFrame::MacActivate(timestamp, activating);
401 }
402 else
403 {
404 // We were scheduled for deactivation, and now we do it.
405 if(s_macDeactivateWindow==this)
406 {
407 s_macDeactivateWindow = NULL;
408 wxFrame::MacActivate(timestamp,activating);
409 if(mdiparent->m_currentChild==this)
410 mdiparent->wxFrame::MacActivate(timestamp,activating);
411 }
412 else // schedule ourselves for deactivation
413 {
414 if(s_macDeactivateWindow)
fd8278bf
VZ
415 wxLogTrace(TRACE_MDI, wxT("window=%p SHOULD have been deactivated, oh well!"),s_macDeactivateWindow);
416 wxLogTrace(TRACE_MDI, wxT("Scheduling delayed deactivation"));
70024cfb
DE
417 s_macDeactivateWindow = this;
418 }
419 }
420}
421
e9576ca5
SC
422// MDI operations
423void wxMDIChildFrame::Maximize()
424{
0a67a93b 425 wxFrame::Maximize() ;
e9576ca5
SC
426}
427
428void wxMDIChildFrame::Restore()
429{
0a67a93b 430 wxFrame::Restore() ;
e9576ca5
SC
431}
432
433void wxMDIChildFrame::Activate()
434{
e9576ca5
SC
435}
436
0a67a93b
SC
437//-----------------------------------------------------------------------------
438// wxMDIClientWindow
439//-----------------------------------------------------------------------------
e9576ca5
SC
440
441wxMDIClientWindow::wxMDIClientWindow()
442{
443}
444
445wxMDIClientWindow::~wxMDIClientWindow()
446{
0a67a93b 447 DestroyChildren();
e9576ca5
SC
448}
449
450bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
451{
84be293d 452 if ( !wxWindow::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style))
a57ac1c4 453 return false;
e40298d5 454
0a67a93b 455 wxModelessWindows.Append(this);
a57ac1c4 456 return true;
e9576ca5
SC
457}
458
be7a1013
DE
459// Get size *available for subwindows* i.e. excluding menu bar.
460void wxMDIClientWindow::DoGetClientSize(int *x, int *y) const
461{
462 wxDisplaySize( x , y ) ;
463}
464
e9576ca5
SC
465// Explicitly call default scroll behaviour
466void wxMDIClientWindow::OnScroll(wxScrollEvent& event)
467{
e9576ca5
SC
468}
469
a57ac1c4 470#endif // wxUSE_MDI
179e085f 471