示例#1
0
        /// <summary>
        /// Adds a mouse scroll definition.
        /// </summary>
        /// <param name="id">The identifier of the key.</param>
        /// <param name="elements">The kb file elements describing the key.</param>
        /// <param name="definition">The keyboard definition to add the key to.</param>
        /// <param name="keyCode">The keycode to add.</param>
        private static void AddMouseScroll(int id, string[] elements, KeyboardDefinition definition, int keyCode)
        {
            if (elements.Length < 10)
            {
                throw new LegacyFileParseException("A key definition line should have at least 10 elements.");
            }

            // Parse the individual elements of the line.
            var posX       = ParseInt(elements[2], "X-Position");
            var posY       = ParseInt(elements[3], "Y-Position");
            var width      = ParseInt(elements[4], "Width");
            var height     = ParseInt(elements[5], "Height");
            var normalText = LegacyCharacterMapping.Replace(elements[6]);

            // Construct the new key definition.
            var newKeyDefinition = new MouseScrollDefinition(
                id: id,
                boundaries: new List <TPoint>
            {
                new TPoint(posX, posY),
                new TPoint(posX + width, posY),
                new TPoint(posX + width, posY + height),
                new TPoint(posX, posY + height)
            },
                keyCode: keyCode,
                text: normalText);

            AddOrOverlap(definition, keyCode, newKeyDefinition);
        }
示例#2
0
 /// <summary>
 /// Handles a selection change in the styles list, loading that style in the main form.
 /// </summary>
 private void StyleList_SelectedIndexChanged(object sender, System.EventArgs e)
 {
     this.DefinitionChanged?.Invoke(
         KeyboardDefinition.Load(this.SelectedCategory, this.SelectedDefinition),
         KeyboardStyle.Load(this.SelectedStyle.Name, this.SelectedStyle.Global),
         this.SelectedStyle.Global);
 }
        /// <summary>
        /// Handles the change of the location, sets the new location and invokes the changed event.
        /// </summary>
        private void txtSize_ValueChanged(VectorTextBox sender, TPoint newSize)
        {
            this.currentDefinition = this.currentDefinition.Resize(new Size(newSize.X, newSize.Y));

            // Only allow reasonable values to be set.
            if (newSize.X >= 25 && newSize.Y >= 25 && newSize.X <= 4096 && newSize.Y <= 4096)
            {
                this.DefinitionChanged?.Invoke(this.currentDefinition);
            }
        }
示例#4
0
        /// <summary>
        /// Handles the MouseDown event for the main form, which can start editing an element, the mouse is pointing
        /// at one.
        /// </summary>
        private void MainForm_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left)
            {
                return;
            }
            if (!this.mnuToggleEditMode.Checked || this.menuOpen)
            {
                return;
            }

            ElementDefinition toManipulate;

            if (this.selectedDefinition != null)
            {
                // Try to manipulate the selected definition, if one is selected.
                this.selectedDefinition.StartManipulating(e.Location, KeyboardState.AltDown, translateOnly: KeyboardState.CtrlDown);
                toManipulate = this.selectedDefinition;
            }
            else
            {
                // If none is selected, allow any key to become the element to manipulate.
                toManipulate = GlobalSettings.CurrentDefinition.Elements
                               .LastOrDefault(x => x.StartManipulating(e.Location, KeyboardState.AltDown, translateOnly: KeyboardState.CtrlDown));
            }

            if (toManipulate == null)
            {
                this.currentlyManipulating = null;
                this.selectedDefinition    = null;

                // Moving everything at once.
                if (KeyboardState.AltDown)
                {
                    this.movingEverythingStart = GlobalSettings.CurrentDefinition.Clone();
                    this.PushUndoHistory();
                    this.movingEverythingFrom = e.Location;
                }

                return;
            }

            var indexToManipulate = GlobalSettings.CurrentDefinition.Elements.IndexOf(toManipulate);

            this.currentlyManipulating = Tuple.Create(indexToManipulate, toManipulate);
            this.highlightedDefinition = null;
            this.manipulationStart     = toManipulate;
            this.cumulManipulation     = new Size();

            this.PushUndoHistory();
            GlobalSettings.CurrentDefinition = GlobalSettings.CurrentDefinition.RemoveElement(toManipulate);

            this.ResetBackBrushes();
        }
