TabControl.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  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 int SliderPos {
  224. get { return slider_pos; }
  225. }
  226. internal ButtonState RightSliderState {
  227. get { return right_slider_state; }
  228. }
  229. internal ButtonState LeftSliderState {
  230. get { return left_slider_state; }
  231. }
  232. [MonoTODO ("Anything special need to be done?")]
  233. protected override CreateParams CreateParams {
  234. get {
  235. CreateParams c = base.CreateParams;
  236. // Do we need to do anything here?
  237. return c;
  238. }
  239. }
  240. protected override Size DefaultSize {
  241. get { return new Size (200, 100); }
  242. }
  243. private Size DefaultItemSize {
  244. get {
  245. return ThemeEngine.Current.TabControlDefaultItemSize;
  246. }
  247. }
  248. public new event EventHandler BackColorChanged {
  249. add { base.BackColorChanged += value; }
  250. remove { base.BackColorChanged -= value; }
  251. }
  252. public new event EventHandler BackgroundImageChanged {
  253. add { base.BackgroundImageChanged += value; }
  254. remove { base.BackgroundImageChanged -= value; }
  255. }
  256. public new event EventHandler ForeColorChanged {
  257. add { base.ForeColorChanged += value; }
  258. remove { base.ForeColorChanged -= value; }
  259. }
  260. public new event PaintEventHandler Paint {
  261. add { base.Paint += value; }
  262. remove { base.Paint -= value; }
  263. }
  264. public new event EventHandler TextChanged {
  265. add { base.TextChanged += value; }
  266. remove { base.TextChanged -= value; }
  267. }
  268. public event DrawItemEventHandler DrawItem;
  269. public event EventHandler SelectedIndexChanged;
  270. public Rectangle GetTabRect (int index)
  271. {
  272. TabPage page = GetTab (index);
  273. return page.TabBounds;
  274. }
  275. public Control GetControl (int index)
  276. {
  277. return GetTab (index);
  278. }
  279. protected override Control.ControlCollection CreateControlsInstance ()
  280. {
  281. return new TabControl.ControlCollection (this);
  282. }
  283. protected override void CreateHandle ()
  284. {
  285. ResizeTabPages ();
  286. base.CreateHandle ();
  287. }
  288. protected override void Dispose (bool disposing)
  289. {
  290. base.Dispose (disposing);
  291. }
  292. protected virtual object [] GetItems ()
  293. {
  294. TabPage [] pages = new TabPage [Controls.Count];
  295. Controls.CopyTo (pages, 0);
  296. return pages;
  297. }
  298. protected virtual object [] GetItems (Type type)
  299. {
  300. object [] pages = (object []) Array.CreateInstance (type, Controls.Count);
  301. Controls.CopyTo (pages, 0);
  302. return pages;
  303. }
  304. protected string GetToolTipText (object item)
  305. {
  306. TabPage page = (TabPage) item;
  307. return page.ToolTipText;
  308. }
  309. protected override void WndProc (ref Message m)
  310. {
  311. switch ((Msg) m.Msg) {
  312. case Msg.WM_PAINT:
  313. PaintEventArgs paint_event;
  314. paint_event = XplatUI.PaintEventStart (Handle);
  315. PaintInternal (paint_event);
  316. XplatUI.PaintEventEnd (Handle);
  317. break;
  318. default:
  319. base.WndProc (ref m);
  320. break;
  321. }
  322. }
  323. private bool CanScrollRight {
  324. get {
  325. if (TabPages [TabCount - 1].TabBounds.Right > ClientRectangle.Right - 40)
  326. return true;
  327. return false;
  328. }
  329. }
  330. private bool CanScrollLeft {
  331. get { return slider_pos > 0; }
  332. }
  333. private void MouseDownHandler (object sender, MouseEventArgs e)
  334. {
  335. if (ShowSlider) {
  336. Rectangle right = ThemeEngine.Current.GetTabControlRightScrollRect (this);
  337. Rectangle left = ThemeEngine.Current.GetTabControlLeftScrollRect (this);
  338. if (right.Contains (e.X, e.Y)) {
  339. right_slider_state = ButtonState.Pushed;
  340. if (CanScrollRight) {
  341. slider_pos++;
  342. SizeTabs ();
  343. }
  344. Refresh ();
  345. return;
  346. } else if (left.Contains (e.X, e.Y)) {
  347. left_slider_state = ButtonState.Pushed;
  348. if (CanScrollLeft) {
  349. slider_pos--;
  350. SizeTabs ();
  351. }
  352. Refresh ();
  353. return;
  354. }
  355. }
  356. int count = Controls.Count;
  357. for (int i = SliderPos; i < count; i++) {
  358. if (!GetTabRect (i).Contains (e.X, e.Y))
  359. continue;
  360. SelectedIndex = i;
  361. break;
  362. }
  363. }
  364. private void MouseUpHandler (object sender, MouseEventArgs e)
  365. {
  366. left_slider_state = ButtonState.Normal;
  367. right_slider_state = ButtonState.Normal;
  368. Refresh ();
  369. }
  370. private void SizeChangedHandler (object sender, EventArgs e)
  371. {
  372. ResizeTabPages ();
  373. }
  374. internal void UpdateTabpage (TabPage page)
  375. {
  376. }
  377. internal int IndexForTabPage (TabPage page)
  378. {
  379. for (int i = 0; i < tab_pages.Count; i++) {
  380. if (page == tab_pages [i])
  381. return i;
  382. }
  383. return -1;
  384. }
  385. private void ResizeTabPages ()
  386. {
  387. CalcTabRows ();
  388. SizeTabs ();
  389. Rectangle r = DisplayRectangle;
  390. foreach (TabPage page in Controls) {
  391. page.Bounds = r;
  392. }
  393. }
  394. private int MinimumTabWidth {
  395. get {
  396. return ThemeEngine.Current.TabControlMinimumTabWidth;
  397. }
  398. }
  399. private Size TabSpacing {
  400. get {
  401. return ThemeEngine.Current.TabControlGetSpacing (this);
  402. }
  403. }
  404. private void CalcTabRows ()
  405. {
  406. switch (Alignment) {
  407. case TabAlignment.Right:
  408. case TabAlignment.Left:
  409. CalcTabRows (Height);
  410. break;
  411. default:
  412. CalcTabRows (Width);
  413. break;
  414. }
  415. }
  416. private void CalcTabRows (int row_width)
  417. {
  418. int xpos = 4;
  419. Size spacing = TabSpacing;
  420. row_count = 1;
  421. show_slider = false;
  422. for (int i = 0; i < TabPages.Count; i++) {
  423. TabPage page = TabPages [i];
  424. int width;
  425. page.Row = 1;
  426. if (SizeMode == TabSizeMode.Fixed) {
  427. width = item_size.Width;
  428. } else {
  429. width = (int) DeviceContext.MeasureString (page.Text, Font).Width + (Padding.X * 2);
  430. }
  431. if (i == SelectedIndex)
  432. width += 8;
  433. if (width < MinimumTabWidth)
  434. width = MinimumTabWidth;
  435. if (xpos + width > row_width && multiline) {
  436. xpos = 4;
  437. for (int j = 0; j < i; j++) {
  438. TabPages [j].Row++;
  439. }
  440. row_count++;
  441. } else if (xpos + width > row_width) {
  442. show_slider = true;
  443. }
  444. xpos += width + 1 + spacing.Width;
  445. }
  446. if (SelectedIndex != -1 && TabPages [SelectedIndex].Row != BottomRow)
  447. DropRow (TabPages [SelectedIndex].Row);
  448. }
  449. private int BottomRow {
  450. get {
  451. switch (Alignment) {
  452. case TabAlignment.Right:
  453. case TabAlignment.Bottom:
  454. return row_count;
  455. default:
  456. return 1;
  457. }
  458. }
  459. }
  460. private int Direction
  461. {
  462. get {
  463. switch (Alignment) {
  464. case TabAlignment.Right:
  465. case TabAlignment.Bottom:
  466. return -1;
  467. default:
  468. return 1;
  469. }
  470. }
  471. }
  472. private void DropRow (int row)
  473. {
  474. int bottom = BottomRow;
  475. int direction = Direction;
  476. foreach (TabPage page in TabPages) {
  477. if (page.Row == row) {
  478. page.Row = bottom;
  479. } else if (direction == 1 && page.Row < row) {
  480. page.Row += direction;
  481. } else if (direction == -1 && page.Row > row) {
  482. page.Row += direction;
  483. }
  484. }
  485. }
  486. private int CalcYPos ()
  487. {
  488. if (Alignment == TabAlignment.Bottom) {
  489. Rectangle r = ThemeEngine.Current.GetTabControlDisplayRectangle (this);
  490. return r.Bottom + 3;
  491. }
  492. return 1;
  493. }
  494. private int CalcXPos ()
  495. {
  496. if (Alignment == TabAlignment.Right) {
  497. Rectangle r = ThemeEngine.Current.GetTabControlDisplayRectangle (this);
  498. return r.Right + 4;
  499. }
  500. return 4;
  501. }
  502. private void SizeTabs ()
  503. {
  504. switch (Alignment) {
  505. case TabAlignment.Right:
  506. case TabAlignment.Left:
  507. SizeTabsV (Height);
  508. break;
  509. default:
  510. SizeTabs (Width);
  511. break;
  512. }
  513. }
  514. private void SizeTabsV (int row_width)
  515. {
  516. int ypos = 1;
  517. int prev_row = 1;
  518. Size spacing = TabSpacing;
  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. ExpandSelected (TabPages [SelectedIndex], 1, row_width - 1);
  542. }
  543. }
  544. private void SizeTabs (int row_width)
  545. {
  546. int ypos = CalcYPos ();
  547. int prev_row = 1;
  548. Size spacing = TabSpacing;
  549. int xpos = 4;
  550. int begin_prev = 0;
  551. if (TabPages.Count == 0)
  552. return;
  553. prev_row = TabPages [0].Row;
  554. for (int i = slider_pos; i < TabPages.Count; i++) {
  555. TabPage page = TabPages [i];
  556. int width;
  557. if (SizeMode == TabSizeMode.Fixed) {
  558. width = item_size.Width;
  559. } else {
  560. width = (int) DeviceContext.MeasureString (page.Text, Font).Width + (Padding.X * 2);
  561. }
  562. if (width < MinimumTabWidth)
  563. width = MinimumTabWidth;
  564. if (page.Row != prev_row)
  565. xpos = 4;
  566. page.TabBounds = new Rectangle (xpos,
  567. ypos + (row_count - page.Row) * (item_size.Height + spacing.Height),
  568. width, item_size.Height);
  569. if (page.Row != prev_row) {
  570. if (SizeMode == TabSizeMode.FillToRight) {
  571. FillRow (begin_prev, i - 1, ((row_width - TabPages [i - 1].TabBounds.Right) / (i - begin_prev)), spacing);
  572. }
  573. begin_prev = i;
  574. }
  575. xpos += width + 1 + spacing.Width;
  576. prev_row = page.Row;
  577. }
  578. if (SizeMode == TabSizeMode.FillToRight) {
  579. FillRow (begin_prev, TabPages.Count - 1,
  580. ((row_width - TabPages [TabPages.Count - 1].TabBounds.Right) / (TabPages.Count - begin_prev)), spacing);
  581. }
  582. if (SelectedIndex != -1) {
  583. ExpandSelected (TabPages [SelectedIndex], 2, row_width - 1);
  584. }
  585. }
  586. private void FillRow (int start, int end, int amount, Size spacing)
  587. {
  588. int xpos = TabPages [start].TabBounds.Left;
  589. for (int i = start; i <= end; i++) {
  590. TabPage page = TabPages [i];
  591. int left = xpos;
  592. int width = (i == end ? Width - left - 3 : page.TabBounds.Width + amount);
  593. page.TabBounds = new Rectangle (left, page.TabBounds.Top,
  594. width, page.TabBounds.Height);
  595. xpos = page.TabBounds.Right + 1 + spacing.Width;
  596. }
  597. }
  598. private void ExpandSelected (TabPage page, int left_edge, int right_edge)
  599. {
  600. if (Appearance != TabAppearance.Normal)
  601. return;
  602. if (Alignment == TabAlignment.Top || Alignment == TabAlignment.Bottom) {
  603. int l = page.TabBounds.Left - 4;
  604. int r = page.TabBounds.Right + 4;
  605. int y = page.TabBounds.Y;
  606. int h = page.TabBounds.Height + 2;
  607. if (l < left_edge)
  608. l = left_edge;
  609. if (r > right_edge && SizeMode != TabSizeMode.Normal)
  610. r = right_edge;
  611. if (Alignment == TabAlignment.Top)
  612. y -= 1;
  613. if (Alignment == TabAlignment.Bottom)
  614. y -= 2;
  615. page.TabBounds = new Rectangle (l, y, r - l, h);
  616. } else {
  617. int l = page.TabBounds.Left - 3;
  618. int r = page.TabBounds.Right + 3;
  619. int t = page.TabBounds.Top - 3;
  620. int b = page.TabBounds.Bottom + 3;
  621. if (t < left_edge)
  622. t = left_edge;
  623. if (b > right_edge)
  624. b = right_edge;
  625. page.TabBounds = new Rectangle (l, t, r - l, b - t);
  626. }
  627. }
  628. private void PaintInternal (PaintEventArgs pe)
  629. {
  630. if (this.Width <= 0 || this.Height <= 0 || this.Visible == false)
  631. return;
  632. Draw ();
  633. pe.Graphics.DrawImageUnscaled (ImageBuffer, 0, 0);
  634. ImageBuffer.Save ("ImageBuffer.bmp");
  635. // On MS the Paint event never seems to be raised
  636. }
  637. private void Redraw (bool recalculate)
  638. {
  639. if (recalculate) {
  640. }
  641. redraw = true;
  642. Refresh ();
  643. }
  644. private void Draw ()
  645. {
  646. ThemeEngine.Current.DrawTabControl (DeviceContext, ClientRectangle, this);
  647. redraw = false;
  648. }
  649. private TabPage GetTab (int index)
  650. {
  651. return Controls [index] as TabPage;
  652. }
  653. private void SetTab (int index, TabPage value)
  654. {
  655. ((IList) Controls).Insert (index, value);
  656. Refresh ();
  657. }
  658. public class ControlCollection : System.Windows.Forms.Control.ControlCollection {
  659. private TabControl owner;
  660. private ArrayList list = new ArrayList ();
  661. public ControlCollection (TabControl owner) : base (owner)
  662. {
  663. this.owner = owner;
  664. }
  665. public override void Add (Control value)
  666. {
  667. if (!(value is TabPage))
  668. throw new ArgumentException ("Cannot add " +
  669. value.GetType ().Name + " to TabControl. " +
  670. "Only TabPages can be directly added to TabControls.");
  671. value.Visible = false;
  672. base.Add (value);
  673. if (Count == 1) {
  674. owner.SelectedIndex = 0;
  675. } else {
  676. // Setting the selected index will calc the tab rows so
  677. // we don't need to do it again
  678. owner.CalcTabRows ();
  679. }
  680. }
  681. }
  682. public class TabPageCollection : IList, ICollection, IEnumerable {
  683. private TabControl owner;
  684. private IList controls;
  685. public TabPageCollection (TabControl owner)
  686. {
  687. if (owner == null)
  688. throw new ArgumentNullException ("Value cannot be null.");
  689. this.owner = owner;
  690. controls = owner.Controls;
  691. }
  692. public virtual int Count {
  693. get { return owner.Controls.Count; }
  694. }
  695. public virtual bool IsReadOnly {
  696. get { return false; }
  697. }
  698. public virtual TabPage this [int index] {
  699. get {
  700. return owner.GetTab (index);
  701. }
  702. set {
  703. owner.SetTab (index, value);
  704. }
  705. }
  706. bool ICollection.IsSynchronized {
  707. get { return false; }
  708. }
  709. object ICollection.SyncRoot {
  710. get { return this; }
  711. }
  712. bool IList.IsFixedSize {
  713. get { return false; }
  714. }
  715. object IList.this [int index] {
  716. get {
  717. return owner.GetTab (index);
  718. }
  719. set {
  720. owner.SetTab (index, (TabPage) value);
  721. }
  722. }
  723. public void Add (TabPage page)
  724. {
  725. if (page == null)
  726. throw new ArgumentNullException ("Value cannot be null.");
  727. owner.Controls.Add (page);
  728. }
  729. public void AddRange (TabPage [] pages)
  730. {
  731. if (pages == null)
  732. throw new ArgumentNullException ("Value cannot be null.");
  733. owner.Controls.AddRange (pages);
  734. }
  735. public virtual void Clear ()
  736. {
  737. owner.Controls.Clear ();
  738. }
  739. public bool Contains (TabPage page)
  740. {
  741. if (page == null)
  742. throw new ArgumentNullException ("Value cannot be null.");
  743. return owner.Controls.Contains (page);
  744. }
  745. public virtual IEnumerator GetEnumerator ()
  746. {
  747. return owner.Controls.GetEnumerator ();
  748. }
  749. public int IndexOf (TabPage page)
  750. {
  751. return owner.Controls.IndexOf (page);
  752. }
  753. public void Remove (TabPage page)
  754. {
  755. owner.Controls.Remove (page);
  756. }
  757. public virtual void RemoveAt (int index)
  758. {
  759. owner.Controls.RemoveAt (index);
  760. }
  761. void ICollection.CopyTo (Array dest, int index)
  762. {
  763. owner.Controls.CopyTo (dest, index);
  764. }
  765. int IList.Add (object value)
  766. {
  767. // return owner.Controls.Add ((TabPage) value);
  768. return -1;
  769. }
  770. bool IList.Contains (object page)
  771. {
  772. return Contains ((TabPage) page);
  773. }
  774. int IList.IndexOf (object page)
  775. {
  776. return IndexOf ((TabPage) page);
  777. }
  778. void IList.Insert (int index, object value)
  779. {
  780. controls.Insert (index, (TabPage) value);
  781. }
  782. void IList.Remove (object value)
  783. {
  784. Remove ((TabPage) value);
  785. }
  786. }
  787. }
  788. }