using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;


// Bitte beachten Sie auch den Fortsetzungsband zu diesem Buch, falls
// Ihnen das Programmieren Spaß gemacht hat und Sie sich fortgeschritteneren 
// Themen zuwenden wollen. Alle Informationen zum Fortsetzungsband finden
// Sie auf der Website: www.tiefer-einsteigen.de 


namespace FilterTextBox
{

    /// <summary>
    /// Definiert die verschiedenen Filtermodi, die vom Steuerelement
    /// FilterTextBox unterstützt werden
    /// </summary>
    public enum FilterMode
    {
        None,                   // kein Filter, verhält sich wie TextBox
        NumericBinary,          // nur 0 und 1 erlaubt
        NumericDecimal,         // nur 0 bis 9 erlaubt
        NumericHexadecimal,     // nur 0 bis 9, und A-F erlaubt
        LettersOnly,            // nur A-Z erlaubt
        CustomFilter            // benutzerdefinierten Filter verwenden
    }


    public class FilterTextBox : TextBox
    {

        /// <summary>
        /// Legt den gewünschten Filtermodus fest oder ruft diesen ab.
        /// </summary>
        [CategoryAttribute("Default")]
        [Description("Legt den gewünschten Filtermodus fest oder ruft diesen ab.")]
        public FilterMode FilterMode { get; set; }

        /// <summary>
        /// Legt fest, ob für eine nicht erlaubte Taste ein Signalton ausgegeben wird.
        /// </summary>
        [CategoryAttribute("Default")]
        [Description("Legt fest, ob für eine nicht erlaubte Taste ein Signalton ausgegeben wird.")]
        public bool BeepOnError { get; set; }

        /// <summary>
        /// Legt einen benutzerdefinierten Filter fest oder ruft diesen ab.
        /// </summary>
        [CategoryAttribute("Default")]
        [Description("Legt einen benutzerdefinierten Filter fest oder ruft diesen ab.")]
        public string AllowedCustom { get; set; }


        // erlaubte Zeichen im Modus NumericBinary
        private string allowedBinary = "01";

        // erlaubte Zeichen im Modus NumericBinary
        private string allowedHexadedimal = "0123456789abcdefABCDEF";


        /// <summary>
        /// Erstellt ein neues Steuerelement des Typs FilterTextBox
        /// </summary>
        public FilterTextBox()
        {
            // Standardwerte festlegen
            this.BeepOnError = false;
            this.FilterMode = FilterMode.LettersOnly;

            base.KeyPress += new KeyPressEventHandler(FilterTextBox_KeyPress);
        }

        private void FilterTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (this.FilterMode == FilterMode.None)
            {
                e.Handled = false;
                return;
            }

            if (this.isCharAllowed(e.KeyChar) == false)
            {
                e.Handled = true;
                if (this.BeepOnError)
                    System.Console.Beep();
            }
            else
            {
                e.Handled = false;
            }
        }

        private bool isCharAllowed(char p)
        {
            if (char.IsControl(p))
                return true;

            switch (this.FilterMode)
            {
                case FilterMode.NumericBinary:
                    if (this.allowedBinary.IndexOf(p) != -1)
                        return true;
                    else
                        return false;

                case FilterMode.NumericHexadecimal:
                    if (this.allowedHexadedimal.IndexOf(p) != -1)
                        return true;
                    else
                        return false;

                case FilterMode.CustomFilter:
                    if (this.AllowedCustom == null)
                        return false;

                    if (this.AllowedCustom.IndexOf(p) != -1)
                        return true;
                    else
                        return false;

                case FilterMode.NumericDecimal:
                    if (char.IsDigit(p))
                        return true;
                    else
                        return false;

                case FilterMode.LettersOnly:
                    if (char.IsLetter(p))
                        return true;
                    else
                        return false;

                default:
                    return false;
            }
        }




    }
}
