using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Collections.ObjectModel;
namespace DevComponents.DotNetBar.Keyboard
{
    // A Keyboard is defined by one or more KeyboardLayout objects.
    // A KeyboardLayout is a layout of certain Key objects.
    // A Key object represents all the data that a virtual key needs (caption, actual key-information to send 
    // to the attached control, hint, bounds, style, etc).
    // Because in this version of the VirtualKeyboard control the user cannot design new layouts for the keyboard, 
    // we will not publicly expose the model classes of the keyboard.
    /// 
    /// Holds information about a single virtual keyboard Key.
    /// 
    public class Key
    {
        private string _Caption;
        
        /// 
        /// Gets the caption on the key.
        /// 
        public string Caption
        {
            get { return _Caption; }
        }
        private string _Info;
        
        /// 
        /// Gets the actual key-information that is sent to the attached control. The format of this information
        /// must confirm to the description for the SendKeys.Send function. For more details, see:
        /// http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx
        /// 
        public string Info
        {
            get { return _Info; }
        }
        private Rectangle _Bounds;
        /// 
        /// Gets the bounds of the key.
        /// 
        public Rectangle Bounds
        {
            get { return _Bounds; }
            internal set { _Bounds = value; }
        }
        
        private KeyStyle _Style;
        /// 
        /// Gets a value representing the way the key looks on the virtual keyboard. A key might look normal, 
        /// lighter, darker or with a pressed effect.
        /// 
        public KeyStyle Style
        {
            get { return _Style; }
        }
        
        private int _ChangeToLayout;
        /// 
        /// Gets the index of the layout to change to, if this key is pressed. A positive value represents a new layout.
        /// KeyboardLayout.NoChange and KeyboardLayout.PreviousLayout constants can also be used with special meaning.
        /// 
        /// 
        /// If this is a positive integer ( >= 0 ), it represents the index of the layout to switch to when this key 
        /// is pressed. In this case, the keyboard does not send any key information to the attached control (the Info
        /// field is ignored), only changes the layout.
        /// 
        /// If this is KeyboardLayout.NoChange the keyboard will send the info to the attached control.
        /// 
        /// If this is KeyboardLayout.PreviousLayout the keyboard will switch to the previous set layout. The keyboard
        /// maintains internally a stack of all used layouts. If no more layouts in the stakc, the keyboard switches to
        /// the layout with index 0.
        /// 
        public int ChangeToLayout
        {
            get { return _ChangeToLayout; }
        }
        private int _ChangeToLayoutEx;
        /// 
        /// Gets the index of the layout to change to, when this key is double clicked. A positive value represents a new layout.
        /// KeyboardLayout.NoChange and KeyboardLayout.PreviousLayout constants can also be used with special meaning.
        /// 
        /// 
        /// If this is a positive integer ( >= 0 ), it represents the index of the layout to switch to when this key 
        /// is pressed. In this case, the keyboard does not send any key information to the attached control (the Info
        /// field is ignored), only changes the layout.
        /// 
        /// If this is KeyboardLayout.NoChange the keyboard will send the info to the attached control.
        /// 
        /// If this is KeyboardLayout.PreviousLayout the keyboard will switch to the previous set layout. The keyboard
        /// maintains internally a stack of all used layouts. If no more layouts in the stakc, the keyboard switches to
        /// the layout with index 0.
        /// 
        public int ChangeToLayoutEx
        {
            get { return _ChangeToLayoutEx; }
        }
        
