Susanna Huhtanen
ihmis.suski@gmail.com 2012
Daniel Mustieles
daniel.mustieles@gmail.com 2011 - 2014
Nicolás Satragno
nsatragno@gmail.com 2012 - 2013
Jorge González
jorgegonz@svn.gnome.org 2011

# El archivo del programa principal

        En esta parte de la guía se construirá el archivo del programa principal de la aplicación del clima. Para escribir y ejecutar todos los ejemplos de código necesita un editor de texto en el que escribir el código, una terminal y GNOME 3 o superior instalado en su equipo. En esta guía se verán las siguientes partes:

          Script para ejecutar la aplicación
          Bibliotecas que importar
          Crear la ventana principal de la aplicación
          Añadir una rejilla y todos los widgets necesarios en ella
          Solicitar la información meteorológica de manera asíncrona
          Conectar las señales a un botón y a una entrada
          weatherapp.js

# Script para ejecutar la aplicación

#!/usr/bin/gjs

Esta línea indica cómo ejecutar el script. Debe ser la primera línea del código y debe ser ejecutable. Para obtener permisos de ejecución vaya a la terminal y ejecute lo siguiente en la carpeta adecuada: chmod +x nombrescript. También puede usar el gestor de archivo. Simplemente vaya a la carpeta donde está el código, pulse con el botón derecho sobre el archivo de código y elija «Propiedades», pulse en la pestaña «Permisos» y marque la casilla para permitir ejecutar el archivo como un programa.

# Bibliotecas que importar

var Gtk = imports.gi.Gtk; const WeatherService = imports.geonames;

Para que el programa funcione se debe importar una biblioteca de introspección de GObject. Para que funcione la IU se necesita GTK+, que se importa al inicio, por lo que está en uso en todos los sitios. También se importa la biblioteca local en JavaScript geonames para usarla aquí.

# Crear la ventana principal de la aplicación

// Initialize the gtk Gtk.init(null, 0); //create your window, name it and connect the x to quit function. Remember that window is a taken word var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); weatherwindow.title = "Todays weather"; //Window only accepts one widget and a title. Further structure with Gtk.boxes of similar weatherwindow.connect("destroy", function(){Gtk.main_quit()});

weatherwindow.show_all(); //and run it Gtk.main();

# Añadir una rejilla y todos los widgets necesarios en ella

var grid = new Gtk.Grid(); weatherwindow.add(grid);

//We initialize the icon here, but deside the file later in geonames.js. var weatherIcon = new Gtk.Image();

//Set some labels to your window var label1 = new Gtk.Label({label: ""}); var label2 = new Gtk.Label({label: "Looking in the sky..."}); var label3 = new Gtk.Label({label: ""});

var entry = new Gtk.Entry(); entry.set_width_chars(4); entry.set_max_length(4); var label4 = new Gtk.Label({label: "Enter ICAO station for weather: "}); var button1 = new Gtk.Button({label: "search!"});

grid.attach(label4, 2, 1, 1, 1); grid.attach_next_to(label1,label4,3,1,1); grid.attach_next_to(label2,label1,3,1,1); grid.attach_next_to(label3,label2,3,1,1); grid.attach_next_to(entry,label4,1,1,1); grid.attach_next_to(button1,entry,1,1,1); grid.attach_next_to(weatherIcon,label2,1,1,1)

En esta sección se crea la rejilla que se usará para posicionar los widgets. Todos los botones, etiquetas y entradas se inicializan y colocan en la rejilla. Como se puede ver en la colocación de los diferentes widgets, no es necesario relacionarlo con un único widget. En este punto, algunas de las etiquetas no tienen contenido. El contenido para esos widgets se aplica más tarde. Si ejecuta la aplicación en este punto, tendrá lista la IU, pero los widgets no estarán conectados con nada. Para esto, se necesita construir primero la biblioteca de búsqueda de tiempo local, y obtener la información que se necesita de manera asíncrona. Cuando la biblioteca local esté lista, se podrá conectar a los widgets necesarios.

# Solicitar la información meteorológica de manera asíncrona