示例#5
0
        /// <summary>
        /// Handles a selection change in the definition list, re-populates the styles list for this definition.
        /// Loads the definition in the main form.
        /// </summary>
        private void DefinitionsList_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            var kbDef = KeyboardDefinition.Load(this.SelectedCategory, this.SelectedDefinition);

            this.LoadStyles();
            if (this.StyleList.Items.Count > 0)
            {
                this.StyleList.SelectedIndex = 0;
            }
            else
            {
                this.DefinitionChanged?.Invoke(kbDef, null, false);
            }
        }
示例#6
0
 /// <summary>
 /// Handles a selection change in the styles list, loading that style in the main form.
 /// </summary>
 private void StyleList_SelectedIndexChanged(object sender, System.EventArgs e)
 {
     try
     {
         this.DefinitionChanged?.Invoke(
             KeyboardDefinition.Load(this.SelectedCategory, this.SelectedDefinition),
             KeyboardStyle.Load(this.SelectedStyle.Name, this.SelectedStyle.Global),
             this.SelectedStyle.Global);
     }
     catch (Exception ex)
     {
         MessageBox.Show($"Failed to load keyboard {this.SelectedDefinition}: {ex.Message}");
         return;
     }
 }
示例#7
0
        /// <summary>
        /// Adds a mouse movement definition.
        /// </summary>
        /// <param name="id">The identifier of the key.</param>
        /// <param name="elements">The kb file elements describing the key.</param>
        /// <param name="definition">The keyboard definition to add the key to.</param>
        private static void AddMouseMovement(int id, string[] elements, KeyboardDefinition definition)
        {
            if (elements.Length < 5)
            {
                throw new LegacyFileParseException("A mouse speed indicator line should have at least 5 elements.");
            }

            // Parse the individual elements of the line.
            var posX   = ParseInt(elements[2], "X-Position");
            var posY   = ParseInt(elements[3], "Y-Position");
            var width  = ParseInt(elements[4], "Width");
            var center = new Point(posX + width / 2, posY + width / 2);

            definition.Elements.Add(new MouseSpeedIndicatorDefinition(id, center, width / 2));
        }
示例#8
0
        /// <summary>
        /// Checks if the key overlaps with any other keys of the same type and keycode. If so, it removes those
        /// keys from the keyboar definition and creates a new one that unifies them. Then the new unified
        /// key is added to the keyboard definition,
        /// </summary>
        /// <typeparam name="TKey">The key type to overlap.</typeparam>
        /// <param name="keyboard">The keyboard definition.</param>
        /// <param name="keyCode">The keycode of the key.</param>
        /// <param name="newKey">The key definition to add or overlap.</param>
        private static void AddOrOverlap <TKey>(KeyboardDefinition keyboard, int keyCode, TKey newKey)
            where TKey : KeyDefinition
        {
            var overlappingEqualKeys = keyboard.Elements.OfType <TKey>()
                                       // Legacy files don't support multiple keycodes per key.
                                       .Where(x => x.KeyCodes.Count == 1 && x.KeyCodes.Single() == keyCode)
                                       .Where(x => x.BordersWith(newKey))
                                       .ToList();

            foreach (var key in overlappingEqualKeys)
            {
                keyboard.Elements.Remove(key);
            }

            keyboard.Elements.Add(newKey.UnionWith(overlappingEqualKeys.ConvertAll <KeyDefinition>(x => x)));
        }
示例#9
0
        /// <summary>
        /// Handles a selection change in the definition list, re-populates the styles list for this definition.
        /// Loads the definition in the main form.
        /// </summary>
        private void DefinitionsList_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            try
            {
                var kbDef = KeyboardDefinition.Load(this.SelectedCategory, this.SelectedDefinition);

                this.LoadStyles();
                if (this.StyleList.Items.Count == 0)
                {
                    this.DefinitionChanged?.Invoke(kbDef, null, false);
                }
            } catch (Exception ex)
            {
                MessageBox.Show($"Failed to load keyboard {this.SelectedDefinition}: {ex.Message}");
                return;
            }
        }
