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"
26 #include "wx/settings.h"
28 #include "wx/dcclient.h"
38 // not defined: use old, square tab implementation (fills in tabs)
39 // defined: use new, rounded tab implementation (doesn't colour in tabs)
40 // #define wxUSE_NEW_METHOD
42 IMPLEMENT_DYNAMIC_CLASS(wxTabControl
, wxObject
)
44 IMPLEMENT_DYNAMIC_CLASS(wxTabLayer
, wxList
)
46 wxTabControl::wxTabControl(wxTabView
*v
)
59 wxTabControl::~wxTabControl(void)
63 void wxTabControl::OnDraw(wxDC
& dc
, bool lastInRow
)
65 // Old, but in some ways better (drawing opaque tabs)
66 #ifndef wxUSE_NEW_METHOD
70 // Top-left of tab view area
71 int viewX
= m_view
->GetViewRect().x
;
72 int viewY
= m_view
->GetViewRect().y
;
74 // Top-left of tab control
75 int tabX
= GetX() + viewX
;
76 int tabY
= GetY() + viewY
;
80 tabHeightInc
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
84 dc
.SetPen(*wxTRANSPARENT_PEN
);
86 // Draw grey background
87 if (m_view
->GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR
)
89 dc
.SetBrush(*m_view
->GetBackgroundBrush());
91 // Add 1 because the pen is transparent. Under Motif, may be different.
93 dc
.DrawRectangle(tabX
, tabY
, (GetWidth()+1), (GetHeight() + tabHeightInc
));
95 dc
.DrawRectangle(tabX
, tabY
, (GetWidth()+1), (GetHeight() + 1 + tabHeightInc
));
99 // Draw highlight and shadow
100 dc
.SetPen(*m_view
->GetHighlightPen());
102 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
103 // a bit if the tab below happens to be selected. Check.
104 wxTabControl
*tabBeneath
= NULL
;
105 int subtractThis
= 0;
106 if (GetColPosition() > 0)
107 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition());
108 if (tabBeneath
&& tabBeneath
->IsSelected())
109 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
111 // Vertical highlight: if first tab, draw to bottom of view
112 if (tabX
== m_view
->GetViewRect().x
&& (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
113 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
));
114 else if (tabX
== m_view
->GetViewRect().x
)
115 // Not box drawing, just to top of view.
116 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
));
118 dc
.DrawLine(tabX
, tabY
, tabX
, (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
120 dc
.DrawLine(tabX
, tabY
, (tabX
+ GetWidth()), tabY
);
121 dc
.SetPen(*m_view
->GetShadowPen());
123 // Test if we're outside the right-hand edge of the view area
124 if (((tabX
+ GetWidth()) >= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
) && (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
126 int bottomY
= m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
+ GetY() + m_view
->GetTabHeight() + m_view
->GetTopMargin();
127 // Add a tab height since we wish to draw to the bottom of the view.
128 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
129 (tabX
+ GetWidth()), bottomY
);
131 // Calculate the far-right of the view, since we don't wish to
133 int rightOfView
= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
+ 1;
135 // Draw the horizontal bit to connect to the view rectangle
136 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
-1),
137 (tabX
+ GetWidth()), (bottomY
-1));
139 // Draw black line to emphasize shadow
140 dc
.SetPen(*wxBLACK_PEN
);
141 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1),
142 (tabX
+ GetWidth() + 1), bottomY
);
144 // Draw the horizontal bit to connect to the view rectangle
145 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
),
146 (tabX
+ GetWidth() + 1), (bottomY
));
152 // 25/5/97 UNLESS it's less than the max number of positions in this row
154 int topY
= m_view
->GetViewRect().y
- m_view
->GetTopMargin();
156 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Item(0)->GetData())->GetCount();
158 // Only down to the bottom of the tab, not to the top of the view
159 if ( GetRowPosition() < (maxPositions
- 1) )
160 topY
= tabY
+ GetHeight() + tabHeightInc
;
167 dc
.DrawLine((tabX
+ GetWidth()), tabY
, (tabX
+ GetWidth()), topY
);
168 // Draw black line to emphasize shadow
169 dc
.SetPen(*wxBLACK_PEN
);
170 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
175 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
176 // a bit if the tab below (and next col along) happens to be selected. Check.
177 wxTabControl
*tabBeneath
= NULL
;
178 int subtractThis
= 0;
179 if (GetColPosition() > 0)
180 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition() + 1);
181 if (tabBeneath
&& tabBeneath
->IsSelected())
182 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
188 // Draw only to next tab down.
189 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
190 (tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
192 // Draw black line to emphasize shadow
193 dc
.SetPen(*wxBLACK_PEN
);
194 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
195 (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
199 // Draw centered text
200 int textY
= tabY
+ m_view
->GetVerticalTabTextSpacing() + tabHeightInc
;
203 dc
.SetFont(* m_view
->GetSelectedTabFont());
205 dc
.SetFont(* GetFont());
207 wxColour
col(m_view
->GetTextColour());
208 dc
.SetTextForeground(col
);
209 dc
.SetBackgroundMode(wxTRANSPARENT
);
210 long textWidth
, textHeight
;
211 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
213 int textX
= (int)(tabX
+ (GetWidth() - textWidth
)/2.0);
214 if (textX
< (tabX
+ 2))
217 dc
.SetClippingRegion(tabX
, tabY
, GetWidth(), GetHeight());
218 dc
.DrawText(GetLabel(), textX
, textY
);
219 dc
.DestroyClippingRegion();
223 dc
.SetPen(*m_view
->GetHighlightPen());
225 // Draw white highlight from the tab's left side to the left hand edge of the view
226 dc
.DrawLine(m_view
->GetViewRect().x
, (tabY
+ GetHeight() + tabHeightInc
),
227 tabX
, (tabY
+ GetHeight() + tabHeightInc
));
229 // Draw white highlight from the tab's right side to the right hand edge of the view
230 dc
.DrawLine((tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
),
231 m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
, (tabY
+ GetHeight() + tabHeightInc
));
234 // New HEL version with rounder tabs
241 tabInc
= m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight();
243 int tabLeft
= GetX() + m_view
->GetViewRect().x
;
244 int tabTop
= GetY() + m_view
->GetViewRect().y
- tabInc
;
245 int tabRight
= tabLeft
+ m_view
->GetTabWidth();
246 int left
= m_view
->GetViewRect().x
;
247 int top
= tabTop
+ m_view
->GetTabHeight() + tabInc
;
248 int right
= left
+ m_view
->GetViewRect().width
;
249 int bottom
= top
+ m_view
->GetViewRect().height
;
253 // TAB is selected - draw TAB and the View's full outline
255 dc
.SetPen(*(m_view
->GetHighlightPen()));
258 pnts
[n
].x
= left
; pnts
[n
++].y
= bottom
;
259 pnts
[n
].x
= left
; pnts
[n
++].y
= top
;
260 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= top
;
261 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
262 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
263 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
264 dc
.DrawLines(n
, pnts
);
275 dc
.SetPen(*(m_view
->GetShadowPen()));
295 dc
.SetPen(*wxBLACK_PEN
);
337 // TAB is not selected - just draw TAB outline and RH edge
338 // if the TAB is the last in the row
340 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Item(0)->GetData())->GetCount();
341 wxTabControl
* tabBelow
= 0;
342 wxTabControl
* tabBelowRight
= 0;
343 if (GetColPosition() > 0)
345 tabBelow
= m_view
->FindTabControlForPosition(
346 GetColPosition() - 1,
350 if (!lastInRow
&& GetColPosition() > 0)
352 tabBelowRight
= m_view
->FindTabControlForPosition(
353 GetColPosition() - 1,
358 float raisedTop
= top
- m_view
->GetTabSelectionHeight() +
359 m_view
->GetTabHeight();
361 dc
.SetPen(*(m_view
->GetHighlightPen()));
367 if (tabBelow
&& tabBelow
->IsSelected())
369 pnts
[n
++].y
= (long)raisedTop
;
375 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
376 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
377 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
378 dc
.DrawLines(n
, pnts
);
380 dc
.SetPen(*(m_view
->GetShadowPen()));
381 if (GetRowPosition() >= maxPositions
- 1)
392 (tabRight
- m_view
->GetHorizontalTabOffset()),
398 if (tabBelowRight
&& tabBelowRight
->IsSelected())
418 dc
.SetPen(*wxBLACK_PEN
);
427 if (GetRowPosition() >= maxPositions
- 1)
429 // draw right hand edge to bottom of view
439 (tabRight
- m_view
->GetHorizontalTabOffset()),
445 // draw right hand edge of TAB
446 if (tabBelowRight
&& tabBelowRight
->IsSelected())
450 (long)(raisedTop
- 1),
467 // Draw centered text
468 dc
.SetPen(*wxBLACK_PEN
);
471 dc
.SetFont(*(m_view
->GetSelectedTabFont()));
475 dc
.SetFont(*(GetFont()));
478 wxColour
col(m_view
->GetTextColour());
479 dc
.SetTextForeground(col
);
480 dc
.SetBackgroundMode(wxTRANSPARENT
);
481 long textWidth
, textHeight
;
482 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
484 float textX
= (tabLeft
+ tabRight
- textWidth
) / 2;
485 float textY
= (tabInc
+ tabTop
+ m_view
->GetVerticalTabTextSpacing());
487 dc
.DrawText(GetLabel(), (long)textX
, (long)textY
);
491 bool wxTabControl::HitTest(int x
, int y
) const
493 // Top-left of tab control
494 int tabX1
= GetX() + m_view
->GetViewRect().x
;
495 int tabY1
= GetY() + m_view
->GetViewRect().y
;
498 int tabX2
= tabX1
+ GetWidth();
499 int tabY2
= tabY1
+ GetHeight();
501 if (x
>= tabX1
&& y
>= tabY1
&& x
<= tabX2
&& y
<= tabY2
)
507 IMPLEMENT_DYNAMIC_CLASS(wxTabView
, wxObject
)
509 wxTabView::wxTabView(long style
)
515 m_tabSelectionHeight
= m_tabHeight
+ 2;
517 m_tabHorizontalOffset
= 10;
518 m_tabHorizontalSpacing
= 2;
519 m_tabVerticalTextSpacing
= 3;
521 m_tabViewRect
.x
= 20;
522 m_tabViewRect
.y
= 20;
523 m_tabViewRect
.width
= 300;
524 m_tabViewRect
.x
= 300;
525 m_highlightColour
= *wxWHITE
;
526 m_shadowColour
= wxColour(128, 128, 128);
527 m_backgroundColour
= *wxLIGHT_GREY
;
528 m_textColour
= *wxBLACK
;
529 m_highlightPen
= wxWHITE_PEN
;
530 m_shadowPen
= wxGREY_PEN
;
531 m_backgroundPen
= wxLIGHT_GREY_PEN
;
532 m_backgroundBrush
= wxLIGHT_GREY_BRUSH
;
533 m_tabFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
534 m_tabSelectedFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
535 m_window
= (wxWindow
*) NULL
;
538 wxTabView::~wxTabView()
543 // Automatically positions tabs
544 // TODO: this should just add the tab to a list, and then
545 // a layout function (e.g. Realize) should be called when all tabs have been added.
546 // The view rect could easily change as the view window is resized.
547 wxTabControl
*wxTabView::AddTab(int id
, const wxString
& label
, wxTabControl
*existingTab
)
549 // First, find which layer we should be adding to.
550 wxNode
*node
= m_layers
.GetLast();
553 wxTabLayer
*newLayer
= new wxTabLayer
;
554 node
= m_layers
.Append(newLayer
);
556 // Check if adding another tab control would go off the
557 // right-hand edge of the layer.
558 wxTabLayer
*tabLayer
= (wxTabLayer
*)node
->GetData();
559 wxNode
*lastTabNode
= tabLayer
->GetLast();
562 wxTabControl
*lastTab
= (wxTabControl
*)lastTabNode
->GetData();
563 // Start another layer (row).
564 // Tricky choice: can't just check if will be overlapping the edge, because
565 // this happens anyway for 2nd and subsequent rows.
566 // Should check this for 1st row, and then subsequent rows should not exceed 1st
568 if (((tabLayer
== m_layers
.GetFirst()->GetData()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
569 > GetViewRect().width
)) ||
570 ((tabLayer
!= m_layers
.GetFirst()->GetData()) && (tabLayer
->GetCount() == ((wxTabLayer
*)m_layers
.GetFirst()->GetData())->GetCount())))
572 tabLayer
= new wxTabLayer
;
573 m_layers
.Append(tabLayer
);
574 lastTabNode
= (wxNode
*) NULL
;
577 int layer
= m_layers
.GetCount() - 1;
579 wxTabControl
*tabControl
= existingTab
;
581 tabControl
= OnCreateTabControl();
582 tabControl
->SetRowPosition(tabLayer
->GetCount());
583 tabControl
->SetColPosition(layer
);
585 wxTabControl
*lastTab
= (wxTabControl
*) NULL
;
587 lastTab
= (wxTabControl
*)lastTabNode
->GetData();
590 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
591 // Offset from view top-left
592 int horizontalOffset
= 0;
594 horizontalOffset
= layer
*GetHorizontalTabOffset();
596 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
598 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
599 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
600 tabControl
->SetId(id
);
601 tabControl
->SetLabel(label
);
602 tabControl
->SetFont(* GetTabFont());
604 tabLayer
->Append(tabControl
);
610 // Remove the tab without deleting the window
611 bool wxTabView::RemoveTab(int id
)
613 wxNode
*layerNode
= m_layers
.GetFirst();
616 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
617 wxNode
*tabNode
= layer
->GetFirst();
620 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
621 if (tab
->GetId() == id
)
623 if (id
== m_tabSelection
)
629 // The layout has changed
633 tabNode
= tabNode
->GetNext();
635 layerNode
= layerNode
->GetNext();
640 bool wxTabView::SetTabText(int id
, const wxString
& label
)
642 wxTabControl
* control
= FindTabControlForId(id
);
645 control
->SetLabel(label
);
649 wxString
wxTabView::GetTabText(int id
) const
651 wxTabControl
* control
= FindTabControlForId(id
);
653 return wxEmptyString
;
655 return control
->GetLabel();
658 // Returns the total height of the tabs component -- this may be several
659 // times the height of a tab, if there are several tab layers (rows).
660 int wxTabView::GetTotalTabHeight()
664 wxNode
*layerNode
= m_layers
.GetFirst();
667 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
668 wxNode
*tabNode
= layer
->GetFirst();
671 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
673 if (tab
->GetY() < minY
)
676 tabNode
= tabNode
->GetNext();
678 layerNode
= layerNode
->GetNext();
684 void wxTabView::ClearTabs(bool deleteTabs
)
686 wxNode
*layerNode
= m_layers
.GetFirst();
689 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
690 wxNode
*tabNode
= layer
->GetFirst();
693 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
696 wxNode
*next
= tabNode
->GetNext();
700 wxNode
*nextLayerNode
= layerNode
->GetNext();
703 layerNode
= nextLayerNode
;
710 // Layout tabs (optional, e.g. if resizing window)
711 void wxTabView::LayoutTabs(void)
713 // Make a list of the tab controls, deleting the wxTabLayers.
716 wxNode
*layerNode
= m_layers
.GetFirst();
719 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
720 wxNode
*tabNode
= layer
->GetFirst();
723 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
724 controls
.Append(tab
);
725 wxNode
*next
= tabNode
->GetNext();
729 wxNode
*nextLayerNode
= layerNode
->GetNext();
732 layerNode
= nextLayerNode
;
735 wxTabControl
*lastTab
= (wxTabControl
*) NULL
;
737 wxTabLayer
*currentLayer
= new wxTabLayer
;
738 m_layers
.Append(currentLayer
);
740 wxNode
*node
= controls
.GetFirst();
743 wxTabControl
*tabControl
= (wxTabControl
*)node
->GetData();
746 // Start another layer (row).
747 // Tricky choice: can't just check if will be overlapping the edge, because
748 // this happens anyway for 2nd and subsequent rows.
749 // Should check this for 1st row, and then subsequent rows should not exceed 1st
751 if (((currentLayer
== m_layers
.GetFirst()->GetData()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
752 > GetViewRect().width
)) ||
753 ((currentLayer
!= m_layers
.GetFirst()->GetData()) && (currentLayer
->GetCount() == ((wxTabLayer
*)m_layers
.GetFirst()->GetData())->GetCount())))
755 currentLayer
= new wxTabLayer
;
756 m_layers
.Append(currentLayer
);
757 lastTab
= (wxTabControl
*) NULL
;
761 int layer
= m_layers
.GetCount() - 1;
763 tabControl
->SetRowPosition(currentLayer
->GetCount());
764 tabControl
->SetColPosition(layer
);
767 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
768 // Offset from view top-left
769 int horizontalOffset
= 0;
771 horizontalOffset
= layer
*GetHorizontalTabOffset();
773 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
775 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
776 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
778 currentLayer
->Append(tabControl
);
779 lastTab
= tabControl
;
781 node
= node
->GetNext();
784 // Move the selected tab to the bottom
785 wxTabControl
*control
= FindTabControlForId(m_tabSelection
);
787 MoveSelectionTab(control
);
792 void wxTabView::Draw(wxDC
& dc
)
794 // Don't draw anything if there are no tabs.
795 if (GetNumberOfTabs() == 0)
798 // Draw top margin area (beneath tabs and above view area)
799 if (GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR
)
801 dc
.SetPen(*wxTRANSPARENT_PEN
);
802 dc
.SetBrush(*GetBackgroundBrush());
804 // Add 1 because the pen is transparent. Under Motif, may be different.
807 (m_tabViewRect
.y
- m_topMargin
),
808 (m_tabViewRect
.width
+ 1),
813 // Draw layers in reverse order
814 wxNode
*node
= m_layers
.GetLast();
817 wxTabLayer
*layer
= (wxTabLayer
*)node
->GetData();
818 wxNode
*node2
= layer
->GetFirst();
821 wxTabControl
*control
= (wxTabControl
*)node2
->GetData();
822 control
->OnDraw(dc
, (node2
->GetNext() == NULL
));
823 node2
= node2
->GetNext();
826 node
= node
->GetPrevious();
830 #ifndef wxUSE_NEW_METHOD
831 if (GetTabStyle() & wxTAB_STYLE_DRAW_BOX
)
833 dc
.SetPen(* GetShadowPen());
837 (GetViewRect().x
+ 1),
838 (GetViewRect().y
+ GetViewRect().height
),
839 (GetViewRect().x
+ GetViewRect().width
+ 1),
840 (GetViewRect().y
+ GetViewRect().height
)
845 (GetViewRect().x
+ GetViewRect().width
),
846 (GetViewRect().y
- GetTopMargin() + 1),
847 (GetViewRect().x
+ GetViewRect().width
),
848 (GetViewRect().y
+ GetViewRect().height
)
851 dc
.SetPen(* wxBLACK_PEN
);
856 (GetViewRect().y
+ GetViewRect().height
+ 1),
857 #if defined(__WXMOTIF__)
858 (GetViewRect().x
+ GetViewRect().width
+ 1),
860 (GetViewRect().x
+ GetViewRect().width
+ 2),
863 (GetViewRect().y
+ GetViewRect().height
+ 1)
868 (GetViewRect().x
+ GetViewRect().width
+ 1),
869 (GetViewRect().y
- GetTopMargin()),
870 (GetViewRect().x
+ GetViewRect().width
+ 1),
871 (GetViewRect().y
+ GetViewRect().height
+ 1)
877 // Process mouse event, return FALSE if we didn't process it
878 bool wxTabView::OnEvent(wxMouseEvent
& event
)
880 if (!event
.LeftDown())
884 event
.GetPosition(&x
, &y
);
886 wxTabControl
*hitControl
= (wxTabControl
*) NULL
;
888 wxNode
*node
= m_layers
.GetFirst();
891 wxTabLayer
*layer
= (wxTabLayer
*)node
->GetData();
892 wxNode
*node2
= layer
->GetFirst();
895 wxTabControl
*control
= (wxTabControl
*)node2
->GetData();
896 if (control
->HitTest((int)x
, (int)y
))
898 hitControl
= control
;
899 node
= (wxNode
*) NULL
;
900 node2
= (wxNode
*) NULL
;
903 node2
= node2
->GetNext();
907 node
= node
->GetNext();
913 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
915 if (hitControl
== currentTab
)
918 ChangeTab(hitControl
);
923 bool wxTabView::ChangeTab(wxTabControl
*control
)
925 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
928 oldTab
= currentTab
->GetId();
930 if (control
== currentTab
)
933 if (m_layers
.GetCount() == 0)
936 if (!OnTabPreActivate(control
->GetId(), oldTab
))
939 // Move the tab to the bottom
940 MoveSelectionTab(control
);
943 currentTab
->SetSelected(FALSE
);
945 control
->SetSelected(TRUE
);
946 m_tabSelection
= control
->GetId();
948 OnTabActivate(control
->GetId(), oldTab
);
950 // Leave window refresh for the implementing window
955 // Move the selected tab to the bottom layer, if necessary,
956 // without calling app activation code
957 bool wxTabView::MoveSelectionTab(wxTabControl
*control
)
959 if (m_layers
.GetCount() == 0)
962 wxTabLayer
*firstLayer
= (wxTabLayer
*)m_layers
.GetFirst()->GetData();
964 // Find what column this tab is at, so we can swap with the one at the bottom.
965 // If we're on the bottom layer, then no need to swap.
966 if (!firstLayer
->Member(control
))
970 wxNode
*thisNode
= FindTabNodeAndColumn(control
, &col
);
973 wxNode
*otherNode
= firstLayer
->Item(col
);
977 // If this is already in the bottom layer, return now
978 if (otherNode
== thisNode
)
981 wxTabControl
*otherTab
= (wxTabControl
*)otherNode
->GetData();
983 // We now have pointers to the tab to be changed to,
984 // and the tab on the first layer. Swap tab structures and
987 int thisX
= control
->GetX();
988 int thisY
= control
->GetY();
989 int thisColPos
= control
->GetColPosition();
990 int otherX
= otherTab
->GetX();
991 int otherY
= otherTab
->GetY();
992 int otherColPos
= otherTab
->GetColPosition();
994 control
->SetPosition(otherX
, otherY
);
995 control
->SetColPosition(otherColPos
);
996 otherTab
->SetPosition(thisX
, thisY
);
997 otherTab
->SetColPosition(thisColPos
);
999 // Swap the data for the nodes
1000 thisNode
->SetData(otherTab
);
1001 otherNode
->SetData(control
);
1006 // Called when a tab is activated
1007 void wxTabView::OnTabActivate(int /*activateId*/, int /*deactivateId*/)
1011 void wxTabView::SetHighlightColour(const wxColour
& col
)
1013 m_highlightColour
= col
;
1014 m_highlightPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
1017 void wxTabView::SetShadowColour(const wxColour
& col
)
1019 m_shadowColour
= col
;
1020 m_shadowPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
1023 void wxTabView::SetBackgroundColour(const wxColour
& col
)
1025 m_backgroundColour
= col
;
1026 m_backgroundPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
1027 m_backgroundBrush
= wxTheBrushList
->FindOrCreateBrush(col
, wxSOLID
);
1030 void wxTabView::SetTabSelection(int sel
, bool activateTool
)
1032 if ( sel
==m_tabSelection
)
1035 int oldSel
= m_tabSelection
;
1036 wxTabControl
*control
= FindTabControlForId(sel
);
1037 wxTabControl
*oldControl
= FindTabControlForId(m_tabSelection
);
1039 if (!OnTabPreActivate(sel
, oldSel
))
1043 control
->SetSelected((sel
!= -1)); // TODO ??
1046 wxFAIL_MSG(_("Could not find tab for id"));
1051 oldControl
->SetSelected(FALSE
);
1053 m_tabSelection
= sel
;
1056 MoveSelectionTab(control
);
1059 OnTabActivate(sel
, oldSel
);
1062 // Find tab control for id
1063 wxTabControl
*wxTabView::FindTabControlForId(int id
) const
1065 wxNode
*node1
= m_layers
.GetFirst();
1068 wxTabLayer
*layer
= (wxTabLayer
*)node1
->GetData();
1069 wxNode
*node2
= layer
->GetFirst();
1072 wxTabControl
*control
= (wxTabControl
*)node2
->GetData();
1073 if (control
->GetId() == id
)
1075 node2
= node2
->GetNext();
1077 node1
= node1
->GetNext();
1079 return (wxTabControl
*) NULL
;
1082 // Find tab control for layer, position (starting from zero)
1083 wxTabControl
*wxTabView::FindTabControlForPosition(int layer
, int position
) const
1085 wxNode
*node1
= m_layers
.Item(layer
);
1087 return (wxTabControl
*) NULL
;
1088 wxTabLayer
*tabLayer
= (wxTabLayer
*)node1
->GetData();
1089 wxNode
*node2
= tabLayer
->Item(position
);
1091 return (wxTabControl
*) NULL
;
1092 return (wxTabControl
*)node2
->GetData();
1095 // Find the node and the column at which this control is positioned.
1096 wxNode
*wxTabView::FindTabNodeAndColumn(wxTabControl
*control
, int *col
) const
1098 wxNode
*node1
= m_layers
.GetFirst();
1101 wxTabLayer
*layer
= (wxTabLayer
*)node1
->GetData();
1103 wxNode
*node2
= layer
->GetFirst();
1106 wxTabControl
*cnt
= (wxTabControl
*)node2
->GetData();
1112 node2
= node2
->GetNext();
1115 node1
= node1
->GetNext();
1117 return (wxNode
*) NULL
;
1120 int wxTabView::CalculateTabWidth(int noTabs
, bool adjustView
)
1122 m_tabWidth
= (int)((m_tabViewRect
.width
- ((noTabs
- 1)*GetHorizontalTabSpacing()))/noTabs
);
1125 m_tabViewRect
.width
= noTabs
*m_tabWidth
+ ((noTabs
-1)*GetHorizontalTabSpacing());
1134 IMPLEMENT_CLASS(wxTabbedDialog
, wxDialog
)
1136 BEGIN_EVENT_TABLE(wxTabbedDialog
, wxDialog
)
1137 EVT_CLOSE(wxTabbedDialog::OnCloseWindow
)
1138 EVT_MOUSE_EVENTS(wxTabbedDialog::OnMouseEvent
)
1139 EVT_PAINT(wxTabbedDialog::OnPaint
)
1142 wxTabbedDialog::wxTabbedDialog(wxWindow
*parent
, wxWindowID id
,
1143 const wxString
& title
,
1144 const wxPoint
& pos
, const wxSize
& size
,
1145 long windowStyle
, const wxString
& name
):
1146 wxDialog(parent
, id
, title
, pos
, size
, windowStyle
, name
)
1148 m_tabView
= (wxTabView
*) NULL
;
1151 wxTabbedDialog::~wxTabbedDialog(void)
1157 void wxTabbedDialog::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
) )
1162 void wxTabbedDialog::OnMouseEvent(wxMouseEvent
& event
)
1165 m_tabView
->OnEvent(event
);
1168 void wxTabbedDialog::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1172 m_tabView
->Draw(dc
);
1179 IMPLEMENT_CLASS(wxTabbedPanel
, wxPanel
)
1181 BEGIN_EVENT_TABLE(wxTabbedPanel
, wxPanel
)
1182 EVT_MOUSE_EVENTS(wxTabbedPanel::OnMouseEvent
)
1183 EVT_PAINT(wxTabbedPanel::OnPaint
)
1186 wxTabbedPanel::wxTabbedPanel(wxWindow
*parent
, wxWindowID id
, const wxPoint
& pos
,
1187 const wxSize
& size
, long windowStyle
, const wxString
& name
):
1188 wxPanel(parent
, id
, pos
, size
, windowStyle
, name
)
1190 m_tabView
= (wxTabView
*) NULL
;
1193 wxTabbedPanel::~wxTabbedPanel(void)
1198 void wxTabbedPanel::OnMouseEvent(wxMouseEvent
& event
)
1201 m_tabView
->OnEvent(event
);
1204 void wxTabbedPanel::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1208 m_tabView
->Draw(dc
);
1215 IMPLEMENT_CLASS(wxPanelTabView
, wxTabView
)
1217 wxPanelTabView::wxPanelTabView(wxPanel
*pan
, long style
): wxTabView(style
), m_tabWindows(wxKEY_INTEGER
)
1220 m_currentWindow
= (wxWindow
*) NULL
;
1222 if (m_panel
->IsKindOf(CLASSINFO(wxTabbedDialog
)))
1223 ((wxTabbedDialog
*)m_panel
)->SetTabView(this);
1224 else if (m_panel
->IsKindOf(CLASSINFO(wxTabbedPanel
)))
1225 ((wxTabbedPanel
*)m_panel
)->SetTabView(this);
1230 wxPanelTabView::~wxPanelTabView(void)
1235 // Called when a tab is activated
1236 void wxPanelTabView::OnTabActivate(int activateId
, int deactivateId
)
1241 wxWindow
*oldWindow
= ((deactivateId
== -1) ? 0 : GetTabWindow(deactivateId
));
1242 wxWindow
*newWindow
= GetTabWindow(activateId
);
1245 oldWindow
->Show(FALSE
);
1247 newWindow
->Show(TRUE
);
1253 void wxPanelTabView::AddTabWindow(int id
, wxWindow
*window
)
1255 m_tabWindows
.Append((long)id
, window
);
1256 window
->Show(FALSE
);
1259 wxWindow
*wxPanelTabView::GetTabWindow(int id
) const
1261 wxNode
*node
= m_tabWindows
.Find((long)id
);
1263 return (wxWindow
*) NULL
;
1264 return (wxWindow
*)node
->GetData();
1267 void wxPanelTabView::ClearWindows(bool deleteWindows
)
1270 m_tabWindows
.DeleteContents(TRUE
);
1271 m_tabWindows
.Clear();
1272 m_tabWindows
.DeleteContents(FALSE
);
1275 void wxPanelTabView::ShowWindowForTab(int id
)
1277 wxWindow
*newWindow
= GetTabWindow(id
);
1278 if (newWindow
== m_currentWindow
)
1280 if (m_currentWindow
)
1281 m_currentWindow
->Show(FALSE
);
1282 newWindow
->Show(TRUE
);
1283 newWindow
->Refresh();
1286 #endif // wxUSE_TAB_DIALOG