#if FRAMEWORK20
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
namespace DevComponents.Editors
{
    /// 
    /// Represents the group of the input items with automatic and manual item focus change.
    /// 
    public class VisualInputGroup : VisualGroup
    {
        #region Private Variables
        #endregion
        #region Events
        #endregion
        #region Constructor
        #endregion
        #region Internal Implementation
        /// 
        /// Resets the input position so the new input overwrites current value.
        /// 
        public void ResetInputPosition()
        {
            foreach (VisualItem item in this.Items)
            {
                VisualInputBase input = item as VisualInputBase;
                if (input != null)
                    input.ResetInputPosition();
            }
        }
        protected override bool OnCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
        {
            if (keyData == Keys.Tab && (Control.ModifierKeys & Keys.Shift) != Keys.Shift && this.TabNavigationEnabled ||
                keyData == Keys.Enter && this.EnterNavigationEnabled ||
                keyData == Keys.Right && this.ArrowNavigationEnabled)
            {
                ValidateInput(this.FocusedItem);
                if (SelectNextInput())
                    return true;
            }
            else if (keyData == Keys.Left && this.ArrowNavigationEnabled ||
                (keyData & Keys.Tab) == Keys.Tab && (keyData & Keys.Shift) == Keys.Shift && this.TabNavigationEnabled)
            {
                ValidateInput(this.FocusedItem);
                if (SelectPreviousInput())
                    return true;
            }
            return base.OnCmdKey(ref msg, keyData);
        }
        private bool _TabNavigationEnabled = true;
        /// 
        /// Gets or sets whether Tab key is used to navigate between the fields. Default value is true.
        /// 
        [DefaultValue(true)]
        public bool TabNavigationEnabled
        {
            get
            {
                return _TabNavigationEnabled;
            }
            set
            {
                _TabNavigationEnabled = value;
            }
        }
        private bool _EnterNavigationEnabled = true;
        /// 
        /// Gets or sets whether Enter key is used to navigate between input fields. Default value is true.
        /// 
        [DefaultValue(true)]
        public bool EnterNavigationEnabled
        {
            get
            {
                return _EnterNavigationEnabled;
            }
            set
            {
                _EnterNavigationEnabled = value;
            }
        }
        private bool _ArrowNavigationEnabled = true;
        /// 
        /// Gets or sets whether Arrow keys are used to navigate between input fields. Default value is true.
        /// 
        [DefaultValue(true)]
        public bool ArrowNavigationEnabled
        {
            get
            {
                return _ArrowNavigationEnabled;
            }
            set
            {
                _ArrowNavigationEnabled = value;
            }
        }
        private bool _AutoAdvance = false;
        /// 
        /// Gets or sets whether input focus is automatically advanced to next input field when input is complete in current one.
        /// 
        [DefaultValue(false)]
        public bool AutoAdvance
        {
            get { return _AutoAdvance; }
            set { _AutoAdvance = value; }
        }
        protected override void OnInputComplete()
        {
            if (ValidateInput(this.FocusedItem))
            {
                if (_AutoAdvance)
                {
                    if (!this.SelectNextInput())
                    {
                        OnGroupInputComplete();
                    }
                }
            }
            base.OnInputComplete();
        }
        protected virtual bool ValidateInput(VisualItem inputItem)
        {
            return true;
        }
        protected virtual void OnGroupInputComplete()
        {
            if (this.Parent != null)
            {
                this.Parent.ProcessInputComplete();
            }
        }
        internal bool SelectNextInput()
        {
            return SelectInputItem(true);
        }
        internal bool SelectPreviousInput()
        {
            return SelectInputItem(false);
        }
        internal bool SelectInputItem(bool moveForward)
        {
            if (this.FocusedItem is VisualInputGroup)
            {
                VisualInputGroup group = this.FocusedItem as VisualInputGroup;
                if (group.SelectInputItem(moveForward))
                    return true;
            }
            VisualCollectionEnumerator enumerator = new VisualCollectionEnumerator(this.Items, !moveForward || this.IsRightToLeft);
            enumerator.CurrentIndex = this.Items.IndexOf(this.FocusedItem);
            while (enumerator.MoveNext())
            {
                VisualInputBase vi = enumerator.Current as VisualInputBase;
                if (vi != null && CanFocus(vi))
                {
                    this.FocusedItem = vi;
                    return true;
                }
                else if (enumerator.Current is VisualInputGroup)
                {
                    VisualInputGroup group = enumerator.Current as VisualInputGroup;
                    if (group.SelectInputItem(moveForward))
                    {
                        this.FocusedItem = group;
                        return true;
                    }
                }
            }
            return false;
        }
        protected override void OnGroupFocused()
        {
            if (this.FocusedItem == null)
                SelectInputItem(true);
        }
        private bool _IsReadOnly = false;
        /// 
        /// Gets or sets whether input items are read-only.
        /// 
        public bool IsReadOnly
        {
            get { return _IsReadOnly; }
            set
            {
                if (_IsReadOnly != value)
                {
                    _IsReadOnly = value;
                    OnIsReadOnlyChanged();
                }
            }
        }
        private void OnIsReadOnlyChanged()
        {
            for (int i = 0; i < this.Items.Count; i++)
            {
                VisualInputBase v = this.Items[i] as VisualInputBase;
                if (v != null) v.IsReadOnly = this.IsReadOnly;
            }
        }
        protected override void OnItemsCollectionChanged(CollectionChangedInfo collectionChangedInfo)
        {
            if (collectionChangedInfo.ChangeType == eCollectionChangeType.Adding || collectionChangedInfo.ChangeType == eCollectionChangeType.Removing ||
                collectionChangedInfo.ChangeType == eCollectionChangeType.Clearing)
            {
                if (collectionChangedInfo.Added != null)
                {
                    foreach (VisualItem item in collectionChangedInfo.Added)
                    {
                        VisualInputBase v = item as VisualInputBase;
                        if (v != null)
                        {
                            v.IsReadOnly = this.IsReadOnly;
                            v.AutoOverwrite = _AutoOverwrite;
                        }
                    }
                }
            }
            base.OnItemsCollectionChanged(collectionChangedInfo);
        }
        private bool _AllowEmptyState = true;
        [DefaultValue(true)]
        public bool AllowEmptyState
        {
            get { return _AllowEmptyState; }
            set
            {
                if (_AllowEmptyState != value)
                {
                    _AllowEmptyState = value;
                    OnAllowEmptyStateChanged();
                    InvalidateArrange();
                }
            }
        }
        protected virtual void OnAllowEmptyStateChanged()
        {
            foreach (VisualItem item in this.Items)
            {
                if (item is VisualNumericInput) ((VisualNumericInput)item).AllowEmptyState = this.AllowEmptyState;
            }
        }
        private bool _IsEmpty = true;
        /// 
        /// Gets or sets whether input group is empty i.e. it does not hold any value.
        /// 
        [DefaultValue(true), Browsable(false)]
        public bool IsEmpty
        {
            get { return _IsEmpty; }
            set
            {
                if (_IsEmpty != value)
                {
                    _IsEmpty = value;
                    if (_IsEmpty)
                    {
                        ResetValue();
                    }
                    if (this.Parent is VisualInputGroup)
                        ((VisualInputGroup)this.Parent).UpdateIsEmpty();
                }
            }
        }
        protected override void OnInputChanged(VisualInputBase input)
        {
            UpdateIsEmpty();
            base.OnInputChanged(input);
        }
        /// 
        /// Updates the IsEmpty property value based on the contained input controls.
        /// 
        public virtual void UpdateIsEmpty()
        {
            bool empty = true;
            foreach (VisualItem item in this.Items)
            {
                if (item is VisualInputBase && !((VisualInputBase)item).IsEmpty)
                {
                    empty = false;
                    break;
                }
                else if (item is VisualInputGroup && !((VisualInputGroup)item).IsEmpty)
                {
                    empty = false;
                    break;
                }
            }
            this.IsEmpty = empty;
        }
        private bool _ResettingValue = false;
        protected virtual void ResetValue()
        {
            _ResettingValue = true;
            try
            {
                VisualItem[] items = new VisualItem[this.Items.Count];
                this.Items.CopyTo(items);
                foreach (VisualItem item in items)
                {
                    if (item is VisualInputGroup)
                        ((VisualInputGroup)item).IsEmpty = true;
                    else if (item is VisualInputBase)
                        ((VisualInputBase)item).IsEmpty = true;
                }
            }
            finally
            {
                _ResettingValue = false;
            }
        }
        private bool _AutoOverwrite = true;
        /// 
        /// Gets or sets whether auto-overwrite functionality for input is enabled. When in auto-overwrite mode input field will erase existing entry
        /// and start new one if typing is continued after InputComplete method is called.
        /// 
        public bool AutoOverwrite
        {
            get { return _AutoOverwrite; }
            set 
            {
                if (_AutoOverwrite != value)
                {
                    _AutoOverwrite = value;
                    OnAutoOverwriteChanged();
                }
            }
        }
        private void OnAutoOverwriteChanged()
        {
            foreach (VisualItem item in this.Items)
            {
                VisualInputBase input = item as VisualInputBase;
                if (input != null && input.AutoOverwrite != _AutoOverwrite)
                    input.AutoOverwrite = _AutoOverwrite;
            }
        }
        private bool _IsUserInput = false;
        /// 
        /// Gets or sets whether current input is the user input.
        /// 
        public bool IsUserInput
        {
            get { return _IsUserInput; }
            set
            {
                _IsUserInput = value;
            }
        }
        private string _SelectNextInputCharacters = "";
        /// 
        /// List of characters that when pressed would select next input field.
        /// 
        public string SelectNextInputCharacters
        {
            get { return _SelectNextInputCharacters; }
            set
            {
                if (value == null) value = "";
                if (_SelectNextInputCharacters != value)
                {
                    _SelectNextInputCharacters = value;
                }
            }
        }
        protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
        {
            if (_SelectNextInputCharacters.Length > 0 && _SelectNextInputCharacters.Contains(e.KeyChar.ToString()))
            {
                if (SelectNextInput())
                {
                    e.Handled = true;
                    return;
                }
            }
            base.OnKeyPress(e);
        }
        #endregion
    }
}
#endif