示例#10
0
        /// <summary>
        /// Handles the loading of the form, all settings are read, hooks are created and the keyboard is initialized.
        /// </summary>
        private void MainForm_Load(object sender, EventArgs e)
        {
            // Load the settings
            if (!GlobalSettings.Load())
            {
                MessageBox.Show(
                    this,
                    $"Failed to load the settings: {GlobalSettings.Errors}",
                    "Failed to load settings");
            }

            this.Location = new Point(GlobalSettings.Settings.X, GlobalSettings.Settings.Y);
            var title = GlobalSettings.Settings.WindowTitle;

            this.Text = string.IsNullOrWhiteSpace(title) ? $"NohBoard {Version.Get}" : title;

            this.GetLatestVersion().Start();

            // Load a definition if possible.
            if (GlobalSettings.Settings.LoadedKeyboard != null && GlobalSettings.Settings.LoadedCategory != null)
            {
                try
                {
                    GlobalSettings.Settings.UpdateDefinition(KeyboardDefinition
                                                             .Load(GlobalSettings.Settings.LoadedCategory, GlobalSettings.Settings.LoadedKeyboard), false);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(
                        "There was an error loading the saved keyboard definition file:" +
                        $"{Environment.NewLine}{ex.Message}");
                    GlobalSettings.Settings.LoadedCategory = null;
                    GlobalSettings.Settings.LoadedKeyboard = null;
                }
            }

            // Load a style if possible.
            if (GlobalSettings.CurrentDefinition != null && GlobalSettings.Settings.LoadedStyle != null)
            {
                try
                {
                    GlobalSettings.Settings.UpdateStyle(KeyboardStyle.Load(
                                                            GlobalSettings.Settings.LoadedStyle,
                                                            GlobalSettings.Settings.LoadedGlobalStyle), false);
                    this.LoadKeyboard();
                    this.ResetBackBrushes();
                }
                catch
                {
                    GlobalSettings.Settings.LoadedStyle = null;
                    MessageBox.Show(
                        $"Failed to load style {GlobalSettings.Settings.LoadedStyle}, loading default style.",
                        "Error loading style.");
                }

                // Enable the mouse hook only if there are mouse keys on the screen.
                if (GlobalSettings.CurrentDefinition.Elements.Any(x => !(x is KeyboardKeyDefinition)))
                {
                    HookManager.EnableMouseHook();
                }

                // Enable the keyboard hook only if there are keyboard keys on the screen.
                if (GlobalSettings.CurrentDefinition.Elements.Any(x => x is KeyboardKeyDefinition))
                {
                    HookManager.EnableKeyboardHook();
                }
            }

            this.UpdateTimer.Interval  = GlobalSettings.Settings.UpdateInterval;
            this.UpdateTimer.Enabled   = true;
            this.KeyCheckTimer.Enabled = true;

            this.Activate();
            this.ApplySettings();
        }
示例#11
0
        /// <summary>
        /// Handles the loading of the form, all settings are read, hooks are created and the keyboard is initialized.
        /// </summary>
        private void MainForm_Load(object sender, EventArgs e)
        {
            // Load the settings
            if (!GlobalSettings.Load())
            {
                MessageBox.Show(
                    this,
                    $"Failed to load the settings: {GlobalSettings.Errors}",
                    "Failed to load settings");
            }

            this.Location = new Point(GlobalSettings.Settings.X, GlobalSettings.Settings.Y);
            this.Text     = $"NohBoard {Version.Get}";

            this.GetLatestVersion().Start();

            // Load a definition if possible.
            if (GlobalSettings.Settings.LoadedKeyboard != null && GlobalSettings.Settings.LoadedCategory != null)
            {
                try
                {
                    GlobalSettings.CurrentDefinition = KeyboardDefinition
                                                       .Load(GlobalSettings.Settings.LoadedCategory, GlobalSettings.Settings.LoadedKeyboard);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(
                        "There was an error loading the saved keyboard definition file:" +
                        $"{Environment.NewLine}{ex.Message}");
                    GlobalSettings.Settings.LoadedCategory = null;
                    GlobalSettings.Settings.LoadedKeyboard = null;
                }
            }

            // Load a style if possible.
            if (GlobalSettings.CurrentDefinition != null && GlobalSettings.Settings.LoadedStyle != null)
            {
                try
                {
                    GlobalSettings.CurrentStyle = KeyboardStyle.Load(
                        GlobalSettings.Settings.LoadedStyle,
                        GlobalSettings.Settings.LoadedGlobalStyle);
                    this.ResetBackBrushes();
                }
                catch
                {
                    GlobalSettings.Settings.LoadedStyle = null;
                    MessageBox.Show(
                        $"Failed to load style {GlobalSettings.Settings.LoadedStyle}, loading default style.",
                        "Error loading style.");
                }
            }

            HookManager.EnableMouseHook();
            HookManager.EnableKeyboardHook();

            this.UpdateTimer.Enabled   = true;
            this.KeyCheckTimer.Enabled = true;

            this.Activate();
            this.ApplySettings();
        }
