/// <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);
        }
        /// <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;
                    }
                }
            }
        }