<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="topic" id="photo-wall.c" xml:lang="el">
  <info>
    <title type="text">Φωτογραφικός τοίχος (C)</title>
    <link type="guide" xref="c"/>

    <desc>Ένας προβολέας εικόνας Clutter</desc>

    <revision pkgversion="0.1" version="0.1" date="2011-03-22" status="review"/>
    <credit type="author">
      <name>Chris Kühl</name>
      <email>chrisk@openismus.com</email>
    </credit>
    <credit type="author">
      <name>Johannes Schmid</name>
      <email>jhs@gnome.org</email>
    </credit>
  </info>

<title>Φωτογραφικός τοίχος</title>

<synopsis>
  <p>Για αυτό το παράδειγμα θα κατασκευάσουμε έναν απλό προβολέα εικόνων χρησιμοποιώντας το Clutter. Θα μάθετε:</p>
  <list>
    <item><p>Αυξομείωση και τοποθέτηση του <code>ClutterActor</code>s</p></item>
    <item><p>Πώς να τοποθετήσετε μια εικόνα σε ένα <code>ClutterActor</code></p></item>
    <item><p>Πώς να κάνετε απλές μεταβάσεις χρησιμοποιώντας το σκελετό κίνησης του Clutter</p></item>
    <item><p>Πώς να κάνετε το <code>ClutterActor</code>s να απαντήσει στα συμβάντα του ποντικιού</p></item>
    <item><p>Πώς να πάρετε ονόματα αρχείου από έναν κατάλογο</p></item>
  </list>
</synopsis>

<section id="intro">
  <title>Εισαγωγή</title>
  <p>Clutter είναι μια βιβλιοθήκη για δημιουργία δυναμικών διεπαφών χρήστη χρησιμοποιώντας το OpenGL για επιτάχυνση υλικού. Αυτό το παράδειγμα δείχνει ένα μικρό, αλλά κεντρικό, τμήμα της Clutter για δημιουργία ενός απλού αλλά ελκυστικού προγράμματος προβολής εικόνας.</p>
  <p>Για να βοηθηθούμε να φτάσουμε τον στόχο μας θα χρησιμοποιήσουμε λίγα άλλα κοινά κομμάτια του GLib επίσης. Το πιο σημαντικό, θα χρησιμοποιήσουμε ένα <code>GSList</code>, μια μοναδικά συνδεμένη λίστα, για να κρατήσουμε το <code>ClutterActor</code>s μας και ένα άλλο για ονόματα διαδρομής αρχείου. Θα χρησιμοποιήσουμε επίσης <code>GDir</code>, ένα βοήθημα για εργασία με καταλόγους, για προσπέλαση του καταλόγου της εικόνας μας και να συγκεντρώσουμε τις διαδρομές του αρχείου.</p>
</section>

