/// <summary>
        /// Handles a key press and performs the appropriate action.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="unicodeKey">The Unicode key.</param>
        /// <param name="modifier">The modifier.</param>
        public bool HandleKeyPress(
            Key key,
            ModifierType modifier,
            uint unicodeKey)
        {
            // Normalize the key code and remove excessive modifiers.
            ModifierType filteredModifiers = modifier
                                             & (ModifierType.ShiftMask | ModifierType.Mod1Mask | ModifierType.ControlMask
                                                | ModifierType.MetaMask | ModifierType.SuperMask);
            int keyCode = GdkUtility.GetNormalizedKeyCode(key, filteredModifiers);

            // Check to see if we have an action for this.
            ModifierType isNormalOrShifted = filteredModifiers & ~ModifierType.ShiftMask;
            bool         isCharacter       = unicodeKey != 0 && isNormalOrShifted == ModifierType.None;
            bool         isAction          = keyBindings.ContainsKey(keyCode);

            if (isAction || isCharacter)
            {
                // Keep track of the original selection.
                TextRange previousSelection = displayContext.Caret.Selection;

                // Mark that we are starting a new action and fire events so
                // other listeners and handle it.
                InAction = true;

                // Perform the appropriate action.
                try
                {
                    if (isAction)
                    {
                        keyBindings[keyCode].Perform(this);
                    }
                    else
                    {
                        TextActions.InsertText(this, (char)unicodeKey);
                    }
                }
                finally
                {
                    InAction = false;
                }

                // Check to see if the selection changed.
                if (previousSelection != displayContext.Caret.Selection)
                {
                    displayContext.Renderer.UpdateSelection(displayContext, previousSelection);
                }

                // We did something, so return processed.
                return(true);
            }

            // No idea what to do, so don't do anything.
            return(false);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Called when a key is pressed.
        /// </summary>
        /// <param name="eventKey">The event key.</param>
        /// <returns></returns>
        protected override bool OnKeyPressEvent(EventKey eventKey)
        {
            // If we don't have a line buffer, don't do anything.
            if (LineBuffer == null)
            {
                return(false);
            }

            // Decompose the key into its components.
            ModifierType modifier;
            Key          key;

            GdkUtility.DecomposeKeys(eventKey, out key, out modifier);

            // Get the unicode character for this key.
            uint unicodeChar = Keyval.ToUnicode(eventKey.KeyValue);

            // Pass it on to the controller.
            return(controller.HandleKeyPress(key, modifier, unicodeChar));
        }
        /// <summary>
        /// Called when the <see cref="ActionManager"/> gets a key press and it passes
        /// it on to the current keybindings.
        /// </summary>
        /// <param name="e">The <see cref="Gtk.KeyPressEventArgs"/> instance
        /// containing the event data.</param>
        public void KeyPressed(KeyPressEventArgs e)
        {
            // Decompose the key into its components.
            ModifierType modifier;
            Key          key;

            GdkUtility.DecomposeKeys(e.Event, out key, out modifier);

            // Get the normalized string accelerator which we use for lookups.
            bool   isPartialAccelerator;
            string accelerator = GdkUtility.ToAcceleratorString(
                key, modifier, out isPartialAccelerator);

            if (isPartialAccelerator)
            {
                // If we are partial, just ignore it.
                return;
            }

            // Build a path with the current accelerator and the new one.
            var acceleratorPath = new HierarchicalPath(accelerator, currentAccelerator);

            // See if we have an accelerator for this path.
            if (!keybindings.Contains(acceleratorPath))
            {
                // Reset the current accelerator key.
                currentAccelerator = HierarchicalPath.AbsoluteRoot;

                // We couldn't find it so return false.
                e.RetVal = false;
                return;
            }

            // Grab the accelerator for this key. If we don't have an item, then
            // this is going to be a continued chain.
            string actionName = keybindings.Get(acceleratorPath);

            if (actionName == null)
            {
                // We are only the first part of an action chain.
                currentAccelerator = acceleratorPath;
                e.RetVal           = true;

                // TODO Fire an event to say incomplete accelerator.
                return;
            }

            // We have found a terminal action, so get the action involved.
            Action action = ActionManager.GetAction(actionName);

            if (action != null)
            {
                action.Activate();
                e.RetVal = true;
            }

            // Add it to the errors.
            ActionManager.Messages.Add(
                new SeverityMessage(
                    Severity.Error,
                    string.Format(
                        "Could not find action {0} to apply keybinding {1}.",
                        actionName,
                        acceleratorPath)));

            // We couldn't find the action so we did nothing.
            e.RetVal = false;
        }
        /// <summary>
        /// Binds the actions from the various classes inside the assembly.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        public void BindActions(Assembly assembly)
        {
            // Make sure we have sane data.
            if (assembly == null)
            {
                throw new ArgumentNullException("assembly");
            }

            // Go through the command factories in this assembly.
            foreach (Type type in assembly.GetTypes())
            {
                // If we can't create it, we don't do anything.
                if (type.IsAbstract)
                {
                    continue;
                }

                // If we are the proper type, create a new one and register it.
                if (typeof(ICommandFactory <OperationContext>).IsAssignableFrom(type))
                {
                    // Create a new instance.
                    var commandFactory =
                        (ICommandFactory <OperationContext>)Activator.CreateInstance(type);
                    CommandFactory.Register(commandFactory);
                }
            }

            // Go through the types in the assembly.
            foreach (Type type in assembly.GetTypes())
            {
                // Check to see if the type contains our attribute.
                bool isFixture = type.HasCustomAttribute <ActionFixtureAttribute>();

                if (!isFixture)
                {
                    continue;
                }

                // Go through all the methods inside the type and make sure they
                // have the action attribute.
                foreach (MethodInfo method in type.GetMethods())
                {
                    // Check to see if this method has the action attribute.
                    bool isAction = method.HasCustomAttribute <ActionAttribute>();

                    if (!isAction)
                    {
                        continue;
                    }

                    // Create an action entry for this element.
                    var action =
                        (Action <EditorViewController>)
                        Delegate.CreateDelegate(typeof(Action <EditorViewController>), method);
                    var entry = new ActionEntry(method.Name, action);

                    actions[method.Name] = entry;

                    // Pull out the state objects and add them into the entry.
                    object[] actionStates =
                        method.GetCustomAttributes(typeof(ActionStateAttribute), false);

                    foreach (ActionStateAttribute actionState in actionStates)
                    {
                        entry.StateTypes.Add(actionState.StateType);
                    }

                    // Pull out the key bindings and assign them.
                    object[] bindings = method.GetCustomAttributes(
                        typeof(KeyBindingAttribute), false);

                    foreach (KeyBindingAttribute keyBinding in bindings)
                    {
                        // Get the keys and modifiers.
                        int keyCode = GdkUtility.GetNormalizedKeyCode(
                            keyBinding.Key, keyBinding.Modifier);

                        // Add the key to the dictionary.
                        keyBindings[keyCode] = entry;
                    }
                }
            }
        }