Blame platform-demos/gl/menubar.vala.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:xi="http://www.w3.org/2001/XInclude" type="guide" style="task" id="menubar.vala" xml:lang="gl">
Packit 1470ea
  <info>
Packit 1470ea
  <title type="text">MenuBar (Vala)</title>
Packit 1470ea
  <link type="guide" xref="beginner.vala#menu-combo-toolbar"/>
Packit 1470ea
  <link type="seealso" xref="aboutdialog.vala"/>
Packit 1470ea
  <link type="seealso" xref="gmenu.vala"/>
Packit 1470ea
    <revision version="0.1" date="2012-05-25" status="draft"/>
Packit 1470ea
Packit 1470ea
    <credit type="author copyright">
Packit 1470ea
      <name>Tiffany Antopolski</name>
Packit 1470ea
      <email its:translate="no">tiffany.antopolski@gmail.com</email>
Packit 1470ea
      <years>2012</years>
Packit 1470ea
    </credit>
Packit 1470ea
Packit 1470ea
    <desc>A widget which holds GtkMenuItem widgets</desc>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Fran Dieguez</mal:name>
Packit 1470ea
      <mal:email>frandieguez@gnome.org</mal:email>
Packit 1470ea
      <mal:years>2012-2013.</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
  <title>MenuBar</title>
Packit 1470ea
  <media type="image" mime="image/png" src="media/menubar.png"/>
Packit 1470ea
  

A MenuBar created using XML and GtkBuilder.

Packit 1470ea
Packit 1470ea
  <links type="section"/>
Packit 1470ea
Packit 1470ea
  <section id="xml"> <title>Create a MenuBar using XML</title>
Packit 1470ea
   

To create the menubar using XML:

Packit 1470ea
   <steps>
Packit 1470ea
     <item>

Create <file>menubar.ui</file> using your favorite text editor.

</item>
Packit 1470ea
     <item>

Enter the following line at the top of the file:

Packit 1470ea
           
Packit 1470ea
]]>
Packit 1470ea
     </item>
Packit 1470ea
    <item>

We want to create the interface which will contain our menubar and its submenus. Our menubar will contain <gui>File</gui>, <gui>Edit</gui>, <gui>Choices</gui> and <gui>Help</gui> submenus. We add the following XML code to the file:

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

Now we will create the .vala file and use GtkBuilder to import the <file>menubar.ui</file> we just created.

</item>
Packit 1470ea
   </steps>
Packit 1470ea
   </section>
Packit 1470ea
   <section id="basis"> <title>Add the MenuBar to the window using GtkBuilder</title>
Packit 1470ea
public class MyWindow : Gtk.ApplicationWindow {
Packit 1470ea
	internal MyWindow (MyApplication app) {
Packit 1470ea
		Object (application: app, title: "MenuBar Example");
Packit 1470ea
		this.set_default_size (200, 200);
Packit 1470ea
	}
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
class MyApplication: Gtk.Application {
Packit 1470ea
	protected override void activate () {
Packit 1470ea
		new MyWindow (this).show ();
Packit 1470ea
	}
Packit 1470ea
	protected override void startup () {
Packit 1470ea
		base.startup ();
Packit 1470ea
Packit 1470ea
		/* Setup menubar. */
Packit 1470ea
		/* Get the UI file. */
Packit 1470ea
		var builder = new Gtk.Builder ();
Packit 1470ea
		try {
Packit 1470ea
			builder.add_from_file ("menubar_basis.ui");
Packit 1470ea
		/* Handle the exception. */
Packit 1470ea
		} catch (Error e) {
Packit 1470ea
			error ("Unable to load file: %s", e.message);
Packit 1470ea
		}
Packit 1470ea
Packit 1470ea
		/* Get the menubar from the builder. */
Packit 1470ea
		this.menubar = builder.get_object ("menubar") as MenuModel;
Packit 1470ea
	}
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
/* main creates and runs the application. */
Packit 1470ea
public int main (string[] args) {
Packit 1470ea
	return new MyApplication ().run (args);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea

Packit 1470ea
Now, compile the vala file, and run it. The application should look like the picture at the top of this page.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
Packit 1470ea
Packit 1470ea
<section id="xml2"> <title>Add items to the menus</title>
Packit 1470ea

We start off by adding 2 menuitems to the <gui>File</gui> menu: <gui>New</gui> and <gui>Quit</gui>. We do this by adding a section to the the File submenu with these items. The <file>menubar.ui</file> should look like this (lines 6 to 13 inclusive comprise the newly added section):

Packit 1470ea
      
Packit 1470ea
Packit 1470ea
<interface>
Packit 1470ea
  <menu id="menubar">
Packit 1470ea
    <submenu>
Packit 1470ea
      <attribute name="label">File</attribute>
Packit 1470ea
      <section>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name="label">New</attribute>
Packit 1470ea
        </item>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name ="label">Quit</attribute>
Packit 1470ea
        </item>
Packit 1470ea
      </section>
Packit 1470ea
    </submenu>
Packit 1470ea
    <submenu>
Packit 1470ea
      <attribute name="label">Edit</attribute>
Packit 1470ea
    </submenu>
Packit 1470ea
    <submenu>
Packit 1470ea
      <attribute name="label">Choices</attribute>
Packit 1470ea
    </submenu>
Packit 1470ea
    <submenu>
Packit 1470ea
      <attribute name="label">Help</attribute>
Packit 1470ea
    </submenu>
Packit 1470ea
  </menu>
Packit 1470ea
</interface>]]>
Packit 1470ea
Packit 1470ea

Following this pattern, you can now add a Copy and a Paste item to the Edit submenu, and an About item to the Help submenu. We will hold off on adding items to the <link xref="menubar.vala#choices">Choices submenu</link> until further in the tutorial.

Packit 1470ea
Packit 1470ea
<note style="tip">

Packit 1470ea
  You do not need to recompile the vala program if you only made changes to the UI file.  Just run your previously compiled application, and the UI changes will be reflected.
Packit 1470ea

</note>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="actions"><title>Setup actions</title>
Packit 1470ea

This is a three step process.

Packit 1470ea
<steps>
Packit 1470ea
  <item>

First we create the ActionEntry array in the MyApplication class.

Packit 1470ea
           An ActionEntry consists of: 

Packit 1470ea
  <list>
Packit 1470ea
    <item>

the "action name" (mandatory)

</item>
Packit 1470ea
    <item>

the callback function to connect to the "activate" signal of the action (if applicable)

</item>
Packit 1470ea
    <item>

the type of the parameter that must be passed to the activate function for the action (if applicable)

</item>
Packit 1470ea
    <item>

the initial state for this action (if applicable)

</item>
Packit 1470ea
    <item>

the callback to connect to "change-state" signal (if applicable)

</item>
Packit 1470ea
  </list>
Packit 1470ea
   
Packit 1470ea
const ActionEntry[] actions = {
Packit 1470ea
    { "new", new_cb }, // {"action name", callback_function}
Packit 1470ea
    { "quit", quit_cb }
Packit 1470ea
};
Packit 1470ea
Packit 1470ea
  </item>
Packit 1470ea
  <item>

Second, we create the callback functions the actions are connected to.

Packit 1470ea
  
Packit 1470ea
void new_cb (SimpleAction action, Variant? parameter) {
Packit 1470ea
    print ("You clicked \"New\"\n");
Packit 1470ea
    //new MyWindow (this).show ();
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
void quit_cb (SimpleAction action, Variant? parameter) {
Packit 1470ea
    print ("You clicked \"Quit\"\n");
Packit 1470ea
    this.quit ();
Packit 1470ea
}
Packit 1470ea
 </item>
Packit 1470ea
  <item>

And lastly, we connect the menu items to the actions in the XML file by adding the "action" attribute:

Packit 1470ea
    
Packit 1470ea
<item>
Packit 1470ea
  <attribute name="label">New</attribute>
Packit 1470ea
  <attribute name="action">app.new</attribute>
Packit 1470ea
</item>
Packit 1470ea
<item>
Packit 1470ea
  <attribute name="label">Quit</attribute>
Packit 1470ea
  <attribute name="action">app.quit</attribute>
Packit 1470ea
</item>]]>
Packit 1470ea
 </item>
Packit 1470ea
</steps>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
Packit 1470ea
<section id="choices"><title>Choices submenu and items with state</title>
Packit 1470ea
  <media type="image" mime="image/png" src="media/menubar_choices.png"/>
Packit 1470ea
  

Lines 30 to 80 inclusive of the <link xref="menubar.vala#xml-code"/> demonstrate

Packit 1470ea
     the XML code used to create the UI for <gui>Choices</gui> menu.

Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="win-app"><title>Actions: Application or Window?</title>
Packit 1470ea
  

Above, we created the "new" and "open" actions as part of the MyApplication class.

Packit 1470ea
  Actions which control the application itself, such as "quit" should be created similarly.

Packit 1470ea
Packit 1470ea
  

Some actions, such as "copy" and "paste" deal with the window, not the application.

Packit 1470ea
  Window actions should be created as part of the window class.

Packit 1470ea
Packit 1470ea
  

Packit 1470ea
   The complete example files contain both application actions and
Packit 1470ea
   window applications.  The window actions are the ones usually included in the <link xref="gmenu.vala">application menu</link> also.  It is not good practice to include window actions in the application menu. For demonstration purposes, the complete example files which follow include XML in the UI file which creates the application menu which includes a "New" and "Open" item, and these are hooked up to the same actions as the menubar items of the same name.
Packit 1470ea
  

Packit 1470ea
Packit 1470ea
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
  <section id="xml-code"><title>Complete XML UI file for this example</title>
Packit 1470ea
<?xml version="1.0" encoding="UTF-8"?>
Packit 1470ea
<interface>
Packit 1470ea
  <menu id="menubar">
Packit 1470ea
    <submenu>
Packit 1470ea
      <attribute name="label">File</attribute>
Packit 1470ea
      <section>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name="label">New</attribute>
Packit 1470ea
          <attribute name="action">app.new</attribute>
Packit 1470ea
        </item>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name="label">Quit</attribute>
Packit 1470ea
          <attribute name="action">app.quit</attribute>
Packit 1470ea
        </item>
Packit 1470ea
      </section>
Packit 1470ea
    </submenu>
Packit 1470ea
    <submenu>
Packit 1470ea
      <attribute name="label">Edit</attribute>
Packit 1470ea
      <section>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name="label">Copy</attribute>
Packit 1470ea
          <attribute name="action">win.copy</attribute>
Packit 1470ea
        </item>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name="label">Paste</attribute>
Packit 1470ea
          <attribute name="action">win.paste</attribute>
Packit 1470ea
        </item>
Packit 1470ea
      </section>
Packit 1470ea
    </submenu>
Packit 1470ea
    <submenu>
Packit 1470ea
      <attribute name="label">Choices</attribute>
Packit 1470ea
      <submenu>
Packit 1470ea
        <attribute name="label">Shapes</attribute>
Packit 1470ea
          <section>
Packit 1470ea
            <item>
Packit 1470ea
              <attribute name="label">Line</attribute>
Packit 1470ea
              <attribute name="action">win.shape</attribute>
Packit 1470ea
              <attribute name="target">line</attribute>
Packit 1470ea
            </item>
Packit 1470ea
            <item>
Packit 1470ea
              <attribute name="label">Triangle</attribute>
Packit 1470ea
              <attribute name="action">win.shape</attribute>
Packit 1470ea
              <attribute name="target">triangle</attribute>
Packit 1470ea
            </item>
Packit 1470ea
            <item>
Packit 1470ea
              <attribute name="label">Square</attribute>
Packit 1470ea
              <attribute name="action">win.shape</attribute>
Packit 1470ea
              <attribute name="target">square</attribute>
Packit 1470ea
            </item>
Packit 1470ea
            <item>
Packit 1470ea
              <attribute name="label">Polygon</attribute>
Packit 1470ea
              <attribute name="action">win.shape</attribute>
Packit 1470ea
              <attribute name="target">polygon</attribute>
Packit 1470ea
            </item>
Packit 1470ea
            <item>
Packit 1470ea
              <attribute name="label">Circle</attribute>
Packit 1470ea
              <attribute name="action">win.shape</attribute>
Packit 1470ea
              <attribute name="target">circle</attribute>
Packit 1470ea
            </item>
Packit 1470ea
          </section>
Packit 1470ea
      </submenu>
Packit 1470ea
      <section>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name="label">On</attribute>
Packit 1470ea
          <attribute name="action">app.state</attribute>
Packit 1470ea
          <attribute name="target">on</attribute>
Packit 1470ea
        </item>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name="label">Off</attribute>
Packit 1470ea
          <attribute name="action">app.state</attribute>
Packit 1470ea
          <attribute name="target">off</attribute>
Packit 1470ea
        </item>
Packit 1470ea
      </section>
Packit 1470ea
      <section>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name="label">Awesome</attribute>
Packit 1470ea
          <attribute name="action">app.awesome</attribute>
Packit 1470ea
        </item>
Packit 1470ea
      </section>
Packit 1470ea
    </submenu>
Packit 1470ea
    <submenu>
Packit 1470ea
      <attribute name="label">Help</attribute>
Packit 1470ea
      <section>
Packit 1470ea
        <item>
Packit 1470ea
          <attribute name="label">About</attribute>
Packit 1470ea
          <attribute name="action">win.about</attribute>
Packit 1470ea
        </item>
Packit 1470ea
      </section>
Packit 1470ea
    </submenu>
Packit 1470ea
  </menu>
Packit 1470ea
  <menu id="appmenu">
Packit 1470ea
    <section>
Packit 1470ea
      <item>
Packit 1470ea
        <attribute name="label">New</attribute>
Packit 1470ea
        <attribute name="action">app.new</attribute>
Packit 1470ea
      </item>
Packit 1470ea
      <item>
Packit 1470ea
        <attribute name="label">Quit</attribute>
Packit 1470ea
        <attribute name="action">app.quit</attribute>
Packit 1470ea
      </item>
Packit 1470ea
    </section>
Packit 1470ea
  </menu>
Packit 1470ea
</interface>
Packit 1470ea
Packit 1470ea
  </section>
Packit 1470ea
  <section id="vala-code"><title>Complete Vala file for this example</title>
Packit 1470ea
public class MyWindow : Gtk.ApplicationWindow {
Packit 1470ea
Packit 1470ea
	/* Callback functions for the window actions. */
Packit 1470ea
	void copy_cb (SimpleAction action, Variant? parameter) {
Packit 1470ea
		print ("\"Copy\" activated\n");
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	void paste_cb (SimpleAction action, Variant? parameter) {
Packit 1470ea
		print ("\"Paste\" activated\n");
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	void shape_cb (SimpleAction action, Variant? parameter) {
Packit 1470ea
		print ("shape is set to %s\n", parameter.get_string(null));
Packit 1470ea
		action.set_state (parameter);
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	/* Create the window actions. */
Packit 1470ea
	const ActionEntry[] actions = {
Packit 1470ea
		/*{ "action name", cb to connect to "activate" signal, parameter type,
Packit 1470ea
		     initial state, cb to connect to "change-state" signal } */
Packit 1470ea
		{ "copy", copy_cb },
Packit 1470ea
		{ "paste", paste_cb },
Packit 1470ea
		{ "shape", shape_cb, "s", "'line'"}
Packit 1470ea
	};
Packit 1470ea
Packit 1470ea
	internal MyWindow (MyApplication app) {
Packit 1470ea
		Object (application: app, title: "MenuBar Example");
Packit 1470ea
		this.set_default_size (200, 200);
Packit 1470ea
Packit 1470ea
		/* Setup window actions. */
Packit 1470ea
		this.add_action_entries (actions, this);
Packit 1470ea
	}
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
class MyApplication: Gtk.Application {
Packit 1470ea
	protected override void activate () {
Packit 1470ea
		new MyWindow (this).show ();
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	/* Callback functions for the application actions. */
Packit 1470ea
	void new_cb (SimpleAction action, Variant? parameter) {
Packit 1470ea
		//new MyWindow (this).show ();
Packit 1470ea
		print ("You clicked \"New\"\n");
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	void quit_cb (SimpleAction action, Variant? parameter) {
Packit 1470ea
		print ("You clicked \"Quit\"\n");
Packit 1470ea
		this.quit ();
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	void awesome_cb (SimpleAction action, Variant? parameter) {
Packit 1470ea
		var active = action.get_state ().get_boolean ();
Packit 1470ea
		action.set_state (new Variant.boolean (!active));
Packit 1470ea
		if (active)
Packit 1470ea
			print ("You unchecked \"Awesome\"\n");
Packit 1470ea
		else
Packit 1470ea
			print ("You checked \"Awesome\"\n");
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	void state_cb (SimpleAction action, Variant? parameter) {
Packit 1470ea
		print ("state is set to %s\n", parameter.get_string(null));
Packit 1470ea
		action.set_state (parameter);
Packit 1470ea
	}
Packit 1470ea
Packit 1470ea
	/* Create the application actions. */
Packit 1470ea
	const ActionEntry[] actions = {
Packit 1470ea
		{ "new", new_cb },
Packit 1470ea
		{ "quit", quit_cb },
Packit 1470ea
		{ "awesome", awesome_cb, null, "false" },
Packit 1470ea
		{ "state", state_cb, "s", "'off'" }
Packit 1470ea
	};
Packit 1470ea
Packit 1470ea
	protected override void startup () {
Packit 1470ea
		base.startup ();
Packit 1470ea
Packit 1470ea
		/* Setup application actions. */
Packit 1470ea
		this.add_action_entries (actions, this);
Packit 1470ea
Packit 1470ea
		/* Setup menubar and app_menu. */
Packit 1470ea
		/* Get the UI file. */
Packit 1470ea
		var builder = new Gtk.Builder ();
Packit 1470ea
		try {
Packit 1470ea
			builder.add_from_file ("menubar.ui");
Packit 1470ea
		} catch (Error e) {
Packit 1470ea
			error ("Unable to load file: %s", e.message);
Packit 1470ea
		}
Packit 1470ea
Packit 1470ea
		/* Get the menubar from the builder. */
Packit 1470ea
		this.menubar = builder.get_object ("menubar") as MenuModel;
Packit 1470ea
Packit 1470ea
		/* Get the app_menu from the builder. */
Packit 1470ea
		this.app_menu = builder.get_object ("appmenu") as MenuModel;
Packit 1470ea
	}
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
/* main creates and runs the application. */
Packit 1470ea
public int main (string[] args) {
Packit 1470ea
	return new MyApplication ().run (args);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="mnemonics"><title>Mnemonics</title>
Packit 1470ea
    

Labels may contain mnemonics. Mnemonics are underlined characters in the label, used for keyboard navigation. Mnemonics are created by placing an underscore before the mnemonic character. For example "_File" instead of just "File" in the menubar.ui label attribute.

Packit 1470ea
   

The mnemonics are visible when you press the <key>Alt</key> key. Pressing <keyseq><key>Alt</key><key>F</key></keyseq> will open the <gui>File</gui> menu.

Packit 1470ea
   

Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="accelerators"><title>Accelerators</title>
Packit 1470ea
    

Accelerators can be explicitly added in the UI definitions. For example, it is common to be able to quit an application by pressing <keyseq><key>Ctrl</key><key>Q</key></keyseq> or to save a file by pressing <keyseq><key>Ctrl</key><key>S</key></keyseq>. To add an accelerator to the UI definition, you simply need add an "accel" attribute to the item.

Packit 1470ea

<Primary>q</attribute>]]> will create the <keyseq><key>Ctrl</key><key>Q</key></keyseq> sequence when added to the Quit label item. Here, "Primary" refers to the <key>Ctrl</key> key on a PC or the <key>⌘</key> key on a Mac.

Packit 1470ea
Packit 1470ea
  
Packit 1470ea
<item>
Packit 1470ea
  <attribute name="label">_Quit</attribute>
Packit 1470ea
  <attribute name="action">app.quit</attribute>
Packit 1470ea
  <attribute name="accel"><Primary>q</attribute>
Packit 1470ea
</item>]]>
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="translatable"><title>Translatable strings</title>
Packit 1470ea
   

Packit 1470ea
   Since GNOME applications are being translated into <link href="http://l10n.gnome.org/languages/">many languages</link>, it is important that the strings in your application are translatable.  To make a label translatable, simple set translatable="yes":
Packit 1470ea
   

Packit 1470ea
   

Packit 1470ea
     Quit</attribute>]]>
Packit 1470ea
  

Packit 1470ea
  </section>
Packit 1470ea
  <section id="documentation"><title>Relevant API documentation</title>
Packit 1470ea

Neste exemplo empregaremos o seguinte:

Packit 1470ea
<list>
Packit 1470ea
  <item>

<link href="http://valadoc.org/gio-2.0/GLib.ActionEntry.html">Glib.ActionEntry</link>

</item>
Packit 1470ea
  <item>

<link href="http://valadoc.org/gio-2.0/Gtk.Builder.html">Gtk.Builder</link>

</item>
Packit 1470ea
</list>
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
Packit 1470ea
<section id="exercises"><title>Exercicios</title>
Packit 1470ea
  <xi:include href="exercises/menubar.vala.exercises"><xi:fallback/></xi:include>
Packit 1470ea
</section>
Packit 1470ea
</page>