示例#12
0
        /// <summary>
        /// Parses an old keyboard file.
        /// </summary>
        /// <param name="fileName">The filename of the legacy keyboard file.</param>
        /// <returns>The parsed keyboard definition.</returns>
        public static KeyboardDefinition Parse(string fileName)
        {
            var file = new FileInfo(fileName);

            if (!file.Exists)
            {
                throw new LegacyFileParseException($"{fileName} does not exist.");
            }

            if (file.Extension != ".kb")
            {
                throw new LegacyFileParseException($"{fileName} does not have the '.kb' extension.");
            }

            var definition = new KeyboardDefinition
            {
                Name     = file.Name.Substring(0, file.Name.Length - file.Extension.Length),
                Version  = Constants.KeyboardVersion,
                Elements = new List <ElementDefinition>()
            };

            var    reader    = new StreamReader(fileName);
            var    index     = 0;
            var    elementId = 0;
            string line;

            while ((line = reader.ReadLine()) != null)
            {
                var elements = line.Split(' ');
                index++;

                try
                {
                    switch (elements[0])
                    {
                    case "key":
                        var keyInfo = LegacyKeyCodeMapping.Map(int.Parse(elements[1]));
                        switch (keyInfo.Item1)
                        {
                        case KeyType.Keyboard:
                            AddKeyboardKey(elementId++, elements, definition, keyInfo.Item2);
                            break;

                        case KeyType.Mouse:
                            AddMouseKey(elementId++, elements, definition, keyInfo.Item2);
                            break;

                        case KeyType.MouseScroll:
                            AddMouseScroll(elementId++, elements, definition, keyInfo.Item2);
                            break;

                        case KeyType.MouseMovement:
                            AddMouseMovement(elementId++, elements, definition);
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                        break;

                    case "width":
                        if (elements.Length < 2)
                        {
                            throw new LegacyFileParseException(
                                      "A keyboard property line should have at least 2 elements.");
                        }

                        definition.Width = ParseInt(elements[1], "Width");
                        break;

                    case "height":
                        if (elements.Length < 2)
                        {
                            throw new LegacyFileParseException(
                                      "A keyboard property line should have at least 2 elements.");
                        }

                        definition.Height = ParseInt(elements[1], "Height");
                        break;

                    case "category":
                        if (elements.Length < 2)
                        {
                            throw new LegacyFileParseException(
                                      "A keyboard property line should have at least 2 elements.");
                        }

                        definition.Category = elements[1];
                        break;
                    }
                }
                catch (Exception ex)
                {
                    throw new LegacyFileParseException($"Unable to parse key file line {index}: '{line}'", ex);
                }
            }

            // Fix the size of the keyboard and the position of the keys. Use the standard of 9 pixels on all edges.
            var bb = definition.GetBoundingBox();

            definition.Elements = definition.Elements.Select(x => x.Translate(9 - bb.Left, 9 - bb.Top)).ToList();
            var bb2 = definition.GetBoundingBox();

            definition.Width  = bb2.Right + 9;
            definition.Height = bb2.Bottom + 9;

            return(definition);
        }
示例#13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="KeyboardPropertiesForm" /> class.
 /// </summary>
 public KeyboardPropertiesForm(KeyboardDefinition initialDefinition)
 {
     this.initialDefinition = initialDefinition ?? throw new ArgumentNullException(nameof(initialDefinition));
     this.currentDefinition = this.initialDefinition.Clone();
     this.InitializeComponent();
 }