]> git.saurik.com Git - wxWidgets.git/blame - src/aui/tabmdi.cpp
updates from Adrián González Alba
[wxWidgets.git] / src / aui / tabmdi.cpp
CommitLineData
cd05bf23 1/////////////////////////////////////////////////////////////////////////////
4444d148 2// Name: src/generic/tabmdi.cpp
cd05bf23
BW
3// Purpose: Generic MDI (Multiple Document Interface) classes
4// Author: Hans Van Leemputten
5// Modified by: Benjamin I. Williams / Kirix Corporation
6// Created: 29/07/2002
7// RCS-ID: $Id$
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/aui/tabmdi.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"
4444d148 36 #include "wx/settings.h"
cd05bf23
BW
37#endif //WX_PRECOMP
38
39#include "wx/stockitem.h"
40
41enum MDI_MENU_ID
42{
43 wxWINDOWCLOSE = 4001,
44 wxWINDOWCLOSEALL,
45 wxWINDOWNEXT,
46 wxWINDOWPREV
47};
48
49//-----------------------------------------------------------------------------
50// wxTabMDIParentFrame
51//-----------------------------------------------------------------------------
52
53IMPLEMENT_DYNAMIC_CLASS(wxTabMDIParentFrame, wxFrame)
54
55BEGIN_EVENT_TABLE(wxTabMDIParentFrame, wxFrame)
56#if wxUSE_MENUS
57 EVT_MENU (wxID_ANY, wxTabMDIParentFrame::DoHandleMenu)
58#endif
59END_EVENT_TABLE()
60
61wxTabMDIParentFrame::wxTabMDIParentFrame()
62{
63 Init();
64}
65
66wxTabMDIParentFrame::wxTabMDIParentFrame(wxWindow *parent,
67 wxWindowID id,
68 const wxString& title,
69 const wxPoint& pos,
70 const wxSize& size,
71 long style,
72 const wxString& name)
73{
74 Init();
75 (void)Create(parent, id, title, pos, size, style, name);
76}
77
78wxTabMDIParentFrame::~wxTabMDIParentFrame()
79{
80 // Make sure the client window is destructed before the menu bars are!
81 wxDELETE(m_pClientWindow);
82
83#if wxUSE_MENUS
84 RemoveWindowMenu(GetMenuBar());
85 delete m_pWindowMenu;
86#endif // wxUSE_MENUS
87}
88
89bool wxTabMDIParentFrame::Create(wxWindow *parent,
90 wxWindowID id,
91 const wxString& title,
92 const wxPoint& pos,
93 const wxSize& size,
94 long style,
95 const wxString& name)
96{
97#if wxUSE_MENUS
98 // this style can be used to prevent a window from having the standard MDI
99 // "Window" menu
100 if (!(style & wxFRAME_NO_WINDOW_MENU))
101 {
102 m_pWindowMenu = new wxMenu;
103 m_pWindowMenu->Append(wxWINDOWCLOSE, _("Cl&ose"));
104 m_pWindowMenu->Append(wxWINDOWCLOSEALL, _("Close All"));
105 m_pWindowMenu->AppendSeparator();
106 m_pWindowMenu->Append(wxWINDOWNEXT, _("&Next"));
107 m_pWindowMenu->Append(wxWINDOWPREV, _("&Previous"));
108 }
109#endif // wxUSE_MENUS
110
111 wxFrame::Create(parent, id, title, pos, size, style, name);
112 OnCreateClient();
113 return true;
114}
115
116#if wxUSE_MENUS
117void wxTabMDIParentFrame::SetWindowMenu(wxMenu* pMenu)
118{
119 // Replace the window menu from the currently loaded menu bar.
120 wxMenuBar *pMenuBar = GetMenuBar();
121
122 if (m_pWindowMenu)
123 {
124 RemoveWindowMenu(pMenuBar);
125 wxDELETE(m_pWindowMenu);
126 }
127
128 if (pMenu)
129 {
130 m_pWindowMenu = pMenu;
131 AddWindowMenu(pMenuBar);
132 }
133}
134
82dc21d3 135void wxTabMDIParentFrame::SetMenuBar(wxMenuBar* pMenuBar)
cd05bf23
BW
136{
137 // Remove the Window menu from the old menu bar
138 RemoveWindowMenu(GetMenuBar());
4444d148 139
cd05bf23
BW
140 // Add the Window menu to the new menu bar.
141 AddWindowMenu(pMenuBar);
4444d148 142
cd05bf23
BW
143 wxFrame::SetMenuBar(pMenuBar);
144 m_pMyMenuBar = GetMenuBar();
145}
146#endif // wxUSE_MENUS
147
148void wxTabMDIParentFrame::SetChildMenuBar(wxTabMDIChildFrame* pChild)
149{
150#if wxUSE_MENUS
151 if (!pChild)
152 {
153 // No Child, set Our menu bar back.
154 SetMenuBar(m_pMyMenuBar);
155
156 // Make sure we know our menu bar is in use
82dc21d3 157 //m_pMyMenuBar = NULL;
cd05bf23
BW
158 }
159 else
160 {
161 if (pChild->GetMenuBar() == NULL)
162 return;
82dc21d3 163
cd05bf23
BW
164 // Do we need to save the current bar?
165 if (m_pMyMenuBar == NULL)
166 m_pMyMenuBar = GetMenuBar();
167
168 SetMenuBar(pChild->GetMenuBar());
169 }
170#endif // wxUSE_MENUS
171}
172
173bool wxTabMDIParentFrame::ProcessEvent(wxEvent& event)
174{
175 // Stops the same event being processed repeatedly
176 static wxEventType inEvent = wxEVT_NULL;
177 if (inEvent == event.GetEventType())
178 return false;
179
180 inEvent = event.GetEventType();
181
182 // Let the active child (if any) process the event first.
183 bool res = false;
184 if (m_pActiveChild &&
185 event.IsCommandEvent() &&
186 event.GetEventObject() != m_pClientWindow &&
187 !(event.GetEventType() == wxEVT_ACTIVATE ||
188 event.GetEventType() == wxEVT_SET_FOCUS ||
189 event.GetEventType() == wxEVT_KILL_FOCUS ||
190 event.GetEventType() == wxEVT_CHILD_FOCUS ||
191 event.GetEventType() == wxEVT_COMMAND_SET_FOCUS ||
192 event.GetEventType() == wxEVT_COMMAND_KILL_FOCUS )
193 )
194 {
195 res = m_pActiveChild->GetEventHandler()->ProcessEvent(event);
196 }
197
198 // If the event was not handled this frame will handle it!
199 if (!res)
200 {
201 //res = GetEventHandler()->ProcessEvent(event);
202 res = wxEvtHandler::ProcessEvent(event);
203 }
204
205 inEvent = wxEVT_NULL;
206
207 return res;
208}
209
210wxTabMDIChildFrame *wxTabMDIParentFrame::GetActiveChild() const
211{
212 return m_pActiveChild;
213}
214
215void wxTabMDIParentFrame::SetActiveChild(wxTabMDIChildFrame* pChildFrame)
216{
217 m_pActiveChild = pChildFrame;
218}
219
220wxTabMDIClientWindow *wxTabMDIParentFrame::GetClientWindow() const
221{
222 return m_pClientWindow;
223}
224
225wxTabMDIClientWindow *wxTabMDIParentFrame::OnCreateClient()
226{
227 m_pClientWindow = new wxTabMDIClientWindow( this );
228 return m_pClientWindow;
229}
230
231void wxTabMDIParentFrame::ActivateNext()
232{
4444d148 233 if (m_pClientWindow && m_pClientWindow->GetSelection() != wxNOT_FOUND)
cd05bf23
BW
234 {
235 size_t active = m_pClientWindow->GetSelection() + 1;
236 if (active >= m_pClientWindow->GetPageCount())
237 active = 0;
238
239 m_pClientWindow->SetSelection(active);
240 }
241}
242
243void wxTabMDIParentFrame::ActivatePrevious()
244{
4444d148 245 if (m_pClientWindow && m_pClientWindow->GetSelection() != wxNOT_FOUND)
cd05bf23
BW
246 {
247 int active = m_pClientWindow->GetSelection() - 1;
248 if (active < 0)
249 active = m_pClientWindow->GetPageCount() - 1;
250
251 m_pClientWindow->SetSelection(active);
252 }
253}
254
255void wxTabMDIParentFrame::Init()
256{
257 m_pClientWindow = NULL;
258 m_pActiveChild = NULL;
259#if wxUSE_MENUS
260 m_pWindowMenu = NULL;
261 m_pMyMenuBar = NULL;
262#endif // wxUSE_MENUS
263}
264
265#if wxUSE_MENUS
266void wxTabMDIParentFrame::RemoveWindowMenu(wxMenuBar* pMenuBar)
267{
268 if (pMenuBar && m_pWindowMenu)
269 {
270 // Remove old window menu
271 int pos = pMenuBar->FindMenu(_("&Window"));
272 if (pos != wxNOT_FOUND)
273 {
274 // DBG:: We're going to delete the wrong menu!!!
275 wxASSERT(m_pWindowMenu == pMenuBar->GetMenu(pos));
276 pMenuBar->Remove(pos);
277 }
278 }
279}
280
281void wxTabMDIParentFrame::AddWindowMenu(wxMenuBar *pMenuBar)
282{
283 if (pMenuBar && m_pWindowMenu)
284 {
285 int pos = pMenuBar->FindMenu(wxGetStockLabel(wxID_HELP,false));
286 if (pos == wxNOT_FOUND)
287 pMenuBar->Append(m_pWindowMenu, _("&Window"));
288 else
289 pMenuBar->Insert(pos, m_pWindowMenu, _("&Window"));
290 }
291}
292
293void wxTabMDIParentFrame::DoHandleMenu(wxCommandEvent& event)
294{
295 switch (event.GetId())
296 {
297 case wxWINDOWCLOSE:
298 if (m_pActiveChild)
299 m_pActiveChild->Close();
300 break;
301 case wxWINDOWCLOSEALL:
302 while (m_pActiveChild)
303 {
304 if (!m_pActiveChild->Close())
305 {
306 return; // failure
307 }
308 else
309 {
310 delete m_pActiveChild;
311 m_pActiveChild = NULL;
312 }
313 }
314 break;
315 case wxWINDOWNEXT:
316 ActivateNext();
317 break;
318 case wxWINDOWPREV:
319 ActivatePrevious();
320 break;
321 default:
322 event.Skip();
323 }
324}
325#endif // wxUSE_MENUS
326
327void wxTabMDIParentFrame::DoGetClientSize(int* width, int* height) const
328{
329 wxFrame::DoGetClientSize(width, height);
330}
331
332//-----------------------------------------------------------------------------
333// wxTabMDIChildFrame
334//-----------------------------------------------------------------------------
335
336IMPLEMENT_DYNAMIC_CLASS(wxTabMDIChildFrame, wxPanel)
337
338BEGIN_EVENT_TABLE(wxTabMDIChildFrame, wxPanel)
339 EVT_MENU_HIGHLIGHT_ALL(wxTabMDIChildFrame::OnMenuHighlight)
340 EVT_ACTIVATE(wxTabMDIChildFrame::OnActivate)
341 EVT_CLOSE(wxTabMDIChildFrame::OnCloseWindow)
342END_EVENT_TABLE()
343
344wxTabMDIChildFrame::wxTabMDIChildFrame()
345{
346 Init();
347}
348
349wxTabMDIChildFrame::wxTabMDIChildFrame(wxTabMDIParentFrame *parent,
350 wxWindowID id,
351 const wxString& title,
352 const wxPoint& WXUNUSED(pos),
353 const wxSize& size,
354 long style,
355 const wxString& name)
356{
357 Init();
358 Create(parent, id, title, wxDefaultPosition, size, style, name);
359}
360
361wxTabMDIChildFrame::~wxTabMDIChildFrame()
362{
363#if wxUSE_MENUS
364 wxDELETE(m_pMenuBar);
365#endif // wxUSE_MENUS
366}
367
368bool wxTabMDIChildFrame::Create(wxTabMDIParentFrame* parent,
369 wxWindowID id,
370 const wxString& title,
371 const wxPoint& WXUNUSED(pos),
372 const wxSize& size,
373 long style,
374 const wxString& name)
375{
376 wxTabMDIClientWindow* pClientWindow = parent->GetClientWindow();
377 wxASSERT_MSG((pClientWindow != (wxWindow*) NULL), wxT("Missing MDI client window."));
378
379 wxPanel::Create(pClientWindow, id, wxDefaultPosition, size, style|wxNO_BORDER, name);
380
381 SetMDIParentFrame(parent);
382
383 // this is the currently active child
384 parent->SetActiveChild(this);
385
386 m_title = title;
387
388 pClientWindow->AddPage(this, title, true);
389 pClientWindow->Refresh();
390
391 return true;
392}
393
394bool wxTabMDIChildFrame::Destroy()
395{
396 wxTabMDIParentFrame* pParentFrame = GetMDIParentFrame();
397 wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame"));
4444d148 398
cd05bf23
BW
399 wxTabMDIClientWindow* pClientWindow = pParentFrame->GetClientWindow();
400 wxASSERT_MSG(pClientWindow, wxT("Missing MDI Client Window"));
4444d148 401
cd05bf23
BW
402 bool bActive = false;
403 if (pParentFrame->GetActiveChild() == this)
404 {
405 pParentFrame->SetActiveChild(NULL);
406 pParentFrame->SetChildMenuBar(NULL);
407 bActive = true;
408 }
4444d148 409
cd05bf23
BW
410 size_t pos, page_count = pClientWindow->GetPageCount();
411 for (pos = 0; pos < page_count; pos++)
412 {
413 if (pClientWindow->GetPage(pos) == this)
414 return pClientWindow->DeletePage(pos);
415 }
4444d148 416
cd05bf23
BW
417 return false;
418}
419
cd05bf23
BW
420#if wxUSE_MENUS
421void wxTabMDIChildFrame::SetMenuBar(wxMenuBar *menu_bar)
422{
423 wxMenuBar *pOldMenuBar = m_pMenuBar;
424 m_pMenuBar = menu_bar;
425
426 if (m_pMenuBar)
427 {
428 wxTabMDIParentFrame* pParentFrame = GetMDIParentFrame();
429 wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame"));
430
431 m_pMenuBar->SetParent(pParentFrame);
432 if (pParentFrame->GetActiveChild() == this)
433 {
434 // replace current menu bars
435 if (pOldMenuBar)
436 pParentFrame->SetChildMenuBar(NULL);
437 pParentFrame->SetChildMenuBar(this);
438 }
439 }
440}
441
442wxMenuBar *wxTabMDIChildFrame::GetMenuBar() const
443{
444 return m_pMenuBar;
445}
446#endif // wxUSE_MENUS
447
448void wxTabMDIChildFrame::SetTitle(const wxString& title)
449{
450 m_title = title;
451
452 wxTabMDIParentFrame* pParentFrame = GetMDIParentFrame();
453 wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame"));
454
455 wxTabMDIClientWindow* pClientWindow = pParentFrame->GetClientWindow();
456 if (pClientWindow != NULL)
457 {
458 size_t pos;
459 for (pos = 0; pos < pClientWindow->GetPageCount(); pos++)
460 {
461 if (pClientWindow->GetPage(pos) == this)
462 {
463 pClientWindow->SetPageText(pos, m_title);
464 break;
465 }
466 }
467 }
468}
469
470wxString wxTabMDIChildFrame::GetTitle() const
471{
472 return m_title;
473}
474
475void wxTabMDIChildFrame::Activate()
476{
477 wxTabMDIParentFrame* pParentFrame = GetMDIParentFrame();
478 wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame"));
479
480 wxTabMDIClientWindow* pClientWindow = pParentFrame->GetClientWindow();
481
482 if (pClientWindow != NULL)
483 {
484 size_t pos;
485 for (pos = 0; pos < pClientWindow->GetPageCount(); pos++)
486 {
487 if (pClientWindow->GetPage(pos) == this)
488 {
489 pClientWindow->SetSelection(pos);
490 break;
491 }
492 }
493 }
494}
495
496void wxTabMDIChildFrame::OnMenuHighlight(wxMenuEvent& event)
497{
498#if wxUSE_STATUSBAR
499 if (m_pMDIParentFrame)
500 {
501 // we don't have any help text for this item,
502 // but may be the MDI frame does?
503 m_pMDIParentFrame->OnMenuHighlight(event);
504 }
505#else
506 wxUnusedVar(event);
507#endif // wxUSE_STATUSBAR
508}
509
510void wxTabMDIChildFrame::OnActivate(wxActivateEvent& WXUNUSED(event))
511{
512 // do nothing
513}
514
515void wxTabMDIChildFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
516{
517 Destroy();
518}
519
520void wxTabMDIChildFrame::SetMDIParentFrame(wxTabMDIParentFrame* parentFrame)
521{
522 m_pMDIParentFrame = parentFrame;
523}
524
525wxTabMDIParentFrame* wxTabMDIChildFrame::GetMDIParentFrame() const
526{
527 return m_pMDIParentFrame;
528}
529
530void wxTabMDIChildFrame::Init()
531{
532 m_pMDIParentFrame = NULL;
533#if wxUSE_MENUS
534 m_pMenuBar = NULL;
535#endif // wxUSE_MENUS
536}
537
538bool wxTabMDIChildFrame::Show(bool WXUNUSED(show))
539{
540 // do nothing
541 return true;
542}
543
544void wxTabMDIChildFrame::DoShow(bool show)
545{
546 wxWindow::Show(show);
547}
548
a94476de 549void wxTabMDIChildFrame::DoSetSize(int x, int y, int width, int height, int sizeFlags)
cd05bf23
BW
550{
551 m_mdi_newrect = wxRect(x, y, width, height);
a94476de
BW
552#ifdef __WXGTK__
553 wxPanel::DoSetSize(x,y,width, height, sizeFlags);
554#endif
cd05bf23
BW
555}
556
557void wxTabMDIChildFrame::DoMoveWindow(int x, int y, int width, int height)
558{
559 m_mdi_newrect = wxRect(x, y, width, height);
560}
561
562void wxTabMDIChildFrame::ApplyMDIChildFrameRect()
563{
564 if (m_mdi_currect != m_mdi_newrect)
565 {
566 wxPanel::DoMoveWindow(m_mdi_newrect.x, m_mdi_newrect.y,
567 m_mdi_newrect.width, m_mdi_newrect.height);
568 m_mdi_currect = m_mdi_newrect;
569 }
570}
571
572
573//-----------------------------------------------------------------------------
574// wxTabMDIClientWindow
575//-----------------------------------------------------------------------------
576
577IMPLEMENT_DYNAMIC_CLASS(wxTabMDIClientWindow, wxAuiMultiNotebook)
578
579BEGIN_EVENT_TABLE(wxTabMDIClientWindow, wxAuiMultiNotebook)
4444d148 580 EVT_AUINOTEBOOK_PAGE_CHANGED(wxID_ANY, wxTabMDIClientWindow::OnPageChanged)
cd05bf23
BW
581 EVT_SIZE(wxTabMDIClientWindow::OnSize)
582END_EVENT_TABLE()
583
584wxTabMDIClientWindow::wxTabMDIClientWindow()
585{
586}
587
588wxTabMDIClientWindow::wxTabMDIClientWindow(wxTabMDIParentFrame* parent, long style)
589{
590 CreateClient(parent, style);
591}
592
593wxTabMDIClientWindow::~wxTabMDIClientWindow()
594{
595 DestroyChildren();
596}
597
598bool wxTabMDIClientWindow::CreateClient(wxTabMDIParentFrame* parent, long style)
599{
600 SetWindowStyleFlag(style);
601
602 if (!wxAuiMultiNotebook::Create(parent,
4444d148 603 wxID_ANY,
cd05bf23
BW
604 wxPoint(0,0),
605 wxSize(100, 100),
606 wxNO_BORDER))
607 {
608 return false;
609 }
4444d148 610
cd05bf23
BW
611 wxColour bkcolour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
612 SetBackgroundColour(bkcolour);
4444d148 613
cd05bf23 614 m_mgr.GetArtProvider()->SetColour(wxAUI_ART_BACKGROUND_COLOUR, bkcolour);
4444d148 615
cd05bf23
BW
616 return true;
617}
618
619int wxTabMDIClientWindow::SetSelection(size_t nPage)
620{
621 return wxAuiMultiNotebook::SetSelection(nPage);
622}
623
624void wxTabMDIClientWindow::PageChanged(int old_selection, int new_selection)
625{
626 // don't do anything if the page doesn't actually change
627 if (old_selection == new_selection)
628 return;
4444d148 629
cd05bf23
BW
630 // don't do anything if the new page is already active
631 if (new_selection != -1)
632 {
633 wxTabMDIChildFrame* child = (wxTabMDIChildFrame*)GetPage(new_selection);
634 if (child->GetMDIParentFrame()->GetActiveChild() == child)
635 return;
636 }
637
638 // notify old active child that it has been deactivated
639 if (old_selection != -1)
640 {
641 wxTabMDIChildFrame* old_child = (wxTabMDIChildFrame*)GetPage(old_selection);
642 wxASSERT_MSG(old_child, wxT("wxTabMDIClientWindow::PageChanged - null page pointer"));
4444d148 643
cd05bf23
BW
644 wxActivateEvent event(wxEVT_ACTIVATE, false, old_child->GetId());
645 event.SetEventObject(old_child);
646 old_child->GetEventHandler()->ProcessEvent(event);
647 }
648
649 // notify new active child that it has been activated
650 if (new_selection != -1)
651 {
652 wxTabMDIChildFrame* active_child = (wxTabMDIChildFrame*)GetPage(new_selection);
653 wxASSERT_MSG(active_child, wxT("wxTabMDIClientWindow::PageChanged - null page pointer"));
4444d148 654
cd05bf23
BW
655 wxActivateEvent event(wxEVT_ACTIVATE, true, active_child->GetId());
656 event.SetEventObject(active_child);
657 active_child->GetEventHandler()->ProcessEvent(event);
658
659 if (active_child->GetMDIParentFrame())
660 {
661 active_child->GetMDIParentFrame()->SetActiveChild(active_child);
662 active_child->GetMDIParentFrame()->SetChildMenuBar(active_child);
663 }
664 }
665}
666
667void wxTabMDIClientWindow::OnPageChanged(wxAuiNotebookEvent& evt)
668{
669 PageChanged(evt.GetOldSelection(), evt.GetSelection());
670 evt.Skip();
671}
672
673void wxTabMDIClientWindow::OnSize(wxSizeEvent& evt)
4444d148 674{
cd05bf23
BW
675 wxAuiMultiNotebook::OnSize(evt);
676
677 for (size_t pos = 0; pos < GetPageCount(); pos++)
678 ((wxTabMDIChildFrame *)GetPage(pos))->ApplyMDIChildFrameRect();
679}
680
681#endif // wxUSE_MDI