1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Generic tabbed dialogs
4 // Author: Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
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"
37 #include "wx/listimpl.cpp"
39 WX_DEFINE_LIST(wxTabLayerList
);
41 // not defined: use old, square tab implementation (fills in tabs)
42 // defined: use new, rounded tab implementation (doesn't colour in tabs)
43 // #define wxUSE_NEW_METHOD
45 IMPLEMENT_DYNAMIC_CLASS(wxTabControl
, wxObject
)
47 // IMPLEMENT_DYNAMIC_CLASS(wxTabLayer, wxList)
49 wxTabControl::wxTabControl(wxTabView
*v
)
62 wxTabControl::~wxTabControl(void)
66 void wxTabControl::OnDraw(wxDC
& dc
, bool lastInRow
)
68 // Old, but in some ways better (drawing opaque tabs)
69 #ifndef wxUSE_NEW_METHOD
73 // Top-left of tab view area
74 int viewX
= m_view
->GetViewRect().x
;
75 int viewY
= m_view
->GetViewRect().y
;
77 // Top-left of tab control
78 int tabX
= GetX() + viewX
;
79 int tabY
= GetY() + viewY
;
83 tabHeightInc
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
87 dc
.SetPen(*wxTRANSPARENT_PEN
);
89 // Draw grey background
90 if (m_view
->GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR
)
92 dc
.SetBrush(*m_view
->GetBackgroundBrush());
94 // Add 1 because the pen is transparent. Under Motif, may be different.
96 dc
.DrawRectangle(tabX
, tabY
, (GetWidth()+1), (GetHeight() + tabHeightInc
));
98 dc
.DrawRectangle(tabX
, tabY
, (GetWidth()+1), (GetHeight() + 1 + tabHeightInc
));
102 // Draw highlight and shadow
103 dc
.SetPen(*m_view
->GetHighlightPen());
105 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
106 // a bit if the tab below happens to be selected. Check.
107 wxTabControl
*tabBeneath
= NULL
;
108 int subtractThis
= 0;
109 if (GetColPosition() > 0)
110 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition());
111 if (tabBeneath
&& tabBeneath
->IsSelected())
112 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
114 // Vertical highlight: if first tab, draw to bottom of view
115 if (tabX
== m_view
->GetViewRect().x
&& (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
116 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
));
117 else if (tabX
== m_view
->GetViewRect().x
)
118 // Not box drawing, just to top of view.
119 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
));
121 dc
.DrawLine(tabX
, tabY
, tabX
, (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
123 dc
.DrawLine(tabX
, tabY
, (tabX
+ GetWidth()), tabY
);
124 dc
.SetPen(*m_view
->GetShadowPen());
126 // Test if we're outside the right-hand edge of the view area
127 if (((tabX
+ GetWidth()) >= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
) && (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
129 int bottomY
= m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
+ GetY() + m_view
->GetTabHeight() + m_view
->GetTopMargin();
130 // Add a tab height since we wish to draw to the bottom of the view.
131 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
132 (tabX
+ GetWidth()), bottomY
);
134 // Calculate the far-right of the view, since we don't wish to
136 int rightOfView
= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
+ 1;
138 // Draw the horizontal bit to connect to the view rectangle
139 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
-1),
140 (tabX
+ GetWidth()), (bottomY
-1));
142 // Draw black line to emphasize shadow
143 dc
.SetPen(*wxBLACK_PEN
);
144 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1),
145 (tabX
+ GetWidth() + 1), bottomY
);
147 // Draw the horizontal bit to connect to the view rectangle
148 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
),
149 (tabX
+ GetWidth() + 1), (bottomY
));
155 // 25/5/97 UNLESS it's less than the max number of positions in this row
157 int topY
= m_view
->GetViewRect().y
- m_view
->GetTopMargin();
159 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Item(0)->GetData())->GetCount();
161 // Only down to the bottom of the tab, not to the top of the view
162 if ( GetRowPosition() < (maxPositions
- 1) )
163 topY
= tabY
+ GetHeight() + tabHeightInc
;
170 dc
.DrawLine((tabX
+ GetWidth()), tabY
, (tabX
+ GetWidth()), topY
);
171 // Draw black line to emphasize shadow
172 dc
.SetPen(*wxBLACK_PEN
);
173 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
178 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
179 // a bit if the tab below (and next col along) happens to be selected. Check.
180 wxTabControl
*tabBeneath
= NULL
;
181 int subtractThis
= 0;
182 if (GetColPosition() > 0)
183 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition() + 1);
184 if (tabBeneath
&& tabBeneath
->IsSelected())
185 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
191 // Draw only to next tab down.
192 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
193 (tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
195 // Draw black line to emphasize shadow
196 dc
.SetPen(*wxBLACK_PEN
);
197 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
198 (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
202 // Draw centered text
203 int textY
= tabY
+ m_view
->GetVerticalTabTextSpacing() + tabHeightInc
;
206 dc
.SetFont(* m_view
->GetSelectedTabFont());
208 dc
.SetFont(* GetFont());
210 wxColour
col(m_view
->GetTextColour());
211 dc
.SetTextForeground(col
);
212 dc
.SetBackgroundMode(wxTRANSPARENT
);
213 long textWidth
, textHeight
;
214 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
216 int textX
= (int)(tabX
+ (GetWidth() - textWidth
)/2.0);
217 if (textX
< (tabX
+ 2))
220 dc
.SetClippingRegion(tabX
, tabY
, GetWidth(), GetHeight());
221 dc
.DrawText(GetLabel(), textX
, textY
);
222 dc
.DestroyClippingRegion();
226 dc
.SetPen(*m_view
->GetHighlightPen());
228 // Draw white highlight from the tab's left side to the left hand edge of the view
229 dc
.DrawLine(m_view
->GetViewRect().x
, (tabY
+ GetHeight() + tabHeightInc
),
230 tabX
, (tabY
+ GetHeight() + tabHeightInc
));
232 // Draw white highlight from the tab's right side to the right hand edge of the view
233 dc
.DrawLine((tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
),
234 m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
, (tabY
+ GetHeight() + tabHeightInc
));
237 // New HEL version with rounder tabs
244 tabInc
= m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight();
246 int tabLeft
= GetX() + m_view
->GetViewRect().x
;
247 int tabTop
= GetY() + m_view
->GetViewRect().y
- tabInc
;
248 int tabRight
= tabLeft
+ m_view
->GetTabWidth();
249 int left
= m_view
->GetViewRect().x
;
250 int top
= tabTop
+ m_view
->GetTabHeight() + tabInc
;
251 int right
= left
+ m_view
->GetViewRect().width
;
252 int bottom
= top
+ m_view
->GetViewRect().height
;
256 // TAB is selected - draw TAB and the View's full outline
258 dc
.SetPen(*(m_view
->GetHighlightPen()));
261 pnts
[n
].x
= left
; pnts
[n
++].y
= bottom
;
262 pnts
[n
].x
= left
; pnts
[n
++].y
= top
;
263 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= top
;
264 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
265 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
266 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
267 dc
.DrawLines(n
, pnts
);
278 dc
.SetPen(*(m_view
->GetShadowPen()));
298 dc
.SetPen(*wxBLACK_PEN
);
340 // TAB is not selected - just draw TAB outline and RH edge
341 // if the TAB is the last in the row
343 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Item(0)->GetData())->GetCount();
344 wxTabControl
* tabBelow
= 0;
345 wxTabControl
* tabBelowRight
= 0;
346 if (GetColPosition() > 0)
348 tabBelow
= m_view
->FindTabControlForPosition(
349 GetColPosition() - 1,
353 if (!lastInRow
&& GetColPosition() > 0)
355 tabBelowRight
= m_view
->FindTabControlForPosition(
356 GetColPosition() - 1,
361 float raisedTop
= top
- m_view
->GetTabSelectionHeight() +
362 m_view
->GetTabHeight();
364 dc
.SetPen(*(m_view
->GetHighlightPen()));
370 if (tabBelow
&& tabBelow
->IsSelected())
372 pnts
[n
++].y
= (long)raisedTop
;
378 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
379 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
380 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
381 dc
.DrawLines(n
, pnts
);
383 dc
.SetPen(*(m_view
->GetShadowPen()));
384 if (GetRowPosition() >= maxPositions
- 1)
395 (tabRight
- m_view
->GetHorizontalTabOffset()),
401 if (tabBelowRight
&& tabBelowRight
->IsSelected())
421 dc
.SetPen(*wxBLACK_PEN
);
430 if (GetRowPosition() >= maxPositions
- 1)
432 // draw right hand edge to bottom of view
442 (tabRight
- m_view
->GetHorizontalTabOffset()),
448 // draw right hand edge of TAB
449 if (tabBelowRight
&& tabBelowRight
->IsSelected())
453 (long)(raisedTop
- 1),
470 // Draw centered text
471 dc
.SetPen(*wxBLACK_PEN
);
474 dc
.SetFont(*(m_view
->GetSelectedTabFont()));
478 dc
.SetFont(*(GetFont()));
481 wxColour
col(m_view
->GetTextColour());
482 dc
.SetTextForeground(col
);
483 dc
.SetBackgroundMode(wxTRANSPARENT
);
484 long textWidth
, textHeight
;
485 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
487 float textX
= (tabLeft
+ tabRight
- textWidth
) / 2;
488 float textY
= (tabInc
+ tabTop
+ m_view
->GetVerticalTabTextSpacing());
490 dc
.DrawText(GetLabel(), (long)textX
, (long)textY
);
494 bool wxTabControl::HitTest(int x
, int y
) const
496 // Top-left of tab control
497 int tabX1
= GetX() + m_view
->GetViewRect().x
;
498 int tabY1
= GetY() + m_view
->GetViewRect().y
;
501 int tabX2
= tabX1
+ GetWidth();
502 int tabY2
= tabY1
+ GetHeight();
504 if (x
>= tabX1
&& y
>= tabY1
&& x
<= tabX2
&& y
<= tabY2
)
510 IMPLEMENT_DYNAMIC_CLASS(wxTabView
, wxObject
)
512 wxTabView::wxTabView(long style
)
518 m_tabSelectionHeight
= m_tabHeight
+ 2;
520 m_tabHorizontalOffset
= 10;
521 m_tabHorizontalSpacing
= 2;
522 m_tabVerticalTextSpacing
= 3;
524 m_tabViewRect
.x
= 20;
525 m_tabViewRect
.y
= 20;
526 m_tabViewRect
.width
= 300;
527 m_tabViewRect
.x
= 300;
528 m_highlightColour
= *wxWHITE
;
529 m_shadowColour
= wxColour(128, 128, 128);
530 m_backgroundColour
= *wxLIGHT_GREY
;
531 m_textColour
= *wxBLACK
;
532 m_highlightPen
= wxWHITE_PEN
;
533 m_shadowPen
= wxGREY_PEN
;
534 m_backgroundPen
= wxLIGHT_GREY_PEN
;
535 m_backgroundBrush
= wxLIGHT_GREY_BRUSH
;
536 m_tabFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
537 m_tabSelectedFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
538 m_window
= (wxWindow
*) NULL
;
541 wxTabView::~wxTabView()
546 // Automatically positions tabs
547 // TODO: this should just add the tab to a list, and then
548 // a layout function (e.g. Realize) should be called when all tabs have been added.
549 // The view rect could easily change as the view window is resized.
550 wxTabControl
*wxTabView::AddTab(int id
, const wxString
& label
, wxTabControl
*existingTab
)
552 // First, find which layer we should be adding to.
553 wxTabLayerList::compatibility_iterator node
= m_layers
.GetLast();
556 wxTabLayer
*newLayer
= new wxTabLayer
;
557 node
= m_layers
.Append(newLayer
);
559 // Check if adding another tab control would go off the
560 // right-hand edge of the layer.
561 wxTabLayer
*tabLayer
= (wxTabLayer
*)node
->GetData();
562 wxList::compatibility_iterator lastTabNode
= tabLayer
->GetLast();
565 wxTabControl
*lastTab
= (wxTabControl
*)lastTabNode
->GetData();
566 // Start another layer (row).
567 // Tricky choice: can't just check if will be overlapping the edge, because
568 // this happens anyway for 2nd and subsequent rows.
569 // Should check this for 1st row, and then subsequent rows should not exceed 1st
571 if (((tabLayer
== m_layers
.GetFirst()->GetData()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
572 > GetViewRect().width
)) ||
573 ((tabLayer
!= m_layers
.GetFirst()->GetData()) && (tabLayer
->GetCount() == ((wxTabLayer
*)m_layers
.GetFirst()->GetData())->GetCount())))
575 tabLayer
= new wxTabLayer
;
576 m_layers
.Append(tabLayer
);
577 lastTabNode
= wxList::compatibility_iterator();
580 int layer
= m_layers
.GetCount() - 1;
582 wxTabControl
*tabControl
= existingTab
;
584 tabControl
= OnCreateTabControl();
585 tabControl
->SetRowPosition(tabLayer
->GetCount());
586 tabControl
->SetColPosition(layer
);
588 wxTabControl
*lastTab
= (wxTabControl
*) NULL
;
590 lastTab
= (wxTabControl
*)lastTabNode
->GetData();
593 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
594 // Offset from view top-left
595 int horizontalOffset
= 0;
597 horizontalOffset
= layer
*GetHorizontalTabOffset();
599 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
601 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
602 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
603 tabControl
->SetId(id
);
604 tabControl
->SetLabel(label
);
605 tabControl
->SetFont(* GetTabFont());
607 tabLayer
->Append(tabControl
);
613 // Remove the tab without deleting the window
614 bool wxTabView::RemoveTab(int id
)
616 wxTabLayerList::compatibility_iterator layerNode
= m_layers
.GetFirst();
619 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
620 wxList::compatibility_iterator tabNode
= layer
->GetFirst();
623 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
624 if (tab
->GetId() == id
)
626 if (id
== m_tabSelection
)
629 layer
->Erase(tabNode
);
632 // The layout has changed
636 tabNode
= tabNode
->GetNext();
638 layerNode
= layerNode
->GetNext();
643 bool wxTabView::SetTabText(int id
, const wxString
& label
)
645 wxTabControl
* control
= FindTabControlForId(id
);
648 control
->SetLabel(label
);
652 wxString
wxTabView::GetTabText(int id
) const
654 wxTabControl
* control
= FindTabControlForId(id
);
656 return wxEmptyString
;
658 return control
->GetLabel();
661 // Returns the total height of the tabs component -- this may be several
662 // times the height of a tab, if there are several tab layers (rows).
663 int wxTabView::GetTotalTabHeight()
667 wxTabLayerList::compatibility_iterator layerNode
= m_layers
.GetFirst();
670 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
671 wxList::compatibility_iterator tabNode
= layer
->GetFirst();
674 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
676 if (tab
->GetY() < minY
)
679 tabNode
= tabNode
->GetNext();
681 layerNode
= layerNode
->GetNext();
687 void wxTabView::ClearTabs(bool deleteTabs
)
689 wxTabLayerList::compatibility_iterator layerNode
= m_layers
.GetFirst();
692 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
693 wxList::compatibility_iterator tabNode
= layer
->GetFirst();
696 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
699 wxList::compatibility_iterator next
= tabNode
->GetNext();
700 layer
->Erase(tabNode
);
703 wxTabLayerList::compatibility_iterator nextLayerNode
= layerNode
->GetNext();
705 m_layers
.Erase(layerNode
);
706 layerNode
= nextLayerNode
;
713 // Layout tabs (optional, e.g. if resizing window)
714 void wxTabView::LayoutTabs(void)
716 // Make a list of the tab controls, deleting the wxTabLayers.
719 wxTabLayerList::compatibility_iterator layerNode
= m_layers
.GetFirst();
722 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
723 wxList::compatibility_iterator tabNode
= layer
->GetFirst();
726 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
727 controls
.Append(tab
);
728 wxList::compatibility_iterator next
= tabNode
->GetNext();
729 layer
->Erase(tabNode
);
732 wxTabLayerList::compatibility_iterator nextLayerNode
= layerNode
->GetNext();
734 m_layers
.Erase(layerNode
);
735 layerNode
= nextLayerNode
;
738 wxTabControl
*lastTab
= (wxTabControl
*) NULL
;
740 wxTabLayer
*currentLayer
= new wxTabLayer
;
741 m_layers
.Append(currentLayer
);
743 wxList::compatibility_iterator node
= controls
.GetFirst();
746 wxTabControl
*tabControl
= (wxTabControl
*)node
->GetData();
749 // Start another layer (row).
750 // Tricky choice: can't just check if will be overlapping the edge, because
751 // this happens anyway for 2nd and subsequent rows.
752 // Should check this for 1st row, and then subsequent rows should not exceed 1st
754 if (((currentLayer
== m_layers
.GetFirst()->GetData()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
755 > GetViewRect().width
)) ||
756 ((currentLayer
!= m_layers
.GetFirst()->GetData()) && (currentLayer
->GetCount() == ((wxTabLayer
*)m_layers
.GetFirst()->GetData())->GetCount())))
758 currentLayer
= new wxTabLayer
;
759 m_layers
.Append(currentLayer
);
760 lastTab
= (wxTabControl
*) NULL
;
764 int layer
= m_layers
.GetCount() - 1;
766 tabControl
->SetRowPosition(currentLayer
->GetCount());
767 tabControl
->SetColPosition(layer
);
770 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
771 // Offset from view top-left
772 int horizontalOffset
= 0;
774 horizontalOffset
= layer
*GetHorizontalTabOffset();
776 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
778 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
779 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
781 currentLayer
->Append(tabControl
);
782 lastTab
= tabControl
;
784 node
= node
->GetNext();
787 // Move the selected tab to the bottom
788 wxTabControl
*control
= FindTabControlForId(m_tabSelection
);
790 MoveSelectionTab(control
);
795 void wxTabView::Draw(wxDC
& dc
)
797 // Don't draw anything if there are no tabs.
798 if (GetNumberOfTabs() == 0)
801 // Draw top margin area (beneath tabs and above view area)
802 if (GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR
)
804 dc
.SetPen(*wxTRANSPARENT_PEN
);
805 dc
.SetBrush(*GetBackgroundBrush());
807 // Add 1 because the pen is transparent. Under Motif, may be different.
810 (m_tabViewRect
.y
- m_topMargin
),
811 (m_tabViewRect
.width
+ 1),
816 // Draw layers in reverse order
817 wxTabLayerList::compatibility_iterator node
= m_layers
.GetLast();
820 wxTabLayer
*layer
= (wxTabLayer
*)node
->GetData();
821 wxList::compatibility_iterator node2
= layer
->GetFirst();
824 wxTabControl
*control
= (wxTabControl
*)node2
->GetData();
825 control
->OnDraw(dc
, (!node2
->GetNext()));
826 node2
= node2
->GetNext();
829 node
= node
->GetPrevious();
833 #ifndef wxUSE_NEW_METHOD
834 if (GetTabStyle() & wxTAB_STYLE_DRAW_BOX
)
836 dc
.SetPen(* GetShadowPen());
840 (GetViewRect().x
+ 1),
841 (GetViewRect().y
+ GetViewRect().height
),
842 (GetViewRect().x
+ GetViewRect().width
+ 1),
843 (GetViewRect().y
+ GetViewRect().height
)
848 (GetViewRect().x
+ GetViewRect().width
),
849 (GetViewRect().y
- GetTopMargin() + 1),
850 (GetViewRect().x
+ GetViewRect().width
),
851 (GetViewRect().y
+ GetViewRect().height
)
854 dc
.SetPen(* wxBLACK_PEN
);
859 (GetViewRect().y
+ GetViewRect().height
+ 1),
860 #if defined(__WXMOTIF__)
861 (GetViewRect().x
+ GetViewRect().width
+ 1),
863 (GetViewRect().x
+ GetViewRect().width
+ 2),
866 (GetViewRect().y
+ GetViewRect().height
+ 1)
871 (GetViewRect().x
+ GetViewRect().width
+ 1),
872 (GetViewRect().y
- GetTopMargin()),
873 (GetViewRect().x
+ GetViewRect().width
+ 1),
874 (GetViewRect().y
+ GetViewRect().height
+ 1)
880 // Process mouse event, return false if we didn't process it
881 bool wxTabView::OnEvent(wxMouseEvent
& event
)
883 if (!event
.LeftDown())
887 event
.GetPosition(&x
, &y
);
889 wxTabControl
*hitControl
= (wxTabControl
*) NULL
;
891 wxTabLayerList::compatibility_iterator node
= m_layers
.GetFirst();
894 wxTabLayer
*layer
= (wxTabLayer
*)node
->GetData();
895 wxList::compatibility_iterator node2
= layer
->GetFirst();
898 wxTabControl
*control
= (wxTabControl
*)node2
->GetData();
899 if (control
->HitTest((int)x
, (int)y
))
901 hitControl
= control
;
902 node
= wxTabLayerList::compatibility_iterator();
903 node2
= wxList::compatibility_iterator();
906 node2
= node2
->GetNext();
910 node
= node
->GetNext();
916 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
918 if (hitControl
== currentTab
)
921 ChangeTab(hitControl
);
926 bool wxTabView::ChangeTab(wxTabControl
*control
)
928 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
931 oldTab
= currentTab
->GetId();
933 if (control
== currentTab
)
936 if (m_layers
.GetCount() == 0)
939 if (!OnTabPreActivate(control
->GetId(), oldTab
))
942 // Move the tab to the bottom
943 MoveSelectionTab(control
);
946 currentTab
->SetSelected(false);
948 control
->SetSelected(true);
949 m_tabSelection
= control
->GetId();
951 OnTabActivate(control
->GetId(), oldTab
);
953 // Leave window refresh for the implementing window
958 // Move the selected tab to the bottom layer, if necessary,
959 // without calling app activation code
960 bool wxTabView::MoveSelectionTab(wxTabControl
*control
)
962 if (m_layers
.GetCount() == 0)
965 wxTabLayer
*firstLayer
= (wxTabLayer
*)m_layers
.GetFirst()->GetData();
967 // Find what column this tab is at, so we can swap with the one at the bottom.
968 // If we're on the bottom layer, then no need to swap.
969 if (!firstLayer
->Member(control
))
973 wxList::compatibility_iterator thisNode
= FindTabNodeAndColumn(control
, &col
);
976 wxList::compatibility_iterator otherNode
= firstLayer
->Item(col
);
980 // If this is already in the bottom layer, return now
981 if (otherNode
== thisNode
)
984 wxTabControl
*otherTab
= (wxTabControl
*)otherNode
->GetData();
986 // We now have pointers to the tab to be changed to,
987 // and the tab on the first layer. Swap tab structures and
990 int thisX
= control
->GetX();
991 int thisY
= control
->GetY();
992 int thisColPos
= control
->GetColPosition();
993 int otherX
= otherTab
->GetX();
994 int otherY
= otherTab
->GetY();
995 int otherColPos
= otherTab
->GetColPosition();
997 control
->SetPosition(otherX
, otherY
);
998 control
->SetColPosition(otherColPos
);
999 otherTab
->SetPosition(thisX
, thisY
);
1000 otherTab
->SetColPosition(thisColPos
);
1002 // Swap the data for the nodes
1003 thisNode
->SetData(otherTab
);
1004 otherNode
->SetData(control
);
1009 // Called when a tab is activated
1010 void wxTabView::OnTabActivate(int /*activateId*/, int /*deactivateId*/)
1014 void wxTabView::SetHighlightColour(const wxColour
& col
)
1016 m_highlightColour
= col
;
1017 m_highlightPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
1020 void wxTabView::SetShadowColour(const wxColour
& col
)
1022 m_shadowColour
= col
;
1023 m_shadowPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
1026 void wxTabView::SetBackgroundColour(const wxColour
& col
)
1028 m_backgroundColour
= col
;
1029 m_backgroundPen
= wxThePenList
->FindOrCreatePen(col
, 1, wxSOLID
);
1030 m_backgroundBrush
= wxTheBrushList
->FindOrCreateBrush(col
, wxSOLID
);
1033 void wxTabView::SetTabSelection(int sel
, bool activateTool
)
1035 if ( sel
==m_tabSelection
)
1038 int oldSel
= m_tabSelection
;
1039 wxTabControl
*control
= FindTabControlForId(sel
);
1040 wxTabControl
*oldControl
= FindTabControlForId(m_tabSelection
);
1042 if (!OnTabPreActivate(sel
, oldSel
))
1046 control
->SetSelected((sel
!= -1)); // TODO ??
1049 wxFAIL_MSG(_("Could not find tab for id"));
1054 oldControl
->SetSelected(false);
1056 m_tabSelection
= sel
;
1059 MoveSelectionTab(control
);
1062 OnTabActivate(sel
, oldSel
);
1065 // Find tab control for id
1066 wxTabControl
*wxTabView::FindTabControlForId(int id
) const
1068 wxTabLayerList::compatibility_iterator node1
= m_layers
.GetFirst();
1071 wxTabLayer
*layer
= (wxTabLayer
*)node1
->GetData();
1072 wxList::compatibility_iterator node2
= layer
->GetFirst();
1075 wxTabControl
*control
= (wxTabControl
*)node2
->GetData();
1076 if (control
->GetId() == id
)
1078 node2
= node2
->GetNext();
1080 node1
= node1
->GetNext();
1082 return (wxTabControl
*) NULL
;
1085 // Find tab control for layer, position (starting from zero)
1086 wxTabControl
*wxTabView::FindTabControlForPosition(int layer
, int position
) const
1088 wxTabLayerList::compatibility_iterator node1
= m_layers
.Item(layer
);
1090 return (wxTabControl
*) NULL
;
1091 wxTabLayer
*tabLayer
= (wxTabLayer
*)node1
->GetData();
1092 wxList::compatibility_iterator node2
= tabLayer
->Item(position
);
1094 return (wxTabControl
*) NULL
;
1095 return (wxTabControl
*)node2
->GetData();
1098 // Find the node and the column at which this control is positioned.
1099 wxList::compatibility_iterator
wxTabView::FindTabNodeAndColumn(wxTabControl
*control
, int *col
) const
1101 wxTabLayerList::compatibility_iterator node1
= m_layers
.GetFirst();
1104 wxTabLayer
*layer
= (wxTabLayer
*)node1
->GetData();
1106 wxList::compatibility_iterator node2
= layer
->GetFirst();
1109 wxTabControl
*cnt
= (wxTabControl
*)node2
->GetData();
1115 node2
= node2
->GetNext();
1118 node1
= node1
->GetNext();
1120 return wxList::compatibility_iterator();
1123 int wxTabView::CalculateTabWidth(int noTabs
, bool adjustView
)
1125 m_tabWidth
= (int)((m_tabViewRect
.width
- ((noTabs
- 1)*GetHorizontalTabSpacing()))/noTabs
);
1128 m_tabViewRect
.width
= noTabs
*m_tabWidth
+ ((noTabs
-1)*GetHorizontalTabSpacing());
1137 IMPLEMENT_CLASS(wxTabbedDialog
, wxDialog
)
1139 BEGIN_EVENT_TABLE(wxTabbedDialog
, wxDialog
)
1140 EVT_CLOSE(wxTabbedDialog::OnCloseWindow
)
1141 EVT_MOUSE_EVENTS(wxTabbedDialog::OnMouseEvent
)
1142 EVT_PAINT(wxTabbedDialog::OnPaint
)
1145 wxTabbedDialog::wxTabbedDialog(wxWindow
*parent
, wxWindowID id
,
1146 const wxString
& title
,
1147 const wxPoint
& pos
, const wxSize
& size
,
1148 long windowStyle
, const wxString
& name
):
1149 wxDialog(parent
, id
, title
, pos
, size
, windowStyle
, name
)
1151 m_tabView
= (wxTabView
*) NULL
;
1154 wxTabbedDialog::~wxTabbedDialog(void)
1160 void wxTabbedDialog::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
) )
1165 void wxTabbedDialog::OnMouseEvent(wxMouseEvent
& event
)
1168 m_tabView
->OnEvent(event
);
1171 void wxTabbedDialog::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1175 m_tabView
->Draw(dc
);
1182 IMPLEMENT_CLASS(wxTabbedPanel
, wxPanel
)
1184 BEGIN_EVENT_TABLE(wxTabbedPanel
, wxPanel
)
1185 EVT_MOUSE_EVENTS(wxTabbedPanel::OnMouseEvent
)
1186 EVT_PAINT(wxTabbedPanel::OnPaint
)
1189 wxTabbedPanel::wxTabbedPanel(wxWindow
*parent
, wxWindowID id
, const wxPoint
& pos
,
1190 const wxSize
& size
, long windowStyle
, const wxString
& name
):
1191 wxPanel(parent
, id
, pos
, size
, windowStyle
, name
)
1193 m_tabView
= (wxTabView
*) NULL
;
1196 wxTabbedPanel::~wxTabbedPanel(void)
1201 void wxTabbedPanel::OnMouseEvent(wxMouseEvent
& event
)
1204 m_tabView
->OnEvent(event
);
1207 void wxTabbedPanel::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1211 m_tabView
->Draw(dc
);
1218 IMPLEMENT_CLASS(wxPanelTabView
, wxTabView
)
1220 wxPanelTabView::wxPanelTabView(wxPanel
*pan
, long style
)
1224 m_currentWindow
= (wxWindow
*) NULL
;
1226 if (m_panel
->IsKindOf(CLASSINFO(wxTabbedDialog
)))
1227 ((wxTabbedDialog
*)m_panel
)->SetTabView(this);
1228 else if (m_panel
->IsKindOf(CLASSINFO(wxTabbedPanel
)))
1229 ((wxTabbedPanel
*)m_panel
)->SetTabView(this);
1234 wxPanelTabView::~wxPanelTabView(void)
1239 // Called when a tab is activated
1240 void wxPanelTabView::OnTabActivate(int activateId
, int deactivateId
)
1245 wxWindow
*oldWindow
= ((deactivateId
== -1) ? 0 : GetTabWindow(deactivateId
));
1246 wxWindow
*newWindow
= GetTabWindow(activateId
);
1249 oldWindow
->Show(false);
1251 newWindow
->Show(true);
1257 void wxPanelTabView::AddTabWindow(int id
, wxWindow
*window
)
1259 wxASSERT(m_tabWindows
.find(id
) == m_tabWindows
.end());
1260 m_tabWindows
[id
] = window
;
1261 window
->Show(false);
1264 wxWindow
*wxPanelTabView::GetTabWindow(int id
) const
1266 wxIntToWindowHashMap::const_iterator it
= m_tabWindows
.find(id
);
1267 return it
== m_tabWindows
.end() ? NULL
: it
->second
;
1270 void wxPanelTabView::ClearWindows(bool deleteWindows
)
1273 WX_CLEAR_HASH_MAP(wxIntToWindowHashMap
, m_tabWindows
);
1274 m_tabWindows
.clear();
1277 void wxPanelTabView::ShowWindowForTab(int id
)
1279 wxWindow
*newWindow
= GetTabWindow(id
);
1280 if (newWindow
== m_currentWindow
)
1282 if (m_currentWindow
)
1283 m_currentWindow
->Show(false);
1284 newWindow
->Show(true);
1285 newWindow
->Refresh();
1288 #endif // wxUSE_TAB_DIALOG