1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/generic/mdig.cpp
3 // Purpose:     Generic MDI (Multiple Document Interface) classes
4 // Author:      Hans Van Leemputten
5 // Modified by:
6 // Created:     29/07/2002
7 // RCS-ID:      $Id: mdig.cpp 41069 2006-09-08 14:38:49Z VS $
8 // Copyright:   (c) Hans Van Leemputten
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15 
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19 
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22 
23 #ifdef __BORLANDC__
24     #pragma hdrstop
25 #endif
26 
27 #if wxUSE_MDI
28 
29 #include "wx/generic/mdig.h"
30 
31 #ifndef WX_PRECOMP
32     #include "wx/panel.h"
33     #include "wx/menu.h"
34     #include "wx/intl.h"
35     #include "wx/log.h"
36 #endif //WX_PRECOMP
37 
38 #include "wx/stockitem.h"
39 
40 enum MDI_MENU_ID
41 {
42     wxWINDOWCLOSE = 4001,
43     wxWINDOWCLOSEALL,
44     wxWINDOWNEXT,
45     wxWINDOWPREV
46 };
47 
48 //-----------------------------------------------------------------------------
49 // wxGenericMDIParentFrame
50 //-----------------------------------------------------------------------------
51 
IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIParentFrame,wxFrame)52 IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIParentFrame, wxFrame)
53 
54 BEGIN_EVENT_TABLE(wxGenericMDIParentFrame, wxFrame)
55 #if wxUSE_MENUS
56     EVT_MENU (wxID_ANY, wxGenericMDIParentFrame::DoHandleMenu)
57 #endif
58 END_EVENT_TABLE()
59 
60 wxGenericMDIParentFrame::wxGenericMDIParentFrame()
61 {
62     Init();
63 }
64 
wxGenericMDIParentFrame(wxWindow * parent,wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size,long style,const wxString & name)65 wxGenericMDIParentFrame::wxGenericMDIParentFrame(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     Init();
74 
75     (void)Create(parent, id, title, pos, size, style, name);
76 }
77 
~wxGenericMDIParentFrame()78 wxGenericMDIParentFrame::~wxGenericMDIParentFrame()
79 {
80     // Make sure the client window is destructed before the menu bars are!
81     wxDELETE(m_pClientWindow);
82 
83 #if wxUSE_MENUS
84     if (m_pMyMenuBar)
85     {
86         delete m_pMyMenuBar;
87         m_pMyMenuBar = (wxMenuBar *) NULL;
88     }
89 
90     RemoveWindowMenu(GetMenuBar());
91 
92     if (m_pWindowMenu)
93     {
94         delete m_pWindowMenu;
95         m_pWindowMenu = (wxMenu*) NULL;
96     }
97 #endif // wxUSE_MENUS
98 }
99 
Create(wxWindow * parent,wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size,long style,const wxString & name)100 bool wxGenericMDIParentFrame::Create(wxWindow *parent,
101                               wxWindowID id,
102                               const wxString& title,
103                               const wxPoint& pos,
104                               const wxSize& size,
105                               long style,
106                               const wxString& name)
107 {
108   // this style can be used to prevent a window from having the standard MDI
109   // "Window" menu
110   if ( !(style & wxFRAME_NO_WINDOW_MENU) )
111   {
112 #if wxUSE_MENUS
113       m_pWindowMenu = new wxMenu;
114 
115       m_pWindowMenu->Append(wxWINDOWCLOSE,    _("Cl&ose"));
116       m_pWindowMenu->Append(wxWINDOWCLOSEALL, _("Close All"));
117       m_pWindowMenu->AppendSeparator();
118       m_pWindowMenu->Append(wxWINDOWNEXT,     _("&Next"));
119       m_pWindowMenu->Append(wxWINDOWPREV,     _("&Previous"));
120 #endif // wxUSE_MENUS
121   }
122 
123   wxFrame::Create( parent, id, title, pos, size, style, name );
124 
125   OnCreateClient();
126 
127   return true;
128 }
129 
130 #if wxUSE_MENUS
SetWindowMenu(wxMenu * pMenu)131 void wxGenericMDIParentFrame::SetWindowMenu(wxMenu* pMenu)
132 {
133     // Replace the window menu from the currently loaded menu bar.
134     wxMenuBar *pMenuBar = GetMenuBar();
135 
136     if (m_pWindowMenu)
137     {
138         RemoveWindowMenu(pMenuBar);
139 
140         wxDELETE(m_pWindowMenu);
141     }
142 
143     if (pMenu)
144     {
145         m_pWindowMenu = pMenu;
146 
147         AddWindowMenu(pMenuBar);
148     }
149 }
150 
SetMenuBar(wxMenuBar * pMenuBar)151 void wxGenericMDIParentFrame::SetMenuBar(wxMenuBar *pMenuBar)
152 {
153     // Remove the Window menu from the old menu bar
154     RemoveWindowMenu(GetMenuBar());
155     // Add the Window menu to the new menu bar.
156     AddWindowMenu(pMenuBar);
157 
158     wxFrame::SetMenuBar(pMenuBar);
159 }
160 #endif // wxUSE_MENUS
161 
SetChildMenuBar(wxGenericMDIChildFrame * pChild)162 void wxGenericMDIParentFrame::SetChildMenuBar(wxGenericMDIChildFrame *pChild)
163 {
164 #if wxUSE_MENUS
165     if (pChild  == (wxGenericMDIChildFrame *) NULL)
166     {
167         // No Child, set Our menu bar back.
168         SetMenuBar(m_pMyMenuBar);
169 
170         // Make sure we know our menu bar is in use
171         m_pMyMenuBar = (wxMenuBar*) NULL;
172     }
173     else
174     {
175         if (pChild->GetMenuBar() == (wxMenuBar*) NULL)
176             return;
177 
178         // Do we need to save the current bar?
179         if (m_pMyMenuBar == NULL)
180             m_pMyMenuBar = GetMenuBar();
181 
182         SetMenuBar(pChild->GetMenuBar());
183     }
184 #endif // wxUSE_MENUS
185 }
186 
ProcessEvent(wxEvent & event)187 bool wxGenericMDIParentFrame::ProcessEvent(wxEvent& event)
188 {
189     /*
190      * Redirect events to active child first.
191      */
192 
193     // Stops the same event being processed repeatedly
194     static wxEventType inEvent = wxEVT_NULL;
195     if (inEvent == event.GetEventType())
196         return false;
197 
198     inEvent = event.GetEventType();
199 
200     // Let the active child (if any) process the event first.
201     bool res = false;
202     if (m_pActiveChild && event.IsKindOf(CLASSINFO(wxCommandEvent))
203 #if 0
204         /* This is sure to not give problems... */
205         && (event.GetEventType() == wxEVT_COMMAND_MENU_SELECTED ||
206             event.GetEventType() == wxEVT_UPDATE_UI )
207 #else
208         /* This was tested on wxMSW and worked... */
209         && event.GetEventObject() != m_pClientWindow
210         && !(event.GetEventType() == wxEVT_ACTIVATE ||
211              event.GetEventType() == wxEVT_SET_FOCUS ||
212              event.GetEventType() == wxEVT_KILL_FOCUS ||
213              event.GetEventType() == wxEVT_CHILD_FOCUS ||
214              event.GetEventType() == wxEVT_COMMAND_SET_FOCUS ||
215              event.GetEventType() == wxEVT_COMMAND_KILL_FOCUS )
216 #endif
217        )
218     {
219         res = m_pActiveChild->GetEventHandler()->ProcessEvent(event);
220     }
221 
222     // If the event was not handled this frame will handle it!
223     if (!res)
224     {
225         res = GetEventHandler()->wxEvtHandler::ProcessEvent(event);
226     }
227 
228     inEvent = wxEVT_NULL;
229 
230     return res;
231 }
232 
GetActiveChild() const233 wxGenericMDIChildFrame *wxGenericMDIParentFrame::GetActiveChild() const
234 {
235     return m_pActiveChild;
236 }
237 
SetActiveChild(wxGenericMDIChildFrame * pChildFrame)238 void wxGenericMDIParentFrame::SetActiveChild(wxGenericMDIChildFrame* pChildFrame)
239 {
240     m_pActiveChild = pChildFrame;
241 }
242 
GetClientWindow() const243 wxGenericMDIClientWindow *wxGenericMDIParentFrame::GetClientWindow() const
244 {
245     return m_pClientWindow;
246 }
247 
OnCreateClient()248 wxGenericMDIClientWindow *wxGenericMDIParentFrame::OnCreateClient()
249 {
250 #if wxUSE_GENERIC_MDI_AS_NATIVE
251     m_pClientWindow = new wxMDIClientWindow( this );
252 #else
253     m_pClientWindow = new wxGenericMDIClientWindow( this );
254 #endif
255     return m_pClientWindow;
256 }
257 
ActivateNext()258 void wxGenericMDIParentFrame::ActivateNext()
259 {
260     if (m_pClientWindow && m_pClientWindow->GetSelection() != -1)
261     {
262         size_t active = m_pClientWindow->GetSelection() + 1;
263         if (active >= m_pClientWindow->GetPageCount())
264             active = 0;
265 
266         m_pClientWindow->SetSelection(active);
267     }
268 }
269 
ActivatePrevious()270 void wxGenericMDIParentFrame::ActivatePrevious()
271 {
272     if (m_pClientWindow && m_pClientWindow->GetSelection() != -1)
273     {
274         int active = m_pClientWindow->GetSelection() - 1;
275         if (active < 0)
276             active = m_pClientWindow->GetPageCount() - 1;
277 
278         m_pClientWindow->SetSelection(active);
279     }
280 }
281 
Init()282 void wxGenericMDIParentFrame::Init()
283 {
284     m_pClientWindow = (wxGenericMDIClientWindow *) NULL;
285     m_pActiveChild = (wxGenericMDIChildFrame *) NULL;
286 #if wxUSE_MENUS
287     m_pWindowMenu = (wxMenu *) NULL;
288     m_pMyMenuBar = (wxMenuBar*) NULL;
289 #endif // wxUSE_MENUS
290 }
291 
292 #if wxUSE_MENUS
RemoveWindowMenu(wxMenuBar * pMenuBar)293 void wxGenericMDIParentFrame::RemoveWindowMenu(wxMenuBar *pMenuBar)
294 {
295     if (pMenuBar && m_pWindowMenu)
296     {
297         // Remove old window menu
298         int pos = pMenuBar->FindMenu(_("&Window"));
299         if (pos != wxNOT_FOUND)
300         {
301             wxASSERT(m_pWindowMenu == pMenuBar->GetMenu(pos)); // DBG:: We're going to delete the wrong menu!!!
302             pMenuBar->Remove(pos);
303         }
304     }
305 }
306 
AddWindowMenu(wxMenuBar * pMenuBar)307 void wxGenericMDIParentFrame::AddWindowMenu(wxMenuBar *pMenuBar)
308 {
309     if (pMenuBar && m_pWindowMenu)
310     {
311         int pos = pMenuBar->FindMenu(wxGetStockLabel(wxID_HELP,false));
312         if (pos == wxNOT_FOUND)
313         {
314             pMenuBar->Append(m_pWindowMenu, _("&Window"));
315         }
316         else
317         {
318             pMenuBar->Insert(pos, m_pWindowMenu, _("&Window"));
319         }
320     }
321 }
322 
DoHandleMenu(wxCommandEvent & event)323 void wxGenericMDIParentFrame::DoHandleMenu(wxCommandEvent &event)
324 {
325     switch (event.GetId())
326     {
327     case wxWINDOWCLOSE:
328         if (m_pActiveChild)
329         {
330             m_pActiveChild->Close();
331         }
332         break;
333     case wxWINDOWCLOSEALL:
334         {
335 #if 0   // code is only needed if next #if is set to 0!
336             wxGenericMDIChildFrame *pFirstActiveChild = m_pActiveChild;
337 #endif
338             while (m_pActiveChild)
339             {
340                 if (!m_pActiveChild->Close())
341                 {
342                     return; // We failed...
343                 }
344                 else
345                 {
346 #if 1   // What's best? Delayed deleting or immediate deleting?
347                     delete m_pActiveChild;
348                     m_pActiveChild = NULL;
349 #else
350                     ActivateNext();
351 
352                     if (pFirstActiveChild == m_pActiveChild)
353                         return; // We've called Close on all items, no need to continue.
354 #endif
355                 }
356             }
357         }
358         break;
359     case wxWINDOWNEXT:
360         ActivateNext();
361         break;
362     case wxWINDOWPREV:
363         ActivatePrevious();
364         break;
365     default :
366         event.Skip();
367     }
368 }
369 #endif // wxUSE_MENUS
370 
DoGetClientSize(int * width,int * height) const371 void wxGenericMDIParentFrame::DoGetClientSize(int *width, int *height) const
372 {
373     wxFrame::DoGetClientSize( width, height );
374 }
375 
376 
377 //-----------------------------------------------------------------------------
378 // wxGenericMDIChildFrame
379 //-----------------------------------------------------------------------------
380 
IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIChildFrame,wxPanel)381 IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIChildFrame, wxPanel)
382 
383 BEGIN_EVENT_TABLE(wxGenericMDIChildFrame, wxPanel)
384     EVT_MENU_HIGHLIGHT_ALL(wxGenericMDIChildFrame::OnMenuHighlight)
385     EVT_ACTIVATE(wxGenericMDIChildFrame::OnActivate)
386 
387     EVT_CLOSE(wxGenericMDIChildFrame::OnCloseWindow)
388     EVT_SIZE(wxGenericMDIChildFrame::OnSize)
389 END_EVENT_TABLE()
390 
391 wxGenericMDIChildFrame::wxGenericMDIChildFrame()
392 {
393     Init();
394 }
395 
wxGenericMDIChildFrame(wxGenericMDIParentFrame * parent,wxWindowID id,const wxString & title,const wxPoint & WXUNUSED (pos),const wxSize & size,long style,const wxString & name)396 wxGenericMDIChildFrame::wxGenericMDIChildFrame( wxGenericMDIParentFrame *parent,
397       wxWindowID id, const wxString& title,
398       const wxPoint& WXUNUSED(pos), const wxSize& size,
399       long style, const wxString& name )
400 {
401     Init();
402 
403     Create( parent, id, title, wxDefaultPosition, size, style, name );
404 }
405 
~wxGenericMDIChildFrame()406 wxGenericMDIChildFrame::~wxGenericMDIChildFrame()
407 {
408     wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame();
409 
410     if (pParentFrame != NULL)
411     {
412         bool bActive = false;
413         if (pParentFrame->GetActiveChild() == this)
414         {
415             pParentFrame->SetActiveChild((wxGenericMDIChildFrame*) NULL);
416             pParentFrame->SetChildMenuBar((wxGenericMDIChildFrame*) NULL);
417             bActive = true;
418         }
419 
420         wxGenericMDIClientWindow *pClientWindow = pParentFrame->GetClientWindow();
421 
422         // Remove page if still there
423         size_t pos;
424         for (pos = 0; pos < pClientWindow->GetPageCount(); pos++)
425         {
426             if (pClientWindow->GetPage(pos) == this)
427             {
428                 if (pClientWindow->RemovePage(pos))
429                     pClientWindow->Refresh();
430                 break;
431             }
432         }
433 
434         if (bActive)
435         {
436             // Set the new selection to the a remaining page
437             if (pClientWindow->GetPageCount() > pos)
438             {
439                 pClientWindow->SetSelection(pos);
440             }
441             else
442             {
443                 if ((int)pClientWindow->GetPageCount() - 1 >= 0)
444                     pClientWindow->SetSelection(pClientWindow->GetPageCount() - 1);
445             }
446         }
447     }
448 
449 #if wxUSE_MENUS
450     wxDELETE(m_pMenuBar);
451 #endif // wxUSE_MENUS
452 }
453 
Create(wxGenericMDIParentFrame * parent,wxWindowID id,const wxString & title,const wxPoint & WXUNUSED (pos),const wxSize & size,long style,const wxString & name)454 bool wxGenericMDIChildFrame::Create( wxGenericMDIParentFrame *parent,
455       wxWindowID id, const wxString& title,
456       const wxPoint& WXUNUSED(pos), const wxSize& size,
457       long style, const wxString& name )
458 {
459     wxGenericMDIClientWindow* pClientWindow = parent->GetClientWindow();
460 
461     wxASSERT_MSG((pClientWindow != (wxWindow*) NULL), wxT("Missing MDI client window.") );
462 
463     wxPanel::Create(pClientWindow, id, wxDefaultPosition, size, style, name);
464 
465     SetMDIParentFrame(parent);
466 
467     // This is the currently active child
468     parent->SetActiveChild(this);
469 
470     m_Title = title;
471 
472     pClientWindow->AddPage(this, title, true);
473     ApplyMDIChildFrameRect();   // Ok confirme the size change!
474     pClientWindow->Refresh();
475 
476     return true;
477 }
478 
479 #if wxUSE_MENUS
SetMenuBar(wxMenuBar * menu_bar)480 void wxGenericMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar )
481 {
482     wxMenuBar *pOldMenuBar = m_pMenuBar;
483     m_pMenuBar = menu_bar;
484 
485     if (m_pMenuBar)
486     {
487         wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame();
488 
489         if (pParentFrame != NULL)
490         {
491             m_pMenuBar->SetParent(pParentFrame);
492 
493             if (pParentFrame->GetActiveChild() == this)
494             {
495                 // Replace current menu bars
496                 if (pOldMenuBar)
497                     pParentFrame->SetChildMenuBar((wxGenericMDIChildFrame*) NULL);
498                 pParentFrame->SetChildMenuBar((wxGenericMDIChildFrame*) this);
499             }
500         }
501     }
502 }
503 
GetMenuBar() const504 wxMenuBar *wxGenericMDIChildFrame::GetMenuBar() const
505 {
506     return m_pMenuBar;
507 }
508 #endif // wxUSE_MENUS
509 
SetTitle(const wxString & title)510 void wxGenericMDIChildFrame::SetTitle(const wxString& title)
511 {
512     m_Title = title;
513 
514     wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame();
515 
516     if (pParentFrame != NULL)
517     {
518         wxGenericMDIClientWindow * pClientWindow = pParentFrame->GetClientWindow();
519 
520         if (pClientWindow != NULL)
521         {
522             size_t pos;
523             for (pos = 0; pos < pClientWindow->GetPageCount(); pos++)
524             {
525                 if (pClientWindow->GetPage(pos) == this)
526                 {
527                     pClientWindow->SetPageText(pos, m_Title);
528                     break;
529                 }
530             }
531         }
532     }
533 }
534 
GetTitle() const535 wxString wxGenericMDIChildFrame::GetTitle() const
536 {
537     return m_Title;
538 }
539 
Activate()540 void wxGenericMDIChildFrame::Activate()
541 {
542     wxGenericMDIParentFrame *pParentFrame = GetMDIParentFrame();
543 
544     if (pParentFrame != NULL)
545     {
546         wxGenericMDIClientWindow * pClientWindow = pParentFrame->GetClientWindow();
547 
548         if (pClientWindow != NULL)
549         {
550             size_t pos;
551             for (pos = 0; pos < pClientWindow->GetPageCount(); pos++)
552             {
553                 if (pClientWindow->GetPage(pos) == this)
554                 {
555                     pClientWindow->SetSelection(pos);
556                     break;
557                 }
558             }
559         }
560     }
561 }
562 
OnMenuHighlight(wxMenuEvent & event)563 void wxGenericMDIChildFrame::OnMenuHighlight(wxMenuEvent& event)
564 {
565 #if wxUSE_STATUSBAR
566     if ( m_pMDIParentFrame)
567     {
568         // we don't have any help text for this item,
569         // but may be the MDI frame does?
570         m_pMDIParentFrame->OnMenuHighlight(event);
571     }
572 #else
573     wxUnusedVar(event);
574 #endif // wxUSE_STATUSBAR
575 }
576 
OnActivate(wxActivateEvent & WXUNUSED (event))577 void wxGenericMDIChildFrame::OnActivate(wxActivateEvent& WXUNUSED(event))
578 {
579     // Do mothing.
580 }
581 
582 /*** Copied from top level..! ***/
583 // default resizing behaviour - if only ONE subwindow, resize to fill the
584 // whole client area
OnSize(wxSizeEvent & WXUNUSED (event))585 void wxGenericMDIChildFrame::OnSize(wxSizeEvent& WXUNUSED(event))
586 {
587     // if we're using constraints or sizers - do use them
588     if ( GetAutoLayout() )
589     {
590         Layout();
591     }
592     else
593     {
594         // do we have _exactly_ one child?
595         wxWindow *child = (wxWindow *)NULL;
596         for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
597               node;
598               node = node->GetNext() )
599         {
600             wxWindow *win = node->GetData();
601 
602             // exclude top level and managed windows (status bar isn't
603             // currently in the children list except under wxMac anyhow, but
604             // it makes no harm to test for it)
605             if ( !win->IsTopLevel() /*&& !IsOneOfBars(win)*/ )
606             {
607                 if ( child )
608                 {
609                     return;     // it's our second subwindow - nothing to do
610                 }
611 
612                 child = win;
613             }
614         }
615 
616         // do we have any children at all?
617         if ( child )
618         {
619             // exactly one child - set it's size to fill the whole frame
620             int clientW, clientH;
621             DoGetClientSize(&clientW, &clientH);
622 
623             // for whatever reasons, wxGTK wants to have a small offset - it
624             // probably looks better with it?
625 #ifdef __WXGTK__
626             static const int ofs = 1;
627 #else
628             static const int ofs = 0;
629 #endif
630 
631             child->SetSize(ofs, ofs, clientW - 2*ofs, clientH - 2*ofs);
632         }
633     }
634 }
635 
636 /*** Copied from top level..! ***/
637 // The default implementation for the close window event.
OnCloseWindow(wxCloseEvent & WXUNUSED (event))638 void wxGenericMDIChildFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
639 {
640     Destroy();
641 }
642 
SetMDIParentFrame(wxGenericMDIParentFrame * parentFrame)643 void wxGenericMDIChildFrame::SetMDIParentFrame(wxGenericMDIParentFrame* parentFrame)
644 {
645     m_pMDIParentFrame = parentFrame;
646 }
647 
GetMDIParentFrame() const648 wxGenericMDIParentFrame* wxGenericMDIChildFrame::GetMDIParentFrame() const
649 {
650     return m_pMDIParentFrame;
651 }
652 
Init()653 void wxGenericMDIChildFrame::Init()
654 {
655     m_pMDIParentFrame = (wxGenericMDIParentFrame *) NULL;
656 #if wxUSE_MENUS
657     m_pMenuBar = (wxMenuBar *) NULL;
658 #endif // wxUSE_MENUS
659 }
660 
DoMoveWindow(int x,int y,int width,int height)661 void wxGenericMDIChildFrame::DoMoveWindow(int x, int y, int width, int height)
662 {
663     m_MDIRect = wxRect(x, y, width, height);
664 }
665 
ApplyMDIChildFrameRect()666 void wxGenericMDIChildFrame::ApplyMDIChildFrameRect()
667 {
668     wxPanel::DoMoveWindow(m_MDIRect.x, m_MDIRect.y, m_MDIRect.width, m_MDIRect.height);
669 }
670 
671 //-----------------------------------------------------------------------------
672 // wxGenericMDIClientWindow
673 //-----------------------------------------------------------------------------
674 
675 #define wxID_NOTEBOOK_CLIENT_AREA wxID_HIGHEST + 100
676 
IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIClientWindow,wxNotebook)677 IMPLEMENT_DYNAMIC_CLASS(wxGenericMDIClientWindow, wxNotebook)
678 
679 BEGIN_EVENT_TABLE(wxGenericMDIClientWindow, wxNotebook)
680     EVT_NOTEBOOK_PAGE_CHANGED(wxID_NOTEBOOK_CLIENT_AREA, wxGenericMDIClientWindow::OnPageChanged)
681     EVT_SIZE(wxGenericMDIClientWindow::OnSize)
682 END_EVENT_TABLE()
683 
684 
685 wxGenericMDIClientWindow::wxGenericMDIClientWindow()
686 {
687 }
688 
wxGenericMDIClientWindow(wxGenericMDIParentFrame * parent,long style)689 wxGenericMDIClientWindow::wxGenericMDIClientWindow( wxGenericMDIParentFrame *parent, long style )
690 {
691     CreateClient( parent, style );
692 }
693 
~wxGenericMDIClientWindow()694 wxGenericMDIClientWindow::~wxGenericMDIClientWindow()
695 {
696     DestroyChildren();
697 }
698 
CreateClient(wxGenericMDIParentFrame * parent,long style)699 bool wxGenericMDIClientWindow::CreateClient( wxGenericMDIParentFrame *parent, long style )
700 {
701     SetWindowStyleFlag(style);
702 
703     bool success = wxNotebook::Create(parent, wxID_NOTEBOOK_CLIENT_AREA, wxPoint(0,0), wxSize(100, 100), 0);
704     if (success)
705     {
706         /*
707         wxFont font(10, wxSWISS, wxNORMAL, wxNORMAL);
708         wxFont selFont(10, wxSWISS, wxNORMAL, wxBOLD);
709         GetTabView()->SetTabFont(font);
710         GetTabView()->SetSelectedTabFont(selFont);
711         GetTabView()->SetTabSize(120, 18);
712         GetTabView()->SetTabSelectionHeight(20);
713         */
714         return true;
715     }
716     else
717         return false;
718 }
719 
SetSelection(size_t nPage)720 int wxGenericMDIClientWindow::SetSelection(size_t nPage)
721 {
722     int oldSelection = wxNotebook::SetSelection(nPage);
723 
724 #if !defined(__WXMSW__) // No need to do this for wxMSW as wxNotebook::SetSelection()
725                         // will already cause this to be done!
726     // Handle the page change.
727     PageChanged(oldSelection, nPage);
728 #endif
729 
730     return oldSelection;
731 }
732 
PageChanged(int OldSelection,int newSelection)733 void wxGenericMDIClientWindow::PageChanged(int OldSelection, int newSelection)
734 {
735     // Don't do to much work, only when something realy should change!
736     if (OldSelection == newSelection)
737         return;
738     // Again check if we realy need to do this...
739     if (newSelection != -1)
740     {
741         wxGenericMDIChildFrame* child = (wxGenericMDIChildFrame *)GetPage(newSelection);
742 
743         if (child->GetMDIParentFrame()->GetActiveChild() == child)
744             return;
745     }
746 
747     // Notify old active child that it has been deactivated
748     if (OldSelection != -1)
749     {
750         wxGenericMDIChildFrame* oldChild = (wxGenericMDIChildFrame *)GetPage(OldSelection);
751         if (oldChild)
752         {
753             wxActivateEvent event(wxEVT_ACTIVATE, false, oldChild->GetId());
754             event.SetEventObject( oldChild );
755             oldChild->GetEventHandler()->ProcessEvent(event);
756         }
757     }
758 
759     // Notify new active child that it has been activated
760     if (newSelection != -1)
761     {
762         wxGenericMDIChildFrame* activeChild = (wxGenericMDIChildFrame *)GetPage(newSelection);
763         if (activeChild)
764         {
765             wxActivateEvent event(wxEVT_ACTIVATE, true, activeChild->GetId());
766             event.SetEventObject( activeChild );
767             activeChild->GetEventHandler()->ProcessEvent(event);
768 
769             if (activeChild->GetMDIParentFrame())
770             {
771                 activeChild->GetMDIParentFrame()->SetActiveChild(activeChild);
772                 activeChild->GetMDIParentFrame()->SetChildMenuBar(activeChild);
773             }
774         }
775     }
776 }
777 
OnPageChanged(wxNotebookEvent & event)778 void wxGenericMDIClientWindow::OnPageChanged(wxNotebookEvent& event)
779 {
780     PageChanged(event.GetOldSelection(), event.GetSelection());
781 
782     event.Skip();
783 }
784 
OnSize(wxSizeEvent & event)785 void wxGenericMDIClientWindow::OnSize(wxSizeEvent& event)
786 {
787     wxNotebook::OnSize(event);
788 
789     size_t pos;
790     for (pos = 0; pos < GetPageCount(); pos++)
791     {
792         ((wxGenericMDIChildFrame *)GetPage(pos))->ApplyMDIChildFrameRect();
793     }
794 }
795 
796 
797 /*
798  * Define normal wxMDI classes based on wxGenericMDI
799  */
800 
801 #if wxUSE_GENERIC_MDI_AS_NATIVE
802 
GetActiveChild() const803 wxMDIChildFrame * wxMDIParentFrame::GetActiveChild() const
804     {
805         wxGenericMDIChildFrame *pGFrame = wxGenericMDIParentFrame::GetActiveChild();
806         wxMDIChildFrame *pFrame = wxDynamicCast(pGFrame, wxMDIChildFrame);
807 
808         wxASSERT_MSG(!(pFrame == NULL && pGFrame != NULL), wxT("Active frame is class not derived from wxMDIChildFrame!"));
809 
810         return pFrame;
811     }
812 
813 IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxGenericMDIParentFrame)
814 IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxGenericMDIChildFrame)
815 IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxGenericMDIClientWindow)
816 
817 #endif // wxUSE_GENERIC_MDI_AS_NATIVE
818 
819 #endif // wxUSE_MDI
820 
821