1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Generic tabbed dialogs
4 // Author: Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "tabg.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
34 // not defined: use old, square tab implementation (fills in tabs)
35 // defined: use new, rounded tab implementation (doesn't colour in tabs)
36 // #define wxUSE_NEW_METHOD
38 IMPLEMENT_DYNAMIC_CLASS(wxTabControl
, wxObject
)
40 IMPLEMENT_DYNAMIC_CLASS(wxTabLayer
, wxList
)
42 wxTabControl::wxTabControl(wxTabView
*v
)
55 wxTabControl::~wxTabControl(void)
59 void wxTabControl::OnDraw(wxDC
& dc
, bool lastInRow
)
61 // Old, but in some ways better (drawing opaque tabs)
62 #ifndef wxUSE_NEW_METHOD
66 // Top-left of tab view area
67 int viewX
= m_view
->GetViewRect().x
;
68 int viewY
= m_view
->GetViewRect().y
;
70 // Top-left of tab control
71 int tabX
= GetX() + viewX
;
72 int tabY
= GetY() + viewY
;
76 tabHeightInc
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
80 dc
.SetPen(*wxTRANSPARENT_PEN
);
82 // Draw grey background
83 if (m_view
->GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR
)
85 dc
.SetBrush(*m_view
->GetBackgroundBrush());
87 // Add 1 because the pen is transparent. Under Motif, may be different.
89 dc
.DrawRectangle(tabX
, tabY
, (GetWidth()+1), (GetHeight() + tabHeightInc
));
91 dc
.DrawRectangle(tabX
, tabY
, (GetWidth()+1), (GetHeight() + 1 + tabHeightInc
));
95 // Draw highlight and shadow
96 dc
.SetPen(*m_view
->GetHighlightPen());
98 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
99 // a bit if the tab below happens to be selected. Check.
100 wxTabControl
*tabBeneath
= NULL
;
101 int subtractThis
= 0;
102 if (GetColPosition() > 0)
103 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition());
104 if (tabBeneath
&& tabBeneath
->IsSelected())
105 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
107 // Vertical highlight: if first tab, draw to bottom of view
108 if (tabX
== m_view
->GetViewRect().x
&& (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
109 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
));
110 else if (tabX
== m_view
->GetViewRect().x
)
111 // Not box drawing, just to top of view.
112 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
));
114 dc
.DrawLine(tabX
, tabY
, tabX
, (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
116 dc
.DrawLine(tabX
, tabY
, (tabX
+ GetWidth()), tabY
);
117 dc
.SetPen(*m_view
->GetShadowPen());
119 // Test if we're outside the right-hand edge of the view area
120 if (((tabX
+ GetWidth()) >= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
) && (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
122 int bottomY
= m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
+ GetY() + m_view
->GetTabHeight() + m_view
->GetTopMargin();
123 // Add a tab height since we wish to draw to the bottom of the view.
124 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
125 (tabX
+ GetWidth()), bottomY
);
127 // Calculate the far-right of the view, since we don't wish to
129 int rightOfView
= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
+ 1;
131 // Draw the horizontal bit to connect to the view rectangle
132 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
-1),
133 (tabX
+ GetWidth()), (bottomY
-1));
135 // Draw black line to emphasize shadow
136 dc
.SetPen(*wxBLACK_PEN
);
137 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1),
138 (tabX
+ GetWidth() + 1), bottomY
);
140 // Draw the horizontal bit to connect to the view rectangle
141 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
),
142 (tabX
+ GetWidth() + 1), (bottomY
));
148 // 25/5/97 UNLESS it's less than the max number of positions in this row
150 int topY
= m_view
->GetViewRect().y
- m_view
->GetTopMargin();
152 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Nth(0)->Data())->Number();
154 // Only down to the bottom of the tab, not to the top of the view
155 if ( GetRowPosition() < (maxPositions
- 1) )
156 topY
= tabY
+ GetHeight() + tabHeightInc
;
163 dc
.DrawLine((tabX
+ GetWidth()), tabY
, (tabX
+ GetWidth()), topY
);
164 // Draw black line to emphasize shadow
165 dc
.SetPen(*wxBLACK_PEN
);
166 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
171 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
172 // a bit if the tab below (and next col along) happens to be selected. Check.
173 wxTabControl
*tabBeneath
= NULL
;
174 int subtractThis
= 0;
175 if (GetColPosition() > 0)
176 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition() + 1);
177 if (tabBeneath
&& tabBeneath
->IsSelected())
178 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
184 // Draw only to next tab down.
185 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
186 (tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
188 // Draw black line to emphasize shadow
189 dc
.SetPen(*wxBLACK_PEN
);
190 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
191 (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
195 // Draw centered text
196 int textY
= tabY
+ m_view
->GetVerticalTabTextSpacing() + tabHeightInc
;
199 dc
.SetFont(* m_view
->GetSelectedTabFont());
201 dc
.SetFont(* GetFont());
203 wxColour
col(m_view
->GetTextColour());
204 dc
.SetTextForeground(col
);
205 dc
.SetBackgroundMode(wxTRANSPARENT
);
206 long textWidth
, textHeight
;
207 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
209 int textX
= (int)(tabX
+ (GetWidth() - textWidth
)/2.0);
210 if (textX
< (tabX
+ 2))
213 dc
.SetClippingRegion(tabX
, tabY
, GetWidth(), GetHeight());
214 dc
.DrawText(GetLabel(), textX
, textY
);
215 dc
.DestroyClippingRegion();
219 dc
.SetPen(*m_view
->GetHighlightPen());
221 // Draw white highlight from the tab's left side to the left hand edge of the view
222 dc
.DrawLine(m_view
->GetViewRect().x
, (tabY
+ GetHeight() + tabHeightInc
),
223 tabX
, (tabY
+ GetHeight() + tabHeightInc
));
225 // Draw white highlight from the tab's right side to the right hand edge of the view
226 dc
.DrawLine((tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
),
227 m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
, (tabY
+ GetHeight() + tabHeightInc
));
230 // New HEL version with rounder tabs
237 tabInc
= m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight();
239 int tabLeft
= GetX() + m_view
->GetViewRect().x
;
240 int tabTop
= GetY() + m_view
->GetViewRect().y
- tabInc
;
241 int tabRight
= tabLeft
+ m_view
->GetTabWidth();
242 int left
= m_view
->GetViewRect().x
;
243 int top
= tabTop
+ m_view
->GetTabHeight() + tabInc
;
244 int right
= left
+ m_view
->GetViewRect().width
;
245 int bottom
= top
+ m_view
->GetViewRect().height
;
249 // TAB is selected - draw TAB and the View's full outline
251 dc
.SetPen(*(m_view
->GetHighlightPen()));
254 pnts
[n
].x
= left
; pnts
[n
++].y
= bottom
;
255 pnts
[n
].x
= left
; pnts
[n
++].y
= top
;
256 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= top
;
257 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
258 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
259 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
260 dc
.DrawLines(n
, pnts
);
271 dc
.SetPen(*(m_view
->GetShadowPen()));
291 dc
.SetPen(*wxBLACK_PEN
);
333 // TAB is not selected - just draw TAB outline and RH edge
334 // if the TAB is the last in the row
336 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Nth(0)->Data())->Number();
337 wxTabControl
* tabBelow
= 0;
338 wxTabControl
* tabBelowRight
= 0;
339 if (GetColPosition() > 0)
341 tabBelow
= m_view
->FindTabControlForPosition(
342 GetColPosition() - 1,
346 if (!lastInRow
&& GetColPosition() > 0)
348 tabBelowRight
= m_view
->FindTabControlForPosition(
349 GetColPosition() - 1,
354 float raisedTop
= top
- m_view
->GetTabSelectionHeight() +
355 m_view
->GetTabHeight();
357 dc
.SetPen(*(m_view
->GetHighlightPen()));
363 if (tabBelow
&& tabBelow
->IsSelected())
365 pnts
[n
++].y
= (long)raisedTop
;
371 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
372 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
373 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
374 dc
.DrawLines(n
, pnts
);
376 dc
.SetPen(*(m_view
->GetShadowPen()));
377 if (GetRowPosition() >= maxPositions
- 1)
388 (tabRight
- m_view
->GetHorizontalTabOffset()),
394 if (tabBelowRight
&& tabBelowRight
->IsSelected())
414 dc
.SetPen(*wxBLACK_PEN
);
423 if (GetRowPosition() >= maxPositions
- 1)
425 // draw right hand edge to bottom of view
435 (tabRight
- m_view
->GetHorizontalTabOffset()),
441 // draw right hand edge of TAB
442 if (tabBelowRight
&& tabBelowRight
->IsSelected())
446 (long)(raisedTop
- 1),
463 // Draw centered text
464 dc
.SetPen(*wxBLACK_PEN
);
467 dc
.SetFont(*(m_view
->GetSelectedTabFont()));
471 dc
.SetFont(*(GetFont()));
474 wxColour
col(m_view
->GetTextColour());
475 dc
.SetTextForeground(col
);
476 dc
.SetBackgroundMode(wxTRANSPARENT
);
477 long textWidth
, textHeight
;
478 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
480 float textX
= (tabLeft
+ tabRight
- textWidth
) / 2;
481 float textY
= (tabInc
+ tabTop
+ m_view
->GetVerticalTabTextSpacing());
483 dc
.DrawText(GetLabel(), (long)textX
, (long)textY
);
487 bool wxTabControl::HitTest(int x
, int y
) const
489 // Top-left of tab control
490 int tabX1
= GetX() + m_view
->GetViewRect().x
;
491 int tabY1
= GetY() + m_view
->GetViewRect().y
;
494 int tabX2
= tabX1
+ GetWidth();
495 int tabY2
= tabY1
+ GetHeight();
497 if (x
>= tabX1
&& y
>= tabY1
&& x
<= tabX2
&& y
<= tabY2
)
503 IMPLEMENT_DYNAMIC_CLASS(wxTabView
, wxObject
)
505 wxTabView::wxTabView(long style
)
511 m_tabSelectionHeight
= m_tabHeight
+ 2;
513 m_tabHorizontalOffset
= 10;
514 m_tabHorizontalSpacing
= 2;
515 m_tabVerticalTextSpacing
= 3;
517 m_tabViewRect
.x
= 20;
518 m_tabViewRect
.y
= 20;
519 m_tabViewRect
.width
= 300;
520 m_tabViewRect
.x
= 300;
521 m_highlightColour
= *wxWHITE
;
522 m_shadowColour
= wxColour(128, 128, 128);
523 m_backgroundColour
= *wxLIGHT_GREY
;
524 m_textColour
= *wxBLACK
;
525 m_highlightPen
= wxWHITE_PEN
;
526 m_shadowPen
= wxGREY_PEN
;
527 m_backgroundPen
= wxLIGHT_GREY_PEN
;
528 m_backgroundBrush
= wxLIGHT_GREY_BRUSH
;
529 m_tabFont
= wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
);
530 m_tabSelectedFont
= wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
);
531 m_window
= (wxWindow
*) NULL
;
534 wxTabView::~wxTabView()
539 // Automatically positions tabs
540 // TODO: this should just add the tab to a list, and then
541 // a layout function (e.g. Realize) should be called when all tabs have been added.
542 // The view rect could easily change as the view window is resized.
543 wxTabControl
*wxTabView::AddTab(int id
, const wxString
& label
, wxTabControl
*existingTab
)
545 // First, find which layer we should be adding to.
546 wxNode
*node
= m_layers
.Last();
549 wxTabLayer
*newLayer
= new wxTabLayer
;
550 node
= m_layers
.Append(newLayer
);
552 // Check if adding another tab control would go off the
553 // right-hand edge of the layer.
554 wxTabLayer
*tabLayer
= (wxTabLayer
*)node
->Data();
555 wxNode
*lastTabNode
= tabLayer
->Last();
558 wxTabControl
*lastTab
= (wxTabControl
*)lastTabNode
->Data();
559 // Start another layer (row).
560 // Tricky choice: can't just check if will be overlapping the edge, because
561 // this happens anyway for 2nd and subsequent rows.
562 // Should check this for 1st row, and then subsequent rows should not exceed 1st
564 if (((tabLayer
== m_layers
.First()->Data()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
565 > GetViewRect().width
)) ||
566 ((tabLayer
!= m_layers
.First()->Data()) && (tabLayer
->Number() == ((wxTabLayer
*)m_layers
.First()->Data())->Number())))
568 tabLayer
= new wxTabLayer
;
569 m_layers
.Append(tabLayer
);
570 lastTabNode
= (wxNode
*) NULL
;
573 int layer
= m_layers
.Number() - 1;
575 wxTabControl
*tabControl
= existingTab
;
577 tabControl
= OnCreateTabControl();
578 tabControl
->SetRowPosition(tabLayer
->Number());
579 tabControl
->SetColPosition(layer
);
581 wxTabControl
*lastTab
= (wxTabControl
*) NULL
;
583 lastTab
= (wxTabControl
*)lastTabNode
->Data();
586 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
587 // Offset from view top-left
588 int horizontalOffset
= 0;
590 horizontalOffset
= layer
*GetHorizontalTabOffset();
592 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
594 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
595 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
596 tabControl
->SetId(id
);
597 tabControl
->SetLabel(label
);
598 tabControl
->SetFont(* GetTabFont());
600 tabLayer
->Append(tabControl
);
606 // Remove the tab without deleting the window
607 bool wxTabView::RemoveTab(int id
)
609 wxNode
*layerNode
= m_layers
.First();
612 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->Data();
613 wxNode
*tabNode
= layer
->First();
616 wxTabControl
*tab
= (wxTabControl
*)tabNode
->Data();
617 if (tab
->GetId() == id
)
619 if (id
== m_tabSelection
)
625 // The layout has changed
629 tabNode
= tabNode
->Next();
631 layerNode
= layerNode
->Next();
636 bool wxTabView::SetTabText(int id
, const wxString
& label
)
638 wxTabControl
* control
= FindTabControlForId(id
);
641 control
->SetLabel(label
);
645 wxString
wxTabView::GetTabText(int id
) const
647 wxTabControl
* control
= FindTabControlForId(id
);
649 return wxEmptyString
;
651 return control
->GetLabel();
654 // Returns the total height of the tabs component -- this may be several
655 // times the height of a tab, if there are several tab layers (rows).
656 int wxTabView::GetTotalTabHeight()
660 wxNode
*layerNode
= m_layers
.First();
663 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->Data();
664 wxNode
*tabNode
= layer
->First();
667 wxTabControl
*tab
= (wxTabControl
*)tabNode
->Data();
669 if (tab
->GetY() < minY
)
672 tabNode
= tabNode
->Next();
674 layerNode
= layerNode
->Next();
680 void wxTabView::ClearTabs(bool deleteTabs
)
682 wxNode
*layerNode
= m_layers
.First();
685 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->Data();
686 wxNode
*tabNode
= layer
->First();
689 wxTabControl
*tab
= (wxTabControl
*)tabNode
->Data();
692 wxNode
*next
= tabNode
->Next();
696 wxNode
*nextLayerNode
= layerNode
->Next();
699 layerNode
= nextLayerNode
;
706 // Layout tabs (optional, e.g. if resizing window)
707 void wxTabView::LayoutTabs(void)
709 // Make a list of the tab controls, deleting the wxTabLayers.
712 wxNode
*layerNode
= m_layers
.First();
715 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->Data();
716 wxNode
*tabNode
= layer
->First();
719 wxTabControl
*tab
= (wxTabControl
*)tabNode
->Data();
720 controls
.Append(tab
);
721 wxNode
*next
= tabNode
->Next();
725 wxNode
*nextLayerNode
= layerNode
->Next();
728 layerNode
= nextLayerNode
;
731 wxTabControl
*lastTab
= (wxTabControl
*) NULL
;
733 wxTabLayer
*currentLayer
= new wxTabLayer
;
734 m_layers
.Append(currentLayer
);
736 wxNode
*node
= controls
.First();
739 wxTabControl
*tabControl
= (wxTabControl
*)node
->Data();
742 // Start another layer (row).
743 // Tricky choice: can't just check if will be overlapping the edge, because
744 // this happens anyway for 2nd and subsequent rows.
745 // Should check this for 1st row, and then subsequent rows should not exceed 1st
747 if (((currentLayer
== m_layers
.First()->Data()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
748 > GetViewRect().width
)) ||
749 ((currentLayer
!= m_layers
.First()->Data()) && (currentLayer
->Number() == ((wxTabLayer
*)m_layers
.First()->Data())->Number())))
751 currentLayer
= new wxTabLayer
;
752 m_layers
.Append(currentLayer
);
753 lastTab
= (wxTabControl
*) NULL
;
757 int layer
= m_layers
.Number() - 1;
759 tabControl
->SetRowPosition(currentLayer
->Number());
760 tabControl
->SetColPosition(layer
);
763 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
764 // Offset from view top-left
765 int horizontalOffset
= 0;
767 horizontalOffset
= layer
*GetHorizontalTabOffset();
769 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
771 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
772 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
774 currentLayer
->Append(tabControl
);
775 lastTab
= tabControl
;
780 // Move the selected tab to the bottom
781 wxTabControl
*control
= FindTabControlForId(m_tabSelection
);
783 MoveSelectionTab(control
);
788 void wxTabView::Draw(wxDC
& dc
)
790 // Don't draw anything if there are no tabs.
791 if (GetNumberOfTabs() == 0)
794 // Draw top margin area (beneath tabs and above view area)
795 if (GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR
)
797 dc
.SetPen(*wxTRANSPARENT_PEN
);
798 dc
.SetBrush(*GetBackgroundBrush());
800 // Add 1 because the pen is transparent. Under Motif, may be different.
803 (m_tabViewRect
.y
- m_topMargin
),
804 (m_tabViewRect
.width
+ 1),
809 // Draw layers in reverse order
810 wxNode
*node
= m_layers
.Last();
813 wxTabLayer
*layer
= (wxTabLayer
*)node
->Data();
814 wxNode
*node2
= layer
->First();
817 wxTabControl
*control
= (wxTabControl
*)node2
->Data();
818 control
->OnDraw(dc
, (node2
->Next() == NULL
));
819 node2
= node2
->Next();
822 node
= node
->Previous();
826 #ifndef wxUSE_NEW_METHOD
827 if (GetTabStyle() & wxTAB_STYLE_DRAW_BOX
)
829 dc
.SetPen(* GetShadowPen());
833 (GetViewRect().x
+ 1),
834 (GetViewRect().y
+ GetViewRect().height
),
835 (GetViewRect().x
+ GetViewRect().width
+ 1),
836 (GetViewRect().y
+ GetViewRect().height
)
841 (GetViewRect().x
+ GetViewRect().width
),
842 (GetViewRect().y
- GetTopMargin() + 1),
843 (GetViewRect().x
+ GetViewRect().width
),
844 (GetViewRect().y
+ GetViewRect().height
)
847 dc
.SetPen(* wxBLACK_PEN
);
852 (GetViewRect().y
+ GetViewRect().height
+ 1),
853 #if defined(__WXMOTIF__)
854 (GetViewRect().x
+ GetViewRect().width
+ 1),
856 (GetViewRect().x
+ GetViewRect().width
+ 2),
859 (GetViewRect().y
+ GetViewRect().height
+ 1)
864 (GetViewRect().x
+ GetViewRect().width
+ 1),
865 (GetViewRect().y
- GetTopMargin()),
866 (GetViewRect().x
+ GetViewRect().width
+ 1),
867 (GetViewRect().y
+ GetViewRect().height
+ 1)
873 // Process mouse event, return FALSE if we didn't process it
874 bool wxTabView::OnEvent(wxMouseEvent
& event
)
876 if (!event
.LeftDown())
880 event
.GetPosition(&x
, &y
);
882 wxTabControl
*hitControl
= (wxTabControl
*) NULL
;
884 wxNode
*node
= m_layers
.First();
887 wxTabLayer
*layer
= (wxTabLayer
*)node
->Data();
888 wxNode
*node2
= layer
->First();
891 wxTabControl
*control
= (wxTabControl
*)node2
->Data();
892 if (control
->HitTest((int)x
, (int)y
))
894 hitControl
= control
;
895 node
= (wxNode
*) NULL
;
896 node2
= (wxNode
*) NULL
;
899 node2
= node2
->Next();
909 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
911 if (hitControl
== currentTab
)
914 ChangeTab(hitControl
);
919 bool wxTabView::ChangeTab(wxTabControl
*control
)
921 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
924 oldTab
= currentTab
->GetId();
926 if (control
== currentTab
)
929 if (m_layers
.Number() == 0)
932 if (!OnTabPreActivate(control
->GetId(), oldTab
))
935 // Move the tab to the bottom
936 MoveSelectionTab(control
);
939 currentTab
->SetSelected(FALSE
);
941 control
->SetSelected(TRUE
);
942 m_tabSelection
= control
->GetId();
944 OnTabActivate(control
->GetId(), oldTab
);
946 // Leave window refresh for the implementing window
951 // Move the selected tab to the bottom layer, if necessary,
952 // without calling app activation code
953 bool wxTabView::MoveSelectionTab(wxTabControl
*control
)
955 if (m_layers
.Number() == 0)
958 wxTabLayer
*firstLayer
= (wxTabLayer
*)m_layers
.First()->Data();
960 // Find what column this tab is at, so we can swap with the one at the bottom.
961 // If we're on the bottom layer, then no need to swap.
962 if (!firstLayer
->Member(control
))
966 wxNode
*thisNode
= FindTabNodeAndColumn(control
, &col
);
969 wxNode
*otherNode
= firstLayer
->Nth(col
);
973 // If this is already in the bottom layer, return now
974 if (otherNode
== thisNode
)
977 wxTabControl
*otherTab
= (wxTabControl
*)otherNode
->Data();
979 // We now have pointers to the tab to be changed to,
980 // and the tab on the first layer. Swap tab structures and
983 int thisX
= control
->GetX();
984 int thisY
= control
->GetY();
985 int thisColPos
= control
->GetColPosition();
986 int otherX
= otherTab
->GetX();
987 int otherY
= otherTab
->GetY();
988 int otherColPos
= otherTab
->GetColPosition();
990 control
->SetPosition(otherX
, otherY
);
991 control
->SetColPosition(otherColPos
);
992 otherTab
->SetPosition(thisX
, thisY
);
993 otherTab
->SetColPosition(thisColPos
);
995 // Swap the data for the nodes
996 thisNode
->SetData(otherTab
);
997 otherNode
->SetData(control
);
1002 // Called when a tab is activated
1003 void wxTabView::OnTabActivate(int /*activateId*/, int /*deactivateId*/)
1007 void wxTabView::SetHighlightColour(const wxColour
& col
)
1009 m_highlightColour
= col
;
1010 m_highlightPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
1013 void wxTabView::SetShadowColour(const wxColour
& col
)
1015 m_shadowColour
= col
;
1016 m_shadowPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
1019 void wxTabView::SetBackgroundColour(const wxColour
& col
)
1021 m_backgroundColour
= col
;
1022 m_backgroundPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
1023 m_backgroundBrush
= wxTheBrushList
->FindOrCreateBrush(col
, wxSOLID
);
1026 void wxTabView::SetTabSelection(int sel
, bool activateTool
)
1028 if ( sel
==m_tabSelection
)
1031 int oldSel
= m_tabSelection
;
1032 wxTabControl
*control
= FindTabControlForId(sel
);
1033 wxTabControl
*oldControl
= FindTabControlForId(m_tabSelection
);
1035 if (!OnTabPreActivate(sel
, oldSel
))
1039 control
->SetSelected((sel
!= -1)); // TODO ??
1042 wxFAIL_MSG(_("Could not find tab for id"));
1047 oldControl
->SetSelected(FALSE
);
1049 m_tabSelection
= sel
;
1052 MoveSelectionTab(control
);
1055 OnTabActivate(sel
, oldSel
);
1058 // Find tab control for id
1059 wxTabControl
*wxTabView::FindTabControlForId(int id
) const
1061 wxNode
*node1
= m_layers
.First();
1064 wxTabLayer
*layer
= (wxTabLayer
*)node1
->Data();
1065 wxNode
*node2
= layer
->First();
1068 wxTabControl
*control
= (wxTabControl
*)node2
->Data();
1069 if (control
->GetId() == id
)
1071 node2
= node2
->Next();
1073 node1
= node1
->Next();
1075 return (wxTabControl
*) NULL
;
1078 // Find tab control for layer, position (starting from zero)
1079 wxTabControl
*wxTabView::FindTabControlForPosition(int layer
, int position
) const
1081 wxNode
*node1
= m_layers
.Nth(layer
);
1083 return (wxTabControl
*) NULL
;
1084 wxTabLayer
*tabLayer
= (wxTabLayer
*)node1
->Data();
1085 wxNode
*node2
= tabLayer
->Nth(position
);
1087 return (wxTabControl
*) NULL
;
1088 return (wxTabControl
*)node2
->Data();
1091 // Find the node and the column at which this control is positioned.
1092 wxNode
*wxTabView::FindTabNodeAndColumn(wxTabControl
*control
, int *col
) const
1094 wxNode
*node1
= m_layers
.First();
1097 wxTabLayer
*layer
= (wxTabLayer
*)node1
->Data();
1099 wxNode
*node2
= layer
->First();
1102 wxTabControl
*cnt
= (wxTabControl
*)node2
->Data();
1108 node2
= node2
->Next();
1111 node1
= node1
->Next();
1113 return (wxNode
*) NULL
;
1116 int wxTabView::CalculateTabWidth(int noTabs
, bool adjustView
)
1118 m_tabWidth
= (int)((m_tabViewRect
.width
- ((noTabs
- 1)*GetHorizontalTabSpacing()))/noTabs
);
1121 m_tabViewRect
.width
= noTabs
*m_tabWidth
+ ((noTabs
-1)*GetHorizontalTabSpacing());
1130 IMPLEMENT_CLASS(wxTabbedDialog
, wxDialog
)
1132 BEGIN_EVENT_TABLE(wxTabbedDialog
, wxDialog
)
1133 EVT_CLOSE(wxTabbedDialog::OnCloseWindow
)
1134 EVT_MOUSE_EVENTS(wxTabbedDialog::OnMouseEvent
)
1135 EVT_PAINT(wxTabbedDialog::OnPaint
)
1138 wxTabbedDialog::wxTabbedDialog(wxWindow
*parent
, wxWindowID id
,
1139 const wxString
& title
,
1140 const wxPoint
& pos
, const wxSize
& size
,
1141 long windowStyle
, const wxString
& name
):
1142 wxDialog(parent
, id
, title
, pos
, size
, windowStyle
, name
)
1144 m_tabView
= (wxTabView
*) NULL
;
1147 wxTabbedDialog::~wxTabbedDialog(void)
1153 void wxTabbedDialog::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
) )
1158 void wxTabbedDialog::OnMouseEvent(wxMouseEvent
& event
)
1161 m_tabView
->OnEvent(event
);
1164 void wxTabbedDialog::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1168 m_tabView
->Draw(dc
);
1175 IMPLEMENT_CLASS(wxTabbedPanel
, wxPanel
)
1177 BEGIN_EVENT_TABLE(wxTabbedPanel
, wxPanel
)
1178 EVT_MOUSE_EVENTS(wxTabbedPanel::OnMouseEvent
)
1179 EVT_PAINT(wxTabbedPanel::OnPaint
)
1182 wxTabbedPanel::wxTabbedPanel(wxWindow
*parent
, wxWindowID id
, const wxPoint
& pos
,
1183 const wxSize
& size
, long windowStyle
, const wxString
& name
):
1184 wxPanel(parent
, id
, pos
, size
, windowStyle
, name
)
1186 m_tabView
= (wxTabView
*) NULL
;
1189 wxTabbedPanel::~wxTabbedPanel(void)
1194 void wxTabbedPanel::OnMouseEvent(wxMouseEvent
& event
)
1197 m_tabView
->OnEvent(event
);
1200 void wxTabbedPanel::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1204 m_tabView
->Draw(dc
);
1211 IMPLEMENT_CLASS(wxPanelTabView
, wxTabView
)
1213 wxPanelTabView::wxPanelTabView(wxPanel
*pan
, long style
): wxTabView(style
), m_tabWindows(wxKEY_INTEGER
)
1216 m_currentWindow
= (wxWindow
*) NULL
;
1218 if (m_panel
->IsKindOf(CLASSINFO(wxTabbedDialog
)))
1219 ((wxTabbedDialog
*)m_panel
)->SetTabView(this);
1220 else if (m_panel
->IsKindOf(CLASSINFO(wxTabbedPanel
)))
1221 ((wxTabbedPanel
*)m_panel
)->SetTabView(this);
1226 wxPanelTabView::~wxPanelTabView(void)
1231 // Called when a tab is activated
1232 void wxPanelTabView::OnTabActivate(int activateId
, int deactivateId
)
1237 wxWindow
*oldWindow
= ((deactivateId
== -1) ? 0 : GetTabWindow(deactivateId
));
1238 wxWindow
*newWindow
= GetTabWindow(activateId
);
1241 oldWindow
->Show(FALSE
);
1243 newWindow
->Show(TRUE
);
1249 void wxPanelTabView::AddTabWindow(int id
, wxWindow
*window
)
1251 m_tabWindows
.Append((long)id
, window
);
1252 window
->Show(FALSE
);
1255 wxWindow
*wxPanelTabView::GetTabWindow(int id
) const
1257 wxNode
*node
= m_tabWindows
.Find((long)id
);
1259 return (wxWindow
*) NULL
;
1260 return (wxWindow
*)node
->Data();
1263 void wxPanelTabView::ClearWindows(bool deleteWindows
)
1266 m_tabWindows
.DeleteContents(TRUE
);
1267 m_tabWindows
.Clear();
1268 m_tabWindows
.DeleteContents(FALSE
);
1271 void wxPanelTabView::ShowWindowForTab(int id
)
1273 wxWindow
*newWindow
= GetTabWindow(id
);
1274 if (newWindow
== m_currentWindow
)
1276 if (m_currentWindow
)
1277 m_currentWindow
->Show(FALSE
);
1278 newWindow
->Show(TRUE
);
1279 newWindow
->Refresh();