<?xml version="1.0" encoding="utf-8"?>
<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="filechooserdialog.vala" xml:lang="ca">
  <info>
  <title type="text">FileChooserDialog (Vala)</title>
    <link type="guide" xref="beginner.vala#file-selectors"/>
    <link type="seealso" xref="textview.vala"/>
    <link type="seealso" xref="menubar.vala"/>
    <link type="seealso" xref="scrolledwindow.vala"/>
    <revision version="0.1" date="2012-07-01" status="draft"/>

    <credit type="author copyright">
      <name>Tiffany Antopolski</name>
      <email its:translate="no">tiffany.antopolski@gmail.com</email>
      <years>2012</years>
    </credit>

    <desc>A dialog suitable for "Open" and "Save" commands.</desc>
  </info>

  <title>FileChooserDialog</title>
  <links type="sections"/>
  <section id="overview"><title>Overview of the example</title>
  <p>This example demonstrates how the FileChooserDialog can be used. It is incorporated into a very simple text editor application.  All the <link xref="menubar.vala#win-app">actions</link>, including the "open", "save" and "save-as" commands can be found in the <link xref="gmenu.vala">app-menu</link>.  Here, the app-menu is created using an XML UI file, which is then imported into the application using Gtk.Builder.</p>
  </section>
  <section id="xml"><title>XML UI file which creates the app-menu</title>
<code mime="application/xml" style="numbered">&lt;?xml version="1.0"?&gt;
&lt;interface&gt;
  &lt;menu id="appmenu"&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name="label"&gt;New&lt;/attribute&gt;
        &lt;attribute name="action"&gt;win.new&lt;/attribute&gt;
      &lt;/item&gt;
      &lt;item&gt;
        &lt;attribute name="label"&gt;Open&lt;/attribute&gt;
        &lt;attribute name="action"&gt;win.open&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name="label"&gt;Save&lt;/attribute&gt;
        &lt;attribute name="action"&gt;win.save&lt;/attribute&gt;
      &lt;/item&gt;
      &lt;item&gt;
        &lt;attribute name="label"&gt;Save As...&lt;/attribute&gt;
        &lt;attribute name="action"&gt;win.save-as&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name="label"&gt;Quit&lt;/attribute&gt;
        &lt;attribute name="action"&gt;app.quit&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
  &lt;/menu&gt;
