1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/tabg.cpp
3 // Purpose: Generic tabbed dialogs; used by wxMotif's wxNotebook
4 // Author: Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
20 #include "wx/settings.h"
22 #include "wx/dcclient.h"
30 #include "wx/generic/tabg.h"
31 #include "wx/listimpl.cpp"
33 WX_DEFINE_LIST(wxTabLayerList
)
35 // not defined: use old, square tab implementation (fills in tabs)
36 // defined: use new, rounded tab implementation (doesn't colour in tabs)
37 // #define wxUSE_NEW_METHOD
39 IMPLEMENT_DYNAMIC_CLASS(wxTabControl
, wxObject
)
41 // IMPLEMENT_DYNAMIC_CLASS(wxTabLayer, wxList)
43 wxTabControl::wxTabControl(wxTabView
*v
)
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 if(m_view
->GetBackgroundBrush())
87 dc
.SetBrush(*m_view
->GetBackgroundBrush());
89 // Add 1 because the pen is transparent. Under Motif, may be different.
91 dc
.DrawRectangle(tabX
, tabY
, (GetWidth()+1), (GetHeight() + tabHeightInc
));
93 dc
.DrawRectangle(tabX
, tabY
, (GetWidth()+1), (GetHeight() + 1 + tabHeightInc
));
97 // Draw highlight and shadow
98 dc
.SetPen(*m_view
->GetHighlightPen());
100 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
101 // a bit if the tab below happens to be selected. Check.
102 wxTabControl
*tabBeneath
= NULL
;
103 int subtractThis
= 0;
104 if (GetColPosition() > 0)
105 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition());
106 if (tabBeneath
&& tabBeneath
->IsSelected())
107 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
109 // Vertical highlight: if first tab, draw to bottom of view
110 if (tabX
== m_view
->GetViewRect().x
&& (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
111 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
));
112 else if (tabX
== m_view
->GetViewRect().x
)
113 // Not box drawing, just to top of view.
114 dc
.DrawLine(tabX
, tabY
, tabX
, (m_view
->GetViewRect().y
));
116 dc
.DrawLine(tabX
, tabY
, tabX
, (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
118 dc
.DrawLine(tabX
, tabY
, (tabX
+ GetWidth()), tabY
);
119 dc
.SetPen(*m_view
->GetShadowPen());
121 // Test if we're outside the right-hand edge of the view area
122 if (((tabX
+ GetWidth()) >= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
) && (m_view
->GetTabStyle() & wxTAB_STYLE_DRAW_BOX
))
124 int bottomY
= m_view
->GetViewRect().y
+ m_view
->GetViewRect().height
+ GetY() + m_view
->GetTabHeight() + m_view
->GetTopMargin();
125 // Add a tab height since we wish to draw to the bottom of the view.
126 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
127 (tabX
+ GetWidth()), bottomY
);
129 // Calculate the far-right of the view, since we don't wish to
131 int rightOfView
= m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
+ 1;
133 // Draw the horizontal bit to connect to the view rectangle
134 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
-1),
135 (tabX
+ GetWidth()), (bottomY
-1));
137 // Draw black line to emphasize shadow
138 dc
.SetPen(*wxBLACK_PEN
);
139 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1),
140 (tabX
+ GetWidth() + 1), bottomY
);
142 // Draw the horizontal bit to connect to the view rectangle
143 dc
.DrawLine((wxMax((tabX
+ GetWidth() - m_view
->GetHorizontalTabOffset()), rightOfView
)), (bottomY
),
144 (tabX
+ GetWidth() + 1), (bottomY
));
150 // 25/5/97 UNLESS it's less than the max number of positions in this row
152 int topY
= m_view
->GetViewRect().y
- m_view
->GetTopMargin();
154 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Item(0)->GetData())->GetCount();
156 // Only down to the bottom of the tab, not to the top of the view
157 if ( GetRowPosition() < (maxPositions
- 1) )
158 topY
= tabY
+ GetHeight() + tabHeightInc
;
165 dc
.DrawLine((tabX
+ GetWidth()), tabY
, (tabX
+ GetWidth()), topY
);
166 // Draw black line to emphasize shadow
167 dc
.SetPen(*wxBLACK_PEN
);
168 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
173 // Calculate the top of the tab beneath. It's the height of the tab, MINUS
174 // a bit if the tab below (and next col along) happens to be selected. Check.
175 wxTabControl
*tabBeneath
= NULL
;
176 int subtractThis
= 0;
177 if (GetColPosition() > 0)
178 tabBeneath
= m_view
->FindTabControlForPosition(GetColPosition() - 1, GetRowPosition() + 1);
179 if (tabBeneath
&& tabBeneath
->IsSelected())
180 subtractThis
= (m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight());
186 // Draw only to next tab down.
187 dc
.DrawLine((tabX
+ GetWidth()), tabY
,
188 (tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
190 // Draw black line to emphasize shadow
191 dc
.SetPen(*wxBLACK_PEN
);
192 dc
.DrawLine((tabX
+ GetWidth() + 1), (tabY
+1), (tabX
+ GetWidth() + 1),
193 (tabY
+ GetHeight() + tabHeightInc
- subtractThis
));
197 // Draw centered text
198 int textY
= tabY
+ m_view
->GetVerticalTabTextSpacing() + tabHeightInc
;
201 dc
.SetFont(* m_view
->GetSelectedTabFont());
203 dc
.SetFont(* GetFont());
205 wxColour
col(m_view
->GetTextColour());
206 dc
.SetTextForeground(col
);
207 dc
.SetBackgroundMode(wxTRANSPARENT
);
208 wxCoord textWidth
, textHeight
;
209 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
211 int textX
= (int)(tabX
+ (GetWidth() - textWidth
)/2.0);
212 if (textX
< (tabX
+ 2))
215 dc
.SetClippingRegion(tabX
, tabY
, GetWidth(), GetHeight());
216 dc
.DrawText(GetLabel(), textX
, textY
);
217 dc
.DestroyClippingRegion();
221 dc
.SetPen(*m_view
->GetHighlightPen());
223 // Draw white highlight from the tab's left side to the left hand edge of the view
224 dc
.DrawLine(m_view
->GetViewRect().x
, (tabY
+ GetHeight() + tabHeightInc
),
225 tabX
, (tabY
+ GetHeight() + tabHeightInc
));
227 // Draw white highlight from the tab's right side to the right hand edge of the view
228 dc
.DrawLine((tabX
+ GetWidth()), (tabY
+ GetHeight() + tabHeightInc
),
229 m_view
->GetViewRect().x
+ m_view
->GetViewRect().width
, (tabY
+ GetHeight() + tabHeightInc
));
232 // New HEL version with rounder tabs
239 tabInc
= m_view
->GetTabSelectionHeight() - m_view
->GetTabHeight();
241 int tabLeft
= GetX() + m_view
->GetViewRect().x
;
242 int tabTop
= GetY() + m_view
->GetViewRect().y
- tabInc
;
243 int tabRight
= tabLeft
+ m_view
->GetTabWidth();
244 int left
= m_view
->GetViewRect().x
;
245 int top
= tabTop
+ m_view
->GetTabHeight() + tabInc
;
246 int right
= left
+ m_view
->GetViewRect().width
;
247 int bottom
= top
+ m_view
->GetViewRect().height
;
251 // TAB is selected - draw TAB and the View's full outline
253 dc
.SetPen(*(m_view
->GetHighlightPen()));
256 pnts
[n
].x
= left
; pnts
[n
++].y
= bottom
;
257 pnts
[n
].x
= left
; pnts
[n
++].y
= top
;
258 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= top
;
259 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
260 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
261 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
262 dc
.DrawLines(n
, pnts
);
273 dc
.SetPen(*(m_view
->GetShadowPen()));
293 dc
.SetPen(*wxBLACK_PEN
);
335 // TAB is not selected - just draw TAB outline and RH edge
336 // if the TAB is the last in the row
338 int maxPositions
= ((wxTabLayer
*)m_view
->GetLayers().Item(0)->GetData())->GetCount();
339 wxTabControl
* tabBelow
= 0;
340 wxTabControl
* tabBelowRight
= 0;
341 if (GetColPosition() > 0)
343 tabBelow
= m_view
->FindTabControlForPosition(
344 GetColPosition() - 1,
348 if (!lastInRow
&& GetColPosition() > 0)
350 tabBelowRight
= m_view
->FindTabControlForPosition(
351 GetColPosition() - 1,
356 float raisedTop
= top
- m_view
->GetTabSelectionHeight() +
357 m_view
->GetTabHeight();
359 dc
.SetPen(*(m_view
->GetHighlightPen()));
365 if (tabBelow
&& tabBelow
->IsSelected())
367 pnts
[n
++].y
= (long)raisedTop
;
373 pnts
[n
].x
= tabLeft
; pnts
[n
++].y
= tabTop
+ 2;
374 pnts
[n
].x
= tabLeft
+ 2; pnts
[n
++].y
= tabTop
;
375 pnts
[n
].x
= tabRight
- 1; pnts
[n
++].y
= tabTop
;
376 dc
.DrawLines(n
, pnts
);
378 dc
.SetPen(*(m_view
->GetShadowPen()));
379 if (GetRowPosition() >= maxPositions
- 1)
390 (tabRight
- m_view
->GetHorizontalTabOffset()),
396 if (tabBelowRight
&& tabBelowRight
->IsSelected())
416 dc
.SetPen(*wxBLACK_PEN
);
425 if (GetRowPosition() >= maxPositions
- 1)
427 // draw right hand edge to bottom of view
437 (tabRight
- m_view
->GetHorizontalTabOffset()),
443 // draw right hand edge of TAB
444 if (tabBelowRight
&& tabBelowRight
->IsSelected())
448 (long)(raisedTop
- 1),
465 // Draw centered text
466 dc
.SetPen(*wxBLACK_PEN
);
469 dc
.SetFont(*(m_view
->GetSelectedTabFont()));
473 dc
.SetFont(*(GetFont()));
476 wxColour
col(m_view
->GetTextColour());
477 dc
.SetTextForeground(col
);
478 dc
.SetBackgroundMode(wxTRANSPARENT
);
479 long textWidth
, textHeight
;
480 dc
.GetTextExtent(GetLabel(), &textWidth
, &textHeight
);
482 float textX
= (tabLeft
+ tabRight
- textWidth
) / 2;
483 float textY
= (tabInc
+ tabTop
+ m_view
->GetVerticalTabTextSpacing());
485 dc
.DrawText(GetLabel(), (long)textX
, (long)textY
);
489 bool wxTabControl::HitTest(int x
, int y
) const
491 // Top-left of tab control
492 int tabX1
= GetX() + m_view
->GetViewRect().x
;
493 int tabY1
= GetY() + m_view
->GetViewRect().y
;
496 int tabX2
= tabX1
+ GetWidth();
497 int tabY2
= tabY1
+ GetHeight();
499 if (x
>= tabX1
&& y
>= tabY1
&& x
<= tabX2
&& y
<= tabY2
)
505 IMPLEMENT_DYNAMIC_CLASS(wxTabView
, wxObject
)
507 wxTabView::wxTabView(long style
)
513 m_tabSelectionHeight
= m_tabHeight
+ 2;
515 m_tabHorizontalOffset
= 10;
516 m_tabHorizontalSpacing
= 2;
517 m_tabVerticalTextSpacing
= 3;
519 m_tabViewRect
.x
= 20;
520 m_tabViewRect
.y
= 20;
521 m_tabViewRect
.width
= 300;
522 m_tabViewRect
.x
= 300;
523 m_highlightColour
= *wxWHITE
;
524 m_shadowColour
= wxColour(128, 128, 128);
525 // m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
526 m_textColour
= *wxBLACK
;
527 m_highlightPen
= wxWHITE_PEN
;
528 m_shadowPen
= wxGREY_PEN
;
529 // SetBackgroundColour(m_backgroundColour);
530 m_tabFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
531 m_tabSelectedFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
535 wxTabView::~wxTabView()
540 // Automatically positions tabs
541 // TODO: this should just add the tab to a list, and then
542 // a layout function (e.g. Realize) should be called when all tabs have been added.
543 // The view rect could easily change as the view window is resized.
544 wxTabControl
*wxTabView::AddTab(int id
, const wxString
& label
, wxTabControl
*existingTab
)
546 // First, find which layer we should be adding to.
547 wxTabLayerList::compatibility_iterator node
= m_layers
.GetLast();
550 wxTabLayer
*newLayer
= new wxTabLayer
;
551 node
= m_layers
.Append(newLayer
);
553 // Check if adding another tab control would go off the
554 // right-hand edge of the layer.
555 wxTabLayer
*tabLayer
= (wxTabLayer
*)node
->GetData();
556 wxList::compatibility_iterator lastTabNode
= tabLayer
->GetLast();
559 wxTabControl
*lastTab
= (wxTabControl
*)lastTabNode
->GetData();
560 // Start another layer (row).
561 // Tricky choice: can't just check if will be overlapping the edge, because
562 // this happens anyway for 2nd and subsequent rows.
563 // Should check this for 1st row, and then subsequent rows should not exceed 1st
565 if (((tabLayer
== m_layers
.GetFirst()->GetData()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
566 > GetViewRect().width
)) ||
567 ((tabLayer
!= m_layers
.GetFirst()->GetData()) && (tabLayer
->GetCount() == ((wxTabLayer
*)m_layers
.GetFirst()->GetData())->GetCount())))
569 tabLayer
= new wxTabLayer
;
570 m_layers
.Append(tabLayer
);
571 lastTabNode
= wxList::compatibility_iterator();
574 int layer
= m_layers
.GetCount() - 1;
576 wxTabControl
*tabControl
= existingTab
;
578 tabControl
= OnCreateTabControl();
579 tabControl
->SetRowPosition(tabLayer
->GetCount());
580 tabControl
->SetColPosition(layer
);
582 wxTabControl
*lastTab
= NULL
;
584 lastTab
= (wxTabControl
*)lastTabNode
->GetData();
587 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
588 // Offset from view top-left
589 int horizontalOffset
= 0;
591 horizontalOffset
= layer
*GetHorizontalTabOffset();
593 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
595 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
596 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
597 tabControl
->SetId(id
);
598 tabControl
->SetLabel(label
);
599 tabControl
->SetFont(* GetTabFont());
601 tabLayer
->Append(tabControl
);
607 // Remove the tab without deleting the window
608 bool wxTabView::RemoveTab(int id
)
610 wxTabLayerList::compatibility_iterator layerNode
= m_layers
.GetFirst();
613 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
614 wxList::compatibility_iterator tabNode
= layer
->GetFirst();
617 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
618 if (tab
->GetId() == id
)
620 if (id
== m_tabSelection
)
623 layer
->Erase(tabNode
);
626 // The layout has changed
630 tabNode
= tabNode
->GetNext();
632 layerNode
= layerNode
->GetNext();
637 bool wxTabView::SetTabText(int id
, const wxString
& label
)
639 wxTabControl
* control
= FindTabControlForId(id
);
642 control
->SetLabel(label
);
646 wxString
wxTabView::GetTabText(int id
) const
648 wxTabControl
* control
= FindTabControlForId(id
);
650 return wxEmptyString
;
652 return control
->GetLabel();
655 // Returns the total height of the tabs component -- this may be several
656 // times the height of a tab, if there are several tab layers (rows).
657 int wxTabView::GetTotalTabHeight()
661 wxTabLayerList::compatibility_iterator layerNode
= m_layers
.GetFirst();
664 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
665 wxList::compatibility_iterator tabNode
= layer
->GetFirst();
668 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
670 if (tab
->GetY() < minY
)
673 tabNode
= tabNode
->GetNext();
675 layerNode
= layerNode
->GetNext();
681 void wxTabView::ClearTabs(bool deleteTabs
)
683 wxTabLayerList::compatibility_iterator layerNode
= m_layers
.GetFirst();
686 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
687 wxList::compatibility_iterator tabNode
= layer
->GetFirst();
690 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
693 wxList::compatibility_iterator next
= tabNode
->GetNext();
694 layer
->Erase(tabNode
);
697 wxTabLayerList::compatibility_iterator nextLayerNode
= layerNode
->GetNext();
699 m_layers
.Erase(layerNode
);
700 layerNode
= nextLayerNode
;
707 // Layout tabs (optional, e.g. if resizing window)
708 void wxTabView::LayoutTabs(void)
710 // Make a list of the tab controls, deleting the wxTabLayers.
713 wxTabLayerList::compatibility_iterator layerNode
= m_layers
.GetFirst();
716 wxTabLayer
*layer
= (wxTabLayer
*)layerNode
->GetData();
717 wxList::compatibility_iterator tabNode
= layer
->GetFirst();
720 wxTabControl
*tab
= (wxTabControl
*)tabNode
->GetData();
721 controls
.Append(tab
);
722 wxList::compatibility_iterator next
= tabNode
->GetNext();
723 layer
->Erase(tabNode
);
726 wxTabLayerList::compatibility_iterator nextLayerNode
= layerNode
->GetNext();
728 m_layers
.Erase(layerNode
);
729 layerNode
= nextLayerNode
;
732 wxTabControl
*lastTab
= NULL
;
734 wxTabLayer
*currentLayer
= new wxTabLayer
;
735 m_layers
.Append(currentLayer
);
737 wxList::compatibility_iterator node
= controls
.GetFirst();
740 wxTabControl
*tabControl
= (wxTabControl
*)node
->GetData();
743 // Start another layer (row).
744 // Tricky choice: can't just check if will be overlapping the edge, because
745 // this happens anyway for 2nd and subsequent rows.
746 // Should check this for 1st row, and then subsequent rows should not exceed 1st
748 if (((currentLayer
== m_layers
.GetFirst()->GetData()) && ((lastTab
->GetX() + 2*lastTab
->GetWidth() + GetHorizontalTabSpacing())
749 > GetViewRect().width
)) ||
750 ((currentLayer
!= m_layers
.GetFirst()->GetData()) && (currentLayer
->GetCount() == ((wxTabLayer
*)m_layers
.GetFirst()->GetData())->GetCount())))
752 currentLayer
= new wxTabLayer
;
753 m_layers
.Append(currentLayer
);
758 int layer
= m_layers
.GetCount() - 1;
760 tabControl
->SetRowPosition(currentLayer
->GetCount());
761 tabControl
->SetColPosition(layer
);
764 int verticalOffset
= (- GetTopMargin()) - ((layer
+1)*GetTabHeight());
765 // Offset from view top-left
766 int horizontalOffset
= 0;
768 horizontalOffset
= layer
*GetHorizontalTabOffset();
770 horizontalOffset
= lastTab
->GetX() + GetTabWidth() + GetHorizontalTabSpacing();
772 tabControl
->SetPosition(horizontalOffset
, verticalOffset
);
773 tabControl
->SetSize(GetTabWidth(), GetTabHeight());
775 currentLayer
->Append(tabControl
);
776 lastTab
= tabControl
;
778 node
= node
->GetNext();
781 // Move the selected tab to the bottom
782 wxTabControl
*control
= FindTabControlForId(m_tabSelection
);
784 MoveSelectionTab(control
);
789 void wxTabView::Draw(wxDC
& dc
)
791 // Don't draw anything if there are no tabs.
792 if (GetNumberOfTabs() == 0)
795 // Draw top margin area (beneath tabs and above view area)
796 if (GetTabStyle() & wxTAB_STYLE_COLOUR_INTERIOR
)
798 dc
.SetPen(*wxTRANSPARENT_PEN
);
799 if(GetBackgroundBrush())
800 dc
.SetBrush(*GetBackgroundBrush());
802 // Add 1 because the pen is transparent. Under Motif, may be different.
805 (m_tabViewRect
.y
- m_topMargin
),
806 (m_tabViewRect
.width
+ 1),
811 // Draw layers in reverse order
812 wxTabLayerList::compatibility_iterator node
= m_layers
.GetLast();
815 wxTabLayer
*layer
= (wxTabLayer
*)node
->GetData();
816 wxList::compatibility_iterator node2
= layer
->GetFirst();
819 wxTabControl
*control
= (wxTabControl
*)node2
->GetData();
820 control
->OnDraw(dc
, (!node2
->GetNext()));
821 node2
= node2
->GetNext();
824 node
= node
->GetPrevious();
828 #ifndef wxUSE_NEW_METHOD
829 if (GetTabStyle() & wxTAB_STYLE_DRAW_BOX
)
831 dc
.SetPen(* GetShadowPen());
835 (GetViewRect().x
+ 1),
836 (GetViewRect().y
+ GetViewRect().height
),
837 (GetViewRect().x
+ GetViewRect().width
+ 1),
838 (GetViewRect().y
+ GetViewRect().height
)
843 (GetViewRect().x
+ GetViewRect().width
),
844 (GetViewRect().y
- GetTopMargin() + 1),
845 (GetViewRect().x
+ GetViewRect().width
),
846 (GetViewRect().y
+ GetViewRect().height
)
849 dc
.SetPen(* wxBLACK_PEN
);
854 (GetViewRect().y
+ GetViewRect().height
+ 1),
855 #if defined(__WXMOTIF__)
856 (GetViewRect().x
+ GetViewRect().width
+ 1),
858 (GetViewRect().x
+ GetViewRect().width
+ 2),
861 (GetViewRect().y
+ GetViewRect().height
+ 1)
866 (GetViewRect().x
+ GetViewRect().width
+ 1),
867 (GetViewRect().y
- GetTopMargin()),
868 (GetViewRect().x
+ GetViewRect().width
+ 1),
869 (GetViewRect().y
+ GetViewRect().height
+ 1)
875 // Process mouse event, return false if we didn't process it
876 bool wxTabView::OnEvent(wxMouseEvent
& event
)
878 if (!event
.LeftDown())
882 event
.GetPosition(&x
, &y
);
884 wxTabControl
*hitControl
= NULL
;
886 wxTabLayerList::compatibility_iterator node
= m_layers
.GetFirst();
889 wxTabLayer
*layer
= (wxTabLayer
*)node
->GetData();
890 wxList::compatibility_iterator node2
= layer
->GetFirst();
893 wxTabControl
*control
= (wxTabControl
*)node2
->GetData();
894 if (control
->HitTest((int)x
, (int)y
))
896 hitControl
= control
;
897 node
= wxTabLayerList::compatibility_iterator();
898 node2
= wxList::compatibility_iterator();
901 node2
= node2
->GetNext();
905 node
= node
->GetNext();
911 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
913 if (hitControl
== currentTab
)
916 ChangeTab(hitControl
);
921 bool wxTabView::ChangeTab(wxTabControl
*control
)
923 wxTabControl
*currentTab
= FindTabControlForId(m_tabSelection
);
926 oldTab
= currentTab
->GetId();
928 if (control
== currentTab
)
931 if (m_layers
.GetCount() == 0)
934 if (!OnTabPreActivate(control
->GetId(), oldTab
))
937 // Move the tab to the bottom
938 MoveSelectionTab(control
);
941 currentTab
->SetSelected(false);
943 control
->SetSelected(true);
944 m_tabSelection
= control
->GetId();
946 OnTabActivate(control
->GetId(), oldTab
);
948 // Leave window refresh for the implementing window
953 // Move the selected tab to the bottom layer, if necessary,
954 // without calling app activation code
955 bool wxTabView::MoveSelectionTab(wxTabControl
*control
)
957 if (m_layers
.GetCount() == 0)
960 wxTabLayer
*firstLayer
= (wxTabLayer
*)m_layers
.GetFirst()->GetData();
962 // Find what column this tab is at, so we can swap with the one at the bottom.
963 // If we're on the bottom layer, then no need to swap.
964 if (!firstLayer
->Member(control
))
968 wxList::compatibility_iterator thisNode
= FindTabNodeAndColumn(control
, &col
);
971 wxList::compatibility_iterator otherNode
= firstLayer
->Item(col
);
975 // If this is already in the bottom layer, return now
976 if (otherNode
== thisNode
)
979 wxTabControl
*otherTab
= (wxTabControl
*)otherNode
->GetData();
981 // We now have pointers to the tab to be changed to,
982 // and the tab on the first layer. Swap tab structures and
985 int thisX
= control
->GetX();
986 int thisY
= control
->GetY();
987 int thisColPos
= control
->GetColPosition();
988 int otherX
= otherTab
->GetX();
989 int otherY
= otherTab
->GetY();
990 int otherColPos
= otherTab
->GetColPosition();
992 control
->SetPosition(otherX
, otherY
);
993 control
->SetColPosition(otherColPos
);
994 otherTab
->SetPosition(thisX
, thisY
);
995 otherTab
->SetColPosition(thisColPos
);
997 // Swap the data for the nodes
998 thisNode
->SetData(otherTab
);
999 otherNode
->SetData(control
);
1004 // Called when a tab is activated
1005 void wxTabView::OnTabActivate(int /*activateId*/, int /*deactivateId*/)
1009 void wxTabView::SetHighlightColour(const wxColour
& col
)
1011 m_highlightColour
= col
;
1012 m_highlightPen
= wxThePenList
->FindOrCreatePen(col
);
1015 void wxTabView::SetShadowColour(const wxColour
& col
)
1017 m_shadowColour
= col
;
1018 m_shadowPen
= wxThePenList
->FindOrCreatePen(col
);
1021 void wxTabView::SetBackgroundColour(const wxColour
& col
)
1023 m_backgroundColour
= col
;
1024 m_backgroundPen
= wxThePenList
->FindOrCreatePen(col
);
1025 m_backgroundBrush
= wxTheBrushList
->FindOrCreateBrush(col
);
1028 // this may be called with sel = zero (which doesn't match any page)
1029 // when wxMotif deletes a page
1030 // so return the first tab...
1032 void wxTabView::SetTabSelection(int sel
, bool activateTool
)
1034 if ( sel
==m_tabSelection
)
1037 int oldSel
= m_tabSelection
;
1038 wxTabControl
*control
= FindTabControlForId(sel
);
1039 if (sel
== 0) sel
=control
->GetId();
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 // this may be called with zero (which doesn't match any page)
1067 // so return the first control...
1068 wxTabControl
*wxTabView::FindTabControlForId(int id
) const
1070 wxTabLayerList::compatibility_iterator node1
= m_layers
.GetFirst();
1073 wxTabLayer
*layer
= (wxTabLayer
*)node1
->GetData();
1074 wxList::compatibility_iterator node2
= layer
->GetFirst();
1077 wxTabControl
*control
= (wxTabControl
*)node2
->GetData();
1078 if (control
->GetId() == id
|| id
== 0)
1080 node2
= node2
->GetNext();
1082 node1
= node1
->GetNext();
1087 // Find tab control for layer, position (starting from zero)
1088 wxTabControl
*wxTabView::FindTabControlForPosition(int layer
, int position
) const
1090 wxTabLayerList::compatibility_iterator node1
= m_layers
.Item(layer
);
1093 wxTabLayer
*tabLayer
= (wxTabLayer
*)node1
->GetData();
1094 wxList::compatibility_iterator node2
= tabLayer
->Item(position
);
1097 return (wxTabControl
*)node2
->GetData();
1100 // Find the node and the column at which this control is positioned.
1101 wxList::compatibility_iterator
wxTabView::FindTabNodeAndColumn(wxTabControl
*control
, int *col
) const
1103 wxTabLayerList::compatibility_iterator node1
= m_layers
.GetFirst();
1106 wxTabLayer
*layer
= (wxTabLayer
*)node1
->GetData();
1108 wxList::compatibility_iterator node2
= layer
->GetFirst();
1111 wxTabControl
*cnt
= (wxTabControl
*)node2
->GetData();
1117 node2
= node2
->GetNext();
1120 node1
= node1
->GetNext();
1122 return wxList::compatibility_iterator();
1125 int wxTabView::CalculateTabWidth(int noTabs
, bool adjustView
)
1127 m_tabWidth
= (int)((m_tabViewRect
.width
- ((noTabs
- 1)*GetHorizontalTabSpacing()))/noTabs
);
1130 m_tabViewRect
.width
= noTabs
*m_tabWidth
+ ((noTabs
-1)*GetHorizontalTabSpacing());
1139 IMPLEMENT_CLASS(wxTabbedDialog
, wxDialog
)
1141 BEGIN_EVENT_TABLE(wxTabbedDialog
, wxDialog
)
1142 EVT_CLOSE(wxTabbedDialog::OnCloseWindow
)
1143 EVT_MOUSE_EVENTS(wxTabbedDialog::OnMouseEvent
)
1144 EVT_PAINT(wxTabbedDialog::OnPaint
)
1147 wxTabbedDialog::wxTabbedDialog(wxWindow
*parent
, wxWindowID id
,
1148 const wxString
& title
,
1149 const wxPoint
& pos
, const wxSize
& size
,
1150 long windowStyle
, const wxString
& name
):
1151 wxDialog(parent
, id
, title
, pos
, size
, windowStyle
, name
)
1156 wxTabbedDialog::~wxTabbedDialog(void)
1162 void wxTabbedDialog::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
) )
1167 void wxTabbedDialog::OnMouseEvent(wxMouseEvent
& event
)
1170 m_tabView
->OnEvent(event
);
1173 void wxTabbedDialog::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1177 m_tabView
->Draw(dc
);
1184 IMPLEMENT_CLASS(wxTabbedPanel
, wxPanel
)
1186 BEGIN_EVENT_TABLE(wxTabbedPanel
, wxPanel
)
1187 EVT_MOUSE_EVENTS(wxTabbedPanel::OnMouseEvent
)
1188 EVT_PAINT(wxTabbedPanel::OnPaint
)
1191 wxTabbedPanel::wxTabbedPanel(wxWindow
*parent
, wxWindowID id
, const wxPoint
& pos
,
1192 const wxSize
& size
, long windowStyle
, const wxString
& name
):
1193 wxPanel(parent
, id
, pos
, size
, windowStyle
, name
)
1198 wxTabbedPanel::~wxTabbedPanel(void)
1203 void wxTabbedPanel::OnMouseEvent(wxMouseEvent
& event
)
1206 m_tabView
->OnEvent(event
);
1209 void wxTabbedPanel::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
1213 m_tabView
->Draw(dc
);
1220 IMPLEMENT_CLASS(wxPanelTabView
, wxTabView
)
1222 wxPanelTabView::wxPanelTabView(wxPanel
*pan
, long style
)
1226 m_currentWindow
= NULL
;
1228 if (m_panel
->IsKindOf(CLASSINFO(wxTabbedDialog
)))
1229 ((wxTabbedDialog
*)m_panel
)->SetTabView(this);
1230 else if (m_panel
->IsKindOf(CLASSINFO(wxTabbedPanel
)))
1231 ((wxTabbedPanel
*)m_panel
)->SetTabView(this);
1236 wxPanelTabView::~wxPanelTabView(void)
1241 // Called when a tab is activated
1242 void wxPanelTabView::OnTabActivate(int activateId
, int deactivateId
)
1247 wxWindow
*oldWindow
= ((deactivateId
== -1) ? 0 : GetTabWindow(deactivateId
));
1248 wxWindow
*newWindow
= GetTabWindow(activateId
);
1251 oldWindow
->Show(false);
1253 newWindow
->Show(true);
1259 void wxPanelTabView::AddTabWindow(int id
, wxWindow
*window
)
1261 wxASSERT(m_tabWindows
.find(id
) == m_tabWindows
.end());
1262 m_tabWindows
[id
] = window
;
1263 window
->Show(false);
1266 wxWindow
*wxPanelTabView::GetTabWindow(int id
) const
1268 wxIntToWindowHashMap::const_iterator it
= m_tabWindows
.find(id
);
1269 return it
== m_tabWindows
.end() ? NULL
: it
->second
;
1272 void wxPanelTabView::ClearWindows(bool deleteWindows
)
1275 WX_CLEAR_HASH_MAP(wxIntToWindowHashMap
, m_tabWindows
);
1276 m_tabWindows
.clear();
1279 void wxPanelTabView::ShowWindowForTab(int id
)
1281 wxWindow
*newWindow
= GetTabWindow(id
);
1282 if (newWindow
== m_currentWindow
)
1284 if (m_currentWindow
)
1285 m_currentWindow
->Show(false);
1286 newWindow
->Show(true);
1287 newWindow
->Refresh();