        private string _Hint;
        /// 
        /// Gets the text that will be displayed in the upper part of the keyboard, as a hint for what the key does,
        /// usually in combination with a modifier key (e.g. Underline, Undo, etc).
        /// 
        public string Hint
        {
            get { return _Hint; }
        }
        /// 
        /// Creates a new Key object.
        /// 
        /// The text displayed on the key.
        /// The information that will be sent to the attached control.
        /// The text in the upper part of the key, that provides a hint for the user about what the key does.
        /// The way the key looks.
        /// The index of the layout to switch to.
        public Key(string caption, string info = null, string hint = "", KeyStyle style = KeyStyle.Normal, int changeToLayout = KeyboardLayout.NoChange, int changeToLayoutEx = KeyboardLayout.NoChange)
        {
            _Caption = caption;
            _Info = info != null ? info : caption;
            _Style = style;
            _Hint = hint;
            _ChangeToLayout = changeToLayout;
            _ChangeToLayoutEx = changeToLayoutEx;
        }
        /// 
        /// Returns a string that represents the current Key.
        /// 
        /// A string that represents the current Key.
        public override string ToString()
        {
            return Caption;
        }
    }
    /// 
    /// Specifies the way a key looks, specifically what color it uses from the ColorTable.
    /// 
    public enum KeyStyle
    {
        /// 
        /// Key should be drawn as a normal key colors.
        /// 
        Normal,
        /// 
        /// Key should be drawn with lighter colors.
        /// 
        Light,
        /// 
        /// Key should be drawn with darker colors.
        /// 
        Dark,
        /// 
        /// Key should be drawn with the pressed color.
        /// 
        Pressed,
        /// 
        /// Key should be drawn with the toggled color.
        /// 
        Toggled
    }
    /// 
    /// Represents a layout for a virtual keyboard.
    /// 
    /// The Keys have coordinates in the KeyboardLayout specified in logical layout units. By default for this version
    /// of the control, a normal key is 10 logical units (LUs) width and 10 LUs height. A space between two keys is 1 LU.
    /// When rendering, we assume the whole Layout is stretched over the Keyboard control, so we need to change from 
    /// LUs (ranging from 0 to layout.LogicalWidth) to pixels (ranging from 0 to control.Width).
    /// This allows the layout to be resized to almost any sizes.
    public class KeyboardLayout
    {
        /// 
        /// Indicates that a key should switch the Keyboard to the previous layout.
        /// 
        public const int PreviousLayout = -2;
        /// 
        /// Indicates that a key does not switch to any layout.
        /// 
        public const int NoChange = -1;
        private KeysCollection _Keys = new KeysCollection();
        /// 
        /// Gets the collection of the Keys in this KeyboardLayout.
        /// 
        public KeysCollection Keys
        {
            get { return _Keys; }
        }
        /// 
        /// Gets the logical width of this KeyboardLayout.
        /// 
        public virtual int LogicalWidth
        {
            get
            {
                int w = 0;
                foreach (Key key in Keys)
                {
                    if (key.Bounds.Right > w)
                        w = key.Bounds.Right;
                }
                return w;
            }
        }
        /// 
        /// Gets the logical height of this KeyboardLayout.
        /// 
        public virtual int LogicalHeight
        {
            get
            {
                int h = 0;
                foreach (Key key in Keys)
                {
                    if (key.Bounds.Bottom > h)
                        h = key.Bounds.Bottom;
                }
                return h;
            }
        }
        /// 
        /// Tests if a certain point hits a key on the virtual keyboard.
        /// 
        /// The x-coordinate of the hit point (in logical units of this KeyboardLayout)
        /// The y-coordinate of the hit point (in logical units of this KeyboardLayout)
        /// Returns the key that was hit, or null if the point didn't hit any keys.
        public Key KeyHitTest(int x, int y)
        {
            foreach (Key key in Keys)
            {
                if (key.Bounds.Contains(x, y))
                    return key;
            }
            return null;
        }
    }
    /// 
    /// Represents a layout for a virtual keyboard in which keys are defined in a linear way. This class
    /// allows creation of layouts in which keys can be ordered from left to right and from top to bottom.
    /// 
    /// 
    /// With the linear layout, the keys are allowed to have any width. The height, however, must be the same.
    /// This layout is build by adding to it spaces, keys and new lines.
    /// A key represents a virtual key AND a space after it.
    /// A space represents a placeholder between two keys and it is used when there is need for a larger space
    /// between two certain keys
    /// A new line represents the fact that a new line of keys should be defined.
    /// 
    /// 
    /// The default virtual keyboard of the VirtualKeyboard control is defined in the following way:
    /// 
    /// AddKey("q");
    /// AddKey("w");
    /// AddKey("e");
    /// // ...
    /// AddKey("p");
    /// AddKey("Backspace");
    ///
    /// AddLine(); // Starts a new row of keys.
    /// AddSpace(4); // Creates a larger space at the beginning of the second row.
    ///
    /// AddKey("a");
    /// AddKey("s");
    /// // ...
    /// 
    /// 
    public class LinearKeyboardLayout : KeyboardLayout
    {
        private int _LastXOffset = 0;
        private int _LastYOffset = 0;
        /// 
        /// The logical size of the space between two keys.
        /// 
        public const int SpaceSize = 1;
        /// 
        /// The logical size of a key.
        /// 
        public const int NormalKeySize = 10;
        /// 
        /// Adds a space to this LinearKeyboardLayout.
        /// 
        /// The size of the space, in logical units.
        public void AddSpace(int width = SpaceSize)
        {
            width = Dpi.Width(width);
            _LastXOffset += width;
        }
        /// 
        /// Starts a new row of keys in this LinearKeyboardLayout.
        /// 
        public void AddLine()
        {
            _LastXOffset = 0;
            _LastYOffset += Dpi.Width(NormalKeySize + SpaceSize);
        }
        /// 
        /// Adds a new key to this LinearKeayboardLayout.
        /// 
        /// The text displayed on the key.
        /// The information that will be sent to the attached control.
        /// The text in the upper part of the key, that provides a hint for the user about what the key does.
        /// The width of the key, in logical units.
        /// The height of the key, in logical units.
        /// The way the key looks.
        /// The index of the layout to switch to.
        /// The index of the layout to switch to, when key is double clicked.
        public void AddKey(string caption, string info = null, string hint = "", int width = NormalKeySize, int height = NormalKeySize, KeyStyle style = KeyStyle.Normal, int layout = KeyboardLayout.NoChange, int layoutEx = KeyboardLayout.NoChange)
        {
            Key key = new Key(caption, info, hint, style, layout, layoutEx);
            width = Dpi.Width(width);
            height = Dpi.Height(height);
            key.Bounds = new Rectangle(_LastXOffset, _LastYOffset, width, height);
            
            _LastXOffset += width;
            AddSpace();
            Keys.Add(key);
        }
    }
    /// 
    /// Represents a Virtual Keyboard.
    /// 
    /// Each Keyboard has a collection of KeyboardLayout objects. The Keyboard also maintains the current Layout among all its layouts.
    public class Keyboard
    {
        private KeyboardLayoutsCollection _Layouts = new KeyboardLayoutsCollection();
        /// 
        /// Gets the collection of the keyboard layouts in this Keyboard.
        /// 
        public KeyboardLayoutsCollection Layouts
        {
            get { return _Layouts; }
        }
        private int _CurrentLayoutIndex;
        /// 
        /// Gets or sets the current layout index of this Keyboard.
        /// 
        public int CurrentLayoutIndex
        {
            get { return _CurrentLayoutIndex; }
            set
            {
                _LayoutStack.Push(_CurrentLayoutIndex);
                _CurrentLayoutIndex = value;
            }
        }
        /// 
        /// Gets the current layout of this Keyboard.
        /// 
        public KeyboardLayout CurrentLayout
        {
            get { return _Layouts[_CurrentLayoutIndex]; }
        }
        private Stack _LayoutStack = new Stack();
        /// 
        /// Switches the Keyboard to the previous layout.
        /// 
        public void ChangeToPreviousLayout()
        {
            if (_LayoutStack.Count > 0)
                _CurrentLayoutIndex = _LayoutStack.Pop();
            else
                _CurrentLayoutIndex = 0;
        }
        /// 
        /// Switches the Keyboard to the first layout and resets the layout stack.
        /// 
        public void ResetLayoutStack()
        {
            _LayoutStack.Clear();
            _CurrentLayoutIndex = 0;
        }
        /// 
        /// Creates the default Keyboard populated with common layouts and functionality.
        /// 
        /// A new Keyboard instance representing a default keyboard.
        public static Keyboard CreateDefaultKeyboard()
        {
            Keyboard keyboard = new Keyboard();
            LinearKeyboardLayout kc; // Actually there are 4 layout objects, but for code simplicity this variable is reused for creating each of them.
            #region Normal style configuration (no modifier keys pressed)
            
            kc = new LinearKeyboardLayout();
            keyboard._Layouts.Add(kc);
            kc.AddKey("q");
            kc.AddKey("w");
            kc.AddKey("e");
            kc.AddKey("r");
            kc.AddKey("t");
            kc.AddKey("y");
            kc.AddKey("u");
            kc.AddKey("i");
            kc.AddKey("o");
            kc.AddKey("p");
            kc.AddKey("Backspace", info: "{BACKSPACE}", width: 21);
            kc.AddLine();
            kc.AddSpace(4);
            kc.AddKey("a");
            kc.AddKey("s");
            kc.AddKey("d");
            kc.AddKey("f");
            kc.AddKey("g");
            kc.AddKey("h");
            kc.AddKey("j");
            kc.AddKey("k");
            kc.AddKey("l");
            kc.AddKey("'");
            kc.AddKey("Enter", info: "{ENTER}", width: 17);
            kc.AddLine();
            kc.AddKey("Shift", info: "", style: KeyStyle.Dark, layout: 1);
            kc.AddKey("z");
            kc.AddKey("x");
            kc.AddKey("c");
            kc.AddKey("v");
            kc.AddKey("b");
            kc.AddKey("n");
            kc.AddKey("m");
            kc.AddKey(",");
            kc.AddKey(".");
            kc.AddKey("?");
            kc.AddKey("Shift", info: "", style: KeyStyle.Dark, layout: 1);
            kc.AddLine();
            kc.AddKey("Ctrl", info: "", style: KeyStyle.Dark, layout: 2);
            kc.AddKey("&123", info: "", style: KeyStyle.Dark, layout: 3);
            kc.AddKey(":-)", info: ":-{)}", style: KeyStyle.Dark);
            //kc.AddKey("Alt", info: "%", style: KeyStyle.Dark);
            kc.AddKey(" ", width: 76);
            kc.AddKey("<", info: "{LEFT}", style: KeyStyle.Dark);
            kc.AddKey(">", info: "{RIGHT}", style: KeyStyle.Dark);
            #endregion
            #region Shift modifier pressed
            kc = new LinearKeyboardLayout();
            keyboard._Layouts.Add(kc);
            kc.AddKey("Q", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("W", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("E", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("R", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("T", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("Y", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("U", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("I", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("O", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("P", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("Backspace", info: "{BACKSPACE}", width: 21);
            kc.AddLine();
            kc.AddSpace(4);
            kc.AddKey("A", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("S", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("D", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("F", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("G", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("H", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("J", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("K", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("L", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("\"", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("Enter", info: "{ENTER}", width: 17);
            kc.AddLine();
            kc.AddKey("Shift", info: "", style: KeyStyle.Pressed, layout: 0, layoutEx: 4);
            kc.AddKey("Z", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("X", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("C", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("V", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("B", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("N", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("M", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey(";", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey(":", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("!", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("Shift", info: "", style: KeyStyle.Pressed, layout: 0, layoutEx: 4);
            kc.AddLine();
            kc.AddKey("Ctrl", info: "", style: KeyStyle.Dark, layout: 2);
            kc.AddKey("&123", info: "", style: KeyStyle.Dark, layout: 3);
            kc.AddKey(":-)", info: ":-{)}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
            kc.AddKey(" ", width: 76, layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("<", info: "+{LEFT}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
            kc.AddKey(">", info: "+{RIGHT}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
            
            #endregion
            #region Ctrl modifier pressed
            
            kc = new LinearKeyboardLayout();
            keyboard._Layouts.Add(kc);
            kc.AddKey("q", info: "^q", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("w", info: "^w", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("e", info: "^e", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("r", info: "^r", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("t", info: "^t", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("y", info: "^y", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("u", info: "^u", hint: "Underline", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("i", info: "^i", hint: "Italic", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("o", info: "^o", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("p", info: "^p", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("Backspace", info: "^{BACKSPACE}", width: 21, layout: KeyboardLayout.PreviousLayout);
            kc.AddLine();
            kc.AddSpace(4);
            kc.AddKey("a", info: "^a", hint: "Select all", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("s", info: "^s", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("d", info: "^d", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("f", info: "^f", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("g", info: "^g", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("h", info: "^h", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("j", info: "^j", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("k", info: "^k", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("l", info: "^l", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("'", info: "^'", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("Enter", info: "^{ENTER}", width: 17, layout: KeyboardLayout.PreviousLayout);
            kc.AddLine();
            kc.AddKey("Shift", info: "", layout: 1);
            kc.AddKey("z", info: "^z", hint: "Undo", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("x", info: "^x", hint: "Cut", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("c", info: "^c", hint: "Copy", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("v", info: "^v", hint: "Paste", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("b", info: "^b", hint: "Bold", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("n", info: "^n", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("m", info: "^m", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey(",", info: "^,", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey(".", info: "^.", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("?", info: "^?", layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("Shift", info: "", layout: 1);
            kc.AddLine();
            kc.AddKey("Ctrl", info: "", style: KeyStyle.Pressed, layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("&123", info: "", style: KeyStyle.Dark, layout: 3);
            kc.AddKey(":-)", info: "^:-{)}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
            kc.AddKey(" ", info: "^ ", width: 76, layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("<", info: "^{LEFT}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
            kc.AddKey(">", info: "^{RIGHT}", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
            #endregion
            #region Symbols and numbers (&123) modifier pressed
            kc = new LinearKeyboardLayout();
            keyboard._Layouts.Add(kc);
            kc.AddKey("!");
            kc.AddKey("@");
            kc.AddKey("#");
            kc.AddKey("$");
            kc.AddKey("½");
            kc.AddKey("-");
            kc.AddKey("+", info: "{+}");
            kc.AddSpace(5);
            kc.AddKey("1", style: KeyStyle.Light);
            kc.AddKey("2", style: KeyStyle.Light);
            kc.AddKey("3", style: KeyStyle.Light);
            kc.AddSpace(5);
            kc.AddKey("Bcks", info: "{BACKSPACE}", style: KeyStyle.Dark);
            kc.AddLine();
            // second line
            kc.AddKey(";");
            kc.AddKey(":");
            kc.AddKey("\"");
            kc.AddKey("%", info: "{%}");
            kc.AddKey("&");
            kc.AddKey("/");
            kc.AddKey("*");
            kc.AddSpace(5);
            kc.AddKey("4", style: KeyStyle.Light);
            kc.AddKey("5", style: KeyStyle.Light);
            kc.AddKey("6", style: KeyStyle.Light);
            kc.AddSpace(5);
            kc.AddKey("Enter", info: "{ENTER}", style: KeyStyle.Dark);
            kc.AddLine();
            // third line
            kc.AddKey("(", info: "{(}");
            kc.AddKey(")", info: "{)}");
            kc.AddKey("[", info: "{[}");
            kc.AddKey("]", info: "{]}");
            kc.AddKey("_");
            kc.AddKey("\\");
            kc.AddKey("=");
            kc.AddSpace(5);
            kc.AddKey("7", style: KeyStyle.Light);
            kc.AddKey("8", style: KeyStyle.Light);
            kc.AddKey("9", style: KeyStyle.Light);
            kc.AddSpace(5);
            kc.AddKey("Tab", info: "{TAB}", style: KeyStyle.Dark);
            kc.AddLine();
            // forth line
            kc.AddKey("...", style: KeyStyle.Dark, layout: KeyboardLayout.PreviousLayout);
            kc.AddKey("&123", info: "", style: KeyStyle.Pressed, layout: KeyboardLayout.PreviousLayout);
            kc.AddKey(":-)", info: ":-{)}", style: KeyStyle.Dark);
            kc.AddKey("<", info: "{LEFT}", style: KeyStyle.Dark);
            kc.AddKey(">", info: "{RIGHT}", style: KeyStyle.Dark);
            kc.AddKey("Space", info: "^ ", width: 21);
            
            kc.AddSpace(5);
            kc.AddKey("0", style:KeyStyle.Light, width: 21);
            kc.AddKey(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, style: KeyStyle.Dark);
            kc.AddSpace(5);
            kc.AddLine();
            #endregion
            #region Shift modifier toggled
            kc = new LinearKeyboardLayout();
            keyboard._Layouts.Add(kc);
            kc.AddKey("Q");
            kc.AddKey("W");
            kc.AddKey("E");
            kc.AddKey("R");
            kc.AddKey("T");
            kc.AddKey("Y");
            kc.AddKey("U");
            kc.AddKey("I");
            kc.AddKey("O");
            kc.AddKey("P");
            kc.AddKey("Backspace", info: "{BACKSPACE}", width: 21);
            kc.AddLine();
            kc.AddSpace(4);
            kc.AddKey("A");
            kc.AddKey("S");
            kc.AddKey("D");
            kc.AddKey("F");
            kc.AddKey("G");
            kc.AddKey("H");
            kc.AddKey("J");
            kc.AddKey("K");
            kc.AddKey("L");
            kc.AddKey("'");
            kc.AddKey("Enter", info: "{ENTER}", width: 17);
            kc.AddLine();
            kc.AddKey("Shift", info: "", style: KeyStyle.Toggled, layout: 0);
            kc.AddKey("Z");
            kc.AddKey("X");
            kc.AddKey("C");
            kc.AddKey("V");
            kc.AddKey("B");
            kc.AddKey("N");
            kc.AddKey("M");
            kc.AddKey(",");
            kc.AddKey(".");
            kc.AddKey("?");
            kc.AddKey("Shift", info: "", style: KeyStyle.Toggled, layout: 0);
            kc.AddLine();
            kc.AddKey("Ctrl", info: "", style: KeyStyle.Dark, layout: 2);
            kc.AddKey("&123", info: "", style: KeyStyle.Dark, layout: 3);
            kc.AddKey(":-)", info: ":-{)}", style: KeyStyle.Dark);
            kc.AddKey(" ", width: 76);
            kc.AddKey("<", info: "+{LEFT}", style: KeyStyle.Dark);
            kc.AddKey(">", info: "+{RIGHT}", style: KeyStyle.Dark);
            #endregion
            return keyboard;
        }
    }
    /// 
    /// Contains a collection of Key objects.
    /// 
    public class KeysCollection : Collection
    {
    }
    /// 
    /// Contains a collection of KeyboardLayout objects.
    /// 
    public class KeyboardLayoutsCollection : Collection
    {
    }
}