]> git.saurik.com Git - wxWidgets.git/blob - src/mac/classic/mdi.cpp
Add more sanity checks to virtual list item nums as the native control sometimes...
[wxWidgets.git] / src / mac / classic / mdi.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/classic/mdi.cpp
3 // Purpose: MDI classes
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #include "wx/mdi.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/log.h"
18 #include "wx/menu.h"
19 #include "wx/settings.h"
20 #endif
21
22 #include "wx/mac/private.h"
23 #include "wx/mac/uma.h"
24
25 extern wxWindowList wxModelessWindows;
26
27 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame)
28 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
29 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
30
31 BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
32 EVT_ACTIVATE(wxMDIParentFrame::OnActivate)
33 EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
34 END_EVENT_TABLE()
35
36 BEGIN_EVENT_TABLE(wxMDIClientWindow, wxWindow)
37 EVT_SCROLL(wxMDIClientWindow::OnScroll)
38 END_EVENT_TABLE()
39
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;
47
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;
51
52 // Status border dimensions
53 static const int wxTHICK_LINE_BORDER = 3;
54
55 // Parent frame
56
57 wxMDIParentFrame::wxMDIParentFrame()
58 {
59 m_clientWindow = NULL;
60 m_currentChild = NULL;
61 m_windowMenu = (wxMenu*) NULL;
62 m_parentFrameActive = true;
63 }
64
65 bool wxMDIParentFrame::Create(wxWindow *parent,
66 wxWindowID id,
67 const wxString& title,
68 const wxPoint& pos,
69 const wxSize& size,
70 long style,
71 const wxString& name)
72 {
73 m_clientWindow = NULL;
74 m_currentChild = NULL;
75
76 // this style can be used to prevent a window from having the standard MDI
77 // "Window" menu
78 if ( style & wxFRAME_NO_WINDOW_MENU )
79 {
80 m_windowMenu = (wxMenu *)NULL;
81 style -= wxFRAME_NO_WINDOW_MENU ;
82 }
83 else // normal case: we have the window menu, so construct it
84 {
85 m_windowMenu = new wxMenu;
86
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"));
93 }
94
95 wxFrame::Create( parent , id , title , pos , size , style , name ) ;
96 m_parentFrameActive = true;
97
98 OnCreateClient();
99
100 return true;
101 }
102
103 wxMDIParentFrame::~wxMDIParentFrame()
104 {
105 DestroyChildren();
106 // already delete by DestroyChildren()
107 #if wxUSE_TOOLBAR
108 m_frameToolBar = NULL;
109 #endif
110 #if wxUSE_STATUSBAR
111 m_frameStatusBar = NULL;
112 #endif
113 m_clientWindow = NULL ;
114
115 if (m_windowMenu)
116 {
117 delete m_windowMenu;
118 m_windowMenu = (wxMenu*) NULL;
119 }
120
121 if ( m_clientWindow )
122 {
123 delete m_clientWindow;
124 m_clientWindow = NULL ;
125 }
126 }
127
128
129 void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar)
130 {
131 wxFrame::SetMenuBar( menu_bar ) ;
132 }
133
134 void wxMDIParentFrame::MacActivate(long timestamp, bool activating)
135 {
136 wxLogDebug(wxT("MDI PARENT=%p MacActivate(0x%08lx,%s)"),this,timestamp,activating?wxT("ACTIV"):wxT("deact"));
137 if(activating)
138 {
139 if(s_macDeactivateWindow && s_macDeactivateWindow->GetParent()==this)
140 {
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;
145 }
146 else if(s_macDeactivateWindow == this)
147 {
148 wxLogDebug(wxT("Avoided deactivation/activation of this=%p"), this);
149 s_macDeactivateWindow = NULL;
150 }
151 else // window to deactivate is NULL or is not us or one of our kids
152 {
153 // activate kid instead
154 if(m_currentChild)
155 m_currentChild->MacActivate(timestamp,activating);
156 else
157 wxFrame::MacActivate(timestamp,activating);
158 }
159 }
160 else
161 {
162 // We were scheduled for deactivation, and now we do it.
163 if(s_macDeactivateWindow==this)
164 {
165 s_macDeactivateWindow = NULL;
166 if(m_currentChild)
167 m_currentChild->MacActivate(timestamp,activating);
168 wxFrame::MacActivate(timestamp,activating);
169 }
170 else // schedule ourselves for deactivation
171 {
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;
176 }
177 }
178 }
179
180 void wxMDIParentFrame::OnActivate(wxActivateEvent& event)
181 {
182 event.Skip();
183 }
184
185 // Returns the active MDI child window
186 wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const
187 {
188 return m_currentChild ;
189 }
190
191 // Create the client window class (don't Create the window,
192 // just return a new class)
193 wxMDIClientWindow *wxMDIParentFrame::OnCreateClient()
194 {
195 m_clientWindow = new wxMDIClientWindow( this );
196 return m_clientWindow;
197 }
198
199 // Responds to colour changes, and passes event on to children.
200 void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
201 {
202 // TODO
203
204 // Propagate the event to the non-top-level children
205 wxFrame::OnSysColourChanged(event);
206 }
207
208 // MDI operations
209 void wxMDIParentFrame::Cascade()
210 {
211 // TODO
212 }
213
214 void wxMDIParentFrame::Tile(wxOrientation WXUNUSED(orient))
215 {
216 // TODO
217 }
218
219 void wxMDIParentFrame::ArrangeIcons()
220 {
221 // TODO
222 }
223
224 void wxMDIParentFrame::ActivateNext()
225 {
226 // TODO
227 }
228
229 void wxMDIParentFrame::ActivatePrevious()
230 {
231 // TODO
232 }
233
234 // Child frame
235
236 wxMDIChildFrame::wxMDIChildFrame()
237 {
238 Init() ;
239 }
240 void wxMDIChildFrame::Init()
241 {
242 }
243
244 bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
245 wxWindowID id,
246 const wxString& title,
247 const wxPoint& pos,
248 const wxSize& size,
249 long style,
250 const wxString& name)
251 {
252 SetName(name);
253
254 if ( id != wxID_ANY )
255 m_windowId = id;
256 else
257 m_windowId = (int)NewControlId();
258
259 if (parent) parent->AddChild(this);
260
261 MacCreateRealWindow( title, pos , size , MacRemoveBordersFromStyle(style) , name ) ;
262
263 m_macWindowBackgroundTheme = kThemeBrushDocumentWindowBackground ;
264 SetThemeWindowBackground( (WindowRef) m_macWindow , m_macWindowBackgroundTheme , false ) ;
265
266 wxModelessWindows.Append(this);
267 return false;
268 }
269
270 wxMDIChildFrame::~wxMDIChildFrame()
271 {
272 wxMDIParentFrame *mdiparent = wxDynamicCast(m_parent, wxMDIParentFrame);
273 wxASSERT(mdiparent);
274 if(mdiparent->m_currentChild == this)
275 mdiparent->m_currentChild = NULL;
276 DestroyChildren();
277 // already delete by DestroyChildren()
278 #if wxUSE_TOOLBAR
279 m_frameToolBar = NULL;
280 #endif
281 #if wxUSE_STATUSBAR
282 m_frameStatusBar = NULL;
283 #endif
284 }
285
286 void wxMDIChildFrame::SetMenuBar(wxMenuBar *menu_bar)
287 {
288 return wxFrame::SetMenuBar( menu_bar ) ;
289 }
290
291 void wxMDIChildFrame::MacActivate(long timestamp, bool activating)
292 {
293 wxLogDebug(wxT("MDI child=%p MacActivate(0x%08lx,%s)"),this,timestamp,activating?wxT("ACTIV"):wxT("deact"));
294 wxMDIParentFrame *mdiparent = wxDynamicCast(m_parent, wxMDIParentFrame);
295 wxASSERT(mdiparent);
296 if(activating)
297 {
298 if(s_macDeactivateWindow == m_parent)
299 {
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;
304 }
305 else if((mdiparent->m_currentChild==this) || !s_macDeactivateWindow)
306 mdiparent->wxFrame::MacActivate(timestamp,activating);
307
308 if(mdiparent->m_currentChild && mdiparent->m_currentChild!=this)
309 mdiparent->m_currentChild->wxFrame::MacActivate(timestamp,false);
310 mdiparent->m_currentChild = this;
311
312 if(s_macDeactivateWindow==this)
313 {
314 wxLogDebug(wxT("Avoided deactivation/activation of this=%p"),this);
315 s_macDeactivateWindow=NULL;
316 }
317 else
318 wxFrame::MacActivate(timestamp, activating);
319 }
320 else
321 {
322 // We were scheduled for deactivation, and now we do it.
323 if(s_macDeactivateWindow==this)
324 {
325 s_macDeactivateWindow = NULL;
326 wxFrame::MacActivate(timestamp,activating);
327 if(mdiparent->m_currentChild==this)
328 mdiparent->wxFrame::MacActivate(timestamp,activating);
329 }
330 else // schedule ourselves for deactivation
331 {
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;
336 }
337 }
338 }
339
340 // MDI operations
341 void wxMDIChildFrame::Maximize()
342 {
343 wxFrame::Maximize() ;
344 }
345
346 void wxMDIChildFrame::Restore()
347 {
348 wxFrame::Restore() ;
349 }
350
351 void wxMDIChildFrame::Activate()
352 {
353 }
354
355 //-----------------------------------------------------------------------------
356 // wxMDIClientWindow
357 //-----------------------------------------------------------------------------
358
359 wxMDIClientWindow::wxMDIClientWindow()
360 {
361 }
362
363 wxMDIClientWindow::~wxMDIClientWindow()
364 {
365 DestroyChildren();
366 }
367
368 bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
369 {
370
371 m_windowId = (int)NewControlId();
372
373 if ( parent )
374 {
375 parent->AddChild(this);
376 }
377 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
378
379 wxModelessWindows.Append(this);
380 return true;
381 }
382
383 // Get size *available for subwindows* i.e. excluding menu bar.
384 void wxMDIClientWindow::DoGetClientSize(int *x, int *y) const
385 {
386 wxDisplaySize( x , y ) ;
387 }
388
389 // Explicitly call default scroll behaviour
390 void wxMDIClientWindow::OnScroll(wxScrollEvent& event)
391 {
392 }