]> git.saurik.com Git - wxWidgets.git/blame - src/generic/tabg.cpp
Fix setting the clipping region for a DC when the region is an
[wxWidgets.git] / src / generic / tabg.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
18680f86 2// Name: src/generic/tabg.cpp
c801d85f
KB
3// Purpose: Generic tabbed dialogs
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c)
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
c801d85f
KB
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
18680f86 16 #pragma hdrstop
c801d85f
KB
17#endif
18
1e6feb95
VZ
19#if wxUSE_TAB_DIALOG
20
c801d85f 21#ifndef WX_PRECOMP
00dd3b18
MB
22 #include "wx/settings.h"
23 #include "wx/intl.h"
ed39ff57 24 #include "wx/dcclient.h"
18680f86 25 #include "wx/math.h"
c801d85f
KB
26#endif
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <stdarg.h>
c801d85f
KB
31
32#include "wx/tab.h"
4410d619
MB
33#include "wx/listimpl.cpp"
34
e933b5bc 35WX_DEFINE_LIST(wxTabLayerList)
c801d85f 36
4b5f3fe6
JS
37// not defined: use old, square tab implementation (fills in tabs)
38// defined: use new, rounded tab implementation (doesn't colour in tabs)
39// #define wxUSE_NEW_METHOD
40
c801d85f
KB
41IMPLEMENT_DYNAMIC_CLASS(wxTabControl, wxObject)
42
4410d619 43// IMPLEMENT_DYNAMIC_CLASS(wxTabLayer, wxList)
c801d85f
KB
44
45wxTabControl::wxTabControl(wxTabView *v)
46{
47 m_view = v;
ca65c044 48 m_isSelected = false;
c801d85f
KB
49 m_offsetX = 0;
50 m_offsetY = 0;
51 m_width = 0;
52 m_height = 0;
53 m_id = 0;
54 m_rowPosition = 0;
55 m_colPosition = 0;
56}
57
58wxTabControl::~wxTabControl(void)
59{
60}
2b854a32 61
c801d85f
KB
62void wxTabControl::OnDraw(wxDC& dc, bool lastInRow)
63{
64 // Old, but in some ways better (drawing opaque tabs)
4b5f3fe6 65#ifndef wxUSE_NEW_METHOD
c801d85f
KB
66 if (!m_view)
67 return;
2b854a32 68
c801d85f
KB
69 // Top-left of tab view area
70 int viewX = m_view->GetViewRect().x;
71 int viewY = m_view->GetViewRect().y;
2b854a32 72
c801d85f
KB
73 // Top-left of tab control
74 int tabX = GetX() + viewX;
75 int tabY = GetY() + viewY;
76 int tabHeightInc = 0;
77 if (m_isSelected)
78 {
4b5f3fe6 79 tabHeightInc = (m_view->GetTabSelectionHeight() - m_view->GetTabHeight());
c801d85f
KB
80 tabY -= tabHeightInc;
81 }
2b854a32 82
4b5f3fe6 83 dc.SetPen(*wxTRANSPARENT_PEN);
c801d85f
KB
84
85 // Draw grey background
4b5f3fe6 86 if (m_view->GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR)
c801d85f 87 {
4b5f3fe6 88 dc.SetBrush(*m_view->GetBackgroundBrush());
c801d85f
KB
89
90 // Add 1 because the pen is transparent. Under Motif, may be different.
02800301
JS
91#ifdef __WXMOTIF__
92 dc.DrawRectangle(tabX, tabY, (GetWidth()+1), (GetHeight() + tabHeightInc));
93#else
c801d85f 94 dc.DrawRectangle(tabX, tabY, (GetWidth()+1), (GetHeight() + 1 + tabHeightInc));
02800301 95#endif
c801d85f 96 }
2b854a32 97
c801d85f 98 // Draw highlight and shadow
4b5f3fe6 99 dc.SetPen(*m_view->GetHighlightPen());
c801d85f
KB
100
101 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
102 // a bit if the tab below happens to be selected. Check.
103 wxTabControl *tabBeneath = NULL;
104 int subtractThis = 0;
105 if (GetColPosition() > 0)
106 tabBeneath = m_view->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition());
107 if (tabBeneath && tabBeneath->IsSelected())
108 subtractThis = (m_view->GetTabSelectionHeight() - m_view->GetTabHeight());
109
110 // Vertical highlight: if first tab, draw to bottom of view
111 if (tabX == m_view->GetViewRect().x && (m_view->GetTabStyle() & wxTAB_STYLE_DRAW_BOX))
112 dc.DrawLine(tabX, tabY, tabX, (m_view->GetViewRect().y + m_view->GetViewRect().height));
113 else if (tabX == m_view->GetViewRect().x)
114 // Not box drawing, just to top of view.
115 dc.DrawLine(tabX, tabY, tabX, (m_view->GetViewRect().y));
116 else
117 dc.DrawLine(tabX, tabY, tabX, (tabY + GetHeight() + tabHeightInc - subtractThis));
118
119 dc.DrawLine(tabX, tabY, (tabX + GetWidth()), tabY);
4b5f3fe6 120 dc.SetPen(*m_view->GetShadowPen());
c801d85f
KB
121
122 // Test if we're outside the right-hand edge of the view area
123 if (((tabX + GetWidth()) >= m_view->GetViewRect().x + m_view->GetViewRect().width) && (m_view->GetTabStyle() & wxTAB_STYLE_DRAW_BOX))
124 {
125 int bottomY = m_view->GetViewRect().y + m_view->GetViewRect().height + GetY() + m_view->GetTabHeight() + m_view->GetTopMargin();
126 // Add a tab height since we wish to draw to the bottom of the view.
127 dc.DrawLine((tabX + GetWidth()), tabY,
128 (tabX + GetWidth()), bottomY);
129
130 // Calculate the far-right of the view, since we don't wish to
131 // draw inside that
132 int rightOfView = m_view->GetViewRect().x + m_view->GetViewRect().width + 1;
133
134 // Draw the horizontal bit to connect to the view rectangle
135 dc.DrawLine((wxMax((tabX + GetWidth() - m_view->GetHorizontalTabOffset()), rightOfView)), (bottomY-1),
136 (tabX + GetWidth()), (bottomY-1));
137
138 // Draw black line to emphasize shadow
4b5f3fe6 139 dc.SetPen(*wxBLACK_PEN);
c801d85f
KB
140 dc.DrawLine((tabX + GetWidth() + 1), (tabY+1),
141 (tabX + GetWidth() + 1), bottomY);
142
143 // Draw the horizontal bit to connect to the view rectangle
144 dc.DrawLine((wxMax((tabX + GetWidth() - m_view->GetHorizontalTabOffset()), rightOfView)), (bottomY),
145 (tabX + GetWidth() + 1), (bottomY));
146 }
147 else
148 {
149 if (lastInRow)
150 {
151 // 25/5/97 UNLESS it's less than the max number of positions in this row
2b854a32 152
c801d85f
KB
153 int topY = m_view->GetViewRect().y - m_view->GetTopMargin();
154
1bc822df 155 int maxPositions = ((wxTabLayer *)m_view->GetLayers().Item(0)->GetData())->GetCount();
c801d85f
KB
156
157 // Only down to the bottom of the tab, not to the top of the view
4b5f3fe6 158 if ( GetRowPosition() < (maxPositions - 1) )
c801d85f
KB
159 topY = tabY + GetHeight() + tabHeightInc;
160
02800301
JS
161#ifdef __WXMOTIF__
162 topY -= 1;
163#endif
164
c801d85f
KB
165 // Shadow
166 dc.DrawLine((tabX + GetWidth()), tabY, (tabX + GetWidth()), topY);
167 // Draw black line to emphasize shadow
4b5f3fe6 168 dc.SetPen(*wxBLACK_PEN);
c801d85f
KB
169 dc.DrawLine((tabX + GetWidth() + 1), (tabY+1), (tabX + GetWidth() + 1),
170 topY);
171 }
172 else
173 {
174 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
175 // a bit if the tab below (and next col along) happens to be selected. Check.
176 wxTabControl *tabBeneath = NULL;
177 int subtractThis = 0;
178 if (GetColPosition() > 0)
179 tabBeneath = m_view->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition() + 1);
180 if (tabBeneath && tabBeneath->IsSelected())
181 subtractThis = (m_view->GetTabSelectionHeight() - m_view->GetTabHeight());
182
02800301
JS
183#ifdef __WXMOTIF__
184 subtractThis += 1;
185#endif
186
c801d85f
KB
187 // Draw only to next tab down.
188 dc.DrawLine((tabX + GetWidth()), tabY,
189 (tabX + GetWidth()), (tabY + GetHeight() + tabHeightInc - subtractThis));
190
191 // Draw black line to emphasize shadow
4b5f3fe6 192 dc.SetPen(*wxBLACK_PEN);
c801d85f
KB
193 dc.DrawLine((tabX + GetWidth() + 1), (tabY+1), (tabX + GetWidth() + 1),
194 (tabY + GetHeight() + tabHeightInc - subtractThis));
195 }
196 }
2b854a32 197
c801d85f
KB
198 // Draw centered text
199 int textY = tabY + m_view->GetVerticalTabTextSpacing() + tabHeightInc;
200
201 if (m_isSelected)
02800301 202 dc.SetFont(* m_view->GetSelectedTabFont());
c801d85f 203 else
02800301 204 dc.SetFont(* GetFont());
c801d85f
KB
205
206 wxColour col(m_view->GetTextColour());
4b5f3fe6 207 dc.SetTextForeground(col);
c801d85f 208 dc.SetBackgroundMode(wxTRANSPARENT);
4b5f3fe6 209 long textWidth, textHeight;
c801d85f
KB
210 dc.GetTextExtent(GetLabel(), &textWidth, &textHeight);
211
212 int textX = (int)(tabX + (GetWidth() - textWidth)/2.0);
7fe7d506
JS
213 if (textX < (tabX + 2))
214 textX = (tabX + 2);
215
216 dc.SetClippingRegion(tabX, tabY, GetWidth(), GetHeight());
c801d85f 217 dc.DrawText(GetLabel(), textX, textY);
7fe7d506 218 dc.DestroyClippingRegion();
c801d85f
KB
219
220 if (m_isSelected)
221 {
4b5f3fe6 222 dc.SetPen(*m_view->GetHighlightPen());
c801d85f
KB
223
224 // Draw white highlight from the tab's left side to the left hand edge of the view
225 dc.DrawLine(m_view->GetViewRect().x, (tabY + GetHeight() + tabHeightInc),
226 tabX, (tabY + GetHeight() + tabHeightInc));
227
228 // Draw white highlight from the tab's right side to the right hand edge of the view
229 dc.DrawLine((tabX + GetWidth()), (tabY + GetHeight() + tabHeightInc),
230 m_view->GetViewRect().x + m_view->GetViewRect().width, (tabY + GetHeight() + tabHeightInc));
231 }
4b5f3fe6
JS
232#else
233 // New HEL version with rounder tabs
c801d85f 234
2b854a32
VZ
235 if (!m_view) return;
236
237 int tabInc = 0;
238 if (m_isSelected)
239 {
240 tabInc = m_view->GetTabSelectionHeight() - m_view->GetTabHeight();
241 }
242 int tabLeft = GetX() + m_view->GetViewRect().x;
243 int tabTop = GetY() + m_view->GetViewRect().y - tabInc;
244 int tabRight = tabLeft + m_view->GetTabWidth();
245 int left = m_view->GetViewRect().x;
246 int top = tabTop + m_view->GetTabHeight() + tabInc;
247 int right = left + m_view->GetViewRect().width;
248 int bottom = top + m_view->GetViewRect().height;
249
250 if (m_isSelected)
251 {
252 // TAB is selected - draw TAB and the View's full outline
253
254 dc.SetPen(*(m_view->GetHighlightPen()));
255 wxPoint pnts[10];
256 int n = 0;
257 pnts[n].x = left; pnts[n++].y = bottom;
258 pnts[n].x = left; pnts[n++].y = top;
259 pnts[n].x = tabLeft; pnts[n++].y = top;
260 pnts[n].x = tabLeft; pnts[n++].y = tabTop + 2;
261 pnts[n].x = tabLeft + 2; pnts[n++].y = tabTop;
262 pnts[n].x = tabRight - 1; pnts[n++].y = tabTop;
263 dc.DrawLines(n, pnts);
264 if (!lastInRow)
265 {
266 dc.DrawLine(
267 (tabRight + 2),
268 top,
269 right,
270 top
271 );
272 }
273
274 dc.SetPen(*(m_view->GetShadowPen()));
275 dc.DrawLine(
276 tabRight,
277 tabTop + 2,
278 tabRight,
279 top
280 );
281 dc.DrawLine(
282 right,
283 top,
284 right,
285 bottom
286 );
287 dc.DrawLine(
288 right,
289 bottom,
290 left,
291 bottom
292 );
293
294 dc.SetPen(*wxBLACK_PEN);
295 dc.DrawPoint(
296 tabRight,
297 tabTop + 1
298 );
299 dc.DrawPoint(
300 tabRight + 1,
301 tabTop + 2
302 );
303 if (lastInRow)
304 {
305 dc.DrawLine(
306 tabRight + 1,
307 bottom,
308 tabRight + 1,
309 tabTop + 1
310 );
311 }
312 else
313 {
314 dc.DrawLine(
315 tabRight + 1,
316 tabTop + 2,
317 tabRight + 1,
318 top
319 );
320 dc.DrawLine(
321 right + 1,
322 top,
323 right + 1,
324 bottom + 1
325 );
326 }
327 dc.DrawLine(
328 right + 1,
329 bottom + 1,
330 left + 1,
331 bottom + 1
332 );
333 }
334 else
335 {
336 // TAB is not selected - just draw TAB outline and RH edge
337 // if the TAB is the last in the row
338
1bc822df 339 int maxPositions = ((wxTabLayer*)m_view->GetLayers().Item(0)->GetData())->GetCount();
2b854a32
VZ
340 wxTabControl* tabBelow = 0;
341 wxTabControl* tabBelowRight = 0;
342 if (GetColPosition() > 0)
343 {
344 tabBelow = m_view->FindTabControlForPosition(
345 GetColPosition() - 1,
346 GetRowPosition()
347 );
348 }
349 if (!lastInRow && GetColPosition() > 0)
350 {
351 tabBelowRight = m_view->FindTabControlForPosition(
352 GetColPosition() - 1,
353 GetRowPosition() + 1
354 );
355 }
356
357 float raisedTop = top - m_view->GetTabSelectionHeight() +
358 m_view->GetTabHeight();
359
360 dc.SetPen(*(m_view->GetHighlightPen()));
361 wxPoint pnts[10];
362 int n = 0;
363
364 pnts[n].x = tabLeft;
365
366 if (tabBelow && tabBelow->IsSelected())
367 {
368 pnts[n++].y = (long)raisedTop;
369 }
370 else
371 {
372 pnts[n++].y = top;
373 }
374 pnts[n].x = tabLeft; pnts[n++].y = tabTop + 2;
375 pnts[n].x = tabLeft + 2; pnts[n++].y = tabTop;
376 pnts[n].x = tabRight - 1; pnts[n++].y = tabTop;
377 dc.DrawLines(n, pnts);
378
379 dc.SetPen(*(m_view->GetShadowPen()));
380 if (GetRowPosition() >= maxPositions - 1)
381 {
382 dc.DrawLine(
383 tabRight,
384 (tabTop + 2),
385 tabRight,
386 bottom
387 );
388 dc.DrawLine(
389 tabRight,
390 bottom,
391 (tabRight - m_view->GetHorizontalTabOffset()),
392 bottom
393 );
394 }
395 else
396 {
397 if (tabBelowRight && tabBelowRight->IsSelected())
398 {
399 dc.DrawLine(
400 tabRight,
401 (long)raisedTop,
402 tabRight,
403 tabTop + 1
404 );
405 }
406 else
407 {
408 dc.DrawLine(
409 tabRight,
410 top - 1,
411 tabRight,
412 tabTop + 1
413 );
414 }
415 }
416
417 dc.SetPen(*wxBLACK_PEN);
418 dc.DrawPoint(
419 tabRight,
420 tabTop + 1
421 );
422 dc.DrawPoint(
423 tabRight + 1,
424 tabTop + 2
425 );
426 if (GetRowPosition() >= maxPositions - 1)
427 {
428 // draw right hand edge to bottom of view
429 dc.DrawLine(
430 tabRight + 1,
431 bottom + 1,
432 tabRight + 1,
433 tabTop + 2
434 );
435 dc.DrawLine(
436 tabRight + 1,
437 bottom + 1,
438 (tabRight - m_view->GetHorizontalTabOffset()),
439 bottom + 1
440 );
441 }
442 else
443 {
444 // draw right hand edge of TAB
445 if (tabBelowRight && tabBelowRight->IsSelected())
446 {
447 dc.DrawLine(
448 tabRight + 1,
449 (long)(raisedTop - 1),
450 tabRight + 1,
451 tabTop + 2
452 );
453 }
454 else
455 {
456 dc.DrawLine(
457 tabRight + 1,
458 top - 1,
459 tabRight + 1,
460 tabTop + 2
461 );
462 }
463 }
464 }
465
466 // Draw centered text
467 dc.SetPen(*wxBLACK_PEN);
468 if (m_isSelected)
469 {
470 dc.SetFont(*(m_view->GetSelectedTabFont()));
471 }
472 else
473 {
474 dc.SetFont(*(GetFont()));
475 }
476
477 wxColour col(m_view->GetTextColour());
478 dc.SetTextForeground(col);
479 dc.SetBackgroundMode(wxTRANSPARENT);
480 long textWidth, textHeight;
481 dc.GetTextExtent(GetLabel(), &textWidth, &textHeight);
482
483 float textX = (tabLeft + tabRight - textWidth) / 2;
484 float textY = (tabInc + tabTop + m_view->GetVerticalTabTextSpacing());
485
486 dc.DrawText(GetLabel(), (long)textX, (long)textY);
c801d85f
KB
487#endif
488}
489
490bool wxTabControl::HitTest(int x, int y) const
491{
492 // Top-left of tab control
493 int tabX1 = GetX() + m_view->GetViewRect().x;
494 int tabY1 = GetY() + m_view->GetViewRect().y;
495
496 // Bottom-right
497 int tabX2 = tabX1 + GetWidth();
498 int tabY2 = tabY1 + GetHeight();
2b854a32 499
c801d85f 500 if (x >= tabX1 && y >= tabY1 && x <= tabX2 && y <= tabY2)
ca65c044 501 return true;
c801d85f 502 else
ca65c044 503 return false;
c801d85f
KB
504}
505
506IMPLEMENT_DYNAMIC_CLASS(wxTabView, wxObject)
507
508wxTabView::wxTabView(long style)
509{
510 m_noTabs = 0;
511 m_tabStyle = style;
512 m_tabSelection = -1;
513 m_tabHeight = 20;
514 m_tabSelectionHeight = m_tabHeight + 2;
515 m_tabWidth = 80;
516 m_tabHorizontalOffset = 10;
517 m_tabHorizontalSpacing = 2;
518 m_tabVerticalTextSpacing = 3;
519 m_topMargin = 5;
520 m_tabViewRect.x = 20;
521 m_tabViewRect.y = 20;
522 m_tabViewRect.width = 300;
523 m_tabViewRect.x = 300;
524 m_highlightColour = *wxWHITE;
525 m_shadowColour = wxColour(128, 128, 128);
836dded8 526 m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
c801d85f
KB
527 m_textColour = *wxBLACK;
528 m_highlightPen = wxWHITE_PEN;
529 m_shadowPen = wxGREY_PEN;
836dded8 530 SetBackgroundColour(m_backgroundColour);
a756f210
VS
531 m_tabFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
532 m_tabSelectedFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
c67daf87 533 m_window = (wxWindow *) NULL;
c801d85f
KB
534}
535
536wxTabView::~wxTabView()
537{
ca65c044 538 ClearTabs(true);
c801d85f 539}
2b854a32 540
c801d85f 541// Automatically positions tabs
4b5f3fe6
JS
542// TODO: this should just add the tab to a list, and then
543// a layout function (e.g. Realize) should be called when all tabs have been added.
544// The view rect could easily change as the view window is resized.
c801d85f
KB
545wxTabControl *wxTabView::AddTab(int id, const wxString& label, wxTabControl *existingTab)
546{
547 // First, find which layer we should be adding to.
4410d619 548 wxTabLayerList::compatibility_iterator node = m_layers.GetLast();
c801d85f
KB
549 if (!node)
550 {
551 wxTabLayer *newLayer = new wxTabLayer;
552 node = m_layers.Append(newLayer);
553 }
554 // Check if adding another tab control would go off the
555 // right-hand edge of the layer.
1bc822df 556 wxTabLayer *tabLayer = (wxTabLayer *)node->GetData();
4410d619 557 wxList::compatibility_iterator lastTabNode = tabLayer->GetLast();
c801d85f
KB
558 if (lastTabNode)
559 {
1bc822df 560 wxTabControl *lastTab = (wxTabControl *)lastTabNode->GetData();
c801d85f
KB
561 // Start another layer (row).
562 // Tricky choice: can't just check if will be overlapping the edge, because
563 // this happens anyway for 2nd and subsequent rows.
564 // Should check this for 1st row, and then subsequent rows should not exceed 1st
565 // in length.
1bc822df 566 if (((tabLayer == m_layers.GetFirst()->GetData()) && ((lastTab->GetX() + 2*lastTab->GetWidth() + GetHorizontalTabSpacing())
c801d85f 567 > GetViewRect().width)) ||
1bc822df 568 ((tabLayer != m_layers.GetFirst()->GetData()) && (tabLayer->GetCount() == ((wxTabLayer *)m_layers.GetFirst()->GetData())->GetCount())))
c801d85f
KB
569 {
570 tabLayer = new wxTabLayer;
571 m_layers.Append(tabLayer);
4410d619 572 lastTabNode = wxList::compatibility_iterator();
c801d85f
KB
573 }
574 }
1bc822df 575 int layer = m_layers.GetCount() - 1;
2b854a32 576
c801d85f
KB
577 wxTabControl *tabControl = existingTab;
578 if (!existingTab)
579 tabControl = OnCreateTabControl();
1bc822df 580 tabControl->SetRowPosition(tabLayer->GetCount());
c801d85f 581 tabControl->SetColPosition(layer);
2b854a32 582
c67daf87 583 wxTabControl *lastTab = (wxTabControl *) NULL;
c801d85f 584 if (lastTabNode)
1bc822df 585 lastTab = (wxTabControl *)lastTabNode->GetData();
2b854a32 586
c801d85f
KB
587 // Top of new tab
588 int verticalOffset = (- GetTopMargin()) - ((layer+1)*GetTabHeight());
589 // Offset from view top-left
590 int horizontalOffset = 0;
591 if (!lastTab)
592 horizontalOffset = layer*GetHorizontalTabOffset();
593 else
594 horizontalOffset = lastTab->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
2b854a32 595
c801d85f
KB
596 tabControl->SetPosition(horizontalOffset, verticalOffset);
597 tabControl->SetSize(GetTabWidth(), GetTabHeight());
598 tabControl->SetId(id);
599 tabControl->SetLabel(label);
02800301 600 tabControl->SetFont(* GetTabFont());
2b854a32 601
c801d85f
KB
602 tabLayer->Append(tabControl);
603 m_noTabs ++;
2b854a32 604
c801d85f
KB
605 return tabControl;
606}
621793f4
JS
607
608// Remove the tab without deleting the window
609bool wxTabView::RemoveTab(int id)
610{
4410d619 611 wxTabLayerList::compatibility_iterator layerNode = m_layers.GetFirst();
621793f4
JS
612 while (layerNode)
613 {
1bc822df 614 wxTabLayer *layer = (wxTabLayer *)layerNode->GetData();
4410d619 615 wxList::compatibility_iterator tabNode = layer->GetFirst();
621793f4
JS
616 while (tabNode)
617 {
1bc822df 618 wxTabControl *tab = (wxTabControl *)tabNode->GetData();
621793f4
JS
619 if (tab->GetId() == id)
620 {
621 if (id == m_tabSelection)
622 m_tabSelection = -1;
623 delete tab;
4410d619 624 layer->Erase(tabNode);
7fe7d506 625 m_noTabs --;
621793f4
JS
626
627 // The layout has changed
f03fc89f 628 LayoutTabs();
ca65c044 629 return true;
621793f4 630 }
1bc822df 631 tabNode = tabNode->GetNext();
621793f4 632 }
1bc822df 633 layerNode = layerNode->GetNext();
621793f4 634 }
ca65c044 635 return false;
621793f4 636}
7fe7d506
JS
637
638bool wxTabView::SetTabText(int id, const wxString& label)
639{
640 wxTabControl* control = FindTabControlForId(id);
641 if (!control)
ca65c044 642 return false;
7fe7d506 643 control->SetLabel(label);
ca65c044 644 return true;
7fe7d506
JS
645}
646
647wxString wxTabView::GetTabText(int id) const
648{
649 wxTabControl* control = FindTabControlForId(id);
650 if (!control)
651 return wxEmptyString;
652 else
653 return control->GetLabel();
654}
2b854a32 655
4b5f3fe6
JS
656// Returns the total height of the tabs component -- this may be several
657// times the height of a tab, if there are several tab layers (rows).
658int wxTabView::GetTotalTabHeight()
659{
660 int minY = 0;
661
4410d619 662 wxTabLayerList::compatibility_iterator layerNode = m_layers.GetFirst();
4b5f3fe6
JS
663 while (layerNode)
664 {
1bc822df 665 wxTabLayer *layer = (wxTabLayer *)layerNode->GetData();
4410d619 666 wxList::compatibility_iterator tabNode = layer->GetFirst();
4b5f3fe6
JS
667 while (tabNode)
668 {
1bc822df 669 wxTabControl *tab = (wxTabControl *)tabNode->GetData();
4b5f3fe6
JS
670
671 if (tab->GetY() < minY)
672 minY = tab->GetY();
673
1bc822df 674 tabNode = tabNode->GetNext();
4b5f3fe6 675 }
1bc822df 676 layerNode = layerNode->GetNext();
4b5f3fe6
JS
677 }
678
679 return - minY;
680}
681
c801d85f
KB
682void wxTabView::ClearTabs(bool deleteTabs)
683{
4410d619 684 wxTabLayerList::compatibility_iterator layerNode = m_layers.GetFirst();
c801d85f
KB
685 while (layerNode)
686 {
1bc822df 687 wxTabLayer *layer = (wxTabLayer *)layerNode->GetData();
4410d619 688 wxList::compatibility_iterator tabNode = layer->GetFirst();
c801d85f
KB
689 while (tabNode)
690 {
1bc822df 691 wxTabControl *tab = (wxTabControl *)tabNode->GetData();
c801d85f
KB
692 if (deleteTabs)
693 delete tab;
4410d619
MB
694 wxList::compatibility_iterator next = tabNode->GetNext();
695 layer->Erase(tabNode);
c801d85f
KB
696 tabNode = next;
697 }
4410d619 698 wxTabLayerList::compatibility_iterator nextLayerNode = layerNode->GetNext();
c801d85f 699 delete layer;
4410d619 700 m_layers.Erase(layerNode);
c801d85f
KB
701 layerNode = nextLayerNode;
702 }
7fe7d506 703 m_noTabs = 0;
51babd09 704 m_tabSelection = -1;
c801d85f 705}
4b5f3fe6
JS
706
707
c801d85f 708// Layout tabs (optional, e.g. if resizing window)
f03fc89f 709void wxTabView::LayoutTabs(void)
c801d85f
KB
710{
711 // Make a list of the tab controls, deleting the wxTabLayers.
712 wxList controls;
713
4410d619 714 wxTabLayerList::compatibility_iterator layerNode = m_layers.GetFirst();
c801d85f
KB
715 while (layerNode)
716 {
1bc822df 717 wxTabLayer *layer = (wxTabLayer *)layerNode->GetData();
4410d619 718 wxList::compatibility_iterator tabNode = layer->GetFirst();
c801d85f
KB
719 while (tabNode)
720 {
1bc822df 721 wxTabControl *tab = (wxTabControl *)tabNode->GetData();
c801d85f 722 controls.Append(tab);
4410d619
MB
723 wxList::compatibility_iterator next = tabNode->GetNext();
724 layer->Erase(tabNode);
c801d85f
KB
725 tabNode = next;
726 }
4410d619 727 wxTabLayerList::compatibility_iterator nextLayerNode = layerNode->GetNext();
c801d85f 728 delete layer;
4410d619 729 m_layers.Erase(layerNode);
c801d85f
KB
730 layerNode = nextLayerNode;
731 }
2b854a32 732
c67daf87 733 wxTabControl *lastTab = (wxTabControl *) NULL;
2b854a32 734
c801d85f
KB
735 wxTabLayer *currentLayer = new wxTabLayer;
736 m_layers.Append(currentLayer);
2b854a32 737
4410d619 738 wxList::compatibility_iterator node = controls.GetFirst();
c801d85f
KB
739 while (node)
740 {
1bc822df 741 wxTabControl *tabControl = (wxTabControl *)node->GetData();
c801d85f
KB
742 if (lastTab)
743 {
744 // Start another layer (row).
745 // Tricky choice: can't just check if will be overlapping the edge, because
746 // this happens anyway for 2nd and subsequent rows.
747 // Should check this for 1st row, and then subsequent rows should not exceed 1st
748 // in length.
1bc822df 749 if (((currentLayer == m_layers.GetFirst()->GetData()) && ((lastTab->GetX() + 2*lastTab->GetWidth() + GetHorizontalTabSpacing())
c801d85f 750 > GetViewRect().width)) ||
1bc822df 751 ((currentLayer != m_layers.GetFirst()->GetData()) && (currentLayer->GetCount() == ((wxTabLayer *)m_layers.GetFirst()->GetData())->GetCount())))
c801d85f
KB
752 {
753 currentLayer = new wxTabLayer;
754 m_layers.Append(currentLayer);
c67daf87 755 lastTab = (wxTabControl *) NULL;
c801d85f
KB
756 }
757 }
2b854a32 758
1bc822df 759 int layer = m_layers.GetCount() - 1;
c801d85f 760
1bc822df 761 tabControl->SetRowPosition(currentLayer->GetCount());
c801d85f 762 tabControl->SetColPosition(layer);
2b854a32 763
c801d85f
KB
764 // Top of new tab
765 int verticalOffset = (- GetTopMargin()) - ((layer+1)*GetTabHeight());
766 // Offset from view top-left
767 int horizontalOffset = 0;
768 if (!lastTab)
769 horizontalOffset = layer*GetHorizontalTabOffset();
770 else
771 horizontalOffset = lastTab->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
2b854a32 772
c801d85f
KB
773 tabControl->SetPosition(horizontalOffset, verticalOffset);
774 tabControl->SetSize(GetTabWidth(), GetTabHeight());
775
776 currentLayer->Append(tabControl);
777 lastTab = tabControl;
778
1bc822df 779 node = node->GetNext();
c801d85f
KB
780 }
781
782 // Move the selected tab to the bottom
783 wxTabControl *control = FindTabControlForId(m_tabSelection);
784 if (control)
785 MoveSelectionTab(control);
786
787}
788
789// Draw all tabs
790void wxTabView::Draw(wxDC& dc)
791{
7fe7d506
JS
792 // Don't draw anything if there are no tabs.
793 if (GetNumberOfTabs() == 0)
794 return;
795
2b854a32
VZ
796 // Draw top margin area (beneath tabs and above view area)
797 if (GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR)
798 {
799 dc.SetPen(*wxTRANSPARENT_PEN);
800 dc.SetBrush(*GetBackgroundBrush());
801
802 // Add 1 because the pen is transparent. Under Motif, may be different.
803 dc.DrawRectangle(
804 m_tabViewRect.x,
805 (m_tabViewRect.y - m_topMargin),
806 (m_tabViewRect.width + 1),
807 (m_topMargin + 1)
808 );
809 }
810
811 // Draw layers in reverse order
4410d619 812 wxTabLayerList::compatibility_iterator node = m_layers.GetLast();
2b854a32
VZ
813 while (node)
814 {
1bc822df 815 wxTabLayer *layer = (wxTabLayer *)node->GetData();
4410d619 816 wxList::compatibility_iterator node2 = layer->GetFirst();
2b854a32
VZ
817 while (node2)
818 {
1bc822df 819 wxTabControl *control = (wxTabControl *)node2->GetData();
4410d619 820 control->OnDraw(dc, (!node2->GetNext()));
1bc822df 821 node2 = node2->GetNext();
2b854a32
VZ
822 }
823
1bc822df 824 node = node->GetPrevious();
2b854a32 825 }
c801d85f
KB
826
827
4b5f3fe6 828#ifndef wxUSE_NEW_METHOD
2b854a32
VZ
829 if (GetTabStyle() & wxTAB_STYLE_DRAW_BOX)
830 {
831 dc.SetPen(* GetShadowPen());
832
833 // Draw bottom line
834 dc.DrawLine(
835 (GetViewRect().x + 1),
836 (GetViewRect().y + GetViewRect().height),
837 (GetViewRect().x + GetViewRect().width + 1),
838 (GetViewRect().y + GetViewRect().height)
839 );
840
841 // Draw right line
842 dc.DrawLine(
843 (GetViewRect().x + GetViewRect().width),
844 (GetViewRect().y - GetTopMargin() + 1),
845 (GetViewRect().x + GetViewRect().width),
846 (GetViewRect().y + GetViewRect().height)
847 );
848
849 dc.SetPen(* wxBLACK_PEN);
850
851 // Draw bottom line
852 dc.DrawLine(
853 (GetViewRect().x),
854 (GetViewRect().y + GetViewRect().height + 1),
02800301 855#if defined(__WXMOTIF__)
2b854a32 856 (GetViewRect().x + GetViewRect().width + 1),
02800301 857#else
2b854a32 858 (GetViewRect().x + GetViewRect().width + 2),
02800301
JS
859#endif
860
2b854a32
VZ
861 (GetViewRect().y + GetViewRect().height + 1)
862 );
863
864 // Draw right line
865 dc.DrawLine(
866 (GetViewRect().x + GetViewRect().width + 1),
867 (GetViewRect().y - GetTopMargin()),
868 (GetViewRect().x + GetViewRect().width + 1),
869 (GetViewRect().y + GetViewRect().height + 1)
870 );
871 }
c801d85f
KB
872#endif
873}
2b854a32 874
ca65c044 875// Process mouse event, return false if we didn't process it
c801d85f
KB
876bool wxTabView::OnEvent(wxMouseEvent& event)
877{
878 if (!event.LeftDown())
ca65c044 879 return false;
2b854a32 880
e6575209
VZ
881 wxCoord x, y;
882 event.GetPosition(&x, &y);
2b854a32 883
c67daf87 884 wxTabControl *hitControl = (wxTabControl *) NULL;
2b854a32 885
4410d619 886 wxTabLayerList::compatibility_iterator node = m_layers.GetFirst();
c801d85f
KB
887 while (node)
888 {
1bc822df 889 wxTabLayer *layer = (wxTabLayer *)node->GetData();
4410d619 890 wxList::compatibility_iterator node2 = layer->GetFirst();
c801d85f
KB
891 while (node2)
892 {
1bc822df 893 wxTabControl *control = (wxTabControl *)node2->GetData();
c801d85f
KB
894 if (control->HitTest((int)x, (int)y))
895 {
896 hitControl = control;
4410d619
MB
897 node = wxTabLayerList::compatibility_iterator();
898 node2 = wxList::compatibility_iterator();
c801d85f
KB
899 }
900 else
1bc822df 901 node2 = node2->GetNext();
c801d85f 902 }
2b854a32 903
c801d85f 904 if (node)
1bc822df 905 node = node->GetNext();
c801d85f 906 }
2b854a32 907
c801d85f 908 if (!hitControl)
ca65c044 909 return false;
2b854a32 910
c801d85f 911 wxTabControl *currentTab = FindTabControlForId(m_tabSelection);
2b854a32 912
c801d85f 913 if (hitControl == currentTab)
ca65c044 914 return false;
2b854a32 915
c801d85f 916 ChangeTab(hitControl);
2b854a32 917
ca65c044 918 return true;
c801d85f
KB
919}
920
921bool wxTabView::ChangeTab(wxTabControl *control)
922{
923 wxTabControl *currentTab = FindTabControlForId(m_tabSelection);
924 int oldTab = -1;
925 if (currentTab)
926 oldTab = currentTab->GetId();
2b854a32 927
c801d85f 928 if (control == currentTab)
ca65c044 929 return true;
2b854a32 930
1bc822df 931 if (m_layers.GetCount() == 0)
ca65c044 932 return false;
2b854a32 933
c801d85f 934 if (!OnTabPreActivate(control->GetId(), oldTab))
ca65c044 935 return false;
c801d85f
KB
936
937 // Move the tab to the bottom
938 MoveSelectionTab(control);
939
940 if (currentTab)
ca65c044 941 currentTab->SetSelected(false);
2b854a32 942
ca65c044 943 control->SetSelected(true);
c801d85f
KB
944 m_tabSelection = control->GetId();
945
946 OnTabActivate(control->GetId(), oldTab);
2b854a32 947
c801d85f
KB
948 // Leave window refresh for the implementing window
949
ca65c044 950 return true;
c801d85f
KB
951}
952
953// Move the selected tab to the bottom layer, if necessary,
954// without calling app activation code
955bool wxTabView::MoveSelectionTab(wxTabControl *control)
956{
1bc822df 957 if (m_layers.GetCount() == 0)
ca65c044 958 return false;
2b854a32 959
1bc822df 960 wxTabLayer *firstLayer = (wxTabLayer *)m_layers.GetFirst()->GetData();
2b854a32 961
c801d85f
KB
962 // Find what column this tab is at, so we can swap with the one at the bottom.
963 // If we're on the bottom layer, then no need to swap.
964 if (!firstLayer->Member(control))
965 {
966 // Do a swap
967 int col = 0;
4410d619 968 wxList::compatibility_iterator thisNode = FindTabNodeAndColumn(control, &col);
c801d85f 969 if (!thisNode)
ca65c044 970 return false;
4410d619 971 wxList::compatibility_iterator otherNode = firstLayer->Item(col);
c801d85f 972 if (!otherNode)
ca65c044 973 return false;
2b854a32 974
c801d85f
KB
975 // If this is already in the bottom layer, return now
976 if (otherNode == thisNode)
ca65c044 977 return true;
2b854a32 978
1bc822df 979 wxTabControl *otherTab = (wxTabControl *)otherNode->GetData();
2b854a32 980
c801d85f
KB
981 // We now have pointers to the tab to be changed to,
982 // and the tab on the first layer. Swap tab structures and
983 // position details.
2b854a32 984
c801d85f
KB
985 int thisX = control->GetX();
986 int thisY = control->GetY();
987 int thisColPos = control->GetColPosition();
988 int otherX = otherTab->GetX();
989 int otherY = otherTab->GetY();
990 int otherColPos = otherTab->GetColPosition();
2b854a32 991
c801d85f
KB
992 control->SetPosition(otherX, otherY);
993 control->SetColPosition(otherColPos);
994 otherTab->SetPosition(thisX, thisY);
995 otherTab->SetColPosition(thisColPos);
2b854a32 996
c801d85f
KB
997 // Swap the data for the nodes
998 thisNode->SetData(otherTab);
999 otherNode->SetData(control);
1000 }
ca65c044 1001 return true;
c801d85f
KB
1002}
1003
1004// Called when a tab is activated
1005void wxTabView::OnTabActivate(int /*activateId*/, int /*deactivateId*/)
1006{
1007}
2b854a32 1008
c801d85f
KB
1009void wxTabView::SetHighlightColour(const wxColour& col)
1010{
1011 m_highlightColour = col;
1012 m_highlightPen = wxThePenList->FindOrCreatePen(col, 1, wxSOLID);
1013}
1014
1015void wxTabView::SetShadowColour(const wxColour& col)
1016{
1017 m_shadowColour = col;
1018 m_shadowPen = wxThePenList->FindOrCreatePen(col, 1, wxSOLID);
1019}
1020
1021void wxTabView::SetBackgroundColour(const wxColour& col)
1022{
1023 m_backgroundColour = col;
1024 m_backgroundPen = wxThePenList->FindOrCreatePen(col, 1, wxSOLID);
1025 m_backgroundBrush = wxTheBrushList->FindOrCreateBrush(col, wxSOLID);
1026}
1027
966b84b9
CE
1028// this may be called with sel = zero (which doesn't match any page)
1029// when wxMotif deletes a page
1030// so return the first tab...
1031
c801d85f
KB
1032void wxTabView::SetTabSelection(int sel, bool activateTool)
1033{
51babd09
JS
1034 if ( sel==m_tabSelection )
1035 return;
1036
c801d85f
KB
1037 int oldSel = m_tabSelection;
1038 wxTabControl *control = FindTabControlForId(sel);
966b84b9 1039 if (sel == 0) sel=control->GetId();
621793f4 1040 wxTabControl *oldControl = FindTabControlForId(m_tabSelection);
c801d85f
KB
1041
1042 if (!OnTabPreActivate(sel, oldSel))
1043 return;
2b854a32 1044
c801d85f 1045 if (control)
621793f4
JS
1046 control->SetSelected((sel != -1)); // TODO ??
1047 else if (sel != -1)
c801d85f 1048 {
621793f4 1049 wxFAIL_MSG(_("Could not find tab for id"));
c801d85f
KB
1050 return;
1051 }
621793f4
JS
1052
1053 if (oldControl)
ca65c044 1054 oldControl->SetSelected(false);
2b854a32 1055
c801d85f 1056 m_tabSelection = sel;
621793f4
JS
1057
1058 if (control)
1059 MoveSelectionTab(control);
2b854a32 1060
c801d85f
KB
1061 if (activateTool)
1062 OnTabActivate(sel, oldSel);
1063}
1064
1065// Find tab control for id
966b84b9
CE
1066// this may be called with zero (which doesn't match any page)
1067// so return the first control...
c801d85f
KB
1068wxTabControl *wxTabView::FindTabControlForId(int id) const
1069{
4410d619 1070 wxTabLayerList::compatibility_iterator node1 = m_layers.GetFirst();
c801d85f
KB
1071 while (node1)
1072 {
1bc822df 1073 wxTabLayer *layer = (wxTabLayer *)node1->GetData();
4410d619 1074 wxList::compatibility_iterator node2 = layer->GetFirst();
c801d85f
KB
1075 while (node2)
1076 {
1bc822df 1077 wxTabControl *control = (wxTabControl *)node2->GetData();
966b84b9 1078 if (control->GetId() == id || id == 0)
c801d85f 1079 return control;
1bc822df 1080 node2 = node2->GetNext();
c801d85f 1081 }
1bc822df 1082 node1 = node1->GetNext();
c801d85f 1083 }
c67daf87 1084 return (wxTabControl *) NULL;
c801d85f
KB
1085}
1086
1087// Find tab control for layer, position (starting from zero)
1088wxTabControl *wxTabView::FindTabControlForPosition(int layer, int position) const
1089{
4410d619 1090 wxTabLayerList::compatibility_iterator node1 = m_layers.Item(layer);
c801d85f 1091 if (!node1)
c67daf87 1092 return (wxTabControl *) NULL;
1bc822df 1093 wxTabLayer *tabLayer = (wxTabLayer *)node1->GetData();
4410d619 1094 wxList::compatibility_iterator node2 = tabLayer->Item(position);
c801d85f 1095 if (!node2)
c67daf87 1096 return (wxTabControl *) NULL;
1bc822df 1097 return (wxTabControl *)node2->GetData();
c801d85f
KB
1098}
1099
1100// Find the node and the column at which this control is positioned.
4410d619 1101wxList::compatibility_iterator wxTabView::FindTabNodeAndColumn(wxTabControl *control, int *col) const
c801d85f 1102{
4410d619 1103 wxTabLayerList::compatibility_iterator node1 = m_layers.GetFirst();
c801d85f
KB
1104 while (node1)
1105 {
1bc822df 1106 wxTabLayer *layer = (wxTabLayer *)node1->GetData();
c801d85f 1107 int c = 0;
4410d619 1108 wxList::compatibility_iterator node2 = layer->GetFirst();
c801d85f
KB
1109 while (node2)
1110 {
1bc822df 1111 wxTabControl *cnt = (wxTabControl *)node2->GetData();
c801d85f
KB
1112 if (cnt == control)
1113 {
1114 *col = c;
1115 return node2;
1116 }
1bc822df 1117 node2 = node2->GetNext();
c801d85f
KB
1118 c ++;
1119 }
1bc822df 1120 node1 = node1->GetNext();
c801d85f 1121 }
4410d619 1122 return wxList::compatibility_iterator();
c801d85f
KB
1123}
1124
1125int wxTabView::CalculateTabWidth(int noTabs, bool adjustView)
1126{
1127 m_tabWidth = (int)((m_tabViewRect.width - ((noTabs - 1)*GetHorizontalTabSpacing()))/noTabs);
1128 if (adjustView)
1129 {
1130 m_tabViewRect.width = noTabs*m_tabWidth + ((noTabs-1)*GetHorizontalTabSpacing());
1131 }
1132 return m_tabWidth;
1133}
1134
1135/*
1136 * wxTabbedDialog
1137 */
2b854a32 1138
c801d85f
KB
1139IMPLEMENT_CLASS(wxTabbedDialog, wxDialog)
1140
1141BEGIN_EVENT_TABLE(wxTabbedDialog, wxDialog)
1142 EVT_CLOSE(wxTabbedDialog::OnCloseWindow)
1143 EVT_MOUSE_EVENTS(wxTabbedDialog::OnMouseEvent)
1144 EVT_PAINT(wxTabbedDialog::OnPaint)
1145END_EVENT_TABLE()
1146
debe6624 1147wxTabbedDialog::wxTabbedDialog(wxWindow *parent, wxWindowID id,
c801d85f
KB
1148 const wxString& title,
1149 const wxPoint& pos, const wxSize& size,
debe6624 1150 long windowStyle, const wxString& name):
c801d85f
KB
1151 wxDialog(parent, id, title, pos, size, windowStyle, name)
1152{
c67daf87 1153 m_tabView = (wxTabView *) NULL;
c801d85f
KB
1154}
1155
1156wxTabbedDialog::~wxTabbedDialog(void)
1157{
1158 if (m_tabView)
1159 delete m_tabView;
1160}
2b854a32 1161
c801d85f
KB
1162void wxTabbedDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event) )
1163{
1164 Destroy();
1165}
1166
1167void wxTabbedDialog::OnMouseEvent(wxMouseEvent& event )
1168{
1169 if (m_tabView)
1170 m_tabView->OnEvent(event);
1171}
1172
1173void wxTabbedDialog::OnPaint(wxPaintEvent& WXUNUSED(event) )
1174{
1175 wxPaintDC dc(this);
1176 if (m_tabView)
1177 m_tabView->Draw(dc);
1178}
1179
1180/*
1181 * wxTabbedPanel
1182 */
2b854a32 1183
c801d85f
KB
1184IMPLEMENT_CLASS(wxTabbedPanel, wxPanel)
1185
1186BEGIN_EVENT_TABLE(wxTabbedPanel, wxPanel)
1187 EVT_MOUSE_EVENTS(wxTabbedPanel::OnMouseEvent)
1188 EVT_PAINT(wxTabbedPanel::OnPaint)
1189END_EVENT_TABLE()
1190
debe6624
JS
1191wxTabbedPanel::wxTabbedPanel(wxWindow *parent, wxWindowID id, const wxPoint& pos,
1192 const wxSize& size, long windowStyle, const wxString& name):
c801d85f
KB
1193 wxPanel(parent, id, pos, size, windowStyle, name)
1194{
c67daf87 1195 m_tabView = (wxTabView *) NULL;
c801d85f
KB
1196}
1197
1198wxTabbedPanel::~wxTabbedPanel(void)
1199{
1200 delete m_tabView;
1201}
2b854a32 1202
c801d85f
KB
1203void wxTabbedPanel::OnMouseEvent(wxMouseEvent& event)
1204{
1205 if (m_tabView)
1206 m_tabView->OnEvent(event);
1207}
1208
1209void wxTabbedPanel::OnPaint(wxPaintEvent& WXUNUSED(event) )
1210{
1211 wxPaintDC dc(this);
1212 if (m_tabView)
1213 m_tabView->Draw(dc);
1214}
1215
1216/*
4b5f3fe6 1217 * wxPanelTabView
c801d85f 1218 */
2b854a32 1219
c801d85f 1220IMPLEMENT_CLASS(wxPanelTabView, wxTabView)
2b854a32 1221
4410d619
MB
1222wxPanelTabView::wxPanelTabView(wxPanel *pan, long style)
1223 : wxTabView(style)
c801d85f
KB
1224{
1225 m_panel = pan;
c67daf87 1226 m_currentWindow = (wxWindow *) NULL;
c801d85f
KB
1227
1228 if (m_panel->IsKindOf(CLASSINFO(wxTabbedDialog)))
1229 ((wxTabbedDialog *)m_panel)->SetTabView(this);
1230 else if (m_panel->IsKindOf(CLASSINFO(wxTabbedPanel)))
1231 ((wxTabbedPanel *)m_panel)->SetTabView(this);
1232
1233 SetWindow(m_panel);
1234}
1235
1236wxPanelTabView::~wxPanelTabView(void)
1237{
ca65c044 1238 ClearWindows(true);
c801d85f
KB
1239}
1240
1241// Called when a tab is activated
1242void wxPanelTabView::OnTabActivate(int activateId, int deactivateId)
1243{
1244 if (!m_panel)
1245 return;
2b854a32 1246
c801d85f
KB
1247 wxWindow *oldWindow = ((deactivateId == -1) ? 0 : GetTabWindow(deactivateId));
1248 wxWindow *newWindow = GetTabWindow(activateId);
1249
1250 if (oldWindow)
ca65c044 1251 oldWindow->Show(false);
c801d85f 1252 if (newWindow)
ca65c044 1253 newWindow->Show(true);
2b854a32 1254
c801d85f
KB
1255 m_panel->Refresh();
1256}
1257
2b854a32 1258
c801d85f
KB
1259void wxPanelTabView::AddTabWindow(int id, wxWindow *window)
1260{
4410d619
MB
1261 wxASSERT(m_tabWindows.find(id) == m_tabWindows.end());
1262 m_tabWindows[id] = window;
ca65c044 1263 window->Show(false);
c801d85f
KB
1264}
1265
1266wxWindow *wxPanelTabView::GetTabWindow(int id) const
1267{
4410d619
MB
1268 wxIntToWindowHashMap::const_iterator it = m_tabWindows.find(id);
1269 return it == m_tabWindows.end() ? NULL : it->second;
c801d85f
KB
1270}
1271
1272void wxPanelTabView::ClearWindows(bool deleteWindows)
1273{
1274 if (deleteWindows)
4410d619
MB
1275 WX_CLEAR_HASH_MAP(wxIntToWindowHashMap, m_tabWindows);
1276 m_tabWindows.clear();
c801d85f
KB
1277}
1278
1279void wxPanelTabView::ShowWindowForTab(int id)
1280{
1281 wxWindow *newWindow = GetTabWindow(id);
1282 if (newWindow == m_currentWindow)
1283 return;
1284 if (m_currentWindow)
ca65c044
WS
1285 m_currentWindow->Show(false);
1286 newWindow->Show(true);
c801d85f
KB
1287 newWindow->Refresh();
1288}
1289
1e6feb95 1290#endif // wxUSE_TAB_DIALOG