コンテキストメニューをインターフェースに合わせて切り替え表示

MyDummySQLProに、ショートカットメニューをつけてみました。

主に、テキストボックスに入っているスクリプトをテンプレートに保存するためのメニュー項目をつけたかったからです。

AccessSavableTextBoxは継承させたかったので、またまたインターフェースでクラス(オブジェクト)を識別認識させています。


IHasCategorizedTextAndContextMenuインターフェースを実装したテキストボックス:TextBoxForTemplate

namespace MyDummySQL.ControlsForTemplate
{
    public class TextBoxForTemplate : AccessSavableTextBox, IHasCategorizedTextAndContextMenu
    {
        private string categoryName = "dummy";
        public string CategoryName {
            get
            {
                if (this.Parent != null && "dummy".Equals(this.categoryName))
                {
                    return this.Parent.Text;
                }
                return this.categoryName;
            }
            set
            {
                this.categoryName = value;
            }
        }

        public TextBoxForTemplate()
            : base()
        {
            this.ContextMenuStrip = (new ContextMenuBuilderFactory()).Create(this).Build();
        }
        public TextBoxForTemplate(string categoryName) : base()
        {
            this.categoryName = categoryName;
            this.ContextMenuStrip = (new ContextMenuBuilderFactory()).Create(this).Build();
        }


    }
}

今回インターフェイスは2種あります。

一つ目、ふつうの「コピー」「切り取り」「貼り付け」しかないコンテキストメニューを表示させるテキストボックス用:IHasTextAndContextMenu

namespace MyDummySQL.ControlsForTemplate
{
    public interface IHasTextAndContextMenu
    {
        string Text { get; set; }
        string SelectedText { get; set; }
        //System.Windows.Forms.ContextMenuStrip ContextMenuStrip { get; set; }
    }
}

二つ目、一つ目のメニューに加えて「テンプレートに保存」「テンプレートから取得」のメニュー項目も表示するテキストボックス用:

namespace MyDummySQL.ControlsForTemplate
{
    public interface IHasCategorizedTextAndContextMenu : IHasTextAndContextMenu
    {
        string CategoryName { get; set; }
    }
}

次に、メニューを作成するクラスを、インターフェースで切り替え生成するファクトリ:ContextMenuBuilderFactory

namespace MyDummySQL.ControlsForTemplate
{
    public class ContextMenuBuilderFactory
    {
        public ContextMenuBuilderFactory() { }

        public ContextMenuBuilder Create(IHasTextAndContextMenu control)
        {
            return new ContextMenuBuilder(control);
        }

        public ContextMenuBuilder Create(IHasCategorizedTextAndContextMenu control)
        {
            return new ContextMenuBuilderWidthCategory(control);
        }
    }
}

次に実際に普通のメニューを作成する”自称ビルダー”(注:ビルダーパターンではないです):ContextMenuBuilder

namespace MyDummySQL.ControlsForTemplate
{
    public class ContextMenuBuilder
    {
        //ContextMenu 
        protected ContextMenuStrip cMenu = new ContextMenuStrip();

        protected IHasTextAndContextMenu HasText = null;

        public ContextMenuBuilder(IHasTextAndContextMenu control)
        {
            this.HasText = control;
        }

        virtual public ContextMenuStrip Build()
        {
            //this.HasText = control;
            /*
            this.BuildCopy();
            this.BuildCut();
            this.BuildPaste();
             */
            this.BuildBasicMenu();
            return this.cMenu;
        }

        private void BuildBasicMenu()
        {
            this.BuildCopy();
            this.BuildCut();
            this.BuildPaste();
        }

        virtual protected void BuildCopy()
        {
            //Copy
            ToolStripMenuItem mCopy = new ToolStripMenuItem();
            mCopy.Text = "コピー(&C)";
            mCopy.Click += delegate
            {
                if (!string.IsNullOrEmpty(this.HasText.SelectedText))
                {
                    Clipboard.SetText(this.HasText.SelectedText);
                }
                else if (!string.IsNullOrEmpty(this.HasText.Text))
                {
                    Clipboard.SetText(this.HasText.Text);
                }
            };
            this.cMenu.Items.Add(mCopy);
        }

