GUI - Menu

sharpnote-menu

Tak jak napisałem w tym poście, zacząłem pracować nad pierwszą aplikacją pakietu, SharpNote’em. Nie bardzo wiem, z której strony ten wielki program ugryźć, więc zacząłem od czegoś prostego - Menu.

Xwt udostępnia dwie klasy do budowania menu: Menu i MenuItem. Struktura jest bardzo prosta – Menu ma kolekcję Items, do której dodajemy kolejne MenuItem. Każdy MenuItem ma etykietę, event Clicked oraz możliwość dodania podmenu. Do tego dochodzą dodatkowe opcje, jak czcionka, checkboxy itp.

Więc jak takie menu tworzymy?

var menuFile = new MenuItem("_File");
var submenuFile = new Menu();

var submenuFileNew = new MenuItem("_New");
var subsubmenuFileNew = new Menu();
var subsubmenuFileNewSource = new MenuItem("_Source file");
var subsubmenuFileNewNote = new MenuItem("_Note");
subsubmenuFileNew.Items.Add(subsubmenuFileNewSource);
subsubmenuFileNew.Items.Add(subsubmenuFileNewNote);
submenuFileNew.SubMenu = subsubmenuFileNew;
(...)
submenuFile.Items.Add(submenuFileNew);
(...)
menuFile.SubMenu = submenuFile;

Żeby mieć możliwość dodawania akcji do poszczególnych MenuItem lub zmieniania ich jakoś, musimy utworzyć każdy osobno, jako kolejne zmienne aby mieć dostęp do ich własności. Dużo kodu.

Więc stwierdziłem, że będę sprytniejszy, i utworzyłem klasę MenuHelper w projekcie SharpOffice.Window, która wygląda tak:

public static class MenuHelper
{
    public static MenuItem CreateMenuItem(string label, EventHandler command = null,
                                          MenuItem[] subMenu = null)
    {
        var menuItem = new MenuItem(label);
        if (command != null)
            menuItem.Clicked += command;
        else if (subMenu != null)
            menuItem.SubMenu = CreateMenu(subMenu);
        return menuItem;
    }

    public static Menu CreateMenu(MenuItem[] subMenu)
    {
        var menu = new Menu();
        foreach (var menuItem in subMenu)
            menu.Items.Add(menuItem);
        return menu;
    }
}

Na razie ograniczyłem możliwości do dodawania eventu lub dodawania podmenu. Za to mam wymierne korzyści z używania tak zrobionego helpera. Po pierwsze mój kod jest czytelniejszy, a po drugie krótszy o niecałe 40%.

var menuFile = MenuHelper.CreateMenuItem("_File", subMenu: new[]
{
  MenuHelper.CreateMenuItem("_New", subMenu: new[]
  {
     MenuHelper.CreateMenuItem("_Source file", command: null),
     MenuHelper.CreateMenuItem("_Note", command: null)
  }),
  MenuHelper.CreateMenuItem("_Open", command: null),
  MenuHelper.CreateMenuItem("E_xit", command: (sender, args) => this.Close())
});