Susanna Huhtanen
ihmis.suski@gmail.com 2012
Ελληνική μεταφραστική ομάδα GNOME
team@gnome.gr 2012-2015
Δημήτρης Σπίγγος
dmtrs32@gmail.com 2012, 2013
Μαρία Θουκιδίδου
marablack3@gmail.com 2014
Θάνος Τρυφωνίδης
tomtryf@gmail.com 2014, 2015

# Το κύριο αρχείο του προγράμματος

        Σε αυτό το τμήμα του οδηγού θα κατασκευάσουμε το κύριο αρχείο του προγράμματος της εφαρμογής καιρού. Για να γράψετε και να τρέξετε όλα τα παραδείγματα κώδικα οι ίδιοι, χρειαζόσαστε έναν επεξεργαστή για το γράψιμο του κώδικα, τερματικό και GNOME 3 ή μεταγενέστερο εγκατεστημένο στον υπολογιστή σας. Σε αυτό το τμήμα θα εξετάσουμε τα παρακάτω μέρη:

          Σενάριο για εκτέλεση της εφαρμογής
          Βιβλιοθήκες για εισαγωγή
          Δημιουργία του κύριου παραθύρου για την εφαρμογή
          Προσθήκη πλέγματος και όλων των απαραίτητων γραφικών στοιχείων σε αυτό
          Αίτηση των πληροφοριών καιρού ασύγχρονα
          Σύνδεση σημάτων σε κουμπί και καταχώριση.
          weatherapp.js

# Σενάριο για εκτέλεση της εφαρμογής

#!/usr/bin/gjs

Αυτή η γραμμή λέει πώς θα εκτελεστεί το σενάριο. Πρέπει να είναι η πρώτη γραμμή του κώδικα και να είναι εκτελέσιμη. Για λήψη των δικαιωμάτων εκτέλεσης πηγαίνετε στον τερματικό και εκτελέστε στον σωστό φάκελο: chmod +x όνομα σεναρίου. Ή μπορείτε να χρησιμοποιήσετε τον διαχειριστή αρχείου γραφικών. Απλά πηγαίνετε στον σωστό φάκελο όπου είναι ο κώδικας σας δεξί κλικ στο αρχείο του κώδικα σας, επιλέξτε ιδιότητες, κλικ στην καρτέλα δικαιωμάτων και σημειώστε το πλαίσιο για να επιτραπεί η εκτέλεση του αρχείου ως πρόγραμμα

# Βιβλιοθήκες για εισαγωγή

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

Για να έχουμε ένα αποτελεσματικό πρόγραμμα χρειαζόμαστε να εισάγουμε μια βιβλιοθήκη GObject αυτανάλυσης για χρήση. Για χρήση UI, χρειαζόμαστε Gtk. Το Gtk εισάγεται στην αρχή, έτσι το έχουμε για χρήση παντού. Εισάγουμε επίσης τη δικιά μας τοπική βιβλιοθήκη JavaScript geonames για να χρησιμοποιηθεί εδώ.

# Δημιουργία του κύριου παραθύρου για την εφαρμογή

// Αρχικοποίηση της gtk Gtk.init(null, 0); //Δημιουργία του παραθύρου σας, ονομασία του και σύνδεσή του x με τη συνάρτηση εξόδου. Να θυνάστε ότι το παράθυρο είναι μια δεδομένη λέξη var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); weatherwindow.title = "Todays weather"; //Το παράθυρο δέχεται μόνο ένα γραφικό στοιχείο και έναν τίτλο. Παραπέρα δομή με παρόμοια Gtk.boxes weatherwindow.connect("destroy", function(){Gtk.main_quit()});

weatherwindow.show_all(); //και εκτέλεσή του Gtk.main();

# Προσθήκη πλέγματος και όλων των απαραίτητων γραφικών στοιχείων σε αυτό

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

//Αρχικοποιούμε εδώ το εικονίδιο, αλλά αποφασίζει το αρχείο αργότερα στο geonames.js. var weatherIcon = new Gtk.Image();

//Ορισμός μερικών ετικετών στο παράθυρό σας 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)

