]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/mdi.cpp
avoid setting initial position if it was not specified, broken in r70734
[wxWidgets.git] / src / osx / carbon / mdi.cpp
CommitLineData
489468fe 1/////////////////////////////////////////////////////////////////////////////
524c47aa 2// Name: src/osx/carbon/mdi.cpp
489468fe
SC
3// Purpose: MDI classes
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
489468fe
SC
7// Copyright: (c) Stefan Csomor
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#include "wx/wxprec.h"
12
13#if wxUSE_MDI
14
15#include "wx/mdi.h"
16
17#ifndef WX_PRECOMP
18 #include "wx/log.h"
19 #include "wx/menu.h"
20 #include "wx/settings.h"
21 #include "wx/statusbr.h"
22#endif
23
1f0c8f31
SC
24#include "wx/osx/private.h"
25#include "wx/osx/uma.h"
489468fe
SC
26
27IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame)
28IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
29IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
30
31BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
32 EVT_ACTIVATE(wxMDIParentFrame::OnActivate)
33 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
34END_EVENT_TABLE()
35
489468fe
SC
36#define TRACE_MDI "mdi"
37
38static const int IDM_WINDOWTILEHOR = 4001;
39static const int IDM_WINDOWCASCADE = 4002;
40static const int IDM_WINDOWICONS = 4003;
41static const int IDM_WINDOWNEXT = 4004;
42static const int IDM_WINDOWTILEVERT = 4005;
43
44// others
45
46void UMAHighlightAndActivateWindow( WindowRef inWindowRef , bool inActivate )
47{
cfea8e61 48#if wxOSX_USE_CARBON // TODO REMOVE
489468fe
SC
49 if ( inWindowRef )
50 {
51// bool isHighlighted = IsWindowHighlited( inWindowRef ) ;
52// if ( inActivate != isHighlighted )
53#ifndef __LP64__
54 GrafPtr port ;
55 GetPort( &port ) ;
56 SetPortWindowPort( inWindowRef ) ;
57#endif
58 HiliteWindow( inWindowRef , inActivate ) ;
59 ControlRef control = NULL ;
60 ::GetRootControl( inWindowRef , &control ) ;
61 if ( control )
62 {
63 if ( inActivate )
64 ::ActivateControl( control ) ;
65 else
66 ::DeactivateControl( control ) ;
67 }
68#ifndef __LP64__
69 SetPort( port ) ;
70#endif
71 }
cfea8e61 72#elif defined(wxOSX_USE_COCOA)
de0d2095
SC
73 wxUnusedVar(inActivate);
74 wxUnusedVar(inWindowRef);
cfea8e61 75// TODO: implement me!
489468fe
SC
76#endif
77}
78
79// ----------------------------------------------------------------------------
80// Parent frame
81// ----------------------------------------------------------------------------
82
83void wxMDIParentFrame::Init()
84{
489468fe
SC
85 m_parentFrameActive = true;
86 m_shouldBeShown = false;
87}
88
89bool wxMDIParentFrame::Create(wxWindow *parent,
c1ec7ee8 90 wxWindowID winid,
489468fe
SC
91 const wxString& title,
92 const wxPoint& pos,
93 const wxSize& size,
94 long style,
95 const wxString& name)
96{
97 // this style can be used to prevent a window from having the standard MDI
98 // "Window" menu
99 if ( style & wxFRAME_NO_WINDOW_MENU )
100 {
d2824cdb 101 m_windowMenu = NULL;
489468fe
SC
102 style -= wxFRAME_NO_WINDOW_MENU ;
103 }
104 else // normal case: we have the window menu, so construct it
105 {
106 m_windowMenu = new wxMenu;
107
108 m_windowMenu->Append(IDM_WINDOWCASCADE, wxT("&Cascade"));
109 m_windowMenu->Append(IDM_WINDOWTILEHOR, wxT("Tile &Horizontally"));
110 m_windowMenu->Append(IDM_WINDOWTILEVERT, wxT("Tile &Vertically"));
111 m_windowMenu->AppendSeparator();
112 m_windowMenu->Append(IDM_WINDOWICONS, wxT("&Arrange Icons"));
113 m_windowMenu->Append(IDM_WINDOWNEXT, wxT("&Next"));
114 }
115
c1ec7ee8 116 if ( !wxFrame::Create( parent , winid , title , pos , size , style , name ) )
489468fe
SC
117 return false;
118
119 m_parentFrameActive = true;
120
121 m_clientWindow = OnCreateClient();
daa9c577
VZ
122 if ( !m_clientWindow || !m_clientWindow->CreateClient(this, style) )
123 return false;
489468fe 124
daa9c577 125 return true;
489468fe
SC
126}
127
128wxMDIParentFrame::~wxMDIParentFrame()
129{
130 DestroyChildren();
131
132 // already deleted by DestroyChildren()
133 m_clientWindow = NULL ;
489468fe
SC
134}
135
136void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar)
137{
138 wxFrame::SetMenuBar( menu_bar ) ;
139}
140
141void wxMDIParentFrame::GetRectForTopLevelChildren(int *x, int *y, int *w, int *h)
142{
143 if (x)
144 *x = 0;
145 if (y)
146 *y = 0;
147
148 wxDisplaySize(w, h);
149}
150
151void wxMDIParentFrame::AddChild(wxWindowBase *child)
152{
153 // moved this to front, so that we don't run into unset m_parent problems later
154 wxFrame::AddChild(child);
155
156 if ( !m_currentChild )
157 {
158 m_currentChild = wxDynamicCast(child, wxMDIChildFrame);
159
160 if ( m_currentChild && IsShown() && !ShouldBeVisible() )
161 {
162 // we shouldn't remain visible any more
163 wxFrame::Show(false);
164 m_shouldBeShown = true;
165 }
166 }
167}
168
169void wxMDIParentFrame::RemoveChild(wxWindowBase *child)
170{
171 if ( child == m_currentChild )
172 {
173 // the current child isn't active any more, try to find another one
174 m_currentChild = NULL;
175
176 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
177 node;
178 node = node->GetNext() )
179 {
180 wxMDIChildFrame *
181 childCur = wxDynamicCast(node->GetData(), wxMDIChildFrame);
182 if ( childCur != child )
183 {
184 m_currentChild = childCur;
185 break;
186 }
187 }
188 }
189
190 wxFrame::RemoveChild(child);
191
192 // if there are no more children left we need to show the frame if we
193 // hadn't shown it before because there were active children and it was
194 // useless (note that we have to do it after fully removing the child, i.e.
195 // after calling the base class RemoveChild() as otherwise we risk to touch
196 // pointer to the child being deleted)
197 if ( !m_currentChild && m_shouldBeShown && !IsShown() )
198 {
199 // we have to show it, but at least move it out of sight and make it of
200 // smallest possible size (unfortunately (0, 0) doesn't work so that it
201 // doesn't appear in expose
202 SetSize(-10000, -10000, 1, 1);
203 Show();
204 }
205}
206
207void wxMDIParentFrame::MacActivate(long timestamp, bool activating)
208{
209 wxLogTrace(TRACE_MDI, wxT("MDI PARENT=%p MacActivate(0x%08lx,%s)"), this, timestamp, activating ? wxT("ACTIV") : wxT("deact"));
210
211 if (activating)
212 {
213 if (s_macDeactivateWindow && s_macDeactivateWindow->GetParent() == this)
214 {
215 wxLogTrace(TRACE_MDI, wxT("child had been scheduled for deactivation, rehighlighting"));
216
b2680ced 217 UMAHighlightAndActivateWindow((WindowRef)s_macDeactivateWindow->GetWXWindow(), true);
489468fe
SC
218
219 wxLogTrace(TRACE_MDI, wxT("finished highliting child"));
220
221 s_macDeactivateWindow = NULL;
222 }
223 else if (s_macDeactivateWindow == this)
224 {
225 wxLogTrace(TRACE_MDI, wxT("Avoided deactivation/activation of this=%p"), this);
226
227 s_macDeactivateWindow = NULL;
228 }
229 else // window to deactivate is NULL or is not us or one of our kids
230 {
231 // activate kid instead
232 if (m_currentChild)
233 m_currentChild->MacActivate(timestamp, activating);
234 else
235 wxFrame::MacActivate(timestamp, activating);
236 }
237 }
238 else
239 {
240 // We were scheduled for deactivation, and now we do it.
241 if (s_macDeactivateWindow == this)
242 {
243 s_macDeactivateWindow = NULL;
244 if (m_currentChild)
245 m_currentChild->MacActivate(timestamp, activating);
246 wxFrame::MacActivate(timestamp, activating);
247 }
248 else // schedule ourselves for deactivation
249 {
250 if (s_macDeactivateWindow)
43b2d5e7 251 {
489468fe 252 wxLogTrace(TRACE_MDI, wxT("window=%p SHOULD have been deactivated, oh well!"), s_macDeactivateWindow);
43b2d5e7 253 }
489468fe
SC
254 wxLogTrace(TRACE_MDI, wxT("Scheduling delayed MDI Parent deactivation"));
255
256 s_macDeactivateWindow = this;
257 }
258 }
259}
260
261void wxMDIParentFrame::OnActivate(wxActivateEvent& event)
262{
263 event.Skip();
264}
265
489468fe
SC
266// Responds to colour changes, and passes event on to children.
267void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
268{
269 // TODO
270
271 // Propagate the event to the non-top-level children
272 wxFrame::OnSysColourChanged(event);
273}
274
489468fe
SC
275bool wxMDIParentFrame::ShouldBeVisible() const
276{
277 for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
278 node;
279 node = node->GetNext() )
280 {
281 wxWindow *win = node->GetData();
282
283 if ( win->IsShown()
284 && !wxDynamicCast(win, wxMDIChildFrame)
285#if wxUSE_STATUSBAR
286 && win != (wxWindow*) GetStatusBar()
287#endif
288 && win != GetClientWindow() )
289 {
290 // if we have a non-MDI child, do remain visible so that it could
291 // be used
292 return true;
293 }
294 }
295
296 return false;
297}
298
299bool wxMDIParentFrame::Show( bool show )
300{
301 m_shouldBeShown = false;
302
303 // don't really show the MDI frame unless it has any children other than
304 // MDI children as it is pretty useless in this case
305
306 if ( show )
307 {
308 if ( !ShouldBeVisible() && m_currentChild )
309 {
310 // don't make the window visible now but remember that we should
311 // have had done it
312 m_shouldBeShown = true;
313
314 return false;
315 }
316 }
317
318 return wxFrame::Show(show);
319}
320
321// ----------------------------------------------------------------------------
322// Child frame
323// ----------------------------------------------------------------------------
324
489468fe
SC
325void wxMDIChildFrame::Init()
326{
327}
328
329bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
c1ec7ee8 330 wxWindowID winid,
489468fe
SC
331 const wxString& title,
332 const wxPoint& pos,
333 const wxSize& size,
334 long style,
335 const wxString& name)
336{
d2824cdb
VZ
337 m_mdiParent = parent;
338
489468fe
SC
339 SetName(name);
340
c1ec7ee8
SC
341 if ( winid == wxID_ANY )
342 winid = (int)NewControlId();
489468fe 343
c1ec7ee8 344 wxNonOwnedWindow::Create( parent, winid, pos , size , MacRemoveBordersFromStyle(style) , name ) ;
d2824cdb 345
489468fe
SC
346 SetTitle( title );
347
348 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
349
350 return true;
351}
352
353wxMDIChildFrame::~wxMDIChildFrame()
354{
355 DestroyChildren();
356}
357
489468fe
SC
358void wxMDIChildFrame::MacActivate(long timestamp, bool activating)
359{
360 wxLogTrace(TRACE_MDI, wxT("MDI child=%p MacActivate(0x%08lx,%s)"),this, timestamp, activating ? wxT("ACTIV") : wxT("deact"));
361
301c0f4c 362 wxMDIParentFrame *mdiparent = m_mdiParent;
489468fe
SC
363 wxASSERT(mdiparent);
364
365 if (activating)
366 {
367 if (s_macDeactivateWindow == m_parent)
368 {
369 wxLogTrace(TRACE_MDI, wxT("parent had been scheduled for deactivation, rehighlighting"));
370
b2680ced 371 UMAHighlightAndActivateWindow((WindowRef)s_macDeactivateWindow->GetWXWindow(), true);
489468fe
SC
372
373 wxLogTrace(TRACE_MDI, wxT("finished highliting parent"));
374
375 s_macDeactivateWindow = NULL;
376 }
377 else if ((mdiparent->m_currentChild == this) || !s_macDeactivateWindow)
378 mdiparent->wxFrame::MacActivate(timestamp, activating);
379
380 if (mdiparent->m_currentChild && mdiparent->m_currentChild != this)
381 mdiparent->m_currentChild->wxFrame::MacActivate(timestamp, false);
382 mdiparent->m_currentChild = this;
383
384 if (s_macDeactivateWindow == this)
385 {
386 wxLogTrace(TRACE_MDI, wxT("Avoided deactivation/activation of this=%p"), this);
387
388 s_macDeactivateWindow = NULL;
389 }
390 else
391 wxFrame::MacActivate(timestamp, activating);
392 }
393 else
394 {
395 // We were scheduled for deactivation, and now we do it.
396 if (s_macDeactivateWindow == this)
397 {
398 s_macDeactivateWindow = NULL;
399 wxFrame::MacActivate(timestamp, activating);
400 if (mdiparent->m_currentChild == this)
401 mdiparent->wxFrame::MacActivate(timestamp, activating);
402 }
403 else // schedule ourselves for deactivation
404 {
405 if (s_macDeactivateWindow)
43b2d5e7 406 {
489468fe 407 wxLogTrace(TRACE_MDI, wxT("window=%p SHOULD have been deactivated, oh well!"), s_macDeactivateWindow);
43b2d5e7 408 }
489468fe
SC
409 wxLogTrace(TRACE_MDI, wxT("Scheduling delayed deactivation"));
410
411 s_macDeactivateWindow = this;
412 }
413 }
414}
415
416// MDI operations
489468fe
SC
417void wxMDIChildFrame::Activate()
418{
3285e9a3
VZ
419 // The base class method calls Activate() so skip it to avoid infinite
420 // recursion and go directly to the real Raise() implementation.
421 wxFrame::Raise();
489468fe
SC
422}
423
424//-----------------------------------------------------------------------------
425// wxMDIClientWindow
426//-----------------------------------------------------------------------------
427
489468fe
SC
428wxMDIClientWindow::~wxMDIClientWindow()
429{
430 DestroyChildren();
431}
432
433bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
434{
435 if ( !wxWindow::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style) )
436 return false;
437
438 return true;
439}
440
489468fe
SC
441void wxMDIClientWindow::DoGetClientSize(int *x, int *y) const
442{
443 wxDisplaySize( x , y ) ;
444}
445
489468fe 446#endif // wxUSE_MDI