[gnome-devel-docs] tutorials <javascript>: Added chapter two about Grids, Images, and Labels



commit 523d84dbd2d5e47732f92e099d2d6204b16d5748
Author: Taryn Fox <jewelfox fursona net>
Date:   Tue Jul 31 07:51:37 2012 -0400

    tutorials <javascript>: Added chapter two about Grids, Images, and Labels

 platform-demos/C/02_welcome_to_the_grid.js.page    |  281 ++++++++++++++++++++
 platform-demos/C/media/02_jsgrid_01.png            |  Bin 0 -> 41051 bytes
 platform-demos/C/media/02_jsgrid_02.png            |  Bin 0 -> 40900 bytes
 platform-demos/C/media/02_jsgrid_03.png            |  Bin 0 -> 42873 bytes
 platform-demos/C/media/02_jsgrid_04.png            |  Bin 0 -> 42557 bytes
 platform-demos/C/media/02_jsgrid_05.png            |  Bin 0 -> 42805 bytes
 platform-demos/C/media/02_jsgrid_06.png            |  Bin 0 -> 43001 bytes
 platform-demos/C/media/02_jsgrid_07.png            |  Bin 0 -> 42629 bytes
 platform-demos/C/media/02_jsgrid_08.png            |  Bin 0 -> 41917 bytes
 platform-demos/C/samples/02_welcome_to_the_grid.js |   88 ++++++
 10 files changed, 369 insertions(+), 0 deletions(-)
