Ctxpopup example

In this example we have a list with two items, when either item is clicked a ctxpopup for it will be shown. Our two ctxpopups are quite different, the one for the first item is a vertical and it's items contain both labels and icons, the one for the second item is horizontal and it's items have icons but not labels.

We will begin examining our example code by looking at the callback we'll use when items in the ctxpopup are clicked. It's very simple, all it does is print the label present in the ctxpopup item:

//Compile with:
//gcc -o ctxpopup_example_01 ctxpopup_example_01.c -g `pkg-config --cflags --libs elementary`
#include <Elementary.h>
static int list_mouse_down = 0;
static void
_dismissed_cb(void *data, Evas_Object *obj, void *event_info)
{
evas_object_del(obj);
}

Next we examine a function that creates ctxpopup items, it was created to avoid repeating the same code whenever we needed to add an item to our ctxpopup. Our function creates an icon from the standard set of icons, and then creates the item, with the label received as an argument. We also set the callback to be called when the item is clicked:

static void
_ctxpopup_item_cb(void *data, Evas_Object *obj, void *event_info)
{
printf("ctxpopup item selected: %s\n", elm_object_item_text_get(event_info));
}

Finally we have the function that will create the ctxpopup for the first item in our list. This one is somewhat more complex though, so let's go through it in parts. First we declare our variable and add the ctxpopup:

Elm_Object_Item *item_new(Evas_Object *ctxpopup, const char * label, const char *icon)
{
Evas_Object *ic = elm_icon_add(ctxpopup);
elm_icon_standard_set(ic, icon);
elm_image_resizable_set(ic, EINA_FALSE, EINA_FALSE);
return elm_ctxpopup_item_append(ctxpopup, label, ic, _ctxpopup_item_cb, NULL);
}
static void
_list_item_cb(void *data, Evas_Object *obj, void *event_info)
{
Evas_Object *ctxpopup;
Elm_Object_Item *it;
Evas_Coord x,y;
if (list_mouse_down > 0) return;
ctxpopup = elm_ctxpopup_add(obj);

Next we create a bunch of items for our ctxpopup, marking two of them as disabled just so we can see what that will look like:

evas_object_smart_callback_add(ctxpopup, "dismissed", _dismissed_cb, NULL);
item_new(ctxpopup, "Go to home folder", "home");
item_new(ctxpopup, "Save file", "file");
item_new(ctxpopup, "Delete file", "delete");
it = item_new(ctxpopup, "Navigate to folder", "folder");
elm_object_item_disabled_set(it, EINA_TRUE);
item_new(ctxpopup, "Edit entry", "edit");
it = item_new(ctxpopup, "Set date and time", "clock");
elm_object_item_disabled_set(it, EINA_TRUE);

Then we ask evas where the mouse pointer was so that we can have our ctxpopup appear in the right place, set a maximum size for the ctxpopup, move it and show it:

evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x, &y);
evas_object_move(ctxpopup, x, y);
evas_object_show(ctxpopup);

And last we mark the list item as not selected:

elm_list_item_selected_set(event_info, EINA_FALSE);
}

Our next function is the callback that will create the ctxpopup for the second list item, it is very similar to the previous function. A couple of interesting things to note is that we ask our ctxpopup to be horizontal, and that we pass NULL as the label for every item:

static void
_list_item_cb2(void *data, Evas_Object *obj, void *event_info)
{
Evas_Object *ctxpopup;
Elm_Object_Item *it;
Evas_Coord x,y;
if (list_mouse_down > 0) return;
ctxpopup = elm_ctxpopup_add(obj);
evas_object_smart_callback_add(ctxpopup, "dismissed", _dismissed_cb, NULL);
elm_ctxpopup_horizontal_set(ctxpopup, EINA_TRUE);
item_new(ctxpopup, NULL, "home");
item_new(ctxpopup, NULL, "file");
item_new(ctxpopup, NULL, "delete");
item_new(ctxpopup, NULL, "folder");
it = item_new(ctxpopup, NULL, "edit");
elm_object_item_disabled_set(it, EINA_TRUE);
item_new(ctxpopup, NULL, "clock");
evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x, &y);
evas_object_move(ctxpopup, x, y);
evas_object_show(ctxpopup);
elm_list_item_selected_set(event_info, EINA_FALSE);
}

And with all of that in place we can now get to our main function where we create the window, the list, the list items and run the main loop:

static void
_list_mouse_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
list_mouse_down++;
}
static void
_list_mouse_up(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
list_mouse_down--;
}
static void
_win_del(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
list_mouse_down = 0;
}
EAPI_MAIN int
elm_main(int argc, char **argv)
{
Evas_Object *win, *list;
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
win = elm_win_util_standard_add("Contextual Popup", "Contextual Popup");
evas_object_smart_callback_add(win, "delete,request", _win_del, NULL);
elm_win_autodel_set(win, EINA_TRUE);
list = elm_list_add(win);
evas_object_event_callback_add(list, EVAS_CALLBACK_MOUSE_DOWN,
_list_mouse_down, NULL);
evas_object_event_callback_add(list, EVAS_CALLBACK_MOUSE_UP,
_list_mouse_up, NULL);
evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_win_resize_object_add(win, list);
elm_list_mode_set(list, ELM_LIST_COMPRESS);
elm_list_item_append(list, "Ctxpopup with icons and labels", NULL, NULL,
_list_item_cb, NULL);
elm_list_item_append(list, "Ctxpopup with icons only", NULL, NULL,
_list_item_cb2, NULL);
evas_object_show(list);
elm_list_go(list);
evas_object_resize(win, 400, 400);
evas_object_show(win);
elm_run();
return 0;
}
ELM_MAIN()

The example will initially look like this:

Note
  This doesn't show the ctxpopup tough, since it will only appear when we click one of the list items.

Here is what our first ctxpopup will look like:

And here the second ctxpopup: