# MenuBar (Vala)

Tiffany Antopolski
tiffany.antopolski@gmail.com 2012
Widget, který sdružuje widgety GtkMenuItem.

# MenuBar

MenuBar vytvořený pomocí XML a GtkBuilder.

# Vytvoření MenuBar pomocí XML

Abyste vytvořili nabídkovou lištu pomocí XML:

Pomocí svého oblíbeného textového editoru vytvořte menubar.ui.

Na začátek souboru vložte následující řádek:

<?xml version="1.0"? encoding="UTF-8"?>

Chceme vytvořit rozhraní, které bude obsahovat naši nabídkovou lištu a její podnabídky. Naše nabídková lišta bude obsahovat podnabídky Soubor, Upravit, Volby a Nápověda. Do souboru přidáme následující kód XML:

<?xml version="1.0" encoding="UTF-8"?> <interface> <menu id="menubar"> <submenu> <attribute name="label">File</attribute> </submenu> <submenu> <attribute name="label">Edit</attribute> </submenu> <submenu> <attribute name="label">Choices</attribute> </submenu> <submenu> <attribute name="label">Help</attribute> </submenu> </menu> </interface>

Nyní vytvoříme soubor .vala a použijeme GtkBuilder k importu souboru menubar.ui, který jsem před chvílí vytvořili.

# Přidání MenuBar do okna pomocí GtkBuilder

public class MyWindow : Gtk.ApplicationWindow { internal MyWindow (MyApplication app) { Object (application: app, title: "MenuBar Example"); this.set_default_size (200, 200); } }

class MyApplication: Gtk.Application { protected override void activate () { new MyWindow (this).show (); } protected override void startup () { base.startup ();

/* Nastaví nabídkovou lištu. */ /* Získá soubor UI. */ var builder = new Gtk.Builder (); try { builder.add_from_file ("menubar_basis.ui"); /* Obsloužení výjimky. */ } catch (Error e) { error ("Unable to load file: %s", e.message); }

/* Získá nabídkovou lištu z objektu builder. */ this.menubar = builder.get_object ("menubar") as MenuModel; } }

/* main vytvoří a spustí aplikaci. */ public int main (string[] args) { return new MyApplication ().run (args); }

Nyní soubor .vala zkompilujte a spusťte. Aplikace by měla vypadat podobně, jako na obrázku na začátku této stránky.

# Přidání položek do nabídky

Začneme přidáním dvou položek nabídky do nabídky File: New a Quit. Provedeme to přidáním `oddílu` s těmito položkami do podnabídky `File`. Soubor menubar.ui by měl vypadat jako tento (řádky 6 až 13 včetně obsahují nově přidaný oddíl):

<?xml version="1.0" encoding="UTF-8"?> <interface> <menu id="menubar"> <submenu> <attribute name="label">File</attribute> <section> <item> <attribute name="label">New</attribute> </item> <item> <attribute name ="label">Quit</attribute> </item> </section> </submenu> <submenu> <attribute name="label">Edit</attribute> </submenu> <submenu> <attribute name="label">Choices</attribute> </submenu> <submenu> <attribute name="label">Help</attribute> </submenu> </menu> </interface>

Podle tohoto vzoru nyní můžete přidat položky Copy a Paste do podnabídky Edit a položku About do podnabídky Help. Zatím se vyhneme přidání položek do podnabídky Choices, tomu se budeme věnovat později v této lekci.

Když provedete změny v souboru s uživatelským rozhraním, nemusíte znovu kompilovat program. Stačí již dříve zkompilovaná aplikace a změny v uživatelském rozhraní se projeví.

# Nastavení akcí

Jde o postup se třemi kroky.

Nejprve vytvoříme pole `ActionEntry` ve třídě `MyApplication`. To se bude skládat z:

názvu akce `"action name"` (povinné)

funkce zpětného volání napojené na signál `"activate"` akce (pokud to je použitelné)

typu parametru, který musí být předán aktivační funkci pro akci (pokud je to použitelné)

počáteční stav této akce (pokud je to použitelné)

zpětné volání napojené na signál `"change-state"` (pokud je to použitelné)