---
diff --git a/platform-demos/C/02_welcome_to_the_grid.js.page b/platform-demos/C/02_welcome_to_the_grid.js.page
new file mode 100644
index 0000000..ee03fc8
--- /dev/null
+++ b/platform-demos/C/02_welcome_to_the_grid.js.page
@@ -0,0 +1,281 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<page xmlns="http://projectmallard.org/1.0/";
+      xmlns:xi="http://www.w3.org/2001/XInclude";
+      type="topic" style="task"
+      id="02_welcome_to_the_grid.js">
+  <info>
+    <link type="guide" xref="beginner.js#tutorials" />
+    <link type="seealso" xref="grid.js" />
+    <link type="seealso" xref="image.js" />
+    <link type="seealso" xref="label.js" />
+    <revision version="0.1" date="2012-07-28" status="draft"/>
+
+    <credit type="author copyright">
+      <name>Taryn Fox</name>
+      <email>jewelfox fursona net</email>
+      <years>2012</years>
+    </credit>
+
+    <desc>Learn how to lay out UI components, like Images and Labels.</desc>
+  </info>
+
+  <title>2. Welcome to the Grid</title>
+  <synopsis>
+    <p>This tutorial will show you how to create basic widgets, or parts of the GNOME user interface, like Images and Labels. You'll then learn how to arrange them all in a Grid, which lets you put widgets exactly where you want them.</p>
+    <note style="warning"><p>Have you taken <link xref="hellognome.js">the first tutorial in this series</link> already? You'll want to do so before continuing.</p></note>
+  </synopsis>
+
+  <links type="section" />
+
+  <section id="native">
+    <title>Going native</title>
+
+    <p>In the last tutorial, we created what was basically a GNOME window frame for a web app. All the GNOME-specific code we needed to learn revolved around putting the WebView -- the widget containing our application -- into an ApplicationWindow, and telling it to display. The application itself was written in HTML and JavaScript, just like most pages on the web.</p>
+    <p>This time, we're going to use only native GNOME widgets. A widget is just a thing, like a checkbox or picture, and GNOME has a wide variety of them to choose from. We call them "native" widgets to distinguish them from things like the button and header in the web app we wrote. Because instead of using web code, these are going to be 100 percent GNOME, using Gtk+.</p>
+    <note style="tip"><p>Gtk+ stands for "GIMP Toolkit." It's like a toolbox of widgets that you can reach into, while building your applications. It was originally written for <link href="http://www.gimp.org/";>the GIMP,</link> which is a free software image editor.</p></note>
+  </section>
+
+  <section id="setup">
+    <title>Setting up our application</title>
+
+    <p>Before we dig out any widgets from the Gtk+ toolbox, we first need to write the basic boilerplate code that our application requires.</p>
+    <code mime="text/javascript"><![CDATA[
+#!/usr/bin/gjs
+
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+]]></code>
+    <p>This part always goes at the start of your code. Depending on what you'll be doing with it, you may want to declare more imports here. What we're writing today is pretty basic, so these are all we need; <input>Gtk</input> for the widgets, and <input>Lang</input> so we can use <input>Lang.bind</input> to connect our application's <input>activate</input> and <input>startup</input> signals to the requisite functions.</p>
+    <p>Speaking of which:</p>
+    <code mime="text/javascript"><![CDATA[
+const WelcomeToTheGrid = new Lang.Class({
+    Name: 'Welcome to the Grid',
+
+    // Create the application itself
+    _init: function() {
+        this.application = new Gtk.Application({
+            application_id: 'org.example.jswelcometothegrid'
+        });
+
+        // Connect 'activate' and 'startup' signals to the callback functions
+        this.application.connect('activate', Lang.bind(this, this._onActivate));
+        this.application.connect('startup', Lang.bind(this, this._onStartup));
+    },
+
+    // Callback function for 'activate' signal presents windows when active
+    _onActivate: function() {
+        this._window.present();
+    },
+
+    // Callback function for 'startup' signal builds the UI
+    _onStartup: function() {
+        this._buildUI ();
+    },
+]]></code>
+    <p>This is the start of the application itself, and the <input>_init</input> function which creates it. It tells <input>_buildUI</input> to create an ApplicationWindow, which we're going to call <input>_window</input>, and it tells our window to present itself whenever needed.</p>
+    <p>This part, again, is pretty much copy-and-paste, but you always want to choose a new <input>application_id</input> each time. Don't be afraid to make it long and descriptive; every GNOME application in the entire world needs a unique one.</p>
+
+    <code mime="text/javascript"><![CDATA[
+    // Build the application's UI
+    _buildUI: function() {
+
+        // Create the application window
+        this._window = new Gtk.ApplicationWindow({
+            application: this.application,
+            window_position: Gtk.WindowPosition.CENTER,
+            border_width: 10,
+            title: "Welcome to the Grid"});
+]]></code>
+    <p>Finally, we start off the <input>_buildUI</input> function by creating a new ApplicationWindow. We specify that it goes with this application, that it should appear in the center of the screen, and that there should be at least 10 pixels between the outside edge and any widgets inside of it. We also give it a title, which will appear at the top of the window.</p>
+  </section>
+
+  <section id="toolbox">
+    <title>Reaching into the Gtk+ toolbox</title>
+    <p>What widgets should we use? Well, let's say we want to write an application that looks like this:</p>
+
+    <media type="image" mime="image/png" src="media/02_jsgrid_01.png"/>
+
+    <p>We're going to need, at the very least, a picture and a text label to go with it. Let's start with the picture:</p>
+    <code mime="text/javascript"><![CDATA[
+        // Create an image
+        this._image = new Gtk.Image ({ file: "gnome-image.png" });
+]]></code>
+
+    <p>You can download the image file used in this example <link href="https://live.gnome.org/TarynFox?action=AttachFile&amp;do=get&amp;target=gnome-image.png";>here.</link> Be sure to put it in the same directory as the code you're writing.</p>
+
+    <code mime="text/javascript"><![CDATA[
+        // Create a label
+        this._label = new Gtk.Label ({ label: "Welcome to GNOME, too!" });
+]]></code>
+    <p>That code adds in the label beneath. You can see how we create widgets, here; each one is a part of Gtk, and we can give it properties that customize how it behaves. In this case, we set the Image's <input>file</input> property to be the filename of the picture we want, and the Label's <input>label</input> property to be the sentence that we want beneath the picture.</p>
+    <note style="tip"><p>Yes, <link href="http://knowyourmeme.com/memes/xzibit-yo-dawg";>it sounds redundant</link> for a Label to have a <input>label</input> property, but it's not. Other widgets that contain text have a <input>label</input> property, so it's <em>consistent</em> for the Label widget to have one too.</p></note>
+    <p>We can't just add these widgets to our window in order, though, the same way HTML elements appear in the order you write them. That's because an ApplicationWindow can only contain one widget.</p>
+    <p>How do we get around that? By making that one widget a container widget, which can hold more than one widget and organize them inside it. Behold: The Grid.</p>
+    <code mime="text/javascript"><![CDATA[
+        // Create the Grid
+        this._grid = new Gtk.Grid ();
+]]></code>
+
+    <p>We're not giving it any properties yet. Those will come later, as we learn how to use the Grid's powers. First, let's attach the Image and Label we made to our Grid.</p>
+    <code mime="text/javascript"><![CDATA[
+        // Attach the image and label to the grid
+        this._grid.attach (this._image, 0, 0, 1, 1);
+        this._grid.attach (this._label, 0, 1, 1, 1);
+]]></code>
+
+    <p>This code looks awfully complicated, but it's not. Here's what those numbers mean:</p>
+    <list type="numbered">
+      <item><p>The <em>first</em> number is what left-to-right position to put things in, starting from 0. Any widget that uses a 0 here goes all the way to the left.</p></item>
+      <item><p>The <em>second</em> number is what top-to-botton position to put a given widget in, starting from 0. The Label goes beneath the Image, so we give the Image a 0 and the Label a 1 here.</p></item>
+      <item><p>The <em>third</em> and <em>fourth</em> numbers are how many columns and rows a widget should take up. We'll see how these work in a minute.</p></item>
+    </list>
+
+    <code mime="text/javascript"><![CDATA[
+        // Add the grid to the window
+        this._window.add (this._grid);
+
+        // Show the window and all child widgets
+        this._window.show_all();
+    }
+
+});
+
+// Run the application
+let app = new WelcomeToTheGrid ();
+app.application.run (ARGV);
+]]></code>
+    <p>Now that we've created the Grid and attached all our widgets to it, we add it to the window and tell the window to show itself, as the last part of the <input>_buildUI</input> function. As always, to finish up we create a new instance of the application's class and tell it to run.</p>
+    <p>Save your application as <input>welcome_to_the_grid.js</input>. Then, to run your application just open a terminal, go to the directory where your application is at, and type</p>
+      <screen> <output style="prompt">$ </output><input>gjs welcome_to_the_grid.js</input> </screen>
+
+    <media type="image" mime="image/png" src="media/02_jsgrid_02.png"/>
+
+    <p>There we go! But wait. That doesn't look right. Why is the Label crammed up next to the Image like that? That doesn't look as nice, and it makes it harder to read. What can we do about this?</p>
+  </section>
+
+  <section id="tweaking">
+    <title>Tweaking the Grid</title>
+
+    <p>One thing we can do, is we can give the Label a <input>margin_top</input> property when we create it. This works sort of like setting a margin for an HTML element using inline CSS styling.</p>
+    <code mime="text/javascript"><![CDATA[
+        // Create a label
+        this._label = new Gtk.Label ({
+            label: "Welcome to GNOME, too!",
+            margin_top: 20 });
+]]></code>
+
+    <p>Of course, if we do that then if we replace the Label with something else -- or add in another widget -- then we have to repeat the margin_top on it too. Otherwise we end up with something like this:</p>
+    <media type="image" mime="image/png" src="media/02_jsgrid_03.png"/>
+
+    <p>We could give the Image a <input>margin_bottom</input> property, but that won't work when the new Label is in a separate column. So how about we try this instead:</p>
+    <code mime="text/javascript"><![CDATA[
+        // Create the Grid
+        this._grid = new Gtk.Grid ({
+            row_spacing: 20 });
+]]></code>
+
+    <p>That makes it so that there are always 20 pixels of space in between each horizontal row.</p>
+    <note style="tip"><p>Yes, you can also set the <input>column_spacing</input> property on a Grid, or the <input>margin_left</input> and <input>margin_right</input> properties on any widget. Try them out, if you like!</p></note>
+  </section>
+
+  <section id="adding">
+    <title>Adding more widgets</title>
+
+    <p>If we did want to add a second Label, how would we do it so that it actually looked like it belonged there? One way is to center the Image on top, so that it's above both Labels instead of just the one on the left. That's where those other numbers in the Grid's <input>attach</input> method come in:</p>
+    <code mime="text/javascript"><![CDATA[
+        // Create a second label
+        this._labelTwo = new Gtk.Label ({
+            label: "The cake is a pie." });
+
+        // Attach the image and labels to the grid
+        this._grid.attach (this._image, 0, 0, 2, 1);
+        this._grid.attach (this._label, 0, 1, 1, 1);
+        this._grid.attach (this._labelTwo, 1, 1, 1, 1);
+]]></code>
+
+    <p>After we create the second Label, we attach it to the Grid to the right of the first Label. Remember, the first two numbers count columns and rows from left to right and top to bottom, starting with 0. So if the first Label is in column 0 and row 1, we can put the second in column 1 and row 1 to put it to the right of the first Label.</p>
+    <p>Note the number 2 in the <input>attach</input> statement for the Image. That's what does the trick here. That number is how many columns the Image spans, remember? So when we put it together, we get something like this:</p>
+    <media type="image" mime="image/png" src="media/02_jsgrid_04.png"/>
+
+    <p>There are two things you should take note of, here.</p>
+    <list>
+      <item><p>Setting the Image to span two columns doesn't stretch the picture itself horizontally. Instead, it stretches the invisible box taken up by the Image widget to fill both columns, then places the Image in the center of that box.</p></item>
+      <item><p>Even though we've set the Grid's <input>row_spacing</input> and the ApplicationWindow's <input>border_width</input> properties, we haven't yet set anything that puts a border in between the two Labels. They were separate earlier when the Image was in only one column, but now that it spans both GNOME doesn't see a reason to keep them apart.</p></item>
+    </list>
+
+    <p>There are at least three ways we can get around that last one. First, we can set a <input>margin_left</input> or <input>margin_right</input> on one of the Labels:</p>
+    <media type="image" mime="image/png" src="media/02_jsgrid_05.png"/>
+
+    <p>Second, we can set the Grid's <input>column_homogenous</input> property to <input>true</input>.</p>
+    <code mime="text/javascript"><![CDATA[
+        // Create the Grid
+        this._grid = new Gtk.Grid ({
+            column_homogeneous: true,
+            row_spacing: 20 });
+]]></code>
+
+    <p>That makes it look something like this:</p>
+    <media type="image" mime="image/png" src="media/02_jsgrid_06.png"/>
+
+    <p>And third, we can set the Grid's <input>column_spacing</input> property, the same way we set its <input>row_spacing</input>.</p>
+    <code mime="text/javascript"><![CDATA[
+        // Create the Grid
+        this._grid = new Gtk.Grid ({
+            column_spacing: 20,
+            row_spacing: 20 });
+]]></code>
+    <p>That makes it look like this:</p>
+    <media type="image" mime="image/png" src="media/02_jsgrid_07.png"/>
+  </section>
+
+  <section id="stock">
+    <title>Using stock images</title>
+
+    <p>GNOME has a lot of stock images on hand already, that we can use if we don't feel like creating our own or if we want a universally-recognized icon. Here's how we create a stock image, compared to how we create a normal one:</p>
+    <code mime="text/javascript"><![CDATA[
+        // Create an image
+        this._image = new Gtk.Image ({ file: "gnome-image.png" });
+
+        // Create a second image using a stock icon
+        this._icon = new Gtk.Image ({ stock: 'gtk-about' });
+]]></code>
+    <p>After that, we attach it to the Grid to the left of the first Label. (We aren't using the second one for this example.)</p>
+    <code mime="text/javascript"><![CDATA[
+        // Attach the images and label to the grid
+        this._grid.attach (this._image, 0, 0, 2, 1);
+        this._grid.attach (this._icon,  0, 1, 1, 1);
+        this._grid.attach (this._label, 1, 1, 1, 1);
+]]></code>
+    <p>That gives us this, when we run it:</p>
+    <media type="image" mime="image/png" src="media/02_jsgrid_08.png"/>
+
+    <p>That's what the stock "About" icon looks like. You can see a list of all the stock items starting with <input>gtk-about</input> in <link href="http://developer.gnome.org/gtk/2.24/gtk-Stock-Items.html#GTK-STOCK-ABOUT:CAPS";>GNOME's developer documentation.</link> It was written for C programmers, but you don't need to know C to use it; just look at the part in quotation marks, like "gtk-about", and copy that part to use the icon next to it.</p>
+    <note style="tip"><p>We put single quotes around 'gtk-about' here because, unlike text strings that have double quotes around them, that part will never need to be translated into another language. In fact, if it <em>were</em> translated it'd break the icon, because its name is still "gtk-about" no matter which language you speak.</p></note>
+  </section>
+
+
+  <section id="next">
+    <title>What's next?</title>
+    <p>Before we go on to the next tutorial, let's try something a little different:</p>
+    <code mime="text/javascript"><![CDATA[
+        // Create a button
+        this._button = new Gtk.Button ({
+            label: "Welcome to GNOME, too!"});
+
+        // Attach the images and button to the grid
+        this._grid.attach (this._image,  0, 0, 2, 1);
+        this._grid.attach (this._icon,   0, 1, 1, 1);
+        this._grid.attach (this._button, 1, 1, 1, 1);
+]]></code>
+
+    <p>That's right, we turned the Label into a Button just by changing the name! If you run the application and click on it, though, you'll find that it doesn't do anything. How do we make our Button do something? That's what we'll find out, in <link xref="getting_the_signal.js">our next tutorial.</link></p>
+    <p>If you like, feel free to spend some time experimenting with Grids, Labels, and Images, including stock images.</p>
+    <note style="tip"><p>One trick you can use to make more complex layouts is to nest Grids inside of each other. This lets you group together related widgets, and rearrange them easily. Take a look at the <link xref="radiobutton.js">RadioButton</link> code sample if you'd like to see how this is done.</p></note>
+  </section>
+
+  <section id="complete">
+    <title>Complete code sample</title>
+<code mime="text/javascript" style="numbered"><xi:include href="samples/02_welcome_to_the_grid.js" parse="text"><xi:fallback/></xi:include></code>
+  </section>
+
+</page>
diff --git a/platform-demos/C/media/02_jsgrid_01.png b/platform-demos/C/media/02_jsgrid_01.png
new file mode 100644
index 0000000..59c1ced
Binary files /dev/null and b/platform-demos/C/media/02_jsgrid_01.png differ
diff --git a/platform-demos/C/media/02_jsgrid_02.png b/platform-demos/C/media/02_jsgrid_02.png
new file mode 100644
index 0000000..f284660
Binary files /dev/null and b/platform-demos/C/media/02_jsgrid_02.png differ
diff --git a/platform-demos/C/media/02_jsgrid_03.png b/platform-demos/C/media/02_jsgrid_03.png
new file mode 100644
index 0000000..7043cb2
Binary files /dev/null and b/platform-demos/C/media/02_jsgrid_03.png differ
diff --git a/platform-demos/C/media/02_jsgrid_04.png b/platform-demos/C/media/02_jsgrid_04.png
new file mode 100644
index 0000000..c73becc
Binary files /dev/null and b/platform-demos/C/media/02_jsgrid_04.png differ
diff --git a/platform-demos/C/media/02_jsgrid_05.png b/platform-demos/C/media/02_jsgrid_05.png
new file mode 100644
index 0000000..872db2e
Binary files /dev/null and b/platform-demos/C/media/02_jsgrid_05.png differ
diff --git a/platform-demos/C/media/02_jsgrid_06.png b/platform-demos/C/media/02_jsgrid_06.png
new file mode 100644
index 0000000..af866fe
Binary files /dev/null and b/platform-demos/C/media/02_jsgrid_06.png differ
diff --git a/platform-demos/C/media/02_jsgrid_07.png b/platform-demos/C/media/02_jsgrid_07.png
new file mode 100644
index 0000000..2cdd9e3
Binary files /dev/null and b/platform-demos/C/media/02_jsgrid_07.png differ
diff --git a/platform-demos/C/media/02_jsgrid_08.png b/platform-demos/C/media/02_jsgrid_08.png
new file mode 100644
index 0000000..113927a
Binary files /dev/null and b/platform-demos/C/media/02_jsgrid_08.png differ
diff --git a/platform-demos/C/samples/02_welcome_to_the_grid.js b/platform-demos/C/samples/02_welcome_to_the_grid.js
new file mode 100644
index 0000000..c282d66
--- /dev/null
+++ b/platform-demos/C/samples/02_welcome_to_the_grid.js
@@ -0,0 +1,88 @@
+#!/usr/bin/gjs
+
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const WelcomeToTheGrid = new Lang.Class({
+    Name: 'Welcome to the Grid',
+
+    // Create the application itself
+    _init: function() {
+        this.application = new Gtk.Application({
+            application_id: 'org.example.jswelcometothegrid'
+        });
+
+    // Connect 'activate' and 'startup' signals to the callback functions
+    this.application.connect('activate', Lang.bind(this, this._onActivate));
+    this.application.connect('startup', Lang.bind(this, this._onStartup));
+    },
+
+    // Callback function for 'activate' signal presents windows when active
+    _onActivate: function() {
+        this._window.present();
+    },
+
+    // Callback function for 'startup' signal builds the UI
+    _onStartup: function() {
+        this._buildUI ();
+    },
+
+
+
+    // Build the application's UI
+    _buildUI: function() {
+
+        // Create the application window
+        this._window = new Gtk.ApplicationWindow({
+            application: this.application,
+            window_position: Gtk.WindowPosition.CENTER,
+            border_width: 10,
+            title: "Welcome to the Grid"});
+
+        // Create the Grid
+        this._grid = new Gtk.Grid ({
+            // column_homogeneous: true,
+            // column_spacing: 20,
+            row_spacing: 20 });
+
+        // Create an image
+        this._image = new Gtk.Image ({ file: "gnome-image.png" });
+
+        // Create a second image using a stock icon
+        this._icon = new Gtk.Image ({ stock: 'gtk-about' });
+
+        // Create a label
+        this._label = new Gtk.Label ({
+            label: "Welcome to GNOME, too!",
+            /* margin_top: 20 */ });
+
+        /* Create a second label
+        this._labelTwo = new Gtk.Label ({
+            label: "The cake is a pie." }); */
+
+        /* Create a button
+        this._button = new Gtk.Button ({
+            label: "Welcome to GNOME, too!"}); */
+
+        // Attach the images and button to the grid
+        this._grid.attach (this._image,  0, 0, 2, 1);
+        this._grid.attach (this._icon,   0, 1, 1, 1);
+        this._grid.attach (this._label,  1, 1, 1, 1);
+
+        // this._grid.attach (this._label, 0, 1, 1, 1);
+        // this._grid.attach (this._labelTwo, 1, 1, 1, 1);
+
+        // this._grid.attach (this._button, 1, 1, 1, 1);
+
+        // Add the grid to the window
+        this._window.add (this._grid);
+
+        // Show the window and all child widgets
+        this._window.show_all();
+    }
+
+});
+
+// Run the application
+let app = new WelcomeToTheGrid ();
+app.application.run (ARGV);



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