]>
Commit | Line | Data |
---|---|---|
6c70a9b5 JS |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: src/generic/mdig.cpp | |
3 | // Purpose: Generic MDI (Multiple Document Interface) classes | |
4 | // Author: Hans Van Leemputten | |
d2824cdb | 5 | // Modified by: 2008-10-31 Vadim Zeitlin: derive from the base classes |
6c70a9b5 | 6 | // Created: 29/07/2002 |
d2824cdb VZ |
7 | // Copyright: (c) 2002 Hans Van Leemputten |
8 | // (c) 2008 Vadim Zeitlin | |
65571936 | 9 | // Licence: wxWindows licence |
6c70a9b5 JS |
10 | ///////////////////////////////////////////////////////////////////////////// |
11 | ||
12 | // =========================================================================== | |
13 | // declarations | |
14 | // =========================================================================== | |
15 | ||
16 | // --------------------------------------------------------------------------- | |
17 | // headers | |
18 | // --------------------------------------------------------------------------- | |
19 | ||
6c70a9b5 JS |
20 | // For compilers that support precompilation, includes "wx.h". |
21 | #include "wx/wxprec.h" | |
22 | ||
23 | #ifdef __BORLANDC__ | |
24 | #pragma hdrstop | |
25 | #endif | |
26 | ||
9a6384ca WS |
27 | #if wxUSE_MDI |
28 | ||
6c70a9b5 | 29 | #ifndef WX_PRECOMP |
6c70a9b5 | 30 | #include "wx/menu.h" |
2b5f62a0 | 31 | #include "wx/intl.h" |
e4db172a | 32 | #include "wx/log.h" |
6c70a9b5 JS |
33 | #endif //WX_PRECOMP |
34 | ||
d2824cdb VZ |
35 | #include "wx/mdi.h" |
36 | #include "wx/generic/mdig.h" | |
37 | #include "wx/notebook.h" | |
38 | #include "wx/scopeguard.h" | |
39 | ||
e27d9a91 | 40 | #include "wx/stockitem.h" |
6c70a9b5 | 41 | |
c0924519 | 42 | enum MDI_MENU_ID |
6c70a9b5 JS |
43 | { |
44 | wxWINDOWCLOSE = 4001, | |
45 | wxWINDOWCLOSEALL, | |
46 | wxWINDOWNEXT, | |
47 | wxWINDOWPREV | |
48 | }; | |
49 | ||
50 | //----------------------------------------------------------------------------- | |
51 | // wxGenericMDIParentFrame | |
52 | //----------------------------------------------------------------------------- | |
53 | ||
54 | IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIParentFrame, wxFrame) | |
55 | ||
56 | BEGIN_EVENT_TABLE(wxGenericMDIParentFrame, wxFrame) | |
d2824cdb | 57 | EVT_CLOSE(wxGenericMDIParentFrame::OnClose) |
d7260478 | 58 | #if wxUSE_MENUS |
d2824cdb | 59 | EVT_MENU(wxID_ANY, wxGenericMDIParentFrame::OnWindowMenu) |
d7260478 | 60 | #endif |
6c70a9b5 JS |
61 | END_EVENT_TABLE() |
62 | ||
d2824cdb | 63 | void wxGenericMDIParentFrame::Init() |
6c70a9b5 | 64 | { |
d2824cdb VZ |
65 | #if wxUSE_MENUS |
66 | m_pMyMenuBar = NULL; | |
67 | #endif // wxUSE_MENUS | |
6c70a9b5 JS |
68 | } |
69 | ||
70 | wxGenericMDIParentFrame::~wxGenericMDIParentFrame() | |
c0924519 | 71 | { |
6c70a9b5 | 72 | // Make sure the client window is destructed before the menu bars are! |
d2824cdb | 73 | wxDELETE(m_clientWindow); |
6c70a9b5 | 74 | |
c0924519 | 75 | #if wxUSE_MENUS |
5276b0a5 | 76 | wxDELETE(m_pMyMenuBar); |
c0924519 | 77 | |
6c70a9b5 | 78 | RemoveWindowMenu(GetMenuBar()); |
6c70a9b5 JS |
79 | #endif // wxUSE_MENUS |
80 | } | |
81 | ||
82 | bool wxGenericMDIParentFrame::Create(wxWindow *parent, | |
83 | wxWindowID id, | |
84 | const wxString& title, | |
85 | const wxPoint& pos, | |
86 | const wxSize& size, | |
87 | long style, | |
88 | const wxString& name) | |
89 | { | |
d2824cdb VZ |
90 | // this style can be used to prevent a window from having the standard MDI |
91 | // "Window" menu | |
92 | if ( !(style & wxFRAME_NO_WINDOW_MENU) ) | |
93 | { | |
6c70a9b5 | 94 | #if wxUSE_MENUS |
d2824cdb | 95 | m_windowMenu = new wxMenu; |
6c70a9b5 | 96 | |
d2824cdb VZ |
97 | m_windowMenu->Append(wxWINDOWCLOSE, _("Cl&ose")); |
98 | m_windowMenu->Append(wxWINDOWCLOSEALL, _("Close All")); | |
99 | m_windowMenu->AppendSeparator(); | |
100 | m_windowMenu->Append(wxWINDOWNEXT, _("&Next")); | |
101 | m_windowMenu->Append(wxWINDOWPREV, _("&Previous")); | |
6c70a9b5 | 102 | #endif // wxUSE_MENUS |
d2824cdb | 103 | } |
6c70a9b5 | 104 | |
d2824cdb VZ |
105 | // the scrolling styles don't make sense neither for us nor for our client |
106 | // window (to which they're supposed to apply) | |
107 | style &= ~(wxHSCROLL | wxVSCROLL); | |
6c70a9b5 | 108 | |
d2824cdb VZ |
109 | if ( !wxFrame::Create( parent, id, title, pos, size, style, name ) ) |
110 | return false; | |
6c70a9b5 | 111 | |
d2824cdb VZ |
112 | wxGenericMDIClientWindow * const client = OnCreateGenericClient(); |
113 | if ( !client->CreateGenericClient(this) ) | |
114 | return false; | |
115 | ||
116 | m_clientWindow = client; | |
117 | ||
118 | return true; | |
119 | } | |
120 | ||
121 | wxGenericMDIClientWindow *wxGenericMDIParentFrame::OnCreateGenericClient() | |
122 | { | |
123 | return new wxGenericMDIClientWindow; | |
124 | } | |
125 | ||
126 | bool wxGenericMDIParentFrame::CloseAll() | |
127 | { | |
128 | wxGenericMDIClientWindow * const client = GetGenericClientWindow(); | |
129 | if ( !client ) | |
130 | return true; // none of the windows left | |
131 | ||
132 | wxBookCtrlBase * const book = client->GetBookCtrl(); | |
133 | while ( book->GetPageCount() ) | |
134 | { | |
135 | wxGenericMDIChildFrame * const child = client->GetChild(0); | |
136 | if ( !child->Close() ) | |
137 | { | |
138 | // it refused to close, don't close the remaining ones neither | |
139 | return false; | |
140 | } | |
141 | } | |
142 | ||
143 | return true; | |
6c70a9b5 JS |
144 | } |
145 | ||
146 | #if wxUSE_MENUS | |
147 | void wxGenericMDIParentFrame::SetWindowMenu(wxMenu* pMenu) | |
148 | { | |
149 | // Replace the window menu from the currently loaded menu bar. | |
150 | wxMenuBar *pMenuBar = GetMenuBar(); | |
151 | ||
d2824cdb | 152 | if (m_windowMenu) |
6c70a9b5 JS |
153 | { |
154 | RemoveWindowMenu(pMenuBar); | |
155 | ||
d2824cdb | 156 | wxDELETE(m_windowMenu); |
6c70a9b5 JS |
157 | } |
158 | ||
159 | if (pMenu) | |
160 | { | |
d2824cdb | 161 | m_windowMenu = pMenu; |
6c70a9b5 JS |
162 | |
163 | AddWindowMenu(pMenuBar); | |
164 | } | |
165 | } | |
166 | ||
167 | void wxGenericMDIParentFrame::SetMenuBar(wxMenuBar *pMenuBar) | |
168 | { | |
169 | // Remove the Window menu from the old menu bar | |
170 | RemoveWindowMenu(GetMenuBar()); | |
171 | // Add the Window menu to the new menu bar. | |
172 | AddWindowMenu(pMenuBar); | |
173 | ||
174 | wxFrame::SetMenuBar(pMenuBar); | |
175 | } | |
176 | #endif // wxUSE_MENUS | |
177 | ||
d2824cdb | 178 | void wxGenericMDIParentFrame::WXSetChildMenuBar(wxGenericMDIChildFrame *pChild) |
6c70a9b5 JS |
179 | { |
180 | #if wxUSE_MENUS | |
d2824cdb | 181 | if (pChild == NULL) |
6c70a9b5 JS |
182 | { |
183 | // No Child, set Our menu bar back. | |
184 | SetMenuBar(m_pMyMenuBar); | |
c0924519 | 185 | |
6c70a9b5 | 186 | // Make sure we know our menu bar is in use |
d2824cdb | 187 | m_pMyMenuBar = NULL; |
6c70a9b5 JS |
188 | } |
189 | else | |
190 | { | |
d2824cdb | 191 | if (pChild->GetMenuBar() == NULL) |
6c70a9b5 JS |
192 | return; |
193 | ||
194 | // Do we need to save the current bar? | |
195 | if (m_pMyMenuBar == NULL) | |
196 | m_pMyMenuBar = GetMenuBar(); | |
197 | ||
198 | SetMenuBar(pChild->GetMenuBar()); | |
199 | } | |
200 | #endif // wxUSE_MENUS | |
201 | } | |
202 | ||
d2824cdb VZ |
203 | wxGenericMDIClientWindow * |
204 | wxGenericMDIParentFrame::GetGenericClientWindow() const | |
6c70a9b5 | 205 | { |
d2824cdb | 206 | return static_cast<wxGenericMDIClientWindow *>(m_clientWindow); |
6c70a9b5 JS |
207 | } |
208 | ||
d2824cdb | 209 | wxBookCtrlBase *wxGenericMDIParentFrame::GetBookCtrl() const |
6c70a9b5 | 210 | { |
d2824cdb VZ |
211 | wxGenericMDIClientWindow * const client = GetGenericClientWindow(); |
212 | return client ? client->GetBookCtrl() : NULL; | |
6c70a9b5 JS |
213 | } |
214 | ||
d2824cdb | 215 | void wxGenericMDIParentFrame::AdvanceActive(bool forward) |
6c70a9b5 | 216 | { |
d2824cdb VZ |
217 | wxBookCtrlBase * const book = GetBookCtrl(); |
218 | if ( book ) | |
219 | book->AdvanceSelection(forward); | |
6c70a9b5 JS |
220 | } |
221 | ||
d2824cdb | 222 | void wxGenericMDIParentFrame::WXUpdateChildTitle(wxGenericMDIChildFrame *child) |
6c70a9b5 | 223 | { |
d2824cdb VZ |
224 | wxGenericMDIClientWindow * const client = GetGenericClientWindow(); |
225 | ||
226 | const int pos = client->FindChild(child); | |
227 | if ( pos == wxNOT_FOUND ) | |
228 | return; | |
229 | ||
230 | client->GetBookCtrl()->SetPageText(pos, child->GetTitle()); | |
6c70a9b5 JS |
231 | } |
232 | ||
d2824cdb | 233 | void wxGenericMDIParentFrame::WXActivateChild(wxGenericMDIChildFrame *child) |
6c70a9b5 | 234 | { |
d2824cdb VZ |
235 | wxGenericMDIClientWindow * const client = GetGenericClientWindow(); |
236 | ||
237 | const int pos = client->FindChild(child); | |
238 | if ( pos == wxNOT_FOUND ) | |
239 | return; | |
240 | ||
241 | client->GetBookCtrl()->SetSelection(pos); | |
6c70a9b5 JS |
242 | } |
243 | ||
d2824cdb | 244 | void wxGenericMDIParentFrame::WXRemoveChild(wxGenericMDIChildFrame *child) |
6c70a9b5 | 245 | { |
d2824cdb VZ |
246 | const bool removingActive = WXIsActiveChild(child); |
247 | if ( removingActive ) | |
6c70a9b5 | 248 | { |
d2824cdb VZ |
249 | SetActiveChild(NULL); |
250 | WXSetChildMenuBar(NULL); | |
6c70a9b5 | 251 | } |
6c70a9b5 | 252 | |
d2824cdb VZ |
253 | wxGenericMDIClientWindow * const client = GetGenericClientWindow(); |
254 | wxCHECK_RET( client, "should have client window" ); | |
255 | ||
256 | wxBookCtrlBase * const book = client->GetBookCtrl(); | |
257 | ||
258 | // Remove page if still there | |
259 | int pos = client->FindChild(child); | |
260 | if ( pos != wxNOT_FOUND ) | |
6c70a9b5 | 261 | { |
d2824cdb VZ |
262 | if ( book->RemovePage(pos) ) |
263 | book->Refresh(); | |
264 | } | |
6c70a9b5 | 265 | |
d2824cdb VZ |
266 | if ( removingActive ) |
267 | { | |
268 | // Set the new selection to a remaining page | |
269 | const size_t count = book->GetPageCount(); | |
270 | if ( count > (size_t)pos ) | |
271 | { | |
272 | book->SetSelection(pos); | |
273 | } | |
274 | else | |
275 | { | |
276 | if ( count > 0 ) | |
277 | book->SetSelection(count - 1); | |
278 | } | |
6c70a9b5 JS |
279 | } |
280 | } | |
281 | ||
d2824cdb VZ |
282 | bool |
283 | wxGenericMDIParentFrame::WXIsActiveChild(wxGenericMDIChildFrame *child) const | |
6c70a9b5 | 284 | { |
d2824cdb | 285 | return static_cast<wxMDIChildFrameBase *>(GetActiveChild()) == child; |
6c70a9b5 JS |
286 | } |
287 | ||
288 | #if wxUSE_MENUS | |
289 | void wxGenericMDIParentFrame::RemoveWindowMenu(wxMenuBar *pMenuBar) | |
290 | { | |
d2824cdb | 291 | if (pMenuBar && m_windowMenu) |
6c70a9b5 JS |
292 | { |
293 | // Remove old window menu | |
2b5f62a0 | 294 | int pos = pMenuBar->FindMenu(_("&Window")); |
6c70a9b5 JS |
295 | if (pos != wxNOT_FOUND) |
296 | { | |
d2824cdb | 297 | wxASSERT(m_windowMenu == pMenuBar->GetMenu(pos)); // DBG:: We're going to delete the wrong menu!!! |
6c70a9b5 JS |
298 | pMenuBar->Remove(pos); |
299 | } | |
300 | } | |
301 | } | |
302 | ||
303 | void wxGenericMDIParentFrame::AddWindowMenu(wxMenuBar *pMenuBar) | |
304 | { | |
d2824cdb | 305 | if (pMenuBar && m_windowMenu) |
c0924519 | 306 | { |
e27d9a91 | 307 | int pos = pMenuBar->FindMenu(wxGetStockLabel(wxID_HELP,false)); |
6c70a9b5 JS |
308 | if (pos == wxNOT_FOUND) |
309 | { | |
d2824cdb | 310 | pMenuBar->Append(m_windowMenu, _("&Window")); |
6c70a9b5 JS |
311 | } |
312 | else | |
313 | { | |
d2824cdb | 314 | pMenuBar->Insert(pos, m_windowMenu, _("&Window")); |
6c70a9b5 JS |
315 | } |
316 | } | |
317 | } | |
318 | ||
d2824cdb | 319 | void wxGenericMDIParentFrame::OnWindowMenu(wxCommandEvent &event) |
6c70a9b5 | 320 | { |
d2824cdb | 321 | switch ( event.GetId() ) |
6c70a9b5 | 322 | { |
d2824cdb VZ |
323 | case wxWINDOWCLOSE: |
324 | if ( m_currentChild ) | |
325 | m_currentChild->Close(); | |
326 | break; | |
327 | ||
328 | case wxWINDOWCLOSEALL: | |
329 | CloseAll(); | |
330 | break; | |
331 | ||
332 | case wxWINDOWNEXT: | |
333 | ActivateNext(); | |
334 | break; | |
335 | ||
336 | case wxWINDOWPREV: | |
337 | ActivatePrevious(); | |
338 | break; | |
339 | ||
340 | default: | |
341 | event.Skip(); | |
6c70a9b5 JS |
342 | } |
343 | } | |
344 | #endif // wxUSE_MENUS | |
345 | ||
d2824cdb | 346 | void wxGenericMDIParentFrame::OnClose(wxCloseEvent& event) |
6c70a9b5 | 347 | { |
d2824cdb VZ |
348 | if ( !CloseAll() ) |
349 | event.Veto(); | |
350 | else | |
351 | event.Skip(); | |
6c70a9b5 JS |
352 | } |
353 | ||
d2824cdb VZ |
354 | bool wxGenericMDIParentFrame::ProcessEvent(wxEvent& event) |
355 | { | |
356 | if ( m_currentChild ) | |
357 | { | |
358 | // the menu events should be given to the child as we show its menu bar | |
359 | // as our own | |
360 | const wxEventType eventType = event.GetEventType(); | |
ce7fe42e | 361 | if ( eventType == wxEVT_MENU || |
d2824cdb VZ |
362 | eventType == wxEVT_UPDATE_UI ) |
363 | { | |
364 | // set the flag indicating that this event was forwarded to the | |
365 | // child from the parent and so shouldn't be propagated upwards if | |
366 | // not processed to avoid infinite loop | |
367 | m_childHandler = m_currentChild; | |
368 | wxON_BLOCK_EXIT_NULL(m_childHandler); | |
369 | ||
3b7fa206 | 370 | if ( m_currentChild->ProcessWindowEvent(event) ) |
d2824cdb VZ |
371 | return true; |
372 | } | |
373 | } | |
6c70a9b5 | 374 | |
d2824cdb VZ |
375 | return wxMDIParentFrameBase::ProcessEvent(event); |
376 | } | |
377 | ||
378 | // ---------------------------------------------------------------------------- | |
6c70a9b5 | 379 | // wxGenericMDIChildFrame |
d2824cdb | 380 | // ---------------------------------------------------------------------------- |
6c70a9b5 | 381 | |
d2824cdb | 382 | IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIChildFrame, wxFrame) |
6c70a9b5 | 383 | |
d2824cdb | 384 | BEGIN_EVENT_TABLE(wxGenericMDIChildFrame, wxFrame) |
6c70a9b5 | 385 | EVT_MENU_HIGHLIGHT_ALL(wxGenericMDIChildFrame::OnMenuHighlight) |
6c70a9b5 | 386 | |
d2824cdb | 387 | EVT_CLOSE(wxGenericMDIChildFrame::OnClose) |
6c70a9b5 JS |
388 | END_EVENT_TABLE() |
389 | ||
d2824cdb | 390 | void wxGenericMDIChildFrame::Init() |
6c70a9b5 | 391 | { |
d2824cdb VZ |
392 | #if wxUSE_MENUS |
393 | m_pMenuBar = NULL; | |
394 | #endif // wxUSE_MENUS | |
6c70a9b5 | 395 | |
d2824cdb VZ |
396 | #if !wxUSE_GENERIC_MDI_AS_NATIVE |
397 | m_mdiParentGeneric = NULL; | |
398 | #endif | |
6c70a9b5 JS |
399 | } |
400 | ||
6c70a9b5 JS |
401 | wxGenericMDIChildFrame::~wxGenericMDIChildFrame() |
402 | { | |
d2824cdb | 403 | wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); |
6c70a9b5 | 404 | |
d2824cdb VZ |
405 | // it could happen that we don't have a valid parent if we hadn't been ever |
406 | // really created -- but in this case there is nothing else to do neither | |
407 | if ( parent ) | |
408 | parent->WXRemoveChild(this); | |
6c70a9b5 JS |
409 | |
410 | #if wxUSE_MENUS | |
d2824cdb | 411 | delete m_pMenuBar; |
6c70a9b5 JS |
412 | #endif // wxUSE_MENUS |
413 | } | |
414 | ||
d2824cdb VZ |
415 | bool wxGenericMDIChildFrame::Create(wxGenericMDIParentFrame *parent, |
416 | wxWindowID id, | |
417 | const wxString& title, | |
418 | const wxPoint& WXUNUSED(pos), | |
419 | const wxSize& size, | |
420 | long WXUNUSED(style), | |
421 | const wxString& name) | |
6c70a9b5 | 422 | { |
d2824cdb VZ |
423 | // unfortunately we can't use the base class m_mdiParent field unless |
424 | // wxGenericMDIParentFrame is wxMDIParentFrame | |
425 | #if wxUSE_GENERIC_MDI_AS_NATIVE | |
426 | m_mdiParent = parent; | |
427 | #else // generic != native | |
428 | // leave m_mdiParent NULL, we don't have it | |
429 | m_mdiParentGeneric = parent; | |
430 | #endif | |
c0924519 | 431 | |
d2824cdb | 432 | wxBookCtrlBase * const book = parent->GetBookCtrl(); |
6c70a9b5 | 433 | |
d2824cdb | 434 | wxASSERT_MSG( book, "Missing MDI client window." ); |
6c70a9b5 | 435 | |
d2824cdb VZ |
436 | // note that we ignore the styles, none of the usual TLW styles apply to |
437 | // this (child) window | |
438 | if ( !wxWindow::Create(book, id, wxDefaultPosition, size, 0, name) ) | |
439 | return false; | |
6c70a9b5 | 440 | |
d2824cdb VZ |
441 | m_title = title; |
442 | book->AddPage(this, title, true); | |
6c70a9b5 | 443 | |
ca65c044 | 444 | return true; |
6c70a9b5 JS |
445 | } |
446 | ||
c0924519 | 447 | #if wxUSE_MENUS |
6c70a9b5 JS |
448 | void wxGenericMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar ) |
449 | { | |
450 | wxMenuBar *pOldMenuBar = m_pMenuBar; | |
451 | m_pMenuBar = menu_bar; | |
452 | ||
453 | if (m_pMenuBar) | |
454 | { | |
d2824cdb | 455 | wxGenericMDIParentFrame *parent = GetGenericMDIParent(); |
c0924519 | 456 | |
d2824cdb | 457 | if ( parent ) |
6c70a9b5 | 458 | { |
d2824cdb | 459 | m_pMenuBar->SetParent(parent); |
6c70a9b5 | 460 | |
d2824cdb | 461 | if ( parent->WXIsActiveChild(this) ) |
6c70a9b5 JS |
462 | { |
463 | // Replace current menu bars | |
464 | if (pOldMenuBar) | |
d2824cdb VZ |
465 | parent->WXSetChildMenuBar(NULL); |
466 | parent->WXSetChildMenuBar(this); | |
6c70a9b5 JS |
467 | } |
468 | } | |
469 | } | |
470 | } | |
471 | ||
472 | wxMenuBar *wxGenericMDIChildFrame::GetMenuBar() const | |
473 | { | |
474 | return m_pMenuBar; | |
475 | } | |
c0924519 | 476 | #endif // wxUSE_MENUS |
6c70a9b5 JS |
477 | |
478 | void wxGenericMDIChildFrame::SetTitle(const wxString& title) | |
479 | { | |
d2824cdb | 480 | m_title = title; |
6c70a9b5 | 481 | |
d2824cdb VZ |
482 | wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); |
483 | if ( parent ) | |
484 | parent->WXUpdateChildTitle(this); | |
485 | //else: it's ok, we might be not created yet | |
6c70a9b5 JS |
486 | } |
487 | ||
488 | void wxGenericMDIChildFrame::Activate() | |
489 | { | |
d2824cdb | 490 | wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); |
6c70a9b5 | 491 | |
d2824cdb VZ |
492 | wxCHECK_RET( parent, "can't activate MDI child without parent" ); |
493 | parent->WXActivateChild(this); | |
6c70a9b5 JS |
494 | } |
495 | ||
496 | void wxGenericMDIChildFrame::OnMenuHighlight(wxMenuEvent& event) | |
497 | { | |
d2824cdb VZ |
498 | wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); |
499 | if ( parent) | |
6c70a9b5 | 500 | { |
c0924519 | 501 | // we don't have any help text for this item, |
6c70a9b5 | 502 | // but may be the MDI frame does? |
d2824cdb | 503 | parent->OnMenuHighlight(event); |
6c70a9b5 JS |
504 | } |
505 | } | |
506 | ||
d2824cdb | 507 | void wxGenericMDIChildFrame::OnClose(wxCloseEvent& WXUNUSED(event)) |
6c70a9b5 | 508 | { |
d2824cdb VZ |
509 | // we're not a TLW so don't delay the destruction of this window |
510 | delete this; | |
6c70a9b5 JS |
511 | } |
512 | ||
8cc208e3 | 513 | bool wxGenericMDIChildFrame::TryAfter(wxEvent& event) |
c0924519 | 514 | { |
d2824cdb VZ |
515 | // we shouldn't propagate the event to the parent if we received it from it |
516 | // in the first place | |
517 | wxGenericMDIParentFrame * const parent = GetGenericMDIParent(); | |
518 | if ( parent && parent->WXIsInsideChildHandler(this) ) | |
519 | return false; | |
6c70a9b5 | 520 | |
8cc208e3 | 521 | return wxTDIChildFrame::TryAfter(event); |
6c70a9b5 JS |
522 | } |
523 | ||
d2824cdb | 524 | // ---------------------------------------------------------------------------- |
6c70a9b5 | 525 | // wxGenericMDIClientWindow |
d2824cdb | 526 | // ---------------------------------------------------------------------------- |
6c70a9b5 | 527 | |
d2824cdb | 528 | IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIClientWindow, wxWindow) |
6c70a9b5 | 529 | |
d2824cdb VZ |
530 | bool |
531 | wxGenericMDIClientWindow::CreateGenericClient(wxWindow *parent) | |
532 | { | |
533 | if ( !wxWindow::Create(parent, wxID_ANY) ) | |
534 | return false; | |
6c70a9b5 | 535 | |
d2824cdb VZ |
536 | m_notebook = new wxNotebook(this, wxID_ANY); |
537 | m_notebook->Connect | |
538 | ( | |
ce7fe42e | 539 | wxEVT_NOTEBOOK_PAGE_CHANGED, |
d2824cdb VZ |
540 | wxNotebookEventHandler( |
541 | wxGenericMDIClientWindow::OnPageChanged), | |
542 | NULL, | |
543 | this | |
544 | ); | |
6c70a9b5 | 545 | |
d2824cdb VZ |
546 | // now that we have a notebook to resize, hook up OnSize() too |
547 | Connect(wxEVT_SIZE, wxSizeEventHandler(wxGenericMDIClientWindow::OnSize)); | |
6c70a9b5 | 548 | |
d2824cdb | 549 | return true; |
6c70a9b5 JS |
550 | } |
551 | ||
d2824cdb | 552 | wxBookCtrlBase *wxGenericMDIClientWindow::GetBookCtrl() const |
6c70a9b5 | 553 | { |
d2824cdb | 554 | return m_notebook; |
6c70a9b5 JS |
555 | } |
556 | ||
d2824cdb | 557 | wxGenericMDIChildFrame *wxGenericMDIClientWindow::GetChild(size_t pos) const |
6c70a9b5 | 558 | { |
d2824cdb | 559 | return static_cast<wxGenericMDIChildFrame *>(GetBookCtrl()->GetPage(pos)); |
6c70a9b5 JS |
560 | } |
561 | ||
d2824cdb | 562 | int wxGenericMDIClientWindow::FindChild(wxGenericMDIChildFrame *child) const |
6c70a9b5 | 563 | { |
d2824cdb VZ |
564 | wxBookCtrlBase * const book = GetBookCtrl(); |
565 | const size_t count = book->GetPageCount(); | |
566 | for ( size_t pos = 0; pos < count; pos++ ) | |
6c70a9b5 | 567 | { |
d2824cdb VZ |
568 | if ( book->GetPage(pos) == child ) |
569 | return pos; | |
6c70a9b5 | 570 | } |
6c70a9b5 | 571 | |
d2824cdb | 572 | return wxNOT_FOUND; |
6c70a9b5 JS |
573 | } |
574 | ||
d2824cdb | 575 | void wxGenericMDIClientWindow::PageChanged(int oldSelection, int newSelection) |
6c70a9b5 | 576 | { |
d2824cdb VZ |
577 | // Don't do anything if nothing changed |
578 | if (oldSelection == newSelection) | |
6c70a9b5 | 579 | return; |
d2824cdb VZ |
580 | |
581 | // Again check if we really need to do this... | |
6c70a9b5 JS |
582 | if (newSelection != -1) |
583 | { | |
d2824cdb | 584 | wxGenericMDIChildFrame * const child = GetChild(newSelection); |
6c70a9b5 | 585 | |
d2824cdb | 586 | if ( child->GetGenericMDIParent()->WXIsActiveChild(child) ) |
6c70a9b5 JS |
587 | return; |
588 | } | |
589 | ||
590 | // Notify old active child that it has been deactivated | |
d2824cdb | 591 | if (oldSelection != -1) |
6c70a9b5 | 592 | { |
d2824cdb | 593 | wxGenericMDIChildFrame * const oldChild = GetChild(oldSelection); |
6c70a9b5 JS |
594 | if (oldChild) |
595 | { | |
ca65c044 | 596 | wxActivateEvent event(wxEVT_ACTIVATE, false, oldChild->GetId()); |
6c70a9b5 JS |
597 | event.SetEventObject( oldChild ); |
598 | oldChild->GetEventHandler()->ProcessEvent(event); | |
599 | } | |
600 | } | |
601 | ||
602 | // Notify new active child that it has been activated | |
603 | if (newSelection != -1) | |
604 | { | |
d2824cdb VZ |
605 | wxGenericMDIChildFrame * const activeChild = GetChild(newSelection); |
606 | if ( activeChild ) | |
6c70a9b5 | 607 | { |
ca65c044 | 608 | wxActivateEvent event(wxEVT_ACTIVATE, true, activeChild->GetId()); |
6c70a9b5 JS |
609 | event.SetEventObject( activeChild ); |
610 | activeChild->GetEventHandler()->ProcessEvent(event); | |
611 | ||
d2824cdb VZ |
612 | wxGenericMDIParentFrame * const |
613 | parent = activeChild->GetGenericMDIParent(); | |
614 | ||
615 | if ( parent ) | |
6c70a9b5 | 616 | { |
d2824cdb VZ |
617 | // this is a dirty hack as activeChild is not really a |
618 | // wxMDIChildFrame at all but we still want to store it in the | |
619 | // base class m_currentChild field and this will work as long | |
620 | // as we only use as wxMDIChildFrameBase pointer (which it is) | |
621 | parent->SetActiveChild( | |
622 | reinterpret_cast<wxMDIChildFrame *>(activeChild)); | |
623 | parent->WXSetChildMenuBar(activeChild); | |
6c70a9b5 JS |
624 | } |
625 | } | |
626 | } | |
627 | } | |
628 | ||
3e97a905 | 629 | void wxGenericMDIClientWindow::OnPageChanged(wxBookCtrlEvent& event) |
6c70a9b5 JS |
630 | { |
631 | PageChanged(event.GetOldSelection(), event.GetSelection()); | |
632 | ||
633 | event.Skip(); | |
634 | } | |
635 | ||
d2824cdb | 636 | void wxGenericMDIClientWindow::OnSize(wxSizeEvent& WXUNUSED(event)) |
6c70a9b5 | 637 | { |
d2824cdb | 638 | m_notebook->SetSize(GetClientSize()); |
6c70a9b5 JS |
639 | } |
640 | ||
b4ca5976 VS |
641 | #endif // wxUSE_MDI |
642 |