using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
-
+using System.Runtime.InteropServices;
+using System.Windows.Forms.Theming;
+using System.Windows.Forms.VisualStyles;
namespace System.Windows.Forms {
+#if NET_2_0
+ [ComVisibleAttribute (true)]
+ [ClassInterfaceAttribute (ClassInterfaceType.AutoDispatch)]
+#endif
[DefaultEvent("SelectedIndexChanged")]
[DefaultProperty("TabPages")]
[Designer("System.Windows.Forms.Design.TabControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
private bool multiline;
private ImageList image_list;
private Size item_size = Size.Empty;
+ private bool item_size_manual;
private Point padding;
private int row_count = 0;
private bool hottrack;
private bool show_tool_tips;
private TabSizeMode size_mode;
private bool show_slider = false;
- private ButtonState right_slider_state;
- private ButtonState left_slider_state;
+ private PushButtonState right_slider_state = PushButtonState.Normal;
+ private PushButtonState left_slider_state = PushButtonState.Normal;
private int slider_pos = 0;
+ TabPage entered_tab_page;
+ bool mouse_down_on_a_tab_page;
+ ToolTip tooltip;
+ ToolTip.TipState tooltip_state = ToolTip.TipState.Down;
+ Timer tooltip_timer;
+
+#if NET_2_0
+ private bool rightToLeftLayout;
+#endif
#endregion // Fields
+ #region UIA Framework Events
+#if NET_2_0
+ static object UIAHorizontallyScrollableChangedEvent = new object ();
+
+ internal event EventHandler UIAHorizontallyScrollableChanged {
+ add { Events.AddHandler (UIAHorizontallyScrollableChangedEvent, value); }
+ remove { Events.RemoveHandler (UIAHorizontallyScrollableChangedEvent, value); }
+ }
+
+ internal void OnUIAHorizontallyScrollableChanged (EventArgs e)
+ {
+ EventHandler eh
+ = (EventHandler) Events [UIAHorizontallyScrollableChangedEvent];
+ if (eh != null)
+ eh (this, e);
+ }
+
+ static object UIAHorizontallyScrolledEvent = new object ();
+
+ internal event EventHandler UIAHorizontallyScrolled {
+ add { Events.AddHandler (UIAHorizontallyScrolledEvent, value); }
+ remove { Events.RemoveHandler (UIAHorizontallyScrolledEvent, value); }
+ }
+
+ internal void OnUIAHorizontallyScrolled (EventArgs e)
+ {
+ EventHandler eh
+ = (EventHandler) Events [UIAHorizontallyScrolledEvent];
+ if (eh != null)
+ eh (this, e);
+ }
+#endif
+ #endregion
+
+ #region UIA Framework Property
+#if NET_2_0
+ internal double UIAHorizontalViewSize {
+ get { return LeftScrollButtonArea.Left * 100 / TabPages [TabCount - 1].TabBounds.Right; }
+ }
+#endif
+ #endregion
+
#region Public Constructors
public TabControl ()
{
tab_pages = new TabPageCollection (this);
SetStyle (ControlStyles.UserPaint, false);
padding = ThemeEngine.Current.TabControlDefaultPadding;
- item_size = ThemeEngine.Current.TabControlDefaultItemSize;
MouseDown += new MouseEventHandler (MouseDownHandler);
+ MouseLeave += new EventHandler (OnMouseLeave);
+ MouseMove += new MouseEventHandler (OnMouseMove);
MouseUp += new MouseEventHandler (MouseUpHandler);
SizeChanged += new EventHandler (SizeChangedHandler);
}
set { base.BackgroundImage = value; }
}
+#if NET_2_0
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public override ImageLayout BackgroundImageLayout {
+ get { return base.BackgroundImageLayout; }
+ set { base.BackgroundImageLayout = value; }
+ }
+#endif
+
public override Rectangle DisplayRectangle {
get {
- return ThemeEngine.Current.GetTabControlDisplayRectangle (this);
+ return ThemeEngine.Current.TabControlGetDisplayRectangle (this);
}
}
+#if NET_2_0
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ protected override bool DoubleBuffered {
+ get { return base.DoubleBuffered; }
+ set { base.DoubleBuffered = value; }
+ }
+#endif
+
[DefaultValue(TabDrawMode.Normal)]
public TabDrawMode DrawMode {
get { return draw_mode; }
}
}
+#if NET_2_0
+ [RefreshProperties (RefreshProperties.Repaint)]
+#endif
[DefaultValue(null)]
public ImageList ImageList {
get { return image_list; }
- set { image_list = value; }
+ set {
+ image_list = value;
+ Redraw ();
+ }
}
[Localizable(true)]
public Size ItemSize {
get {
- return item_size;
+ if (item_size_manual)
+ return item_size;
+
+ if (!IsHandleCreated)
+ return Size.Empty;
+
+ Size size = item_size;
+ if (SizeMode != TabSizeMode.Fixed) {
+ size.Width += padding.X * 2;
+ size.Height += padding.Y * 2;
+ }
+
+ if (tab_pages.Count == 0)
+ size.Width = 0;
+
+ return size;
}
set {
if (value.Height < 0 || value.Width < 0)
throw new ArgumentException ("'" + value + "' is not a valid value for 'ItemSize'.");
item_size = value;
+ item_size_manual = true;
Redraw ();
}
}
}
[Localizable(true)]
- public new Point Padding {
+ public
+#if NET_2_0
+ new
+#endif
+ Point Padding {
get { return padding; }
set {
if (value.X < 0 || value.Y < 0)
}
+#if NET_2_0
+ [MonoTODO ("RTL not supported")]
+ [Localizable (true)]
+ [DefaultValue (false)]
+ public virtual bool RightToLeftLayout {
+ get { return this.rightToLeftLayout; }
+ set {
+ if (value != this.rightToLeftLayout) {
+ this.rightToLeftLayout = value;
+ this.OnRightToLeftLayoutChanged (EventArgs.Empty);
+ }
+ }
+ }
+#endif
+
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int RowCount {
get { return selected_index; }
set {
- if (!this.IsHandleCreated) {
- selected_index = value;
- return;
- }
-
if (value < -1) {
+#if NET_2_0
+ throw new ArgumentOutOfRangeException ("SelectedIndex", "Value of '" + value + "' is valid for 'SelectedIndex'. " +
+ "'SelectedIndex' must be greater than or equal to -1.");
+#else
throw new ArgumentException ("'" + value + "' is not a valid value for 'value'. " +
"'value' must be greater than or equal to -1.");
+#endif
+ }
+ if (!this.IsHandleCreated) {
+ if (selected_index != value) {
+ selected_index = value;
+#if !NET_2_0
+ OnSelectedIndexChanged (EventArgs.Empty);
+#endif
+ }
+ return;
}
- if (value >= TabCount)
+ if (value >= TabCount) {
+ if (value != selected_index)
+ OnSelectedIndexChanged (EventArgs.Empty);
return;
+ }
if (value == selected_index) {
- Invalidate(GetTabRect (selected_index));
+ if (selected_index > -1)
+ Invalidate(GetTabRect (selected_index));
+ return;
+ }
+
+#if NET_2_0
+ TabControlCancelEventArgs ret = new TabControlCancelEventArgs (SelectedTab, selected_index, false, TabControlAction.Deselecting);
+ OnDeselecting (ret);
+ if (ret.Cancel)
+ return;
+
+#endif
+ Focus ();
+ int old_index = selected_index;
+ int new_index = value;
+
+ selected_index = new_index;
+
+#if NET_2_0
+ ret = new TabControlCancelEventArgs (SelectedTab, selected_index, false, TabControlAction.Selecting);
+ OnSelecting (ret);
+ if (ret.Cancel) {
+ selected_index = old_index;
return;
}
+#endif
SuspendLayout ();
Rectangle invalid = Rectangle.Empty;
bool refresh = false;
-
- if (value != -1 && show_slider && value < slider_pos) {
- slider_pos = value;
+
+ if (new_index != -1 && show_slider && new_index < slider_pos) {
+ slider_pos = new_index;
refresh = true;
}
- if (value != -1) {
- int le = TabPages [value].TabBounds.Right;
- int re = ThemeEngine.Current.GetTabControlLeftScrollRect (this).Left;
+ if (new_index != -1) {
+ int le = TabPages[new_index].TabBounds.Right;
+ int re = LeftScrollButtonArea.Left;
if (show_slider && le > re) {
int i = 0;
+ for (i = 0; i < new_index - 1; i++) {
+ if (TabPages [i].TabBounds.Left < 0) // tab scrolled off the visible area, ignore
+ continue;
- for (i = value; i < TabPages.Count; i++) {
- if (TabPages [i].TabBounds.Right > re)
+ if (TabPages [new_index].TabBounds.Right - TabPages[i].TabBounds.Right < re) {
+ i++;
break;
+ }
}
slider_pos = i;
refresh = true;
}
}
- if (selected_index != -1) {
+ if (old_index != -1 && new_index != -1) {
if (!refresh)
- invalid = GetTabRect (selected_index);
- ((TabPage) Controls [selected_index]).SetVisible (false);
+ invalid = GetTabRect (old_index);
+ ((TabPage) Controls[old_index]).SetVisible (false);
}
- selected_index = value;
-
- OnSelectedIndexChanged (EventArgs.Empty);
TabPage selected = null;
- if (selected_index != -1) {
- selected = (TabPage) Controls [selected_index];
- invalid = Rectangle.Union (invalid, GetTabRect (selected_index));
+ if (new_index != -1) {
+ selected = (TabPage) Controls[new_index];
+ invalid = Rectangle.Union (invalid, GetTabRect (new_index));
selected.SetVisible (true);
}
+ OnSelectedIndexChanged (EventArgs.Empty);
+
ResumeLayout ();
if (refresh) {
SizeTabs ();
Refresh ();
- } else if (selected_index != -1 && selected.Row != BottomRow) {
- DropRow (TabPages [selected_index].Row);
+ } else if (new_index != -1 && selected.Row != BottomRow) {
+ DropRow (TabPages[new_index].Row);
// calculating what to invalidate here seems to be slower then just
// refreshing the whole thing
SizeTabs ();
} else {
SizeTabs ();
// The lines are drawn on the edges of the tabs so the invalid area should
- // needs to include the extra pixels of line width.
+ // needs to include the extra pixels of line width (but should not
+ // overflow the control bounds).
if (appearance == TabAppearance.Normal) {
invalid.Inflate (6, 4);
+ invalid.Intersect (ClientRectangle);
}
Invalidate (invalid);
}
}
}
+#if NET_2_0
+ [Editor ("System.Windows.Forms.Design.TabPageCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
+#else
[DefaultValue(null)]
+#endif
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[MergableProperty(false)]
public TabPageCollection TabPages {
get { return base.Text; }
set { base.Text = value; }
}
-
#endregion // Public Instance Properties
#region Internal Properties
internal bool ShowSlider {
get { return show_slider; }
- set { show_slider = value; }
+ set {
+ show_slider = value;
+
+#if NET_2_0
+ // UIA Framework Event: HorizontallyScrollable Changed
+ OnUIAHorizontallyScrollableChanged (EventArgs.Empty);
+#endif
+ }
}
internal int SliderPos {
get { return slider_pos; }
}
- internal ButtonState RightSliderState {
+ internal PushButtonState RightSliderState {
get { return right_slider_state; }
+ private set {
+ if (right_slider_state == value)
+ return;
+ PushButtonState old_value = right_slider_state;
+ right_slider_state = value;
+ if (NeedsToInvalidateScrollButton (old_value, value))
+ Invalidate (RightScrollButtonArea);
+ }
}
- internal ButtonState LeftSliderState {
+ internal PushButtonState LeftSliderState {
get { return left_slider_state; }
+ set {
+ if (left_slider_state == value)
+ return;
+ PushButtonState old_value = left_slider_state;
+ left_slider_state = value;
+ if (NeedsToInvalidateScrollButton (old_value, value))
+ Invalidate (LeftScrollButtonArea);
+ }
+ }
+
+ bool NeedsToInvalidateScrollButton (PushButtonState oldState, PushButtonState newState)
+ {
+ if ((oldState == PushButtonState.Hot && newState == PushButtonState.Normal) ||
+ (oldState == PushButtonState.Normal && newState == PushButtonState.Hot))
+ return HasHotElementStyles;
+ return true;
}
+ internal TabPage EnteredTabPage {
+ get { return entered_tab_page; }
+ private set {
+ if (entered_tab_page == value)
+ return;
+ if (HasHotElementStyles) {
+ Region area_to_invalidate = new Region ();
+ area_to_invalidate.MakeEmpty ();
+ if (entered_tab_page != null)
+ area_to_invalidate.Union (entered_tab_page.TabBounds);
+ entered_tab_page = value;
+ if (entered_tab_page != null)
+ area_to_invalidate.Union (entered_tab_page.TabBounds);
+ Invalidate (area_to_invalidate);
+ area_to_invalidate.Dispose ();
+ } else
+ entered_tab_page = value;
+
+ if (value == null)
+ CloseToolTip ();
+ else
+ SetToolTip (GetToolTipText (value));
+ }
+ }
#endregion // Internal Properties
#region Protected Instance Properties
return GetTab (index);
}
+#if NET_2_0
+ public void SelectTab (TabPage tabPage)
+ {
+ if (tabPage == null)
+ throw new ArgumentNullException ("tabPage");
+
+ SelectTab (this.tab_pages [tabPage]);
+ }
+
+ public void SelectTab (string tabPageName)
+ {
+ if (tabPageName == null)
+ throw new ArgumentNullException ("tabPageName");
+
+ SelectTab (this.tab_pages [tabPageName]);
+ }
+
+ public void SelectTab (int index)
+ {
+ if (index < 0 || index > this.tab_pages.Count - 1)
+ throw new ArgumentOutOfRangeException ("index");
+
+ SelectedIndex = index;
+ }
+
+ public void DeselectTab (TabPage tabPage)
+ {
+ if (tabPage == null)
+ throw new ArgumentNullException ("tabPage");
+
+ DeselectTab (this.tab_pages [tabPage]);
+ }
+
+ public void DeselectTab (string tabPageName)
+ {
+ if (tabPageName == null)
+ throw new ArgumentNullException ("tabPageName");
+
+ DeselectTab (this.tab_pages [tabPageName]);
+ }
+
+ public void DeselectTab (int index)
+ {
+ if (index == SelectedIndex) {
+ if (index >= 0 && index < this.tab_pages.Count - 1)
+ SelectedIndex = ++index;
+ else
+ SelectedIndex = 0;
+ }
+ }
+
+#endif
+
public override string ToString ()
{
string res = String.Concat (base.ToString (),
#endregion // Public Instance Methods
#region Protected Instance Methods
+
+ #region Handles
protected override Control.ControlCollection CreateControlsInstance ()
{
return new TabControl.ControlCollection (this);
}
- protected void UpdateTabSelection (bool uiselected)
- {
- ResizeTabPages ();
- }
-
protected override void CreateHandle ()
{
base.CreateHandle ();
+ selected_index = (selected_index >= TabCount ? (TabCount > 0 ? 0 : -1) : selected_index);
+
+ if (TabCount > 0) {
+ if (selected_index > -1)
+ this.SelectedTab.SetVisible(true);
+ else
+ tab_pages[0].SetVisible(true);
+ }
ResizeTabPages ();
}
base.OnHandleDestroyed (e);
}
+ protected override void Dispose (bool disposing)
+ {
+ CloseToolTip ();
+ base.Dispose (disposing);
+ }
+
+ #endregion
+
+ #region Events
protected virtual void OnDrawItem (DrawItemEventArgs e)
{
if (DrawMode != TabDrawMode.OwnerDrawFixed)
base.OnStyleChanged (e);
}
+ protected virtual void OnSelectedIndexChanged (EventArgs e)
+ {
+ EventHandler eh = (EventHandler) (Events[SelectedIndexChangedEvent]);
+ if (eh != null)
+ eh (this, e);
+ }
+
+ internal override void OnPaintInternal (PaintEventArgs pe)
+ {
+ if (GetStyle (ControlStyles.UserPaint))
+ return;
+
+ Draw (pe.Graphics, pe.ClipRectangle);
+ pe.Handled = true;
+ }
+
+#if NET_2_0
+ protected override void OnEnter (EventArgs e)
+ {
+ base.OnEnter (e);
+ if (SelectedTab != null)
+ SelectedTab.FireEnter ();
+ }
+
+ protected override void OnLeave (EventArgs e)
+ {
+ if (SelectedTab != null)
+ SelectedTab.FireLeave ();
+ base.OnLeave (e);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Advanced)]
+ protected virtual void OnRightToLeftLayoutChanged (EventArgs e)
+ {
+ EventHandler eh = (EventHandler) (Events[RightToLeftLayoutChangedEvent]);
+ if (eh != null)
+ eh (this, e);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ protected override void ScaleCore (float dx, float dy)
+ {
+ base.ScaleCore (dx, dy);
+ }
+
+ protected virtual void OnDeselecting (TabControlCancelEventArgs e)
+ {
+ TabControlCancelEventHandler eh = (TabControlCancelEventHandler) (Events[DeselectingEvent]);
+ if (eh != null)
+ eh (this, e);
+
+ if (!e.Cancel)
+ OnDeselected (new TabControlEventArgs (SelectedTab, selected_index, TabControlAction.Deselected));
+ }
+
+ protected virtual void OnDeselected (TabControlEventArgs e)
+ {
+ TabControlEventHandler eh = (TabControlEventHandler) (Events[DeselectedEvent]);
+ if (eh != null)
+ eh (this, e);
+
+ if (this.SelectedTab != null)
+ this.SelectedTab.FireLeave ();
+ }
+
+ protected virtual void OnSelecting (TabControlCancelEventArgs e)
+ {
+ TabControlCancelEventHandler eh = (TabControlCancelEventHandler) (Events[SelectingEvent]);
+ if (eh != null)
+ eh (this, e);
+
+ if (!e.Cancel)
+ OnSelected (new TabControlEventArgs (SelectedTab, selected_index, TabControlAction.Selected));
+ }
+
+ protected virtual void OnSelected (TabControlEventArgs e)
+ {
+ TabControlEventHandler eh = (TabControlEventHandler) (Events[SelectedEvent]);
+ if (eh != null)
+ eh (this, e);
+
+ if (this.SelectedTab != null)
+ this.SelectedTab.FireEnter ();
+ }
+#endif
+
+ #endregion
+
+ #region Keys
protected override bool ProcessKeyPreview (ref Message m)
{
return base.ProcessKeyPreview (ref m);
}
- protected override void OnKeyDown (KeyEventArgs e)
+ protected override void OnKeyDown (KeyEventArgs ke)
{
- if (e.KeyCode == Keys.Tab && (e.KeyData & Keys.Control) != 0) {
- if ((e.KeyData & Keys.Shift) == 0)
+ base.OnKeyDown (ke);
+ if (ke.Handled)
+ return;
+
+ if (ke.KeyCode == Keys.Tab && (ke.KeyData & Keys.Control) != 0) {
+ if ((ke.KeyData & Keys.Shift) == 0)
SelectedIndex = (SelectedIndex + 1) % TabCount;
else
- SelectedIndex = (SelectedIndex - 1) % TabCount;
- e.Handled = true;
- } else if (e.KeyCode == Keys.Home) {
+ SelectedIndex = (SelectedIndex + TabCount - 1) % TabCount;
+ ke.Handled = true;
+ } else if (ke.KeyCode == Keys.Home) {
SelectedIndex = 0;
- e.Handled = true;
- } else if (e.KeyCode == Keys.End) {
+ ke.Handled = true;
+ } else if (ke.KeyCode == Keys.End) {
SelectedIndex = TabCount - 1;
- e.Handled = true;
- } else if (e.KeyCode == Keys.Left && SelectedIndex > 0) {
- SelectedIndex--;
- e.Handled = true;
- } else if (e.KeyCode == Keys.Right && SelectedIndex < TabCount - 1) {
- SelectedIndex++;
- e.Handled = true;
- }
-
- base.OnKeyDown (e);
+ ke.Handled = true;
+ } else if (NavigateTabs (ke.KeyCode))
+ ke.Handled = true;
}
- protected override bool IsInputKey (Keys key)
+ protected override bool IsInputKey (Keys keyData)
{
- switch (key & Keys.KeyCode) {
+ switch (keyData & Keys.KeyCode) {
case Keys.Home:
case Keys.End:
case Keys.Left:
case Keys.Right:
+ case Keys.Up:
+ case Keys.Down:
return true;
}
- return base.IsInputKey (key);
+ return base.IsInputKey (keyData);
}
-
- protected override void Dispose (bool disposing)
+
+ private bool NavigateTabs (Keys keycode)
{
- base.Dispose (disposing);
+ bool move_left = false;
+ bool move_right = false;
+
+ if (alignment == TabAlignment.Bottom || alignment == TabAlignment.Top) {
+ if (keycode == Keys.Left)
+ move_left = true;
+ else if (keycode == Keys.Right)
+ move_right = true;
+ } else {
+ if (keycode == Keys.Up)
+ move_left = true;
+ else if (keycode == Keys.Down)
+ move_right = true;
+ }
+
+ if (move_left) {
+ if (SelectedIndex > 0) {
+ SelectedIndex--;
+ return true;
+ }
+ }
+
+ if (move_right) {
+ if (SelectedIndex < TabCount - 1) {
+ SelectedIndex++;
+ return true;
+ }
+ }
+
+ return false;
}
+ #endregion
+ #region Pages Collection
protected void RemoveAll ()
{
Controls.Clear ();
return pages;
}
- protected virtual object [] GetItems (Type type)
+ protected virtual object [] GetItems (Type baseType)
{
- object [] pages = (object []) Array.CreateInstance (type, Controls.Count);
+ object[] pages = (object[])Array.CreateInstance (baseType, Controls.Count);
Controls.CopyTo (pages, 0);
return pages;
}
+ #endregion
+
+#if NET_2_0
+ protected void UpdateTabSelection (bool updateFocus)
+#else
+ protected void UpdateTabSelection (bool uiselected)
+#endif
+ {
+ ResizeTabPages ();
+ }
protected string GetToolTipText (object item)
{
protected override void WndProc (ref Message m)
{
- base.WndProc (ref m);
- }
-
- protected virtual void OnSelectedIndexChanged (EventArgs e)
- {
- EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
- if (eh != null)
- eh (this, e);
- }
-
- internal override void OnPaintInternal (PaintEventArgs pe)
- {
- Draw (pe.Graphics, pe.ClipRectangle);
- pe.Handled = true;
- }
-
- internal override void OnGotFocusInternal(EventArgs e) {
- has_focus = true;
- if (selected_index == -1 && this.TabCount > 0)
- this.SelectedIndex = 0;
- if (selected_index != -1)
- Invalidate(GetTabRect(selected_index));
- base.OnGotFocusInternal (e);
- }
-
-
- internal override void OnLostFocusInternal(EventArgs e) {
- has_focus = false;
- if (selected_index != -1)
- Invalidate(GetTabRect(selected_index));
- base.OnLostFocusInternal (e);
+ switch ((Msg)m.Msg) {
+ case Msg.WM_SETFOCUS:
+ if (selected_index == -1 && this.TabCount > 0)
+ this.SelectedIndex = 0;
+ if (selected_index != -1)
+ Invalidate(GetTabRect(selected_index));
+ base.WndProc (ref m);
+ break;
+ case Msg.WM_KILLFOCUS:
+ if (selected_index != -1)
+ Invalidate(GetTabRect(selected_index));
+ base.WndProc (ref m);
+ break;
+ default:
+ base.WndProc (ref m);
+ break;
+ }
}
-
#endregion // Protected Instance Methods
#region Internal & Private Methods
private void MouseDownHandler (object sender, MouseEventArgs e)
{
+ if ((e.Button & MouseButtons.Left) == 0)
+ return;
+
if (ShowSlider) {
- Rectangle right = ThemeEngine.Current.GetTabControlRightScrollRect (this);
- Rectangle left = ThemeEngine.Current.GetTabControlLeftScrollRect (this);
+ Rectangle right = RightScrollButtonArea;
+ Rectangle left = LeftScrollButtonArea;
if (right.Contains (e.X, e.Y)) {
- right_slider_state = ButtonState.Pushed;
+ right_slider_state = PushButtonState.Pressed;
if (CanScrollRight) {
slider_pos++;
SizeTabs ();
- Invalidate (new Rectangle (0, 0, Width, DisplayRectangle.Top));
+#if NET_2_0
+ // UIA Framework Event: Horizontally Scrolled
+ OnUIAHorizontallyScrolled (EventArgs.Empty);
+#endif
+
+ switch (this.Alignment) {
+ case TabAlignment.Top:
+ Invalidate (new Rectangle (0, 0, Width, ItemSize.Height));
+ break;
+ case TabAlignment.Bottom:
+ Invalidate (new Rectangle (0, DisplayRectangle.Bottom, Width, Height - DisplayRectangle.Bottom));
+ break;
+ case TabAlignment.Left:
+ Invalidate (new Rectangle (0, 0, DisplayRectangle.Left, Height));
+ break;
+ case TabAlignment.Right:
+ Invalidate (new Rectangle (DisplayRectangle.Right, 0, Width - DisplayRectangle.Right, Height));
+ break;
+ }
+
} else {
Invalidate (right);
}
return;
} else if (left.Contains (e.X, e.Y)) {
- left_slider_state = ButtonState.Pushed;
+ left_slider_state = PushButtonState.Pressed;
if (CanScrollLeft) {
slider_pos--;
SizeTabs ();
- Invalidate (new Rectangle (0, 0, Width, DisplayRectangle.Top));
+#if NET_2_0
+ // UIA Framework Event: Horizontally Scrolled
+ OnUIAHorizontallyScrolled (EventArgs.Empty);
+#endif
+
+ switch (this.Alignment) {
+ case TabAlignment.Top:
+ Invalidate (new Rectangle (0, 0, Width, ItemSize.Height));
+ break;
+ case TabAlignment.Bottom:
+ Invalidate (new Rectangle (0, DisplayRectangle.Bottom, Width, Height - DisplayRectangle.Bottom));
+ break;
+ case TabAlignment.Left:
+ Invalidate (new Rectangle (0, 0, DisplayRectangle.Left, Height));
+ break;
+ case TabAlignment.Right:
+ Invalidate (new Rectangle (DisplayRectangle.Right, 0, Width - DisplayRectangle.Right, Height));
+ break;
+ }
} else {
Invalidate (left);
}
if (!GetTabRect (i).Contains (e.X, e.Y))
continue;
SelectedIndex = i;
+ mouse_down_on_a_tab_page = true;
break;
}
}
private void MouseUpHandler (object sender, MouseEventArgs e)
{
- if (ShowSlider && (left_slider_state == ButtonState.Pushed || right_slider_state == ButtonState.Pushed)) {
+ mouse_down_on_a_tab_page = false;
+ if (ShowSlider && (left_slider_state == PushButtonState.Pressed || right_slider_state == PushButtonState.Pressed)) {
Rectangle invalid;
- if (left_slider_state == ButtonState.Pushed)
- invalid = ThemeEngine.Current.GetTabControlLeftScrollRect (this);
- else
- invalid = ThemeEngine.Current.GetTabControlRightScrollRect (this);
- left_slider_state = ButtonState.Normal;
- right_slider_state = ButtonState.Normal;
-
+ if (left_slider_state == PushButtonState.Pressed) {
+ invalid = LeftScrollButtonArea;
+ left_slider_state = GetScrollButtonState (invalid, e.Location);
+ } else {
+ invalid = RightScrollButtonArea;
+ right_slider_state = GetScrollButtonState (invalid, e.Location);
+ }
Invalidate (invalid);
}
}
- private void SizeChangedHandler (object sender, EventArgs e)
- {
- Redraw ();
+ bool HasHotElementStyles {
+ get {
+ return ThemeElements.CurrentTheme.TabControlPainter.HasHotElementStyles (this);
+ }
+ }
+
+ Rectangle LeftScrollButtonArea {
+ get {
+ return ThemeElements.CurrentTheme.TabControlPainter.GetLeftScrollRect (this);
+ }
}
- internal void UpdateTabpage (TabPage page)
+ Rectangle RightScrollButtonArea {
+ get {
+ return ThemeElements.CurrentTheme.TabControlPainter.GetRightScrollRect (this);
+ }
+ }
+
+ static PushButtonState GetScrollButtonState (Rectangle scrollButtonArea, Point cursorLocation)
{
+ return scrollButtonArea.Contains (cursorLocation) ? PushButtonState.Hot : PushButtonState.Normal;
+ }
+ private void SizeChangedHandler (object sender, EventArgs e)
+ {
+ Redraw ();
}
internal int IndexForTabPage (TabPage page)
private void CalcTabRows (int row_width)
{
- int xpos = 4;
+ int xpos = 0;
+ int ypos = 0;
Size spacing = TabSpacing;
if (TabPages.Count > 0)
row_count = 1;
show_slider = false;
+ CalculateItemSize ();
+
for (int i = 0; i < TabPages.Count; i++) {
TabPage page = TabPages [i];
- int width;
-
- page.Row = 1;
+ int aux = 0;
+ SizeTab (page, i, row_width, ref xpos, ref ypos, spacing, 0, ref aux, true);
+ }
- if (SizeMode == TabSizeMode.Fixed) {
- width = item_size.Width;
- } else {
- width = (int) DeviceContext.MeasureString (page.Text, Font).Width + (Padding.X * 2);
- if (ImageList != null && page.ImageIndex >= 0 && page.ImageIndex < ImageList.Images.Count) {
- width += ImageList.ImageSize.Width + 2;
- item_size.Height = ImageList.ImageSize.Height + 3;
- }
- }
+ if (SelectedIndex != -1 && TabPages.Count > SelectedIndex && TabPages[SelectedIndex].Row != BottomRow)
+ DropRow (TabPages [SelectedIndex].Row);
+ }
- if (i == SelectedIndex)
- width += 8;
- if (width < MinimumTabWidth)
- width = MinimumTabWidth;
+ // ItemSize per-se is used mostly only to retrieve the Height,
+ // since the actual Width of the tabs is computed individually,
+ // except when SizeMode is TabSizeMode.Fixed, where Width is used as well.
+ private void CalculateItemSize ()
+ {
+ if (item_size_manual)
+ return;
- if (xpos + width > row_width && multiline) {
- xpos = 4;
- for (int j = 0; j < i; j++) {
- TabPages [j].Row++;
- }
- row_count++;
- } else if (xpos + width > row_width) {
- show_slider = true;
- }
+ SizeF size;
+ if (tab_pages.Count > 0) {
+ // .Net uses the first tab page if available.
+ size = TextRenderer.MeasureString (tab_pages [0].Text, Font);
- xpos += width + 1 + spacing.Width;
+ } else {
+ size = TextRenderer.MeasureString ("a", Font);
+ size.Width = 0;
}
- if (SelectedIndex != -1 && TabPages [SelectedIndex].Row != BottomRow)
- DropRow (TabPages [SelectedIndex].Row);
+ if (size_mode == TabSizeMode.Fixed)
+ size.Width = 96;
+ if (size.Width < MinimumTabWidth)
+ size.Width = MinimumTabWidth;
+ if (image_list != null && image_list.ImageSize.Height > size.Height)
+ size.Height = image_list.ImageSize.Height;
+
+ item_size = size.ToSize ();
}
private int BottomRow {
- get {
- switch (Alignment) {
- case TabAlignment.Right:
- case TabAlignment.Bottom:
- return row_count;
- default:
- return 1;
- }
- }
+ get { return 1; }
}
private int Direction
{
get {
- switch (Alignment) {
- case TabAlignment.Right:
- case TabAlignment.Bottom:
- return -1;
- default:
- return 1;
- }
+ return 1;
}
}
private void DropRow (int row)
{
+ if (Appearance != TabAppearance.Normal)
+ return;
+
int bottom = BottomRow;
int direction = Direction;
private int CalcYPos ()
{
- if (Alignment == TabAlignment.Bottom) {
- Rectangle r = ThemeEngine.Current.GetTabControlDisplayRectangle (this);
- return r.Bottom + 3;
- }
- return 1;
+ if (Alignment == TabAlignment.Bottom || Alignment == TabAlignment.Left)
+ return ThemeEngine.Current.TabControlGetPanelRect (this).Bottom;
+
+ if (Appearance == TabAppearance.Normal)
+ return this.ClientRectangle.Y + ThemeEngine.Current.TabControlSelectedDelta.Y;
+
+ return this.ClientRectangle.Y;
+
}
private int CalcXPos ()
{
- if (Alignment == TabAlignment.Right) {
- Rectangle r = ThemeEngine.Current.GetTabControlDisplayRectangle (this);
- return r.Right + 4;
- }
- return 4;
+ if (Alignment == TabAlignment.Right)
+ return ThemeEngine.Current.TabControlGetPanelRect (this).Right;
+
+ if (Appearance == TabAppearance.Normal)
+ return this.ClientRectangle.X + ThemeEngine.Current.TabControlSelectedDelta.X;
+ return this.ClientRectangle.X;
}
private void SizeTabs ()
switch (Alignment) {
case TabAlignment.Right:
case TabAlignment.Left:
- SizeTabsV (Height);
+ SizeTabs (Height, true);
break;
default:
- SizeTabs (Width);
+ SizeTabs (Width, false);
break;
}
}
-
- private void SizeTabsV (int row_width)
+
+ private void SizeTabs (int row_width, bool vertical)
{
- int ypos = 1;
+ int ypos = 0;
+ int xpos = 0;
int prev_row = 1;
Size spacing = TabSpacing;
- int xpos = CalcXPos ();
int begin_prev = 0;
-
+
if (TabPages.Count == 0)
return;
prev_row = TabPages [0].Row;
- for (int i = 0; i < TabPages.Count; i++) {
- TabPage page = TabPages [i];
- int width;
-
- if (SizeMode == TabSizeMode.Fixed) {
- width = item_size.Width;
- } else {
- width = (int) DeviceContext.MeasureString (page.Text, Font).Width + (Padding.X * 2);
- if (ImageList != null && page.ImageIndex >= 0 && page.ImageIndex < ImageList.Images.Count) {
- width += ImageList.ImageSize.Width + 2;
- item_size.Height = ImageList.ImageSize.Height + 3;
- }
- }
-
- if (width < MinimumTabWidth)
- width = MinimumTabWidth;
- if (page.Row != prev_row)
- ypos = 1;
-
- page.TabBounds = new Rectangle (xpos + (row_count - page.Row) * ((item_size.Height - 2) + spacing.Width),
- ypos, item_size.Height - 2, width);
-
- if (page.Row != prev_row) {
- if (SizeMode == TabSizeMode.FillToRight && !ShowSlider) {
- FillRowV (begin_prev, i - 1, ((row_width - TabPages [i - 1].TabBounds.Bottom) / (i - begin_prev)), spacing);
- }
- begin_prev = i;
+ // Reset the slider position if the slider isn't needed
+ // anymore (ie window size was increased so all tabs are visible)
+ if (!show_slider)
+ slider_pos = 0;
+ else {
+ // set X = -1 for marking tabs that are not visible due to scrolling
+ for (int i = 0; i < slider_pos; i++) {
+ TabPage page = TabPages[i];
+ Rectangle x = page.TabBounds;
+ x.X = -1;
+ page.TabBounds = x;
}
-
- ypos += width + spacing.Width;
+ }
+
+ for (int i = slider_pos; i < TabPages.Count; i++) {
+ TabPage page = TabPages[i];
+ SizeTab (page, i, row_width, ref xpos, ref ypos, spacing, prev_row, ref begin_prev, false);
prev_row = page.Row;
}
if (SizeMode == TabSizeMode.FillToRight && !ShowSlider) {
- FillRowV (begin_prev, TabPages.Count - 1,
- ((row_width - TabPages [TabPages.Count - 1].TabBounds.Bottom) / (TabPages.Count - begin_prev)), spacing);
+ FillRow (begin_prev, TabPages.Count - 1,
+ ((row_width - TabPages [TabPages.Count - 1].TabBounds.Right) / (TabPages.Count - begin_prev)),
+ spacing, vertical);
}
if (SelectedIndex != -1) {
- ExpandSelected (TabPages [SelectedIndex], 2, row_width - 1);
+ ExpandSelected (TabPages [SelectedIndex], 0, row_width - 1);
}
}
+
+ private void SizeTab (TabPage page, int i, int row_width, ref int xpos, ref int ypos,
+ Size spacing, int prev_row, ref int begin_prev, bool widthOnly)
+ {
+ int width, height = 0;
+
+ if (SizeMode == TabSizeMode.Fixed) {
+ width = item_size.Width;
+ } else {
+ width = MeasureStringWidth (DeviceContext, page.Text, page.Font);
+ width += (Padding.X * 2) + 2;
+
+ if (ImageList != null && page.ImageIndex >= 0) {
+ width += ImageList.ImageSize.Width + ThemeEngine.Current.TabControlImagePadding.X;
+
+ int image_size = ImageList.ImageSize.Height + ThemeEngine.Current.TabControlImagePadding.Y;
+ if (item_size.Height < image_size)
+ item_size.Height = image_size;
+ }
- private void SizeTabs (int row_width)
- {
- int ypos = CalcYPos ();
- int prev_row = 1;
- Size spacing = TabSpacing;
- int xpos = 4;
- int begin_prev = 0;
-
- if (TabPages.Count == 0)
- return;
-
- prev_row = TabPages [0].Row;
+ if (width < MinimumTabWidth)
+ width = MinimumTabWidth;
+ }
- // Reset the slider position if the slider isn't needed
- // anymore (ie window size was increased so all tabs are visible)
- if (!show_slider)
- slider_pos = 0;
+ // Use ItemSize property to recover the padding info as well.
+ height = ItemSize.Height - ThemeEngine.Current.TabControlSelectedDelta.Height; // full height only for selected tab
- for (int i = slider_pos; i < TabPages.Count; i++) {
- TabPage page = TabPages [i];
- int width;
-
- if (SizeMode == TabSizeMode.Fixed) {
- width = item_size.Width;
- } else {
- width = (int) DeviceContext.MeasureString (page.Text, Font).Width + (Padding.X * 2);
- if (ImageList != null && page.ImageIndex >= 0 && page.ImageIndex < ImageList.Images.Count) {
- width += ImageList.ImageSize.Width + 2;
- item_size.Height = ImageList.ImageSize.Height + 3;
+ if (i == SelectedIndex)
+ width += ThemeEngine.Current.TabControlSelectedSpacing;
+
+ if (widthOnly) {
+ page.TabBounds = new Rectangle (xpos, 0, width, 0);
+ page.Row = row_count;
+ if (xpos + width > row_width && multiline) {
+ xpos = 0;
+ row_count++;
+ } else if (xpos + width > row_width) {
+ show_slider = true;
+ }
+ if (i == selected_index && show_slider) {
+ for (int j = i-1; j >= 0; j--) {
+ if (TabPages [j].TabBounds.Left < xpos + width - row_width) {
+ slider_pos = j+1;
+ break;
+ }
}
}
+ } else {
+ if (page.Row != prev_row) {
+ xpos = 0;
+ }
- if (width < MinimumTabWidth)
- width = MinimumTabWidth;
- if (page.Row != prev_row)
- xpos = 4;
+ switch (Alignment) {
+ case TabAlignment.Top:
+ page.TabBounds = new Rectangle (
+ xpos + CalcXPos (),
+ ypos + (height + spacing.Height) * (row_count - page.Row) + CalcYPos (),
+ width,
+ height);
+ break;
+ case TabAlignment.Bottom:
+ page.TabBounds = new Rectangle (
+ xpos + CalcXPos (),
+ ypos + (height + spacing.Height) * (row_count - page.Row) + CalcYPos (),
+ width,
+ height);
+ break;
+ case TabAlignment.Left:
+ if (Appearance == TabAppearance.Normal) {
+ // tab rows are positioned right to left
+ page.TabBounds = new Rectangle (
+ ypos + (height + spacing.Height) * (row_count - page.Row) + CalcXPos (),
+ xpos,
+ height,
+ width);
+ } else {
+ // tab rows are positioned left to right
+ page.TabBounds = new Rectangle (
+ ypos + (height + spacing.Height) * (page.Row - 1) + CalcXPos (),
+ xpos,
+ height,
+ width);
+ }
- page.TabBounds = new Rectangle (xpos,
- ypos + (row_count - page.Row) * (item_size.Height + spacing.Height),
- width, item_size.Height);
-
+ break;
+ case TabAlignment.Right:
+ if (Appearance == TabAppearance.Normal) {
+ // tab rows are positioned left to right
+ page.TabBounds = new Rectangle (
+ ypos + (height + spacing.Height) * (page.Row - 1) + CalcXPos (),
+ xpos,
+ height,
+ width);
+ } else {
+ // tab rows are positioned right to left
+ page.TabBounds = new Rectangle (
+ ypos + (height + spacing.Height) * (row_count - page.Row) + CalcXPos (),
+ xpos,
+ height,
+ width);
+ }
+
+ break;
+ }
+
if (page.Row != prev_row) {
if (SizeMode == TabSizeMode.FillToRight && !ShowSlider) {
- FillRow (begin_prev, i - 1, ((row_width - TabPages [i - 1].TabBounds.Right) / (i - begin_prev)), spacing);
+ bool vertical = alignment == TabAlignment.Right || alignment == TabAlignment.Left;
+ int offset = vertical ? TabPages [i - 1].TabBounds.Bottom : TabPages [i - 1].TabBounds.Right;
+ FillRow (begin_prev, i - 1, ((row_width - offset) / (i - begin_prev)), spacing,
+ vertical);
}
begin_prev = i;
- }
-
- xpos += width + 1 + spacing.Width;
- prev_row = page.Row;
+ }
}
- if (SizeMode == TabSizeMode.FillToRight && !ShowSlider) {
- FillRow (begin_prev, TabPages.Count - 1,
- ((row_width - TabPages [TabPages.Count - 1].TabBounds.Right) / (TabPages.Count - begin_prev)), spacing);
- }
+ xpos += width + spacing.Width + ThemeEngine.Current.TabControlColSpacing;
+ }
- if (SelectedIndex != -1) {
- ExpandSelected (TabPages [SelectedIndex], 2, row_width - 1);
- }
+ private void FillRow (int start, int end, int amount, Size spacing, bool vertical)
+ {
+ if (vertical)
+ FillRowV (start, end, amount, spacing);
+ else
+ FillRow (start, end, amount, spacing);
}
-
+
private void FillRow (int start, int end, int amount, Size spacing)
{
int xpos = TabPages [start].TabBounds.Left;
if (Appearance != TabAppearance.Normal)
return;
- if (Alignment == TabAlignment.Top || Alignment == TabAlignment.Bottom) {
- int l = page.TabBounds.Left - 4;
- int r = page.TabBounds.Right + 4;
- int y = page.TabBounds.Y;
- int h = page.TabBounds.Height + 3;
-
- if (l < left_edge)
- l = left_edge;
- if (r > right_edge && SizeMode != TabSizeMode.Normal)
- r = right_edge;
- if (Alignment == TabAlignment.Top)
- y -= 1;
- if (Alignment == TabAlignment.Bottom)
- y -= 2;
-
- page.TabBounds = new Rectangle (l, y, r - l, h);
- } else {
- int l = page.TabBounds.Left - 3;
- int r = page.TabBounds.Right + 3;
- int t = page.TabBounds.Top - 3;
- int b = page.TabBounds.Bottom + 3;
-
- if (t < left_edge)
- t = left_edge;
- if (b > right_edge)
- b = right_edge;
-
- page.TabBounds = new Rectangle (l, t, r - l, b - t);
+ Rectangle r = page.TabBounds;
+ switch (Alignment) {
+ case TabAlignment.Top:
+ case TabAlignment.Left:
+ r.Y -= ThemeEngine.Current.TabControlSelectedDelta.Y;
+ r.X -= ThemeEngine.Current.TabControlSelectedDelta.X;
+ break;
+ case TabAlignment.Bottom:
+ r.Y -= ThemeEngine.Current.TabControlSelectedDelta.Y;
+ r.X -= ThemeEngine.Current.TabControlSelectedDelta.X;
+ break;
+ case TabAlignment.Right:
+ r.Y -= ThemeEngine.Current.TabControlSelectedDelta.Y;
+ r.X -= ThemeEngine.Current.TabControlSelectedDelta.X;
+ break;
}
+
+ r.Width += ThemeEngine.Current.TabControlSelectedDelta.Width;
+ r.Height += ThemeEngine.Current.TabControlSelectedDelta.Height;
+ if (r.Left < left_edge)
+ r.X = left_edge;
+ // Adjustment can't be used for right alignment, since it is
+ // the only one that has a different X origin than 0
+ if (r.Right > right_edge && SizeMode != TabSizeMode.Normal &&
+ alignment != TabAlignment.Right)
+ r.Width = right_edge - r.X;
+ page.TabBounds = r;
}
private void Draw (Graphics dc, Rectangle clip)
private void SetTab (int index, TabPage value)
{
- ((IList) Controls).Insert (index, value);
+ if (!tab_pages.Contains (value)) {
+ this.Controls.Add (value);
+ }
+ this.Controls.RemoveAt (index);
+ this.Controls.SetChildIndex (value, index);
Redraw ();
}
-
+#if NET_2_0
+ private void InsertTab (int index, TabPage value)
+ {
+ if (!tab_pages.Contains (value)) {
+ this.Controls.Add (value);
+ }
+ this.Controls.SetChildIndex (value, index);
+ Redraw ();
+ }
+#endif
internal void Redraw ()
{
+ if (!IsHandleCreated)
+ return;
+
ResizeTabPages ();
Refresh ();
}
+ private int MeasureStringWidth (Graphics graphics, string text, Font font)
+ {
+ if (text == String.Empty)
+ return 0;
+ StringFormat format = new StringFormat();
+ RectangleF rect = new RectangleF(0, 0, 1000, 1000);
+ CharacterRange[] ranges = { new CharacterRange(0, text.Length) };
+ Region[] regions = new Region[1];
+
+ format.SetMeasurableCharacterRanges(ranges);
+ format.FormatFlags = StringFormatFlags.NoClip;
+ format.FormatFlags |= StringFormatFlags.NoWrap;
+ regions = graphics.MeasureCharacterRanges(text + "I", font, rect, format);
+ rect = regions[0].GetBounds(graphics);
+
+ return (int)(rect.Width);
+ }
+
+ void SetToolTip (string text)
+ {
+ if (text == null || text.Length == 0) {
+ CloseToolTip ();
+ return;
+ }
+
+ if (tooltip == null) {
+ tooltip = new ToolTip ();
+ tooltip_timer = new Timer ();
+ tooltip_timer.Tick += new EventHandler (ToolTipTimerTick);
+ }
+
+ CloseToolTip ();
+
+ tooltip_state = ToolTip.TipState.Initial;
+ tooltip_timer.Interval = 500;
+ tooltip_timer.Start ();
+ }
+
+ void CloseToolTip ()
+ {
+ if (tooltip == null)
+ return;
+
+ tooltip.Hide (this);
+ tooltip_timer.Stop ();
+ tooltip_state = ToolTip.TipState.Down;
+ }
+
+ void ToolTipTimerTick (object o, EventArgs args)
+ {
+ switch (tooltip_state) {
+ case ToolTip.TipState.Initial:
+ tooltip_timer.Stop ();
+ tooltip_timer.Interval = 5000;
+ tooltip_timer.Start ();
+ tooltip_state = ToolTip.TipState.Show;
+ tooltip.Present (this, GetToolTipText (EnteredTabPage));
+ break;
+ case ToolTip.TipState.Show:
+ CloseToolTip ();
+ break;
+ }
+ }
+
+ void OnMouseMove (object sender, MouseEventArgs e)
+ {
+ if (!mouse_down_on_a_tab_page && ShowSlider) {
+ if (LeftSliderState == PushButtonState.Pressed ||
+ RightSliderState == PushButtonState.Pressed)
+ return;
+ if (LeftScrollButtonArea.Contains (e.Location)) {
+ LeftSliderState = PushButtonState.Hot;
+ RightSliderState = PushButtonState.Normal;
+ EnteredTabPage = null;
+ return;
+ }
+ if (RightScrollButtonArea.Contains (e.Location)) {
+ RightSliderState = PushButtonState.Hot;
+ LeftSliderState = PushButtonState.Normal;
+ EnteredTabPage = null;
+ return;
+ }
+ LeftSliderState = PushButtonState.Normal;
+ RightSliderState = PushButtonState.Normal;
+ }
+ if (EnteredTabPage != null && EnteredTabPage.TabBounds.Contains (e.Location))
+ return;
+ for (int index = 0; index < TabCount; index++) {
+ TabPage tab_page = TabPages[index];
+ if (tab_page.TabBounds.Contains (e.Location)) {
+ EnteredTabPage = tab_page;
+ return;
+ }
+ }
+ EnteredTabPage = null;
+ }
+
+ void OnMouseLeave (object sender, EventArgs e)
+ {
+ if (ShowSlider) {
+ LeftSliderState = PushButtonState.Normal;
+ RightSliderState = PushButtonState.Normal;
+ }
+ EnteredTabPage = null;
+ }
#endregion // Internal & Private Methods
#region Events
remove { base.BackgroundImageChanged -= value; }
}
+#if NET_2_0
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event EventHandler BackgroundImageLayoutChanged
+ {
+ add { base.BackgroundImageLayoutChanged += value; }
+ remove { base.BackgroundImageLayoutChanged -= value; }
+ }
+#endif
+
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public new event EventHandler ForeColorChanged {
add { Events.AddHandler (SelectedIndexChangedEvent, value); }
remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
}
+
+#if NET_2_0
+ static object SelectedEvent = new object ();
+
+ public event TabControlEventHandler Selected {
+ add { Events.AddHandler (SelectedEvent, value); }
+ remove { Events.RemoveHandler (SelectedEvent, value); }
+ }
+
+ static object DeselectedEvent = new object ();
+
+ public event TabControlEventHandler Deselected
+ {
+ add { Events.AddHandler (DeselectedEvent, value); }
+ remove { Events.RemoveHandler (DeselectedEvent, value); }
+ }
+
+ static object SelectingEvent = new object ();
+
+ public event TabControlCancelEventHandler Selecting
+ {
+ add { Events.AddHandler (SelectingEvent, value); }
+ remove { Events.RemoveHandler (SelectingEvent, value); }
+ }
+
+ static object DeselectingEvent = new object ();
+
+ public event TabControlCancelEventHandler Deselecting
+ {
+ add { Events.AddHandler (DeselectingEvent, value); }
+ remove { Events.RemoveHandler (DeselectingEvent, value); }
+ }
+
+ static object RightToLeftLayoutChangedEvent = new object ();
+ public event EventHandler RightToLeftLayoutChanged
+ {
+ add { Events.AddHandler (RightToLeftLayoutChangedEvent, value); }
+ remove { Events.RemoveHandler (RightToLeftLayoutChangedEvent, value); }
+ }
+#endif
#endregion // Events
#region Class TaControl.ControlCollection
+#if NET_2_0
+ [ComVisible (false)]
+#endif
public new class ControlCollection : System.Windows.Forms.Control.ControlCollection {
private TabControl owner;
page.SetVisible (false);
base.Add (value);
+ if (owner.TabCount == 1 && owner.selected_index < 0)
+ owner.SelectedIndex = 0;
owner.Redraw ();
}
public override void Remove (Control value)
{
+ bool change_index = false;
+
TabPage page = value as TabPage;
- if (page != null) {
+ if (page != null && owner.Controls.Contains (page)) {
int index = owner.IndexForTabPage (page);
if (index < owner.SelectedIndex || owner.SelectedIndex == Count - 1)
- owner.SelectedIndex--;
+ change_index = true;
}
+
base.Remove (value);
+
+ // We don't want to raise SelectedIndexChanged until after we
+ // have removed from the collection, so TabCount will be
+ // correct for the user.
+ if (change_index && Count > 0) {
+ // Clear the selected index internally, to avoid trying to access the previous
+ // selected tab when setting the new one - this is what .net seems to do
+ int prev_selected_index = owner.SelectedIndex;
+ owner.selected_index = -1;
+
+ owner.SelectedIndex = --prev_selected_index;
+ } else if (change_index) {
+ owner.selected_index = -1;
+ owner.OnSelectedIndexChanged (EventArgs.Empty);
+ } else
+ owner.Redraw ();
}
}
#endregion // Class TabControl.ControlCollection
}
set {
owner.SetTab (index, value);
- }
+ }
+ }
+#if NET_2_0
+ public virtual TabPage this [string key] {
+ get {
+ if (string.IsNullOrEmpty (key))
+ return null;
+
+ int index = this.IndexOfKey (key);
+ if (index < 0 || index >= this.Count)
+ return null;
+
+ return this[index];
+ }
+ }
+#endif
+
+ internal int this[TabPage tabPage] {
+ get {
+ if (tabPage == null)
+ return -1;
+
+ for (int i = 0; i < this.Count; i++)
+ if (this[i].Equals (tabPage))
+ return i;
+
+ return -1;
+ }
}
bool ICollection.IsSynchronized {
}
}
- public void Add (TabPage page)
+ public void Add (TabPage value)
{
- if (page == null)
+ if (value == null)
throw new ArgumentNullException ("Value cannot be null.");
- owner.Controls.Add (page);
+ owner.Controls.Add (value);
+ }
+
+#if NET_2_0
+ public void Add (string text)
+ {
+ TabPage page = new TabPage (text);
+ this.Add (page);
+ }
+
+ public void Add (string key, string text)
+ {
+ TabPage page = new TabPage (text);
+ page.Name = key;
+ this.Add (page);
}
+ public void Add (string key, string text, int imageIndex)
+ {
+ TabPage page = new TabPage (text);
+ page.Name = key;
+ page.ImageIndex = imageIndex;
+ this.Add (page);
+ }
+
+ // .Net sets the ImageKey, but does not show the image when this is used
+ public void Add (string key, string text, string imageKey)
+ {
+ TabPage page = new TabPage (text);
+ page.Name = key;
+ page.ImageKey = imageKey;
+ this.Add (page);
+ }
+#endif
+
public void AddRange (TabPage [] pages)
{
if (pages == null)
public virtual void Clear ()
{
owner.Controls.Clear ();
+ owner.Invalidate ();
}
public bool Contains (TabPage page)
return owner.Controls.Contains (page);
}
+#if NET_2_0
+ public virtual bool ContainsKey (string key)
+ {
+ int index = this.IndexOfKey (key);
+ return (index >= 0 && index < this.Count);
+ }
+#endif
+
public IEnumerator GetEnumerator ()
{
return owner.Controls.GetEnumerator ();
return owner.Controls.IndexOf (page);
}
- public void Remove (TabPage page)
+#if NET_2_0
+ public virtual int IndexOfKey(string key)
+ {
+ if (string.IsNullOrEmpty (key))
+ return -1;
+
+ for (int i = 0; i < this.Count; i++) {
+ if (string.Compare (this[i].Name, key, true,
+ System.Globalization.CultureInfo.InvariantCulture) == 0) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+#endif
+
+ public void Remove (TabPage value)
{
- owner.Controls.Remove (page);
+ owner.Controls.Remove (value);
+ owner.Invalidate ();
}
public void RemoveAt (int index)
{
owner.Controls.RemoveAt (index);
+ owner.Invalidate ();
+ }
+
+#if NET_2_0
+ public virtual void RemoveByKey (string key)
+ {
+ int index = this.IndexOfKey (key);
+ if (index >= 0 && index < this.Count)
+ this.RemoveAt (index);
}
+#endif
void ICollection.CopyTo (Array dest, int index)
{
if (value == null)
throw new ArgumentException ("value");
owner.Controls.Add (page);
- return owner.Controls.IndexOf (page);
+ return owner.Controls.IndexOf (page);
}
- bool IList.Contains (object value)
+ bool IList.Contains (object page)
{
- TabPage page = value as TabPage;
- if (page == null)
+ TabPage tabPage = page as TabPage;
+ if (tabPage == null)
return false;
- return Contains (page);
+ return Contains (tabPage);
}
- int IList.IndexOf (object value)
+ int IList.IndexOf (object page)
{
- TabPage page = value as TabPage;
- if (page == null)
+ TabPage tabPage = page as TabPage;
+ if (tabPage == null)
return -1;
- return IndexOf ((TabPage) page);
+ return IndexOf (tabPage);
}
+#if NET_2_0
+ void IList.Insert (int index, object tabPage)
+#else
void IList.Insert (int index, object value)
+#endif
{
throw new NotSupportedException ();
}
+#if NET_2_0
+ public void Insert (int index, string text)
+ {
+ owner.InsertTab (index, new TabPage (text));
+ }
+
+ public void Insert (int index, TabPage tabPage)
+ {
+ owner.InsertTab (index, tabPage);
+ }
+
+ public void Insert (int index, string key, string text)
+ {
+ TabPage page = new TabPage(text);
+ page.Name = key;
+ owner.InsertTab (index, page);
+ }
+
+ public void Insert (int index, string key, string text, int imageIndex)
+ {
+ TabPage page = new TabPage(text);
+ page.Name = key;
+ owner.InsertTab (index, page);
+ page.ImageIndex = imageIndex;
+ }
+
+ public void Insert (int index, string key, string text, string imageKey)
+ {
+ TabPage page = new TabPage(text);
+ page.Name = key;
+ owner.InsertTab (index, page);
+ page.ImageKey = imageKey;
+ }
+#endif
void IList.Remove (object value)
{
TabPage page = value as TabPage;