[gnome-devel-docs] platform-demos: Added image-viewer C++ example (draft)



commit 52288574f2ef2c060cea9ed4cebae0bbfbd47367
Author: Johannes Schmid <jhs gnome org>
Date:   Sun Mar 20 18:01:45 2011 -0400

    platform-demos: Added image-viewer C++ example (draft)

 platform-demos/C/image-viewer.cpp.page        |  236 +++++++++++++++++++++++++
 platform-demos/C/image-viewer/image-viewer.cc |   67 +++++++
 2 files changed, 303 insertions(+), 0 deletions(-)
---
diff --git a/platform-demos/C/image-viewer.cpp.page b/platform-demos/C/image-viewer.cpp.page
new file mode 100644
index 0000000..d646abe
--- /dev/null
+++ b/platform-demos/C/image-viewer.cpp.page
@@ -0,0 +1,236 @@
+<page xmlns="http://projectmallard.org/1.0/";
+      type="topic"
+      id="image-viewer.cpp">
+
+  <info>
+    <link type="guide" xref="index#cpp"/>
+    
+    <desc>A little bit more than a simple "Hello world" Gtkmm application.</desc>
+    
+    <revision pkgversion="0.1" version="0.1" date="2011-03-18" status="review"/>
+    <credit type="author">
+      <name>GNOME Documentation Project</name>
+      <email>gnome-doc-list gnome org</email>
+    </credit>
+    <credit type="author">
+      <name>Johannes Schmid</name>
+      <email>jhs gnome org</email>
+    </credit>    
+  </info>
+
+<title>Image Viewer</title>
+
+<synopsis>
+  <p>In this tutorial, you will learn:</p>
+  <list>
+    <item><p>Some basic concepts of the C/GObject programming</p></item>
+    <item><p>How to write a Gtk application in C</p></item>
+  </list>
+</synopsis>
+
+<media type="image" mime="image/png" src="media/image-viewer.png"/>
+
+<section>
+  <title>Create a project in Anjuta</title>
+  <p>Before you start coding, you'll need to set up a new project in Anjuta. This will create all of the files you need to build and run the code later on. It's also useful for keeping everything together.</p>
+  <steps>
+    <item>
+    <p>Start Anjuta and click <guiseq><gui>File</gui><gui>New</gui><gui>Project</gui></guiseq> to open the project wizard.</p>
+    </item>
+    <item>
+    <p>Choose <gui>Gtkmm (Simple)</gui> from the <gui>C++</gui> tab, click <gui>Forward</gui>, and fill-out your details on the next few pages. Use <file>image-viewer</file> as project name and directory.</p>
+   	</item>
+    <item>
+    <p>Make sure that <gui>Use GtkBuilder for user interface</gui> is disabled as we will
+    create the UI manually in this tutorial. Check the <link xref="guitar-tuner.cpp">Guitar-Tuner</link>
+    tutorial using the interface builder.</p>
+    </item>
+    <item>
+    <p>Click <gui>Finished</gui> and the project will be created for you. Open <file>src/main.cc</file> from the <gui>Project</gui> or <gui>File</gui> tabs. You should see some code which starts with the lines:</p>
+    <code mime="text/x-csrc"><![CDATA[
+#include <gtkmm.h>
+#include <iostream>
+
+#include "config.h">]]></code>
+    </item>
+  </steps>
+</section>
+
+<section>
+  <title>Build the code for the first time</title>
+  <p>This is a very basic C++ code setting up Gtkmm. More details are given below; skip this list if you understand the basics:</p>  
+  <list>
+  <item>
+    <p>The three <code>#include</code> lines at the top include the <code>config</code> (useful autoconf build defines), <code>gtkmm</code> (user interface) and <code>iostream</code> (C++-STL) libraries. Functions from these libraries are used in the rest of the code.</p>
+   </item>
+   <item>
+    <p>The <code>main</code> function creates a new (empty) window and sets the window title.</p>
+   </item>
+   <item>
+    <p>The <code>kit::run()</code> call start the GTKmm mainloop, which runs the user interface and starts listening for events (like clicks and key presses). As we give the window
+    as argument to that function, the application will automatically exit when 
+    that window is closed.</p>
+   </item>
+  </list>
+
+  <p>This code is ready to be used, so you can compile it by clicking <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> (or press <keyseq><key>Shift</key><key>F7</key></keyseq>).</p>
+  <p>Press <gui>Configure</gui> on the next window that appears to configure a debug build. You only need to do this once, for the first build.</p>
+</section>
+
+<section>
+<title>Creating the user interface</title>
+<p>Now we will bring live into the empty window. <em>Gtkmm</em> organizes the user interface
+with <em>Gtk::Container</em>s that can contain other widgets and even other containers. Here we
+will use the simplest available container, a <em>Gtk::Box</em>:</p>
+<code mime="text/x-csrc"><![CDATA[
+int
+main (int argc, char *argv[])
+{
+	Gtk::Main kit(argc, argv);
+
+	Gtk::Window* main_win = new Gtk::Window(Gtk::WINDOW_TOPLEVEL);
+	main_win->set_title ("image-viewer-cpp");
+
+	Gtk::Box* box = new Gtk::Box();
+	box->set_orientation (Gtk::ORIENTATION_VERTICAL);
+	box->set_spacing(5);
+
+	Gtk::Image* image = new Gtk::Image();
+	box->pack_start (*image, true, true);
+	
+	Gtk::Button* button = new Gtk::Button("Open Imageâ?¦");
+	box->pack_start (*button, false, false);
+
+	main_win->add(*box);
+
+	button->signal_clicked().connect (sigc::bind<Gtk::Image*>(sigc::ptr_fun(&on_open_image), image));
+
+	main_win->show_all();
+	
+	if (main_win)
+	{
+		kit.run(*main_win);
+	}
+	return 0;
+}
+]]></code>
+  <steps>
+    <item>
+    <p>The first lines create the widgets we want to use, a button for opening up an image, the image view widget itself and the box we will use as container. </p>
+    </item>
+    <item>
+    <p>The calls to <code>pack_start()</code> add the two widgets to the box and define their behaviour. The image will
+    expand to any available space while the button will just be as big as needed. You will notice that we don't set
+    explicit sizes on the widgets. In <em>Gtkmm</em> this is usually not needed at makes it much easier to have a layout that
+    looks good in different window sizes. Next, the box is added to the window.</p>
+    </item>
+    <item>
+    <p>>We need to define what happens when the user clicks on the button. <em>Gtkmm</em> uses the concept of <em>signals</em> and
+    the buttons fires the <em>clicked</em> signal that we can connect to some action. This is done using the <code>signal_clicked().connect()</code>
+    method which tells <em>Gtkmm</em> to call the <code>on_open_image</code> when the button is clicked and
+    to pass the image as additional argument to that function. We will define the <em>callback</em> in the next section.</p>
+    </item>
+    <item>
+    <p>The last step is to show all widgets in the window using
+    <code>show_all()</code>. This is equivalent to using the <code>show()</code>
+    method on all our widgets.</p>
+    </item>
+  </steps>
+</section>
+
+<section>
+<title>Showing the image</title>
+<p>We will now define the signal handler for the <em>click</em>-signal or the 
+button we mentioned before. Add this code before the <code>main()</code>
+method.</p>
+<code mime="text/x-csrc"><![CDATA[
+static void
+on_open_image (Gtk::Image* image)
+{
+	Gtk::FileChooserDialog dialog("Open image",
+	                              Gtk::FILE_CHOOSER_ACTION_OPEN);
+	dialog.add_button (Gtk::Stock::OPEN,
+	                   Gtk::RESPONSE_ACCEPT);
+	dialog.add_button (Gtk::Stock::CANCEL,
+	                   Gtk::RESPONSE_CANCEL);
+
+	Glib::RefPtr<Gtk::FileFilter> filter =
+		Gtk::FileFilter::create();
+	filter->add_pixbuf_formats();
+	dialog.add_filter (filter);
+
+	switch (dialog.run())
+	{
+		case Gtk::RESPONSE_ACCEPT:
+			image->set(dialog.get_filename());
+			break;
+		default:
+			break;
+	}
+	dialog.hide();
+}
+]]></code>
+  <p>This is a bit more complicated than anything we've attempted so far, so let's break it down:</p>
+  <list>
+    <item><p>The argument to the signal is the image object that we passed while connecting the signal, Actually the signal could have other arguments but the <em>clicked</em> doesn't have any. </p>    </item> 
+    <item>
+      <p>The next interesting line is where the dialog for choosing the file is created using
+      <code>Gtk::FileChooserDialog()</code>. The function takes the title of the dialog and
+      the type of dialog this should be. In our case, it is an <em>Open</em> dialog</p>
+    </item>
+    <item>
+    <p>The next two lines add an <em>Open</em> and a <em>Close</em> button to the dialog.</p>
+    <p>Notice that we are using <em>stock</em> button names from Gtk, instead of manually typing "Cancel" or "Open". The advantage of using stock names is that the button labels will already be translated into the user's language.</p>
+    <p>The second argument to the <code>add_button()</code> method is a value to identify
+    the clicked button. We use predefined values provided by Gtkmm here, too.
+    </p>
+    </item>
+    <item>
+    <p>The next two lines restrict the <gui>Open</gui> dialog to only display files which can be opened by Gtk::Image. A filter object is created first; we then add all kinds of files supported by Gtk::Pixbuf (which includes most image formats like PNG and JPEG) to the filter. Finally, we set this filter to be the <gui>Open</gui> dialog's filter.</p>
+    <p><code>Glib::RefPtr</code> is a smart pointer used here, that makes sure that the filter is
+    destroyed when there is no reference to it anymore.</p>
+    </item>
+    <item>
+    <p><code>dialog.run()</code> displays the <gui>Open</gui> dialog. The dialog will wait for the user to choose an image; when they do, <code>dialog.run()</code> will return the value <code>GTK::RESPONSE_ACCEPT</code> (it would return <code>GTK::RESPONSE_CANCEL</code> if the user clicked <gui>Cancel</gui>). The <code>switch</code> statement tests for this.</p>
+    </item>
+    <item><p>Assuming that the user did click <gui>Open</gui>, the next line loads the
+    file into the Gtk::Image so that it is displayed.</p>
+    </item>
+    <item>
+    <p>In the final line of this method, we hide the <gui>Open</gui> dialog because we don't need it any more. The dialog would be hidden anyway, as it is only a local variable and is
+    destroyed (and such hidden) when the scope ends.</p>
+    </item>
+  </list>
+</section>
+
+<section>
+  <title>Build and run the application</title>
+  <p>All of the code should now be ready to go. Click <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> to build everything again, and then <guiseq><gui>Run</gui><gui>Run</gui></guiseq> to start the application.</p>
+  <p>If you haven't already done so, choose the <file>Debug/src/image-viewer</file> application in the dialog that appears. Finally, hit <gui>Run</gui> and enjoy!</p>
+</section>
+
+<section>
+ <title>Reference Implementation</title>
+ <p>If you run into problems with the tutorial, compare your code with this <link href="image-viewer/image-viewer.cc">reference code</link>.</p>
+</section>
+
+<section>
+  <title>Next steps</title>
+  <p>Here are some ideas for how you can extend this simple demonstration:</p>
+  <list>
+   <item>
+   <p>Have the user select a directory rather than a file, and provide controls to cycle through all of the images in a directory.</p>
+   </item>
+   <item>
+   <p>Apply random filters and effects to the image when it is loaded and allow the user to save the modified image.</p>
+   <p><link href="http://www.gegl.org/api.html";>GEGL</link> provides powerful image manipulation capabilities.</p>
+   </item>
+   <item>
+   <p>Allow the user to load images from network shares, scanners, and other more complicated sources.</p>
+   <p>You can use <link href="http://library.gnome.org/devel/gio/unstable/";>GIO</link> to handle network file tranfers and the like, and <link href="http://library.gnome.org/devel/gnome-scan/unstable/";>GNOME Scan</link> to handle scanning.</p>
+   </item>
+  </list>
+</section>
+
+
+</page>
diff --git a/platform-demos/C/image-viewer/image-viewer.cc b/platform-demos/C/image-viewer/image-viewer.cc
new file mode 100644
index 0000000..d65a2dc
--- /dev/null
+++ b/platform-demos/C/image-viewer/image-viewer.cc
@@ -0,0 +1,67 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+#include <gtkmm.h>
+#include <iostream>
+
+#include "config.h"
+
+
+#ifdef ENABLE_NLS
+#  include <libintl.h>
+#endif
+
+
+static void
+on_open_image (Gtk::Image* image)
+{
+	Gtk::FileChooserDialog dialog("Open image",
+	                              Gtk::FILE_CHOOSER_ACTION_OPEN);
+	dialog.add_button (Gtk::Stock::OPEN,
+	                   Gtk::RESPONSE_ACCEPT);
+	dialog.add_button (Gtk::Stock::CANCEL,
+	                   Gtk::RESPONSE_CANCEL);
+
+	Glib::RefPtr<Gtk::FileFilter> filter =
+		Gtk::FileFilter::create();
+	filter->add_pixbuf_formats();
+	dialog.add_filter (filter);
+
+	switch (dialog.run())
+	{
+		case Gtk::RESPONSE_ACCEPT:
+			image->set(dialog.get_filename());
+			break;
+		default:
+			break;
+	}
+	dialog.hide();
+}
+
+int
+main (int argc, char *argv[])
+{
+	Gtk::Main kit(argc, argv);
+
+	Gtk::Window* main_win = new Gtk::Window(Gtk::WINDOW_TOPLEVEL);
+	main_win->set_title ("image-viewer-cpp");
+
+	Gtk::Box* box = new Gtk::Box();
+	box->set_orientation (Gtk::ORIENTATION_VERTICAL);
+	box->set_spacing(5);
+	main_win->add(*box);
+
+	Gtk::Image* image = new Gtk::Image();
+	box->pack_start (*image, true, true);
+	
+	Gtk::Button* button = new Gtk::Button("Open Imageâ?¦");
+	button->signal_clicked().connect (sigc::bind<Gtk::Image*>(sigc::ptr_fun(&on_open_image), image));
+	box->pack_start (*button, false, false);
+	
+	main_win->show_all();
+	
+	if (main_win)
+	{
+		kit.run(*main_win);
+	}
+	return 0;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]