]> git.saurik.com Git - wxWidgets.git/blob - src/aui/tabmdi.cpp
generate middle click events (patch 1521314)
[wxWidgets.git] / src / aui / tabmdi.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/tabmdi.cpp
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"
36 #include "wx/settings.h"
37 #endif //WX_PRECOMP
38
39 #include "wx/stockitem.h"
40
41 enum MDI_MENU_ID
42 {
43 wxWINDOWCLOSE = 4001,
44 wxWINDOWCLOSEALL,
45 wxWINDOWNEXT,
46 wxWINDOWPREV
47 };
48
49 //-----------------------------------------------------------------------------
50 // wxTabMDIParentFrame
51 //-----------------------------------------------------------------------------
52
53 IMPLEMENT_DYNAMIC_CLASS(wxTabMDIParentFrame, wxFrame)
54
55 BEGIN_EVENT_TABLE(wxTabMDIParentFrame, wxFrame)
56 #if wxUSE_MENUS
57 EVT_MENU (wxID_ANY, wxTabMDIParentFrame::DoHandleMenu)
58 #endif
59 END_EVENT_TABLE()
60
61 wxTabMDIParentFrame::wxTabMDIParentFrame()
62 {
63 Init();
64 }
65
66 wxTabMDIParentFrame::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
78 wxTabMDIParentFrame::~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
89 bool 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
117 void 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
135 void wxTabMDIParentFrame::SetMenuBar(wxMenuBar* pMenuBar)
136 {
137 // Remove the Window menu from the old menu bar
138 RemoveWindowMenu(GetMenuBar());
139
140 // Add the Window menu to the new menu bar.
141 AddWindowMenu(pMenuBar);
142
143 wxFrame::SetMenuBar(pMenuBar);
144 m_pMyMenuBar = GetMenuBar();
145 }
146 #endif // wxUSE_MENUS
147
148 void 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
157 //m_pMyMenuBar = NULL;
158 }
159 else
160 {
161 if (pChild->GetMenuBar() == NULL)
162 return;
163
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
173 bool 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
210 wxTabMDIChildFrame *wxTabMDIParentFrame::GetActiveChild() const
211 {
212 return m_pActiveChild;
213 }
214
215 void wxTabMDIParentFrame::SetActiveChild(wxTabMDIChildFrame* pChildFrame)
216 {
217 m_pActiveChild = pChildFrame;
218 }
219
220 wxTabMDIClientWindow *wxTabMDIParentFrame::GetClientWindow() const
221 {
222 return m_pClientWindow;
223 }
224
225 wxTabMDIClientWindow *wxTabMDIParentFrame::OnCreateClient()
226 {
227 m_pClientWindow = new wxTabMDIClientWindow( this );
228 return m_pClientWindow;
229 }
230
231 void wxTabMDIParentFrame::ActivateNext()
232 {
233 if (m_pClientWindow && m_pClientWindow->GetSelection() != wxNOT_FOUND)
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
243 void wxTabMDIParentFrame::ActivatePrevious()
244 {
245 if (m_pClientWindow && m_pClientWindow->GetSelection() != wxNOT_FOUND)
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
255 void 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
266 void 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
281 void 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
293 void 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
327 void wxTabMDIParentFrame::DoGetClientSize(int* width, int* height) const
328 {
329 wxFrame::DoGetClientSize(width, height);
330 }
331
332 //-----------------------------------------------------------------------------
333 // wxTabMDIChildFrame
334 //-----------------------------------------------------------------------------
335
336 IMPLEMENT_DYNAMIC_CLASS(wxTabMDIChildFrame, wxPanel)
337
338 BEGIN_EVENT_TABLE(wxTabMDIChildFrame, wxPanel)
339 EVT_MENU_HIGHLIGHT_ALL(wxTabMDIChildFrame::OnMenuHighlight)
340 EVT_ACTIVATE(wxTabMDIChildFrame::OnActivate)
341 EVT_CLOSE(wxTabMDIChildFrame::OnCloseWindow)
342 END_EVENT_TABLE()
343
344 wxTabMDIChildFrame::wxTabMDIChildFrame()
345 {
346 Init();
347 }
348
349 wxTabMDIChildFrame::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
361 wxTabMDIChildFrame::~wxTabMDIChildFrame()
362 {
363 #if wxUSE_MENUS
364 wxDELETE(m_pMenuBar);
365 #endif // wxUSE_MENUS
366 }
367
368 bool 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
394 bool wxTabMDIChildFrame::Destroy()
395 {
396 wxTabMDIParentFrame* pParentFrame = GetMDIParentFrame();
397 wxASSERT_MSG(pParentFrame, wxT("Missing MDI Parent Frame"));
398
399 wxTabMDIClientWindow* pClientWindow = pParentFrame->GetClientWindow();
400 wxASSERT_MSG(pClientWindow, wxT("Missing MDI Client Window"));
401
402 bool bActive = false;
403 if (pParentFrame->GetActiveChild() == this)
404 {
405 pParentFrame->SetActiveChild(NULL);
406 pParentFrame->SetChildMenuBar(NULL);
407 bActive = true;
408 }
409
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 }
416
417 return false;
418 }
419
420 #if wxUSE_MENUS
421 void 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
442 wxMenuBar *wxTabMDIChildFrame::GetMenuBar() const
443 {
444 return m_pMenuBar;
445 }
446 #endif // wxUSE_MENUS
447
448 void 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
470 wxString wxTabMDIChildFrame::GetTitle() const
471 {
472 return m_title;
473 }
474
475 void 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
496 void 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
510 void wxTabMDIChildFrame::OnActivate(wxActivateEvent& WXUNUSED(event))
511 {
512 // do nothing
513 }
514
515 void wxTabMDIChildFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
516 {
517 Destroy();
518 }
519
520 void wxTabMDIChildFrame::SetMDIParentFrame(wxTabMDIParentFrame* parentFrame)
521 {
522 m_pMDIParentFrame = parentFrame;
523 }
524
525 wxTabMDIParentFrame* wxTabMDIChildFrame::GetMDIParentFrame() const
526 {
527 return m_pMDIParentFrame;
528 }
529
530 void wxTabMDIChildFrame::Init()
531 {
532 m_pMDIParentFrame = NULL;
533 #if wxUSE_MENUS
534 m_pMenuBar = NULL;
535 #endif // wxUSE_MENUS
536 }
537
538 bool wxTabMDIChildFrame::Show(bool WXUNUSED(show))
539 {
540 // do nothing
541 return true;
542 }
543
544 void wxTabMDIChildFrame::DoShow(bool show)
545 {
546 wxWindow::Show(show);
547 }
548
549 void wxTabMDIChildFrame::DoSetSize(int x, int y, int width, int height, int WXUNUSED(sizeFlags))
550 {
551 m_mdi_newrect = wxRect(x, y, width, height);
552 }
553
554 void wxTabMDIChildFrame::DoMoveWindow(int x, int y, int width, int height)
555 {
556 m_mdi_newrect = wxRect(x, y, width, height);
557 }
558
559 void wxTabMDIChildFrame::ApplyMDIChildFrameRect()
560 {
561 if (m_mdi_currect != m_mdi_newrect)
562 {
563 wxPanel::DoMoveWindow(m_mdi_newrect.x, m_mdi_newrect.y,
564 m_mdi_newrect.width, m_mdi_newrect.height);
565 m_mdi_currect = m_mdi_newrect;
566 }
567 }
568
569
570 //-----------------------------------------------------------------------------
571 // wxTabMDIClientWindow
572 //-----------------------------------------------------------------------------
573
574 IMPLEMENT_DYNAMIC_CLASS(wxTabMDIClientWindow, wxAuiMultiNotebook)
575
576 BEGIN_EVENT_TABLE(wxTabMDIClientWindow, wxAuiMultiNotebook)
577 EVT_AUINOTEBOOK_PAGE_CHANGED(wxID_ANY, wxTabMDIClientWindow::OnPageChanged)
578 EVT_SIZE(wxTabMDIClientWindow::OnSize)
579 END_EVENT_TABLE()
580
581 wxTabMDIClientWindow::wxTabMDIClientWindow()
582 {
583 }
584
585 wxTabMDIClientWindow::wxTabMDIClientWindow(wxTabMDIParentFrame* parent, long style)
586 {
587 CreateClient(parent, style);
588 }
589
590 wxTabMDIClientWindow::~wxTabMDIClientWindow()
591 {
592 DestroyChildren();
593 }
594
595 bool wxTabMDIClientWindow::CreateClient(wxTabMDIParentFrame* parent, long style)
596 {
597 SetWindowStyleFlag(style);
598
599 if (!wxAuiMultiNotebook::Create(parent,
600 wxID_ANY,
601 wxPoint(0,0),
602 wxSize(100, 100),
603 wxNO_BORDER))
604 {
605 return false;
606 }
607
608 wxColour bkcolour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
609 SetBackgroundColour(bkcolour);
610
611 m_mgr.GetArtProvider()->SetColour(wxAUI_ART_BACKGROUND_COLOUR, bkcolour);
612
613 return true;
614 }
615
616 int wxTabMDIClientWindow::SetSelection(size_t nPage)
617 {
618 return wxAuiMultiNotebook::SetSelection(nPage);
619 }
620
621 void wxTabMDIClientWindow::PageChanged(int old_selection, int new_selection)
622 {
623 // don't do anything if the page doesn't actually change
624 if (old_selection == new_selection)
625 return;
626
627 // don't do anything if the new page is already active
628 if (new_selection != -1)
629 {
630 wxTabMDIChildFrame* child = (wxTabMDIChildFrame*)GetPage(new_selection);
631 if (child->GetMDIParentFrame()->GetActiveChild() == child)
632 return;
633 }
634
635 // notify old active child that it has been deactivated
636 if (old_selection != -1)
637 {
638 wxTabMDIChildFrame* old_child = (wxTabMDIChildFrame*)GetPage(old_selection);
639 wxASSERT_MSG(old_child, wxT("wxTabMDIClientWindow::PageChanged - null page pointer"));
640
641 wxActivateEvent event(wxEVT_ACTIVATE, false, old_child->GetId());
642 event.SetEventObject(old_child);
643 old_child->GetEventHandler()->ProcessEvent(event);
644 }
645
646 // notify new active child that it has been activated
647 if (new_selection != -1)
648 {
649 wxTabMDIChildFrame* active_child = (wxTabMDIChildFrame*)GetPage(new_selection);
650 wxASSERT_MSG(active_child, wxT("wxTabMDIClientWindow::PageChanged - null page pointer"));
651
652 wxActivateEvent event(wxEVT_ACTIVATE, true, active_child->GetId());
653 event.SetEventObject(active_child);
654 active_child->GetEventHandler()->ProcessEvent(event);
655
656 if (active_child->GetMDIParentFrame())
657 {
658 active_child->GetMDIParentFrame()->SetActiveChild(active_child);
659 active_child->GetMDIParentFrame()->SetChildMenuBar(active_child);
660 }
661 }
662 }
663
664 void wxTabMDIClientWindow::OnPageChanged(wxAuiNotebookEvent& evt)
665 {
666 PageChanged(evt.GetOldSelection(), evt.GetSelection());
667 evt.Skip();
668 }
669
670 void wxTabMDIClientWindow::OnSize(wxSizeEvent& evt)
671 {
672 wxAuiMultiNotebook::OnSize(evt);
673
674 for (size_t pos = 0; pos < GetPageCount(); pos++)
675 ((wxTabMDIChildFrame *)GetPage(pos))->ApplyMDIChildFrameRect();
676 }
677
678 #endif // wxUSE_MDI