&lt;/interface&gt;
</code>
  </section>
  <section id="vala-code"><title>Vala Code</title>
  <code mime="text/x-csharp" style="numbered">class MyWindow: Gtk.ApplicationWindow {

	/* MyWindow instance variables. */
	GLib.File? file;
	Gtk.TextBuffer buffer;
	Gtk.TextView textview;
	Gtk.ScrolledWindow scrolled_window;

	/* Create ActionEntries. */
	const ActionEntry[] actions = {
		{ "new", new_cb },
		{ "open", open_cb },
		{ "save", save_cb },
		{ "save-as", save_as_cb }
	};

	/* Constructor creates MyWindow, and add the scrolled_window. */
	internal MyWindow (MyApplication app) {
		Object (application: app, title: "FileChooserDialog Example");
		this.set_default_size (400, 400);

		/* Add the ActionEntries to MyWindow. */
		this.add_action_entries (actions, this);

		buffer = new Gtk.TextBuffer (null); //stores text to be displayed
		textview = new Gtk.TextView.with_buffer (buffer); //displays TextBuffer
		textview.set_wrap_mode (Gtk.WrapMode.WORD); //sets line wrapping

		scrolled_window = new Gtk.ScrolledWindow (null, null);
		scrolled_window.set_policy (Gtk.PolicyType.AUTOMATIC,
		                            Gtk.PolicyType.AUTOMATIC);

		scrolled_window.add (textview);
		scrolled_window.set_border_width (5);

        this.add (scrolled_window);
		this.show_all ();
	}

	void new_cb (SimpleAction action, Variant? parameter) {
		file = null;
		buffer.set_text ("");
		print ("New file created\n");
	}

	/* Create FileChooserDialog in OPEN mode. */
	void open_cb (SimpleAction action, Variant? parameter) {

		var open_dialog = new Gtk.FileChooserDialog ("Pick a file",
		                                             this as Gtk.Window,
		                                             Gtk.FileChooserAction.OPEN,
		                                             Gtk.Stock.CANCEL,
		                                             Gtk.ResponseType.CANCEL,
		                                             Gtk.Stock.OPEN,
		                                             Gtk.ResponseType.ACCEPT);

		open_dialog.local_only = false; //allow for uri
		open_dialog.set_modal (true);
		open_dialog.response.connect (open_response_cb);
		open_dialog.show ();
	}

	/* Either open the file and load the file contents or cancel. */
	void open_response_cb (Gtk.Dialog dialog, int response_id) {
		var open_dialog = dialog as Gtk.FileChooserDialog;

		switch (response_id) {
			case Gtk.ResponseType.ACCEPT: //open the file
				file = open_dialog.get_file();

				uint8[] file_contents;

				try {
					file.load_contents (null, out file_contents, null);
				}
				catch (GLib.Error err) { //handle the exception
					error ("%s\n", err.message);
				}
				/* Set the buffer text to be the contents of the file. */
				buffer.set_text ((string) file_contents,
				                 file_contents.length);

				print ("opened: %s\n", (open_dialog.get_filename ()));
				break;

			case Gtk.ResponseType.CANCEL:
				print ("cancelled: FileChooserAction.OPEN\n");
				break;
		}
		dialog.destroy ();
	}


	/* Create FileChooserDialog in SAVE mode. */
	void save_as_cb (SimpleAction action, Variant? parameter) {
		var save_dialog = new Gtk.FileChooserDialog ("Pick a file",
		                                             this as Gtk.Window,
		                                             Gtk.FileChooserAction.SAVE,
		                                             Gtk.Stock.CANCEL,
		                                             Gtk.ResponseType.CANCEL,
		                                             Gtk.Stock.SAVE,
		                                             Gtk.ResponseType.ACCEPT);

		save_dialog.set_do_overwrite_confirmation (true);
		save_dialog.set_modal (true);
		if (file != null) {
			try {
				(save_dialog as Gtk.FileChooser).set_file (file);
			}
			catch (GLib.Error error) {
				print ("%s\n", error.message);
			}
		}
		save_dialog.response.connect (save_as_response_cb);
		save_dialog.show ();
	}

	void save_as_response_cb (Gtk.Dialog dialog, int response_id) {
		var save_dialog = dialog as Gtk.FileChooserDialog;

		switch (response_id) {
			case Gtk.ResponseType.ACCEPT:
				file = save_dialog.get_file();
				this.save_to_file ();
				break;
			default:
				break;
		}
			dialog.destroy ();
	}

	/* Save the existing contents to the file.
	 * If file does not exist, call save_as_cb.
	 */
	void save_cb (SimpleAction action, Variant? parameter) {
		if (file != null) {
			this.save_to_file ();
		}
		else {
			save_as_cb (action, parameter);
		}
	}

	void save_to_file (){
		Gtk.TextIter start;
		Gtk.TextIter end;

		buffer.get_bounds (out start, out end);
		string current_contents = buffer.get_text (start, end, false);
		try {
				file.replace_contents (current_contents.data, null, false,
				                       GLib.FileCreateFlags.NONE, null, null);

				print ("saved: %s\n", file.get_path ());
		}
		catch (GLib.Error err) {
			error ("%s\n", err.message);
		}
	}
}

/* This is the application */
class MyApplication: Gtk.Application {
	protected override void activate () {
		new MyWindow (this).show_all;
	}

	const ActionEntry[] actions = {
		{ "quit", quit_cb }
	};

	void quit_cb (SimpleAction action, Variant? parameter) {
		this.quit ();
	}

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

		/* Setup actions */
		this.add_action_entries (actions, this);

		/* Setup menus */
		var builder = new Gtk.Builder ();
		try {
			builder.add_from_file ("filechooserdialog.ui");
		} catch (GLib.Error err) {
			error ("Unable to load file: %s\n", err.message);
		}
		this.app_menu = builder.get_object ("appmenu") as MenuModel;
	}
}

/* main creates and runs the application. */
public int main (string[] args) {
	return new MyApplication ().run (args);
}
</code>
  </section>
  <section id="api"><title>Relevant API documentation</title>
<p>
  In this sample we used the following:
</p>
<list>
  <item><p><link href="http://valadoc.org/gtk+-3.0/Gtk.FileChooser.html">FileChooser</link></p></item>
  <item><p><link href="http://valadoc.org/gtk+-3.0/Gtk.FileChooserDialog.html">FileChooserDialog</link></p></item>
  <item><p><link href="http://valadoc.org/gtk+-3.0/Gtk.Builder.html">Gtk.Builder</link></p></item>
  <item><p><link href="http://valadoc.org/gio-2.0/GLib.ActionEntry.html">GLib.ActionEntry</link></p></item>
</list>
</section>
</page>
