Διακόπτης (JavaScript) Taryn Fox jewelfox@fursona.net 2012 Ένας κινητός διακόπτης που μπορεί να αντιστρέφεται σε ναι και όχι Ελληνική μεταφραστική ομάδα GNOME team@gnome.gr 2012-2015 Δημήτρης Σπίγγος dmtrs32@gmail.com 2012, 2013 Μαρία Θουκιδίδου marablack3@gmail.com 2014 Θάνος Τρυφωνίδης tomtryf@gmail.com 2014, 2015 Διακόπτης

Ένας διακόπτης έχει δύο θέσεις ενεργή/ανενεργή. Αυτό το παράδειγμα εμφανίζει πώς μπορείτε να χρησιμοποιήσετε πολλαπλούς διακόπτες μαζί για να ελέγξετε ποια εικόνα προβάλλεται στο παράθυρο. Οι εικόνες που χρησιμοποιούνται σε αυτό το παράδειγμα μπορούν να φορτωθούν εδώ.

Το παράθυρο θα περιέχει ένα εικονίδιο "σπασμένης εικόνας" αντί για μια εικόνα εάν τα αρχεία εικόνας με όνομα redfox.png, muteswan.png, fruitbat.png και gentoopenguin.png δεν είναι στον ίδιο κατάλογο. Μπορείτε να αλλάξετε τον κώδικα και τις εικόνες ολόγυρα όπως θέλετε, αλλά οι φωτογραφίες με άδεια Creative Commons που χρησιμοποιούνται σε αυτό το παράδειγμα πάρθηκαν από τις ακόλουθες πηγές και περικόπηκαν σε 640x425:

φωτογραφία κόκκινης αλεπούς από τον Rob Lee, με άδεια CC-By

φωτογραφία πιγκουίνου Gentoo από τον Ken Funakoshi, με άδεια CC-By-SA

φωτογραφία νυχτερίδας φρούτων από τον Shek Graham, licensed CC-By

φωτογραφία σιωπηλού κύκνου από Mindaugas Urbonas, με άδεια CC-By-SA

Μνείες φωτογραφίας και πληροφορίες αδειοδότησης εμφανίζονται στο AboutDialog. Να θυμάστε πάντα να μνημονεύετε τον αρχικό καλλιτέχνη όταν χρησιμοποιείτεεργασίες με άδεια Creative Commons! της εφαρμογής

Βιβλιοθήκες για εισαγωγή #!/usr/bin/gjs const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk; const Lang = imports.lang;

Αυτές είναι οι βιβλιοθήκες που χρειαζόμαστε να εισάγουμε αυτήν την εφαρμογή για να εκτελεστεί. Να θυμόσαστε ότι η γραμμή που λέει στο GNOME ότι χρησιμοποιούμε Gjs χρειάζεται πάντοτε να πάει στην αρχή.

Δημιουργία του παραθύρου εφαρμογής const SwitchExample = new Lang.Class({ Name: 'Switch Example', // Δημιουργία της εφαρμογής αυτής καθεαυτής _init: function() { this.application = new Gtk.Application({ application_id: 'org.example.jsswitch', flags: Gio.ApplicationFlags.FLAGS_NONE }); // Σύνδεση των σημάτων 'activate' και 'startup' με τις συναρτήσεις επανάκλησης this.application.connect('activate', Lang.bind(this, this._onActivate)); this.application.connect('startup', Lang.bind(this, this._onStartup)); }, // Η συνάρτηση επανάκλησης για το σήμα 'activate' παρουσιάζει ένα παράθυρο όταν είναι ενεργή _onActivate: function() { this._window.present(); }, // Η συνάρτηση επανάκλησης για το σήμα 'startup'δημιουργεί το μενού και δομεί τη διεπαφή χρήστη _onStartup: function() { this._initMenus(); this._buildUI (); },

Όλος ο κώδικας για αυτό το παράδειγμα πηγαίνει στην κλάση SwitchExample. Ο παραπάνω κώδικας δημιουργεί μια Gtk.Application για να μπουν μέσα τα γραφικά στοιχεία μας και τα παράθυρα.

Πριν καλέσουμε _buildUI για δημιουργία του παραθύρου και των γραφικών στοιχείων μέσα του, χρειαζόμαστε να καλέσουμε _initMenus, που λέει στο GNOME να δημιουργήσει το μενού. Μπορούμε να βάλουμε τον ενεργό κώδικα για _initMenus μετά τον κώδικα για _buildUI, αφού δεν πειράζει η σειρά που τα βάλαμε όσο το _initMenus καλείται πρώτο στο _onStartup.

// Δόμηση της διεπαφής χρήστη της εφαρμογής _buildUI: function() { // Δημιουργία του παραθύρου της εφαρμογής this._window = new Gtk.ApplicationWindow({ application: this.application, window_position: Gtk.WindowPosition.CENTER, border_width: 20, title: "Animal Creator"});

Η συνάρτηση _buildUI είναι εκεί που βάζουμε όλον τον κώδικα για να δημιουργήσουμε τη διεπαφή χρήστη της εφαρμογής. Το πρώτο βήμα δημιουργεί ένα νέο Gtk.ApplicationWindow για να βάλουμε μέσα τα γραφικά στοιχεία μας.

Δημιουργία των διακοπτών // Δημιουργία του γραφικού της εικόνας και ορισμός της προεπιλεγμένης της εικόνας this._image = new Gtk.Image ({file: "redfox.png"});

Δημιουργούμε πρώτα την εικόνα που οι διακόπτες θα ελέγχουν. Να θυμάστε ότι ένα αρχείο με όνομα redfox.png χρειάζεται να είναι στον ίδιο κατάλογο όπως αυτή η εφαρμογή.

// Δημιουργία μιας ετικέτας για τον πρώτο διακόπτη this._flyLabel = new Gtk.Label ({ label: "Make it fly", margin_right: 30}); // Δημιουργία του πρώτου διακόπτη και ορισμός της προεπιλεγμένης του θέσης this._flySwitch = new Gtk.Switch ({active: false}); this._flySwitch.connect ('notify::active', Lang.bind (this, this._switchFlip)); // Δημιουργία μιας ετικέτας για τον δεύτερο διακόπτη this._birdLabel = new Gtk.Label ({ label: "Make it a bird", margin_right: 30}); // Δημιουργία του δεύτερου διακόπτη this._birdSwitch = new Gtk.Switch ({active: false}); this._birdSwitch.connect ('notify::active', Lang.bind (this, this._switchFlip));

Χρησιμοποιούμε μια ετικέτα για να σημειώσουμε κάθε διακόπτη και να τους δώσουμε λίγο περιθώριο στα δεξιά έτσι ώστε να μην στριμώχνονται ακριβώς δίπλα στους διακόπτες. Μετά δημιουργούμε τους διακόπτες και τους ορίζουμε ανενεργούς από προεπιλογή.

Το σήμα που ένας διακόπτης στέλνει όταν αντιστρέφεται ενεργά/ανενεργά λέγεται notify::active. Μετά τη δημιουργία κάθε διακόπτη, συνδέουμε το σήμα του notify::active σε μια συνάρτηση που λέγεται _switchFlip. Εάν έχετε πολλούς διακόπτες που ο καθένας τους κάνει κάτι διαφορετικό, ίσως θελήσετε να τους συνδέσετε σε διαφορετικές συναρτήσεις, αλλά εδώ και οι δυο χρησιμοποιούνται για το ίδιο πράγμα: τον έλεγχο της εμφανιζόμενης εικόνας από το _image.

// Δημιουργία πλέγματος για τις ετικέτες και τους διακόπτες κάτω από την εικόνα this._UIGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER, margin_top: 20}); // Προσάρτηση των ετικετών και διακοπτών σε αυτό το πλέγμα this._UIGrid.attach (this._flyLabel, 0, 0, 1, 1); this._UIGrid.attach (this._flySwitch, 1, 0, 1, 1); this._UIGrid.attach (this._birdLabel, 0, 1, 1, 1); this._UIGrid.attach (this._birdSwitch, 1, 1, 1, 1); // Δημιουργία ενός κύριου πλέγματος για να τοποθετηθούν μέσα η γραφική διεπαφή και η εικόνα this._mainGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER }); // Προσάρτηση του πλέγματος εικόνας και διεπαφής χρήστη στο κύριο πλέγμα this._mainGrid.attach (this._image, 0, 0, 1, 1); this._mainGrid.attach (this._UIGrid, 0, 1, 1, 1);

Δημιουργούμε ένα πλέγμα για τις ετικέτες και τους διακόπτες πρώτα, έτσι ώστε να μπορούμε να τις οργανώσουμε σε μια διάταξη 2x2 με ένα περιθώριο μεταξύ του και της εικόνας. Έπειτα βάζουμε αυτό το πλέγμα σε ένα μεγαλύτερο πλέγμα 2x1 που έχει την εικόνα στην κορυφή και το πλέγμα με τις ετικέτες και τους διακόπτες στο τέλος.

// Προσθήκη του κύριου πλέγματος στο παράθυρο this._window.add (this._mainGrid); // Εμφάνιση του παραθύρου και όλων των θυγατρικών γραφικών στοιχείων this._window.show_all(); },

Τελικά, προσθέτουμε το μεγαλύτερο πλέγμα στο παράθυρο, έπειτα λέμε στο παράθυρο να εμφανίσει τον εαυτόν του και όλα τα γραφικά στοιχεία μέσα του.

Η συνάρτηση που χειρίζεται τους διακόπτες που αντιστράφηκαν _switchFlip: function() { // Αλλαγή της εικόνας ανάλογα με το ποιοι διακόπτες αντιστρέφονται if (this._flySwitch.get_active()) { if (this._birdSwitch.get_active()) this._image.set_from_file ("muteswan.png"); else this._image.set_from_file ("fruitbat.png"); } else { if (this._birdSwitch.get_active()) this._image.set_from_file ("gentoopenguin.png"); else this._image.set_from_file ("redfox.png"); } },

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

Δημιουργία του AboutDialog _initMenus: function() { // Δόμηση του μενού της εφαρμογής, έτσι ώστε να μπορούμε να έχουμε ένα πλήκτρο "About" let menu = new Gio.Menu(); menu.append("About", 'app.about'); menu.append("Quit",'app.quit'); this.application.set_app_menu(menu); // ΣΑύνδεση του πλήκτρου "About" με τη συνάρτηση _showAbout() let aboutAction = new Gio.SimpleAction ({ name: 'about' }); aboutAction.connect('activate', Lang.bind(this, function() { this._showAbout(); })); this.application.add_action(aboutAction); // Σύνδεση του πλήκτρου "Quit"με τη συνάρτηση που κλείνει το παράθυρο let quitAction = new Gio.SimpleAction ({ name: 'quit' }); quitAction.connect('activate', Lang.bind(this, function() { this._window.destroy(); })); this.application.add_action(quitAction); },

Το πρώτο βήμα είναι η δόμηση του GMenu στο οποίο το κουμπί "About" μπαίνει. Αυτό είναι το μενού που εμφανίζεται όταν πατάς το όνομα της εφαρμογής στην πάνω αριστερή γωνία της οθόνης, δίπλα στο μενού ενέργειες. Το μενού μας έχει μόνο δύο επιλογές: περί και κλείσιμο.

_showAbout: function () { // Πίνακες συμβολοσειρών των ονομάτων των ατόμων που εμπλέκονται στο έργο var artists = ['Rob Lee http://en.wikipedia.org/wiki/File:Fuzzy_Freddy.jpg', 'Ken Funakoshi http://en.wikipedia.org/wiki/File:Pygoscelis_papua_-Nagasaki_Penguin_Aquarium_-swimming_underwater-8a.jpg', 'Shek Graham http://www.flickr.com/photos/shekgraham/127431519/in/photostream/', 'Mindaugas Urbonas http://commons.wikimedia.org/wiki/File:Mute_Swan-Mindaugas_Urbonas.jpg']; var authors = ["GNOME Documentation Team"]; var documenters = ["GNOME Documentation Team"]; // Δημιουργία του διαλόγου Περί let aboutDialog = new Gtk.AboutDialog({ title: "AboutDialog Example", program_name: "Animal Creator", copyright: "Copyright \xa9 2012 GNOME Documentation Team\n\nRed fox photo licensed CC-By by Rob Lee\nGentoo penguin photo licensed CC-By-SA by Ken Funakoshi\nFruit bat photo licensed CC-By by Shek Graham\nMute swan photo licensed CC-By-SA by Mindaugas Urbonas\nLinks to the originals are available under Credits.\n\nHave you hugged a penguin today?", artists: artists, authors: authors, documenters: documenters, website: "http://developer.gnome.org", website_label: "GNOME Developer Website" }); // Προσάρτηση του διαλόγου Περί στο παράθυρο aboutDialog.modal = true; aboutDialog.transient_for = this._window; // Εμφάνιση του διαλόγου Περί aboutDialog.show(); // Σύνδεση του πλήκτρου Κλείσιμο με το σήμα καταστροφής του διαλόγου aboutDialog.connect('response', function() { aboutDialog.destroy(); }); } });

Ένας AboutDialog έχει πολλά διαφορετικά πράγματα που μπορείτε να ορίσετε, για να μνημονεύσετε οποιονδήποτε δούλεψε στην εφαρμογή και να αφήσετε μια σημείωση σε οποιονδήποτε το διαβάζει. Σε αυτήν την περίπτωση, η ενότητα πνευματικών δικαιωμάτων περιέχει τη σημείωση μας και μνείες των αρχικών φωτογράφων, ενώ η ενότητα των καλλιτεχνών σας εμφανίζει μια λίστα των φωτογράφων με συνδέσμους στις αρχικές φωτογραφίες όταν πατάτε το κουμπί με τις μνείες. Τα URLs του ιστού μετά τα ονόματα τους στον πίνακα κάνουν τα ονόματα τους επιλέξιμους συνδέσμους στην ενότητα με τις μνείες.

// Εκτέλεση της εφαρμογής let app = new SwitchExample (); app.application.run (ARGV);

Τελικά, δημιουργούμε ένα νέο παράδειγμα της ολοκληρωμένης κλάσης SwitchExample και εκτελούμε την εφαρμογή.

Δείγμα πλήρους κώδικα #!/usr/bin/gjs imports.gi.versions.Gtk = '3.0'; const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk; class SwitchExample { // Create the application itself constructor() { this.application = new Gtk.Application({ application_id: 'org.example.jsswitch' }); // Connect 'activate' and 'startup' signals to the callback functions this.application.connect('activate', this._onActivate.bind(this)); this.application.connect('startup', this._onStartup.bind(this)); } // Callback function for 'activate' signal presents window when active _onActivate() { this._window.present(); } // Callback function for 'startup' signal creates the menu and builds the UI _onStartup() { this._initMenus(); this._buildUI(); } // Build the application's UI _buildUI() { // Create the application window this._window = new Gtk.ApplicationWindow({ application: this.application, window_position: Gtk.WindowPosition.CENTER, border_width: 20, title: "Animal Creator"}); // Create the image widget and set its default picture this._image = new Gtk.Image ({file: "redfox.png"}); // Create a label for the first switch this._flyLabel = new Gtk.Label ({ label: "Make it fly", margin_right: 30}); // Create the first switch and set its default position this._flySwitch = new Gtk.Switch ({active: false}); this._flySwitch.connect ('notify::active', this._switchFlip.bind(this)); // Create a label for the second switch this._birdLabel = new Gtk.Label ({ label: "Make it a bird", margin_right: 30}); // Create the second switch this._birdSwitch = new Gtk.Switch ({active: false}); this._birdSwitch.connect ('notify::active', this._switchFlip.bind(this)); // Create a grid for the labels and switches beneath the picture this._UIGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER, margin_top: 20}); // Attach the labels and switches to that grid this._UIGrid.attach (this._flyLabel, 0, 0, 1, 1); this._UIGrid.attach (this._flySwitch, 1, 0, 1, 1); this._UIGrid.attach (this._birdLabel, 0, 1, 1, 1); this._UIGrid.attach (this._birdSwitch, 1, 1, 1, 1); // Create a master grid to put both the UI and the picture into this._mainGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER }); // Attach the picture and the UI grid to the master grid this._mainGrid.attach (this._image, 0, 0, 1, 1); this._mainGrid.attach (this._UIGrid, 0, 1, 1, 1); // Add the master grid to the window this._window.add (this._mainGrid); // Show the window and all child widgets this._window.show_all(); } _switchFlip() { // Change the picture depending on which switches are flipped if (this._flySwitch.get_active()) { if (this._birdSwitch.get_active()) this._image.set_from_file ("muteswan.png"); else this._image.set_from_file ("fruitbat.png"); } else { if (this._birdSwitch.get_active()) this._image.set_from_file ("gentoopenguin.png"); else this._image.set_from_file ("redfox.png"); } } _initMenus() { // Build the application's menu so we can have an "About" button let menu = new Gio.Menu(); menu.append("About", 'app.about'); menu.append("Quit",'app.quit'); this.application.set_app_menu(menu); // Bind the "About" button to the _showAbout() function let aboutAction = new Gio.SimpleAction ({ name: 'about' }); aboutAction.connect('activate', () => { this._showAbout(); }); this.application.add_action(aboutAction); // Bind the "Quit" button to the function that closes the window let quitAction = new Gio.SimpleAction ({ name: 'quit' }); quitAction.connect('activate', () => { this._window.destroy(); }); this.application.add_action(quitAction); } _showAbout() { // String arrays of the names of the people involved in the project var artists = ['Rob Lee http://en.wikipedia.org/wiki/File:Fuzzy_Freddy.png', 'Ken Funakoshi http://en.wikipedia.org/wiki/File:Pygoscelis_papua_-Nagasaki_Penguin_Aquarium_-swimming_underwater-8a.png', 'Shek Graham http://www.flickr.com/photos/shekgraham/127431519/in/photostream/', 'Mindaugas Urbonas http://commons.wikimedia.org/wiki/File:Mute_Swan-Mindaugas_Urbonas.png']; var authors = ["GNOME Documentation Team"]; var documenters = ["GNOME Documentation Team"]; // Create the About dialog let aboutDialog = new Gtk.AboutDialog({ title: "AboutDialog Example", program_name: "Animal Creator", copyright: "Copyright \xa9 2012 GNOME Documentation Team\n\nRed fox photo licensed CC-By by Rob Lee\nGentoo penguin photo licensed CC-By-SA by Ken Funakoshi\nFruit bat photo licensed CC-By by Shek Graham\nMute swan photo licensed CC-By-SA by Mindaugas Urbonas\nLinks to the originals are available under Credits.\n\nHave you hugged a penguin today?", artists: artists, authors: authors, documenters: documenters, website: "http://developer.gnome.org", website_label: "GNOME Developer Website" }); // Attach the About dialog to the window aboutDialog.modal = true; aboutDialog.transient_for = this._window; // Show the About dialog aboutDialog.show(); // Connect the Close button to the destroy signal for the dialog aboutDialog.connect('response', function() { aboutDialog.destroy(); }); } }; // Run the application let app = new SwitchExample (); app.application.run (ARGV);
Τεκμηρίωση σε βάθος

GMenu

GSimpleAction

Gtk.Application

Gtk.ApplicationWindow

Gtk.Grid

Gtk.Image

Gtk.Label

Gtk.Switch