1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc.
23 // Jackson Harper (jackson@ximian.com)
27 using System
.Collections
;
28 using System
.ComponentModel
;
29 using System
.ComponentModel
.Design
;
33 namespace System
.Windows
.Forms
{
34 [DefaultEvent("SelectedIndexChanged")]
35 [DefaultProperty("TabPages")]
36 [Designer("System.Windows.Forms.Design.TabControlDesigner, " + Consts
.AssemblySystem_Design
, "System.ComponentModel.Design.IDesigner")]
37 public class TabControl
: Control
{
39 private int selected_index
= -1;
40 private TabAlignment alignment
;
41 private TabAppearance appearance
;
42 private TabDrawMode draw_mode
;
43 private bool multiline
;
44 private ImageList image_list
;
45 private Size item_size
= Size
.Empty
;
46 private Point padding
;
47 private int row_count
= 1;
48 private bool hottrack
;
49 private TabPageCollection tab_pages
;
50 private bool show_tool_tips
;
51 private TabSizeMode size_mode
;
52 private Rectangle display_rect
;
53 private bool show_slider
= false;
54 private ButtonState right_slider_state
;
55 private ButtonState left_slider_state
;
56 private int slider_pos
= 0;
59 #region Public Constructors
62 tab_pages
= new TabPageCollection (this);
63 SetStyle (ControlStyles
.UserPaint
, false);
64 padding
= ThemeEngine
.Current
.TabControlDefaultPadding
;
65 item_size
= ThemeEngine
.Current
.TabControlDefaultItemSize
;
67 MouseDown
+= new MouseEventHandler (MouseDownHandler
);
68 MouseUp
+= new MouseEventHandler (MouseUpHandler
);
69 SizeChanged
+= new EventHandler (SizeChangedHandler
);
72 #endregion // Public Constructors
74 #region Public Instance Properties
75 [DefaultValue(TabAlignment
.Top
)]
77 [RefreshProperties(RefreshProperties
.All
)]
78 public TabAlignment Alignment
{
79 get { return alignment; }
81 if (alignment
== value)
84 if (alignment
== TabAlignment
.Left
|| alignment
== TabAlignment
.Right
)
90 [DefaultValue(TabAppearance
.Normal
)]
92 public TabAppearance Appearance
{
93 get { return appearance; }
95 if (appearance
== value)
103 [EditorBrowsable(EditorBrowsableState
.Never
)]
104 public override Color BackColor
{
105 get { return ThemeEngine.Current.ColorControl; }
106 set { /* nothing happens on set on MS */ }
110 [EditorBrowsable(EditorBrowsableState
.Never
)]
111 public override Image BackgroundImage
{
112 get { return base.BackgroundImage; }
113 set { base.BackgroundImage = value; }
116 public override Rectangle DisplayRectangle
{
118 return ThemeEngine
.Current
.GetTabControlDisplayRectangle (this);
122 [DefaultValue(TabDrawMode
.Normal
)]
123 public TabDrawMode DrawMode
{
124 get { return draw_mode; }
126 if (draw_mode
== value)
134 [EditorBrowsable(EditorBrowsableState
.Never
)]
135 public override Color ForeColor
{
136 get { return base.ForeColor; }
137 set { base.ForeColor = value; }
140 [DefaultValue(false)]
141 public bool HotTrack
{
142 get { return hottrack; }
144 if (hottrack
== value)
152 public ImageList ImageList
{
153 get { return image_list; }
154 set { image_list = value; }
158 public Size ItemSize
{
163 if (value.Height
< 0 || value.Width
< 0)
164 throw new ArgumentException ("'" + value + "' is not a valid value for 'ItemSize'.");
170 [DefaultValue(false)]
171 public bool Multiline
{
172 get { return multiline; }
174 if (multiline
== value)
177 if (!multiline
&& alignment
== TabAlignment
.Left
|| alignment
== TabAlignment
.Right
)
178 alignment
= TabAlignment
.Top
;
184 public Point Padding
{
185 get { return padding; }
187 if (value.X
< 0 || value.Y
< 0)
188 throw new ArgumentException ("'" + value + "' is not a valid value for 'Padding'.");
189 if (padding
== value)
198 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
199 public int RowCount
{
200 get { return row_count; }
205 public int SelectedIndex
{
206 get { return selected_index; }
208 if (selected_index
== value)
210 if (selected_index
< -1) {
211 throw new ArgumentException ("'" + value + "' is not a valid value for 'value'. " +
212 "'value' must be greater than or equal to -1.");
214 if (value >= TabCount
)
219 Rectangle invalid
= Rectangle
.Empty
;
220 bool refresh
= false;
222 if (-1 != value && show_slider
&& value < slider_pos
) {
228 int le
= TabPages
[value].TabBounds
.Right
;
229 int re
= ThemeEngine
.Current
.GetTabControlLeftScrollRect (this).Left
;
230 if (show_slider
&& le
> re
) {
234 for (i
= value; i
< TabPages
.Count
; i
++) {
235 if (TabPages
[i
].TabBounds
.Right
> re
)
243 if (selected_index
!= -1) {
245 invalid
= GetTabRect (selected_index
);
246 Controls
[selected_index
].Visible
= false;
248 selected_index
= value;
250 OnSelectedIndexChanged (EventArgs
.Empty
);
252 TabPage selected
= null;
254 if (selected_index
!= -1) {
255 selected
= (TabPage
) Controls
[selected_index
];
256 invalid
= Rectangle
.Union (invalid
, GetTabRect (selected_index
));
257 selected
.Visible
= true;
265 } else if (selected_index
!= -1 && selected
.Row
!= BottomRow
) {
266 DropRow (TabPages
[selected_index
].Row
);
267 // calculating what to invalidate here seems to be slower then just
268 // refreshing the whole thing
273 // The lines are drawn on the edges of the tabs so the invalid area should
274 // needs to include the extra pixels of line width.
275 if (appearance
== TabAppearance
.Normal
) {
276 invalid
.Inflate (6, 4);
278 Invalidate (invalid
);
284 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
285 public TabPage SelectedTab
{
287 if (selected_index
== -1)
289 return tab_pages
[selected_index
];
292 int index
= IndexForTabPage (value);
293 if (index
== selected_index
)
295 SelectedIndex
= index
;
299 [DefaultValue(false)]
301 public bool ShowToolTips
{
302 get { return show_tool_tips; }
304 if (show_tool_tips
== value)
306 show_tool_tips
= value;
311 [DefaultValue(TabSizeMode
.Normal
)]
312 [RefreshProperties(RefreshProperties
.Repaint
)]
313 public TabSizeMode SizeMode
{
314 get { return size_mode; }
316 if (size_mode
== value)
324 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
325 public int TabCount
{
327 return tab_pages
.Count
;
332 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
333 [MergableProperty(false)]
334 public TabPageCollection TabPages
{
335 get { return tab_pages; }
340 [EditorBrowsable(EditorBrowsableState
.Never
)]
341 public override string Text
{
342 get { return base.Text; }
343 set { base.Text = value; }
346 #endregion // Public Instance Properties
348 #region Internal Properties
349 internal bool ShowSlider
{
350 get { return show_slider; }
351 set { show_slider = value; }
354 internal int SliderPos
{
355 get { return slider_pos; }
358 internal ButtonState RightSliderState
{
359 get { return right_slider_state; }
362 internal ButtonState LeftSliderState
{
363 get { return left_slider_state; }
366 private Size DefaultItemSize
{
368 return ThemeEngine
.Current
.TabControlDefaultItemSize
;
372 #endregion // Internal Properties
374 #region Protected Instance Properties
375 protected override CreateParams CreateParams
{
377 CreateParams c
= base.CreateParams
;
382 protected override Size DefaultSize
{
383 get { return new Size (200, 100); }
386 #endregion // Protected Instance Properties
388 #region Public Instance Methods
389 public Rectangle
GetTabRect (int index
)
391 TabPage page
= GetTab (index
);
392 return page
.TabBounds
;
395 public Control
GetControl (int index
)
397 return GetTab (index
);
400 public override string ToString ()
402 string res
= String
.Concat (base.ToString (),
403 ", TabPages.Count: ",
406 res
= String
.Concat (res
, ", TabPages[0]: ",
411 #endregion // Public Instance Methods
413 #region Protected Instance Methods
414 protected override Control
.ControlCollection
CreateControlsInstance ()
416 return new TabControl
.ControlCollection (this);
419 protected void UpdateTabSelection (bool uiselected
)
424 protected override void CreateHandle ()
426 base.CreateHandle ();
430 protected override void OnHandleCreated (EventArgs e
)
432 base.OnHandleCreated (e
);
435 protected override void OnHandleDestroyed (EventArgs e
)
437 base.OnHandleDestroyed (e
);
440 protected virtual void OnDrawItem (DrawItemEventArgs e
)
442 if (DrawItem
!= null && DrawMode
== TabDrawMode
.OwnerDrawFixed
)
446 internal void OnDrawItemInternal (DrawItemEventArgs e
)
451 protected override void OnFontChanged (EventArgs e
)
453 base.OnFontChanged (e
);
457 protected override void OnResize (EventArgs e
)
462 protected override void OnStyleChanged (EventArgs e
)
464 base.OnStyleChanged (e
);
467 protected override bool ProcessKeyPreview (ref Message m
)
469 return base.ProcessKeyPreview (ref m
);
472 protected override void OnKeyDown (KeyEventArgs e
)
474 if (e
.KeyCode
== Keys
.Tab
&& (e
.KeyData
& Keys
.Control
) != 0) {
475 if ((e
.KeyData
& Keys
.Shift
) == 0)
476 SelectedIndex
= (SelectedIndex
+ 1) % TabCount
;
478 SelectedIndex
= (SelectedIndex
- 1) % TabCount
;
480 } else if (e
.KeyCode
== Keys
.Home
) {
483 } else if (e
.KeyCode
== Keys
.End
) {
484 SelectedIndex
= TabCount
- 1;
486 } else if (e
.KeyCode
== Keys
.Left
&& SelectedIndex
> 0) {
489 } else if (e
.KeyCode
== Keys
.Right
&& SelectedIndex
< TabCount
- 1) {
497 protected override bool IsInputKey (Keys key
)
499 switch (key
& Keys
.KeyCode
) {
507 return base.IsInputKey (key
);
510 protected override void Dispose (bool disposing
)
512 base.Dispose (disposing
);
515 protected void RemoveAll ()
520 protected virtual object [] GetItems ()
522 TabPage
[] pages
= new TabPage
[Controls
.Count
];
523 Controls
.CopyTo (pages
, 0);
527 protected virtual object [] GetItems (Type type
)
529 object [] pages
= (object []) Array
.CreateInstance (type
, Controls
.Count
);
530 Controls
.CopyTo (pages
, 0);
534 protected string GetToolTipText (object item
)
536 TabPage page
= (TabPage
) item
;
537 return page
.ToolTipText
;
540 protected override void WndProc (ref Message m
)
542 base.WndProc (ref m
);
545 protected virtual void OnSelectedIndexChanged (EventArgs e
)
547 if (SelectedIndexChanged
!= null)
548 SelectedIndexChanged (this, e
);
551 internal override void OnPaintInternal (PaintEventArgs pe
)
553 Draw (pe
.Graphics
, pe
.ClipRectangle
);
556 #endregion // Protected Instance Methods
558 #region Internal & Private Methods
559 private bool CanScrollRight
{
561 return (slider_pos
< TabCount
- 1);
565 private bool CanScrollLeft
{
566 get { return slider_pos > 0; }
569 private void MouseDownHandler (object sender
, MouseEventArgs e
)
572 Rectangle right
= ThemeEngine
.Current
.GetTabControlRightScrollRect (this);
573 Rectangle left
= ThemeEngine
.Current
.GetTabControlLeftScrollRect (this);
574 if (right
.Contains (e
.X
, e
.Y
)) {
575 right_slider_state
= ButtonState
.Pushed
;
576 if (CanScrollRight
) {
580 Invalidate (new Rectangle (0, 0, Width
, DisplayRectangle
.Top
));
585 } else if (left
.Contains (e
.X
, e
.Y
)) {
586 left_slider_state
= ButtonState
.Pushed
;
591 Invalidate (new Rectangle (0, 0, Width
, DisplayRectangle
.Top
));
599 int count
= Controls
.Count
;
600 for (int i
= SliderPos
; i
< count
; i
++) {
601 if (!GetTabRect (i
).Contains (e
.X
, e
.Y
))
608 private void MouseUpHandler (object sender
, MouseEventArgs e
)
610 if (ShowSlider
&& (left_slider_state
== ButtonState
.Pushed
|| right_slider_state
== ButtonState
.Pushed
)) {
612 if (left_slider_state
== ButtonState
.Pushed
)
613 invalid
= ThemeEngine
.Current
.GetTabControlLeftScrollRect (this);
615 invalid
= ThemeEngine
.Current
.GetTabControlRightScrollRect (this);
616 left_slider_state
= ButtonState
.Normal
;
617 right_slider_state
= ButtonState
.Normal
;
619 Invalidate (invalid
);
623 private void SizeChangedHandler (object sender
, EventArgs e
)
628 internal void UpdateTabpage (TabPage page
)
633 internal int IndexForTabPage (TabPage page
)
635 for (int i
= 0; i
< tab_pages
.Count
; i
++) {
636 if (page
== tab_pages
[i
])
642 private void ResizeTabPages ()
646 Rectangle r
= DisplayRectangle
;
647 foreach (TabPage page
in Controls
) {
652 private int MinimumTabWidth
{
654 return ThemeEngine
.Current
.TabControlMinimumTabWidth
;
658 private Size TabSpacing
{
660 return ThemeEngine
.Current
.TabControlGetSpacing (this);
664 private void CalcTabRows ()
667 case TabAlignment
.Right
:
668 case TabAlignment
.Left
:
669 CalcTabRows (Height
);
677 private void CalcTabRows (int row_width
)
680 Size spacing
= TabSpacing
;
685 for (int i
= 0; i
< TabPages
.Count
; i
++) {
686 TabPage page
= TabPages
[i
];
691 if (SizeMode
== TabSizeMode
.Fixed
) {
692 width
= item_size
.Width
;
694 width
= (int) DeviceContext
.MeasureString (page
.Text
, Font
).Width
+ (Padding
.X
* 2);
697 if (i
== SelectedIndex
)
699 if (width
< MinimumTabWidth
)
700 width
= MinimumTabWidth
;
702 if (xpos
+ width
> row_width
&& multiline
) {
704 for (int j
= 0; j
< i
; j
++) {
708 } else if (xpos
+ width
> row_width
) {
712 xpos
+= width
+ 1 + spacing
.Width
;
715 if (SelectedIndex
!= -1 && TabPages
[SelectedIndex
].Row
!= BottomRow
)
716 DropRow (TabPages
[SelectedIndex
].Row
);
719 private int BottomRow
{
722 case TabAlignment
.Right
:
723 case TabAlignment
.Bottom
:
731 private int Direction
735 case TabAlignment
.Right
:
736 case TabAlignment
.Bottom
:
744 private void DropRow (int row
)
746 int bottom
= BottomRow
;
747 int direction
= Direction
;
749 foreach (TabPage page
in TabPages
) {
750 if (page
.Row
== row
) {
752 } else if (direction
== 1 && page
.Row
< row
) {
753 page
.Row
+= direction
;
754 } else if (direction
== -1 && page
.Row
> row
) {
755 page
.Row
+= direction
;
760 private int CalcYPos ()
762 if (Alignment
== TabAlignment
.Bottom
) {
763 Rectangle r
= ThemeEngine
.Current
.GetTabControlDisplayRectangle (this);
769 private int CalcXPos ()
771 if (Alignment
== TabAlignment
.Right
) {
772 Rectangle r
= ThemeEngine
.Current
.GetTabControlDisplayRectangle (this);
779 private void SizeTabs ()
782 case TabAlignment
.Right
:
783 case TabAlignment
.Left
:
792 private void SizeTabsV (int row_width
)
796 Size spacing
= TabSpacing
;
797 int xpos
= CalcXPos ();
800 if (TabPages
.Count
== 0)
803 prev_row
= TabPages
[0].Row
;
805 for (int i
= 0; i
< TabPages
.Count
; i
++) {
806 TabPage page
= TabPages
[i
];
809 if (SizeMode
== TabSizeMode
.Fixed
) {
810 width
= item_size
.Width
;
812 width
= (int) DeviceContext
.MeasureString (page
.Text
, Font
).Width
+ (Padding
.X
* 2);
815 if (width
< MinimumTabWidth
)
816 width
= MinimumTabWidth
;
817 if (page
.Row
!= prev_row
)
820 page
.TabBounds
= new Rectangle (xpos
+ (row_count
- page
.Row
) * ((item_size
.Height
- 2) + spacing
.Width
),
821 ypos
, item_size
.Height
- 2, width
);
823 if (page
.Row
!= prev_row
) {
824 if (SizeMode
== TabSizeMode
.FillToRight
&& !ShowSlider
) {
825 FillRowV (begin_prev
, i
- 1, ((row_width
- TabPages
[i
- 1].TabBounds
.Bottom
) / (i
- begin_prev
)), spacing
);
830 ypos
+= width
+ spacing
.Width
;
834 if (SizeMode
== TabSizeMode
.FillToRight
&& !ShowSlider
) {
835 FillRowV (begin_prev
, TabPages
.Count
- 1,
836 ((row_width
- TabPages
[TabPages
.Count
- 1].TabBounds
.Bottom
) / (TabPages
.Count
- begin_prev
)), spacing
);
839 if (SelectedIndex
!= -1) {
840 ExpandSelected (TabPages
[SelectedIndex
], 2, row_width
- 1);
844 private void SizeTabs (int row_width
)
846 int ypos
= CalcYPos ();
848 Size spacing
= TabSpacing
;
852 if (TabPages
.Count
== 0)
855 prev_row
= TabPages
[0].Row
;
857 // Reset the slider position if the slider isn't needed
858 // anymore (ie window size was increased so all tabs are visible)
862 for (int i
= slider_pos
; i
< TabPages
.Count
; i
++) {
863 TabPage page
= TabPages
[i
];
866 if (SizeMode
== TabSizeMode
.Fixed
) {
867 width
= item_size
.Width
;
869 width
= (int) DeviceContext
.MeasureString (page
.Text
, Font
).Width
+ (Padding
.X
* 2);
872 if (width
< MinimumTabWidth
)
873 width
= MinimumTabWidth
;
874 if (page
.Row
!= prev_row
)
877 page
.TabBounds
= new Rectangle (xpos
,
878 ypos
+ (row_count
- page
.Row
) * (item_size
.Height
+ spacing
.Height
),
879 width
, item_size
.Height
);
881 if (page
.Row
!= prev_row
) {
882 if (SizeMode
== TabSizeMode
.FillToRight
&& !ShowSlider
) {
883 FillRow (begin_prev
, i
- 1, ((row_width
- TabPages
[i
- 1].TabBounds
.Right
) / (i
- begin_prev
)), spacing
);
888 xpos
+= width
+ 1 + spacing
.Width
;
892 if (SizeMode
== TabSizeMode
.FillToRight
&& !ShowSlider
) {
893 FillRow (begin_prev
, TabPages
.Count
- 1,
894 ((row_width
- TabPages
[TabPages
.Count
- 1].TabBounds
.Right
) / (TabPages
.Count
- begin_prev
)), spacing
);
897 if (SelectedIndex
!= -1) {
898 ExpandSelected (TabPages
[SelectedIndex
], 2, row_width
- 1);
902 private void FillRow (int start
, int end
, int amount
, Size spacing
)
904 int xpos
= TabPages
[start
].TabBounds
.Left
;
905 for (int i
= start
; i
<= end
; i
++) {
906 TabPage page
= TabPages
[i
];
908 int width
= (i
== end
? Width
- left
- 3 : page
.TabBounds
.Width
+ amount
);
910 page
.TabBounds
= new Rectangle (left
, page
.TabBounds
.Top
,
911 width
, page
.TabBounds
.Height
);
912 xpos
= page
.TabBounds
.Right
+ 1 + spacing
.Width
;
916 private void FillRowV (int start
, int end
, int amount
, Size spacing
)
918 int ypos
= TabPages
[start
].TabBounds
.Top
;
919 for (int i
= start
; i
<= end
; i
++) {
920 TabPage page
= TabPages
[i
];
922 int height
= (i
== end
? Height
- top
- 5 : page
.TabBounds
.Height
+ amount
);
924 page
.TabBounds
= new Rectangle (page
.TabBounds
.Left
, top
,
925 page
.TabBounds
.Width
, height
);
926 ypos
= page
.TabBounds
.Bottom
+ 1;
930 private void ExpandSelected (TabPage page
, int left_edge
, int right_edge
)
932 if (Appearance
!= TabAppearance
.Normal
)
935 if (Alignment
== TabAlignment
.Top
|| Alignment
== TabAlignment
.Bottom
) {
936 int l
= page
.TabBounds
.Left
- 4;
937 int r
= page
.TabBounds
.Right
+ 4;
938 int y
= page
.TabBounds
.Y
;
939 int h
= page
.TabBounds
.Height
+ 3;
943 if (r
> right_edge
&& SizeMode
!= TabSizeMode
.Normal
)
945 if (Alignment
== TabAlignment
.Top
)
947 if (Alignment
== TabAlignment
.Bottom
)
950 page
.TabBounds
= new Rectangle (l
, y
, r
- l
, h
);
952 int l
= page
.TabBounds
.Left
- 3;
953 int r
= page
.TabBounds
.Right
+ 3;
954 int t
= page
.TabBounds
.Top
- 3;
955 int b
= page
.TabBounds
.Bottom
+ 3;
962 page
.TabBounds
= new Rectangle (l
, t
, r
- l
, b
- t
);
966 private void Draw (Graphics dc
, Rectangle clip
)
968 ThemeEngine
.Current
.DrawTabControl (dc
, clip
, this);
971 private TabPage
GetTab (int index
)
973 return Controls
[index
] as TabPage
;
976 private void SetTab (int index
, TabPage
value)
978 ((IList
) Controls
).Insert (index
, value);
982 internal void Redraw ()
988 #endregion // Internal & Private Methods
992 [EditorBrowsable(EditorBrowsableState
.Never
)]
993 public new event EventHandler BackColorChanged
{
994 add { base.BackColorChanged += value; }
995 remove { base.BackColorChanged -= value; }
999 [EditorBrowsable(EditorBrowsableState
.Never
)]
1000 public new event EventHandler BackgroundImageChanged
{
1001 add { base.BackgroundImageChanged += value; }
1002 remove { base.BackgroundImageChanged -= value; }
1006 [EditorBrowsable(EditorBrowsableState
.Never
)]
1007 public new event EventHandler ForeColorChanged
{
1008 add { base.ForeColorChanged += value; }
1009 remove { base.ForeColorChanged -= value; }
1013 [EditorBrowsable(EditorBrowsableState
.Never
)]
1014 public new event PaintEventHandler Paint
{
1015 add { base.Paint += value; }
1016 remove { base.Paint -= value; }
1020 [EditorBrowsable(EditorBrowsableState
.Never
)]
1021 public new event EventHandler TextChanged
{
1022 add { base.TextChanged += value; }
1023 remove { base.TextChanged -= value; }
1026 public event DrawItemEventHandler DrawItem
;
1027 public event EventHandler SelectedIndexChanged
;
1028 #endregion // Events
1031 #region Class TaControl.ControlCollection
1032 public class ControlCollection
: System
.Windows
.Forms
.Control
.ControlCollection
{
1034 private TabControl owner
;
1035 private ArrayList list
= new ArrayList ();
1037 public ControlCollection (TabControl owner
) : base (owner
)
1042 public override void Add (Control
value)
1044 if (!(value is TabPage
))
1045 throw new ArgumentException ("Cannot add " +
1046 value.GetType ().Name
+ " to TabControl. " +
1047 "Only TabPages can be directly added to TabControls.");
1049 value.Visible
= false;
1052 owner
.SelectedIndex
= 0;
1054 // Setting the selected index will calc the tab rows so
1055 // we don't need to do it again
1056 owner
.ResizeTabPages ();
1060 public override void Remove (Control
value)
1062 TabPage page
= value as TabPage
;
1064 int index
= owner
.IndexForTabPage (page
);
1065 if (index
< owner
.SelectedIndex
|| owner
.SelectedIndex
== Count
- 1)
1066 owner
.SelectedIndex
--;
1068 base.Remove (value);
1071 #endregion // Class TabControl.ControlCollection
1073 #region Class TabPage.TabPageCollection
1074 public class TabPageCollection
: IList
, ICollection
, IEnumerable
{
1076 private TabControl owner
;
1078 public TabPageCollection (TabControl owner
)
1081 throw new ArgumentNullException ("Value cannot be null.");
1087 get { return owner.Controls.Count; }
1090 public bool IsReadOnly
{
1091 get { return false; }
1094 public virtual TabPage
this [int index
] {
1096 return owner
.GetTab (index
);
1099 owner
.SetTab (index
, value);
1103 bool ICollection
.IsSynchronized
{
1104 get { return false; }
1107 object ICollection
.SyncRoot
{
1108 get { return this; }
1111 bool IList
.IsFixedSize
{
1112 get { return false; }
1115 object IList
.this [int index
] {
1117 return owner
.GetTab (index
);
1120 owner
.SetTab (index
, (TabPage
) value);
1124 public void Add (TabPage page
)
1127 throw new ArgumentNullException ("Value cannot be null.");
1128 owner
.Controls
.Add (page
);
1131 public void AddRange (TabPage
[] pages
)
1134 throw new ArgumentNullException ("Value cannot be null.");
1135 owner
.Controls
.AddRange (pages
);
1138 public virtual void Clear ()
1140 owner
.Controls
.Clear ();
1143 public bool Contains (TabPage page
)
1146 throw new ArgumentNullException ("Value cannot be null.");
1147 return owner
.Controls
.Contains (page
);
1150 public IEnumerator
GetEnumerator ()
1152 return owner
.Controls
.GetEnumerator ();
1155 public int IndexOf (TabPage page
)
1157 return owner
.Controls
.IndexOf (page
);
1160 public void Remove (TabPage page
)
1162 owner
.Controls
.Remove (page
);
1165 public void RemoveAt (int index
)
1167 owner
.Controls
.RemoveAt (index
);
1170 void ICollection
.CopyTo (Array dest
, int index
)
1172 owner
.Controls
.CopyTo (dest
, index
);
1175 int IList
.Add (object value)
1177 TabPage page
= value as TabPage
;
1179 throw new ArgumentException ("value");
1180 owner
.Controls
.Add (page
);
1181 return owner
.Controls
.IndexOf (page
);
1184 bool IList
.Contains (object value)
1186 TabPage page
= value as TabPage
;
1189 return Contains (page
);
1192 int IList
.IndexOf (object value)
1194 TabPage page
= value as TabPage
;
1197 return IndexOf ((TabPage
) page
);
1200 void IList
.Insert (int index
, object value)
1202 throw new NotSupportedException ();
1205 void IList
.Remove (object value)
1207 TabPage page
= value as TabPage
;
1210 Remove ((TabPage
) value);
1213 #endregion // Class TabPage.TabPageCollection