enlightenment/src/bin/e_gadget.c

336 lines
9.0 KiB
C

/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include "e.h"
/*
* Todo:
*
* Add module init / free callbacks
* Automate configuration loading / saving (pass in an EDD, handle the rest)
* Decide on a location / filename convention for 3rd party themes, and
* fallback to this for the "theme/modules/module_name" category
* Should the functions be done in a similar fashion to the module functions?
* (that is, set function names, used if defined in module, otherwise not).
* This would require making e_module aware of them somehow.
*
*/
static E_Gadget_Face *_e_gadget_face_new(E_Gadget *gad, E_Container *con, E_Zone *zone);
static void _e_gadget_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi);
static void _e_gadget_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi);
static void _e_gadget_free(E_Gadget *gad);
static void _e_gadget_face_cb_gmc_change(void * data, E_Gadman_Client *gmc, E_Gadman_Change change);
static void _e_gadget_face_menu_init(E_Gadget_Face *face);
static void _e_gadget_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
/**
* Create a new gadget. Takes an E_Gadget_Api struct.
* The module and name fields of the api struct are required. The rest are
* optional, however in order to be useful, at least func_face_init and
* func_face_free should be defined. The possible fields api fields are:
*
* E_Module *module - the module that contains this gadget
*
* char *name - a unique name for this module
*
* void (*func_face_init) (void *data, E_Gadget_Face *gadget_face) -
* A function that initializes the gadget's face. All evas objects should
* be drawn on gadget_face->evas.
*
* void (*func_face_free) (void *data, E_Gadget_Face *gadget_face) -
* A function that frees all memory allocated in func_face_init
*
* void (*func_change) (void *data, E_Gadget_Face *gadget_face,
* E_Gadman_Client *gmc, E_Gadman_Change change) -
* A function that is called whenever the gadget is resized.
*
* void (*func_face_menu_init) (void *data, E_Gadget_Face *gadget_face) -
* A function that initializes the gadget's face menu. This is displayed
* when the user right clicks on the gadget's face.
*
* void *data - a pointer to some data to be passed to all callbacks.
*
*/
EAPI E_Gadget *
e_gadget_new(E_Gadget_Api *api)
{
E_Gadget *gad;
Evas_List *managers, *l = NULL, *l2 = NULL, *l3 = NULL;
if (!api || !api->module || !api->name) return NULL;
gad = E_OBJECT_ALLOC(E_Gadget, E_GADGET_TYPE, _e_gadget_free);
if (!gad) return NULL;
gad->module = api->module;
e_object_ref(E_OBJECT(gad->module));
gad->name = evas_stringshare_add(api->name);
gad->funcs.face_init = api->func_face_init;
gad->funcs.face_free = api->func_face_free;
gad->funcs.change = api->func_change;
gad->funcs.face_menu_init = api->func_face_menu_init;
gad->data = api->data;
/* get all desktop evases, and call init function on them */
managers = e_manager_list();
for(l = managers; l; l = l->next)
{
E_Manager *man;
man = l->data;
for(l2 = man->containers; l2; l2 = l2->next)
{
E_Container *con;
con = l2->data;
if (api->per_zone)
{
for(l3 = con->zones; l3; l3 = l3->next)
{
E_Zone *zone;
zone = l3->data;
_e_gadget_face_new(gad, con, zone);
}
}
else
{
_e_gadget_face_new(gad, con, NULL);
}
}
}
return gad;
}
static E_Gadget_Face *
_e_gadget_face_new(E_Gadget *gad, E_Container *con, E_Zone *zone)
{
E_Gadget_Face *face;
E_Gadget_Change *change;
Evas_Object *o;
char buf[1024];
face = E_NEW(E_Gadget_Face, 1);
if (!face) return NULL;
face->gad = gad;
face->con = con;
if (zone) face->zone = zone;
else face->zone = (E_Zone *)evas_list_data(con->zones);
e_object_ref(E_OBJECT(con));
face->evas = con->bg_evas;
evas_event_freeze(face->evas);
/* create an event object */
o = evas_object_rectangle_add(con->bg_evas);
face->event_obj = o;
evas_object_layer_set(o, 2);
evas_object_repeat_events_set(o, 1);
evas_object_color_set(o, 0, 0, 0, 0);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _e_gadget_cb_mouse_down, face);
evas_object_show(o);
/* create a gadman client */
snprintf(buf, sizeof(buf), "module.%s", gad->name);
face->gmc = e_gadman_client_new(con->gadman);
e_gadman_client_zone_set(face->gmc, face->zone);
e_gadman_client_domain_set(face->gmc, buf, gad->num_faces);
/* set up some gadman defaults */
e_gadman_client_policy_set(face->gmc,
E_GADMAN_POLICY_ANYWHERE |
E_GADMAN_POLICY_HMOVE |
E_GADMAN_POLICY_VMOVE |
E_GADMAN_POLICY_HSIZE |
E_GADMAN_POLICY_VSIZE );
e_gadman_client_min_size_set(face->gmc, 4, 4);
e_gadman_client_max_size_set(face->gmc, 128, 128);
e_gadman_client_auto_size_set(face->gmc, 40, 40);
e_gadman_client_align_set(face->gmc, 1.0, 1.0);
e_gadman_client_resize(face->gmc, 40, 40);
change = E_NEW(E_Gadget_Change, 1);
if (change)
{
change->gadget = gad;
change->face = face;
face->change = change;
}
e_gadman_client_change_func_set(face->gmc, _e_gadget_face_cb_gmc_change, change);
gad->faces = evas_list_append(gad->faces, face);
face->face_num = gad->num_faces;
gad->num_faces++;
/* call the user init */
if (gad->funcs.face_init) (gad->funcs.face_init)(gad->data, face);
_e_gadget_face_menu_init(face);
e_gadman_client_load(face->gmc);
evas_event_thaw(face->evas);
return face;
}
EAPI void
e_gadget_face_theme_set(E_Gadget_Face *face, char *category, char *group)
{
Evas_Object *o;
if(!face) return;
o = edje_object_add(face->evas);
face->main_obj = o;
e_theme_edje_object_set(o, category, group);
evas_object_show(o);
}
static void
_e_gadget_face_menu_init(E_Gadget_Face *face)
{
E_Menu_Item *mi;
if (!face) return;
face->menu = e_menu_new();
if (face->gad && face->gad->module && face->gad->module->func.config)
{
mi = e_menu_item_new(face->menu);
e_menu_item_label_set(mi, _("Configuration"));
e_util_menu_item_edje_icon_set(mi, "enlightenment/configuration");
e_menu_item_callback_set(mi, _e_gadget_cb_menu_configure, face->gad);
}
mi = e_menu_item_new(face->menu);
e_menu_item_label_set(mi, _("Edit Mode"));
e_util_menu_item_edje_icon_set(mi, "enlightenment/gadgets");
e_menu_item_callback_set(mi, _e_gadget_cb_menu_edit, face);
if (face->gad->funcs.face_menu_init) (face->gad->funcs.face_menu_init)(face->gad->data, face);
}
static void
_e_gadget_cb_menu_configure(void *data, E_Menu *m, E_Menu_Item *mi)
{
E_Gadget *gad;
E_Module *module;
gad = data;
if (!gad) return;
module = gad->module;
if (!module) return;
if (module->func.config) (module->func.config)(module);
}
static void
_e_gadget_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi)
{
E_Gadget_Face *face;
face = data;
e_gadman_mode_set(face->gmc->gadman, E_GADMAN_MODE_EDIT);
}
static void
_e_gadget_free(E_Gadget *gad)
{
Evas_List *l;
if (!gad) return;
for (l = gad->faces; l; l = l->next) {
E_Gadget_Face *face = l->data;
e_object_unref(E_OBJECT(face->con));
e_object_del(E_OBJECT(face->gmc));
e_object_del(E_OBJECT(face->menu));
E_FREE(face->change);
if (face->main_obj) evas_object_del(face->main_obj);
if (face->event_obj) evas_object_del(face->event_obj);
if(gad->funcs.face_free) (gad->funcs.face_free)(gad->data, face);
E_FREE(face);
}
evas_list_free(gad->faces);
e_object_unref(E_OBJECT(gad->module));
if (gad->name) evas_stringshare_del(gad->name);
free(gad);
}
static void
_e_gadget_face_cb_gmc_change(void * data, E_Gadman_Client *gmc, E_Gadman_Change change)
{
E_Gadget_Change *gdc = data;
E_Gadget_Face *face;
Evas_Coord x, y, w, h;
if(!gdc || !gdc->gadget || !gdc->face) return;
face = gdc->face;
switch(change)
{
case E_GADMAN_CHANGE_MOVE_RESIZE:
e_gadman_client_geometry_get(face->gmc, &x, &y, &w, &h);
if (face->main_obj)
{
evas_object_move(face->main_obj, x, y);
evas_object_resize(face->main_obj, w, h);
}
if (face->event_obj)
{
evas_object_move(face->event_obj, x, y);
evas_object_resize(face->event_obj, w, h);
}
break;
case E_GADMAN_CHANGE_RAISE:
if (face->main_obj)
{
evas_object_raise(face->main_obj);
}
if (face->event_obj)
{
evas_object_raise(face->event_obj);
}
break;
case E_GADMAN_CHANGE_EDGE:
break;
case E_GADMAN_CHANGE_ZONE:
break;
}
if (gdc->gadget->funcs.change) (gdc->gadget->funcs.change)(gdc->gadget->data, gdc->face, gmc, change);
}
static void
_e_gadget_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
Evas_Event_Mouse_Down *ev;
E_Gadget_Face *face;
ev = event_info;
face = data;
if (!face) return;
if (ev->button == 3 && face->menu)
{
e_menu_activate_mouse(face->menu, e_zone_current_get(face->con),
ev->output.x, ev->output.y, 1, 1,
E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
e_util_container_fake_mouse_up_all_later(face->con);
}
}