(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / TabControl.cs
blobba85f53df5a19a2e21dcf7c6be6a76521cb3c9a7
1 //
2 // System.Windows.Forms.TabControl.cs
3 //
4 // Author:
5 // stubbed out by Jackson Harper (jackson@latitudegeo.com)
6 // Dennis Hayes (dennish@Raytek.com)
7 // implemented by Aleksey Ryabchuk (ryabchuk@yahoo.com)
8 // (C) 2002 Ximian, Inc
9 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.ComponentModel;
32 using System.Collections;
33 using System.Drawing;
34 using System.Runtime.InteropServices;
36 namespace System.Windows.Forms {
38 public class TabControl : Control {
40 public class ControlCollection : Control.ControlCollection {
42 public ControlCollection ( TabControl owner ): base( owner ){ }
44 public override void Add( Control c ) {
45 if ( !( c is TabPage ) ) {
46 throw new ArgumentException();
48 base.Add(c);
49 if ( owner.IsHandleCreated )
50 ((TabControl) owner).addPage ( c, Count - 1);
53 public override void Clear () {
54 base.Clear ( );
55 if ( owner.IsHandleCreated )
56 ((TabControl) owner).removeAllTabs ( );
59 public override void Remove ( Control value ) {
60 int index = IndexOf ( value );
61 base.Remove ( value );
62 if ( index != -1 && owner.IsHandleCreated )
63 ((TabControl) owner).removeTab ( value, index );
67 private int selectedIndex;
68 private TabAlignment tabAlignment;
69 private bool multiline;
70 private TabAppearance appearance;
71 private TabDrawMode tabDrawMode;
72 private bool hotTrack;
73 private Point padding;
74 private Size itemSize;
75 private TabSizeMode sizeMode;
76 private bool showTooltips;
77 private ImageList imageList;
79 public TabControl() {
80 SubClassWndProc_ = true;
81 selectedIndex = -1;
82 multiline = false;
83 tabAlignment = TabAlignment.Top;
84 appearance = TabAppearance.Normal;
85 tabDrawMode = TabDrawMode.Normal;
86 hotTrack = false;
87 padding = new Point ( 6, 3 );
88 itemSize = Size.Empty;
89 sizeMode = TabSizeMode.Normal;
90 showTooltips = false;
93 public TabAlignment Alignment {
94 get {
95 return tabAlignment;
97 set {
98 if ( !Enum.IsDefined ( typeof(TabAlignment), value ) )
99 throw new InvalidEnumArgumentException( "Alignment",
100 (int)value,
101 typeof(TabAlignment));
103 if ( tabAlignment != value ) {
104 if ( value == TabAlignment.Right ||
105 value == TabAlignment.Left )
106 multiline = true;
108 tabAlignment = value;
110 recreate ( );
115 public TabAppearance Appearance {
116 get { return appearance; }
117 set {
118 if ( !Enum.IsDefined ( typeof(TabAppearance), value ) )
119 throw new InvalidEnumArgumentException( "Appearance",
120 (int)value,
121 typeof(TabAppearance));
123 if ( appearance != value ) {
124 appearance = value;
126 recreate ( );
131 [EditorBrowsable (EditorBrowsableState.Never)]
132 public override Color BackColor {
133 get { return base.BackColor; }
134 set { base.BackColor = value; }
137 [EditorBrowsable (EditorBrowsableState.Never)]
138 public override Image BackgroundImage {
139 get { return base.BackgroundImage; }
140 set { base.BackgroundImage = value;}
143 public override Rectangle DisplayRectangle {
144 get {
145 RECT rect = new RECT( );
146 Rectangle disp = base.DisplayRectangle;
148 rect.left = disp.Left;
149 rect.top = disp.Top;
150 rect.right= disp.Right;
151 rect.bottom = disp.Bottom;
153 Win32.SendMessage ( Handle, (int)TabControlMessages.TCM_ADJUSTRECT, 0, ref rect );
155 return new Rectangle ( rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
159 public TabDrawMode DrawMode {
160 get { return tabDrawMode; }
161 set {
162 if ( !Enum.IsDefined ( typeof(TabDrawMode), value ) )
163 throw new InvalidEnumArgumentException( "DrawMode",
164 (int)value,
165 typeof(TabDrawMode));
167 if ( tabDrawMode != value ) {
168 tabDrawMode = value;
170 recreate ( );
175 [EditorBrowsable (EditorBrowsableState.Never)]
176 public override Color ForeColor {
177 get { return base.ForeColor; }
178 set { base.ForeColor = value; }
181 public bool HotTrack {
182 get { return hotTrack; }
183 set {
184 if ( hotTrack != value ) {
185 hotTrack = value;
187 recreate ( );
192 public ImageList ImageList {
193 get { return imageList; }
194 set {
195 if ( imageList != value ) {
196 imageList = value;
197 if ( IsHandleCreated )
198 setImageList ( imageList != null ? imageList.Handle : IntPtr.Zero );
203 [MonoTODO]
204 public Size ItemSize {
205 get { return itemSize; } // FIXME: don't know how to get size initially
206 set {
207 if ( itemSize != value ) {
208 if ( value.Width < 0 || value.Height < 0 )
209 throw new ArgumentException ( ); // FIXME: message
211 itemSize = value;
213 if ( IsHandleCreated )
214 setItemSize ( );
219 public bool Multiline {
220 get { return multiline; }
221 set {
222 if ( multiline != value ) {
223 multiline = value;
225 if ( multiline == false && ( Alignment == TabAlignment.Left ||
226 Alignment == TabAlignment.Right ) )
227 tabAlignment = TabAlignment.Top;
229 recreate ( );
234 public Point Padding {
235 get { return padding; }
236 set {
237 if ( padding != value ) {
238 if ( value.X < 0 || value.Y < 0 )
239 throw new ArgumentException (
240 string.Format ( "'{0}' is not a valid value for 'Padding'.", value ) );
242 padding = value;
244 if ( IsHandleCreated )
245 setPadding ( );
250 public int RowCount {
251 get {
252 if ( TabCount == 0)
253 return 0;
254 if ( Multiline == false )
255 return 1;
256 // referencing this property creates handle in ms.swf
257 return Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_GETROWCOUNT, 0, 0);
261 public int SelectedIndex {
262 get { return selectedIndex; }
263 set {
264 if ( selectedIndex != value ) {
265 if ( value < -1 )
266 throw new ArgumentException (
267 string.Format( " '{0}' is not a valid value for 'value'. 'value' must be greater than or equal to -1.", value ) );
269 selectedIndex = value;
271 if ( IsHandleCreated )
272 selectPage ( selectedIndex );
277 public TabPage SelectedTab {
278 get {
279 if ( SelectedIndex >= 0 )
280 return TabPages[ SelectedIndex ];
281 return null;
283 set {
284 int index = TabPages.IndexOf ( value );
285 if ( index >= 0 )
286 SelectedIndex = index;
290 public bool ShowToolTips {
291 get { return showTooltips; }
292 set {
293 if ( showTooltips != value ) {
294 showTooltips = value;
296 recreate ( );
301 public TabSizeMode SizeMode {
302 get { return sizeMode; }
303 set {
304 if ( !Enum.IsDefined ( typeof(TabSizeMode), value ) )
305 throw new InvalidEnumArgumentException( "SizeMode",
306 (int)value,
307 typeof(TabSizeMode));
309 if ( sizeMode != value ) {
310 sizeMode = value;
312 recreate ( );
317 public int TabCount {
318 get { return Controls.Count; }
321 public TabControl.TabPageCollection TabPages {
322 get { return new TabPageCollection ( this ); }
325 [EditorBrowsable (EditorBrowsableState.Never)]
326 public override string Text {
327 get { return base.Text; }
328 set { base.Text = value;}
331 public Rectangle GetTabRect( int index ) {
332 if ( index < 0 || index >= TabCount )
333 throw new ArgumentOutOfRangeException( "index" );
334 RECT rect = new RECT();
335 Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_GETITEMRECT, index, ref rect );
336 return new Rectangle( rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top );
340 public override string ToString() {
341 string str = GetType().FullName.ToString () + ", TabPages.Count: ";
342 str += TabCount.ToString ( );
343 for ( int i = 0; i < TabPages.Count ; i++ ) {
345 str += ", TabPage[" + i + "]: " + TabPages[i].ToString ( );
347 return str;
350 public event DrawItemEventHandler DrawItem;
351 public event EventHandler SelectedIndexChanged;
353 [MonoTODO]
354 protected override CreateParams CreateParams {
355 get {
356 CreateParams createParams = base.CreateParams;
357 createParams.ClassName = Win32.TABCONTROL;
358 createParams.Style = (int) ( WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE | WindowStyles.WS_OVERLAPPED ) |
359 (int) ( TabControlStyles.TCS_RAGGEDRIGHT );
361 if ( Multiline )
362 createParams.Style |= (int) TabControlStyles.TCS_MULTILINE;
364 if (DrawMode == TabDrawMode.OwnerDrawFixed)
365 createParams.Style |= (int) TabControlStyles.TCS_OWNERDRAWFIXED;
367 if ( HotTrack )
368 createParams.Style |= (int) TabControlStyles.TCS_HOTTRACK;
370 if ( ShowToolTips )
371 createParams.Style |= (int) TabControlStyles.TCS_TOOLTIPS;
373 switch ( Alignment ) {
374 case TabAlignment.Bottom:
375 createParams.Style |= (int) TabControlStyles.TCS_BOTTOM;
376 break;
377 case TabAlignment.Left:
378 createParams.Style |= (int) TabControlStyles.TCS_VERTICAL;
379 break;
380 case TabAlignment.Right:
381 createParams.Style |= (int) ( TabControlStyles.TCS_RIGHT | TabControlStyles.TCS_VERTICAL );
382 break;
385 switch ( Appearance ) {
386 case TabAppearance.Buttons:
387 createParams.Style |= (int) TabControlStyles.TCS_BUTTONS;
388 break;
389 case TabAppearance.FlatButtons:
390 createParams.Style |= (int) TabControlStyles.TCS_FLATBUTTONS;
391 break;
392 case TabAppearance.Normal:
393 createParams.Style |= (int) TabControlStyles.TCS_TABS;
394 break;
397 switch ( SizeMode ) {
398 case TabSizeMode.Fixed:
399 createParams.Style |= (int) TabControlStyles.TCS_FIXEDWIDTH;
400 break;
401 case TabSizeMode.FillToRight:
402 createParams.Style |= (int) TabControlStyles.TCS_RIGHTJUSTIFY;
403 break;
406 return createParams;
410 protected override Size DefaultSize {
411 get { return new System.Drawing.Size(200, 100); }
414 protected override Control.ControlCollection CreateControlsInstance() {
415 return new ControlCollection ( this );
418 protected override void CreateHandle() {
419 initCommonControlsLibrary ( );
420 base.CreateHandle();
423 [MonoTODO]
424 protected override void Dispose(bool disposing) { // .NET V1.1 Beta. .needs implmentation
425 base.Dispose(disposing);
428 [MonoTODO]
429 protected override bool IsInputKey(Keys keyData) {
430 return false;
433 [MonoTODO]
434 protected virtual void OnDrawItem(DrawItemEventArgs e) {
435 throw new NotImplementedException ();
438 [MonoTODO]
439 protected override void OnFontChanged(EventArgs e) {
440 throw new NotImplementedException ();
443 [MonoTODO]
444 protected override void OnHandleCreated(EventArgs e) {
445 base.OnHandleCreated ( e );
446 setPages ( );
447 setPadding ( );
448 setItemSize ( );
449 if ( imageList != null )
450 setImageList ( imageList.Handle );
453 [MonoTODO]
454 protected override void OnHandleDestroyed(EventArgs e) {
455 base.OnHandleDestroyed ( e );
458 [MonoTODO]
459 protected override void OnKeyDown(KeyEventArgs ke) {
460 base.OnKeyDown( ke );
463 [MonoTODO]
464 protected override void OnResize(EventArgs e) {
465 for ( int i = 0; i < Controls.Count; i++ )
466 Controls[ i ].SetBounds ( 0, 0, 0, 0, BoundsSpecified.None );
468 base.OnResize ( e );
471 protected virtual void OnSelectedIndexChanged(EventArgs e) {
472 if ( SelectedIndexChanged != null )
473 SelectedIndexChanged ( this, e );
476 [MonoTODO]
477 protected override void OnStyleChanged(EventArgs e) {
478 throw new NotImplementedException ();
481 [MonoTODO]
482 protected override bool ProcessKeyPreview(ref Message m) {
483 return base.ProcessKeyPreview( ref m );
486 protected void RemoveAll() {
487 Controls.Clear ( );
490 protected override void OnCreateControl () {
491 // create pages as needed
494 [MonoTODO]
495 protected override void WndProc(ref Message m) {
496 switch ((Msg) m.Msg ) {
497 case Msg.WM_NOTIFY:
498 NMHDR nmhdr = (NMHDR)Marshal.PtrToStructure ( m.LParam, typeof ( NMHDR ) );
499 switch ( nmhdr.code ) {
500 case (int)TabControlNotifications.TCN_SELCHANGE:
501 selectedIndex = Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_GETCURSEL, 0, 0);
502 updatePage ( selectedIndex , true );
503 OnSelectedIndexChanged ( EventArgs.Empty );
504 break;
505 case (int)TabControlNotifications.TCN_SELCHANGING:
506 m.Result = IntPtr.Zero;
507 break;
509 break;
510 default:
511 base.WndProc ( ref m );
512 break;
516 private void initCommonControlsLibrary ( ) {
517 if ( !RecreatingHandle ) {
518 INITCOMMONCONTROLSEX initEx = new INITCOMMONCONTROLSEX();
519 initEx.dwICC = CommonControlInitFlags.ICC_TAB_CLASSES;
520 Win32.InitCommonControlsEx(initEx);
524 private void update ( ) {
527 private void updatePage ( int index , bool doShowOrHide ) {
528 if ( Controls.Count != 0 && index >=0 && index < Controls.Count ) {
529 Control c = Controls[ index ];
531 if ( c.Created == false )
532 c.CreateControl ( );
534 c.SetBounds ( 0, 0, 0, 0, BoundsSpecified.None );
535 if ( doShowOrHide )
536 showOrHidePages( index );
540 private void setPages ( ) {
541 for (int i = 0; i < Controls.Count; i++ )
542 addPage ( Controls[i], i );
545 private void addPage ( Control page, int index ) {
546 TabPage tabPage = page as TabPage;
547 if ( tabPage.isAdded )
548 return;
550 TCITEM header = new TCITEM();
551 header.mask = (uint) ( TabControlItemFlags.TCIF_TEXT | TabControlItemFlags.TCIF_IMAGE );
552 header.pszText = tabPage.Text;
553 header.iImage = tabPage.ImageIndex;
555 sendMessageHelper ( TabControlMessages.TCM_INSERTITEM, index, ref header );
556 tabPage.isAdded = true;
558 if ( !RecreatingHandle && index == SelectedIndex )
559 selectPage ( index );
562 internal void pageTextChanged ( TabPage page ) {
563 if ( IsHandleCreated ) {
564 int index = Controls.IndexOf ( page );
565 if ( index != -1 ) {
566 TCITEM header = new TCITEM();
567 header.mask = (uint) TabControlItemFlags.TCIF_TEXT;
568 header.pszText = page.Text;
570 sendMessageHelper ( TabControlMessages.TCM_SETITEM, index, ref header );
575 internal void pageImageIndexChanged ( TabPage page ) {
576 if ( IsHandleCreated ) {
577 int index = Controls.IndexOf ( page );
578 if ( index != -1 ) {
579 TCITEM header = new TCITEM();
580 header.mask = (uint) TabControlItemFlags.TCIF_IMAGE;
581 header.iImage = page.ImageIndex;
583 sendMessageHelper ( TabControlMessages.TCM_SETITEM, index, ref header );
588 private void sendMessageHelper ( TabControlMessages mes, int index, ref TCITEM hdr ) {
589 if ( IsHandleCreated ) {
590 IntPtr ptr = Marshal.AllocHGlobal ( Marshal.SizeOf ( hdr ) );
591 Marshal.StructureToPtr( hdr, ptr, false );
592 Win32.SendMessage ( Handle , (int)mes, index, ptr.ToInt32() );
593 Marshal.FreeHGlobal ( ptr );
597 private void setPadding ( ) {
598 Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETPADDING, 0, Win32.MAKELONG ( Padding.X, Padding.Y ) );
601 private void setItemSize ( ) {
602 if ( ItemSize != Size.Empty ) {
603 Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETITEMSIZE, 0, Win32.MAKELONG ( ItemSize.Width, ItemSize.Height ) );
607 private void selectPage ( int selectedIndex ) {
608 if ( selectedIndex != -1 ) {
609 if ( Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETCURSEL, selectedIndex, 0 ) != -1 )
610 OnSelectedIndexChanged ( EventArgs.Empty );
612 updatePage ( selectedIndex != -1 ? selectedIndex : 0 , true );
615 private void removeAllTabs ( ) {
616 for (int i = 0; i < Controls.Count; i++ )
617 ( ( TabPage ) Controls[i] ).isAdded = false;
619 if ( IsHandleCreated )
620 Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_DELETEALLITEMS, 0, 0 );
623 private void removeTab ( Control c, int index ) {
624 if ( IsHandleCreated )
625 Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_DELETEITEM, index, 0 );
626 ( ( TabPage ) c ).isAdded = false;
629 private void showOrHidePages ( int index ) {
630 for (int i = 0; i < Controls.Count; i++ )
631 Controls[i].Visible = ( i == index ) ? true : false;
634 private void setImageList ( IntPtr handle )
636 Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETIMAGELIST, 0, handle.ToInt32 ( ) );
638 int CurrentPage = SelectedIndex;
639 updatePage ( CurrentPage, false );
641 if ( Controls.Count != 0 && CurrentPage >=0 && CurrentPage < Controls.Count )
642 Controls [ CurrentPage ].Invalidate ( true );
645 private void recreate ( ) {
646 removeAllTabs ( );
648 if ( IsHandleCreated ) {
649 RecreateHandle ( );
650 selectPage ( SelectedIndex );
654 public class TabPageCollection : IList, ICollection, IEnumerable {
655 TabControl owner;
656 Control.ControlCollection collection;
658 public TabPageCollection( TabControl owner ) {
659 this.owner = owner;
660 collection = owner.Controls;
663 public int Count {
664 get { return collection.Count; }
667 public bool IsReadOnly {
668 get { return collection.IsReadOnly; }
671 [MonoTODO]
672 public virtual TabPage this[int index] {
673 get { return collection[ index ] as TabPage; }
674 set {
675 ( (IList)collection )[ index ] = value;
676 owner.update ( );
680 public void Add(TabPage value) {
681 collection.Add ( value );
684 public void AddRange( TabPage[] pages ) {
685 collection.AddRange ( pages );
688 public virtual void Clear() {
689 collection.Clear ( );
692 public bool Contains( TabPage page ) {
693 return collection.Contains ( page );
696 public IEnumerator GetEnumerator() {
697 return collection.GetEnumerator ( );
700 public int IndexOf( TabPage page ) {
701 return collection.IndexOf ( page );
704 public void Remove( TabPage value ) {
705 collection.Remove ( value );
708 public void RemoveAt(int index) {
709 collection.RemoveAt ( index );
712 /// <summary>
713 /// IList Interface implmentation.
714 /// </summary>
715 bool IList.IsReadOnly{
716 get{ return this.IsReadOnly; }
719 bool IList.IsFixedSize{
720 get{ return (( IList )collection).IsFixedSize; }
723 object IList.this[int index]{
724 get{ return collection [ index ]; }
725 set{ if ( ! (value is TabPage) )
726 throw new ArgumentException ( );
727 this[ index ] = (TabPage) value;
728 owner.update ( );
732 void IList.Clear(){
733 this.Clear ( );
736 [MonoTODO]
737 int IList.Add( object value ) {
738 TabPage page = value as TabPage;
739 if ( page == null )
740 throw new ArgumentException ( );
741 this.Add ( page );
742 return this.IndexOf ( page );
745 [MonoTODO]
746 bool IList.Contains( object value ){
747 return this.Contains ( value as TabPage );
750 [MonoTODO]
751 int IList.IndexOf( object value ){
752 return this.IndexOf ( value as TabPage );
755 [MonoTODO]
756 void IList.Insert(int index, object value){
757 if ( ! (value is TabPage) )
758 throw new ArgumentException ( );
760 (( IList )collection).Insert ( index, value );
761 owner.update ( );
764 void IList.Remove( object value ){
765 this.Remove ( value as TabPage );
768 void IList.RemoveAt( int index){
769 this.RemoveAt ( index );
771 // End of IList interface
773 /// <summary>
774 /// ICollection Interface implmentation.
775 /// </summary>
776 int ICollection.Count{
777 get{ return this.Count; }
780 bool ICollection.IsSynchronized{
781 get{ return ( (ICollection) collection).IsSynchronized; }
784 object ICollection.SyncRoot{
785 get{ return ( (ICollection) collection).SyncRoot; }
788 void ICollection.CopyTo(Array array, int index){
789 ( (ICollection) collection ).CopyTo ( array, index );
791 // End Of ICollection