TabControl.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  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:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  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.
  19. //
  20. // Copyright (c) 2004 Novell, Inc.
  21. //
  22. // Authors:
  23. // Jackson Harper ([email protected])
  24. using System;
  25. using System.Drawing;
  26. using System.Collections;
  27. namespace System.Windows.Forms {
  28. public class TabControl : Control {
  29. private int selected_index = -1;
  30. private TabAlignment alignment;
  31. private TabAppearance appearance;
  32. private TabDrawMode draw_mode;
  33. private bool multiline;
  34. private ImageList image_list;
  35. private Size item_size = Size.Empty;
  36. private Point padding;
  37. private int row_count = 1;
  38. private bool hottrack;
  39. private TabPageCollection tab_pages;
  40. private bool show_tool_tips;
  41. private TabSizeMode size_mode;
  42. private bool redraw;
  43. private Rectangle display_rect;
  44. private bool show_slider = false;
  45. private ButtonState right_slider_state;
  46. private ButtonState left_slider_state;
  47. private int slider_pos = 0;
  48. public TabControl ()
  49. {
  50. tab_pages = new TabPageCollection (this);
  51. SetStyle (ControlStyles.UserPaint, true);
  52. padding = ThemeEngine.Current.TabControlDefaultPadding;
  53. item_size = ThemeEngine.Current.TabControlDefaultItemSize;
  54. MouseDown += new MouseEventHandler (MouseDownHandler);
  55. MouseUp += new MouseEventHandler (MouseUpHandler);
  56. SizeChanged += new EventHandler (SizeChangedHandler);
  57. }
  58. public TabAlignment Alignment {
  59. get { return alignment; }
  60. set {
  61. if (alignment == value)
  62. return;
  63. alignment = value;
  64. if (alignment == TabAlignment.Left || alignment == TabAlignment.Right)
  65. multiline = true;
  66. Refresh ();
  67. }
  68. }
  69. public TabAppearance Appearance {
  70. get { return appearance; }
  71. set {
  72. if (appearance == value)
  73. return;
  74. appearance = value;
  75. Refresh ();
  76. }
  77. }
  78. public override Color BackColor {
  79. get { return base.BackColor; }
  80. set { /* nothing happens on set on MS */ }
  81. }
  82. public override Image BackgroundImage {
  83. get { return base.BackgroundImage; }
  84. set { base.BackgroundImage = value; }
  85. }
  86. public override Rectangle DisplayRectangle {
  87. get {
  88. return ThemeEngine.Current.GetTabControlDisplayRectangle (this);
  89. }
  90. }
  91. public TabDrawMode DrawMode {
  92. get { return draw_mode; }
  93. set {
  94. if (draw_mode == value)
  95. return;
  96. draw_mode = value;
  97. Refresh ();
  98. }
  99. }
  100. public override Color ForeColor {
  101. get { return base.ForeColor; }
  102. set { base.ForeColor = value; }
  103. }
  104. public bool HotTrack {
  105. get { return hottrack; }
  106. set {
  107. if (hottrack == value)
  108. return;
  109. hottrack = value;
  110. Refresh ();
  111. }
  112. }
  113. public ImageList ImageList {
  114. get { return image_list; }
  115. set { image_list = value; }
  116. }
  117. public Size ItemSize {
  118. get {
  119. return item_size;
  120. }
  121. set {
  122. if (value.Height < 0 || value.Width < 0)
  123. throw new ArgumentException ("'" + value + "' is not a valid value for 'ItemSize'.");
  124. item_size = value;
  125. Refresh ();
  126. }
  127. }
  128. public bool Multiline {
  129. get { return multiline; }
  130. set {
  131. if (multiline == value)
  132. return;
  133. multiline = value;
  134. if (!multiline && alignment == TabAlignment.Left || alignment == TabAlignment.Right)
  135. alignment = TabAlignment.Top;
  136. Refresh ();
  137. }
  138. }
  139. public Point Padding {
  140. get { return padding; }
  141. set {
  142. if (value.X < 0 || value.Y < 0)
  143. throw new ArgumentException ("'" + value + "' is not a valid value for 'Padding'.");
  144. if (padding == value)
  145. return;
  146. padding = value;
  147. Refresh ();
  148. }
  149. }
  150. public int RowCount {
  151. get { return row_count; }
  152. }
  153. public int SelectedIndex {
  154. get { return selected_index; }
  155. set {
  156. if (selected_index == value)
  157. return;
  158. if (selected_index < -1) {
  159. throw new ArgumentException ("'" + value + "' is not a valid value for 'value'. " +
  160. "'value' must be greater than or equal to -1.");
  161. }
  162. SuspendLayout ();
  163. if (selected_index != -1)
  164. Controls [selected_index].Visible = false;
  165. selected_index = value;
  166. if (selected_index != -1)
  167. Controls [selected_index].Visible = true;
  168. ResumeLayout ();
  169. if (SelectedIndex != -1 && TabPages [SelectedIndex].Row != BottomRow)
  170. DropRow (TabPages [selected_index].Row);
  171. SizeTabs ();
  172. Refresh ();
  173. }
  174. }
  175. public TabPage SelectedTab {
  176. get {
  177. if (selected_index == -1)
  178. return null;
  179. return tab_pages [selected_index];
  180. }
  181. set {
  182. int index = IndexForTabPage (value);
  183. if (index == selected_index)
  184. return;
  185. selected_index = index;
  186. Refresh ();
  187. }
  188. }
  189. public bool ShowToolTips {
  190. get { return show_tool_tips; }
  191. set {
  192. if (show_tool_tips == value)
  193. return;
  194. show_tool_tips = value;
  195. Refresh ();
  196. }
  197. }
  198. public TabSizeMode SizeMode {
  199. get { return size_mode; }
  200. set {
  201. if (size_mode == value)
  202. return;
  203. size_mode = value;
  204. Refresh ();
  205. }
  206. }
  207. public int TabCount {
  208. get {
  209. return tab_pages.Count;
  210. }
  211. }
  212. public TabPageCollection TabPages {
  213. get { return tab_pages; }
  214. }
  215. public override string Text {
  216. get { return base.Text; }
  217. set { base.Text = value; }
  218. }
  219. internal bool ShowSlider {
  220. get { return show_slider; }
  221. set { show_slider = value; }
  222. }
  223. internal ButtonState RightSliderState {
  224. get { return right_slider_state; }
  225. }
  226. internal ButtonState LeftSliderState {
  227. get { return left_slider_state; }
  228. }
  229. [MonoTODO ("Anything special need to be done?")]
  230. protected override CreateParams CreateParams {
  231. get {
  232. CreateParams c = base.CreateParams;
  233. // Do we need to do anything here?
  234. return c;
  235. }
  236. }
  237. protected override Size DefaultSize {
  238. get { return new Size (200, 100); }
  239. }
  240. private Size DefaultItemSize {
  241. get {
  242. return ThemeEngine.Current.TabControlDefaultItemSize;
  243. }
  244. }
  245. public new event EventHandler BackColorChanged {
  246. add { base.BackColorChanged += value; }
  247. remove { base.BackColorChanged -= value; }
  248. }
  249. public new event EventHandler BackgroundImageChanged {
  250. add { base.BackgroundImageChanged += value; }
  251. remove { base.BackgroundImageChanged -= value; }
  252. }
  253. public new event EventHandler ForeColorChanged {
  254. add { base.ForeColorChanged += value; }
  255. remove { base.ForeColorChanged -= value; }
  256. }
  257. public new event PaintEventHandler Paint {
  258. add { base.Paint += value; }
  259. remove { base.Paint -= value; }
  260. }
  261. public new event EventHandler TextChanged {
  262. add { base.TextChanged += value; }
  263. remove { base.TextChanged -= value; }
  264. }
  265. public event DrawItemEventHandler DrawItem;
  266. public event EventHandler SelectedIndexChanged;
  267. public Rectangle GetTabRect (int index)
  268. {
  269. TabPage page = GetTab (index);
  270. return page.TabBounds;
  271. }
  272. public Control GetControl (int index)
  273. {
  274. return GetTab (index);
  275. }
  276. protected override Control.ControlCollection CreateControlsInstance ()
  277. {
  278. return new TabControl.ControlCollection (this);
  279. }
  280. protected override void CreateHandle ()
  281. {
  282. ResizeTabPages ();
  283. base.CreateHandle ();
  284. }
  285. protected override void Dispose (bool disposing)
  286. {
  287. base.Dispose (disposing);
  288. }
  289. protected virtual object [] GetItems ()
  290. {
  291. TabPage [] pages = new TabPage [Controls.Count];
  292. Controls.CopyTo (pages, 0);
  293. return pages;
  294. }
  295. protected virtual object [] GetItems (Type type)
  296. {
  297. object [] pages = (object []) Array.CreateInstance (type, Controls.Count);
  298. Controls.CopyTo (pages, 0);
  299. return pages;
  300. }
  301. protected string GetToolTipText (object item)
  302. {
  303. TabPage page = (TabPage) item;
  304. return page.ToolTipText;
  305. }
  306. protected override void WndProc (ref Message m)
  307. {
  308. switch ((Msg) m.Msg) {
  309. case Msg.WM_PAINT:
  310. PaintEventArgs paint_event;
  311. paint_event = XplatUI.PaintEventStart (Handle);
  312. PaintInternal (paint_event);
  313. XplatUI.PaintEventEnd (Handle);
  314. break;
  315. default:
  316. base.WndProc (ref m);
  317. break;
  318. }
  319. }
  320. private bool CanScrollRight {
  321. get {
  322. if (TabPages [TabCount - 1].TabBounds.Right > ClientRectangle.Right - 40)
  323. return true;
  324. return false;
  325. }
  326. }
  327. private bool CanScrollLeft {
  328. get { return slider_pos > 0; }
  329. }
  330. private void MouseDownHandler (object sender, MouseEventArgs e)
  331. {
  332. if (ShowSlider) {
  333. Rectangle right = ThemeEngine.Current.GetTabControlRightScrollRect (this);
  334. Rectangle left = ThemeEngine.Current.GetTabControlLeftScrollRect (this);
  335. if (right.Contains (e.X, e.Y)) {
  336. right_slider_state = ButtonState.Pushed;
  337. if (CanScrollRight) {
  338. Console.WriteLine ("right slider pos: " + slider_pos);
  339. slider_pos--;
  340. SizeTabs ();
  341. }
  342. Refresh ();
  343. return;
  344. } else if (left.Contains (e.X, e.Y)) {
  345. left_slider_state = ButtonState.Pushed;
  346. if (CanScrollLeft) {
  347. Console.WriteLine ("left slider pos: " + slider_pos);
  348. slider_pos++;
  349. SizeTabs ();
  350. }
  351. Refresh ();
  352. return;
  353. }
  354. }
  355. int count = Controls.Count;
  356. for (int i = 0; i<count; i++) {
  357. if (!GetTabRect (i).Contains (e.X, e.Y))
  358. continue;
  359. SelectedIndex = i;
  360. break;
  361. }
  362. }
  363. private void MouseUpHandler (object sender, MouseEventArgs e)
  364. {
  365. left_slider_state = ButtonState.Normal;
  366. right_slider_state = ButtonState.Normal;
  367. Refresh ();
  368. }
  369. private void SizeChangedHandler (object sender, EventArgs e)
  370. {
  371. ResizeTabPages ();
  372. }
  373. internal void UpdateTabpage (TabPage page)
  374. {
  375. }
  376. internal int IndexForTabPage (TabPage page)
  377. {
  378. for (int i = 0; i < tab_pages.Count; i++) {
  379. if (page == tab_pages [i])
  380. return i;
  381. }
  382. return -1;
  383. }
  384. private void ResizeTabPages ()
  385. {
  386. CalcTabRows ();
  387. SizeTabs ();
  388. Rectangle r = DisplayRectangle;
  389. foreach (TabPage page in Controls) {
  390. page.Bounds = r;
  391. }
  392. }
  393. private int MinimumTabWidth {
  394. get {
  395. return ThemeEngine.Current.TabControlMinimumTabWidth;
  396. }
  397. }
  398. private Size TabSpacing {
  399. get {
  400. return ThemeEngine.Current.TabControlGetSpacing (this);
  401. }
  402. }
  403. private void CalcTabRows ()
  404. {
  405. switch (Alignment) {
  406. case TabAlignment.Right:
  407. case TabAlignment.Left:
  408. CalcTabRows (Height);
  409. break;
  410. default:
  411. CalcTabRows (Width);
  412. break;
  413. }
  414. }
  415. private void CalcTabRows (int row_width)
  416. {
  417. int xpos = 4;
  418. Size spacing = TabSpacing;
  419. row_count = 1;
  420. show_slider = false;
  421. for (int i = 0; i < TabPages.Count; i++) {
  422. TabPage page = TabPages [i];
  423. int width;
  424. page.Row = 1;
  425. if (SizeMode == TabSizeMode.Fixed) {
  426. width = item_size.Width;
  427. } else {
  428. width = (int) DeviceContext.MeasureString (page.Text, Font).Width + (Padding.X * 2);
  429. }
  430. if (i == SelectedIndex)
  431. width += 8;
  432. if (width < MinimumTabWidth)
  433. width = MinimumTabWidth;
  434. if (xpos + width > row_width && multiline) {
  435. xpos = 4;
  436. for (int j = 0; j < i; j++) {
  437. TabPages [j].Row++;
  438. }
  439. row_count++;
  440. } else if (xpos + width > row_width) {
  441. show_slider = true;
  442. }
  443. xpos += width + 1 + spacing.Width;
  444. }
  445. if (SelectedIndex != -1 && TabPages [SelectedIndex].Row != BottomRow)
  446. DropRow (TabPages [SelectedIndex].Row);
  447. }
  448. private int BottomRow {
  449. get {
  450. switch (Alignment) {
  451. case TabAlignment.Right:
  452. case TabAlignment.Bottom:
  453. return row_count;
  454. default:
  455. return 1;
  456. }
  457. }
  458. }
  459. private int Direction
  460. {
  461. get {
  462. switch (Alignment) {
  463. case TabAlignment.Right:
  464. case TabAlignment.Bottom:
  465. return -1;
  466. default:
  467. return 1;
  468. }
  469. }
  470. }
  471. private void DropRow (int row)
  472. {
  473. int bottom = BottomRow;
  474. int direction = Direction;
  475. foreach (TabPage page in TabPages) {
  476. if (page.Row == row) {
  477. page.Row = bottom;
  478. } else if (direction == 1 && page.Row < row) {
  479. page.Row += direction;
  480. } else if (direction == -1 && page.Row > row) {
  481. page.Row += direction;
  482. }
  483. }
  484. }
  485. private int CalcYPos ()
  486. {
  487. if (Alignment == TabAlignment.Bottom) {
  488. Rectangle r = ThemeEngine.Current.GetTabControlDisplayRectangle (this);
  489. return r.Bottom + 3;
  490. }
  491. return 1;
  492. }
  493. private int CalcXPos ()
  494. {
  495. if (Alignment == TabAlignment.Right) {
  496. Rectangle r = ThemeEngine.Current.GetTabControlDisplayRectangle (this);
  497. return r.Right + 4;
  498. }
  499. return 4;
  500. }
  501. private void SizeTabs ()
  502. {
  503. switch (Alignment) {
  504. case TabAlignment.Right:
  505. case TabAlignment.Left:
  506. SizeTabsV (Height);
  507. break;
  508. default:
  509. SizeTabs (Width);
  510. break;
  511. }
  512. }
  513. private void SizeTabsV (int row_width)
  514. {
  515. int ypos = 1;
  516. int prev_row = 1;
  517. Size spacing = TabSpacing;
  518. int size = item_size.Height + 2 + spacing.Width;
  519. int xpos = CalcXPos ();
  520. if (TabPages.Count == 0)
  521. return;
  522. prev_row = TabPages [0].Row;
  523. for (int i = 0; i < TabPages.Count; i++) {
  524. TabPage page = TabPages [i];
  525. int width;
  526. if (SizeMode == TabSizeMode.Fixed) {
  527. width = item_size.Width;
  528. } else {
  529. width = (int) DeviceContext.MeasureString (page.Text, Font).Width + (Padding.X * 2);
  530. }
  531. if (width < MinimumTabWidth)
  532. width = MinimumTabWidth;
  533. if (page.Row != prev_row)
  534. ypos = 1;
  535. page.TabBounds = new Rectangle (xpos + (row_count - page.Row) * ((item_size.Height - 2) + spacing.Width),
  536. ypos, item_size.Height - 2, width);
  537. ypos += width + spacing.Width;
  538. prev_row = page.Row;
  539. }
  540. if (SelectedIndex != -1) {
  541. TabPage page = TabPages [SelectedIndex];
  542. ExpandSelected (TabPages [SelectedIndex], 1, row_width - 1);
  543. }
  544. }
  545. private void SizeTabs (int row_width)
  546. {
  547. int ypos = CalcYPos ();
  548. int prev_row = 1;
  549. Size spacing = TabSpacing;
  550. int size = item_size.Width + 2 + (spacing.Width * 2);
  551. int xpos = 4 + (slider_pos * size);
  552. int begin_prev = 0;
  553. if (TabPages.Count == 0)
  554. return;
  555. prev_row = TabPages [0].Row;
  556. for (int i = 0; i < TabPages.Count; i++) {
  557. TabPage page = TabPages [i];
  558. int width;
  559. if (SizeMode == TabSizeMode.Fixed) {
  560. width = item_size.Width;
  561. } else {
  562. width = (int) DeviceContext.MeasureString (page.Text, Font).Width + (Padding.X * 2);
  563. }
  564. if (width < MinimumTabWidth)
  565. width = MinimumTabWidth;
  566. if (page.Row != prev_row)
  567. xpos = 4 + (slider_pos * size);
  568. page.TabBounds = new Rectangle (xpos,
  569. ypos + (row_count - page.Row) * (item_size.Height + spacing.Height),
  570. width, item_size.Height);
  571. if (page.Row != prev_row) {
  572. if (SizeMode == TabSizeMode.FillToRight) {
  573. FillRow (begin_prev, i - 1, ((row_width - TabPages [i - 1].TabBounds.Right) / (i - begin_prev)), spacing);
  574. }
  575. begin_prev = i;
  576. }
  577. xpos += width + 1 + spacing.Width;
  578. prev_row = page.Row;
  579. }
  580. if (SizeMode == TabSizeMode.FillToRight) {
  581. FillRow (begin_prev, TabPages.Count - 1,
  582. ((row_width - TabPages [TabPages.Count - 1].TabBounds.Right) / (TabPages.Count - begin_prev)), spacing);
  583. }
  584. if (SelectedIndex != -1) {
  585. TabPage page = TabPages [SelectedIndex];
  586. ExpandSelected (TabPages [SelectedIndex], 2, row_width - 1);
  587. }
  588. }
  589. private void FillRow (int start, int end, int amount, Size spacing)
  590. {
  591. int xpos = TabPages [start].TabBounds.Left;
  592. for (int i = start; i <= end; i++) {
  593. TabPage page = TabPages [i];
  594. int left = xpos;
  595. int width = (i == end ? Width - left - 3 : page.TabBounds.Width + amount);
  596. page.TabBounds = new Rectangle (left, page.TabBounds.Top,
  597. width, page.TabBounds.Height);
  598. xpos = page.TabBounds.Right + 1 + spacing.Width;
  599. }
  600. }
  601. private void ExpandSelected (TabPage page, int left_edge, int right_edge)
  602. {
  603. if (Appearance != TabAppearance.Normal)
  604. return;
  605. if (Alignment == TabAlignment.Top || Alignment == TabAlignment.Bottom) {
  606. int l = page.TabBounds.Left - 4;
  607. int r = page.TabBounds.Right + 4;
  608. int y = page.TabBounds.Y;
  609. int h = page.TabBounds.Height + 2;
  610. if (l < left_edge)
  611. l = left_edge;
  612. if (r > right_edge && SizeMode != TabSizeMode.Normal)
  613. r = right_edge;
  614. if (Alignment == TabAlignment.Top)
  615. y -= 1;
  616. if (Alignment == TabAlignment.Bottom)
  617. y -= 2;
  618. page.TabBounds = new Rectangle (l, y, r - l, h);
  619. } else {
  620. int l = page.TabBounds.Left - 3;
  621. int r = page.TabBounds.Right + 3;
  622. int t = page.TabBounds.Top - 3;
  623. int b = page.TabBounds.Bottom + 3;
  624. if (t < left_edge)
  625. t = left_edge;
  626. if (b > right_edge)
  627. b = right_edge;
  628. page.TabBounds = new Rectangle (l, t, r - l, b - t);
  629. }
  630. }
  631. private void PaintInternal (PaintEventArgs pe)
  632. {
  633. if (this.Width <= 0 || this.Height <= 0 || this.Visible == false)
  634. return;
  635. Draw ();
  636. pe.Graphics.DrawImageUnscaled (ImageBuffer, 0, 0);
  637. ImageBuffer.Save ("ImageBuffer.bmp");
  638. // On MS the Paint event never seems to be raised
  639. }
  640. private void Redraw (bool recalculate)
  641. {
  642. if (recalculate) {
  643. }
  644. redraw = true;
  645. Refresh ();
  646. }
  647. private void Draw ()
  648. {
  649. ThemeEngine.Current.DrawTabControl (DeviceContext, ClientRectangle, this);
  650. redraw = false;
  651. }
  652. private TabPage GetTab (int index)
  653. {
  654. return Controls [index] as TabPage;
  655. }
  656. private void SetTab (int index, TabPage value)
  657. {
  658. ((IList) Controls).Insert (index, value);
  659. Refresh ();
  660. }
  661. public class ControlCollection : System.Windows.Forms.Control.ControlCollection {
  662. private TabControl owner;
  663. private ArrayList list = new ArrayList ();
  664. public ControlCollection (TabControl owner) : base (owner)
  665. {
  666. this.owner = owner;
  667. }
  668. public override void Add (Control value)
  669. {
  670. if (!(value is TabPage))
  671. throw new ArgumentException ("Cannot add " +
  672. value.GetType ().Name + " to TabControl. " +
  673. "Only TabPages can be directly added to TabControls.");
  674. value.Visible = false;
  675. base.Add (value);
  676. if (Count == 1) {
  677. owner.SelectedIndex = 0;
  678. } else {
  679. // Setting the selected index will calc the tab rows so
  680. // we don't need to do it again
  681. owner.CalcTabRows ();
  682. }
  683. }
  684. }
  685. public class TabPageCollection : IList, ICollection, IEnumerable {
  686. private TabControl owner;
  687. private IList controls;
  688. public TabPageCollection (TabControl owner)
  689. {
  690. if (owner == null)
  691. throw new ArgumentNullException ("Value cannot be null.");
  692. this.owner = owner;
  693. controls = owner.Controls;
  694. }
  695. public virtual int Count {
  696. get { return owner.Controls.Count; }
  697. }
  698. public virtual bool IsReadOnly {
  699. get { return false; }
  700. }
  701. public virtual TabPage this [int index] {
  702. get {
  703. return owner.GetTab (index);
  704. }
  705. set {
  706. owner.SetTab (index, value);
  707. }
  708. }
  709. bool ICollection.IsSynchronized {
  710. get { return false; }
  711. }
  712. object ICollection.SyncRoot {
  713. get { return this; }
  714. }
  715. bool IList.IsFixedSize {
  716. get { return false; }
  717. }
  718. object IList.this [int index] {
  719. get {
  720. return owner.GetTab (index);
  721. }
  722. set {
  723. owner.SetTab (index, (TabPage) value);
  724. }
  725. }
  726. public void Add (TabPage page)
  727. {
  728. if (page == null)
  729. throw new ArgumentNullException ("Value cannot be null.");
  730. owner.Controls.Add (page);
  731. }
  732. public void AddRange (TabPage [] pages)
  733. {
  734. if (pages == null)
  735. throw new ArgumentNullException ("Value cannot be null.");
  736. owner.Controls.AddRange (pages);
  737. }
  738. public virtual void Clear ()
  739. {
  740. owner.Controls.Clear ();
  741. }
  742. public bool Contains (TabPage page)
  743. {
  744. if (page == null)
  745. throw new ArgumentNullException ("Value cannot be null.");
  746. return owner.Controls.Contains (page);
  747. }
  748. public virtual IEnumerator GetEnumerator ()
  749. {
  750. return owner.Controls.GetEnumerator ();
  751. }
  752. public int IndexOf (TabPage page)
  753. {
  754. return owner.Controls.IndexOf (page);
  755. }
  756. public void Remove (TabPage page)
  757. {
  758. owner.Controls.Remove (page);
  759. }
  760. public virtual void RemoveAt (int index)
  761. {
  762. owner.Controls.RemoveAt (index);
  763. }
  764. void ICollection.CopyTo (Array dest, int index)
  765. {
  766. owner.Controls.CopyTo (dest, index);
  767. }
  768. int IList.Add (object value)
  769. {
  770. // return owner.Controls.Add ((TabPage) value);
  771. return -1;
  772. }
  773. bool IList.Contains (object page)
  774. {
  775. return Contains ((TabPage) page);
  776. }
  777. int IList.IndexOf (object page)
  778. {
  779. return IndexOf ((TabPage) page);
  780. }
  781. void IList.Insert (int index, object value)
  782. {
  783. controls.Insert (index, (TabPage) value);
  784. }
  785. void IList.Remove (object value)
  786. {
  787. Remove ((TabPage) value);
  788. }
  789. }
  790. }
  791. }