1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/aui/tabmdi.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"
30 #include "wx/aui/tabmdi.h"
37 #include "wx/settings.h"
40 #include "wx/stockitem.h"
41 #include "wx/aui/dockart.h"
51 //-----------------------------------------------------------------------------
52 // wxAuiMDIParentFrame
53 //-----------------------------------------------------------------------------
55 IMPLEMENT_DYNAMIC_CLASS(wxAuiMDIParentFrame
, wxFrame
)
57 BEGIN_EVENT_TABLE(wxAuiMDIParentFrame
, wxFrame
)
59 EVT_MENU (wxID_ANY
, wxAuiMDIParentFrame::DoHandleMenu
)
60 EVT_UPDATE_UI (wxID_ANY
, wxAuiMDIParentFrame::DoHandleUpdateUI
)
64 wxAuiMDIParentFrame::wxAuiMDIParentFrame()
69 wxAuiMDIParentFrame::wxAuiMDIParentFrame(wxWindow
*parent
,
71 const wxString
& title
,
78 (void)Create(parent
, id
, title
, pos
, size
, style
, name
);
81 wxAuiMDIParentFrame::~wxAuiMDIParentFrame()
83 // Make sure the client window is destructed before the menu bars are!
84 wxDELETE(m_pClientWindow
);
87 wxDELETE(m_pMyMenuBar
);
88 RemoveWindowMenu(GetMenuBar());
89 wxDELETE(m_pWindowMenu
);
93 bool wxAuiMDIParentFrame::Create(wxWindow
*parent
,
95 const wxString
& title
,
102 // this style can be used to prevent a window from having the standard MDI
104 if (!(style
& wxFRAME_NO_WINDOW_MENU
))
106 m_pWindowMenu
= new wxMenu
;
107 m_pWindowMenu
->Append(wxWINDOWCLOSE
, _("Cl&ose"));
108 m_pWindowMenu
->Append(wxWINDOWCLOSEALL
, _("Close All"));
109 m_pWindowMenu
->AppendSeparator();
110 m_pWindowMenu
->Append(wxWINDOWNEXT
, _("&Next"));
111 m_pWindowMenu
->Append(wxWINDOWPREV
, _("&Previous"));
113 #endif // wxUSE_MENUS
115 if ( !wxFrame::Create(parent
, id
, title
, pos
, size
, style
, name
) )
118 m_pClientWindow
= OnCreateClient();
119 return m_pClientWindow
!= NULL
;
123 void wxAuiMDIParentFrame::SetArtProvider(wxAuiTabArt
* provider
)
127 m_pClientWindow
->SetArtProvider(provider
);
131 wxAuiTabArt
* wxAuiMDIParentFrame::GetArtProvider()
133 if (!m_pClientWindow
)
136 return m_pClientWindow
->GetArtProvider();
139 wxAuiNotebook
* wxAuiMDIParentFrame::GetNotebook() const
141 return static_cast<wxAuiNotebook
*>(m_pClientWindow
);
147 void wxAuiMDIParentFrame::SetWindowMenu(wxMenu
* pMenu
)
149 // Replace the window menu from the currently loaded menu bar.
150 wxMenuBar
*pMenuBar
= GetMenuBar();
154 RemoveWindowMenu(pMenuBar
);
155 wxDELETE(m_pWindowMenu
);
160 m_pWindowMenu
= pMenu
;
161 AddWindowMenu(pMenuBar
);
165 void wxAuiMDIParentFrame::SetMenuBar(wxMenuBar
* pMenuBar
)
167 // Remove the Window menu from the old menu bar
168 RemoveWindowMenu(GetMenuBar());
170 // Add the Window menu to the new menu bar.
171 AddWindowMenu(pMenuBar
);
173 wxFrame::SetMenuBar(pMenuBar
);
174 //m_pMyMenuBar = GetMenuBar();
176 #endif // wxUSE_MENUS
178 void wxAuiMDIParentFrame::SetChildMenuBar(wxAuiMDIChildFrame
* pChild
)
183 // No Child, set Our menu bar back.
185 SetMenuBar(m_pMyMenuBar
);
187 SetMenuBar(GetMenuBar());
189 // Make sure we know our menu bar is in use
194 if (pChild
->GetMenuBar() == NULL
)
197 // Do we need to save the current bar?
198 if (m_pMyMenuBar
== NULL
)
199 m_pMyMenuBar
= GetMenuBar();
201 SetMenuBar(pChild
->GetMenuBar());
203 #endif // wxUSE_MENUS
206 bool wxAuiMDIParentFrame::ProcessEvent(wxEvent
& event
)
208 // stops the same event being processed repeatedly
209 if (m_pLastEvt
== &event
)
213 // let the active child (if any) process the event first.
215 if (m_pActiveChild
&&
216 event
.IsCommandEvent() &&
217 event
.GetEventObject() != m_pClientWindow
&&
218 !(event
.GetEventType() == wxEVT_ACTIVATE
||
219 event
.GetEventType() == wxEVT_SET_FOCUS
||
220 event
.GetEventType() == wxEVT_KILL_FOCUS
||
221 event
.GetEventType() == wxEVT_CHILD_FOCUS
||
222 event
.GetEventType() == wxEVT_COMMAND_SET_FOCUS
||
223 event
.GetEventType() == wxEVT_COMMAND_KILL_FOCUS
)
226 res
= m_pActiveChild
->GetEventHandler()->ProcessEvent(event
);
231 // if the event was not handled this frame will handle it,
232 // which is why we need the protection code at the beginning
234 res
= wxEvtHandler::ProcessEvent(event
);
242 wxAuiMDIChildFrame
*wxAuiMDIParentFrame::GetActiveChild() const
244 return m_pActiveChild
;
247 void wxAuiMDIParentFrame::SetActiveChild(wxAuiMDIChildFrame
* pChildFrame
)
249 m_pActiveChild
= pChildFrame
;
252 wxAuiMDIClientWindow
*wxAuiMDIParentFrame::GetClientWindow() const
254 return m_pClientWindow
;
257 wxAuiMDIClientWindow
*wxAuiMDIParentFrame::OnCreateClient()
259 return new wxAuiMDIClientWindow( this );
262 void wxAuiMDIParentFrame::ActivateNext()
264 if (m_pClientWindow
&& m_pClientWindow
->GetSelection() != wxNOT_FOUND
)
266 size_t active
= m_pClientWindow
->GetSelection() + 1;
267 if (active
>= m_pClientWindow
->GetPageCount())
270 m_pClientWindow
->SetSelection(active
);
274 void wxAuiMDIParentFrame::ActivatePrevious()
276 if (m_pClientWindow
&& m_pClientWindow
->GetSelection() != wxNOT_FOUND
)
278 int active
= m_pClientWindow
->GetSelection() - 1;
280 active
= m_pClientWindow
->GetPageCount() - 1;
282 m_pClientWindow
->SetSelection(active
);
286 void wxAuiMDIParentFrame::Init()
289 m_pClientWindow
= NULL
;
290 m_pActiveChild
= NULL
;
292 m_pWindowMenu
= NULL
;
294 #endif // wxUSE_MENUS
298 void wxAuiMDIParentFrame::RemoveWindowMenu(wxMenuBar
* pMenuBar
)
300 if (pMenuBar
&& m_pWindowMenu
)
302 // Remove old window menu
303 int pos
= pMenuBar
->FindMenu(_("&Window"));
304 if (pos
!= wxNOT_FOUND
)
306 // DBG:: We're going to delete the wrong menu!!!
307 wxASSERT(m_pWindowMenu
== pMenuBar
->GetMenu(pos
));
308 pMenuBar
->Remove(pos
);
313 void wxAuiMDIParentFrame::AddWindowMenu(wxMenuBar
*pMenuBar
)
315 if (pMenuBar
&& m_pWindowMenu
)
317 int pos
= pMenuBar
->FindMenu(wxGetStockLabel(wxID_HELP
,wxSTOCK_NOFLAGS
));
318 if (pos
== wxNOT_FOUND
)
319 pMenuBar
->Append(m_pWindowMenu
, _("&Window"));
321 pMenuBar
->Insert(pos
, m_pWindowMenu
, _("&Window"));
325 void wxAuiMDIParentFrame::DoHandleMenu(wxCommandEvent
& event
)
327 switch (event
.GetId())
331 m_pActiveChild
->Close();
333 case wxWINDOWCLOSEALL
:
334 while (m_pActiveChild
)
336 if (!m_pActiveChild
->Close())
353 void wxAuiMDIParentFrame::DoHandleUpdateUI(wxUpdateUIEvent
& event
)
355 switch (event
.GetId())
358 case wxWINDOWCLOSEALL
:
360 wxAuiMDIClientWindow
* client_window
= GetClientWindow();
361 wxCHECK_RET(client_window
, wxS("Missing MDI Client Window"));
362 size_t pages
= client_window
->GetPageCount();
363 event
.Enable(pages
>= 1);
370 wxAuiMDIClientWindow
* client_window
= GetClientWindow();
371 wxCHECK_RET(client_window
, wxS("Missing MDI Client Window"));
372 size_t pages
= client_window
->GetPageCount();
373 event
.Enable(pages
>= 2);
381 #endif // wxUSE_MENUS
383 void wxAuiMDIParentFrame::DoGetClientSize(int* width
, int* height
) const
385 wxFrame::DoGetClientSize(width
, height
);
388 void wxAuiMDIParentFrame::Tile(wxOrientation orient
)
390 wxAuiMDIClientWindow
* client_window
= GetClientWindow();
391 wxASSERT_MSG(client_window
, wxT("Missing MDI Client Window"));
393 int cur_idx
= client_window
->GetSelection();
397 if (orient
== wxVERTICAL
)
399 client_window
->Split(cur_idx
, wxLEFT
);
401 else if (orient
== wxHORIZONTAL
)
403 client_window
->Split(cur_idx
, wxTOP
);
408 //-----------------------------------------------------------------------------
409 // wxAuiMDIChildFrame
410 //-----------------------------------------------------------------------------
412 IMPLEMENT_DYNAMIC_CLASS(wxAuiMDIChildFrame
, wxPanel
)
414 BEGIN_EVENT_TABLE(wxAuiMDIChildFrame
, wxPanel
)
415 EVT_MENU_HIGHLIGHT_ALL(wxAuiMDIChildFrame::OnMenuHighlight
)
416 EVT_ACTIVATE(wxAuiMDIChildFrame::OnActivate
)
417 EVT_CLOSE(wxAuiMDIChildFrame::OnCloseWindow
)
420 wxAuiMDIChildFrame::wxAuiMDIChildFrame()
425 wxAuiMDIChildFrame::wxAuiMDIChildFrame(wxAuiMDIParentFrame
*parent
,
427 const wxString
& title
,
428 const wxPoint
& WXUNUSED(pos
),
431 const wxString
& name
)
435 // There are two ways to create an tabbed mdi child fram without
436 // making it the active document. Either Show(false) can be called
437 // before Create() (as is customary on some ports with wxFrame-type
438 // windows), or wxMINIMIZE can be passed in the style flags. Note that
439 // wxAuiMDIChildFrame is not really derived from wxFrame, as wxMDIChildFrame
440 // is, but those are the expected symantics. No style flag is passed
441 // onto the panel underneath.
442 if (style
& wxMINIMIZE
)
443 m_activateOnCreate
= false;
445 Create(parent
, id
, title
, wxDefaultPosition
, size
, 0, name
);
448 wxAuiMDIChildFrame::~wxAuiMDIChildFrame()
450 wxAuiMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
453 if (pParentFrame
->GetActiveChild() == this)
455 pParentFrame
->SetActiveChild(NULL
);
456 pParentFrame
->SetChildMenuBar(NULL
);
458 wxAuiMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
459 wxASSERT(pClientWindow
);
460 int idx
= pClientWindow
->GetPageIndex(this);
461 if (idx
!= wxNOT_FOUND
)
463 pClientWindow
->RemovePage(idx
);
468 wxDELETE(m_pMenuBar
);
469 #endif // wxUSE_MENUS
472 bool wxAuiMDIChildFrame::Create(wxAuiMDIParentFrame
* parent
,
474 const wxString
& title
,
475 const wxPoint
& WXUNUSED(pos
),
478 const wxString
& name
)
480 wxAuiMDIClientWindow
* pClientWindow
= parent
->GetClientWindow();
481 wxASSERT_MSG((pClientWindow
!= NULL
), wxT("Missing MDI client window."));
483 // see comment in constructor
484 if (style
& wxMINIMIZE
)
485 m_activateOnCreate
= false;
487 wxSize cli_size
= pClientWindow
->GetClientSize();
489 // create the window off-screen to prevent flicker
490 wxPanel::Create(pClientWindow
,
492 wxPoint(cli_size
.x
+1, cli_size
.y
+1),
498 SetMDIParentFrame(parent
);
500 // this is the currently active child
501 parent
->SetActiveChild(this);
505 pClientWindow
->AddPage(this, title
, m_activateOnCreate
);
506 pClientWindow
->Refresh();
511 bool wxAuiMDIChildFrame::Destroy()
513 wxAuiMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
514 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
516 wxAuiMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
517 wxASSERT_MSG(pClientWindow
, wxT("Missing MDI Client Window"));
519 if (pParentFrame
->GetActiveChild() == this)
521 // deactivate ourself
522 wxActivateEvent
event(wxEVT_ACTIVATE
, false, GetId());
523 event
.SetEventObject(this);
524 GetEventHandler()->ProcessEvent(event
);
526 pParentFrame
->SetActiveChild(NULL
);
527 pParentFrame
->SetChildMenuBar(NULL
);
530 size_t page_count
= pClientWindow
->GetPageCount();
531 for (size_t pos
= 0; pos
< page_count
; pos
++)
533 if (pClientWindow
->GetPage(pos
) == this)
534 return pClientWindow
->DeletePage(pos
);
541 void wxAuiMDIChildFrame::SetMenuBar(wxMenuBar
*menu_bar
)
543 wxMenuBar
*pOldMenuBar
= m_pMenuBar
;
544 m_pMenuBar
= menu_bar
;
548 wxAuiMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
549 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
551 m_pMenuBar
->SetParent(pParentFrame
);
552 if (pParentFrame
->GetActiveChild() == this)
554 // replace current menu bars
556 pParentFrame
->SetChildMenuBar(NULL
);
557 pParentFrame
->SetChildMenuBar(this);
562 wxMenuBar
*wxAuiMDIChildFrame::GetMenuBar() const
566 #endif // wxUSE_MENUS
568 void wxAuiMDIChildFrame::SetTitle(const wxString
& title
)
572 wxAuiMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
573 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
575 wxAuiMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
576 if (pClientWindow
!= NULL
)
579 for (pos
= 0; pos
< pClientWindow
->GetPageCount(); pos
++)
581 if (pClientWindow
->GetPage(pos
) == this)
583 pClientWindow
->SetPageText(pos
, m_title
);
590 wxString
wxAuiMDIChildFrame::GetTitle() const
595 void wxAuiMDIChildFrame::SetIcons(const wxIconBundle
& icons
)
597 // get icon with the system icon size
598 SetIcon(icons
.GetIcon(-1));
599 m_iconBundle
= icons
;
602 const wxIconBundle
& wxAuiMDIChildFrame::GetIcons() const
607 void wxAuiMDIChildFrame::SetIcon(const wxIcon
& icon
)
609 wxAuiMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
610 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
615 bmp
.CopyFromIcon(m_icon
);
617 wxAuiMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
618 if (pClientWindow
!= NULL
)
620 int idx
= pClientWindow
->GetPageIndex(this);
624 pClientWindow
->SetPageBitmap((size_t)idx
, bmp
);
629 const wxIcon
& wxAuiMDIChildFrame::GetIcon() const
635 void wxAuiMDIChildFrame::Activate()
637 wxAuiMDIParentFrame
* pParentFrame
= GetMDIParentFrame();
638 wxASSERT_MSG(pParentFrame
, wxT("Missing MDI Parent Frame"));
640 wxAuiMDIClientWindow
* pClientWindow
= pParentFrame
->GetClientWindow();
642 if (pClientWindow
!= NULL
)
645 for (pos
= 0; pos
< pClientWindow
->GetPageCount(); pos
++)
647 if (pClientWindow
->GetPage(pos
) == this)
649 pClientWindow
->SetSelection(pos
);
656 void wxAuiMDIChildFrame::OnMenuHighlight(wxMenuEvent
& event
)
659 if (m_pMDIParentFrame
)
661 // we don't have any help text for this item,
662 // but may be the MDI frame does?
663 m_pMDIParentFrame
->OnMenuHighlight(event
);
667 #endif // wxUSE_STATUSBAR
670 void wxAuiMDIChildFrame::OnActivate(wxActivateEvent
& WXUNUSED(event
))
675 void wxAuiMDIChildFrame::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
))
680 void wxAuiMDIChildFrame::SetMDIParentFrame(wxAuiMDIParentFrame
* parentFrame
)
682 m_pMDIParentFrame
= parentFrame
;
685 wxAuiMDIParentFrame
* wxAuiMDIChildFrame::GetMDIParentFrame() const
687 return m_pMDIParentFrame
;
690 void wxAuiMDIChildFrame::Init()
692 m_activateOnCreate
= true;
693 m_pMDIParentFrame
= NULL
;
696 #endif // wxUSE_MENUS
699 bool wxAuiMDIChildFrame::Show(bool show
)
701 m_activateOnCreate
= show
;
707 void wxAuiMDIChildFrame::DoShow(bool show
)
709 wxWindow::Show(show
);
712 void wxAuiMDIChildFrame::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
714 m_mdiNewRect
= wxRect(x
, y
, width
, height
);
716 wxPanel::DoSetSize(x
,y
,width
, height
, sizeFlags
);
718 wxUnusedVar(sizeFlags
);
722 void wxAuiMDIChildFrame::DoMoveWindow(int x
, int y
, int width
, int height
)
724 m_mdiNewRect
= wxRect(x
, y
, width
, height
);
727 void wxAuiMDIChildFrame::ApplyMDIChildFrameRect()
729 if (m_mdiCurRect
!= m_mdiNewRect
)
731 wxPanel::DoMoveWindow(m_mdiNewRect
.x
, m_mdiNewRect
.y
,
732 m_mdiNewRect
.width
, m_mdiNewRect
.height
);
733 m_mdiCurRect
= m_mdiNewRect
;
738 //-----------------------------------------------------------------------------
739 // wxAuiMDIClientWindow
740 //-----------------------------------------------------------------------------
742 IMPLEMENT_DYNAMIC_CLASS(wxAuiMDIClientWindow
, wxAuiNotebook
)
744 BEGIN_EVENT_TABLE(wxAuiMDIClientWindow
, wxAuiNotebook
)
745 EVT_AUINOTEBOOK_PAGE_CHANGED(wxID_ANY
, wxAuiMDIClientWindow::OnPageChanged
)
746 EVT_AUINOTEBOOK_PAGE_CLOSE(wxID_ANY
, wxAuiMDIClientWindow::OnPageClose
)
747 EVT_SIZE(wxAuiMDIClientWindow::OnSize
)
750 wxAuiMDIClientWindow::wxAuiMDIClientWindow()
754 wxAuiMDIClientWindow::wxAuiMDIClientWindow(wxAuiMDIParentFrame
* parent
, long style
)
756 CreateClient(parent
, style
);
759 bool wxAuiMDIClientWindow::CreateClient(wxAuiMDIParentFrame
* parent
, long style
)
761 SetWindowStyleFlag(style
);
763 wxSize caption_icon_size
=
764 wxSize(wxSystemSettings::GetMetric(wxSYS_SMALLICON_X
),
765 wxSystemSettings::GetMetric(wxSYS_SMALLICON_Y
));
766 SetUniformBitmapSize(caption_icon_size
);
768 if (!wxAuiNotebook::Create(parent
,
772 wxAUI_NB_DEFAULT_STYLE
| wxNO_BORDER
))
777 wxColour bkcolour
= wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE
);
778 SetOwnBackgroundColour(bkcolour
);
780 m_mgr
.GetArtProvider()->SetColour(wxAUI_DOCKART_BACKGROUND_COLOUR
, bkcolour
);
785 int wxAuiMDIClientWindow::SetSelection(size_t nPage
)
787 return wxAuiNotebook::SetSelection(nPage
);
790 void wxAuiMDIClientWindow::PageChanged(int old_selection
, int new_selection
)
792 // don't do anything if the page doesn't actually change
793 if (old_selection
== new_selection
)
797 // don't do anything if the new page is already active
798 if (new_selection != -1)
800 wxAuiMDIChildFrame* child = (wxAuiMDIChildFrame*)GetPage(new_selection);
801 if (child->GetMDIParentFrame()->GetActiveChild() == child)
806 // notify old active child that it has been deactivated
807 if ((old_selection
!= -1) && (old_selection
< (int)GetPageCount()))
809 wxAuiMDIChildFrame
* old_child
= (wxAuiMDIChildFrame
*)GetPage(old_selection
);
810 wxASSERT_MSG(old_child
, wxT("wxAuiMDIClientWindow::PageChanged - null page pointer"));
812 wxActivateEvent
event(wxEVT_ACTIVATE
, false, old_child
->GetId());
813 event
.SetEventObject(old_child
);
814 old_child
->GetEventHandler()->ProcessEvent(event
);
817 // notify new active child that it has been activated
818 if (new_selection
!= -1)
820 wxAuiMDIChildFrame
* active_child
= (wxAuiMDIChildFrame
*)GetPage(new_selection
);
821 wxASSERT_MSG(active_child
, wxT("wxAuiMDIClientWindow::PageChanged - null page pointer"));
823 wxActivateEvent
event(wxEVT_ACTIVATE
, true, active_child
->GetId());
824 event
.SetEventObject(active_child
);
825 active_child
->GetEventHandler()->ProcessEvent(event
);
827 if (active_child
->GetMDIParentFrame())
829 active_child
->GetMDIParentFrame()->SetActiveChild(active_child
);
830 active_child
->GetMDIParentFrame()->SetChildMenuBar(active_child
);
837 void wxAuiMDIClientWindow::OnPageClose(wxAuiNotebookEvent
& evt
)
839 wxAuiMDIChildFrame
* wnd
;
840 wnd
= static_cast<wxAuiMDIChildFrame
*>(GetPage(evt
.GetSelection()));
844 // regardless of the result of wnd->Close(), we've
845 // already taken care of the close operations, so
846 // suppress further processing
850 void wxAuiMDIClientWindow::OnPageChanged(wxAuiNotebookEvent
& evt
)
852 PageChanged(evt
.GetOldSelection(), evt
.GetSelection());
855 void wxAuiMDIClientWindow::OnSize(wxSizeEvent
& evt
)
857 wxAuiNotebook::OnSize(evt
);
859 for (size_t pos
= 0; pos
< GetPageCount(); pos
++)
860 ((wxAuiMDIChildFrame
*)GetPage(pos
))->ApplyMDIChildFrameRect();