<section id="anjuta">
  <title>Δημιουργία έργου με το Anjuta</title>
  <p>Πριν ξεκινήσετε να προγραμματίζετε, πρέπει να δημιουργήσετε ένα καινούργιο έργο στο Anjuta. Έτσι θα δημιουργηθούν όλα τα απαραίτητα αρχεία που χρειάζονται για την εκτέλεση του κώδικα αργότερα. Επίσης θα ήταν χρήσιμο να τα κρατάτε όλα μαζί.</p>
  <steps>
    <item>
    <p>Ξεκινήστε το Anjuta και πατήστε <guiseq><gui>αρχείο</gui><gui>νέο</gui><gui>έργο</gui></guiseq> για να ανοίξετε τον οδηγό του έργου.</p>
    </item>
    <item>
    <p>Επιλέξτε <gui>Gtk+ (απλό)</gui> από την καρτέλα <gui>C</gui>, πατήστε <gui>συνέχεια</gui> και συμπληρώστε τις λεπτομέρειές σας στις επόμενες λίγες σελίδες. Χρησιμοποιήστε το <file>photo-wall</file> ως όνομα του έργου και του καταλόγου.</p>
   	</item>
    <item>
    <p>Σιγουρευτείτε ότι η <gui>χρήση του GtkBuilder για διεπαφή χρήστη</gui> είναι ανενεργή επειδή θα φτιάξουμε το UI χειροκίνητα σε αυτό το μάθημα. Σημειώστε το μάθημα <link xref="guitar-tuner.c">ρυθμιστής κιθάρας</link> χρησιμοποιώντας τον κατασκευαστή διεπαφής.</p>
    </item>
    <item>
    <p>Ενεργοποιήστε <gui>ρύθμιση εξωτερικών πακέτων</gui>. Στην επόμενη σελίδα, επιλέξτε <em>clutter-1.0</em> από τη λίστα για να συμπεριλάβετε τη βιβλιοθήκη Clutter στο έργο σας.</p>
    </item>
    <item>
    <p>Πατήστε <gui>εφαρμογή</gui> και το έργο θα δημιουργηθεί για σας. Ανοίξτε το <file>src/main.c</file> από τις καρτέλες <gui>έργο</gui> ή <gui>αρχείο</gui>. Θα πρέπει να δείτε κάποιο κώδικα που ξεκινάει με τις γραμμές:</p>
    <code mime="text/x-csrc"><![CDATA[
#include <config.h>
#include <gtk/gtk.h>]]></code>
    </item>
  </steps>
</section>

<section id="look">
  <title>Μια ματιά στο φωτογραφικό πίνακα</title>
  <p>Ο προβολέας εικόνας μας παρουσιάζει τον χρήστη με έναν τοίχο εικόνων.</p>
  <media type="image" mime="image/png" src="media/photo-wall.png"/>
  <p>Όταν κάνουμε κλικ σε μια εικόνα, κινείται για να γεμίσει την περιοχή προβολής. Όταν κάνουμε κλικ σε μια εστιασμένη εικόνα επιστρέφεται στην αρχική της θέση χρησιμοποιώντας μια κίνηση με την ίδια διάρκεια των 500 ms.</p>
  <media type="image" mime="image/png" src="media/photo-wall-focused.png"/>
</section>

<section id="setup">
  <title>Αρχική ρύθμιση</title>
  <p>Το παρακάτω τμήμα κώδικα περιέχει πολλούς ορισμούς και μεταβλητές που θα χρησιμοποιήσουμε στις παρακάτω ενότητες. Χρησιμοποιήστε αυτό ως αναφορά για άλλες ενότητες. Αντιγράψτε αυτόν τον κώδικα στην αρχή του <file>src/main.c</file>:</p>
<code mime="text/x-csrc" style="numbered"><![CDATA[
#include <clutter/clutter.h>

#define STAGE_WIDTH  800
#define STAGE_HEIGHT 600

#define THUMBNAIL_SIZE 200
#define ROW_COUNT (STAGE_HEIGHT / THUMBNAIL_SIZE)
#define COL_COUNT (STAGE_WIDTH  / THUMBNAIL_SIZE)
#define THUMBNAIL_COUNT (ROW_COUNT * COL_COUNT)

#define ANIMATION_DURATION_MS 500

#define FOCUS_DEPTH 100.0
#define UNFOCUS_DEPTH 0.0

#define IMAGE_DIR_PATH "./berlin_images/"

static GSList *actor_list = NULL;
static GSList *img_path_list = NULL;

typedef struct Position
{
    float x;
    float y;
}
Position;

static Position origin = {0, 0};
]]>
</code>
</section>

<section id="code">
  <title>Μετάβαση στον κώδικα</title>
  <p>Θα ξεκινήσουμε ρίχνοντας μια ματιά στη συνάρτηση <code>main()</code> ως σύνολο. Έπειτα θα συζητήσουμε τις άλλες ενότητες κώδικα λεπτομερώς. Αλλάξτε το <file>src/main.c</file> για να περιέχει αυτήν την συνάρτηση <code>main()</code>. Μπορείτε να διαγράψετε τη συνάρτηση <code>create_window()</code> καθώς δεν τη χρειαζόμαστε σε αυτό το παράδειγμα.</p>
  <code mime="text/x-csrc" style="numbered"><![CDATA[
int
main(int argc, char *argv[])
{
    ClutterColor stage_color = { 16, 16, 16, 255 };
    ClutterActor *stage = NULL;

    clutter_init(&argc, &argv);

    stage = clutter_stage_get_default();
    clutter_actor_set_size(stage, STAGE_WIDTH, STAGE_HEIGHT);
    clutter_stage_set_color(CLUTTER_STAGE (stage), &stage_color);

    load_image_path_names();

    guint row = 0;
    guint col = 0;
    for(row=0; row < ROW_COUNT; ++row)
    {
        for(col=0; col < COL_COUNT; ++col)
        {
            GSList *img_path_node = g_slist_nth(img_path_list, (row * COL_COUNT) + col);
            ClutterActor *actor = clutter_texture_new_from_file((gchar *)(img_path_node->data), NULL);
            initialize_actor(actor, row, col);
            clutter_container_add_actor(CLUTTER_CONTAINER(stage), actor);
            actor_list = g_slist_prepend(actor_list, actor);
        }
    }

    /* Show the stage. */
    clutter_actor_show(stage);

    /* Start the clutter main loop. */
    clutter_main();

    return 0;
}]]></code>
  <list>
    <item><p>Γραμμή 4: <code>ClutterColor</code> ορίστηκε ορίζοντας τις τιμές κόκκινου, πράσινου, γαλάζιου και διαφάνειας (άλφα). Το εύρος τιμών από 0-255. Για διαφάνεια τιμή 255 είναι αδιαφανής.</p></item>
    <item><p>Γραμμή 7: Πρέπει να αρχικοποιήσετε το Clutter. Εάν το ξεχάσετε, θα πάρετε πολύ περίεργα σφάλματα. Προειδοποιηθήκατε.</p></item>
    <item><p>Γραμμές 9-11. Εδώ παίρνουμε την προεπιλογή <code>ClutterStage</code> που δόθηκε από <code>clutter_init</code>. Έπειτα ορίζουμε το μέγεθος χρησιμοποιώντας τους ορισμούς από την προηγούμενη ενότητα και τη διεύθυνση του <code>ClutterColor</code> που μόλις ορίσαμε.</p>
      <note><p>Ένας <code>ClutterStage</code> είναι ανώτατου επιπέδου <code>ClutterActor</code> στον οποίο άλλοι <code>ClutterActor</code> τοποθετούνται.</p></note>
</item>
    <item><p>Γραμμή 12: Εδώ καλούμε τη συνάρτηση μας για λήψη των διαδρομών αρχείου εικόνας. Θα το δούμε σε λίγο.</p></item>
    <item><p>Γραμμές 14-26: Εδώ ρυθμίζουμε το <code>ClutterActor</code>s, φόρτωση των εικόνων και τοποθέτησή τους στο σημείο τους στον τοίχο εικόνας. Θα το δούμε λεπτομερώς στην επόμενη ενότητα.</p></item>
    <item><p>Γραμμή 29: εμφάνιση του σταδίου και <em>όλων των θυγατρικών του</em>, που σημαίνει των εικόνων μας.</p></item>
    <item><p>Γραμμή 32: Έναρξη του κύριου βρόχου του Clutter.</p></item>
  </list>
</section>

<section id="actors">
  <title>Εγκατάσταση των δραστών εικόνας</title>
 <note><p>Στο Clutter, ένας δράστης είναι το πιο βασικό οπτικό στοιχείο. Βασικά, οτιδήποτε βλέπετε είναι ένας δράστης.</p></note>
<p>Σε αυτήν την ενότητα, πρόκειται να κοιτάξουμε στενότερα το χρησιμοποιούμενο βρόχο για εγκατάσταση του <code>ClutterActor</code>s που θα εμφανίσει τις εικόνες μας.</p>
  <code mime="text/x-csrc" style="numbered"><![CDATA[
for(row=0; row < ROW_COUNT; ++row)
{
    for(col=0; col < COL_COUNT; ++col)
    {
        GSList *img_path_node = g_slist_nth(img_path_list, (row * COL_COUNT) + col);
        ClutterActor *actor = clutter_texture_new_from_file((gchar *)(img_path_node->data), NULL);
        initialize_actor(actor, row, col);
        clutter_container_add_actor(CLUTTER_CONTAINER(stage), actor);
        actor_list = g_slist_prepend(actor_list, actor);
    }
}
]]>
</code>
<list>
  <item><p>Γραμμή 5: Εδώ θέλουμε να πάρουμε τη διαδρομή στη θέση <var>n</var> στο <code>GSList</code> που κρατά τα ονόματα διαδρομής εικόνας. Η <var>n</var> θέση υπολογίζεται βασισμένη στη <code>row</code> και <code>col</code>. Η επιστρεφόμενη τιμή είναι ένας δείκτης σε μια <code>GSList</code> που είναι μόνο ένας κόμβος στη λίστα. Θα τον χρησιμοποιήσουμε για τη λήψη της ενεργής διαδρομής στην επόμενη γραμμή. Η πρώτη παράμετρος είναι ένας δείκτης στην κεφαλή της λίστας.</p>
  </item>
  <item><p>Γραμμή 6: Εδώ δημιουργείται στην πραγματικότητα ο <code>ClutterActor</code> και τοποθετείται η εικόνα στον δράστη. Το πρώτο όρισμα είναι η διαδρομή προσπέλασης μέσα από τον κόμβο <code>GSList</code>. Το δεύτερο όρισμα είναι για αναφορά σφάλματος, αλλά το αγνοούμε για λόγους συντομίας.</p>
  </item>
  <item><p>Γραμμή 7: θα δούμε αυτή την συνάρτηση σε επόμενη ενότητα.</p>
  </item>
  <item><p>Γραμμή 8: Αυτή προσθέτει τον <code>ClutterActor</code> στο στάδιο, που είναι ένας περιέκτης. Επίσης υποθέτει ιδιοκτησία του <code>ClutterActor</code> που είναι κάτι που θα θελήσετε να κοιτάξετε καθώς πηγαίνετε βαθύτερα στην ανάπτυξη του GNOME. Δείτε την <link href="http://library.gnome.org/devel/gobject/stable/gobject-memory.html"><code>GObject</code>τεκμηρίωση</link> για τις φρικτές λεπτομέρειες.</p>
  </item>
  <item><p>Γραμμή 9: Αυτό προσθέτει το <code>ClutterActor</code> σε ένα <code>GSList</code>, έτσι ώστε αργότερα να μπορούμε να επαναλάβουμε το <code>ClutterActor</code>.</p>
<note><p>Σημειώστε ότι θέλουμε να προτάξουμε το <code>ClutterActor</code> παρά να το προσαρτήσουμε για αποφυγή διάσχισης της λίστας με κάθε εισαγωγή. Θα δείτε συχνά το <code>g_slist_prepend</code> ακολουθούμενο από <code>g_slist_reverse</code> επειδή είναι πιο γρήγορο παρά η εισαγωγή πολλών αντικειμένων στο τέλος της λίστας.</p></note>
  </item>
</list>
</section>

<section id="load">
  <title>Φόρτωση των εικόνων</title>
  <p>Ας κάνουμε μια σύντομη διακοπή από το Clutter για να δούμε πώς μπορούμε να πάρουμε τα ονόματα αρχείου από τον κατάλογό μας των εικόνων.</p>
  <code mime="text/x-csrc" style="numbered"><![CDATA[
static void
load_image_path_names()
{
    /* Ensure we can access the directory. */
    GError *error = NULL;
    GDir *dir = g_dir_open(IMAGE_DIR_PATH, 0, &error);
    if(error)
    {
        g_warning("g_dir_open() failed with error: %s\n", error->message);
        g_clear_error(&error);
        return;
    }

    const gchar *filename = g_dir_read_name(dir);
    while(filename)
    {
        if(g_str_has_suffix(filename, ".jpg") || g_str_has_suffix(filename, ".png"))
        {
            gchar *path = g_build_filename(IMAGE_DIR_PATH, filename, NULL);
            img_path_list = g_slist_prepend(img_path_list, path);
        }
        filename = g_dir_read_name(dir);
    }
}]]></code>
  <list>
    <item><p>Γραμμές 5 και 12: Αυτό ανοίγει τον κατάλογό μας ή, εάν συμβεί σφάλμα, επιστρέφει μετά την εκτύπωση ένα μήνυμα σφάλματος.</p></item>
    <item><p>Γραμμές 14-23: Η πρώτη γραμμή παίρνει ένα άλλο όνομα αρχείου από το <code>GDir</code> που ανοίξαμε πιο νωρίς. Εάν υπήρχε ένα αρχείο εικόνας (που ελέγχουμε κοιτώντας την επέκτασή του, ".png" ή ".jpg") στον κατάλογο συνεχίζουμε να προτάσσουμε τη διαδρομή καταλόγου εικόνας στο όνομα αρχείου και το προτάσσουμε στη λίστα που εγκαταστήσαμε νωρίτερα. Τελευταία προσπαθούμε να πάρουμε το επόμενο όνομα διαδρομής και ξαναεισάγουμε το βρόχο εάν βρεθεί κάποιο άλλο αρχείο.</p></item>
  </list>
</section>

<section id="actors2">
  <title>Εγκατάσταση των δραστών</title>
  <p>Ας ρίξουμε μια ματιά τώρα στο μέγεθος και την τοποθέτηση του <code>ClutterActor</code> και επίσης να ετοιμάσουμε το <code>ClutterActor</code> για αλληλεπίδραση χρήστη.</p>
  <code mime="text/x-csrc" style="numbered"><![CDATA[
/* This function handles setting up and placing the rectangles. */
static void
initialize_actor(ClutterActor *actor, guint row, guint col)
{
    clutter_actor_set_size(actor, THUMBNAIL_SIZE, THUMBNAIL_SIZE);
    clutter_actor_set_position(actor, col * THUMBNAIL_SIZE, row * THUMBNAIL_SIZE);
    clutter_actor_set_reactive(actor, TRUE);

    g_signal_connect(actor,
                     "button-press-event",
                     G_CALLBACK(actor_clicked_cb),
                     NULL);
}]]></code>
  <list>
    <item>
      <p>Γραμμή 7: ρύθμιση αντίδρασης δράστη σημαίνει ότι αντιδρά σε συμβάντα, τέτοια όπως <code>button-press-event</code> στην περίπτωσή μας. Για φωτογραφικό τοίχο, όλοι οι <code>ClutterActor</code> στον τοίχο θα πρέπει αρχικά να είναι αντιδραστικοί.</p>
    </item>
    <item>
      <p>Γραμμή 9-12: Τώρα συνδέουμε το <code>button-press-event</code> στην επανάκληση <code>actor_clicked_cb</code> που θα δούμε στη συνέχεια.</p>
    </item>
  </list>
  <p>Σε αυτό το σημείο πήραμε έναν τοίχο εικόνων που είναι έτοιμες να προβληθούν.</p>
</section>

<section id="click">
  <title>Αντίδραση στα κλικ</title>
  <p>

  </p>
  <code mime="text/x-csrc" style="numbered"><![CDATA[
static gboolean
actor_clicked_cb(ClutterActor *actor,
                 ClutterEvent *event,
                 gpointer      user_data)
{
    /* Flag to keep track of our state. */
    static gboolean is_focused = FALSE;

    g_slist_foreach(actor_list, foreach_set_focus_state, &is_focused);

    if(is_focused)
    {
        clutter_actor_animate(actor, CLUTTER_LINEAR, ANIMATION_DURATION_MS,
                              "x",      origin.x,
                              "y",      origin.y,
                              "depth",  UNFOCUS_DEPTH,
                              "width",  (float) THUMBNAIL_SIZE,
                              "height", (float) THUMBNAIL_SIZE,
                              NULL);
    }
    else
    {
        /*Save the current location before animating. */
        clutter_actor_get_position(actor, &origin.x, &origin.y);
        clutter_actor_set_reactive(actor, TRUE);
        clutter_actor_animate(actor, CLUTTER_LINEAR, ANIMATION_DURATION_MS,
                              "x",      (STAGE_WIDTH - STAGE_HEIGHT) / 2.0,
                              "y",      0.0,
                              "depth",  FOCUS_DEPTH,
                              "width",  (float) STAGE_HEIGHT,
                              "height", (float) STAGE_HEIGHT,
                              NULL);
    }

    /* Toggle our flag. */
    is_focused = !is_focused;

    return TRUE;
}]]></code>
  <list>
    <item><p>Γραμμές 1-4: Πρέπει να βεβαιωθούμε ότι η συνάρτηση επανάκλησής μας ταιριάζει με την απαιτούμενη υπογραφή για το σήμα <code>button_clicked_event</code>. Για το παράδειγμά μας, θα χρησιμοποιήσουμε μόνο το πρώτο όρισμα, το <code>ClutterActor</code> που στην πραγματικότητα πατήθηκε.</p>
<note>
  <p>Λίγες λέξεις για τα ορίσματα που δεν χρησιμοποιούμε σε αυτό το παράδειγμα. Ο <code>ClutterEvent</code> είναι διαφορετικός ανάλογα με τι συμβάν επεξεργάζεται. Για παράδειγμα, ένα συμβάν πλήκτρου παράγει ένα <code>ClutterKeyEvent</code> από το οποίο μπορείτε να πάρετε το πλήκτρο που πατήθηκε μεταξύ άλλων πληροφοριών. Για τα συμβάντα κλικ του ποντικιού παίρνετε <code>ClutterButtonEvent</code> από το οποίο μπορείτε να πάρετε τις τιμές <code>x</code> και <code>y</code>. Δείτε την τεκμηρίωση του Clutter για άλλους τύπους <code>ClutterEvent</code>.</p>
  <p>Ο <code>user_data</code> είναι τι χρησιμοποιεί κάποιος για να περάσει δεδομένα στη συνάρτηση. Ένας δείκτης σε οποιοδήποτε τύπο δεδομένων μπορεί να περαστεί. Εάν χρειαζόσαστε πολλαπλά δεδομένα να περαστούν στην επανάκληση, μπορείτε να τοποθετήσετε τα δεδομένα σε μια δομή και να περάσετε τη διεύθυνσή του.</p>
</note></item>
    <item><p>Γραμμή 7: Προδιατάσσουμε μια στατική σημαία για εντοπισμό της κατάστασης στην οποία είμαστε: κατάσταση τοίχου ή κατάσταση εστίασης. Ξεκινάμε σε κατάσταση τοίχου, έτσι καμιά εικόνα δεν έχει εστίαση. Έτσι, ορίζουμε τη σημαία σε <code>FALSE</code> αρχικά.</p></item>
    <item><p>Γραμμή 9: Αυτή η γραμμή κώδικα τρέχει μια προσαρμοσμένη συνάρτηση, <code>foreach_set_focus_state</code>, για κάθε στοιχείο στη <code>actor_list</code> μας, περνώντας τη διεύθυνση στη σημαία <code>is_focused</code>. Θα δούμε τον ορισμό της συνάρτησης <code>foreach_set_focus_state</code> στην επόμενη ενότητα.</p></item>
    <item><p>Γραμμές 13-19: Φτάνοντας αυτόν τον κώδικα σημαίνει ότι μια εικόνα που έχει τρέχουσα εστίαση και θέλουμε να επιστρέψει σε κατάσταση τοίχου. Η συνάρτηση <code>clutter_actor_animate</code> χρησιμοποιείται για την κίνηση μιας ιδιότητας του <code>ClutterActor</code> ή ιδιοτήτων από την τρέχουσες καταστάσεις στις συγκεκριμένες καταστάσεις. Τα ορίσματα είναι όπως ακολουθεί:</p>
<list type="numbered">
  <item><p>Η διεύθυνση του <code>ClutterActor</code> για κίνηση</p></item>
  <item><p>Η κατάσταση κίνησης για χρήση. Εδώ χρησιμοποιούμε <code>CLUTTER_LINEAR</code> έτσι ώστε να έχουμε μια σταθερή ταχύτητα για κίνηση.</p></item>
  <item><p>Η διάρκεια της κίνησης σε ms. Επέλεξα 500 ms για αυτό το παράδειγμα.</p></item>
  <item><p>Τα υπολειπόμενα ορίσματα είναι ζεύγη ιδιότητας/τιμής. Εδώ θέλουμε να ορίσουμε την τιμή <code>x</code> στην αρχική τιμή <code>x</code>, αυτός ο <code>ClutterActor</code> ήταν πριν μεταφερθεί σε εστίαση.</p></item>
  <item><p>Το τελευταίο όρισμα πρέπει πάντοτε να είναι <code>NULL</code> για να δείξει ότι δεν υπάρχουν περισσότερες ιδιότητες να οριστούν.</p></item>
</list>
<note><p>Η ιδιότητα <code>depth</code> χρειάζεται περισσότερη εξήγηση. Χρειαζόμαστε να ανυψώσουμε την εστιασμένη εικόνα, έτσι ώστε να μην ολισθήσει πίσω από άλλο <code>ClutterActor</code>. Σε αυτή την ενότητα επιστρέφουμε στο ίδιο βάθος όπως οι άλλες στον τοίχο.</p>
<p>Το βάθος επίσης καθορίζει ποιος <code>ClutterActor</code> δέχεται συμβάντα. Ένας <code>ClutterActor</code> με υψηλότερη τιμή βάθους δέχεται τα συμβάντα κλικ και μπορεί να επιλέξει εάν το συμβάν στέλνεται στο <code>ClutterActor</code> κάτω από αυτό. Θα δούμε πώς δουλεύει αυτό σε λίγα βήματα.</p></note>
    </item>
    <item><p>Γραμμή 24: φτάνοντας αυτή τη γραμμή του κώδικα σημαίνει ότι είμαστε προς το παρόν στην κατάσταση τοίχου και πρόκειται να δώσουμε μια <code>ClutterActor</code> εστίαση. Εδώ αποθηκεύουμε την αρχική θέση, έτσι ώστε να μπορούμε να επιστρέψουμε αργότερα.</p></item>
    <item><p>Γραμμή 25: ορίζοντας την ιδιότητα <code>reactive</code> του <code>ClutterActor</code> σε <code>TRUE</code> κάνει το <code>ClutterActor</code> να αντιδράσει σε συμβάντα. Σε αυτή την εστιασμένη κατάσταση ο μόνος <code>ClutterActor</code> που θέλουμε να δεχθεί συμβάντα θα είναι ο προβαλλόμενος <code>ClutterActor</code>. Κλικ στο <code>ClutterActor</code> θα επιστρέψει στην αρχική του θέση.</p></item>
    <item><p>Γραμμές 27-33: Αυτό είναι όμοιο με την παραπάνω ομάδα κώδικα. Σημειώστε ότι ορίζουμε το βάθος ανύψωσης του πάνω από τις άλλες εικόνες.</p></item>
    <item><p>Γραμμή 37: Εδώ εναλλάσσουμε τη σημαία <code>is_focused</code> στην τρέχουσα κατάσταση.</p></item>
<item><p>Όπως αναφέρθηκε προηγουμένως, ο <code>ClutterActor</code> με υψηλότερες τιμές <code>depth</code> δέχεται συμβάντα αλλά μπορούν να επιτρέψουν <code>ClutterActor</code> από κάτω τους να δεχθούν επίσης συμβάντα. Επιστροφή σε <code>TRUE</code> θα σταματήσει τα συμβάντα από το να συνεχίσουν, ενώ <code>FALSE</code> θα συνεχίσει τα συμβάντα.</p>
 <note>
   <p>Να θυμόσαστε, όμως, ότι για αποδοχή συμβάντων το <code>ClutterActor</code> πρέπει να οριστεί σε <code>reactive</code>.</p>
 </note>
</item>
 </list>
 <p>Το παρακάτω είναι μια συνάρτηση διευκόλυνσης που πέρασε σε <code>g_slist_foreach</code>.</p>
 <code mime="text/x-csrc" style="numbered"><![CDATA[
static void
foreach_set_focus_state(gpointer data, gpointer user_data)
{
    ClutterActor *actor = CLUTTER_ACTOR(data);
    gboolean is_reactive = *((gboolean*)user_data);

    clutter_actor_set_reactive(actor, is_reactive);
}]]></code>
<list>
  <item><p>Γραμμές 2-5: Η υπογραφή αυτής της συνάρτησης απαιτεί δύο <code>gpointer</code>. Το πρώτο είναι ένας δείκτης στο <code>ClutterActor</code> που η <code>GSList</code> μας κρατά και ο άλλος είναι η σημαία <code>is_focused</code> που περάσαμε στην προηγούμενη ενότητα. Θέλουμε να τα αλλάξουμε και να τα αποθηκεύσουμε για εύκολη χρήση.</p></item>
  <item><p>Γραμμή 7: Ανάλογα με ποια τιμή Μπουλ πέρασε, ο <code>ClutterActor</code> θα οριστεί να απαντήσει ή όχι στα συμβάντα.</p></item>
</list>
</section>

<section id="run">
  <title>Κατασκευή και εκτέλεση της εφαρμογής</title>
  <p>Όλος ο κώδικας πρέπει τώρα να είναι έτοιμος. Τώρα χρειαζόσαστε μερικές εικόνες για φόρτωση. Από προεπιλογή, οι εικόνες φορτώνονται από έναν κατάλογο <file>berlin_images</file>. Εάν θέλετε, μπορείτε να αλλάξετε τη γραμμή <code>#define IMAGE_DIR_PATH</code> κοντά στην κορυφή για να αναφερθείτε στον κατάλογο φωτογραφιών, ή να δημιουργήσετε ένα κατάλογο <file>berlin_images</file> με κλικ στο <guiseq><gui>έργο</gui><gui>νέος κατάλογος...</gui></guiseq> και δημιουργία ενός καταλόγου <file>berlin_images</file> ως υποκαταλόγου του καταλόγου <file>photo-wall</file>. Βεβαιωθείτε ότι βάλατε τουλάχιστον δώδεκα εικόνες στον κατάλογο!</p>
  <p>Όταν τελειώσετε, κλικ <guiseq><gui>κατασκευή</gui><gui>κατασκευή έργου</gui></guiseq> για να κατασκευάσετε οτιδήποτε ξανά, έπειτα <guiseq><gui>τρέξιμο</gui><gui>εκτέλεση</gui></guiseq> για έναρξη της εφαρμογής.</p>
  <p>Εάν δεν το έχετε ήδη κάνει, επιλέξτε την εφαρμογή <file>Debug/src/photo-wall</file> στον διάλογο που εμφανίζεται. Τελικά πατήστε <gui>εκτέλεση</gui> και απολαύστε το!</p>
</section>

<section id="impl">
 <title>Υλοποίηση αναφοράς</title>
 <p>Αν αντιμετωπίσετε πρόβλημα με το μάθημα, συγκρίνετε τον κώδικά σας με αυτόν <link href="photo-wall/photo-wall.c">κώδικας αναφοράς</link>.</p>
</section>

</page>
