cedric pushed a commit to branch master.

http://git.enlightenment.org/website/www-content.git/commit/?id=bcd78dd3f49c6d6b0754852a42b847a6cbcdcfde

commit bcd78dd3f49c6d6b0754852a42b847a6cbcdcfde
Author: Clément Bénier <clement.ben...@openwide.fr>
Date:   Mon Jun 29 15:59:36 2015 +0200

    Wiki pages naviframe_tutorial created: tuto + image + code c
    
    Signed-off-by: Clément Bénier <clement.ben...@openwide.fr>
    Signed-off-by: Pierre Le Magourou <pierre.lemagou...@openwide.fr>
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 media/code_c/tutorial/naviframe/naviframe.c | 227 +++++++++++++++++++++++++
 media/naviframe.png                         | Bin 0 -> 61362 bytes
 pages/docs.txt                              |   1 +
 pages/tutorial/naviframe_tutorial.txt       | 247 ++++++++++++++++++++++++++++
 4 files changed, 475 insertions(+)

diff --git a/media/code_c/tutorial/naviframe/naviframe.c 
b/media/code_c/tutorial/naviframe/naviframe.c
new file mode 100644
index 0000000..bd643ae
--- /dev/null
+++ b/media/code_c/tutorial/naviframe/naviframe.c
@@ -0,0 +1,227 @@
+#include <Elementary.h>
+
+#define __UNUSED__ __attribute__((__unused__))
+
+// NOTE: A zipper is a datastructure for an ordered set of elements and a
+// cursor in this set, meaning there are elements before the cursor (which are
+// stored inside the naviframe) and after (which are stored in the "popped"
+// list.
+struct naviframe_zipper
+{
+   Evas_Object *naviframe;
+   Eina_List *popped;
+};
+
+static struct naviframe_zipper *
+_naviframe_add(Evas_Object *parent)
+{
+   struct naviframe_zipper *z = malloc(sizeof(struct naviframe_zipper));
+   z->naviframe = elm_naviframe_add(parent);
+   z->popped = NULL;
+
+   evas_object_size_hint_weight_set(z->naviframe, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(z->naviframe, EVAS_HINT_FILL, 
EVAS_HINT_FILL);
+   evas_object_show(z->naviframe);
+   // By default, objects are destroyed when they are popped from the naviframe
+   // To save and re-use them, enable "preserve_on_pop"
+   elm_naviframe_content_preserve_on_pop_set(z->naviframe, EINA_TRUE);
+
+   return z;
+}
+
+// forward declaration of the _button function since there is a circular
+// reference below
+static Evas_Object * _button(struct naviframe_zipper *, int direction);
+
+// Save the element that is popped from the naviframe
+// callback of the prev button
+static void
+_naviframe_prev(void *data, Evas_Object *o __UNUSED__, void *event_info 
__UNUSED__)
+{
+   struct naviframe_zipper *z = data;
+   //if more than one item push in naviframe
+   if (elm_naviframe_bottom_item_get(z->naviframe) != 
elm_naviframe_top_item_get(z->naviframe))
+     {
+        z->popped = eina_list_prepend(z->popped, 
elm_naviframe_item_pop(z->naviframe));
+     }
+}
+
+// Set the first element after the current one available and push it to the
+// naviframe
+// callback of the next button
+static void
+_naviframe_next(void *data, Evas_Object *o __UNUSED__, void *event_info 
__UNUSED__)
+{
+   struct naviframe_zipper *z = data;
+   Evas_Object *label, *prev, *next;
+   const char *text;
+   Elm_Object_Item *it;
+
+   label = eina_list_data_get(z->popped);
+   z->popped = eina_list_remove_list(z->popped, z->popped);
+   if (label != NULL)
+     {
+        // The widget is saved inside the naviframe but nothing more; we need
+        // to create new buttons and set the title text again (copy the one
+        // from the label that is saved).
+        text = elm_object_text_get(label);
+        // The _button function creates a button which is either "Previous" 
(-1) or
+        // "Next" (1)
+        prev = _button(z, -1);
+        next = _button(z, 1);
+        it = elm_naviframe_item_push(z->naviframe, text, prev, next, label, 
NULL);
+     }
+}
+
+// Build either a "Previous" or a "Next" button
+static Evas_Object *
+_button(struct naviframe_zipper *z, int direction)
+{
+   Evas_Object *button;
+   Evas_Smart_Cb callback;
+   const char *text;
+   if (direction < 0)
+     {
+        text = "Previous";
+        callback = _naviframe_prev;
+     }
+   else
+     {
+        text = "Next";
+        callback = _naviframe_next;
+     }
+   button = elm_button_add(z->naviframe);
+   elm_object_text_set(button, text);
+   evas_object_smart_callback_add(button, "clicked", callback, z);
+   return button;
+}
+
+// Generic naviframe-populate function:
+// Its third (and last) parameter is a callback for customization, i.e. pushes
+// the new items to a specific position; it returns a "context" value that is
+// used between its calls and enables behaviors such as "push after the
+// previously-pushed item"
+static struct naviframe_zipper*
+_naviframe_populate_gen(Evas_Object *parent, const char *id,
+        void * (*populate_cb) (Evas_Object *nav, const char *title, Evas_Object
+            *prev, Evas_Object *next, Evas_Object *label, Elm_Object_Item 
*context)
+        )
+{
+   struct naviframe_zipper *z;
+   Evas_Object *label,*label2, *prev, *next;
+   Elm_Object_Item *context = NULL;
+   char buf[256];
+   int i;
+
+   z = _naviframe_add(parent);
+
+   for (i = 0; i < 20; i++)
+     {
+        label = elm_label_add(z->naviframe);
+        label2 = elm_label_add(z->naviframe);
+        snprintf(buf, sizeof(buf), "%s [%d]", id, i);
+        elm_object_text_set(label, buf);
+        evas_object_show(label);
+        evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        // The _button function creates a button which is either "Previous" 
(-1) or
+        // "Next" (1)
+        prev = _button(z, -1);
+        next = _button(z, 1);
+        // Use the populate_cb callback to provide the customization of the 
way the
+        // elements are added inside the naviframe
+        context = populate_cb(z->naviframe, buf, prev, next, label, context);
+     }
+   return z;
+}
+
+// Push items one after the other
+static Elm_Object_Item *
+_populate_cb__push(Evas_Object *nav, const char *title,
+        Evas_Object *prev, Evas_Object *next, Evas_Object *label,
+        Elm_Object_Item *context)
+{
+   return elm_naviframe_item_push(nav, title, prev, next, label, NULL);
+}
+
+// Push items one after the other but use insert_after for it
+static Elm_Object_Item *
+_populate_cb__push_then_insert_after(Evas_Object *nav, const char *title,
+        Evas_Object *prev, Evas_Object *next, Evas_Object *label,
+        Elm_Object_Item *context)
+{
+   if (context == NULL)
+     {
+        return elm_naviframe_item_push(nav, title, prev, next, label, NULL);
+     }
+   else
+     {
+        return elm_naviframe_item_insert_after(nav, context, title, prev, 
next, label, NULL);
+     }
+}
+
+// Push one item and repeatedly insert new items before the last inserted
+// item
+static Elm_Object_Item *
+_populate_cb__push_then_insert_before(Evas_Object *nav, const char *title,
+        Evas_Object *prev, Evas_Object *next, Evas_Object *label,
+        Elm_Object_Item *context)
+{
+   if (context == NULL)
+     {
+        return elm_naviframe_item_push(nav, title, prev, next, label, NULL);
+     }
+   else
+     {
+        return elm_naviframe_item_insert_before(nav, context, title, prev, 
next, label, NULL);
+     }
+}
+
+static void
+_delete_cb(void *data, Evas_Object *obj, void *event_info)
+{
+   struct naviframe_zipper **z = data;
+   free(*z);
+   free(*(z+1));
+   free(*(z+2));
+   free(z);
+   evas_object_del(obj);
+}
+
+EAPI_MAIN int
+elm_main(int argc, char **argv)
+{
+   Evas_Object *win;
+
+   win = elm_win_util_standard_add("Naviframe", "Naviframe Tutorial");
+   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   Evas_Object *box;
+   struct naviframe_zipper **z = malloc(3*sizeof(struct naviframe_zipper *));
+
+   box = elm_box_add(win);
+   elm_box_horizontal_set(box, EINA_FALSE);
+   elm_box_homogeneous_set(box, EINA_TRUE);
+   evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(box);
+   elm_win_resize_object_add(win, box);
+
+   z[0] = _naviframe_populate_gen(win, "Before", (void 
*)_populate_cb__push_then_insert_before);
+   elm_box_pack_end(box, (*z)->naviframe);
+
+   z[1] = _naviframe_populate_gen(win, "After", (void 
*)_populate_cb__push_then_insert_after);
+   elm_box_pack_end(box, (*(z+1))->naviframe);
+
+   z[2] = _naviframe_populate_gen(win, "Push", (void *)_populate_cb__push);
+   elm_box_pack_end(box, (*(z+2))->naviframe);
+
+   evas_object_smart_callback_add(win, "delete,request", _delete_cb, z);
+   //win 400x400 px
+   evas_object_resize(win, 400, 400);
+   evas_object_show(win);
+   elm_run();
+   return 0;
+}
+ELM_MAIN()
diff --git a/media/naviframe.png b/media/naviframe.png
new file mode 100644
index 0000000..9aee9f5
Binary files /dev/null and b/media/naviframe.png differ
diff --git a/pages/docs.txt b/pages/docs.txt
index 5301ff1..e630888 100644
--- a/pages/docs.txt
+++ b/pages/docs.txt
@@ -41,6 +41,7 @@ Go check the current available version of EFL on each 
distro/platform:
   * [[tutorial/genlist_tutorial|Genlist Tutorial]]
   * [[tutorial/panes_tutorial|Panes Tutorial]]
   * [[tutorial/form_tutorial|Form Tutorial]]
+  * [[tutorial/naviframe_tutorial|Naviframe Tutorial]]
 
 ----
 
diff --git a/pages/tutorial/naviframe_tutorial.txt 
b/pages/tutorial/naviframe_tutorial.txt
new file mode 100644
index 0000000..e3cbc68
--- /dev/null
+++ b/pages/tutorial/naviframe_tutorial.txt
@@ -0,0 +1,247 @@
+~~Title: Naviframe Tutorial~~
+==== Naviframe Tutorial ====
+
+Naviframes are containers useful for implementing interfaces with several
+screens having a previous/next relationship.
+
+{{ :naviframe.png?direct1100x439 |list}}
+
+//**__The whole code__ : **//{{/code_c/tutorial/naviframe/naviframe.c}}
+
+=== Creating Naviframes ===
+
+Naviframes are containers useful for implementing interfaces with several
+screens having a previous/next relationship.
+
+This tutorial shows a UI with three naviframes. Each naviframe is made of 20
+screens, each made up of a label
+, a title with the same text, and previous and next buttons, which are
+used to navigate between the screens.
+
+The naviframe is "one-way": elements are added, and when the user clicks on
+the "previous" button, they are removed; there is no "next" button by default.
+To add it, we define a structure that holds the naviframe object along with a
+stack of the elements that the user has popped by using the "previous" button.
+
+Note that it is possible to create the elements on-the-fly each time the
+"next" button is pressed. Both approaches are valid.
+
+<code c>
+// NOTE: A zipper is a datastructure for an ordered set of elements and a
+// cursor in this set, meaning there are elements before the cursor (which are
+// stored inside the naviframe) and after (which are stored in the "popped"
+// list.
+struct naviframe_zipper
+{
+   Evas_Object *naviframe;
+   Eina_List *popped;
+};
+</code>
+
+To add several naviframes, create a function that factors their creation and
+initializes the ''naviframe_zipper'' structure defined above.
+
+<code c>
+static struct naviframe_zipper *
+_naviframe_add(Evas_Object *parent)
+{
+   struct naviframe_zipper *z = malloc(sizeof(struct naviframe_zipper));
+   z->naviframe = elm_naviframe_add(parent);
+   z->popped = NULL;
+
+   evas_object_size_hint_weight_set(z->naviframe, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(z->naviframe, EVAS_HINT_FILL, 
EVAS_HINT_FILL);
+   evas_object_show(z->naviframe);
+   // By default, objects are destroyed when they are popped from the naviframe
+   // To save and re-use them, enable "preserve_on_pop"
+   elm_naviframe_content_preserve_on_pop_set(z->naviframe, EINA_TRUE);
+
+   return z;
+}
+</code>
+
+Create buttons that are at the top of the naviframe and allow the user to go
+back and forth between the screens. The naviframe widget builds a button for
+"previous" by default, but allows the programmers to provide their own
+buttons. It has a specific slot for the "next" button.
+
+<code c>
+// Save the element that is popped from the naviframe
+// callback of the prev button
+static void
+_naviframe_prev(void *data, Evas_Object *o __UNUSED__, void *event_info 
__UNUSED__)
+{
+   struct naviframe_zipper *z = data;
+   //if more than one item push in naviframe
+   if (elm_naviframe_bottom_item_get(z->naviframe) != 
elm_naviframe_top_item_get(z->naviframe))
+     {
+        z->popped = eina_list_prepend(z->popped, 
elm_naviframe_item_pop(z->naviframe));
+     }
+}
+
+// Set the first element after the current one available and push it to the
+// naviframe
+//callback of the next button
+static void
+_naviframe_next(void *data, Evas_Object *o __UNUSED__, void *event_info 
__UNUSED__)
+{
+   struct naviframe_zipper *z = data;
+   Evas_Object *label, *prev, *next;
+   const char *text;
+   Elm_Object_Item *it;
+
+   label = eina_list_data_get(z->popped);
+   z->popped = eina_list_remove_list(z->popped, z->popped);
+   if (label != NULL)
+     {
+        // The widget is saved inside the naviframe but nothing more; we need
+        // to create new buttons and set the title text again (copy the one
+        // from the label that is saved).
+        text = elm_object_text_get(label);
+        // The _button function creates a button which is either "Previous" 
(-1) or
+        // "Next" (1)
+        prev = _button(z, -1);
+        next = _button(z, 1);
+        it = elm_naviframe_item_push(z->naviframe, text, prev, next, label, 
NULL);
+     }
+}
+</code>
+
+When a naviframe and the pages that go inside it are built, populate it.
+
+Remember that three naviframes are created, each populated in a different way.
+The common bits have been factored out as a function and the specific parts
+are executed through a callback. The generic function is shown below.
+
+<code c>
+// Generic naviframe-populate function:
+// Its third (and last) parameter is a callback for customization, i.e. pushes
+// the new items to a specific position; it returns a "context" value that is
+// used between its calls and enables behaviors such as "push after the
+// previously-pushed item"
+static struct naviframe_zipper*
+_naviframe_populate_gen(Evas_Object *parent, const char *id,
+        void * (*populate_cb) (Evas_Object *nav, const char *title, Evas_Object
+            *prev, Evas_Object *next, Evas_Object *label, Elm_Object_Item 
*context)
+        )
+{
+   struct naviframe_zipper *z;
+   Evas_Object *label, *prev, *next;
+   Elm_Object_Item *context = NULL;
+   char buf[256];
+   int i;
+
+   z = _naviframe_add(parent);
+
+   for (i = 0; i < 20; i++)
+     {
+        label = elm_label_add(z->naviframe);
+        snprintf(buf, sizeof(buf), "%s [%d]", id, i);
+        elm_object_text_set(label, buf);
+        evas_object_show(label);
+        evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
+        // The _button function creates a button which is either "Previous" 
(-1) or
+        // "Next" (1)
+        prev = _button(z, -1);
+        next = _button(z, 1);
+        // Use the populate_cb callback to provide the customization of the 
way the
+        // elements are added inside the naviframe
+        context = populate_cb(z->naviframe, buf, prev, next, label, context);
+     }
+   return z;
+}
+</code>
+
+The prototype of the callbacks is fairly large, but that is because of the
+syntax for callbacks in C.
+
+<code c>
+// Push items one after the other
+static Elm_Object_Item *
+_populate_cb__push(Evas_Object *nav, const char *title,
+        Evas_Object *prev, Evas_Object *next, Evas_Object *label,
+        Elm_Object_Item *context)
+{
+   return elm_naviframe_item_push(nav, title, prev, next, label, NULL);
+}
+
+// Push items one after the other but use insert_after for it
+static Elm_Object_Item *
+_populate_cb__push_then_insert_after(Evas_Object *nav, const char *title,
+        Evas_Object *prev, Evas_Object *next, Evas_Object *label,
+        Elm_Object_Item *context)
+{
+   if (context == NULL)
+     {
+         return elm_naviframe_item_push(nav, title, prev, next, label, NULL);
+     }
+   else
+     {
+         return elm_naviframe_item_insert_after(nav, context, title, prev, 
next, label, NULL);
+     }
+}
+
+// Push one item and repeatedly insert new items before the last inserted
+// item
+static Elm_Object_Item *
+_populate_cb__push_then_insert_before(Evas_Object *nav, const char *title,
+        Evas_Object *prev, Evas_Object *next, Evas_Object *label,
+        Elm_Object_Item *context)
+{
+   if (context == NULL)
+     {
+        return elm_naviframe_item_push(nav, title, prev, next, label, NULL);
+     }
+   else
+     {
+        return elm_naviframe_item_insert_before(nav, context, title, prev, 
next, label, NULL);
+     }
+}
+</code>
+
+Create a window with a vertical box, which holds the three naviframes from the
+''elm_main()''.
+
+<code c>
+
+EAPI_MAIN int
+elm_main(int argc, char **argv)
+{
+   Evas_Object *win;
+
+   win = elm_win_util_standard_add("Naviframe", "Naviframe Tutorial");
+   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   Evas_Object *box;
+   struct naviframe_zipper **z = malloc(3*sizeof(struct naviframe_zipper *));
+
+   box = elm_box_add(win);
+   elm_box_horizontal_set(box, EINA_FALSE);
+   elm_box_homogeneous_set(box, EINA_TRUE);
+   evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(box);
+   elm_win_resize_object_add(win, box);
+
+   z[0] = _naviframe_populate_gen(win, "Before", 
(void*)_populate_cb__push_then_insert_before);
+   elm_box_pack_end(box, (*z)->naviframe);
+
+   z[1] = _naviframe_populate_gen(win, "After", 
(void*)_populate_cb__push_then_insert_after);
+   elm_box_pack_end(box, (*(z+1))->naviframe);
+
+   z[2] = _naviframe_populate_gen(win, "Push", (void *)_populate_cb__push);
+   elm_box_pack_end(box, (*(z+2))->naviframe);
+
+   evas_object_smart_callback_add(win, "delete,request", _delete_cb, z);
+   //win 400x400 px
+   evas_object_resize(win, 400, 400);
+   evas_object_show(win);
+   elm_run();
+   return 0;
+}
+ELM_MAIN()
+</code>
+\\
+//**__The whole code__ : **//{{/code_c/tutorial/naviframe/naviframe.c}}

-- 


Reply via email to