        virtual protected void BuildCut()
        {
            //Cut
            ToolStripMenuItem mCut = new ToolStripMenuItem();
            mCut.Text = "切り取り(&X)";
            mCut.Click += delegate
            {
                if (!string.IsNullOrEmpty(this.HasText.SelectedText))
                {
                    Clipboard.SetText(this.HasText.SelectedText);
                    this.HasText.SelectedText = "";
                }
                else if (!string.IsNullOrEmpty(this.HasText.Text))
                {
                    Clipboard.SetText(this.HasText.Text);
                    this.HasText.Text = "";
                }
            };
            this.cMenu.Items.Add(mCut);
        }

        virtual protected void BuildPaste()
        {
            //Paste
            ToolStripMenuItem mPaste = new ToolStripMenuItem();
            mPaste.Text = "貼り付け(&V)";
            mPaste.Click += delegate
            {
                if (!string.IsNullOrEmpty(this.HasText.SelectedText))
                {
                    this.HasText.SelectedText = Clipboard.GetText();
                }
                else
                {
                    this.HasText.Text = Clipboard.GetText();
                }
            };
            cMenu.Items.Add(mPaste);
        }

    }
}

さらに上のクラスを継承して、「テンプレートに保存」「テンプレートから取得」メニューを追加する”自称ビルダー”:ContextMenuBuilder
(ただし、テンプレート保存・取得の実装プログラムはまだ作っていませんので、仮です)

namespace MyDummySQL.ControlsForTemplate
{
    public class ContextMenuBuilderWidthCategory : ContextMenuBuilder
    {
        //private IHasCategorizedTextAndContextMenu HasCategorizedText = null;

        public ContextMenuBuilderWidthCategory(IHasCategorizedTextAndContextMenu control)
            : base(control)
        {
            this.HasText = control;
        }

        public override ContextMenuStrip Build()
        {
            this.cMenu = base.Build();
            BuildAddToTemplate();
            BuildGetFromTemplate();

            return this.cMenu;
        }

        virtual public void BuildAddToTemplate()
        {
            //Copy
            ToolStripMenuItem mToTemp = new ToolStripMenuItem();
            mToTemp.Text = "テンプレートに保存(&T)";
            mToTemp.Click += delegate
            {
                string template = string.Empty;
                string category = string.Empty;

                if (!string.IsNullOrEmpty(this.HasText.SelectedText))
                {
                    template = this.HasText.SelectedText;
                }
                else if (!string.IsNullOrEmpty(this.HasText.Text))
                {
                    template = this.HasText.Text;
                }

                IHasCategorizedTextAndContextMenu obj = this.HasText as IHasCategorizedTextAndContextMenu;
                if (obj != null)
                {
                    category = obj.CategoryName;
                }

                frmAddTemplates addFrm = new frmAddTemplates(category, template);
                addFrm.Show();

            };
            this.cMenu.Items.Add(mToTemp);
        }
        virtual public void BuildGetFromTemplate()
        {
            //Copy
            ToolStripMenuItem mFromTemp = new ToolStripMenuItem();
            mFromTemp.Text = "テンプレートから取得(&G)";
            mFromTemp.Click += delegate
            {
                string template = string.Empty;
                string category = string.Empty;

                if (!string.IsNullOrEmpty(this.HasText.SelectedText))
                {
                    template = this.HasText.SelectedText;
                }
                else if (!string.IsNullOrEmpty(this.HasText.Text))
                {
                    template = this.HasText.Text;
                }

                IHasCategorizedTextAndContextMenu obj = this.HasText as IHasCategorizedTextAndContextMenu;
                if (obj != null)
                {
                    category = obj.CategoryName;
                }

                frmTemplates frmTemp = new frmTemplates();
                frmTemp.Show();

            };
            this.cMenu.Items.Add(mFromTemp);
        }

    }
}

テンプレート関連を扱うフォームは以下のような感じです。

・・・つ、疲れた。また来週〜。