using System;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using DevComponents.DotNetBar.Rendering;
using System.Drawing;
using DevComponents.DotNetBar.TextMarkup;
using System.Reflection;
using DevComponents.Editors;
using System.Collections;
namespace DevComponents.DotNetBar.Controls
{
    [ToolboxBitmap(typeof(TextBoxX), "Controls.TextBoxX.ico"), ToolboxItem(true), Designer("DevComponents.DotNetBar.Design.TextBoxXDesigner, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral,  PublicKeyToken=90f470f34c89ccaf")]
    public class TextBoxX : TextBox, INonClientControl
#if FRAMEWORK20
, IInputButtonControl
#endif
    {
        #region Private Variables
        private NonClientPaintHandler m_NCPainter = null;
        private string m_WatermarkText = "";
        private bool m_Focused = false;
        private Font m_WatermarkFont = null;
        private Color m_WatermarkColor = SystemColors.GrayText;
        private ElementStyle m_BorderStyle = null;
        private IntPtr m_LastFocusWindow;
        private string m_OriginalText;
        private bool m_IsTextBoxItem = false;
        private Color m_FocusHighlightColor = ColorScheme.GetColor(0xFFFF88);
        private bool m_FocusHighlightEnabled = false;
        private Color m_LastBackColor = Color.Empty;
        #endregion
        #region Events
#if FRAMEWORK20
        /// 
        /// Occurs when ButtonCustom control is clicked.
        /// 
        public event EventHandler ButtonCustomClick;
        /// 
        /// Occurs when ButtonCustom2 control is clicked.
        /// 
        public event EventHandler ButtonCustom2Click;
#endif
        #endregion
        #region Constructor
        public TextBoxX()
        {
#if FRAMEWORK20
            _ButtonCustom = new InputButtonSettings(this);
            _ButtonCustom2 = new InputButtonSettings(this);
            CreateButtonGroup();
#endif
            m_BorderStyle = new ElementStyle();
            m_BorderStyle.StyleChanged += new EventHandler(BorderStyle_StyleChanged);
            m_NCPainter = new NonClientPaintHandler(this, eScrollBarSkin.Optimized);
            base.BorderStyle = BorderStyle.None;
            this.AutoSize = false;
            StyleManager.Register(this);
        }
        /// 
        /// Called by StyleManager to notify control that style on manager has changed and that control should refresh its appearance if
        /// its style is controlled by StyleManager.
        /// 
        /// New active style.
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void StyleManagerStyleChanged(eDotNetBarStyle newStyle)
        {
            // Metro needs BackColor and ForeColor set
            if (StyleManager.IsMetro(newStyle) || StyleManager.IsMetro(StyleManager.PreviousStyle) && !StyleManager.IsMetro(newStyle))
                StyleManager.UpdateAmbientColors(this);
            UpdateEnabledBackColor();
        }
        internal TextBoxX(bool isTextBoxItem)
            : this()
        {
            m_IsTextBoxItem = isTextBoxItem;
        }
        protected override void Dispose(bool disposing)
        {
            if (m_NCPainter != null)
            {
                m_NCPainter.Dispose();
                //m_NCPainter = null;
            }
            if (m_BorderStyle != null) m_BorderStyle.StyleChanged -= new EventHandler(BorderStyle_StyleChanged);
            StyleManager.Unregister(this);
            base.Dispose(disposing);
        }
        #endregion
        #region Windows Messages Handling
        private bool m_IgnoreFocus = false;
        private bool _MouseOverButtons = false;
        protected override void WndProc(ref Message m)
        {
            if (this.IsDisposed)
            {
                base.WndProc(ref m);
                return;
            }
            if (m_NCPainter != null)
            {
                bool callBase = m_NCPainter.WndProc(ref m);
                if (callBase)
                    base.WndProc(ref m);
            }
            else
            {
                base.WndProc(ref m);
            }
#if FRAMEWORK20
            if (RenderButtons)
            {
                switch (m.Msg)
                {
                    case (int)WinApi.WindowsMessages.WM_NCMOUSEMOVE:
                    case (int)WinApi.WindowsMessages.WM_NCHITTEST:
                        {
                            Point p = PointToClient(new Point(WinApi.LOWORD(m.LParam), WinApi.HIWORD(m.LParam)));
                            if (_ButtonGroup.RenderBounds.Contains(p))
                            {
                                m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.ClientArea);
                                return;
                            }
                            break;
                        }
                }
            }
#endif
            switch (m.Msg)
            {
                case (int)WinApi.WindowsMessages.WM_SETFOCUS:
                    {
                        if (m_IgnoreFocus)
                        {
                            m_IgnoreFocus = false;
                        }
                        else
                        {
                            m_Focused = true;
                            m_LastFocusWindow = m.WParam;
                            m_OriginalText = this.Text;
                            if (this.FocusHighlightEnabled && this.Enabled)
                            {
                                m_LastBackColor = this.BackColor;
                                this.BackColor = this.FocusHighlightColor;
                                this.InvalidateNonClient();
                            }
                        }
                        break;
                    }
                case (int)WinApi.WindowsMessages.WM_KILLFOCUS:
                    {
                        if (!m_Focused)
                        {
                            m_IgnoreFocus = true;
                        }
                        else
                        {
                            m_Focused = false;
                            if (this.Text.Length == 0)
                                this.Invalidate();
                            if (this.FocusHighlightEnabled && !m_LastBackColor.IsEmpty)
                            {
                                this.BackColor = m_LastBackColor;
                                this.InvalidateNonClient();
                            }
                        }
                        break;
                    }
                case (int)WinApi.WindowsMessages.WM_PAINT:
                    {
                        if (RenderWatermark)
                            DrawWatermark();
                        if (this.Parent is ItemControl)
                            ((ItemControl)this.Parent).UpdateKeyTipsCanvas();
                        break;
                    }
            }
        }
        private bool RenderWatermark
        {
            get
            {
                if (!_WatermarkEnabled)
                    return false;
                if (_WatermarkBehavior == eWatermarkBehavior.HideOnFocus)
                    return !m_Focused && this.Enabled && this.Text != null && this.Text.Length == 0 && (m_WatermarkText.Length > 0 || _WatermarkImage != null);
                else
                    return this.Enabled && this.Text != null && this.Text.Length == 0 && (m_WatermarkText.Length > 0 || _WatermarkImage != null);
            }
        }
        #endregion
        #region Internal Implementation
        private bool _IsEnterInputKey = false;
        /// 
        /// Indicates whether internal override for IsInputKey returns true for the Enter key.
        /// 
        [DefaultValue(false), Category("Behavior"), Description("Indicates whether internal override for IsInputKey returns true for the Enter key.")]
        public bool IsEnterInputKey
        {
            get { return _IsEnterInputKey; }
            set { _IsEnterInputKey = value; }
        }
        protected override bool IsInputKey(Keys keyData)
        {
            if (keyData == Keys.Enter && _IsEnterInputKey)
                return true;
            return base.IsInputKey(keyData);
        }
        private bool _AutoSelectAll = false;
        /// 
        /// Indicates whether all text is auto-selected when control gets input focus. Default value is false.
        /// 
        [DefaultValue(false), Category("Behavior"), Description("Indicates whether all text is auto-selected when control gets input focus.")]
        public bool AutoSelectAll
        {
            get { return _AutoSelectAll; }
            set { _AutoSelectAll = value; }
        }
        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            _ButtonGroup.ProcessKeyPress(e);
            if (!this.Multiline && _PreventEnterBeep && e.KeyChar == (char)Keys.Enter)
            {
                e.Handled = true;
            }
            base.OnKeyPress(e);
        }
        private bool _PreventEnterBeep = false;
        /// 
        /// Gets or sets whether control prevents Beep sound when Enter key is pressed.
        /// 
        [DefaultValue(false), Category("Behavior"), Description("Gets or sets whether control prevents Beep sound when Enter key is pressed.")]
        public bool PreventEnterBeep
        {
            get { return _PreventEnterBeep; }
            set
            {
                _PreventEnterBeep = value;
            }
        }
        /// 
        /// Gets or sets whether FocusHighlightColor is used as background color to highlight text box when it has input focus. Default value is false.
        /// 
        [DefaultValue(false), Browsable(true), Category("Appearance"), Description("Indicates whether FocusHighlightColor is used as background color to highlight text box when it has input focus.")]
        public bool FocusHighlightEnabled
        {
            get { return m_FocusHighlightEnabled; }
            set
            {
                if (m_FocusHighlightEnabled != value)
                {
                    m_FocusHighlightEnabled = value;
                    if (this.Focused)
                        this.Invalidate();
                    if (!m_FocusHighlightEnabled)
                        this.ResetBackColor();
                }
            }
        }
        /// 
        /// Gets or sets the color used as background color to highlight text box when it has input focus and focus highlight is enabled.
        /// 
        [Browsable(true), Category("Appearance"), Description("Indicates color used as background color to highlight text box when it has input focus and focus highlight is enabled.")]
        public Color FocusHighlightColor
        {
            get { return m_FocusHighlightColor; }
            set
            {
                if (m_FocusHighlightColor != value)
                {
                    m_FocusHighlightColor = value;
                    if (this.Focused)
                        this.Invalidate();
                }
            }
        }
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeFocusHighlightColor()
        {
            return !m_FocusHighlightColor.Equals(ColorScheme.GetColor(0xFFFF88));
        }
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetFocusHighlightColor()
        {
            FocusHighlightColor = ColorScheme.GetColor(0xFFFF88);
        }
        internal void ReleaseFocus()
        {
            if (this.Focused && m_LastFocusWindow != IntPtr.Zero)
            {
                IntPtr focus = m_LastFocusWindow;
                m_LastFocusWindow = IntPtr.Zero;
                Control ctrl = Control.FromChildHandle(focus);
                if (ctrl != this)
                {
                    Control p = this.Parent;
                    while (p != null)
                    {
                        if (p == ctrl)
                        {
                            if (ctrl is MenuPanel)
                                ctrl.Focus();
                            return;
                        }
                        p = p.Parent;
                    }
                    if (ctrl != null)
                        ctrl.Focus();
                    else
                    {
                        NativeFunctions.SetFocus(focus);
                    }
                }
            }
        }
        protected override void OnKeyUp(KeyEventArgs e)
        {
            _ButtonGroup.ProcessKeyUp(e);
            base.OnKeyUp(e);
        }
        protected override void OnKeyDown(KeyEventArgs e)
        {
            _ButtonGroup.ProcessKeyDown(e);
            base.OnKeyDown(e);
            if (m_IsTextBoxItem)
            {
                /*if (e.KeyCode == Keys.Enter)
                    ReleaseFocus();
                else*/
                if (!e.Handled && e.KeyCode == Keys.Escape)
                {
                    this.Text = m_OriginalText;
                    this.SelectionStart = 0;
                    ReleaseFocus();
                }
            }
        }
        /// 
        /// Occurs during preprocessing to handle command keys. Command keys are keys that always take precedence over regular input keys. Examples of command keys include accelerators and menu shortcuts. Set Handled=true to indicate that you handled the key and that it should not be passed for further processing.
        /// 
        [Description("Occurs during preprocessing to handle command keys. Command keys are keys that always take precedence over regular input keys. Examples of command keys include accelerators and menu shortcuts. Set Handled=true to indicate that you handled the key and that it should not be passed for further processing.")]
        public event KeyEventHandler CommandKeyDown;
        /// 
        /// Raises CommandKeyDown event.
        /// 
        /// Provides event arguments.
        protected virtual void OnCommandKeyDown(KeyEventArgs e)
        {
            KeyEventHandler handler = CommandKeyDown;
            if (handler != null)
                handler(this, e);
        }
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if ((keyData & Keys.A) == Keys.A && Control.ModifierKeys == Keys.ControlKey)
            {
                this.SelectAll();
                return true;
            }
            if (_ButtonGroup.ProcessCmdKey(ref msg, keyData))
                return true;
            if (CommandKeyDown != null)
            {
                KeyEventArgs args = new KeyEventArgs(keyData);
                OnCommandKeyDown(args);
                if (args.Handled) return true;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }
        protected override void OnGotFocus(EventArgs e)
        {
            if (_AutoSelectAll)
                this.SelectAll();
            base.OnGotFocus(e);
        }
        protected override void OnLostFocus(EventArgs e)
        {
            m_LastFocusWindow = IntPtr.Zero;
            base.OnLostFocus(e);
        }
        /// 
        /// Gets or sets the scrollbar skinning type when control is using Office 2007 style.
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public eScrollBarSkin ScrollbarSkin
        {
            get { return m_NCPainter.SkinScrollbars; }
            set { m_NCPainter.SkinScrollbars = value; }
        }
        /// 
        /// Specifies the control border style. Default value has Class property set so the system style for the control is used.
        /// 
        [Browsable(true), Category("Style"), Description("Specifies the control border style. Default value has Class property set so the system style for the control is used."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ElementStyle Border
        {
            get { return m_BorderStyle; }
        }
        private void BorderStyle_StyleChanged(object sender, EventArgs e)
        {
            InvalidateNonClient();
        }
        protected override void OnReadOnlyChanged(EventArgs e)
        {
            InvalidateNonClient();
            base.OnReadOnlyChanged(e);
        }
        /// 
        /// Invalidates non-client area of the text box as response to the border changes.
        /// 
        public void InvalidateNonClient()
        {
            if (!BarFunctions.IsHandleValid(this)) return;
            NativeFunctions.SetWindowPos(this.Handle, IntPtr.Zero, 0, 0, 0, 0, NativeFunctions.SWP_FRAMECHANGED |
                                NativeFunctions.SWP_NOACTIVATE | NativeFunctions.SWP_NOMOVE | NativeFunctions.SWP_NOSIZE | NativeFunctions.SWP_NOZORDER);
            SetAutoHeight();
            const int RDW_INVALIDATE = 0x0001;
            const int RDW_FRAME = 0x0400;
            NativeFunctions.RECT r = new NativeFunctions.RECT(0, 0, this.Width, this.Height);
            NativeFunctions.RedrawWindow(this.Handle, ref r, IntPtr.Zero, RDW_INVALIDATE | RDW_FRAME);
        }
        private TextMarkup.BodyElement m_TextMarkup = null;
        private void MarkupTextChanged()
        {
            m_TextMarkup = null;
            if (!TextMarkup.MarkupParser.IsMarkup(ref m_WatermarkText))
                return;
            m_TextMarkup = TextMarkup.MarkupParser.Parse(m_WatermarkText);
            ResizeMarkup();
        }
        private void ResizeMarkup()
        {
            if (m_TextMarkup != null)
            {
                using (Graphics g = this.CreateGraphics())
                {
                    MarkupDrawContext dc = GetMarkupDrawContext(g);
                    m_TextMarkup.Measure(GetWatermarkBounds().Size, dc);
                    Size sz = m_TextMarkup.Bounds.Size;
                    m_TextMarkup.Arrange(new Rectangle(GetWatermarkBounds().Location, sz), dc);
                }
            }
        }
        private Rectangle GetWatermarkBounds()
        {
            Rectangle r = this.ClientRectangle;
            r.Inflate(-1, 0);
            return r;
        }
        private void DrawWatermark()
        {
            using (Graphics g = this.CreateGraphics())
            {
                Rectangle bounds = GetWatermarkBounds();
                if (_WatermarkImage != null)
                {
                    Rectangle imageBounds = new Rectangle(Point.Empty, _WatermarkImage.Size);
                    if (_WatermarkImageAlignment == ContentAlignment.BottomCenter)
                        imageBounds.Location = new Point(bounds.X + (bounds.Width - imageBounds.Width) / 2, bounds.Bottom - imageBounds.Height);
                    else if (_WatermarkImageAlignment == ContentAlignment.BottomLeft)
                        imageBounds.Location = new Point(bounds.X, bounds.Bottom - imageBounds.Height);
                    else if (_WatermarkImageAlignment == ContentAlignment.BottomRight)
                        imageBounds.Location = new Point(bounds.Right - imageBounds.Width, bounds.Bottom - imageBounds.Height);
                    else if (_WatermarkImageAlignment == ContentAlignment.MiddleCenter)
                        imageBounds.Location = new Point(bounds.X + (bounds.Width - imageBounds.Width) / 2, bounds.Y + (bounds.Height - imageBounds.Height) / 2);
                    else if (_WatermarkImageAlignment == ContentAlignment.MiddleLeft)
                        imageBounds.Location = new Point(bounds.X, bounds.Y + (bounds.Height - imageBounds.Height) / 2);
                    else if (_WatermarkImageAlignment == ContentAlignment.MiddleRight)
                        imageBounds.Location = new Point(bounds.Right - imageBounds.Width, bounds.Y + (bounds.Height - imageBounds.Height) / 2);
                    else if (_WatermarkImageAlignment == ContentAlignment.TopCenter)
                        imageBounds.Location = new Point(bounds.X + (bounds.Width - imageBounds.Width) / 2, bounds.Y);
                    else if (_WatermarkImageAlignment == ContentAlignment.TopLeft)
                        imageBounds.Location = new Point(bounds.X, bounds.Y);
                    else if (_WatermarkImageAlignment == ContentAlignment.TopRight)
                        imageBounds.Location = new Point(bounds.Right - imageBounds.Width, bounds.Y);
                    g.DrawImage(_WatermarkImage, imageBounds);
                    if (_WatermarkImageAlignment == ContentAlignment.BottomLeft || _WatermarkImageAlignment == ContentAlignment.MiddleLeft || _WatermarkImageAlignment == ContentAlignment.TopLeft)
                    {
                        bounds.X = imageBounds.Right;
                        bounds.Width = Math.Max(0, bounds.Width - imageBounds.Width);
                    }
                    else if (_WatermarkImageAlignment == ContentAlignment.BottomRight || _WatermarkImageAlignment == ContentAlignment.MiddleRight || _WatermarkImageAlignment == ContentAlignment.TopRight)
                    {
                        bounds.Width = Math.Max(0, bounds.Width - imageBounds.Width);
                    }
                }
                if (bounds.Width <= 0) return;
                if (m_TextMarkup != null)
                {
                    MarkupDrawContext dc = GetMarkupDrawContext(g);
                    m_TextMarkup.Render(dc);
                }
                else
                {
                    eTextFormat tf = eTextFormat.Left;
                    if (this.Multiline)
                    {
                        if (this.TextAlign == HorizontalAlignment.Center)
                            tf |= eTextFormat.VerticalCenter;
                        else if (TextAlign == HorizontalAlignment.Right)
                            tf |= eTextFormat.Bottom;
                    }
                    if (this.RightToLeft == RightToLeft.Yes) tf |= eTextFormat.RightToLeft;
                    if (this.TextAlign == HorizontalAlignment.Left)
                        tf |= eTextFormat.Left;
                    else if (this.TextAlign == HorizontalAlignment.Right)
                        tf |= eTextFormat.Right;
                    else if (this.TextAlign == HorizontalAlignment.Center)
                        tf |= eTextFormat.HorizontalCenter;
                    tf |= eTextFormat.EndEllipsis;
                    tf |= eTextFormat.WordBreak;
                    TextDrawing.DrawString(g, m_WatermarkText, (m_WatermarkFont == null ? this.Font : m_WatermarkFont),
                        m_WatermarkColor, bounds, tf);
                }
            }
        }
        protected override void OnFontChanged(EventArgs e)
        {
            SetAutoHeight();
            base.OnFontChanged(e);
        }
        /// 
        /// Calculates and sets the text-box height based on font and style. This method is used internally and should not be used.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void SetAutoHeight()
        {
            if (!this.AutoSize && this.Multiline == false && this.BorderStyle == BorderStyle.None && !this.IsDisposed && this.Parent != null && !m_IsTextBoxItem)
            {
                int h = this.FontHeight;
                if (this.Font != null) h = Math.Max(h, this.Font.Height);
                h++;
                // Adjust for DPI other than 96
                //using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero))
                //{
                //    if (graphics.DpiX != 96f)
                //    {
                //        h = (int)Math.Ceiling(h * (graphics.DpiX / 96f));
                //    }
                //}
                bool disposeStyle = false;
                ElementStyle style = GetBorderStyle(out disposeStyle);
                if (style != null)
                {
                    if (style.PaintTopBorder)
                    {
                        if (style.CornerType == eCornerType.Rounded || style.CornerType == eCornerType.Diagonal)
                            h += Math.Max(style.BorderTopWidth, style.CornerDiameter / 2 + 1);
                        else
                            h += style.BorderTopWidth;
                    }
                    if (style.PaintBottomBorder)
                    {
                        if (style.CornerType == eCornerType.Rounded || style.CornerType == eCornerType.Diagonal)
                            h += Math.Max(style.BorderBottomWidth, style.CornerDiameter / 2 + 1);
                        else
                            h += style.BorderBottomWidth;
                    }
                    h += style.PaddingTop + style.PaddingBottom;
                    if (disposeStyle) style.Dispose();
                }
#if (FRAMEWORK20)
                if (_ButtonCustom != null && _ButtonCustom.Visible && _ButtonCustom.Image != null)
                {
                    h = Math.Max(h, _ButtonCustom.Image.Height + 6);
                }
                if (_ButtonCustom2 != null && _ButtonCustom2.Visible && _ButtonCustom2.Image != null)
                {
                    h = Math.Max(h, _ButtonCustom2.Image.Height + 6);
                }
#endif
                this.Height = h;
            }
        }
        protected override void OnResize(EventArgs e)
        {
            ResizeMarkup();
#if (FRAMEWORK20)
            _ButtonGroup.InvalidateArrange();
#endif
            base.OnResize(e);
        }
        private MarkupDrawContext GetMarkupDrawContext(Graphics g)
        {
            return new MarkupDrawContext(g, (m_WatermarkFont == null ? this.Font : m_WatermarkFont), m_WatermarkColor, this.RightToLeft == RightToLeft.Yes);
        }
        protected override void OnTextAlignChanged(EventArgs e)
        {
            if (m_WatermarkText.Length > 0)
                this.Invalidate();
            base.OnTextAlignChanged(e);
        }
        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
        }
        private Color _EnabledBackColor = Color.Empty;
        protected override void OnEnabledChanged(EventArgs e)
        {
            if (m_WatermarkText.Length > 0)
                this.Invalidate();
            UpdateEnabledBackColor();
            base.OnEnabledChanged(e);
        }
        private void UpdateEnabledBackColor()
        {
            if (!_DisabledBackColor.IsEmpty)
            {
                if (!this.Enabled)
                {
                    _EnabledBackColor = this.BackColor;
                    this.BackColor = _DisabledBackColor;
                }
                else if (!_EnabledBackColor.IsEmpty)
                {
                    this.BackColor = _EnabledBackColor;
                    _EnabledBackColor = Color.Empty;
                }
            }
        }
        protected override void OnTextChanged(EventArgs e)
        {
            if (m_WatermarkText.Length > 0)
                this.Invalidate();
            base.OnTextChanged(e);
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new BorderStyle BorderStyle
        {
            get { return base.BorderStyle; }
            set { }
        }
        private Rendering.BaseRenderer m_DefaultRenderer = null;
        private Rendering.BaseRenderer m_Renderer = null;
        private eRenderMode m_RenderMode = eRenderMode.Global;
        /// 
        /// Returns the renderer control will be rendered with.
        /// 
        /// The current renderer.
        public virtual Rendering.BaseRenderer GetRenderer()
        {
            if (m_RenderMode == eRenderMode.Global && Rendering.GlobalManager.Renderer != null)
                return Rendering.GlobalManager.Renderer;
            else if (m_RenderMode == eRenderMode.Custom && m_Renderer != null)
                return m_Renderer;
            if (m_DefaultRenderer == null)
                m_DefaultRenderer = new Rendering.Office2007Renderer();
            return m_DefaultRenderer;
        }
        /// 
        /// Gets or sets the rendering mode used by control. Default value is eRenderMode.Global which means that static GlobalManager.Renderer is used. If set to Custom then Renderer property must
        /// also be set to the custom renderer that will be used.
        /// 
        [Browsable(false), DefaultValue(eRenderMode.Global)]
        public eRenderMode RenderMode
        {
            get { return m_RenderMode; }
            set
            {
                if (m_RenderMode != value)
                {
                    m_RenderMode = value;
                    this.Invalidate(true);
                }
            }
        }
        /// 
        /// Gets or sets the custom renderer used by the items on this control. RenderMode property must also be set to eRenderMode.Custom in order renderer
        /// specified here to be used.
        /// 
        [Browsable(false), DefaultValue(null)]
        public DevComponents.DotNetBar.Rendering.BaseRenderer Renderer
        {
            get
            {
                return m_Renderer;
            }
            set { m_Renderer = value; }
        }
        private bool _WatermarkEnabled = true;
        /// 
        /// Gets or sets whether watermark text is displayed when control is empty. Default value is true.
        /// 
        [DefaultValue(true), Description("Indicates whether watermark text is displayed when control is empty.")]
        public virtual bool WatermarkEnabled
        {
            get { return _WatermarkEnabled; }
            set { _WatermarkEnabled = value; this.Invalidate(); }
        }
        private Image _WatermarkImage = null;
        /// 
        /// Gets or sets the watermark image displayed inside of the control when Text is not set and control does not have input focus.
        /// 
        [DefaultValue(null), Category("Appearance"), Description("Indicates watermark image displayed inside of the control when Text is not set and control does not have input focus.")]
        public Image WatermarkImage
        {
            get { return _WatermarkImage; }
            set { _WatermarkImage = value; this.Invalidate(); }
        }
        private ContentAlignment _WatermarkImageAlignment = ContentAlignment.MiddleLeft;
        /// 
        /// Gets or sets the watermark image alignment.
        /// 
        [DefaultValue(ContentAlignment.MiddleLeft), Category("Appearance"), Description("Indicates watermark image alignment.")]
        public ContentAlignment WatermarkImageAlignment
        {
            get { return _WatermarkImageAlignment; }
            set { _WatermarkImageAlignment = value; this.Invalidate(); }
        }
        /// 
        /// Gets or sets the watermark (tip) text displayed inside of the control when Text is not set and control does not have input focus. This property supports text-markup.
        /// 
        [Browsable(true), DefaultValue(""), Localizable(true), Category("Appearance"), Description("Indicates watermark text displayed inside of the control when Text is not set and control does not have input focus."), Editor("DevComponents.DotNetBar.Design.TextMarkupUIEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral,  PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor))]
        public string WatermarkText
        {
            get { return m_WatermarkText; }
            set
            {
                if (value == null) value = "";
                m_WatermarkText = value;
                MarkupTextChanged();
                this.Invalidate();
            }
        }
        /// 
        /// Gets or sets the watermark font.
        /// 
        [Browsable(true), Category("Appearance"), Description("Indicates watermark font."), DefaultValue(null)]
        public Font WatermarkFont
        {
            get { return m_WatermarkFont; }
            set { m_WatermarkFont = value; this.Invalidate(); }
        }
        /// 
        /// Gets or sets the watermark text color.
        /// 
        [Browsable(true), Category("Appearance"), Description("Indicates watermark text color.")]
        public Color WatermarkColor
        {
            get { return m_WatermarkColor; }
            set { m_WatermarkColor = value; this.Invalidate(); }
        }
        /// 
        /// Indicates whether property should be serialized by Windows Forms designer.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeWatermarkColor()
        {
            return m_WatermarkColor != SystemColors.GrayText;
        }
        /// 
        /// Resets the property to default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetWatermarkColor()
        {
            this.WatermarkColor = SystemColors.GrayText;
        }
        private eWatermarkBehavior _WatermarkBehavior = eWatermarkBehavior.HideOnFocus;
        /// 
        /// Gets or sets the watermark hiding behaviour. Default value indicates that watermark is hidden when control receives input focus.
        /// 
        [DefaultValue(eWatermarkBehavior.HideOnFocus), Category("Behavior"), Description("Indicates watermark hiding behaviour.")]
        public eWatermarkBehavior WatermarkBehavior
        {
            get { return _WatermarkBehavior; }
            set { _WatermarkBehavior = value; this.Invalidate(); }
        }
        private ElementStyle GetBorderStyle(out bool disposeStyle)
        {
            disposeStyle = false;
            m_BorderStyle.SetColorScheme(this.GetColorScheme());
            return ElementStyleDisplay.GetElementStyle(m_BorderStyle, out disposeStyle);
        }
#if FRAMEWORK20
        private InputButtonSettings _ButtonCustom = null;
        /// 
        /// Gets the object that describes the settings for the custom button that can execute an custom action of your choosing when clicked.
        /// 
        [Category("Buttons"), Description("Describes the settings for the custom button that can execute an custom action of your choosing when clicked."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public InputButtonSettings ButtonCustom
        {
            get
            {
                return _ButtonCustom;
            }
        }
        private InputButtonSettings _ButtonCustom2 = null;
        /// 
        /// Gets the object that describes the settings for the custom button that can execute an custom action of your choosing when clicked.
        /// 
        [Category("Buttons"), Description("Describes the settings for the custom button that can execute an custom action of your choosing when clicked."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public InputButtonSettings ButtonCustom2
        {
            get
            {
                return _ButtonCustom2;
            }
        }
        void IInputButtonControl.InputButtonSettingsChanged(InputButtonSettings inputButtonSettings)
        {
            OnInputButtonSettingsChanged(inputButtonSettings);
        }
        protected virtual void OnInputButtonSettingsChanged(InputButtonSettings inputButtonSettings)
        {
            UpdateButtons();
        }
        private VisualGroup _ButtonGroup = null;
        private void UpdateButtons()
        {
            RecreateButtons();
            _ButtonGroup.InvalidateArrange();
            this.InvalidateNonClient();
        }
        protected virtual void RecreateButtons()
        {
            VisualItem[] buttons = CreateOrderedButtonList();
            // Remove all system buttons that are already in the list
            VisualGroup group = _ButtonGroup;
            VisualItem[] items = new VisualItem[group.Items.Count];
            group.Items.CopyTo(items);
            foreach (VisualItem item in items)
            {
                if (item.ItemType == eSystemItemType.SystemButton)
                {
                    group.Items.Remove(item);
                    if (item == _ButtonCustom.ItemReference)
                        item.MouseUp -= new MouseEventHandler(CustomButtonClick);
                    else if (item == _ButtonCustom2.ItemReference)
                        item.MouseUp -= new MouseEventHandler(CustomButton2Click);
                }
            }
            // Add new buttons to the list
            group.Items.AddRange(buttons);
        }
        private void CustomButtonClick(object sender, MouseEventArgs e)
        {
            if (_ButtonCustom.ItemReference.RenderBounds.Contains(e.X, e.Y))
                OnButtonCustomClick(e);
        }
        /// 
        /// Invokes ButtonCustomClick event.
        /// 
        public void PerformButtonCustomClick()
        {
            OnButtonCustomClick(EventArgs.Empty);
        }
        protected virtual void OnButtonCustomClick(EventArgs e)
        {
            if (ButtonCustomClick != null)
                ButtonCustomClick(this, e);
        }
        private void CustomButton2Click(object sender, MouseEventArgs e)
        {
            if (_ButtonCustom2.ItemReference.RenderBounds.Contains(e.X, e.Y))
                OnButtonCustom2Click(e);
        }
        /// 
        /// Invokes ButtonCustomClick2 event.
        /// 
        public void PerformButtonCustom2Click()
        {
            OnButtonCustom2Click(EventArgs.Empty);
        }
        protected virtual void OnButtonCustom2Click(EventArgs e)
        {
            if (ButtonCustom2Click != null)
                ButtonCustom2Click(this, e);
        }
        private VisualItem[] CreateOrderedButtonList()
        {
            SortedList list = CreateSortedButtonList();
            VisualItem[] items = new VisualItem[list.Count];
            list.Values.CopyTo(items, 0);
            return items;
        }
        private void CustomButtonKeyClick(object sender, EventArgs e)
        {
            if (e is KeyEventArgs)
                OnButtonCustomClick(e);
        }
        private void CustomButton2KeyClick(object sender, EventArgs e)
        {
            if (e is KeyEventArgs)
                OnButtonCustom2Click(e);
        }
        protected virtual SortedList CreateSortedButtonList()
        {
            SortedList list = new SortedList(4);
            if (_ButtonCustom.Visible)
            {
                VisualItem button = CreateButton(_ButtonCustom);
                if (_ButtonCustom.ItemReference != null)
                {
                    _ButtonCustom.ItemReference.MouseUp -= CustomButtonClick;
                    _ButtonCustom.ItemReference.Click -= CustomButtonKeyClick;
                }
                _ButtonCustom.ItemReference = button;
                button.Click += CustomButtonKeyClick;
                button.MouseUp += new MouseEventHandler(CustomButtonClick);
                button.Enabled = _ButtonCustom.Enabled;
                list.Add(_ButtonCustom, button);
            }
            if (_ButtonCustom2.Visible)
            {
                VisualItem button = CreateButton(_ButtonCustom2);
                if (_ButtonCustom2.ItemReference != null)
                {
                    _ButtonCustom2.ItemReference.MouseUp -= CustomButton2Click;
                    _ButtonCustom2.ItemReference.Click -= CustomButton2KeyClick;
                }
                _ButtonCustom2.ItemReference = button;
                button.Click += CustomButton2KeyClick;
                button.MouseUp += new MouseEventHandler(CustomButton2Click);
                button.Enabled = _ButtonCustom2.Enabled;
                list.Add(_ButtonCustom2, button);
            }
            return list;
        }
        protected virtual VisualItem CreateButton(InputButtonSettings buttonSettings)
        {
            VisualCustomButton button = new VisualCustomButton();
            ApplyButtonSettings(buttonSettings, button);
            return button;
        }
        protected virtual void ApplyButtonSettings(InputButtonSettings buttonSettings, VisualButton button)
        {
            button.Text = buttonSettings.Text;
            button.Image = buttonSettings.Image;
            button.ItemType = eSystemItemType.SystemButton;
            button.Enabled = buttonSettings.Enabled;
            button.Shortcut = buttonSettings.Shortcut;
            button.Tooltip = buttonSettings.Tooltip;
            button.Symbol = buttonSettings.Symbol;
            button.SymbolSet = buttonSettings.SymbolSet;
            button.SymbolColor = buttonSettings.SymbolColor;
            button.Checked = buttonSettings.Checked;
        }
        private void CreateButtonGroup()
        {
            VisualGroup group = new VisualGroup();
            group.HorizontalItemSpacing = 0;
            group.ArrangeInvalid += ButtonGroupArrangeInvalid;
            group.RenderInvalid += ButtonGroupRenderInvalid;
            group.ResetMouseHover += ButtonGroupResetMouseHover;
            _ButtonGroup = group;
        }
        private void ButtonGroupRenderInvalid(object sender, EventArgs e)
        {
            InvalidateNonClient();
        }
        private void ButtonGroupArrangeInvalid(object sender, EventArgs e)
        {
            InvalidateNonClient();
        }
        private void ButtonGroupResetMouseHover(object sender, EventArgs e)
        {
            DevComponents.AdvTree.Interop.WinApi.ResetHover(this);
        }
        private bool _MouseOver = false;
        private PaintInfo CreatePaintInfo(Graphics g)
        {
            PaintInfo p = new PaintInfo();
            p.Graphics = g;
            p.DefaultFont = this.Font;
            p.ForeColor = this.ForeColor;
            p.RenderOffset = new System.Drawing.Point();
            Size s = this.Size;
            bool disposeStyle = false;
            ElementStyle style = GetBorderStyle(out disposeStyle);
            s.Height -= (ElementStyleLayout.TopWhiteSpace(style, eSpacePart.Border) + ElementStyleLayout.BottomWhiteSpace(style, eSpacePart.Border)) + 2;
            s.Width -= (ElementStyleLayout.LeftWhiteSpace(style, eSpacePart.Border) + ElementStyleLayout.RightWhiteSpace(style, eSpacePart.Border)) + 2;
            p.AvailableSize = s;
            p.ParentEnabled = this.Enabled;
            p.MouseOver = _MouseOver || this.Focused;
            if (disposeStyle) style.Dispose();
            return p;
        }
        private bool RenderButtons
        {
            get
            {
                return (this.ScrollBars == ScrollBars.None) && (_ButtonCustom != null && _ButtonCustom.Visible || _ButtonCustom2 != null && _ButtonCustom2.Visible);
            }
        }
        private void PaintButtons(Graphics g)
        {
            PaintInfo p = CreatePaintInfo(g);
            if (!_ButtonGroup.IsLayoutValid)
            {
                _ButtonGroup.PerformLayout(p);
            }
            bool disposeStyle = false;
            ElementStyle style = GetBorderStyle(out disposeStyle);
            //p.RenderOffset = new Point(this.Width - ElementStyleLayout.RightWhiteSpace(style, eSpacePart.Border) - _ButtonGroup.Size.Width, ElementStyleLayout.TopWhiteSpace(style, eSpacePart.Border));
            _ButtonGroup.RenderBounds = new Rectangle(this.Width - (ElementStyleLayout.RightWhiteSpace(style, eSpacePart.Border) + 1) - _ButtonGroup.Size.Width, ElementStyleLayout.TopWhiteSpace(style, eSpacePart.Border) + 1,
                _ButtonGroup.Size.Width, _ButtonGroup.Size.Height);
            _ButtonGroup.ProcessPaint(p);
            if (disposeStyle) style.Dispose();
        }
        private Cursor _ControlCursor = null;
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (RenderButtons)
            {
                _ButtonGroup.ProcessMouseMove(e);
                if (_ButtonGroup.RenderBounds.Contains(e.X, e.Y))
                {
                    if (_ControlCursor == null)
                    {
                        _InternalCursorChange = true;
                        _ControlCursor = this.Cursor;
                        this.Cursor = Cursors.Arrow;
                        _InternalCursorChange = false;
                    }
                }
                else if (_ControlCursor != null)
                {
                    _InternalCursorChange = true;
                    this.Cursor = _ControlCursor;
                    _ControlCursor = null;
                    _InternalCursorChange = false;
                }
            }
            base.OnMouseMove(e);
        }
        protected override void OnMouseEnter(EventArgs e)
        {
            _MouseOver = true;
            base.OnMouseEnter(e);
        }
        protected override void OnMouseLeave(EventArgs e)
        {
            _MouseOver = false;
            if (RenderButtons)
            {
                _ButtonGroup.ProcessMouseLeave();
                if (_ControlCursor != null)
                {
                    _InternalCursorChange = true;
                    this.Cursor = _ControlCursor;
                    _ControlCursor = null;
                    _InternalCursorChange = false;
                }
            }
            base.OnMouseLeave(e);
        }
        private bool _InternalCursorChange = false;
        protected override void OnCursorChanged(EventArgs e)
        {
            if (_ControlCursor != null && !_InternalCursorChange)
                _ControlCursor = this.Cursor;
            base.OnCursorChanged(e);
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (RenderButtons)
                _ButtonGroup.ProcessMouseDown(e);
            base.OnMouseDown(e);
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (RenderButtons)
                _ButtonGroup.ProcessMouseUp(e);
            base.OnMouseUp(e);
        }
        protected override void OnMouseHover(EventArgs e)
        {
            if (RenderButtons)
                _ButtonGroup.ProcessMouseHover(e);
            base.OnMouseHover(e);
        }
#endif
        #endregion
        #region INonClientControl Members
        void INonClientControl.BaseWndProc(ref Message m)
        {
            base.WndProc(ref m);
        }
        //CreateParams INonClientControl.ControlCreateParams
        //{
        //    get { return base.CreateParams; }
        //}
        ItemPaintArgs INonClientControl.GetItemPaintArgs(System.Drawing.Graphics g)
        {
            ItemPaintArgs pa = new ItemPaintArgs(this as IOwner, this, g, GetColorScheme());
            pa.Renderer = this.GetRenderer();
            pa.DesignerSelection = false; // m_DesignerSelection;
            pa.GlassEnabled = !this.DesignMode && WinApi.IsGlassEnabled;
            return pa;
        }
        ElementStyle INonClientControl.BorderStyle
        {
            get { bool disposeStyle = false; return GetBorderStyle(out disposeStyle); }
        }
        void INonClientControl.PaintBackground(PaintEventArgs e)
        {
            if (this.Parent == null) return;
            Type t = typeof(Control);
            MethodInfo mi = t.GetMethod("PaintTransparentBackground", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(PaintEventArgs), typeof(Rectangle) }, null);
            if (mi != null)
            {
                mi.Invoke(this, new object[] { e, new Rectangle(0, 0, this.Width, this.Height) });
            }
        }
        private ColorScheme m_ColorScheme = null;
        /// 
        /// Returns the color scheme used by control. Color scheme for Office2007 style will be retrived from the current renderer instead of
        /// local color scheme referenced by ColorScheme property.
        /// 
        /// An instance of ColorScheme object.
        protected virtual ColorScheme GetColorScheme()
        {
            BaseRenderer r = GetRenderer();
            if (r is Office2007Renderer)
                return ((Office2007Renderer)r).ColorTable.LegacyColors;
            if (m_ColorScheme == null)
                m_ColorScheme = new ColorScheme(eDotNetBarStyle.Office2007);
            return m_ColorScheme;
        }
        IntPtr INonClientControl.Handle
        {
            get { return this.Handle; }
        }
        int INonClientControl.Width
        {
            get { return this.Width; }
        }
        int INonClientControl.Height
        {
            get { return this.Height; }
        }
        bool INonClientControl.IsHandleCreated
        {
            get { return this.IsHandleCreated; }
        }
        Point INonClientControl.PointToScreen(Point client)
        {
            return this.PointToScreen(client);
        }
        Color INonClientControl.BackColor
        {
            get { return this.BackColor; }
        }
        void INonClientControl.AdjustClientRectangle(ref Rectangle r)
        {
#if FRAMEWORK20
            if (RenderButtons)
            {
                if (!_ButtonGroup.IsLayoutValid)
                {
                    using (Graphics g = this.CreateGraphics())
                    {
                        PaintInfo p = CreatePaintInfo(g);
                        _ButtonGroup.PerformLayout(p);
                    }
                }
                r.Width -= _ButtonGroup.Size.Width + 1;
            }
#endif
        }
        void INonClientControl.AdjustBorderRectangle(ref Rectangle r) { }
        void INonClientControl.RenderNonClient(Graphics g)
        {
#if FRAMEWORK20
            if (RenderButtons)
                PaintButtons(g);
#endif
        }
        private Color _DisabledBackColor = Color.Empty;
        /// 
        /// Specifies back color when Enabled=false
        /// 
        [Browsable(true), Category("Appearance"), Description("Specifies back color when Enabled=false")]
        public Color DisabledBackColor
        {
            get { return _DisabledBackColor; }
            set
            {
                _DisabledBackColor = value;
                if (!Enabled) this.Invalidate();
            }
        }
        public bool ShouldSerializeDisabledBackColor()
        {
            return !_DisabledBackColor.IsEmpty;
        }
        public void ResetDisabledBackColor()
        {
            DisabledBackColor = Color.Empty;
        }
        #endregion
    }
}