1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/mdig.cpp
3 // Purpose: Generic MDI (Multiple Document Interface) classes
4 // Author: Hans Van Leemputten
5 // Modified by: Benjamin I. Williams / Kirix Corporation
8 // Copyright: (c) Hans Van Leemputten
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/aui/tabmdi.h"
38 #include "wx/stockitem.h"
48 //-----------------------------------------------------------------------------
49 // wxTabMDIParentFrame
50 //-----------------------------------------------------------------------------
52 IMPLEMENT_DYNAMIC_CLASS(wxTabMDIParentFrame
, wxFrame
)
54 BEGIN_EVENT_TABLE(wxTabMDIParentFrame
, wxFrame
)
56 EVT_MENU (wxID_ANY
, wxTabMDIParentFrame::DoHandleMenu
)
60 wxTabMDIParentFrame::wxTabMDIParentFrame()
65 wxTabMDIParentFrame::wxTabMDIParentFrame(wxWindow
*parent
,
67 const wxString
& title
,
74 (void)Create(parent
, id
, title
, pos
, size
, style
, name
);
77 wxTabMDIParentFrame::~wxTabMDIParentFrame()
79 // Make sure the client window is destructed before the menu bars are!
80 wxDELETE(m_pClientWindow
);
83 RemoveWindowMenu(GetMenuBar());
88 bool wxTabMDIParentFrame::Create(wxWindow
*parent
,
90 const wxString
& title
,
97 // this style can be used to prevent a window from having the standard MDI
99 if (!(style
& wxFRAME_NO_WINDOW_MENU
))
101 m_pWindowMenu
= new wxMenu
;
102 m_pWindowMenu
->Append(wxWINDOWCLOSE
, _("Cl&ose"));
103 m_pWindowMenu
->Append(wxWINDOWCLOSEALL
, _("Close All"));
104 m_pWindowMenu
->AppendSeparator();
105 m_pWindowMenu
->Append(wxWINDOWNEXT
, _("&Next"));
106 m_pWindowMenu
->Append(wxWINDOWPREV
, _("&Previous"));
108 #endif // wxUSE_MENUS
110 wxFrame::Create(parent
, id
, title
, pos
, size
, style
, name
);
116 void wxTabMDIParentFrame::SetWindowMenu(wxMenu
* pMenu
)
118 // Replace the window menu from the currently loaded menu bar.
119 wxMenuBar
*pMenuBar
= GetMenuBar();
123 RemoveWindowMenu(pMenuBar
);
124 wxDELETE(m_pWindowMenu
);
129 m_pWindowMenu
= pMenu
;
130 AddWindowMenu(pMenuBar
);
134 void wxTabMDIParentFrame::SetMenuBar(wxMenuBar
*pMenuBar
)
136 // Remove the Window menu from the old menu bar
137 RemoveWindowMenu(GetMenuBar());
139 // Add the Window menu to the new menu bar.
140 AddWindowMenu(pMenuBar
);
142 wxFrame::SetMenuBar(pMenuBar
);
143 m_pMyMenuBar
= GetMenuBar();
145 #endif // wxUSE_MENUS
147 void wxTabMDIParentFrame::SetChildMenuBar(wxTabMDIChildFrame
* pChild
)
152 // No Child, set Our menu bar back.
153 SetMenuBar(m_pMyMenuBar
);
155 // Make sure we know our menu bar is in use
160 if (pChild
->GetMenuBar() == NULL
)
163 // Do we need to save the current bar?
164 if (m_pMyMenuBar
== NULL
)
165 m_pMyMenuBar
= GetMenuBar();
167 SetMenuBar(pChild
->GetMenuBar());
169 #endif // wxUSE_MENUS
172 bool wxTabMDIParentFrame::ProcessEvent(wxEvent
& event
)
174 // Stops the same event being processed repeatedly
175 static wxEventType inEvent
= wxEVT_NULL
;
176 if (inEvent
== event
.GetEventType())
179 inEvent
= event
.GetEventType();
181 // Let the active child (if any) process the event first.
183 if (m_pActiveChild
&&
184 event
.IsCommandEvent() &&
185 event
.GetEventObject() != m_pClientWindow
&&
186 !(event
.GetEventType() == wxEVT_ACTIVATE
||
187 event
.GetEventType() == wxEVT_SET_FOCUS
||
188 event
.GetEventType() == wxEVT_KILL_FOCUS
||
189 event
.GetEventType() == wxEVT_CHILD_FOCUS
||
190 event
.GetEventType() == wxEVT_COMMAND_SET_FOCUS
||
191 event
.GetEventType() == wxEVT_COMMAND_KILL_FOCUS
)
194 res
= m_pActiveChild
->GetEventHandler()->ProcessEvent(event
);
197 // If the event was not handled this frame will handle it!
200 //res = GetEventHandler()->ProcessEvent(event);
201 res
= wxEvtHandler::ProcessEvent(event
);
204 inEvent
= wxEVT_NULL
;
209 wxTabMDIChildFrame
*wxTabMDIParentFrame::GetActiveChild() const
211 return m_pActiveChild
;
214 void wxTabMDIParentFrame::SetActiveChild(wxTabMDIChildFrame
* pChildFrame
)
216 m_pActiveChild
= pChildFrame
;
219 wxTabMDIClientWindow
*wxTabMDIParentFrame::GetClientWindow() const
221 return m_pClientWindow
;
224 wxTabMDIClientWindow
*wxTabMDIParentFrame::OnCreateClient()
226 m_pClientWindow
= new wxTabMDIClientWindow( this );
227 return m_pClientWindow
;
230 void wxTabMDIParentFrame::ActivateNext()
232 if (m_pClientWindow
&& m_pClientWindow
->GetSelection() != -1)
234 size_t active
= m_pClientWindow
->GetSelection() + 1;
235 if (active
>= m_pClientWindow
->GetPageCount())
238 m_pClientWindow
->SetSelection(active
);
242 void wxTabMDIParentFrame::ActivatePrevious()
244 if (m_pClientWindow
&& m_pClientWindow
->GetSelection() != -1)
246 int active
= m_pClientWindow
->GetSelection() - 1;
248 active
= m_pClientWindow
->GetPageCount() - 1;
250 m_pClientWindow
->SetSelection(active
);
254 void wxTabMDIParentFrame::Init()
256 m_pClientWindow
= NULL
;
257 m_pActiveChild
= NULL
;
259 m_pWindowMenu
= NULL
;
261 #endif // wxUSE_MENUS
265 void wxTabMDIParentFrame::RemoveWindowMenu(wxMenuBar
* pMenuBar
)
267 if (pMenuBar
&& m_pWindowMenu
)
269 // Remove old window menu
270 int pos
= pMenuBar
->FindMenu(_("&Window"));
271 if (pos
!= wxNOT_FOUND
)
273 // DBG:: We're going to delete the wrong menu!!!
274 wxASSERT(m_pWindowMenu
== pMenuBar
->GetMenu(pos
));
275 pMenuBar
->Remove(pos
);
280 void wxTabMDIParentFrame::AddWindowMenu(wxMenuBar
*pMenuBar
)
282 if (pMenuBar
&& m_pWindowMenu
)
284 int pos
= pMenuBar
->FindMenu(wxGetStockLabel(wxID_HELP
,false));
285 if (pos
== wxNOT_FOUND
)
286 pMenuBar
->Append(m_pWindowMenu
, _("&Window"));
288 pMenuBar
->Insert(pos
, m_pWindowMenu
, _("&Window"));
292 void wxTabMDIParentFrame::DoHandleMenu(wxCommandEvent
& event
)
294 switch (event
.GetId())
298 m_pActiveChild
->Close();
300 case wxWINDOWCLOSEALL
:
301 while (m_pActiveChild
)
303 if (!m_pActiveChild
->Close())
309 delete m_pActiveChild
;
310 m_pActiveChild
= NULL
;
324 #endif // wxUSE_MENUS
326 void wxTabMDIParentFrame::DoGetClientSize(int* width
, int* height
) const
328 wxFrame::DoGetClientSize(width
, height
);
331 //-----------------------------------------------------------------------------
332 // wxTabMDIChildFrame
333 //-----------------------------------------------------------------------------
335 IMPLEMENT_DYNAMIC_CLASS(wxTabMDIChildFrame
, wxPanel
)
337 BEGIN_EVENT_TABLE(wxTabMDIChildFrame
, wxPanel
)
338 EVT_MENU_HIGHLIGHT_ALL(wxTabMDIChildFrame::OnMenuHighlight
)
339 EVT_ACTIVATE(wxTabMDIChildFrame::OnActivate
)
340 EVT_CLOSE(wxTabMDIChildFrame::OnCloseWindow
)
343 wxTabMDIChildFrame::wxTabMDIChildFrame()
348 wxTabMDIChildFrame::wxTabMDIChildFrame(wxTabMDIParentFrame
*parent
,
350 const wxString
& title
,
351 const wxPoint
& WXUNUSED(pos
),
354 const wxString
& name
)
357 Create(parent
, id
, title
, wxDefaultPosition
, size
, style
, name
);
360 wxTabMDIChildFrame::~wxTabMDIChildFrame()
363 wxDELETE(m_pMenuBar
);
364 #endif // wxUSE_MENUS
367 bool wxTabMDIChildFrame::Create(wxTabMDIParentFrame
* parent
,
369 const wxString
& title
,
370 const wxPoint
& WXUNUSED(pos
),
373 const wxString
& name
)
375 wxTabMDIClientWindow
* pClientWindow
= parent
->GetClientWindow();
376 wxASSERT_MSG((pClientWindow
!= (wxWindow
*) NULL
), wxT("Missing MDI client window."));
378 wxPanel::Create(pClientWindow
, id
, wxDefaultPosition
, size
, style
|wxNO_BORDER
, name
);
380 SetMDIParentFrame(parent
);
382 // this is the currently active child
383 parent
->SetActiveChild(this);
387 pClientWindow
->AddPage(this, title
, true);
388 pClientWindow
->Refresh();
393 bool wxTabMDIChildFrame::Destroy()
395 wxTabMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
396 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
398 wxTabMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
399 wxASSERT_MSG(pClientWindow
, wxT("Missing MDI Client Window"));
401 bool bActive
= false;
402 if (pParentFrame
->GetActiveChild() == this)
404 pParentFrame
->SetActiveChild(NULL
);
405 pParentFrame
->SetChildMenuBar(NULL
);
409 size_t pos
, page_count
= pClientWindow
->GetPageCount();
410 for (pos
= 0; pos
< page_count
; pos
++)
412 if (pClientWindow
->GetPage(pos
) == this)
413 return pClientWindow
->DeletePage(pos
);
420 wxTabMDIParentFrame* pParentFrame = GetMDIParentFrame();
421 wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame"));
423 bool bActive = false;
424 if (pParentFrame->GetActiveChild() == this)
426 pParentFrame->SetActiveChild(NULL);
427 pParentFrame->SetChildMenuBar(NULL);
431 wxTabMDIClientWindow* pClientWindow = pParentFrame->GetClientWindow();
433 // remove page if it is still there
435 for (pos = 0; pos < pClientWindow->GetPageCount(); pos++)
437 if (pClientWindow->GetPage(pos) == this)
439 if (pClientWindow->RemovePage(pos))
440 pClientWindow->Refresh();
447 // Set the new selection to the a remaining page
448 if (pos < pClientWindow->GetPageCount())
450 pClientWindow->SetSelection(pos);
454 if (pClientWindow->GetPageCount() >= 1)
455 pClientWindow->SetSelection(pClientWindow->GetPageCount() - 1);
459 // delete the child frame with pending delete, as is
460 // customary with frame windows
461 if (!wxPendingDelete.Member(this))
462 wxPendingDelete.Append(this);
469 void wxTabMDIChildFrame::SetMenuBar(wxMenuBar
*menu_bar
)
471 wxMenuBar
*pOldMenuBar
= m_pMenuBar
;
472 m_pMenuBar
= menu_bar
;
476 wxTabMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
477 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
479 m_pMenuBar
->SetParent(pParentFrame
);
480 if (pParentFrame
->GetActiveChild() == this)
482 // replace current menu bars
484 pParentFrame
->SetChildMenuBar(NULL
);
485 pParentFrame
->SetChildMenuBar(this);
490 wxMenuBar
*wxTabMDIChildFrame::GetMenuBar() const
494 #endif // wxUSE_MENUS
496 void wxTabMDIChildFrame::SetTitle(const wxString
& title
)
500 wxTabMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
501 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
503 wxTabMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
504 if (pClientWindow
!= NULL
)
507 for (pos
= 0; pos
< pClientWindow
->GetPageCount(); pos
++)
509 if (pClientWindow
->GetPage(pos
) == this)
511 pClientWindow
->SetPageText(pos
, m_title
);
518 wxString
wxTabMDIChildFrame::GetTitle() const
523 void wxTabMDIChildFrame::Activate()
525 wxTabMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
526 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
528 wxTabMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
530 if (pClientWindow
!= NULL
)
533 for (pos
= 0; pos
< pClientWindow
->GetPageCount(); pos
++)
535 if (pClientWindow
->GetPage(pos
) == this)
537 pClientWindow
->SetSelection(pos
);
544 void wxTabMDIChildFrame::OnMenuHighlight(wxMenuEvent
& event
)
547 if (m_pMDIParentFrame
)
549 // we don't have any help text for this item,
550 // but may be the MDI frame does?
551 m_pMDIParentFrame
->OnMenuHighlight(event
);
555 #endif // wxUSE_STATUSBAR
558 void wxTabMDIChildFrame::OnActivate(wxActivateEvent
& WXUNUSED(event
))
563 void wxTabMDIChildFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
568 void wxTabMDIChildFrame::SetMDIParentFrame(wxTabMDIParentFrame
* parentFrame
)
570 m_pMDIParentFrame
= parentFrame
;
573 wxTabMDIParentFrame
* wxTabMDIChildFrame::GetMDIParentFrame() const
575 return m_pMDIParentFrame
;
578 void wxTabMDIChildFrame::Init()
580 m_pMDIParentFrame
= NULL
;
583 #endif // wxUSE_MENUS
586 bool wxTabMDIChildFrame::Show(bool WXUNUSED(show
))
592 void wxTabMDIChildFrame::DoShow(bool show
)
594 wxWindow::Show(show
);
597 void wxTabMDIChildFrame::DoSetSize(int x
, int y
, int width
, int height
, int WXUNUSED(sizeFlags
))
599 m_mdi_newrect
= wxRect(x
, y
, width
, height
);
602 void wxTabMDIChildFrame::DoMoveWindow(int x
, int y
, int width
, int height
)
604 m_mdi_newrect
= wxRect(x
, y
, width
, height
);
607 void wxTabMDIChildFrame::ApplyMDIChildFrameRect()
609 if (m_mdi_currect
!= m_mdi_newrect
)
611 wxPanel::DoMoveWindow(m_mdi_newrect
.x
, m_mdi_newrect
.y
,
612 m_mdi_newrect
.width
, m_mdi_newrect
.height
);
613 m_mdi_currect
= m_mdi_newrect
;
618 //-----------------------------------------------------------------------------
619 // wxTabMDIClientWindow
620 //-----------------------------------------------------------------------------
622 IMPLEMENT_DYNAMIC_CLASS(wxTabMDIClientWindow
, wxAuiMultiNotebook
)
624 BEGIN_EVENT_TABLE(wxTabMDIClientWindow
, wxAuiMultiNotebook
)
625 EVT_AUINOTEBOOK_PAGE_CHANGED(-1, wxTabMDIClientWindow::OnPageChanged
)
626 EVT_SIZE(wxTabMDIClientWindow::OnSize
)
629 wxTabMDIClientWindow::wxTabMDIClientWindow()
633 wxTabMDIClientWindow::wxTabMDIClientWindow(wxTabMDIParentFrame
* parent
, long style
)
635 CreateClient(parent
, style
);
638 wxTabMDIClientWindow::~wxTabMDIClientWindow()
643 bool wxTabMDIClientWindow::CreateClient(wxTabMDIParentFrame
* parent
, long style
)
645 SetWindowStyleFlag(style
);
647 if (!wxAuiMultiNotebook::Create(parent
,
656 wxColour bkcolour
= wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
);
657 SetBackgroundColour(bkcolour
);
659 m_mgr
.GetArtProvider()->SetColour(wxAUI_ART_BACKGROUND_COLOUR
, bkcolour
);
664 int wxTabMDIClientWindow::SetSelection(size_t nPage
)
666 return wxAuiMultiNotebook::SetSelection(nPage
);
669 void wxTabMDIClientWindow::PageChanged(int old_selection
, int new_selection
)
671 // don't do anything if the page doesn't actually change
672 if (old_selection
== new_selection
)
675 // don't do anything if the new page is already active
676 if (new_selection
!= -1)
678 wxTabMDIChildFrame
* child
= (wxTabMDIChildFrame
*)GetPage(new_selection
);
679 if (child
->GetMDIParentFrame()->GetActiveChild() == child
)
683 // notify old active child that it has been deactivated
684 if (old_selection
!= -1)
686 wxTabMDIChildFrame
* old_child
= (wxTabMDIChildFrame
*)GetPage(old_selection
);
687 wxASSERT_MSG(old_child
, wxT("wxTabMDIClientWindow::PageChanged - null page pointer"));
689 wxActivateEvent
event(wxEVT_ACTIVATE
, false, old_child
->GetId());
690 event
.SetEventObject(old_child
);
691 old_child
->GetEventHandler()->ProcessEvent(event
);
694 // notify new active child that it has been activated
695 if (new_selection
!= -1)
697 wxTabMDIChildFrame
* active_child
= (wxTabMDIChildFrame
*)GetPage(new_selection
);
698 wxASSERT_MSG(active_child
, wxT("wxTabMDIClientWindow::PageChanged - null page pointer"));
700 wxActivateEvent
event(wxEVT_ACTIVATE
, true, active_child
->GetId());
701 event
.SetEventObject(active_child
);
702 active_child
->GetEventHandler()->ProcessEvent(event
);
704 if (active_child
->GetMDIParentFrame())
706 active_child
->GetMDIParentFrame()->SetActiveChild(active_child
);
707 active_child
->GetMDIParentFrame()->SetChildMenuBar(active_child
);
712 void wxTabMDIClientWindow::OnPageChanged(wxAuiNotebookEvent
& evt
)
714 PageChanged(evt
.GetOldSelection(), evt
.GetSelection());
718 void wxTabMDIClientWindow::OnSize(wxSizeEvent
& evt
)
720 wxAuiMultiNotebook::OnSize(evt
);
722 for (size_t pos
= 0; pos
< GetPageCount(); pos
++)
723 ((wxTabMDIChildFrame
*)GetPage(pos
))->ApplyMDIChildFrameRect();