function getWeatherForStation() { var station = entry.get_text();

var GeoNames = new WeatherService.GeoNames(station); //"EFHF";

GeoNames.getWeather(function(error, weather) { //this here works bit like signals. This code will be run when we have weather. if (error) { label2.set_text("Suggested ICAO station does not exist Try EFHF"); return; } weatherIcon.file = GeoNames.getIcon(weather);

label1.set_text("Temperature is " + weather.weatherObservation.temperature + " degrees."); if (weather.weatherObservation.weatherCondition !== "n/a"){ label2.set_text("Looks like there is " + weather.weatherObservation.weatherCondition + " in the sky."); } else { label2.set_text("Looks like there is " + weather.weatherObservation.clouds + " in the sky."); } label3.set_text("Windspeed is " + weather.weatherObservation.windSpeed + " m/s") // ... }); }

Esta función se dedica a llamar a la información meteorológica y a actualizar las etiquetas y los iconos correctamente. Al principio de la función, se obtiene la entrada del usuario para la búsqueda. Por lo tanto, la primera vez se usa la biblioteca propia y se asigna a la variable GeoNames. Al asignar WeatherService se da la estación. Lo primero que se hace con GeoNames es solicitar el tiempo. Todo lo que sucede después de GeoNames.getWeather(function(error, weather) ocurre sólo si se obtiene un mensaje de error o información del tiempo incorrecta. Si no pasa nada de esto, el resto del programa funciona de manera normal, por lo que «main_Quit» funciona.

# Conectar señales a un botón y a una entrada

entry.connect("key_press_event", function(widget, event) { if (entry.get_text().length === 4) { // Enough is enough getWeatherForStation(); } return false; });

button1.connect("clicked", function(){ getWeatherForStation(); });

Finalmente se tienen las conexiones que hacen que la aplicación completa funcione como debería. Se han conectado la entrada y el botón para que hagan la misma cosa, obtener el tiempo. Por lo tanto, no importa si pulsa el botón o si pulsa «Intro».

# Weatherapp.js

El archivo Weatherapp.js se parece a esto:

#!/usr/bin/gjs //The previous line is a hash bang tells how to run the script. // Note that the script has to be executable (run in terminal in the right folder: chmod +x scriptname)

var Gtk = imports.gi.Gtk;

const WeatherService = imports.geonames; //Bring your own library from same folder (as set in GJS_PATH). If using autotools .desktop will take care of this

// Initialize the gtk Gtk.init(null, 0); //create your window, name it and connect the x to quit function. Remember that window is a taken word var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); weatherwindow.title = "Todays weather"; //Window only accepts one widget and a title. Further structure with Gtk.boxes of similar weatherwindow.connect("destroy", function(){Gtk.main_quit()}); //We initialize the icon here, but deside the file later in geonames.js.

var weatherIcon = new Gtk.Image();

//Set some labels to your window var label1 = new Gtk.Label({label: ""}); var label2 = new Gtk.Label({label: "Looking in the sky..."}); var label3 = new Gtk.Label({label: ""});

var grid = new Gtk.Grid(); weatherwindow.add(grid);

var entry = new Gtk.Entry(); entry.set_width_chars(4); entry.set_max_length(4); var label4 = new Gtk.Label({label: "Enter ICAO station for weather: "}); var button1 = new Gtk.Button({label: "search!"});

//some weather

entry.connect("key_press_event", function(widget, event) { // FIXME: Get weather on enter (key 13) if (entry.get_text().length === 4) { // Enough is enough getWeatherForStation(); } return false; });

button1.connect("clicked", function(){ getWeatherForStation(); });

function getWeatherForStation() { var station = entry.get_text();

var GeoNames = new WeatherService.GeoNames(station); //"EFHF";

GeoNames.getWeather(function(error, weather) { //this here works bit like signals. This code will be run when we have weather. if (error) { label2.set_text("Suggested ICAO station does not exist Try EFHF"); return; } weatherIcon.file = GeoNames.getIcon(weather);

label1.set_text("Temperature is " + weather.weatherObservation.temperature + " degrees."); if (weather.weatherObservation.weatherCondition !== "n/a"){ label2.set_text("Looks like there is " + weather.weatherObservation.weatherCondition + " in the sky."); } else { label2.set_text("Looks like there is " + weather.weatherObservation.clouds + " in the sky."); } label3.set_text("Windspeed is " + weather.weatherObservation.windSpeed + " m/s") // ... }); }

grid.attach(label4, 2, 1, 1, 1); grid.attach_next_to(label1,label4,3,1,1); grid.attach_next_to(label2,label1,3,1,1); grid.attach_next_to(label3,label2,3,1,1); grid.attach_next_to(entry,label4,1,1,1); grid.attach_next_to(button1,entry,1,1,1); grid.attach_next_to(weatherIcon,label2,1,1,1) weatherwindow.show_all(); //and run it Gtk.main();

Ejecútela hasta que tenga listos todos los archivos de autotools:

     $  GJS_PATH=`pwd` gjs weatherapp.js

Use este comando en la terminal cuando desarrolle sus módulos. Al llamar a su programa de este modo, sabe dónde encontrar las bibliotecas de JavaScript personalizadas, (geonames.js en este caso).