Susanna Huhtanen
ihmis.suski@gmail.com 2012

# Soubor s hlavním programem

        V této části lekce sestavíme hlavní programový soubor aplikace s počasím. Abyste si mohli napsat a spustit kód příkladu sami, budete potřebovat v počítači nainstalovaný editor pro psaní kódu, terminál a GNOME 3.0 nebo novější. V této lekci budeme postupovat následujícími částmi:

          Skript pro spuštění aplikace
          Importované knihovny
          Vytvoření hlavního okna pro aplikaci
          Přidání mřížky a všech potřebných widgetů do ní
          Žádání o informace o počasí asynchronně
          Připojení signálů k tlačítkům a vstupním polím
          weatherapp.js

# Skript pro spuštění aplikace

#!/usr/bin/gjs

Tento řádek říká, jak spustit skript. Musí být prvním řádek v souboru s kódem a soubor musí být spustitelný. Abyste získali práva na spuštění, jděte do terminálu a ve správné složce spusťte: chmod +x název_skriptu. Nebo můžete použít grafického správce souborů. Přejděte do správné složky s vašim kódem, klikněte na soubor s kódem pravým tlačítkem, zvolte vlastnosti, klikněte na kartu oprávnění a zaškrtněte políčko, které povoluje spuštění souboru jako programu.

# Importované knihovny

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

Abychom získali funkční program, potřebujeme naimportovat GObject Introspection, což je knihovna, kterou využíváme. Pro funkční uživatelské rozhraní potřebujeme také Gtk. Gtk se importuje hned na začátku, takže jej můžeme použít kdekoliv. Importujeme také naši vlastní místní knihovnu geoname napsanou v jazyce JavaScript, protože ji zde využijeme.

# Vytvoření hlavního okna pro aplikaci

// Inicializuje GTK Gtk.init(null, 0); // Vytvoří okno, pojmenuje jej a napojí tlačítko „X“ na funkci pro ukončení // Pamatujte, že „window“ je rezervované slovo var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); weatherwindow.title = "Today’s weather"; // Okno přijímá jen jeden widget a název. Pro sloužitější struktury slouží Gtk.boxes apod. weatherwindow.connect("destroy", function(){Gtk.main_quit()});

weatherwindow.show_all(); // A spustí ji Gtk.main();

# Přidání mřížky a všech potřebných widgetů do ní

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

// Zde inicializujeme ikony, ale rozhodne se až později v geonames.js. var weatherIcon = new Gtk.Image();

// Nastaví nějaké popisky do vašeho okna 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)

V této části vytvoříme mřížku, kterou se chystáme použít k umístění widgetů. Všechna tlačítka, popisky a vstupní pole jsou inicializována a umístěna v mřížce. Jak je vidět z umístění různých widgetů, nemusí se vztahovat jen k jednomu widgetu. V tuto chvíli nemají některé popisky žádný obsah. Ten bude doplněn později. Když aplikaci v této fázi spustíte, budete mít připravené uživatelské rozhraní, ale widgety nabudou nikam napojeny. Z tohoto důvodu potřebujeme nejprve sestavit místní knihovnu pro vyhledávání počasí a pak získávat informace, což chceme dělat asynchronně. Až budeme mít naši místní knihovnu připravenou, můžeme ji napojit na potřebné widgety.

# Žádání o informace o počasí asynchroně

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

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

GeoNames.getWeather(function(error, weather) { /* Toto funguje trochu jako signály. Tento kód bude spuštěn, kdykoliv budeme mít informaci o počasí. */ 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") // ... }); }

Tato funkce je určena k ptaní se na informace o počasí a k odpovídající aktualizaci popisků a ikon. Na začátku této funkce získáme vstup od uživatele udávající, na co se ptát. Takže zde konečně poprvé použijeme naši vlastní knihovnu a přiřadíme ji do proměnné `GeoNames`. Jakmile přiřadíme `WeatherService`, předáme ji obsluhu. První co uděláme v GeoNames, je dotaz na počasí. Vše, co se stane po `GeoNames.getWeather(function(error, weather)`, může být jen to, že dostaneme chybovou zprávu nebo informace o počasí. Pokud nic z toho nedorazí, bude zbytek programu normálně fungovat, včetně `main_Quit`.

# Připojení signálů k tlačítkům a vstupním polím

entry.connect("key_press_event", function(widget, event) { if (entry.get_text().length === 4) { // To už by stačilo getWeatherForStation(); } return false; });

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

A nakonec zde máme propojení, která zajistí, že celá aplikace poběží jak má. Propojíme vstupní pole a tlačítko, aby dělali to stejné, získali informace o počasí. Nebude tak záležet na tom, jestli zmáčknete Enter nebo kliknete na tlačítko search.

# Weatherapp.js

Soubor Weatherapp.js vypadá nějak takto:

#!/usr/bin/gjs // Předchozí řádek je tzv. "hash bang", který říká, jak skript spustit // Upozorňujeme, že skript musí být spustitelný // (v terminálu ve správné složce proveďte: chmod +x název_skriptu)

var Gtk = imports.gi.Gtk;

const WeatherService = imports.geonames; // Připraví vaši vlastní knihovnu ze stejné složky (nastaveno v GJS_PATH) // Pokud používáte autotools, .desktop se o to postará

// Inicializuje GTK Gtk.init(null, 0); // Vytvoří okno, pojmenuje jej a napojí tlačítko „X“ na funkci pro ukončení // Pamatujte, že „window“ je rezervované slovo var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); weatherwindow.title = "Today’s weather"; // Okno přijímá jen jeden widget a název. Pro sloužitější struktury slouží Gtk.boxes apod. weatherwindow.connect("destroy", function(){Gtk.main_quit()}); // Zde inicializujeme ikony, ale rozhodne se až později v geonames.js.

var weatherIcon = new Gtk.Image();

// Nastaví nějaké popisky do vašeho okna 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!"});

// Nějaké počasí

entry.connect("key_press_event", function(widget, event) { // FIXME: Získat počasí klávesou Enter (key 13) if (entry.get_text().length === 4) { // To už by stačilo 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) { // Toto funguje trochu jako signály. Tento kód bude spuštěn, kdykoliv budeme mít informaci o počasí 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(); // A spustí ji Gtk.main();

Nechte běžet, dokud nebudou připravené všechny soubory autotools:

     $  GJS_PATH=`pwd` gjs weatherapp.js

Tento příkaz použijte v terminálu při vývoji svých modulů. Když zavoláte svůj program tímto způsobem, bude vědět, kde má hledat vaše vlastí knihovny v jazyce JavaScript, v tomto případě geonames.js.