const ActionEntry[] actions = { { "new", new_cb }, // {"action name", callback_function} { "quit", quit_cb } };

Zadruhé vytvoříme funkce zpětného volání, na které jsou akce napojené.

void new_cb (SimpleAction action, Variant? parameter) { print ("You clicked \"New\"\n"); //new MyWindow (this).show (); }

void quit_cb (SimpleAction action, Variant? parameter) { print ("You clicked \"Quit\"\n"); this.quit (); }

A nakonec v souboru XML napojíme položku nabídky na akci přidáním atributu `"action"`:

<item> <attribute name="label">New</attribute> <attribute name="action">app.new</attribute> </item> <item> <attribute name="label">Quit</attribute> <attribute name="action">app.quit</attribute> </item>

# Podnabídka „Choices“ a položky se stavem

Řádky 30 až 80 včetně v předvádí kód XML použitý k vytvoření uživatelského rozhraní nabídky Choices.

# Akce: Aplikace nebo okno?

Výše jsme vytvořili akce `"new"` a `"open"` jako součást třídy `MyApplication`. Akce, které ovládají přímo aplikaci, jako je `"quit"` by se vytvořily podobně.

Některé akce, jako je `"copy"` (kopírovat) nebo `"paste"` (vložit) se vztahují k oknu a ne k aplikaci. Akce okna by měly být vytvářeny jako součást třídy okna.

Soubor s celým příkladem obsahuje jak akce aplikace, tak akce okna. Akce okna jsu obvykle zároveň i součástí aplikační nabídky. Není dobrým zvykem vkládat akce okna do aplikační nabídky. Pro předváděcí účely zahrnuje soubor s celým příkladem, který následuje, kód XML v souboru .ui, který vytvoří aplikační nabídku včetně položek `"New"` a `"Open"` a ty jsou zavěšeny na stejnou akci, jako položky nabídkové lišty se stejným názvem.

# Celý soubor s uživatelským rozhraním ve formátu XML pro tento příklad

<?xml version="1.0" encoding="UTF-8"?> <interface> <menu id="menubar"> <submenu> <attribute name="label">File</attribute> <section> <item> <attribute name="label">New</attribute> <attribute name="action">app.new</attribute> </item> <item> <attribute name="label">Quit</attribute> <attribute name="action">app.quit</attribute> </item> </section> </submenu> <submenu> <attribute name="label">Edit</attribute> <section> <item> <attribute name="label">Copy</attribute> <attribute name="action">win.copy</attribute> </item> <item> <attribute name="label">Paste</attribute> <attribute name="action">win.paste</attribute> </item> </section> </submenu> <submenu> <attribute name="label">Choices</attribute> <submenu> <attribute name="label">Shapes</attribute> <section> <item> <attribute name="label">Line</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">line</attribute> </item> <item> <attribute name="label">Triangle</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">triangle</attribute> </item> <item> <attribute name="label">Square</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">square</attribute> </item> <item> <attribute name="label">Polygon</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">polygon</attribute> </item> <item> <attribute name="label">Circle</attribute> <attribute name="action">win.shape</attribute> <attribute name="target">circle</attribute> </item> </section> </submenu> <section> <item> <attribute name="label">On</attribute> <attribute name="action">app.state</attribute> <attribute name="target">on</attribute> </item> <item> <attribute name="label">Off</attribute> <attribute name="action">app.state</attribute> <attribute name="target">off</attribute> </item> </section> <section> <item> <attribute name="label">Awesome</attribute> <attribute name="action">app.awesome</attribute> </item> </section> </submenu> <submenu> <attribute name="label">Help</attribute> <section> <item> <attribute name="label">About</attribute> <attribute name="action">win.about</attribute> </item> </section> </submenu> </menu> <menu id="appmenu"> <section> <item> <attribute name="label">New</attribute> <attribute name="action">app.new</attribute> </item> <item> <attribute name="label">Quit</attribute> <attribute name="action">app.quit</attribute> </item> </section> </menu> </interface>

# Kompletní soubor v jazyce Vala pro tento příklad

public class MyWindow : Gtk.ApplicationWindow {

/* Funkce zpětného volání pro akce okna */ void copy_cb (SimpleAction action, Variant? parameter) { print ("\"Copy\" activated\n"); }

void paste_cb (SimpleAction action, Variant? parameter) { print ("\"Paste\" activated\n"); }

void shape_cb (SimpleAction action, Variant? parameter) { print ("shape is set to %s\n", parameter.get_string(null)); action.set_state (parameter); }

/* Vytvoří akce okna */ const ActionEntry[] actions = { /*{ "název akce", zpětné volání pro přípojení signálu "activate", typ parametru, počáteční stav, zpětné volání pro připojení signálu "change-state" } */ { "copy", copy_cb }, { "paste", paste_cb }, { "shape", shape_cb, "s", "'line'"} };

internal MyWindow (MyApplication app) { Object (application: app, title: "MenuBar Example"); this.set_default_size (200, 200);

/* Nastaví akce oknu */ this.add_action_entries (actions, this); } }

class MyApplication: Gtk.Application { protected override void activate () { new MyWindow (this).show (); }

/* Funkce zpětného volání pro akce aplikace */ void new_cb (SimpleAction action, Variant? parameter) { //new MyWindow (this).show (); print ("You clicked \"New\"\n"); }

void quit_cb (SimpleAction action, Variant? parameter) { print ("You clicked \"Quit\"\n"); this.quit (); }

void awesome_cb (SimpleAction action, Variant? parameter) { var active = action.get_state ().get_boolean (); action.set_state (new Variant.boolean (!active)); if (active) print ("You unchecked \"Awesome\"\n"); else print ("You checked \"Awesome\"\n"); }

void state_cb (SimpleAction action, Variant? parameter) { print ("state is set to %s\n", parameter.get_string(null)); action.set_state (parameter); }

/* Vytvoří akce aplikace */ const ActionEntry[] actions = { { "new", new_cb }, { "quit", quit_cb }, { "awesome", awesome_cb, null, "false" }, { "state", state_cb, "s", "'off'" } };

protected override void startup () { base.startup ();

/* Nastaví akce aplikaci */ this.add_action_entries (actions, this);

/* Nastaví nabídkovou lištu a aplikační nabídku */ /* Získá soubor s uživatelským rozhraním */ var builder = new Gtk.Builder (); try { builder.add_from_file ("menubar.ui"); } catch (Error e) { error ("Unable to load file: %s", e.message); }

/* Získá nabídkovou lištu od objektu builder */ this.menubar = builder.get_object ("menubar") as MenuModel;

/* Získá aplikační nabídku od objektu builder */ this.app_menu = builder.get_object ("appmenu") as MenuModel; } }

/* main vytvoří a spustí aplikaci */ public int main (string[] args) { return new MyApplication ().run (args); }

# Horké klávesy

Popisky mohou obsahovat horké (mnemotechnické) klávesy. Mají podobu podtržených písmen v popiscích a používají se pro ovládání z klávesnice. Horké klávesy se vytváří umístěním podtržítka před příslušný znak. Například `"_File"` namísto `"File"` v atributu `label` v menubar.ui.

Horké klávesy jsou vidět, když zmáčknete klávesu Alt. Zmáčknutím Alt F otevřete nabídku File.

# Klávesové zkratky

Klávesové zkratky mohou být přidány přímo do definicí uživatelského rozhraní. Například je běžné, že aplikaci lze ukončit zmáčknutím CtrlQ, nebo že lze uložit soubor zmáčknutím CtrlS. Pro přidání klávesové zkratky do definice uživatelského rozhraní stačí akorát přidat do položky atribut `"accel"`.

`<attribute name="accel">&lt;Primary&gt;q</attribute>` vytvoří sekvenci CtrlQ při přidávání položky `Quit`. „Primary“ má zde význam klávesy Ctrl na počítačích PC nebo klávesy ⌘ na počítačích Mac.

<item> <attribute name="label">_Quit</attribute> <attribute name="action">app.quit</attribute> <attribute name="accel">&lt;Primary&gt;q</attribute> </item>

# Přeložitelné řetězce

Protože aplikace GNOME jsou překládány do mnoha jazyků, je důležité, aby řetězce ve vaší aplikaci byly přeložitelné. U popisku to zajistíte jednoduše nastavením `translatable="yes"`:

`<attribute name="label" translatable="yes">Quit</attribute>`

# Příslušná dokumentace k API

V této ukázce se používá následující:

Glib.ActionEntry

Gtk.Builder

# Cvičení