Σε ενότητα αυτήν την ενότητα δημιουργούμε το πλέγμα που πρόκειται να χρησιμοποιήσουμε για τοποθέτηση των γραφικών στοιχείων. Όλα τα κουμπιά, ετικέτες και καταχωρίσεις αρχικοποιούνται και τοποθετούνται στο πλέγμα. Όπως φαίνεται από την τοποθέτηση των διαφορετικών γραφικών στοιχείων, δεν χρειάζεται να σχετίζονται μόνο με ένα γραφικό στοιχείο. Σε αυτό το σημείο μερικές από τις ετικέτες δεν έχουν περιεχόμενο. Το περιεχόμενο για αυτά τα γραφικά στοιχεία εφαρμόζεται αργότερα. Εάν τρέξετε την εφαρμογή σε αυτό το στάδιο, θα έχετε έτοιμο το UI, αλλά τα γραφικά στοιχεία δεν συνδέονται με τίποτα. Για αυτό χρειαζόμαστε πρώτα να κατασκευάσουμε την τοπική βιβλιοθήκη αναζήτησης καιρού και έπειτα να πάρουμε την πληροφορία που χρειαζόμαστε ασύγχρονα. Όταν έχουμε την τοπική μας βιβλιοθήκη έτοιμη, μπορούμε να το συνδέσουμε με τα απαραίτητα γραφικά στοιχεία.

# Αίτηση των πληροφοριών καιρού ασύγχρονα

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

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

GeoNames.getWeather(function(error, 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") // ... }); }

Αυτή η λειτουργία αφιερώνεται στην κλήση για τις πληροφορίες καιρού και ενημέρωση ετικετών και εικονιδίων ανάλογα. Στην αρχή της λειτουργίας παίρνουμε την είσοδο χρήστη για αναζήτηση. Έτσι εδώ για την πρώτη φορά χρησιμοποιούμε τη δική μας βιβλιοθήκη και τις αποδίδουμε τη μεταβλητή GeoNames. Ενώ εκχωρούμε την WeatherService της δίνουμε τον σταθμό. Το πρώτο πράγμα που κάνουμε με τα GeoNames είναι η αίτηση καιρού. Οτιδήποτε μετά τα GeoNamesgetWeather.getWeather (συνάρτηση (σφάλμα, καιρός) συμβαίνει μόνο εάν είτε πάρουμε ένα μήνυμα σφάλματος ή πληροφορίες καιρού. Εάν δεν έρθει κανένα, το υπόλοιπο του προγράμματος δουλεύει τόσο κανονικά, όσο το main_Quit δουλεύει.

# Σύνδεση σημάτων σε κουμπί και καταχώριση.

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(); });

Και τελικά έχουμε τις συνδέσεις που κάνουν όλη την εφαρμογή να τρέχει όπως θα έπρεπε. Συνδέουμε και την καταχώριση και το κουμπί για να κάνουν το ίδιο πράγμα, παίρνοντας τον καιρό. Έτσι δεν πειράζει, εάν πατήσετε εάν πατήσετε εισαγωγή ή κλικ στο κουμπί αναζήτησης.

# Weatherapp.js

Το αρχείο Weatherapp.js μοιάζει με αυτό:

#!/usr/bin/gjs //Η προηγούμενη γραμμή αρχίζει με δίεση-θαυμαστικό που λέει π να εκτελεστεί το σενάριο. // Σημειώστε ότι το σενάριο πρέπει να είναι εκτελέσιμο (εκτέλεση σε τερματικό στον δεξιό φάκελο: chmod +x scriptname)

var Gtk = imports.gi.Gtk;

const WeatherService = imports.geonames; //Μεταφορά της δικής σας βιβλιοθήκης από τον ίδιο φάκελο (όπως ορίστηκε στο GJS_PATH). Αν χρησιμοποιείτε autotools .desktop θα φροντίσει για αυτό

// Αρχικοποίηση της gtk Gtk.init(null, 0); //Δημιουργία του παραθύρου σας, ονομασία του, και σύνδεση του x με τη συνάρτηση εξόδου. Να θυμάστε ότι το παράθυρο είναι μια δεσμευμένη λέξη var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL}); weatherwindow.title = "Todays weather"; //Το παράθυρο δέχεται μόνο ένα γραφικό στοιχείο και έναν τίτλο. Παραπέρα δομή όμοια μεGtk.boxes 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();

//Ορισμός μερικών ετικετών στο παράθυρό σας 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!"});

//Κάποιος καιρός

entry.connect("key_press_event", function(widget, event) { // FIXME: Λήψη καιρού με την εισαγωγή (πλήκτρο 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) { //Αυτό εδώ δουλεύει λίγο σαν σήματα. Αυτός ο κώδικας θα εκτελεστεί όταν έχουμε καιρό. 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(); //και εκτέλεσή του Gtk.main();

Εκτέλεση μέχρι να έχετε όλα τα αρχεία autotools έτοιμα. :

     $  GJS_PATH=`pwd` gjs weatherapp.js

Χρησιμοποιήστε αυτήν την εντολή στο τερματικό ενώ αναπτύσσετε τα αρθρώματά σας. Όταν καλείτε το πρόγραμμά σας με αυτόν τον τρόπο, ξέρει πού θα βρει τις προσαρμοσμένες JSlibraries, σε αυτήν την περίπτωση το geonames.js.