diff --git a/legacy/evas/doc/examples.dox b/legacy/evas/doc/examples.dox index d061246223..35866dbd98 100644 --- a/legacy/evas/doc/examples.dox +++ b/legacy/evas/doc/examples.dox @@ -16,6 +16,8 @@ * @ref Example_Evas_Aspect_Hints * * @ref Example_Evas_Size_Hints + * + * @ref Example_Evas_Stacking */ /** @@ -68,3 +70,51 @@ * @include evas-hints.c * @example evas-hints.c */ + +/** + * @page Example_Evas_Stacking Evas object stacking functions + * @dontinclude evas-stacking.c + * + * In this example, we illustrate how to stack objects in a custom + * manner and how to deal with layers. + * + * We have three objects of interest in it -- white background, red + * rectangle, green rectangle and blue rectangle. + * @skip d.bg = evas_object_rectangle_add(d.canvas); + * @until evas_object_resize(d.bg, WIDTH, HEIGHT); + * @skip d.rects[2] = evas_object_rectangle_add(d.canvas); + * @until evas_object_show(d.rects[0]); + * @dontinclude evas-stacking.c + * Like in other Evas examples, one interacts with it be means of key commands: + * @skip "commands are:\n" + * @until "\th - print help\n"); + * At any given point, like seem above, you'll be operating one rectangle only. + * Try stacking it below an adjacent object with "b": + * @skip evas_object_stack_below(d.rects[d.cur_rect], neighbour); + * @until evas_object_stack_below(d.rects[d.cur_rect], neighbour); + * @dontinclude evas-stacking.c + * "a" will do the opposite: + * @skip evas_object_stack_above(d.rects[d.cur_rect], neighbour); + * @until evas_object_stack_above(d.rects[d.cur_rect], neighbour); + * To bring it directly to the top/bottom, use "t"/"m", respectively: + * @dontinclude evas-stacking.c + * @skip evas_object_raise(d.rects[d.cur_rect]); + * @until evas_object_raise(d.rects[d.cur_rect]); + * @skip evas_object_lower(d.rects[d.cur_rect]); + * @until evas_object_lower(d.rects[d.cur_rect]); + * At any time, use the "s" command to see the status of the + * ordering. It will show the background's ordering too. Note that it + * also shows the @b layer for this object. It starts at a @b + * different layer than the others. Use "l" to change its layer + * (higher layer numbers mean higher layers). If the background is on + * the same layer as the others (0), you'll see it interact with them + * on the ordering. If it's in the layer above, no matter what you do, + * you'll see nothing but the white rectangle: it covers the other + * layers. For the initial layer (-1), it will never mess nor occlude + * the others. + * + * The full example follows. + * + * @include evas-stacking.c + * @example evas-stacking.c + */ diff --git a/legacy/evas/src/examples/Makefile.am b/legacy/evas/src/examples/Makefile.am index e7d8f563e1..04883a1577 100644 --- a/legacy/evas/src/examples/Makefile.am +++ b/legacy/evas/src/examples/Makefile.am @@ -61,6 +61,10 @@ pkglib_PROGRAMS += evas_hints evas_hints_SOURCES = evas-hints.c evas_hints_LDADD = $(top_builddir)/src/lib/libevas.la @ECORE_EVAS_LIBS@ +pkglib_PROGRAMS += evas_stacking +evas_stacking_SOURCES = evas-stacking.c +evas_stacking_LDADD = $(top_builddir)/src/lib/libevas.la @ECORE_EVAS_LIBS@ + #the ones using ecore_evas and edje follow AM_CPPFLAGS += @EDJE_CFLAGS@ @@ -94,7 +98,8 @@ files_DATA += \ $(srcdir)/evas-object-manipulation.c \ $(srcdir)/evas-events.c \ $(srcdir)/evas-aspect-hints.c \ - $(srcdir)/evas-hints.c + $(srcdir)/evas-hints.c \ + $(srcdir)/evas-stacking.c endif EXTRA_DIST = $(EDCS) \ diff --git a/legacy/evas/src/examples/evas-stacking.c b/legacy/evas/src/examples/evas-stacking.c new file mode 100644 index 0000000000..559d2e9a21 --- /dev/null +++ b/legacy/evas/src/examples/evas-stacking.c @@ -0,0 +1,281 @@ +/** + * Simple Evas example illustrating objects stacking and + * canvas layers. + * + * You'll need at least one engine built for it (excluding the buffer + * one) and the png image loader also built. See stdout/stderr for + * output. + * + * @verbatim + * gcc -o evas-stacking evas-stacking.c `pkg-config --libs --cflags ecore-evas edje` + * @endverbatim + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include +#include + +#define WIDTH 320 +#define HEIGHT 320 + +struct test_data +{ + Ecore_Evas *ee; + Evas *canvas; + Evas_Object *bg; + Evas_Object *rects[3]; /* red, green, blue */ + int layers[3]; /* default, below it, above it */ + int cur_rect, cur_layer; +}; + +static struct test_data d = {0}; + +/* here just to keep our example's window size and background image's + * size in synchrony */ +static void +_canvas_resize_cb(Ecore_Evas *ee) +{ + int w, h; + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + evas_object_resize(d.bg, w, h); +} + +/* use the following commands to interact with this example - 'h' is + * the key for help */ +static void +_on_keydown(void *data __UNUSED__, + Evas *evas __UNUSED__, + Evas_Object *o __UNUSED__, + void *einfo) +{ + Evas_Event_Key_Down *ev = einfo; + const char *name = evas_object_name_get(d.rects[d.cur_rect]); + + if (strcmp(ev->keyname, "h") == 0) /* print help */ + { + fprintf(stdout, + "commands are:\n" + "\tc - change the target rectangle to operate on\n" + "\ta - stack target rectangle one level above\n" + "\tb - stack target rectangle one level below\n" + "\tt - stack target rectangle up to the top of its layer\n" + "\tm - stack target rectangle down to the bottom of its layer\n" + "\ts - print current stacking information\n" + "\tl - change background rectangle's layer\n" + "\th - print help\n"); + return; + } + + if (strcmp(ev->keyname, "s") == 0) /* get status of the + * rectangles WRT size + * hints */ + { + Evas_Object *rect; + + fprintf(stdout, "Order of stacking, from top to bottom, is: "); + + rect = evas_object_top_get(evas); + fprintf(stdout, "%s", evas_object_name_get(rect)); + + rect = evas_object_below_get(rect); + while (rect) + { + fprintf(stdout, ", %s", evas_object_name_get(rect)); + rect = evas_object_below_get(rect); + } + + fprintf(stdout, ".\n"); + + fprintf(stdout, "Current target rectangle is %s\n", + evas_object_name_get(d.rects[d.cur_rect])); + + fprintf(stdout, "Background rectangle's layer is %d\n", + evas_object_layer_get(d.bg)); + + return; + } + + if (strcmp(ev->keyname, "l") == 0) /* change background rectangle's layer */ + { + d.cur_layer = (d.cur_layer + 1) % 3; + evas_object_layer_set(d.bg, d.layers[d.cur_layer]); + + fprintf(stdout, "Changing background rectangle's layer to %d\n", + d.layers[d.cur_layer]); + return; + } + + if (strcmp(ev->keyname, "c") == 0) /* change rectangle to operate on */ + { + d.cur_rect = (d.cur_rect + 1) % 3; + + fprintf(stdout, "Changing target rectangle to the %s one\n", + evas_object_name_get(d.rects[d.cur_rect])); + return; + } + + if (strcmp(ev->keyname, "t") == 0) /* bring target to top */ + { + Evas_Object *neighbour; + + evas_object_raise(d.rects[d.cur_rect]); + + fprintf(stdout, "%s rectangle was re-stacked to the top if its layer\n", + name); + + neighbour = evas_object_below_get(d.rects[d.cur_rect]); + fprintf(stdout, "Below of %s rect is %s\n", name, + neighbour ? evas_object_name_get(neighbour) : "no object"); + return; + } + + if (strcmp(ev->keyname, "m") == 0) /* bring target to bottom */ + { + Evas_Object *neighbour; + + evas_object_lower(d.rects[d.cur_rect]); + + fprintf(stdout, + "%s rectangle was re-stacked to the bottom if its layer\n", + name); + + neighbour = evas_object_below_get(d.rects[d.cur_rect]); + fprintf(stdout, "Below of %s rect is %s\n", name, + neighbour ? evas_object_name_get(neighbour) : "no object"); + return; + } + + if (strcmp(ev->keyname, "a") == 0) /* stack target above */ + { + Evas_Object *neighbour = evas_object_above_get(d.rects[d.cur_rect]); + + if (!neighbour || (evas_object_layer_get(d.rects[d.cur_rect]) != + evas_object_layer_get(neighbour))) + return; + + evas_object_stack_above(d.rects[d.cur_rect], neighbour); + + fprintf(stdout, "%s rectangle was re-stacked one level above\n", name); + + neighbour = evas_object_above_get(d.rects[d.cur_rect]); + fprintf(stdout, "Above of %s rect is %s\n", name, + neighbour ? evas_object_name_get(neighbour) : "no object"); + + neighbour = evas_object_below_get(d.rects[d.cur_rect]); + fprintf(stdout, "Below of %s rect is %s\n", name, + neighbour ? evas_object_name_get(neighbour) : "no object"); + return; + } + + if (strcmp(ev->keyname, "b") == 0) /* stack target below */ + { + Evas_Object *neighbour = evas_object_below_get(d.rects[d.cur_rect]); + + if (!neighbour || (evas_object_layer_get(d.rects[d.cur_rect]) != + evas_object_layer_get(neighbour))) + return; + + evas_object_stack_below(d.rects[d.cur_rect], neighbour); + + fprintf(stdout, "%s rectangle was re-stacked one level below\n", name); + + neighbour = evas_object_above_get(d.rects[d.cur_rect]); + fprintf(stdout, "Above of %s rect is %s\n", name, + neighbour ? evas_object_name_get(neighbour) : "no object"); + + neighbour = evas_object_below_get(d.rects[d.cur_rect]); + + fprintf(stdout, "Below of %s rect is %s\n", name, + neighbour ? evas_object_name_get(neighbour) : "no object"); + return; + } +} + +static void +_on_destroy(Ecore_Evas *ee __UNUSED__) +{ + ecore_main_loop_quit(); +} + +int +main(void) +{ + if (!ecore_evas_init()) + return EXIT_FAILURE; + + /* this will give you a window with an Evas canvas under the first + * engine available */ + d.ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL); + if (!d.ee) + goto error; + + ecore_evas_callback_destroy_set(d.ee, _on_destroy); + ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb); + ecore_evas_show(d.ee); + + /* the canvas pointer, de facto */ + d.canvas = ecore_evas_get(d.ee); + + d.bg = evas_object_rectangle_add(d.canvas); + evas_object_name_set(d.bg, "background"); /* white bg */ + evas_object_color_set(d.bg, 255, 255, 255, 255); + evas_object_move(d.bg, 0, 0); + evas_object_resize(d.bg, WIDTH, HEIGHT); + + d.layers[0] = evas_object_layer_get(d.bg); + d.layers[1] = d.layers[0] - 1; + d.layers[2] = d.layers[0] + 1; + + d.cur_layer = 1; + evas_object_layer_set(d.bg, d.layers[d.cur_layer]); /* let's start with it + * below the default + * layer */ + + evas_object_show(d.bg); + + evas_object_focus_set(d.bg, EINA_TRUE); + evas_object_event_callback_add( + d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL); + + d.rects[2] = evas_object_rectangle_add(d.canvas); + evas_object_name_set(d.rects[2], "blue"); + evas_object_color_set(d.rects[2], 0, 0, 255, 255); + + evas_object_resize(d.rects[2], WIDTH / 2.2, WIDTH / 2.2); + evas_object_move(d.rects[2], WIDTH / 6, WIDTH / 4.5); + evas_object_show(d.rects[2]); + + d.rects[1] = evas_object_rectangle_add(d.canvas); + evas_object_name_set(d.rects[1], "green"); + evas_object_color_set(d.rects[1], 0, 255, 0, 255); + + evas_object_resize(d.rects[1], WIDTH / 2.2, WIDTH / 2.2); + evas_object_move(d.rects[1], WIDTH / 2.5, WIDTH / 7); + evas_object_show(d.rects[1]); + + d.rects[0] = evas_object_rectangle_add(d.canvas); + evas_object_name_set(d.rects[0], "red"); + evas_object_color_set(d.rects[0], 255, 0, 0, 255); + + evas_object_resize(d.rects[0], WIDTH / 2.2, WIDTH / 2.2); + evas_object_move(d.rects[0], WIDTH / 3, WIDTH / 2.5); + evas_object_show(d.rects[0]); + + ecore_main_loop_begin(); + + ecore_evas_shutdown(); + return 0; + +error: + fprintf(stderr, "you got to have at least one evas engine built and linked" + " up to ecore-evas for this example to run properly.\n"); + return -1; +} diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index adae01fa52..11c1887278 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -2668,9 +2668,12 @@ EAPI const Eina_List *evas_font_path_list (const Evas *e) EINA_WA * Methods that are broadly used, like those that change the color, * clippers and geometry of an Evas object. * - * A thorough example on this group of functions can be seen @ref + * An example on the most used functions in this group can be seen @ref * Example_Evas_Object_Manipulation "here". * + * For function dealing with stacking, the examples are gathered @ref + * Example_Evas_Stacking "here". + * * @ingroup Evas_Object_Group */ @@ -2847,25 +2850,37 @@ EAPI Eina_Bool evas_object_focus_get (const Evas_Object *obj /** - * Sets the layer of the evas that the given object will be part of. - * - * It is not possible to change the layer of a smart object's child. + * Sets the layer of the its canvas that the given object will be part + * of. * * @param obj The given Evas object. * @param l The number of the layer to place the object on. - * Between #EVAS_LAYER_MIN and #EVAS_LAYER_MAX. + * Must be between #EVAS_LAYER_MIN and #EVAS_LAYER_MAX. + * + * If you don't use this function, you'll be dealing with an @b unique + * layer of objects, the default one. Additional layers are handy when + * you don't want a set of objects to interfere with another set with + * regard to @b stacking. Two layers are completely disjoint in that + * matter. + * + * This is a low-level function, which you'd be using when something + * should be always on top, for example. + * + * @warning Be careful, it doesn't make sense to change the layer of + * smart objects' children. Smart objects have a layer of their own, + * which should contain all their children objects. + * + * @see evas_object_layer_get() */ EAPI void evas_object_layer_set (Evas_Object *obj, short l) EINA_ARG_NONNULL(1); /** - * Retrieves the layer of the evas that the given object is part of. + * Retrieves the layer of its canvas that the given object is part of. * - * Be careful, it doesn't make sense to change the layer of smart object's - * child. So the returned value could be wrong in some case. Don't rely on - * it's accuracy. + * @param obj The given Evas object to query layer from + * @return Number of the its layer * - * @param obj The given Evas object. - * @return Number of the layer. + * @see evas_object_layer_set() */ EAPI short evas_object_layer_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; @@ -3249,9 +3264,16 @@ EAPI Evas *evas_object_evas_get (const Evas_Object *obj EAPI const char *evas_object_type_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; /** - * Raise @p obj to the top of its layer. + * Raise @p obj to the bottom of its layer. * * @param obj the object to raise + * + * @p obj will, then, be the highest one in the layer it belongs + * to. Object on other layers won't get touched. + * + * @see evas_object_stack_above() + * @see evas_object_stack_below() + * @see evas_object_lower() */ EAPI void evas_object_raise (Evas_Object *obj) EINA_ARG_NONNULL(1); @@ -3259,50 +3281,102 @@ EAPI void evas_object_raise (Evas_Object *obj) EINA * Lower @p obj to the bottom of its layer. * * @param obj the object to lower + * + * @p obj will, then, be the lowest one in the layer it belongs + * to. Objects on other layers won't get touched. + * + * @see evas_object_stack_above() + * @see evas_object_stack_below() + * @see evas_object_raise() */ EAPI void evas_object_lower (Evas_Object *obj) EINA_ARG_NONNULL(1); /** * Stack @p obj immediately above @p above * - * If @p obj is a member of a smart object, then @p above must also be - * a member of the same smart object. - * - * Similarly, if @p obj is not a member of smart object, @p above may - * not either. - * * @param obj the object to stack * @param above the object above which to stack + * + * Objects, in a given canvas, are stacked in the order they get added + * to it. This means that, if they overlap, the highest ones will + * cover the lowest ones, in that order. This function is a way to + * change the stacking order for the objects. + * + * This function is intended to be used with objects belonging to + * the same layer in a given canvas, otherwise it will fail (and + * accomplish nothing). + * + * If you have smart objects on your canvas and @p obj is a member of + * one of them, then @p above must also be a member of the same + * smart object. + * + * Similarly, if @p obj is not a member of a smart object, @p above + * must not be either. + * + * @see evas_object_layer_get() + * @see evas_object_layer_set() + * @see evas_object_stack_below() */ EAPI void evas_object_stack_above (Evas_Object *obj, Evas_Object *above) EINA_ARG_NONNULL(1, 2); /** * Stack @p obj immediately below @p below * - * If @p obj is a member of a smart object, then @p below must also be - * a member of the same smart object. - * - * Similarly, if @p obj is not a member of smart object, @p below may - * not either. - * * @param obj the object to stack * @param below the object below which to stack + * + * Objects, in a given canvas, are stacked in the order they get added + * to it. This means that, if they overlap, the highest ones will + * cover the lowest ones, in that order. This function is a way to + * change the stacking order for the objects. + * + * This function is intended to be used with objects belonging to + * the same layer in a given canvas, otherwise it will fail (and + * accomplish nothing). + * + * If you have smart objects on your canvas and @p obj is a member of + * one of them, then @p below must also be a member of the same + * smart object. + * + * Similarly, if @p obj is not a member of a smart object, @p below + * must not be either. + * + * @see evas_object_layer_get() + * @see evas_object_layer_set() + * @see evas_object_stack_below() */ EAPI void evas_object_stack_below (Evas_Object *obj, Evas_Object *below) EINA_ARG_NONNULL(1, 2); /** - * Get the Evas object above @p obj + * Get the Evas object stacked right above @p obj + * + * @param obj an #Evas_Object + * @return the #Evas_Object directly above @p obj, if any, or @c NULL, + * if none + * + * This function will traverse layers in its search, if there are + * objects on layers above the one @p obj is placed at. + * + * @see evas_object_layer_get() + * @see evas_object_layer_set() + * @see evas_object_below_get() * - * @param obj an Evas_Object - * @return the Evas_Object directly above */ EAPI Evas_Object *evas_object_above_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; /** - * Get the Evas object below @p obj + * Get the Evas object stacked right below @p obj * - * @param obj an Evas_Object - * @return the Evas_Object directly below + * @param obj an #Evas_Object + * @return the #Evas_Object directly below @p obj, if any, or @c NULL, + * if none + * + * This function will traverse layers in its search, if there are + * objects on layers below the one @p obj is placed at. + * + * @see evas_object_layer_get() + * @see evas_object_layer_set() + * @see evas_object_below_set() */ EAPI Evas_Object *evas_object_below_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; @@ -4792,6 +4866,11 @@ EAPI Evas_Render_Op evas_object_render_op_get (const Evas_Obje * @ingroup Evas_Object_Group */ +/** + * @addtogroup Evas_Object_Group_Find + * @{ + */ + /** * Retrieve the object that currently has focus. * @@ -4892,23 +4971,45 @@ EAPI Evas_Object *evas_object_top_in_rectangle_get (const Evas *e, Evas_Co EAPI Eina_List *evas_objects_at_xy_get (const Evas *e, Evas_Coord x, Evas_Coord y, Eina_Bool include_pass_events_objects, Eina_Bool include_hidden_objects) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; EAPI Eina_List *evas_objects_in_rectangle_get (const Evas *e, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool include_pass_events_objects, Eina_Bool include_hidden_objects) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; - /** - * Get the lowest Evas object on the Evas @p e + * Get the lowest (stacked) Evas object on the canvas @p * - * @param e an Evas - * @return the lowest object + * @param e a valid canvas pointer + * @return a pointer to the lowest object on it, if any, or @c NULL, + * otherwise + * + * This function will take all populated layers in the canvas into + * account, getting the lowest object for the lowest layer, naturally. + * + * @see evas_object_layer_get() + * @see evas_object_layer_set() + * @see evas_object_below_set() + * @see evas_object_above_set() */ EAPI Evas_Object *evas_object_bottom_get (const Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; /** - * Get the highest Evas object on the Evas @p e + * Get the highest (stacked) Evas object on the canvas @p * - * @param e an Evas - * @return the highest object + * @param e a valid canvas pointer + * @return a pointer to the highest object on it, if any, or @c NULL, + * otherwise + * + * This function will take all populated layers in the canvas into + * account, getting the highest object for the highest layer, + * naturally. + * + * @see evas_object_layer_get() + * @see evas_object_layer_set() + * @see evas_object_below_set() + * @see evas_object_above_set() */ EAPI Evas_Object *evas_object_top_get (const Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; +/** + * @} + */ + /** * @defgroup Evas_Object_Group_Interceptors Object Method Interceptors *