//
// System.Windows.Forms.TabControl.cs
//
// Author:
// stubbed out by Jackson Harper (jackson@latitudegeo.com)
// Dennis Hayes (dennish@Raytek.com)
// implemented by Aleksey Ryabchuk (ryabchuk@yahoo.com)
// (C) 2002 Ximian, Inc
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.ComponentModel;
using System.Collections;
using System.Drawing;
using System.Runtime.InteropServices;
namespace System.Windows.Forms{
public class TabControl : Control {
public class ControlCollection : Control.ControlCollection {
public ControlCollection ( TabControl owner ): base( owner ){ }
public override void Add( Control c ) {
if ( !( c is TabPage ) ) {
throw new ArgumentException();
}
base.Add(c);
if ( owner.IsHandleCreated )
((TabControl) owner).addPage ( c, Count - 1);
}
public override void Clear () {
base.Clear ( );
if ( owner.IsHandleCreated )
((TabControl) owner).removeAllTabs ( );
}
public override void Remove ( Control value ) {
int index = IndexOf ( value );
base.Remove ( value );
if ( index != -1 && owner.IsHandleCreated )
((TabControl) owner).removeTab ( value, index );
}
}
private int selectedIndex;
private TabAlignment tabAlignment;
private bool multiline;
private TabAppearance appearance;
private TabDrawMode tabDrawMode;
private bool hotTrack;
private Point padding;
private Size itemSize;
private TabSizeMode sizeMode;
private bool showTooltips;
private ImageList imageList;
public TabControl() {
SubClassWndProc_ = true;
selectedIndex = -1;
multiline = false;
tabAlignment = TabAlignment.Top;
appearance = TabAppearance.Normal;
tabDrawMode = TabDrawMode.Normal;
hotTrack = false;
padding = new Point ( 6, 3 );
itemSize = Size.Empty;
sizeMode = TabSizeMode.Normal;
showTooltips = false;
}
public TabAlignment Alignment {
get {
return tabAlignment;
}
set {
if ( !Enum.IsDefined ( typeof(TabAlignment), value ) )
throw new InvalidEnumArgumentException( "Alignment",
(int)value,
typeof(TabAlignment));
if ( tabAlignment != value ) {
if ( value == TabAlignment.Right ||
value == TabAlignment.Left )
multiline = true;
tabAlignment = value;
recreate ( );
}
}
}
public TabAppearance Appearance {
get { return appearance; }
set {
if ( !Enum.IsDefined ( typeof(TabAppearance), value ) )
throw new InvalidEnumArgumentException( "Appearance",
(int)value,
typeof(TabAppearance));
if ( appearance != value ) {
appearance = value;
recreate ( );
}
}
}
[EditorBrowsable (EditorBrowsableState.Never)]
public override Color BackColor {
get { return base.BackColor; }
set { base.BackColor = value; }
}
[EditorBrowsable (EditorBrowsableState.Never)]
public override Image BackgroundImage {
get { return base.BackgroundImage; }
set { base.BackgroundImage = value;}
}
public override Rectangle DisplayRectangle {
get {
RECT rect = new RECT( );
Rectangle disp = base.DisplayRectangle;
rect.left = disp.Left;
rect.top = disp.Top;
rect.right= disp.Right;
rect.bottom = disp.Bottom;
Win32.SendMessage ( Handle, (int)TabControlMessages.TCM_ADJUSTRECT, 0, ref rect );
return new Rectangle ( rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
}
}
public TabDrawMode DrawMode {
get { return tabDrawMode; }
set {
if ( !Enum.IsDefined ( typeof(TabDrawMode), value ) )
throw new InvalidEnumArgumentException( "DrawMode",
(int)value,
typeof(TabDrawMode));
if ( tabDrawMode != value ) {
tabDrawMode = value;
recreate ( );
}
}
}
[EditorBrowsable (EditorBrowsableState.Never)]
public override Color ForeColor {
get { return base.ForeColor; }
set { base.ForeColor = value; }
}
public bool HotTrack {
get { return hotTrack; }
set {
if ( hotTrack != value ) {
hotTrack = value;
recreate ( );
}
}
}
public ImageList ImageList {
get { return imageList; }
set {
if ( imageList != value ) {
imageList = value;
if ( IsHandleCreated )
setImageList ( imageList != null ? imageList.Handle : IntPtr.Zero );
}
}
}
[MonoTODO]
public Size ItemSize {
get { return itemSize; } // FIXME: don't know how to get size initially
set {
if ( itemSize != value ) {
if ( value.Width < 0 || value.Height < 0 )
throw new ArgumentException ( ); // FIXME: message
itemSize = value;
if ( IsHandleCreated )
setItemSize ( );
}
}
}
public bool Multiline {
get { return multiline; }
set {
if ( multiline != value ) {
multiline = value;
if ( multiline == false && ( Alignment == TabAlignment.Left ||
Alignment == TabAlignment.Right ) )
tabAlignment = TabAlignment.Top;
recreate ( );
}
}
}
public Point Padding {
get { return padding; }
set {
if ( padding != value ) {
if ( value.X < 0 || value.Y < 0 )
throw new ArgumentException (
string.Format ( "'{0}' is not a valid value for 'Padding'.", value ) );
padding = value;
if ( IsHandleCreated )
setPadding ( );
}
}
}
public int RowCount {
get {
if ( TabCount == 0)
return 0;
if ( Multiline == false )
return 1;
// referencing this property creates handle in ms.swf
return Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_GETROWCOUNT, 0, 0);
}
}
public int SelectedIndex {
get { return selectedIndex; }
set {
if ( selectedIndex != value ) {
if ( value < -1 )
throw new ArgumentException (
string.Format( " '{0}' is not a valid value for 'value'. 'value' must be greater than or equal to -1.", value ) );
selectedIndex = value;
if ( IsHandleCreated )
selectPage ( selectedIndex );
}
}
}
public TabPage SelectedTab {
get {
if ( SelectedIndex >= 0 )
return TabPages[ SelectedIndex ];
return null;
}
set {
int index = TabPages.IndexOf ( value );
if ( index >= 0 )
SelectedIndex = index;
}
}
public bool ShowToolTips {
get { return showTooltips; }
set {
if ( showTooltips != value ) {
showTooltips = value;
recreate ( );
}
}
}
public TabSizeMode SizeMode {
get { return sizeMode; }
set {
if ( !Enum.IsDefined ( typeof(TabSizeMode), value ) )
throw new InvalidEnumArgumentException( "SizeMode",
(int)value,
typeof(TabSizeMode));
if ( sizeMode != value ) {
sizeMode = value;
recreate ( );
}
}
}
public int TabCount {
get { return Controls.Count; }
}
public TabControl.TabPageCollection TabPages {
get { return new TabPageCollection ( this ); }
}
[EditorBrowsable (EditorBrowsableState.Never)]
public override string Text {
get { return base.Text; }
set { base.Text = value;}
}
public Rectangle GetTabRect( int index ) {
if ( index < 0 || index >= TabCount )
throw new ArgumentOutOfRangeException( "index" );
RECT rect = new RECT();
Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_GETITEMRECT, index, ref rect );
return new Rectangle( rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top );
}
public override string ToString() {
string str = GetType().FullName.ToString () + ", TabPages.Count: ";
str += TabCount.ToString ( );
for ( int i = 0; i < TabPages.Count ; i++ ) {
str += ", TabPage[" + i + "]: " + TabPages[i].ToString ( );
}
return str;
}
public event DrawItemEventHandler DrawItem;
public event EventHandler SelectedIndexChanged;
[MonoTODO]
protected override CreateParams CreateParams {
get {
CreateParams createParams = base.CreateParams;
createParams.ClassName = Win32.TABCONTROL;
createParams.Style = (int) ( WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE | WindowStyles.WS_OVERLAPPED ) |
(int) ( TabControlStyles.TCS_RAGGEDRIGHT );
if ( Multiline )
createParams.Style |= (int) TabControlStyles.TCS_MULTILINE;
if (DrawMode == TabDrawMode.OwnerDrawFixed)
createParams.Style |= (int) TabControlStyles.TCS_OWNERDRAWFIXED;
if ( HotTrack )
createParams.Style |= (int) TabControlStyles.TCS_HOTTRACK;
if ( ShowToolTips )
createParams.Style |= (int) TabControlStyles.TCS_TOOLTIPS;
switch ( Alignment ) {
case TabAlignment.Bottom:
createParams.Style |= (int) TabControlStyles.TCS_BOTTOM;
break;
case TabAlignment.Left:
createParams.Style |= (int) TabControlStyles.TCS_VERTICAL;
break;
case TabAlignment.Right:
createParams.Style |= (int) ( TabControlStyles.TCS_RIGHT | TabControlStyles.TCS_VERTICAL );
break;
}
switch ( Appearance ) {
case TabAppearance.Buttons:
createParams.Style |= (int) TabControlStyles.TCS_BUTTONS;
break;
case TabAppearance.FlatButtons:
createParams.Style |= (int) TabControlStyles.TCS_FLATBUTTONS;
break;
case TabAppearance.Normal:
createParams.Style |= (int) TabControlStyles.TCS_TABS;
break;
}
switch ( SizeMode ) {
case TabSizeMode.Fixed:
createParams.Style |= (int) TabControlStyles.TCS_FIXEDWIDTH;
break;
case TabSizeMode.FillToRight:
createParams.Style |= (int) TabControlStyles.TCS_RIGHTJUSTIFY;
break;
}
return createParams;
}
}
protected override Size DefaultSize {
get { return new System.Drawing.Size(200, 100); }
}
protected override Control.ControlCollection CreateControlsInstance() {
return new ControlCollection ( this );
}
protected override void CreateHandle() {
initCommonControlsLibrary ( );
base.CreateHandle();
}
[MonoTODO]
protected override void Dispose(bool disposing) { // .NET V1.1 Beta. .needs implmentation
base.Dispose(disposing);
}
[MonoTODO]
protected override bool IsInputKey(Keys keyData) {
return false;
}
[MonoTODO]
protected virtual void OnDrawItem(DrawItemEventArgs e) {
throw new NotImplementedException ();
}
[MonoTODO]
protected override void OnFontChanged(EventArgs e) {
throw new NotImplementedException ();
}
[MonoTODO]
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated ( e );
setPages ( );
setPadding ( );
setItemSize ( );
if ( imageList != null )
setImageList ( imageList.Handle );
}
[MonoTODO]
protected override void OnHandleDestroyed(EventArgs e) {
base.OnHandleDestroyed ( e );
}
[MonoTODO]
protected override void OnKeyDown(KeyEventArgs ke) {
base.OnKeyDown( ke );
}
[MonoTODO]
protected override void OnResize(EventArgs e) {
for ( int i = 0; i < Controls.Count; i++ )
Controls[ i ].SetBounds ( 0, 0, 0, 0, BoundsSpecified.None );
base.OnResize ( e );
}
protected virtual void OnSelectedIndexChanged(EventArgs e) {
if ( SelectedIndexChanged != null )
SelectedIndexChanged ( this, e );
}
[MonoTODO]
protected override void OnStyleChanged(EventArgs e) {
throw new NotImplementedException ();
}
[MonoTODO]
protected override bool ProcessKeyPreview(ref Message m) {
return base.ProcessKeyPreview( ref m );
}
protected void RemoveAll() {
Controls.Clear ( );
}
protected override void OnCreateControl () {
// create pages as needed
}
[MonoTODO]
protected override void WndProc(ref Message m) {
switch ((Msg) m.Msg ) {
case Msg.WM_NOTIFY:
NMHDR nmhdr = (NMHDR)Marshal.PtrToStructure ( m.LParam, typeof ( NMHDR ) );
switch ( nmhdr.code ) {
case (int)TabControlNotifications.TCN_SELCHANGE:
selectedIndex = Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_GETCURSEL, 0, 0);
updatePage ( selectedIndex , true );
OnSelectedIndexChanged ( EventArgs.Empty );
break;
case (int)TabControlNotifications.TCN_SELCHANGING:
m.Result = IntPtr.Zero;
break;
}
break;
default:
base.WndProc ( ref m );
break;
}
}
private void initCommonControlsLibrary ( ) {
if ( !RecreatingHandle ) {
INITCOMMONCONTROLSEX initEx = new INITCOMMONCONTROLSEX();
initEx.dwICC = CommonControlInitFlags.ICC_TAB_CLASSES;
Win32.InitCommonControlsEx(initEx);
}
}
private void update ( ) {
}
private void updatePage ( int index , bool doShowOrHide ) {
if ( Controls.Count != 0 && index >=0 && index < Controls.Count ) {
Control c = Controls[ index ];
if ( c.Created == false )
c.CreateControl ( );
c.SetBounds ( 0, 0, 0, 0, BoundsSpecified.None );
if ( doShowOrHide )
showOrHidePages( index );
}
}
private void setPages ( ) {
for (int i = 0; i < Controls.Count; i++ )
addPage ( Controls[i], i );
}
private void addPage ( Control page, int index ) {
TabPage tabPage = page as TabPage;
if ( tabPage.isAdded )
return;
TCITEM header = new TCITEM();
header.mask = (uint) ( TabControlItemFlags.TCIF_TEXT | TabControlItemFlags.TCIF_IMAGE );
header.pszText = tabPage.Text;
header.iImage = tabPage.ImageIndex;
sendMessageHelper ( TabControlMessages.TCM_INSERTITEM, index, ref header );
tabPage.isAdded = true;
if ( !RecreatingHandle && index == SelectedIndex )
selectPage ( index );
}
internal void pageTextChanged ( TabPage page ) {
if ( IsHandleCreated ) {
int index = Controls.IndexOf ( page );
if ( index != -1 ) {
TCITEM header = new TCITEM();
header.mask = (uint) TabControlItemFlags.TCIF_TEXT;
header.pszText = page.Text;
sendMessageHelper ( TabControlMessages.TCM_SETITEM, index, ref header );
}
}
}
internal void pageImageIndexChanged ( TabPage page ) {
if ( IsHandleCreated ) {
int index = Controls.IndexOf ( page );
if ( index != -1 ) {
TCITEM header = new TCITEM();
header.mask = (uint) TabControlItemFlags.TCIF_IMAGE;
header.iImage = page.ImageIndex;
sendMessageHelper ( TabControlMessages.TCM_SETITEM, index, ref header );
}
}
}
private void sendMessageHelper ( TabControlMessages mes, int index, ref TCITEM hdr ) {
if ( IsHandleCreated ) {
IntPtr ptr = Marshal.AllocHGlobal ( Marshal.SizeOf ( hdr ) );
Marshal.StructureToPtr( hdr, ptr, false );
Win32.SendMessage ( Handle , (int)mes, index, ptr.ToInt32() );
Marshal.FreeHGlobal ( ptr );
}
}
private void setPadding ( ) {
Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETPADDING, 0, Win32.MAKELONG ( Padding.X, Padding.Y ) );
}
private void setItemSize ( ) {
if ( ItemSize != Size.Empty ) {
Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETITEMSIZE, 0, Win32.MAKELONG ( ItemSize.Width, ItemSize.Height ) );
}
}
private void selectPage ( int selectedIndex ) {
if ( selectedIndex != -1 ) {
if ( Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETCURSEL, selectedIndex, 0 ) != -1 )
OnSelectedIndexChanged ( EventArgs.Empty );
}
updatePage ( selectedIndex != -1 ? selectedIndex : 0 , true );
}
private void removeAllTabs ( ) {
for (int i = 0; i < Controls.Count; i++ )
( ( TabPage ) Controls[i] ).isAdded = false;
if ( IsHandleCreated )
Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_DELETEALLITEMS, 0, 0 );
}
private void removeTab ( Control c, int index ) {
if ( IsHandleCreated )
Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_DELETEITEM, index, 0 );
( ( TabPage ) c ).isAdded = false;
}
private void showOrHidePages ( int index ) {
for (int i = 0; i < Controls.Count; i++ )
Controls[i].Visible = ( i == index ) ? true : false;
}
private void setImageList ( IntPtr handle )
{
Win32.SendMessage ( Handle, (int) TabControlMessages.TCM_SETIMAGELIST, 0, handle.ToInt32 ( ) );
int CurrentPage = SelectedIndex;
updatePage ( CurrentPage, false );
if ( Controls.Count != 0 && CurrentPage >=0 && CurrentPage < Controls.Count )
Controls [ CurrentPage ].Invalidate ( true );
}
private void recreate ( ) {
removeAllTabs ( );
if ( IsHandleCreated ) {
RecreateHandle ( );
selectPage ( SelectedIndex );
}
}
public class TabPageCollection : IList, ICollection, IEnumerable {
TabControl owner;
Control.ControlCollection collection;
public TabPageCollection( TabControl owner ) {
this.owner = owner;
collection = owner.Controls;
}
public int Count {
get { return collection.Count; }
}
public bool IsReadOnly {
get { return collection.IsReadOnly; }
}
[MonoTODO]
public virtual TabPage this[int index] {
get { return collection[ index ] as TabPage; }
set {
( (IList)collection )[ index ] = value;
owner.update ( );
}
}
public void Add(TabPage value) {
collection.Add ( value );
}
public void AddRange( TabPage[] pages ) {
collection.AddRange ( pages );
}
public virtual void Clear() {
collection.Clear ( );
}
public bool Contains( TabPage page ) {
return collection.Contains ( page );
}
public IEnumerator GetEnumerator() {
return collection.GetEnumerator ( );
}
public int IndexOf( TabPage page ) {
return collection.IndexOf ( page );
}
public void Remove( TabPage value ) {
collection.Remove ( value );
}
public void RemoveAt(int index) {
collection.RemoveAt ( index );
}
/// <summary>
/// IList Interface implmentation.
/// </summary>
bool IList.IsReadOnly{
get{ return this.IsReadOnly; }
}
bool IList.IsFixedSize{
get{ return (( IList )collection).IsFixedSize; }
}
object IList.this[int index]{
get{ return collection [ index ]; }
set{ if ( ! (value is TabPage) )
throw new ArgumentException ( );
this[ index ] = (TabPage) value;
owner.update ( );
}
}
void IList.Clear(){
this.Clear ( );
}
[MonoTODO]
int IList.Add( object value ) {
TabPage page = value as TabPage;
if ( page == null )
throw new ArgumentException ( );
this.Add ( page );
return this.IndexOf ( page );
}
[MonoTODO]
bool IList.Contains( object value ){
return this.Contains ( value as TabPage );
}
[MonoTODO]
int IList.IndexOf( object value ){
return this.IndexOf ( value as TabPage );
}
[MonoTODO]
void IList.Insert(int index, object value){
if ( ! (value is TabPage) )
throw new ArgumentException ( );
(( IList )collection).Insert ( index, value );
owner.update ( );
}
void IList.Remove( object value ){
this.Remove ( value as TabPage );
}
void IList.RemoveAt( int index){
this.RemoveAt ( index );
}
// End of IList interface
/// <summary>
/// ICollection Interface implmentation.
/// </summary>
int ICollection.Count{
get{ return this.Count; }
}
bool ICollection.IsSynchronized{
get{ return ( (ICollection) collection).IsSynchronized; }
}
object ICollection.SyncRoot{
get{ return ( (ICollection) collection).SyncRoot; }
}
void ICollection.CopyTo(Array array, int index){
( (ICollection) collection ).CopyTo ( array, index );
}
// End Of ICollection
}
}
}
|