]> git.saurik.com Git - wxWidgets.git/blame - src/aui/auibook.cpp
Minor header cleaning.
[wxWidgets.git] / src / aui / auibook.cpp
CommitLineData
cd05bf23 1///////////////////////////////////////////////////////////////////////////////
4444d148 2// Name: src/aui/auibook.cpp
cd05bf23
BW
3// Purpose: wxaui: wx advanced user interface - notebook
4// Author: Benjamin I. Williams
5// Modified by:
6// Created: 2006-06-28
7// Copyright: (C) Copyright 2006, Kirix Corporation, All Rights Reserved
8// Licence: wxWindows Library Licence, Version 3.1
9///////////////////////////////////////////////////////////////////////////////
10
11// ----------------------------------------------------------------------------
12// headers
13// ----------------------------------------------------------------------------
14
15#include "wx/wxprec.h"
16
17#ifdef __BORLANDC__
18 #pragma hdrstop
19#endif
20
21#if wxUSE_AUI
22
189da67c 23#include "wx/aui/auibook.h"
cd05bf23
BW
24
25#ifndef WX_PRECOMP
4444d148 26 #include "wx/settings.h"
03265113 27 #include "wx/image.h"
cd05bf23
BW
28#endif
29
4444d148
WS
30#include "wx/aui/tabmdi.h"
31#include "wx/dcbuffer.h"
32
cd05bf23
BW
33#include "wx/arrimpl.cpp"
34WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray)
35WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray)
36
37DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING)
38DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED)
39DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON)
40DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG)
41DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG)
42DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION)
43
44
45
46IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent)
47
cd05bf23
BW
48
49
cd05bf23
BW
50
51
52// This functions are here for this proof of concept
53// and will be factored out later. See dockart.cpp
54static wxColor StepColour(const wxColor& c, int percent)
55{
56 int r = c.Red(), g = c.Green(), b = c.Blue();
57 return wxColour((unsigned char)wxMin((r*percent)/100,255),
58 (unsigned char)wxMin((g*percent)/100,255),
59 (unsigned char)wxMin((b*percent)/100,255));
60}
61
62// This functions are here for this proof of concept
63// and will be factored out later. See dockart.cpp
64static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h,
65 const wxColour& color)
66{
67 wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
df00bdf7
RR
68 img.Replace(0,0,0,123,123,123);
69 img.Replace(255,255,255,color.Red(),color.Green(),color.Blue());
cd05bf23
BW
70 img.SetMaskColour(123,123,123);
71 return wxBitmap(img);
72}
73
74static void DrawButton(wxDC& dc,
75 const wxRect& _rect,
76 const wxBitmap& bmp,
77 const wxColour& bkcolour,
78 int button_state)
79{
80 wxRect rect = _rect;
81
82 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
83 {
84 rect.x++;
85 rect.y++;
86 }
87
88 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
89 button_state == wxAUI_BUTTON_STATE_PRESSED)
90 {
91 dc.SetBrush(wxBrush(StepColour(bkcolour, 120)));
92 dc.SetPen(wxPen(StepColour(bkcolour, 70)));
93
94 // draw the background behind the button
95 dc.DrawRectangle(rect.x, rect.y, 15, 15);
96 }
97
98 // draw the button itself
99 dc.DrawBitmap(bmp, rect.x, rect.y, true);
100}
101
102
103
104
3f69756e
BW
105
106// -- wxDefaultTabArt class implementation --
107
108wxDefaultTabArt::wxDefaultTabArt()
cd05bf23
BW
109{
110 m_normal_font = *wxNORMAL_FONT;
111 m_selected_font = *wxNORMAL_FONT;
112 m_selected_font.SetWeight(wxBOLD);
113 m_measuring_font = m_selected_font;
4444d148 114
cd05bf23 115 wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
4444d148 116
cd05bf23
BW
117 wxColour background_colour = StepColour(base_colour, 95);
118 wxColour normaltab_colour = base_colour;
119 wxColour selectedtab_colour = *wxWHITE;
4444d148 120
cd05bf23
BW
121 m_bkbrush = wxBrush(background_colour);
122 m_normal_bkbrush = wxBrush(normaltab_colour);
123 m_normal_bkpen = wxPen(normaltab_colour);
124 m_selected_bkbrush = wxBrush(selectedtab_colour);
125 m_selected_bkpen = wxPen(selectedtab_colour);
126}
127
488e50ee
BW
128wxDefaultTabArt::~wxDefaultTabArt()
129{
130}
131
3f69756e
BW
132void wxDefaultTabArt::DrawBackground(
133 wxDC* dc,
134 const wxRect& rect)
135{
136 // draw background
137 dc->SetBrush(m_bkbrush);
138 dc->SetPen(*wxTRANSPARENT_PEN);
139 dc->DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2);
140
141 // draw base line
142 dc->SetPen(*wxGREY_PEN);
143 dc->DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1);
144}
145
146// DrawTab() draws an individual tab.
147//
148// dc - output dc
149// in_rect - rectangle the tab should be confined to
150// caption - tab's caption
151// active - whether or not the tab is active
152// out_rect - actual output rectangle
153// x_extent - the advance x; where the next tab should start
154
155void wxDefaultTabArt::DrawTab(wxDC* dc,
156 const wxRect& in_rect,
157 const wxString& caption_text,
158 bool active,
159 wxRect* out_rect,
160 int* x_extent)
161{
162 wxCoord normal_textx, normal_texty;
163 wxCoord selected_textx, selected_texty;
164 wxCoord measured_textx, measured_texty;
165 wxCoord textx, texty;
166
167
168 // if the caption is empty, measure some temporary text
169 wxString caption = caption_text;
170 if (caption_text.empty())
171 caption = wxT("Xj");
172
173 // measure text
174 dc->SetFont(m_measuring_font);
175 dc->GetTextExtent(caption, &measured_textx, &measured_texty);
176
177 dc->SetFont(m_selected_font);
178 dc->GetTextExtent(caption, &selected_textx, &selected_texty);
179
180 dc->SetFont(m_normal_font);
181 dc->GetTextExtent(caption, &normal_textx, &normal_texty);
182
183 caption = caption_text;
184
185 wxCoord tab_height = measured_texty + 4;
186 wxCoord tab_width = measured_textx + tab_height + 5;
187 wxCoord tab_x = in_rect.x;
188 wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
189
190
191 // select pen, brush and font for the tab to be drawn
192
193 if (active)
194 {
195 dc->SetPen(m_selected_bkpen);
196 dc->SetBrush(m_selected_bkbrush);
197 dc->SetFont(m_selected_font);
198 textx = selected_textx;
199 texty = selected_texty;
200 }
201 else
202 {
203 dc->SetPen(m_normal_bkpen);
204 dc->SetBrush(m_normal_bkbrush);
205 dc->SetFont(m_normal_font);
206 textx = normal_textx;
207 texty = normal_texty;
208 }
209
210
211 // -- draw line --
212
213 wxPoint points[7];
214 points[0].x = tab_x;
215 points[0].y = tab_y + tab_height - 1;
216 points[1].x = tab_x + tab_height - 3;
217 points[1].y = tab_y + 2;
218 points[2].x = tab_x + tab_height + 3;
219 points[2].y = tab_y;
220 points[3].x = tab_x + tab_width - 2;
221 points[3].y = tab_y;
222 points[4].x = tab_x + tab_width;
223 points[4].y = tab_y + 2;
224 points[5].x = tab_x + tab_width;
225 points[5].y = tab_y + tab_height - 1;
226 points[6] = points[0];
227
228
229 dc->DrawPolygon(6, points);
230
231 dc->SetPen(*wxGREY_PEN);
232
233 //dc->DrawLines(active ? 6 : 7, points);
234 dc->DrawLines(7, points);
235
236 // -- draw text --
237
238 dc->DrawText(caption,
239 tab_x + (tab_height/3) + (tab_width/2) - (textx/2),
240 tab_y + tab_height - texty - 2);
241
242 *out_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
243 *x_extent = tab_width - (tab_height/2) - 1;
244}
245
246
247void wxDefaultTabArt::SetNormalFont(const wxFont& font)
248{
249 m_normal_font = font;
250}
251
252void wxDefaultTabArt::SetSelectedFont(const wxFont& font)
253{
254 m_selected_font = font;
255}
256
257void wxDefaultTabArt::SetMeasuringFont(const wxFont& font)
258{
259 m_measuring_font = font;
260}
261
262
263
264
265
266
267// -- wxAuiTabContainer class implementation --
268
269
270// wxAuiTabContainer is a class which contains information about each
271// tab. It also can render an entire tab control to a specified DC.
272// It's not a window class itself, because this code will be used by
273// the wxFrameMananger, where it is disadvantageous to have separate
274// windows for each tab control in the case of "docked tabs"
275
276// A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
277// which can be used as a tab control in the normal sense.
278
279
280wxAuiTabContainer::wxAuiTabContainer()
281{
282 m_art = new wxDefaultTabArt;
283}
284
fe498448
BW
285wxAuiTabContainer::~wxAuiTabContainer()
286{
3f69756e
BW
287 delete m_art;
288}
289
290void wxAuiTabContainer::SetArtProvider(wxTabArt* art)
291{
292 delete m_art;
293 m_art = art;
294}
295
296wxTabArt* wxAuiTabContainer::GetArtProvider()
297{
298 return m_art;
fe498448
BW
299}
300
cd05bf23
BW
301void wxAuiTabContainer::SetNormalFont(const wxFont& font)
302{
3f69756e 303 m_art->SetNormalFont(font);
cd05bf23
BW
304}
305
306void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
307{
3f69756e 308 m_art->SetSelectedFont(font);
cd05bf23
BW
309}
310
311void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
312{
3f69756e 313 m_art->SetMeasuringFont(font);
cd05bf23
BW
314}
315
316void wxAuiTabContainer::SetRect(const wxRect& rect)
317{
318 m_rect = rect;
319}
320
321bool wxAuiTabContainer::AddPage(wxWindow* page,
322 const wxAuiNotebookPage& info)
323{
324 wxAuiNotebookPage page_info;
325 page_info = info;
326 page_info.window = page;
4444d148 327
cd05bf23
BW
328 m_pages.Add(page_info);
329
330 return true;
331}
332
333bool wxAuiTabContainer::InsertPage(wxWindow* page,
334 const wxAuiNotebookPage& info,
335 size_t idx)
336{
337 wxAuiNotebookPage page_info;
338 page_info = info;
339 page_info.window = page;
4444d148 340
cd05bf23
BW
341 if (idx >= m_pages.GetCount())
342 m_pages.Add(page_info);
343 else
344 m_pages.Insert(page_info, idx);
345
346 return true;
347}
348
349bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
350{
351 size_t i, page_count = m_pages.GetCount();
352 for (i = 0; i < page_count; ++i)
353 {
354 wxAuiNotebookPage& page = m_pages.Item(i);
355 if (page.window == wnd)
356 {
357 m_pages.RemoveAt(i);
358 return true;
359 }
360 }
4444d148 361
cd05bf23
BW
362 return false;
363}
364
365bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
366{
367 bool found = false;
4444d148 368
cd05bf23
BW
369 size_t i, page_count = m_pages.GetCount();
370 for (i = 0; i < page_count; ++i)
371 {
372 wxAuiNotebookPage& page = m_pages.Item(i);
373 if (page.window == wnd)
374 {
375 page.active = true;
376 found = true;
377 }
378 else
379 {
380 page.active = false;
381 }
382 }
4444d148 383
cd05bf23
BW
384 return found;
385}
386
387void wxAuiTabContainer::SetNoneActive()
388{
389 size_t i, page_count = m_pages.GetCount();
390 for (i = 0; i < page_count; ++i)
391 {
392 wxAuiNotebookPage& page = m_pages.Item(i);
393 page.active = false;
394 }
395}
396
397bool wxAuiTabContainer::SetActivePage(size_t page)
398{
399 if (page >= m_pages.GetCount())
400 return false;
4444d148 401
cd05bf23
BW
402 return SetActivePage(m_pages.Item(page).window);
403}
4444d148 404
cd05bf23
BW
405int wxAuiTabContainer::GetActivePage() const
406{
407 size_t i, page_count = m_pages.GetCount();
408 for (i = 0; i < page_count; ++i)
409 {
410 wxAuiNotebookPage& page = m_pages.Item(i);
411 if (page.active)
412 return i;
413 }
4444d148 414
cd05bf23
BW
415 return -1;
416}
417
418wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
419{
420 if (idx >= m_pages.GetCount())
421 return NULL;
4444d148 422
cd05bf23
BW
423 return m_pages[idx].window;
424}
425
426int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
427{
428 size_t i, page_count = m_pages.GetCount();
429 for (i = 0; i < page_count; ++i)
430 {
431 wxAuiNotebookPage& page = m_pages.Item(i);
432 if (page.window == wnd)
433 return i;
434 }
435 return -1;
436}
437
438wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
439{
440 wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
441
442 return m_pages[idx];
443}
444
445wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
446{
447 return m_pages;
448}
449
450size_t wxAuiTabContainer::GetPageCount() const
451{
452 return m_pages.GetCount();
453}
454
b6418695 455void wxAuiTabContainer::AddButton(int id, int location, const wxBitmap& bmp)
cd05bf23
BW
456{
457 wxAuiTabContainerButton button;
458 button.id = id;
459 button.bitmap = bmp;
b6418695 460 button.location = location;
cd05bf23 461 button.cur_state = wxAUI_BUTTON_STATE_NORMAL;
4444d148 462
cd05bf23
BW
463 m_buttons.Add(button);
464}
465
466
467
cd05bf23
BW
468// Render() renders the tab catalog to the specified DC
469// It is a virtual function and can be overridden to
470// provide custom drawing capabilities
471void wxAuiTabContainer::Render(wxDC* raw_dc)
4444d148 472{
cd05bf23
BW
473 wxMemoryDC dc;
474 wxBitmap bmp;
475 bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
476 dc.SelectObject(bmp);
4444d148 477
3f69756e 478 m_art->DrawBackground(&dc, m_rect);
4444d148 479
cd05bf23 480 int offset = 0;
b6418695
BW
481 size_t i;
482
483 // draw the buttons on the right side
484 offset = m_rect.x + m_rect.width;
485 size_t button_count = m_buttons.GetCount();
486 for (i = 0; i < button_count; ++i)
487 {
488 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
489
490 if (button.location != wxRIGHT)
491 continue;
492
493 wxRect button_rect(offset - button.bitmap.GetWidth(), 1,
494 button.bitmap.GetWidth(), button.bitmap.GetHeight());
495
496 button.rect = button_rect;
497
498 DrawButton(dc, button.rect, button.bitmap,
499 //m_bkbrush.GetColour(),
500 *wxWHITE,
501 button.cur_state);
502
503 offset -= button.bitmap.GetWidth();
504 }
505
506
507
508 offset = 0;
509
510 // draw the buttons on the left side
511
512 for (i = 0; i < button_count; ++i)
513 {
514 wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
515
516 if (button.location != wxLEFT)
517 continue;
518
519 wxRect button_rect(offset, 1,
520 button.bitmap.GetWidth(),
521 button.bitmap.GetHeight());
522
523 button.rect = button_rect;
524
525 DrawButton(dc, button.rect, button.bitmap,
526 //m_bkbrush.GetColour(),
527 *wxWHITE,
528 button.cur_state);
529
530 offset += button.bitmap.GetWidth();
531 }
532
533
534 // draw the tabs
535 size_t page_count = m_pages.GetCount();
cd05bf23
BW
536
537 size_t active = 999;
538 int active_offset = 0;
4444d148 539
cd05bf23
BW
540 int x_extent = 0;
541 wxRect rect = m_rect;
542 rect.y = 0;
543 rect.width = 1000;
544 rect.height = m_rect.height;
4444d148 545
cd05bf23
BW
546 for (i = 0; i < page_count; ++i)
547 {
548 wxAuiNotebookPage& page = m_pages.Item(i);
4444d148 549
cd05bf23 550 rect.x = offset;
4444d148 551
3f69756e 552 m_art->DrawTab(&dc,
cd05bf23
BW
553 rect,
554 page.caption,
555 page.active,
556 &page.rect,
557 &x_extent);
4444d148 558
cd05bf23
BW
559 if (page.active)
560 {
561 active = i;
562 active_offset = offset;
563 }
4444d148 564
cd05bf23
BW
565 offset += x_extent;
566 }
4444d148 567
cd05bf23
BW
568 // draw the active tab again so it stands in the foreground
569 if (active < m_pages.GetCount())
570 {
571 wxAuiNotebookPage& page = m_pages.Item(active);
572
573 rect.x = active_offset;
3f69756e 574 m_art->DrawTab(&dc,
cd05bf23
BW
575 rect,
576 page.caption,
577 page.active,
578 &page.rect,
579 &x_extent);
580 }
4444d148 581
4444d148 582
cd05bf23
BW
583 raw_dc->Blit(m_rect.x, m_rect.y, m_rect.GetWidth(), m_rect.GetHeight(), &dc, 0, 0);
584}
585
586
587// TabHitTest() tests if a tab was hit, passing the window pointer
588// back if that condition was fulfilled. The function returns
589// true if a tab was hit, otherwise false
590bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
591{
22a35096 592 if (!m_rect.Contains(x,y))
cd05bf23 593 return false;
4444d148 594
cd05bf23 595 size_t i, page_count = m_pages.GetCount();
4444d148 596
cd05bf23
BW
597 for (i = 0; i < page_count; ++i)
598 {
599 wxAuiNotebookPage& page = m_pages.Item(i);
22a35096 600 if (page.rect.Contains(x,y))
cd05bf23
BW
601 {
602 *hit = page.window;
603 return true;
604 }
605 }
4444d148 606
cd05bf23
BW
607 return false;
608}
609
610// ButtonHitTest() tests if a button was hit. The function returns
611// true if a button was hit, otherwise false
612bool wxAuiTabContainer::ButtonHitTest(int x, int y,
613 wxAuiTabContainerButton** hit) const
614{
22a35096 615 if (!m_rect.Contains(x,y))
cd05bf23 616 return false;
4444d148 617
cd05bf23 618 size_t i, button_count = m_buttons.GetCount();
4444d148 619
cd05bf23
BW
620 for (i = 0; i < button_count; ++i)
621 {
622 wxAuiTabContainerButton& button = m_buttons.Item(i);
22a35096 623 if (button.rect.Contains(x,y))
cd05bf23
BW
624 {
625 *hit = &button;
626 return true;
627 }
628 }
4444d148 629
cd05bf23
BW
630 return false;
631}
632
633
634
635// the utility function ShowWnd() is the same as show,
636// except it handles wxTabMDIChildFrame windows as well,
637// as the Show() method on this class is "unplugged"
638static void ShowWnd(wxWindow* wnd, bool show)
639{
640 if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
641 {
642 wxTabMDIChildFrame* cf = (wxTabMDIChildFrame*)wnd;
643 cf->DoShow(show);
644 }
645 else
646 {
647 wnd->Show(show);
648 }
649}
650
651
652// DoShowHide() this function shows the active window, then
653// hides all of the other windows (in that order)
654void wxAuiTabContainer::DoShowHide()
655{
656 wxAuiNotebookPageArray& pages = GetPages();
657 size_t i, page_count = pages.GetCount();
658
659 // show new active page first
660 for (i = 0; i < page_count; ++i)
661 {
662 wxAuiNotebookPage& page = pages.Item(i);
663 if (page.active)
664 {
665 ShowWnd(page.window, true);
666 break;
667 }
668 }
669
670 // hide all other pages
671 for (i = 0; i < page_count; ++i)
672 {
673 wxAuiNotebookPage& page = pages.Item(i);
674 ShowWnd(page.window, page.active);
675 }
676}
677
678
679
680
681
682
683// -- wxAuiTabCtrl class implementation --
684
685
686const int wxAuiButtonClose = 101;
687
688BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
689 EVT_PAINT(wxAuiTabCtrl::OnPaint)
690 EVT_ERASE_BACKGROUND(wxAuiTabCtrl::OnEraseBackground)
691 EVT_SIZE(wxAuiTabCtrl::OnSize)
692 EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
693 EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
694 EVT_MOTION(wxAuiTabCtrl::OnMotion)
695 EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
696END_EVENT_TABLE()
697
698
699wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent,
700 wxWindowID id,
701 const wxPoint& pos,
702 const wxSize& size,
4444d148 703 long style) : wxControl(parent, id, pos, size, style)
cd05bf23
BW
704{
705 m_click_pt = wxDefaultPosition;
706 m_is_dragging = false;
707 m_hover_button = NULL;
4444d148
WS
708
709 // FIXME: copied from dockart-- needs to put in a common place
df00bdf7
RR
710#if defined( __WXMAC__ )
711 static unsigned char close_bits[]={
712 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
713 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
714 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
715#elif defined( __WXGTK__)
716 static unsigned char close_bits[]={
717 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
718 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
719 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
720#else
cd05bf23
BW
721 static unsigned char close_bits[]={
722 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
723 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
724 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
df00bdf7 725#endif
4444d148 726
b6418695 727 AddButton(101, wxRIGHT, BitmapFromBits(close_bits, 16, 16, *wxBLACK));
cd05bf23
BW
728}
729
730
731void wxAuiTabCtrl::OnPaint(wxPaintEvent&)
732{
733 wxPaintDC dc(this);
4444d148 734
cd05bf23 735 dc.SetFont(GetFont());
4444d148 736
cd05bf23
BW
737 if (GetPageCount() > 0)
738 Render(&dc);
739}
740
741void wxAuiTabCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
742{
743}
744
745void wxAuiTabCtrl::OnSize(wxSizeEvent& evt)
746{
747 wxSize s = evt.GetSize();
748 wxRect r(0, 0, s.GetWidth(), s.GetHeight());
749 SetRect(r);
750}
751
752void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt)
753{
754 CaptureMouse();
755 m_click_pt = wxDefaultPosition;
756 m_is_dragging = false;
757 m_click_tab = -1;
4444d148 758
cd05bf23
BW
759 wxWindow* wnd;
760 if (TabHitTest(evt.m_x, evt.m_y, &wnd))
761 {
762 wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
763 e.SetSelection(GetIdxFromWindow(wnd));
764 e.SetOldSelection(GetActivePage());
765 e.SetEventObject(this);
766 GetEventHandler()->ProcessEvent(e);
4444d148 767
cd05bf23
BW
768 m_click_pt.x = evt.m_x;
769 m_click_pt.y = evt.m_y;
770 m_click_tab = e.GetSelection();
771 }
4444d148 772
cd05bf23
BW
773 if (m_hover_button)
774 {
775 m_hover_button->cur_state = wxAUI_BUTTON_STATE_PRESSED;
776 Refresh();
777 Update();
778 }
779}
780
781void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&)
782{
783 if (GetCapture() == this)
784 ReleaseMouse();
4444d148 785
cd05bf23
BW
786 if (m_is_dragging)
787 {
788 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
789 evt.SetSelection(m_click_tab);
790 evt.SetOldSelection(m_click_tab);
791 evt.SetEventObject(this);
792 GetEventHandler()->ProcessEvent(evt);
793 return;
794 }
4444d148 795
cd05bf23
BW
796 if (m_hover_button)
797 {
798 m_hover_button->cur_state = wxAUI_BUTTON_STATE_HOVER;
799 Refresh();
800 Update();
4444d148 801
cd05bf23
BW
802 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
803 evt.SetInt(m_hover_button->id);
804 evt.SetEventObject(this);
805 GetEventHandler()->ProcessEvent(evt);
806 }
4444d148 807
cd05bf23
BW
808 m_click_pt = wxDefaultPosition;
809 m_is_dragging = false;
810 m_click_tab = -1;
811}
812
813void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
814{
815 wxPoint pos = evt.GetPosition();
816
817 // check if the mouse is hovering above a button
818 wxAuiTabContainerButton* button;
819 if (ButtonHitTest(pos.x, pos.y, &button))
820 {
b6418695
BW
821 if (m_hover_button && button != m_hover_button)
822 {
823 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
824 m_hover_button = NULL;
825 Refresh();
826 Update();
827 }
828
cd05bf23
BW
829 if (button->cur_state != wxAUI_BUTTON_STATE_HOVER)
830 {
831 button->cur_state = wxAUI_BUTTON_STATE_HOVER;
832 Refresh();
833 Update();
834 m_hover_button = button;
835 return;
836 }
837 }
838 else
839 {
840 if (m_hover_button)
841 {
842 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
843 m_hover_button = NULL;
844 Refresh();
845 Update();
846 }
847 }
4444d148
WS
848
849
cd05bf23
BW
850 if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition)
851 return;
4444d148 852
cd05bf23
BW
853 if (m_is_dragging)
854 {
855 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId);
856 evt.SetSelection(m_click_tab);
857 evt.SetOldSelection(m_click_tab);
858 evt.SetEventObject(this);
859 GetEventHandler()->ProcessEvent(evt);
860 return;
4444d148
WS
861 }
862
863
cd05bf23
BW
864 int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
865 int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
866
867 if (abs(pos.x - m_click_pt.x) > drag_x_threshold ||
868 abs(pos.y - m_click_pt.y) > drag_y_threshold)
869 {
870 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId);
871 evt.SetSelection(m_click_tab);
872 evt.SetOldSelection(m_click_tab);
873 evt.SetEventObject(this);
874 GetEventHandler()->ProcessEvent(evt);
4444d148 875
cd05bf23
BW
876 m_is_dragging = true;
877 }
878}
879
880void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event))
881{
882 if (m_hover_button)
883 {
884 m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL;
885 m_hover_button = NULL;
886 Refresh();
887 Update();
888 }
889}
890
891
892// wxTabFrame is an interesting case. It's important that all child pages
893// of the multi-notebook control are all actually children of that control
894// (and not grandchildren). wxTabFrame facilitates this. There is one
895// instance of wxTabFrame for each tab control inside the multi-notebook.
896// It's important to know that wxTabFrame is not a real window, but it merely
897// used to capture the dimensions/positioning of the internal tab control and
898// it's managed page windows
899
900class wxTabFrame : public wxWindow
901{
902public:
903
904 wxTabFrame()
905 {
906 m_tabs = NULL;
907 m_rect = wxRect(0,0,200,200);
da5e85d9
BW
908 m_tab_ctrl_height = 20;
909 }
4444d148 910
da5e85d9
BW
911 void SetTabCtrlHeight(int h)
912 {
913 m_tab_ctrl_height = h;
cd05bf23 914 }
4444d148 915
cd05bf23
BW
916 void DoSetSize(int x, int y,
917 int width, int height,
918 int WXUNUSED(sizeFlags = wxSIZE_AUTO))
919 {
920 m_rect = wxRect(x, y, width, height);
921 DoSizing();
922 }
4444d148 923
cd05bf23
BW
924 void DoGetClientSize(int* x, int* y) const
925 {
926 *x = m_rect.width;
927 *y = m_rect.height;
928 }
4f450f41
RD
929
930 bool Show( bool WXUNUSED(show = true) ) { return false; }
4444d148 931
cd05bf23
BW
932 void DoSizing()
933 {
934 if (!m_tabs)
935 return;
4444d148 936
da5e85d9 937 int tab_height = wxMin(m_rect.height, m_tab_ctrl_height);
cd05bf23
BW
938 m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, tab_height);
939 m_tabs->SetSize(m_rect.x, m_rect.y, m_rect.width, tab_height);
940 m_tabs->SetRect(wxRect(0, 0, m_rect.width, tab_height));
941 m_tabs->Refresh();
9d59bf68 942 m_tabs->Update();
4444d148 943
cd05bf23
BW
944 wxAuiNotebookPageArray& pages = m_tabs->GetPages();
945 size_t i, page_count = pages.GetCount();
4444d148 946
cd05bf23
BW
947 for (i = 0; i < page_count; ++i)
948 {
949 wxAuiNotebookPage& page = pages.Item(i);
950 page.window->SetSize(m_rect.x, m_rect.y+tab_height, m_rect.width, m_rect.height-tab_height);
4444d148 951
cd05bf23
BW
952 if (page.window->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
953 {
954 wxTabMDIChildFrame* wnd = (wxTabMDIChildFrame*)page.window;
955 wnd->ApplyMDIChildFrameRect();
956 }
957 }
958 }
959
134e83cb
BW
960 void DoGetSize(int* x, int* y) const
961 {
962 if (x)
963 *x = m_rect.GetWidth();
964 if (y)
965 *y = m_rect.GetHeight();
966 }
4444d148 967
134e83cb
BW
968 void Update()
969 {
970 // does nothing
971 }
4444d148 972
cd05bf23
BW
973public:
974
975 wxRect m_rect;
976 wxRect m_tab_rect;
977 wxAuiTabCtrl* m_tabs;
da5e85d9 978 int m_tab_ctrl_height;
cd05bf23
BW
979};
980
981
982
983
984
985// -- wxAuiMultiNotebook class implementation --
986
987BEGIN_EVENT_TABLE(wxAuiMultiNotebook, wxControl)
988 //EVT_ERASE_BACKGROUND(wxAuiMultiNotebook::OnEraseBackground)
989 //EVT_SIZE(wxAuiMultiNotebook::OnSize)
990 //EVT_LEFT_DOWN(wxAuiMultiNotebook::OnLeftDown)
991 EVT_CHILD_FOCUS(wxAuiMultiNotebook::OnChildFocus)
992 EVT_COMMAND_RANGE(10000, 10100,
993 wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING,
994 wxAuiMultiNotebook::OnTabClicked)
995 EVT_COMMAND_RANGE(10000, 10100,
996 wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG,
4444d148 997 wxAuiMultiNotebook::OnTabBeginDrag)
cd05bf23
BW
998 EVT_COMMAND_RANGE(10000, 10100,
999 wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
4444d148 1000 wxAuiMultiNotebook::OnTabEndDrag)
cd05bf23
BW
1001 EVT_COMMAND_RANGE(10000, 10100,
1002 wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION,
1003 wxAuiMultiNotebook::OnTabDragMotion)
1004 EVT_COMMAND_RANGE(10000, 10100,
1005 wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
1006 wxAuiMultiNotebook::OnTabButton)
1007END_EVENT_TABLE()
1008
1009wxAuiMultiNotebook::wxAuiMultiNotebook()
1010{
1011 m_curpage = -1;
1012 m_tab_id_counter = 10000;
1013 m_dummy_wnd = NULL;
da5e85d9 1014 m_tab_ctrl_height = 20;
cd05bf23
BW
1015}
1016
1017wxAuiMultiNotebook::wxAuiMultiNotebook(wxWindow *parent,
1018 wxWindowID id,
1019 const wxPoint& pos,
1020 const wxSize& size,
1021 long style) : wxControl(parent, id, pos, size, style)
1022{
1023 InitNotebook();
1024}
1025
1026bool wxAuiMultiNotebook::Create(wxWindow* parent,
1027 wxWindowID id,
1028 const wxPoint& pos,
1029 const wxSize& size,
1030 long style)
1031{
1032 if (!wxControl::Create(parent, id, pos, size, style))
1033 return false;
4444d148 1034
cd05bf23 1035 InitNotebook();
4444d148 1036
cd05bf23
BW
1037 return true;
1038}
1039
1040// InitNotebook() contains common initialization
1041// code called by all constructors
1042void wxAuiMultiNotebook::InitNotebook()
1043{
da5e85d9
BW
1044 m_curpage = -1;
1045 m_tab_id_counter = 10000;
1046 m_dummy_wnd = NULL;
1047 m_tab_ctrl_height = 20;
4444d148 1048
cd05bf23
BW
1049 m_normal_font = *wxNORMAL_FONT;
1050 m_selected_font = *wxNORMAL_FONT;
1051 m_selected_font.SetWeight(wxBOLD);
4444d148 1052
da5e85d9
BW
1053 // choose a default for the tab height
1054 wxClientDC dc(this);
1055 int tx, ty;
1056 dc.SetFont(m_selected_font);
1057 dc.GetTextExtent(wxT("ABCDEFGHhijklm"), &tx, &ty);
1058 m_tab_ctrl_height = (ty*150)/100;
4444d148
WS
1059
1060 m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0));
cd05bf23
BW
1061 m_dummy_wnd->SetSize(200, 200);
1062 m_dummy_wnd->Show(false);
4444d148 1063
cd05bf23 1064 m_mgr.SetManagedWindow(this);
4444d148 1065
cd05bf23
BW
1066 m_mgr.AddPane(m_dummy_wnd,
1067 wxPaneInfo().Name(wxT("dummy")).Bottom().Show(false));
4444d148 1068
cd05bf23
BW
1069 m_mgr.Update();
1070}
1071
1072wxAuiMultiNotebook::~wxAuiMultiNotebook()
1073{
1074 m_mgr.UnInit();
1075}
1076
3f69756e
BW
1077void wxAuiMultiNotebook::SetArtProvider(wxTabArt* art)
1078{
1079 m_tabs.SetArtProvider(art);
1080}
1081
1082wxTabArt* wxAuiMultiNotebook::GetArtProvider()
1083{
1084 return m_tabs.GetArtProvider();
1085}
1086
cd05bf23
BW
1087bool wxAuiMultiNotebook::AddPage(wxWindow* page,
1088 const wxString& caption,
1089 bool select,
1090 const wxBitmap& bitmap)
1091{
1092 return InsertPage(GetPageCount(), page, caption, select, bitmap);
1093}
4444d148 1094
cd05bf23
BW
1095bool wxAuiMultiNotebook::InsertPage(size_t page_idx,
1096 wxWindow* page,
1097 const wxString& caption,
1098 bool select,
1099 const wxBitmap& bitmap)
1100{
1101 wxAuiNotebookPage info;
1102 info.window = page;
1103 info.caption = caption;
1104 info.bitmap = bitmap;
1105 info.active = false;
1106
1107 // if there are currently no tabs, the first added
1108 // tab must be active
1109 if (m_tabs.GetPageCount() == 0)
1110 info.active = true;
1111
1112 m_tabs.InsertPage(page, info, page_idx);
1113
1114 wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
1115 if (page_idx >= active_tabctrl->GetPageCount())
1116 active_tabctrl->AddPage(page, info);
1117 else
1118 active_tabctrl->InsertPage(page, info, page_idx);
4444d148 1119
cd05bf23
BW
1120 DoSizing();
1121 active_tabctrl->DoShowHide();
4444d148 1122
cd05bf23
BW
1123 if (select)
1124 {
1125 int idx = m_tabs.GetIdxFromWindow(page);
1126 wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiMultiNotebook::InsertPage()"));
4444d148 1127
cd05bf23
BW
1128 SetSelection(idx);
1129 }
4444d148 1130
cd05bf23
BW
1131 return true;
1132}
1133
1134
1135// DeletePage() removes a tab from the multi-notebook,
1136// and destroys the window as well
1137bool wxAuiMultiNotebook::DeletePage(size_t page_idx)
ae4558e0 1138{
4444d148 1139 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
ae4558e0 1140 wxWindow* new_active = NULL;
4444d148 1141
cd05bf23
BW
1142 // find out which onscreen tab ctrl owns this tab
1143 wxAuiTabCtrl* ctrl;
1144 int ctrl_idx;
1145 if (!FindTab(wnd, &ctrl, &ctrl_idx))
1146 return false;
4444d148 1147
cd05bf23
BW
1148 // find a new page and set it as active
1149 int new_idx = ctrl_idx+1;
1150 if (new_idx >= (int)ctrl->GetPageCount())
1151 new_idx = ctrl_idx-1;
4444d148 1152
cd05bf23
BW
1153 if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
1154 {
ae4558e0 1155 new_active = ctrl->GetWindowFromIdx(new_idx);
cd05bf23
BW
1156 }
1157 else
1158 {
1159 // set the active page to the first page that
1160 // isn't the one being deleted
cd05bf23
BW
1161 size_t i, page_count = m_tabs.GetPageCount();
1162 for (i = 0; i < page_count; ++i)
1163 {
1164 wxWindow* w = m_tabs.GetWindowFromIdx(i);
1165 if (wnd != w)
1166 {
ae4558e0 1167 new_active = m_tabs.GetWindowFromIdx(i);
cd05bf23
BW
1168 break;
1169 }
1170 }
cd05bf23 1171 }
4444d148 1172
cd05bf23
BW
1173 // remove the tab from main catalog
1174 if (!m_tabs.RemovePage(wnd))
1175 return false;
4444d148 1176
cd05bf23
BW
1177 // remove the tab from the onscreen tab ctrl
1178 ctrl->RemovePage(wnd);
4444d148 1179
cd05bf23
BW
1180 // actually destroy the window now
1181 if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1182 {
1183 // delete the child frame with pending delete, as is
1184 // customary with frame windows
1185 if (!wxPendingDelete.Member(wnd))
1186 wxPendingDelete.Append(wnd);
1187 }
1188 else
1189 {
1190 wnd->Destroy();
1191 }
4444d148 1192
cd05bf23 1193 RemoveEmptyTabFrames();
4444d148 1194
ae4558e0
BW
1195 // set new active pane
1196 if (new_active)
1197 {
1198 m_curpage = -1;
1199 SetSelection(m_tabs.GetIdxFromWindow(new_active));
1200 }
1201
cd05bf23
BW
1202 return true;
1203}
1204
1205
1206
1207// RemovePage() removes a tab from the multi-notebook,
1208// but does not destroy the window
1209bool wxAuiMultiNotebook::RemovePage(size_t page_idx)
1210{
1211 // remove the tab from our own catalog
1212 wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
1213 if (!m_tabs.RemovePage(wnd))
1214 return false;
4444d148 1215
cd05bf23
BW
1216 // remove the tab from the onscreen tab ctrl
1217 wxAuiTabCtrl* ctrl;
1218 int ctrl_idx;
1219 if (FindTab(wnd, &ctrl, &ctrl_idx))
1220 {
1221 ctrl->RemovePage(wnd);
1222 return true;
1223 }
4444d148 1224
cd05bf23
BW
1225 return false;
1226}
1227
1228// SetPageText() changes the tab caption of the specified page
1229bool wxAuiMultiNotebook::SetPageText(size_t page_idx, const wxString& text)
4444d148 1230{
cd05bf23
BW
1231 if (page_idx >= m_tabs.GetPageCount())
1232 return false;
4444d148 1233
cd05bf23
BW
1234 // update our own tab catalog
1235 wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
1236 page_info.caption = text;
4444d148 1237
cd05bf23
BW
1238 // update what's on screen
1239 wxAuiTabCtrl* ctrl;
1240 int ctrl_idx;
1241 if (FindTab(page_info.window, &ctrl, &ctrl_idx))
1242 {
1243 wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx);
1244 info.caption = text;
1245 ctrl->Refresh();
639a4f7b 1246 ctrl->Update();
cd05bf23 1247 }
4444d148 1248
cd05bf23
BW
1249 return true;
1250}
1251
1252// GetSelection() returns the index of the currently active page
1253int wxAuiMultiNotebook::GetSelection() const
1254{
1255 return m_curpage;
1256}
1257
1258// SetSelection() sets the currently active page
1259size_t wxAuiMultiNotebook::SetSelection(size_t new_page)
1260{
1261 wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page);
1262 if (!wnd)
1263 return m_curpage;
4444d148 1264
cd05bf23
BW
1265 wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId);
1266 evt.SetSelection(new_page);
1267 evt.SetOldSelection(m_curpage);
1268 evt.SetEventObject(this);
1269 if (!GetEventHandler()->ProcessEvent(evt) || evt.IsAllowed())
1270 {
1271 // program allows the page change
1272 evt.SetEventType(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED);
1273 (void)GetEventHandler()->ProcessEvent(evt);
1274
1275
1276
1277 wxAuiTabCtrl* ctrl;
1278 int ctrl_idx;
1279 if (FindTab(wnd, &ctrl, &ctrl_idx))
4444d148 1280 {
cd05bf23 1281 m_tabs.SetActivePage(wnd);
4444d148 1282
cd05bf23
BW
1283 ctrl->SetActivePage(ctrl_idx);
1284 DoSizing();
1285 ctrl->DoShowHide();
4444d148 1286
cd05bf23
BW
1287 int old_curpage = m_curpage;
1288 m_curpage = new_page;
1289
1290
1291 // set fonts
1292 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1293 size_t i, pane_count = all_panes.GetCount();
1294 for (i = 0; i < pane_count; ++i)
1295 {
1296 wxPaneInfo& pane = all_panes.Item(i);
1297 if (pane.name == wxT("dummy"))
1298 continue;
1299 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
1300 if (tabctrl != ctrl)
1301 tabctrl->SetSelectedFont(m_normal_font);
1302 else
1303 tabctrl->SetSelectedFont(m_selected_font);
1304 tabctrl->Refresh();
1305 }
1306
1307 wnd->SetFocus();
4444d148 1308
cd05bf23
BW
1309 return old_curpage;
1310 }
1311 }
1312
1313 return m_curpage;
1314}
1315
1316// GetPageCount() returns the total number of
1317// pages managed by the multi-notebook
1318size_t wxAuiMultiNotebook::GetPageCount() const
1319{
1320 return m_tabs.GetPageCount();
1321}
1322
1323// GetPage() returns the wxWindow pointer of the
1324// specified page
1325wxWindow* wxAuiMultiNotebook::GetPage(size_t page_idx) const
1326{
1327 wxASSERT(page_idx < m_tabs.GetPageCount());
4444d148 1328
cd05bf23
BW
1329 return m_tabs.GetWindowFromIdx(page_idx);
1330}
1331
1332// DoSizing() performs all sizing operations in each tab control
1333void wxAuiMultiNotebook::DoSizing()
1334{
1335 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1336 size_t i, pane_count = all_panes.GetCount();
1337 for (i = 0; i < pane_count; ++i)
1338 {
1339 if (all_panes.Item(i).name == wxT("dummy"))
1340 continue;
1341
1342 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1343 tabframe->DoSizing();
1344 }
1345}
1346
1347// GetActiveTabCtrl() returns the active tab control. It is
1348// called to determine which control gets new windows being added
1349wxAuiTabCtrl* wxAuiMultiNotebook::GetActiveTabCtrl()
1350{
1351 if (m_curpage >= 0 && m_curpage < (int)m_tabs.GetPageCount())
1352 {
1353 wxAuiTabCtrl* ctrl;
1354 int idx;
4444d148 1355
cd05bf23
BW
1356 // find the tab ctrl with the current page
1357 if (FindTab(m_tabs.GetPage(m_curpage).window,
1358 &ctrl, &idx))
4444d148 1359 {
cd05bf23
BW
1360 return ctrl;
1361 }
1362 }
4444d148 1363
cd05bf23
BW
1364 // no current page, just find the first tab ctrl
1365 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1366 size_t i, pane_count = all_panes.GetCount();
1367 for (i = 0; i < pane_count; ++i)
1368 {
1369 if (all_panes.Item(i).name == wxT("dummy"))
1370 continue;
4444d148 1371
cd05bf23
BW
1372 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1373 return tabframe->m_tabs;
1374 }
4444d148 1375
cd05bf23
BW
1376 // If there is no tabframe at all, create one
1377 wxTabFrame* tabframe = new wxTabFrame;
da5e85d9 1378 tabframe->SetTabCtrlHeight(m_tab_ctrl_height);
cd05bf23
BW
1379 tabframe->m_tabs = new wxAuiTabCtrl(this,
1380 m_tab_id_counter++,
1381 wxDefaultPosition,
1382 wxDefaultSize,
1383 wxNO_BORDER);
1384 m_mgr.AddPane(tabframe,
4444d148
WS
1385 wxPaneInfo().Center().CaptionVisible(false));
1386
cd05bf23 1387 m_mgr.Update();
4444d148 1388
cd05bf23
BW
1389 return tabframe->m_tabs;
1390}
1391
1392// FindTab() finds the tab control that currently contains the window as well
1393// as the index of the window in the tab control. It returns true if the
1394// window was found, otherwise false.
1395bool wxAuiMultiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
1396{
1397 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1398 size_t i, pane_count = all_panes.GetCount();
1399 for (i = 0; i < pane_count; ++i)
1400 {
1401 if (all_panes.Item(i).name == wxT("dummy"))
1402 continue;
4444d148 1403
cd05bf23 1404 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
4444d148 1405
cd05bf23
BW
1406 int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
1407 if (page_idx != -1)
1408 {
1409 *ctrl = tabframe->m_tabs;
1410 *idx = page_idx;
1411 return true;
1412 }
1413 }
4444d148 1414
cd05bf23
BW
1415 return false;
1416}
1417
1418
1419void wxAuiMultiNotebook::OnEraseBackground(wxEraseEvent&)
1420{
1421}
1422
1423void wxAuiMultiNotebook::OnSize(wxSizeEvent&)
1424{
1425}
1426
1427void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent& command_evt)
1428{
1429 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
4444d148 1430
cd05bf23
BW
1431 wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject();
1432 wxASSERT(ctrl != NULL);
4444d148 1433
cd05bf23
BW
1434 wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
1435 wxASSERT(wnd != NULL);
4444d148 1436
cd05bf23
BW
1437 int idx = m_tabs.GetIdxFromWindow(wnd);
1438 wxASSERT(idx != -1);
4444d148 1439
cd05bf23
BW
1440 SetSelection(idx);
1441}
1442
1443void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent&)
1444{
1445}
1446
1447void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt)
1448{
1449 wxPoint screen_pt = ::wxGetMousePosition();
1450 wxPoint client_pt = ScreenToClient(screen_pt);
1451 wxPoint zero(0,0);
4444d148 1452
cd05bf23 1453 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4444d148 1454
cd05bf23
BW
1455 wxAuiTabCtrl* tab_ctrl = GetTabCtrlFromPoint(client_pt);
1456 if (tab_ctrl == src_tabs)
1457 {
1458 // inner-tabctrl dragging is not yet implemented
1459 m_mgr.HideHint();
1460 return;
1461 }
4444d148 1462
cd05bf23
BW
1463 if (tab_ctrl)
1464 {
1465 wxRect hint_rect = tab_ctrl->GetRect();
1466 ClientToScreen(&hint_rect.x, &hint_rect.y);
1467 m_mgr.ShowHint(hint_rect);
1468 }
1469 else
1470 {
1471 m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
1472 }
1473}
1474
1475
1476
1477void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
1478{
1479 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1480
1481 m_mgr.HideHint();
4444d148 1482
cd05bf23
BW
1483
1484 // get the mouse position, which will be used to determine the drop point
1485 wxPoint mouse_screen_pt = ::wxGetMousePosition();
1486 wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
1487
1488
1489 // the src tab control is the control that fired this event
1490 wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
1491 wxAuiTabCtrl* dest_tabs = NULL;
4444d148 1492
cd05bf23
BW
1493
1494 // If the pointer is in an existing tab frame, do a tab insert
1495 wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt);
1496 wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd);
1497 if (tab_frame)
1498 {
1499 dest_tabs = tab_frame->m_tabs;
4444d148 1500
cd05bf23
BW
1501 if (dest_tabs == src_tabs)
1502 return;
1503 }
1504 else
1505 {
1506 // If there is no tabframe at all, create one
1507 wxTabFrame* new_tabs = new wxTabFrame;
da5e85d9 1508 new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
cd05bf23
BW
1509 new_tabs->m_tabs = new wxAuiTabCtrl(this,
1510 m_tab_id_counter++,
1511 wxDefaultPosition,
1512 wxDefaultSize,
1513 wxNO_BORDER);
1514 m_mgr.AddPane(new_tabs,
1515 wxPaneInfo().Bottom().CaptionVisible(false),
1516 mouse_client_pt);
1517 m_mgr.Update();
1518 dest_tabs = new_tabs->m_tabs;
1519 }
4444d148
WS
1520
1521
1522
cd05bf23
BW
1523 // remove the page from the source tabs
1524 wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection());
1525 page_info.active = false;
1526 src_tabs->RemovePage(page_info.window);
1527 if (src_tabs->GetPageCount() > 0)
1528 {
1529 src_tabs->SetActivePage((size_t)0);
1530 src_tabs->DoShowHide();
1531 src_tabs->Refresh();
1532 }
1533
4444d148
WS
1534
1535
cd05bf23
BW
1536 // add the page to the destination tabs
1537 dest_tabs->AddPage(page_info.window, page_info);
4444d148 1538
cd05bf23 1539 if (src_tabs->GetPageCount() == 0)
4444d148 1540 {
cd05bf23
BW
1541 RemoveEmptyTabFrames();
1542 }
4444d148 1543
cd05bf23
BW
1544 DoSizing();
1545 dest_tabs->DoShowHide();
1546 dest_tabs->Refresh();
1547
1548 SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
1549}
1550
1551wxAuiTabCtrl* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint& pt)
1552{
1553 // if we've just removed the last tab from the source
1554 // tab set, the remove the tab control completely
1555 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1556 size_t i, pane_count = all_panes.GetCount();
1557 for (i = 0; i < pane_count; ++i)
1558 {
1559 if (all_panes.Item(i).name == wxT("dummy"))
1560 continue;
4444d148 1561
cd05bf23 1562 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
22a35096 1563 if (tabframe->m_tab_rect.Contains(pt))
cd05bf23
BW
1564 return tabframe->m_tabs;
1565 }
4444d148 1566
cd05bf23
BW
1567 return NULL;
1568}
1569
1570wxWindow* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl)
1571{
1572 // if we've just removed the last tab from the source
1573 // tab set, the remove the tab control completely
1574 wxPaneInfoArray& all_panes = m_mgr.GetAllPanes();
1575 size_t i, pane_count = all_panes.GetCount();
1576 for (i = 0; i < pane_count; ++i)
1577 {
1578 if (all_panes.Item(i).name == wxT("dummy"))
1579 continue;
4444d148 1580
cd05bf23
BW
1581 wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
1582 if (tabframe->m_tabs == tab_ctrl)
1583 {
1584 return tabframe;
1585 }
1586 }
4444d148 1587
cd05bf23
BW
1588 return NULL;
1589}
1590
1591void wxAuiMultiNotebook::RemoveEmptyTabFrames()
1592{
cd05bf23
BW
1593 // if we've just removed the last tab from the source
1594 // tab set, the remove the tab control completely
1595 wxPaneInfoArray all_panes = m_mgr.GetAllPanes();
1596 size_t i, pane_count = all_panes.GetCount();
1597 for (i = 0; i < pane_count; ++i)
1598 {
1599 if (all_panes.Item(i).name == wxT("dummy"))
1600 continue;
1601
1602 wxTabFrame* tab_frame = (wxTabFrame*)all_panes.Item(i).window;
1603 if (tab_frame->m_tabs->GetPageCount() == 0)
1604 {
1605 m_mgr.DetachPane(tab_frame);
4444d148 1606
cd05bf23
BW
1607 // use pending delete because sometimes during
1608 // window closing, refreshs are pending
1609 if (!wxPendingDelete.Member(tab_frame->m_tabs))
4444d148 1610 wxPendingDelete.Append(tab_frame->m_tabs);
cd05bf23 1611 //tab_frame->m_tabs->Destroy();
4444d148 1612
cd05bf23 1613 delete tab_frame;
cd05bf23
BW
1614 }
1615 }
4444d148
WS
1616
1617
cd05bf23
BW
1618 // check to see if there is still a center pane;
1619 // if there isn't, make a frame the center pane
1620 wxPaneInfoArray panes = m_mgr.GetAllPanes();
1621 pane_count = panes.GetCount();
1622 wxWindow* first_good = NULL;
1623 bool center_found = false;
1624 for (i = 0; i < pane_count; ++i)
1625 {
1626 if (panes.Item(i).name == wxT("dummy"))
1627 continue;
1628 if (panes.Item(i).dock_direction == wxAUI_DOCK_CENTRE)
1629 center_found = true;
1630 if (!first_good)
1631 first_good = panes.Item(i).window;
1632 }
1633
1634 if (!center_found && first_good)
1635 {
1636 m_mgr.GetPane(first_good).Centre();
cd05bf23
BW
1637 }
1638
4444d148 1639 m_mgr.Update();
cd05bf23
BW
1640}
1641
1642void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent& evt)
1643{
1644 int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
1645 if (idx != -1 && idx != m_curpage)
1646 {
4444d148 1647 SetSelection(idx);
cd05bf23
BW
1648 }
1649}
1650
1651
1652void wxAuiMultiNotebook::OnTabButton(wxCommandEvent& command_evt)
1653{
1654 wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt;
1655 wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
4444d148 1656
cd05bf23 1657 int button_id = evt.GetInt();
4444d148 1658
cd05bf23
BW
1659 if (button_id == wxAuiButtonClose)
1660 {
1661 int selection = tabs->GetActivePage();
4444d148 1662
cd05bf23
BW
1663 if (selection != -1)
1664 {
1665 wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
4444d148 1666
cd05bf23
BW
1667 if (close_wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame)))
1668 {
1669 close_wnd->Close();
1670 }
1671 else
1672 {
1673 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
1674 DeletePage(main_idx);
1675 }
1676 }
1677 }
1678}
1679
1680
1681
1682
1683#endif // wxUSE_AUI