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
)
46 m_labelFont
= (wxFont
*) NULL
;
56 wxTabControl::~wxTabControl(void)
60 void wxTabControl::OnDraw(wxDC
& dc
, bool lastInRow
)
62 // Old, but in some ways better (drawing opaque tabs)
63 #ifndef wxUSE_NEW_METHOD
67 // Top-left of tab view area
68 int viewX
= m_view
->GetViewRect().x
;
69 int viewY
= m_view
->GetViewRect().y
;
71 // Top-left of tab control
72 int tabX
= GetX() + viewX
;
73 int tabY
= GetY() + viewY
;
77 tabHeightInc
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
81 dc
.SetPen(*wxTRANSPARENT_PEN
);
83 // Draw grey background
84 if (m_view
->GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR
)
86 dc
.SetBrush(*m_view
->GetBackgroundBrush());
88 // Add 1 because the pen is transparent. Under Motif, may be different.
89 dc
.DrawRectangle(tabX
, tabY
, (GetWidth()+1), (GetHeight() + 1 + tabHeightInc
));
92 // Draw highlight and shadow
93 dc
.SetPen(*m_view
->GetHighlightPen());
95 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
96 // a bit if the tab below happens to be selected. Check.
97 wxTabControl
*tabBeneath
= NULL
;
99 if (GetColPosition() > 0)
100 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition());
101 if (tabBeneath
&& tabBeneath
->IsSelected())
102 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
104 // Vertical highlight: if first tab, draw to bottom of view
105 if (tabX
== m_view
->GetViewRect().x
&& (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
106 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
));
107 else if (tabX
== m_view
->GetViewRect().x
)
108 // Not box drawing, just to top of view.
109 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
));
111 dc
.DrawLine(tabX
, tabY
, tabX
, (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
113 dc
.DrawLine(tabX
, tabY
, (tabX
+ GetWidth()), tabY
);
114 dc
.SetPen(*m_view
->GetShadowPen());
116 // Test if we're outside the right-hand edge of the view area
117 if (((tabX
+ GetWidth()) >= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
) && (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
119 int bottomY
= m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
+ GetY() + m_view
->GetTabHeight() + m_view
->GetTopMargin();
120 // Add a tab height since we wish to draw to the bottom of the view.
121 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
122 (tabX
+ GetWidth()), bottomY
);
124 // Calculate the far-right of the view, since we don't wish to
126 int rightOfView
= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
+ 1;
128 // Draw the horizontal bit to connect to the view rectangle
129 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
-1),
130 (tabX
+ GetWidth()), (bottomY
-1));
132 // Draw black line to emphasize shadow
133 dc
.SetPen(*wxBLACK_PEN
);
134 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1),
135 (tabX
+ GetWidth() + 1), bottomY
);
137 // Draw the horizontal bit to connect to the view rectangle
138 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
),
139 (tabX
+ GetWidth() + 1), (bottomY
));
145 // 25/5/97 UNLESS it's less than the max number of positions in this row
147 int topY
= m_view
->GetViewRect().y
- m_view
->GetTopMargin();
149 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Nth(0)->Data())->Number();
151 // Only down to the bottom of the tab, not to the top of the view
152 if ( GetRowPosition() < (maxPositions
- 1) )
153 topY
= tabY
+ GetHeight() + tabHeightInc
;
156 dc
.DrawLine((tabX
+ GetWidth()), tabY
, (tabX
+ GetWidth()), topY
);
157 // Draw black line to emphasize shadow
158 dc
.SetPen(*wxBLACK_PEN
);
159 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
164 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
165 // a bit if the tab below (and next col along) happens to be selected. Check.
166 wxTabControl
*tabBeneath
= NULL
;
167 int subtractThis
= 0;
168 if (GetColPosition() > 0)
169 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition() + 1);
170 if (tabBeneath
&& tabBeneath
->IsSelected())
171 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
173 // Draw only to next tab down.
174 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
175 (tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
177 // Draw black line to emphasize shadow
178 dc
.SetPen(*wxBLACK_PEN
);
179 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
180 (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
184 // Draw centered text
185 int textY
= tabY
+ m_view
->GetVerticalTabTextSpacing() + tabHeightInc
;
188 dc
.SetFont(*m_view
->GetSelectedTabFont());
190 dc
.SetFont(*GetFont());
192 wxColour
col(m_view
->GetTextColour());
193 dc
.SetTextForeground(col
);
194 dc
.SetBackgroundMode(wxTRANSPARENT
);
195 long textWidth
, textHeight
;
196 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
198 int textX
= (int)(tabX
+ (GetWidth() - textWidth
)/2.0);
199 dc
.DrawText(GetLabel(), textX
, textY
);
203 dc
.SetPen(*m_view
->GetHighlightPen());
205 // Draw white highlight from the tab's left side to the left hand edge of the view
206 dc
.DrawLine(m_view
->GetViewRect().x
, (tabY
+ GetHeight() + tabHeightInc
),
207 tabX
, (tabY
+ GetHeight() + tabHeightInc
));
209 // Draw white highlight from the tab's right side to the right hand edge of the view
210 dc
.DrawLine((tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
),
211 m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
, (tabY
+ GetHeight() + tabHeightInc
));
214 // New HEL version with rounder tabs
221 tabInc
= m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight();
223 int tabLeft
= GetX() + m_view
->GetViewRect().x
;
224 int tabTop
= GetY() + m_view
->GetViewRect().y
- tabInc
;
225 int tabRight
= tabLeft
+ m_view
->GetTabWidth();
226 int left
= m_view
->GetViewRect().x
;
227 int top
= tabTop
+ m_view
->GetTabHeight() + tabInc
;
228 int right
= left
+ m_view
->GetViewRect().width
;
229 int bottom
= top
+ m_view
->GetViewRect().height
;
233 // TAB is selected - draw TAB and the View's full outline
235 dc
.SetPen(*(m_view
->GetHighlightPen()));
238 pnts
[n
].x
= left
; pnts
[n
++].y
= bottom
;
239 pnts
[n
].x
= left
; pnts
[n
++].y
= top
;
240 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= top
;
241 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
242 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
243 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
244 dc
.DrawLines(n
, pnts
);
255 dc
.SetPen(*(m_view
->GetShadowPen()));
275 dc
.SetPen(*wxBLACK_PEN
);
317 // TAB is not selected - just draw TAB outline and RH edge
318 // if the TAB is the last in the row
320 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Nth(0)->Data())->Number();
321 wxTabControl
* tabBelow
= 0;
322 wxTabControl
* tabBelowRight
= 0;
323 if (GetColPosition() > 0)
325 tabBelow
= m_view
->FindTabControlForPosition(
326 GetColPosition() - 1,
330 if (!lastInRow
&& GetColPosition() > 0)
332 tabBelowRight
= m_view
->FindTabControlForPosition(
333 GetColPosition() - 1,
338 float raisedTop
= top
- m_view
->GetTabSelectionHeight() +
339 m_view
->GetTabHeight();
341 dc
.SetPen(*(m_view
->GetHighlightPen()));
347 if (tabBelow
&& tabBelow
->IsSelected())
349 pnts
[n
++].y
= (long)raisedTop
;
355 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
356 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
357 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
358 dc
.DrawLines(n
, pnts
);
360 dc
.SetPen(*(m_view
->GetShadowPen()));
361 if (GetRowPosition() >= maxPositions
- 1)
372 (tabRight
- m_view
->GetHorizontalTabOffset()),
378 if (tabBelowRight
&& tabBelowRight
->IsSelected())
398 dc
.SetPen(*wxBLACK_PEN
);
407 if (GetRowPosition() >= maxPositions
- 1)
409 // draw right hand edge to bottom of view
419 (tabRight
- m_view
->GetHorizontalTabOffset()),
425 // draw right hand edge of TAB
426 if (tabBelowRight
&& tabBelowRight
->IsSelected())
430 (long)(raisedTop
- 1),
447 // Draw centered text
448 dc
.SetPen(*wxBLACK_PEN
);
451 dc
.SetFont(*(m_view
->GetSelectedTabFont()));
455 dc
.SetFont(*(GetFont()));
458 wxColour
col(m_view
->GetTextColour());
459 dc
.SetTextForeground(col
);
460 dc
.SetBackgroundMode(wxTRANSPARENT
);
461 long textWidth
, textHeight
;
462 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
464 float textX
= (tabLeft
+ tabRight
- textWidth
) / 2;
465 float textY
= (tabInc
+ tabTop
+ m_view
->GetVerticalTabTextSpacing());
467 dc
.DrawText(GetLabel(), (long)textX
, (long)textY
);
471 bool wxTabControl::HitTest(int x
, int y
) const
473 // Top-left of tab control
474 int tabX1
= GetX() + m_view
->GetViewRect().x
;
475 int tabY1
= GetY() + m_view
->GetViewRect().y
;
478 int tabX2
= tabX1
+ GetWidth();
479 int tabY2
= tabY1
+ GetHeight();
481 if (x
>= tabX1
&& y
>= tabY1
&& x
<= tabX2
&& y
<= tabY2
)
487 IMPLEMENT_DYNAMIC_CLASS(wxTabView
, wxObject
)
489 wxTabView::wxTabView(long style
)
495 m_tabSelectionHeight
= m_tabHeight
+ 2;
497 m_tabHorizontalOffset
= 10;
498 m_tabHorizontalSpacing
= 2;
499 m_tabVerticalTextSpacing
= 3;
501 m_tabViewRect
.x
= 20;
502 m_tabViewRect
.y
= 20;
503 m_tabViewRect
.width
= 300;
504 m_tabViewRect
.x
= 300;
505 m_highlightColour
= *wxWHITE
;
506 m_shadowColour
= wxColour(128, 128, 128);
507 m_backgroundColour
= *wxLIGHT_GREY
;
508 m_textColour
= *wxBLACK
;
509 m_highlightPen
= wxWHITE_PEN
;
510 m_shadowPen
= wxGREY_PEN
;
511 m_backgroundPen
= wxLIGHT_GREY_PEN
;
512 m_backgroundBrush
= wxLIGHT_GREY_BRUSH
;
513 m_tabFont
= wxTheFontList
->FindOrCreateFont(9, wxSWISS
, wxNORMAL
, wxNORMAL
);
514 m_tabSelectedFont
= wxTheFontList
->FindOrCreateFont(9, wxSWISS
, wxNORMAL
, wxBOLD
);
515 m_window
= (wxWindow
*) NULL
;
518 wxTabView::~wxTabView()
522 // Automatically positions tabs
523 // TODO: this should just add the tab to a list, and then
524 // a layout function (e.g. Realize) should be called when all tabs have been added.
525 // The view rect could easily change as the view window is resized.
526 wxTabControl
*wxTabView::AddTab(int id
, const wxString
& label
, wxTabControl
*existingTab
)
528 // First, find which layer we should be adding to.
529 wxNode
*node
= m_layers
.Last();
532 wxTabLayer
*newLayer
= new wxTabLayer
;
533 node
= m_layers
.Append(newLayer
);
535 // Check if adding another tab control would go off the
536 // right-hand edge of the layer.
537 wxTabLayer
*tabLayer
= (wxTabLayer
*)node
->Data();
538 wxNode
*lastTabNode
= tabLayer
->Last();
541 wxTabControl
*lastTab
= (wxTabControl
*)lastTabNode
->Data();
542 // Start another layer (row).
543 // Tricky choice: can't just check if will be overlapping the edge, because
544 // this happens anyway for 2nd and subsequent rows.
545 // Should check this for 1st row, and then subsequent rows should not exceed 1st
547 if (((tabLayer
== m_layers
.First()->Data()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
548 > GetViewRect().width
)) ||
549 ((tabLayer
!= m_layers
.First()->Data()) && (tabLayer
->Number() == ((wxTabLayer
*)m_layers
.First()->Data())->Number())))
551 tabLayer
= new wxTabLayer
;
552 m_layers
.Append(tabLayer
);
553 lastTabNode
= (wxNode
*) NULL
;
556 int layer
= m_layers
.Number() - 1;
558 wxTabControl
*tabControl
= existingTab
;
560 tabControl
= OnCreateTabControl();
561 tabControl
->SetRowPosition(tabLayer
->Number());
562 tabControl
->SetColPosition(layer
);
564 wxTabControl
*lastTab
= (wxTabControl
*) NULL
;
566 lastTab
= (wxTabControl
*)lastTabNode
->Data();
569 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
570 // Offset from view top-left
571 int horizontalOffset
= 0;
573 horizontalOffset
= layer
*GetHorizontalTabOffset();
575 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
577 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
578 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
579 tabControl
->SetId(id
);
580 tabControl
->SetLabel(label
);
581 tabControl
->SetFont(GetTabFont());
583 tabLayer
->Append(tabControl
);
589 // Returns the total height of the tabs component -- this may be several
590 // times the height of a tab, if there are several tab layers (rows).
591 int wxTabView::GetTotalTabHeight()
595 wxNode
*layerNode
= m_layers
.First();
598 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->Data();
599 wxNode
*tabNode
= layer
->First();
602 wxTabControl
*tab
= (wxTabControl
*)tabNode
->Data();
604 if (tab
->GetY() < minY
)
607 tabNode
= tabNode
->Next();
609 layerNode
= layerNode
->Next();
615 void wxTabView::ClearTabs(bool deleteTabs
)
617 wxNode
*layerNode
= m_layers
.First();
620 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->Data();
621 wxNode
*tabNode
= layer
->First();
624 wxTabControl
*tab
= (wxTabControl
*)tabNode
->Data();
627 wxNode
*next
= tabNode
->Next();
631 wxNode
*nextLayerNode
= layerNode
->Next();
634 layerNode
= nextLayerNode
;
639 // Layout tabs (optional, e.g. if resizing window)
640 void wxTabView::Layout(void)
642 // Make a list of the tab controls, deleting the wxTabLayers.
645 wxNode
*layerNode
= m_layers
.First();
648 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->Data();
649 wxNode
*tabNode
= layer
->First();
652 wxTabControl
*tab
= (wxTabControl
*)tabNode
->Data();
653 controls
.Append(tab
);
654 wxNode
*next
= tabNode
->Next();
658 wxNode
*nextLayerNode
= layerNode
->Next();
661 layerNode
= nextLayerNode
;
664 wxTabControl
*lastTab
= (wxTabControl
*) NULL
;
666 wxTabLayer
*currentLayer
= new wxTabLayer
;
667 m_layers
.Append(currentLayer
);
669 wxNode
*node
= controls
.First();
672 wxTabControl
*tabControl
= (wxTabControl
*)node
->Data();
675 // Start another layer (row).
676 // Tricky choice: can't just check if will be overlapping the edge, because
677 // this happens anyway for 2nd and subsequent rows.
678 // Should check this for 1st row, and then subsequent rows should not exceed 1st
680 if (((currentLayer
== m_layers
.First()->Data()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
681 > GetViewRect().width
)) ||
682 ((currentLayer
!= m_layers
.First()->Data()) && (currentLayer
->Number() == ((wxTabLayer
*)m_layers
.First()->Data())->Number())))
684 currentLayer
= new wxTabLayer
;
685 m_layers
.Append(currentLayer
);
686 lastTab
= (wxTabControl
*) NULL
;
690 int layer
= m_layers
.Number() - 1;
692 tabControl
->SetRowPosition(currentLayer
->Number());
693 tabControl
->SetColPosition(layer
);
696 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
697 // Offset from view top-left
698 int horizontalOffset
= 0;
700 horizontalOffset
= layer
*GetHorizontalTabOffset();
702 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
704 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
705 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
707 currentLayer
->Append(tabControl
);
708 lastTab
= tabControl
;
713 // Move the selected tab to the bottom
714 wxTabControl
*control
= FindTabControlForId(m_tabSelection
);
716 MoveSelectionTab(control
);
721 void wxTabView::Draw(wxDC
& dc
)
723 // Draw top margin area (beneath tabs and above view area)
724 if (GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR
)
726 dc
.SetPen(*wxTRANSPARENT_PEN
);
727 dc
.SetBrush(*GetBackgroundBrush());
729 // Add 1 because the pen is transparent. Under Motif, may be different.
732 (m_tabViewRect
.y
- m_topMargin
),
733 (m_tabViewRect
.width
+ 1),
738 // Draw layers in reverse order
739 wxNode
*node
= m_layers
.Last();
742 wxTabLayer
*layer
= (wxTabLayer
*)node
->Data();
743 wxNode
*node2
= layer
->First();
746 wxTabControl
*control
= (wxTabControl
*)node2
->Data();
747 control
->OnDraw(dc
, (node2
->Next() == NULL
));
748 node2
= node2
->Next();
751 node
= node
->Previous();
755 #ifndef wxUSE_NEW_METHOD
756 if (GetTabStyle() & wxTAB_STYLE_DRAW_BOX
)
758 dc
.SetPen(GetShadowPen());
762 (GetViewRect().x
+ 1),
763 (GetViewRect().y
+ GetViewRect().height
),
764 (GetViewRect().x
+ GetViewRect().width
+ 1),
765 (GetViewRect().y
+ GetViewRect().height
)
770 (GetViewRect().x
+ GetViewRect().width
),
771 (GetViewRect().y
- GetTopMargin() + 1),
772 (GetViewRect().x
+ GetViewRect().width
),
773 (GetViewRect().y
+ GetViewRect().height
)
776 dc
.SetPen(wxBLACK_PEN
);
781 (GetViewRect().y
+ GetViewRect().height
+ 1),
782 (GetViewRect().x
+ GetViewRect().width
+ 2),
783 (GetViewRect().y
+ GetViewRect().height
+ 1)
788 (GetViewRect().x
+ GetViewRect().width
+ 1),
789 (GetViewRect().y
- GetTopMargin()),
790 (GetViewRect().x
+ GetViewRect().width
+ 1),
791 (GetViewRect().y
+ GetViewRect().height
+ 1)
797 // Process mouse event, return FALSE if we didn't process it
798 bool wxTabView::OnEvent(wxMouseEvent
& event
)
800 if (!event
.LeftDown())
804 event
.Position(&x
, &y
);
806 wxTabControl
*hitControl
= (wxTabControl
*) NULL
;
808 wxNode
*node
= m_layers
.First();
811 wxTabLayer
*layer
= (wxTabLayer
*)node
->Data();
812 wxNode
*node2
= layer
->First();
815 wxTabControl
*control
= (wxTabControl
*)node2
->Data();
816 if (control
->HitTest((int)x
, (int)y
))
818 hitControl
= control
;
819 node
= (wxNode
*) NULL
;
820 node2
= (wxNode
*) NULL
;
823 node2
= node2
->Next();
833 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
835 if (hitControl
== currentTab
)
838 ChangeTab(hitControl
);
843 bool wxTabView::ChangeTab(wxTabControl
*control
)
845 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
848 oldTab
= currentTab
->GetId();
850 if (control
== currentTab
)
853 if (m_layers
.Number() == 0)
856 if (!OnTabPreActivate(control
->GetId(), oldTab
))
859 // Move the tab to the bottom
860 MoveSelectionTab(control
);
863 currentTab
->SetSelected(FALSE
);
865 control
->SetSelected(TRUE
);
866 m_tabSelection
= control
->GetId();
868 OnTabActivate(control
->GetId(), oldTab
);
870 // Leave window refresh for the implementing window
875 // Move the selected tab to the bottom layer, if necessary,
876 // without calling app activation code
877 bool wxTabView::MoveSelectionTab(wxTabControl
*control
)
879 if (m_layers
.Number() == 0)
882 wxTabLayer
*firstLayer
= (wxTabLayer
*)m_layers
.First()->Data();
884 // Find what column this tab is at, so we can swap with the one at the bottom.
885 // If we're on the bottom layer, then no need to swap.
886 if (!firstLayer
->Member(control
))
890 wxNode
*thisNode
= FindTabNodeAndColumn(control
, &col
);
893 wxNode
*otherNode
= firstLayer
->Nth(col
);
897 // If this is already in the bottom layer, return now
898 if (otherNode
== thisNode
)
901 wxTabControl
*otherTab
= (wxTabControl
*)otherNode
->Data();
903 // We now have pointers to the tab to be changed to,
904 // and the tab on the first layer. Swap tab structures and
907 int thisX
= control
->GetX();
908 int thisY
= control
->GetY();
909 int thisColPos
= control
->GetColPosition();
910 int otherX
= otherTab
->GetX();
911 int otherY
= otherTab
->GetY();
912 int otherColPos
= otherTab
->GetColPosition();
914 control
->SetPosition(otherX
, otherY
);
915 control
->SetColPosition(otherColPos
);
916 otherTab
->SetPosition(thisX
, thisY
);
917 otherTab
->SetColPosition(thisColPos
);
919 // Swap the data for the nodes
920 thisNode
->SetData(otherTab
);
921 otherNode
->SetData(control
);
926 // Called when a tab is activated
927 void wxTabView::OnTabActivate(int /*activateId*/, int /*deactivateId*/)
931 void wxTabView::SetHighlightColour(const wxColour
& col
)
933 m_highlightColour
= col
;
934 m_highlightPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
937 void wxTabView::SetShadowColour(const wxColour
& col
)
939 m_shadowColour
= col
;
940 m_shadowPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
943 void wxTabView::SetBackgroundColour(const wxColour
& col
)
945 m_backgroundColour
= col
;
946 m_backgroundPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
947 m_backgroundBrush
= wxTheBrushList
->FindOrCreateBrush(col
, wxSOLID
);
950 void wxTabView::SetTabSelection(int sel
, bool activateTool
)
952 int oldSel
= m_tabSelection
;
953 wxTabControl
*control
= FindTabControlForId(sel
);
955 if (!OnTabPreActivate(sel
, oldSel
))
959 control
->SetSelected((sel
!= 0)); // TODO ??
962 wxMessageBox(_("Could not find tab for id"), _("Error"), wxOK
);
966 m_tabSelection
= sel
;
967 MoveSelectionTab(control
);
970 OnTabActivate(sel
, oldSel
);
973 // Find tab control for id
974 wxTabControl
*wxTabView::FindTabControlForId(int id
) const
976 wxNode
*node1
= m_layers
.First();
979 wxTabLayer
*layer
= (wxTabLayer
*)node1
->Data();
980 wxNode
*node2
= layer
->First();
983 wxTabControl
*control
= (wxTabControl
*)node2
->Data();
984 if (control
->GetId() == id
)
986 node2
= node2
->Next();
988 node1
= node1
->Next();
990 return (wxTabControl
*) NULL
;
993 // Find tab control for layer, position (starting from zero)
994 wxTabControl
*wxTabView::FindTabControlForPosition(int layer
, int position
) const
996 wxNode
*node1
= m_layers
.Nth(layer
);
998 return (wxTabControl
*) NULL
;
999 wxTabLayer
*tabLayer
= (wxTabLayer
*)node1
->Data();
1000 wxNode
*node2
= tabLayer
->Nth(position
);
1002 return (wxTabControl
*) NULL
;
1003 return (wxTabControl
*)node2
->Data();
1006 // Find the node and the column at which this control is positioned.
1007 wxNode
*wxTabView::FindTabNodeAndColumn(wxTabControl
*control
, int *col
) const
1009 wxNode
*node1
= m_layers
.First();
1012 wxTabLayer
*layer
= (wxTabLayer
*)node1
->Data();
1014 wxNode
*node2
= layer
->First();
1017 wxTabControl
*cnt
= (wxTabControl
*)node2
->Data();
1023 node2
= node2
->Next();
1026 node1
= node1
->Next();
1028 return (wxNode
*) NULL
;
1031 int wxTabView::CalculateTabWidth(int noTabs
, bool adjustView
)
1033 m_tabWidth
= (int)((m_tabViewRect
.width
- ((noTabs
- 1)*GetHorizontalTabSpacing()))/noTabs
);
1036 m_tabViewRect
.width
= noTabs
*m_tabWidth
+ ((noTabs
-1)*GetHorizontalTabSpacing());
1045 IMPLEMENT_CLASS(wxTabbedDialog
, wxDialog
)
1047 BEGIN_EVENT_TABLE(wxTabbedDialog
, wxDialog
)
1048 EVT_CLOSE(wxTabbedDialog::OnCloseWindow
)
1049 EVT_MOUSE_EVENTS(wxTabbedDialog::OnMouseEvent
)
1050 EVT_PAINT(wxTabbedDialog::OnPaint
)
1053 wxTabbedDialog::wxTabbedDialog(wxWindow
*parent
, wxWindowID id
,
1054 const wxString
& title
,
1055 const wxPoint
& pos
, const wxSize
& size
,
1056 long windowStyle
, const wxString
& name
):
1057 wxDialog(parent
, id
, title
, pos
, size
, windowStyle
, name
)
1059 m_tabView
= (wxTabView
*) NULL
;
1062 wxTabbedDialog::~wxTabbedDialog(void)
1068 void wxTabbedDialog::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
) )
1073 void wxTabbedDialog::OnMouseEvent(wxMouseEvent
& event
)
1076 m_tabView
->OnEvent(event
);
1079 void wxTabbedDialog::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1083 m_tabView
->Draw(dc
);
1090 IMPLEMENT_CLASS(wxTabbedPanel
, wxPanel
)
1092 BEGIN_EVENT_TABLE(wxTabbedPanel
, wxPanel
)
1093 EVT_MOUSE_EVENTS(wxTabbedPanel::OnMouseEvent
)
1094 EVT_PAINT(wxTabbedPanel::OnPaint
)
1097 wxTabbedPanel::wxTabbedPanel(wxWindow
*parent
, wxWindowID id
, const wxPoint
& pos
,
1098 const wxSize
& size
, long windowStyle
, const wxString
& name
):
1099 wxPanel(parent
, id
, pos
, size
, windowStyle
, name
)
1101 m_tabView
= (wxTabView
*) NULL
;
1104 wxTabbedPanel::~wxTabbedPanel(void)
1109 void wxTabbedPanel::OnMouseEvent(wxMouseEvent
& event
)
1112 m_tabView
->OnEvent(event
);
1115 void wxTabbedPanel::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1119 m_tabView
->Draw(dc
);
1126 IMPLEMENT_CLASS(wxPanelTabView
, wxTabView
)
1128 wxPanelTabView::wxPanelTabView(wxPanel
*pan
, long style
): wxTabView(style
), m_tabWindows(wxKEY_INTEGER
)
1131 m_currentWindow
= (wxWindow
*) NULL
;
1133 if (m_panel
->IsKindOf(CLASSINFO(wxTabbedDialog
)))
1134 ((wxTabbedDialog
*)m_panel
)->SetTabView(this);
1135 else if (m_panel
->IsKindOf(CLASSINFO(wxTabbedPanel
)))
1136 ((wxTabbedPanel
*)m_panel
)->SetTabView(this);
1141 wxPanelTabView::~wxPanelTabView(void)
1146 // Called when a tab is activated
1147 void wxPanelTabView::OnTabActivate(int activateId
, int deactivateId
)
1152 wxWindow
*oldWindow
= ((deactivateId
== -1) ? 0 : GetTabWindow(deactivateId
));
1153 wxWindow
*newWindow
= GetTabWindow(activateId
);
1156 oldWindow
->Show(FALSE
);
1158 newWindow
->Show(TRUE
);
1164 void wxPanelTabView::AddTabWindow(int id
, wxWindow
*window
)
1166 m_tabWindows
.Append((long)id
, window
);
1167 window
->Show(FALSE
);
1170 wxWindow
*wxPanelTabView::GetTabWindow(int id
) const
1172 wxNode
*node
= m_tabWindows
.Find((long)id
);
1174 return (wxWindow
*) NULL
;
1175 return (wxWindow
*)node
->Data();
1178 void wxPanelTabView::ClearWindows(bool deleteWindows
)
1181 m_tabWindows
.DeleteContents(TRUE
);
1182 m_tabWindows
.Clear();
1183 m_tabWindows
.DeleteContents(FALSE
);
1186 void wxPanelTabView::ShowWindowForTab(int id
)
1188 wxWindow
*newWindow
= GetTabWindow(id
);
1189 if (newWindow
== m_currentWindow
)
1191 if (m_currentWindow
)
1192 m_currentWindow
->Show(FALSE
);
1193 newWindow
->Show(TRUE
);
1194 newWindow
->Refresh();