From: victor <victor.scorpion@gmail.com>

Hi guys.

Here is my solution for #113 ticket request. This allows to transfer a
gadget to different locations. In short,

- any module can register arbitrary number of locations by invoking
e_gadcon_location_register().
- module is responsible to provide 2 functions, one for removing
particular gadget and one to add particular gadget class.
- module responsible to equip its gadcon(s) with reference to registered
location. If a gadcon contains non-NULL location reference, each gadget
contained by this gadcon can have submenu on its context menu. Template
function for constructing such submenu is provided
e_gadcon_client_add_location_menu. Gadgets can be moved from and to this
location by invoking menu items. Gadcons with NULL location reference
can accept transferred gadgets by module logic but can't send contained
gadgets to another module.
- module responsible to unregister location when gadcon is no more
available.
- menu items for context submenu is sorted by E_GADCON_SITE_XXX assigned
to that. Module can assign and change an icon for context menu item
corresponding to its location(s).
- Currently only shelves and gadman (desktop) used in gadget transfer
operations. I believe it is no trouble to ivolve any other
gadcon-capable module into the process. If you want to have that, please
just let me know.

Here the patch in attachmet. It even works, at least sometimes and at
least for me. Hope you'll find it useful.



SVN revision: 42121
This commit is contained in:
victor 2009-08-31 11:23:03 +00:00 committed by Carsten Haitzler
parent 6d7d2889f5
commit 324e84908c
5 changed files with 312 additions and 5 deletions

View File

@ -80,6 +80,7 @@ static void e_gadcon_layout_unpack(Evas_Object *obj);
static void _e_gadcon_provider_populate_request(const E_Gadcon_Client_Class *cc);
static void _e_gadcon_provider_populate_unrequest(const E_Gadcon_Client_Class *cc);
static int _e_gadcon_location_change(E_Gadcon_Client * gcc, E_Gadcon_Location *src, E_Gadcon_Location *dst);
/********************/
#define E_LAYOUT_ITEM_DRAG_RESIST_LEVEL 10
@ -190,6 +191,7 @@ static Eina_List *providers_list = NULL;
static Eina_List *gadcons = NULL;
static Eina_List *populate_requests = NULL;
static Ecore_Idler *populate_idler = NULL;
static Eina_List *gadcon_locations = NULL;
/* This is the gadcon client which is currently dragged */
static E_Gadcon_Client *drag_gcc = NULL;
@ -285,6 +287,7 @@ e_gadcon_swallowed_new(const char *name, int id, Evas_Object *obj, char *swallow
gc->name = eina_stringshare_add(name);
gc->id = id;
gc->layout_policy = E_GADCON_LAYOUT_POLICY_PANEL;
gc->location = NULL;
gc->edje.o_parent = obj;
gc->edje.swallow_name = eina_stringshare_add(swallow_name);
@ -1254,6 +1257,85 @@ e_gadcon_client_zone_get(E_Gadcon_Client *gcc)
return e_gadcon_zone_get(gcc->gadcon);
}
static void
_e_gadcon_client_change_gadcon(void *data, E_Menu *m, E_Menu_Item *mi)
{
E_Gadcon_Location *src, *dst;
E_Gadcon_Client * gcc;
gcc = data;
src = gcc->gadcon->location;
dst = e_object_data_get(E_OBJECT(mi));
_e_gadcon_location_change(gcc, src, dst);
}
static void
_e_gadcon_add_locations_menu_for_site(E_Menu *m, E_Gadcon_Client *gcc, E_Gadcon_Site site, int * count)
{
E_Menu_Item *mi;
const Eina_List *l;
E_Gadcon_Location * loc;
int k = *count;
EINA_LIST_FOREACH(gadcon_locations, l, loc)
{
if (loc->site == site)
{
if (k)
{
k = 0;
mi = e_menu_item_new(m);
e_menu_item_separator_set(mi, 1);
(*count) = 0;
}
mi = e_menu_item_new(m);
e_menu_item_label_set(mi, loc->name);
e_object_data_set(E_OBJECT(mi), loc);
e_menu_item_callback_set(mi, _e_gadcon_client_change_gadcon, gcc);
if (loc == gcc->gadcon->location) e_menu_item_disabled_set(mi, 1);
if (loc->icon_name) e_util_menu_item_theme_icon_set(mi, loc->icon_name);
(*count)++;
}
}
}
static void
_e_gadcon_gadget_move_to_pre_cb(void *data, E_Menu *m)
{
E_Gadcon_Client *gcc;
const char *name;
int n = 0;
e_menu_pre_activate_callback_set(m, NULL, NULL);
gcc = data;
_e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_SHELF, &n);
_e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_DESKTOP, &n);
_e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_TOOLBAR, &n);
_e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_EFM_TOOLBAR, &n);
_e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_UNKNOWN, &n);
}
EAPI void
e_gadcon_client_add_location_menu(E_Gadcon_Client *gcc, E_Menu *menu)
{
E_Menu *mn;
E_Menu_Item *mi;
E_OBJECT_CHECK(gcc);
E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
if (gcc->gadcon->location)
{
mn = e_menu_new();
mi = e_menu_item_new(menu);
e_menu_item_label_set(mi, _("Move this gadget to"));
e_util_menu_item_theme_icon_set(mi, "preferences-appearance");
e_menu_item_submenu_set(mi, mn);
e_menu_pre_activate_callback_set(mn, _e_gadcon_gadget_move_to_pre_cb, gcc);
}
}
EAPI void
e_gadcon_client_util_menu_items_append(E_Gadcon_Client *gcc, E_Menu *menu, int flags)
{
@ -1317,6 +1399,8 @@ e_gadcon_client_util_menu_items_append(E_Gadcon_Client *gcc, E_Menu *menu, int f
e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_edit, gcc);
}
e_gadcon_client_add_location_menu(gcc, menu);
mi = e_menu_item_new(menu);
e_menu_item_label_set(mi, _("Remove this gadget"));
e_util_menu_item_theme_icon_set(mi, "list-remove");
@ -5141,3 +5225,69 @@ _e_gadcon_provider_populate_unrequest(const E_Gadcon_Client_Class *cc)
populate_idler = NULL;
}
}
/* gadgets movement between different gadcons */
EAPI E_Gadcon_Location *
e_gadcon_location_new(const char * name,
E_Gadcon_Site site,
int (*add_func) (void *data, const E_Gadcon_Client_Class *cc),
void * add_data,
void (*remove_func) (void *data, E_Gadcon_Client *cc),
void * remove_data)
{
E_Gadcon_Location *loc;
loc = E_NEW(E_Gadcon_Location, 1);
loc->name = eina_stringshare_add(name);
loc->site = site;
loc->gadget_add.func = add_func;
loc->gadget_add.data = add_data;
loc->gadget_remove.func = remove_func;
loc->gadget_remove.data = remove_data;
loc->icon_name = NULL;
return loc;
}
EAPI void
e_gadcon_location_set_icon_name(E_Gadcon_Location *loc, const char *name)
{
if (loc->icon_name) eina_stringshare_del(loc->icon_name);
if (name)
loc->icon_name = eina_stringshare_add(name);
else
loc->icon_name = NULL;
}
EAPI void
e_gadcon_location_free(E_Gadcon_Location *loc)
{
eina_stringshare_del(loc->name);
if (loc->icon_name) eina_stringshare_del(loc->icon_name);
free(loc);
}
EAPI void
e_gadcon_location_register (E_Gadcon_Location * loc)
{
gadcon_locations = eina_list_append(gadcon_locations, loc);
}
EAPI void
e_gadcon_location_unregister (E_Gadcon_Location * loc)
{
gadcon_locations = eina_list_remove(gadcon_locations, loc);
}
static int
_e_gadcon_location_change(E_Gadcon_Client * gcc, E_Gadcon_Location *src, E_Gadcon_Location *dst)
{
E_Gadcon_Client_Class *cc;
cc = eina_hash_find(providers, gcc->cf->name);
if (!cc) return 0;
if (!dst->gadget_add.func(dst->gadget_add.data, cc)) return 0;
src->gadget_remove.func(src->gadget_remove.data, gcc);
return 1;
}

View File

@ -47,6 +47,7 @@ typedef enum _E_Gadcon_Site
typedef struct _E_Gadcon E_Gadcon;
typedef struct _E_Gadcon_Client E_Gadcon_Client;
typedef struct _E_Gadcon_Client_Class E_Gadcon_Client_Class;
typedef struct _E_Gadcon_Location E_Gadcon_Location;
#else
#ifndef E_GADCON_H
@ -115,6 +116,7 @@ struct _E_Gadcon
Ecore_X_Window xdnd_win;
E_Shelf *shelf;
E_Toolbar *toolbar;
E_Gadcon_Location *location;
E_Drop_Handler *drop_handler;
@ -210,6 +212,29 @@ struct _E_Gadcon_Client
E_Config_Gadcon_Client *cf;
};
/* defines usable gadget placements such as Desktop, Shelf #, etc */
/* next fields are mandatory (not NULL): name, add_gadget.func, remove_gadget.func */
struct _E_Gadcon_Location
{
/* location name */
const char * name;
/* icon related to location, such as "preferences-desktop-shelf" for shelves, "preferences-desktop" for menus */
const char * icon_name;
E_Gadcon_Site site;
/* adds gadcon client to location. Returns nonzero on success */
struct
{
int (*func) (void *data, const E_Gadcon_Client_Class *cc);
void *data;
} gadget_add;
/* removes existing gadcon client from location */
struct
{
void (*func) (void *data, E_Gadcon_Client *gcc);
void *data;
} gadget_remove;
};
EAPI int e_gadcon_init(void);
EAPI int e_gadcon_shutdown(void);
EAPI void e_gadcon_provider_register(const E_Gadcon_Client_Class *cc);
@ -277,5 +302,19 @@ EAPI Eina_Bool e_gadcon_site_is_efm_toolbar(E_Gadcon_Site site);
EAPI Eina_Bool e_gadcon_site_is_any_toolbar(E_Gadcon_Site site); // all toolbar sities
EAPI Eina_Bool e_gadcon_site_is_not_toolbar(E_Gadcon_Site site); // all non-toolbar sities
/* location helpers */
EAPI E_Gadcon_Location *
e_gadcon_location_new(const char * name, E_Gadcon_Site site,
int (*add_func) (void *data, const E_Gadcon_Client_Class *cc),
void * add_data,
void (*remove_func) (void *data, E_Gadcon_Client *cc),
void * remove_data);
EAPI void e_gadcon_location_free(E_Gadcon_Location *loc);
EAPI void e_gadcon_location_register (E_Gadcon_Location * loc);
EAPI void e_gadcon_location_unregister (E_Gadcon_Location * loc);
EAPI void e_gadcon_location_set_icon_name(E_Gadcon_Location *loc, const char *name);
EAPI void e_gadcon_client_add_location_menu(E_Gadcon_Client *gcc, E_Menu *menu);
#endif
#endif

View File

@ -27,6 +27,9 @@ static int _e_shelf_cb_hide_animator_timer(void *data);
static int _e_shelf_cb_hide_urgent_timer(void *data);
static int _e_shelf_cb_instant_hide_timer(void *data);
static void _e_shelf_menu_pre_cb(void *data, E_Menu *m);
static void _e_shelf_gadcon_client_remove (void *data, E_Gadcon_Client *gcc);
static int _e_shelf_gadcon_client_add (void *data, const E_Gadcon_Client_Class *cc);
static const char * _e_shelf_orient_icon_name_get (E_Shelf *s);
static Eina_List *shelves = NULL;
static Eina_Hash *winid_shelves = NULL;
@ -94,6 +97,7 @@ e_shelf_zone_new(E_Zone *zone, const char *name, const char *style, int popup, i
E_Shelf *es;
const char *option;
char buf[1024];
const char * locname;
es = E_OBJECT_ALLOC(E_Shelf, E_SHELF_TYPE, _e_shelf_free);
if (!es) return NULL;
@ -159,6 +163,11 @@ e_shelf_zone_new(E_Zone *zone, const char *name, const char *style, int popup, i
}
es->gadcon = e_gadcon_swallowed_new(es->name, es->id, es->o_base, "e.swallow.content");
locname = es->name;
if (!name) locname = _("Shelf #");
snprintf(buf, sizeof(buf), "%s %i", locname, es->id);
es->gadcon->location = e_gadcon_location_new (buf, E_GADCON_SITE_SHELF, _e_shelf_gadcon_client_add, es, _e_shelf_gadcon_client_remove, es);
e_gadcon_location_register(es->gadcon->location);
// hmm dnd in ibar and ibox kill this. ok. need to look into this more
// es->gadcon->instant_edit = 1;
e_gadcon_min_size_request_callback_set(es->gadcon,
@ -505,6 +514,7 @@ e_shelf_orient(E_Shelf *es, E_Gadcon_Orient orient)
_e_shelf_orient_string_get(es));
edje_object_signal_emit(es->o_base, buf, "e");
edje_object_message_signal_process(es->o_base);
e_gadcon_location_set_icon_name(es->gadcon->location, _e_shelf_orient_icon_name_get (es));
e_zone_useful_geometry_dirty(es->zone);
}
@ -752,6 +762,7 @@ e_shelf_config_new(E_Zone *zone, E_Config_Shelf *cf_es)
static void
_e_shelf_free(E_Shelf *es)
{
e_gadcon_location_unregister(es->gadcon->location);
e_zone_useful_geometry_dirty(es->zone);
E_FREE_LIST(es->handlers, ecore_event_handler_del);
@ -1722,3 +1733,84 @@ _e_shelf_menu_pre_cb(void *data, E_Menu *m)
e_util_menu_item_theme_icon_set(mi, "list-remove");
e_menu_item_callback_set(mi, _e_shelf_cb_menu_delete, es);
}
static void
_e_shelf_gadcon_client_remove (void *data, E_Gadcon_Client *gcc)
{
E_Shelf *s;
E_Gadcon *gc;
s = data;
gc = s->gadcon;
e_gadcon_client_config_del(gc->cf, gcc->cf);
e_gadcon_unpopulate(gc);
e_gadcon_populate(gc);
e_config_save_queue();
}
static int
_e_shelf_gadcon_client_add (void *data, const E_Gadcon_Client_Class *cc)
{
E_Shelf *s;
E_Gadcon *gc;
s = data;
gc = s->gadcon;
if (!e_gadcon_client_config_new(gc, cc->name)) return 0;
e_gadcon_unpopulate(gc);
e_gadcon_populate(gc);
e_config_save_queue();
return 1;
}
static const char *
_e_shelf_orient_icon_name_get (E_Shelf * s)
{
const char * name;
name = NULL;
switch (s->cfg->orient)
{
case E_GADCON_ORIENT_LEFT:
name = "preferences-position-left";
break;
case E_GADCON_ORIENT_RIGHT:
name = "preferences-position-right";
break;
case E_GADCON_ORIENT_TOP:
name = "preferences-position-top";
break;
case E_GADCON_ORIENT_BOTTOM:
name = "preferences-position-bottom";
break;
case E_GADCON_ORIENT_CORNER_TL:
name = "preferences-position-top-left";
break;
case E_GADCON_ORIENT_CORNER_TR:
name = "preferences-position-top-right";
break;
case E_GADCON_ORIENT_CORNER_BL:
name = "preferences-position-bottom-left";
break;
case E_GADCON_ORIENT_CORNER_BR:
name = "preferences-position-bottom-right";
break;
case E_GADCON_ORIENT_CORNER_LT:
name = "preferences-position-left-top";
break;
case E_GADCON_ORIENT_CORNER_RT:
name = "preferences-position-right-top";
break;
case E_GADCON_ORIENT_CORNER_LB:
name = "preferences-position-left-bottom";
break;
case E_GADCON_ORIENT_CORNER_RB:
name = "preferences-position-right-bottom";
break;
default:
name = "preferences-desktop-shelf";
break;
}
return name;
}

View File

@ -12,7 +12,7 @@ static char *_get_bind_text(const char* action);
static Evas_Object* _create_mover(E_Gadcon *gc);
static Evas_Object* _get_mover(E_Gadcon_Client *gcc);
static E_Gadcon* _gadman_gadcon_new(const char* name, Gadman_Layer_Type layer, E_Zone *zone);
static E_Gadcon* _gadman_gadcon_new(const char* name, Gadman_Layer_Type layer, E_Zone *zone, E_Gadcon_Location * loc);
static void on_shape_change(void *data, E_Container_Shape *es, E_Container_Shape_Change ch);
@ -38,8 +38,12 @@ static void on_menu_delete(void *data, E_Menu *m, E_Menu_Item *mi);
static void on_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi);
static void on_menu_add(void *data, E_Menu *m, E_Menu_Item *mi);
static int _e_gadman_client_add (void *data __UNUSED__, const E_Gadcon_Client_Class *cc);
static void _e_gadman_client_remove (void *data __UNUSED__, E_Gadcon_Client *gcc);
E_Gadcon_Client *current = NULL;
Manager *Man = NULL;
static E_Gadcon_Location * location = NULL;
/* Implementation */
void
@ -64,6 +68,11 @@ gadman_init(E_Module *m)
/* with this we can trap screen resolution change (a better way?)*/
e_container_shape_change_callback_add(Man->container, on_shape_change, NULL);
/* create and register "desktop" location */
location = e_gadcon_location_new ("Desktop", E_GADCON_SITE_DESKTOP, _e_gadman_client_add, NULL, _e_gadman_client_remove, NULL);
e_gadcon_location_set_icon_name(location, "preferences-desktop");
e_gadcon_location_register(location);
/* iterating through zones - and making gadmans on each */
EINA_LIST_FOREACH(Man->container->zones, l, zone)
{
@ -72,7 +81,7 @@ gadman_init(E_Module *m)
for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++)
{
E_Gadcon *gc = _gadman_gadcon_new(layer_name[layer], layer, zone);
E_Gadcon *gc = _gadman_gadcon_new(layer_name[layer], layer, zone, location);
Man->gadcons[layer] = eina_list_append(Man->gadcons[layer], gc);
}
}
@ -84,6 +93,7 @@ gadman_shutdown(void)
E_Gadcon *gc;
unsigned int layer;
e_gadcon_location_unregister(location);
e_container_shape_change_callback_del(Man->container, on_shape_change, NULL);
for (layer = 0; layer < GADMAN_LAYER_COUNT; layer++)
@ -203,7 +213,7 @@ gadman_gadget_place(E_Config_Gadcon_Client *cf, Gadman_Layer_Type layer, E_Zone
}
E_Gadcon_Client *
gadman_gadget_add(E_Gadcon_Client_Class *cc, Gadman_Layer_Type layer)
gadman_gadget_add(const E_Gadcon_Client_Class *cc, Gadman_Layer_Type layer)
{
E_Config_Gadcon_Client *cf = NULL;
E_Gadcon_Client *gcc;
@ -444,7 +454,7 @@ gadman_update_bg(void)
/* Internals */
static E_Gadcon*
_gadman_gadcon_new(const char* name, Gadman_Layer_Type layer, E_Zone *zone)
_gadman_gadcon_new(const char* name, Gadman_Layer_Type layer, E_Zone *zone, E_Gadcon_Location * loc)
{
const Eina_List *l;
E_Gadcon *gc;
@ -457,6 +467,7 @@ _gadman_gadcon_new(const char* name, Gadman_Layer_Type layer, E_Zone *zone)
gc->name = eina_stringshare_add(name);
gc->layout_policy = E_GADCON_LAYOUT_POLICY_PANEL;
gc->orient = E_GADCON_ORIENT_FLOAT;
gc->location = loc;
/* Create ecore fullscreen window */
if (layer > GADMAN_LAYER_BG)
@ -763,6 +774,8 @@ _attach_menu(void *data, E_Gadcon_Client *gcc, E_Menu *menu)
e_util_menu_item_theme_icon_set(mi, "transform-scale");
e_menu_item_callback_set(mi, on_menu_edit, gcc);
e_gadcon_client_add_location_menu(gcc, menu);
/* Remove this gadgets */
mi = e_menu_item_new(menu);
e_menu_item_label_set(mi, _("Remove this gadget"));
@ -1340,3 +1353,16 @@ on_hide_stop(void *data __UNUSED__, Evas_Object *o __UNUSED__,
{
ecore_evas_hide(Man->top_ee);
}
static int
_e_gadman_client_add (void *data __UNUSED__, const E_Gadcon_Client_Class *cc)
{
return !!gadman_gadget_add(cc, GADMAN_LAYER_BG);
}
static void
_e_gadman_client_remove (void *data __UNUSED__, E_Gadcon_Client *gcc)
{
gadman_gadget_del(gcc);
}

View File

@ -73,7 +73,7 @@ extern Manager *Man;
void gadman_init(E_Module *m);
void gadman_shutdown(void);
E_Gadcon_Client *gadman_gadget_add(E_Gadcon_Client_Class *cc, Gadman_Layer_Type layer);
E_Gadcon_Client *gadman_gadget_add(const E_Gadcon_Client_Class *cc, Gadman_Layer_Type layer);
void gadman_gadget_del(E_Gadcon_Client *gcc);
E_Gadcon_Client *gadman_gadget_place(E_Config_Gadcon_Client *cf, Gadman_Layer_Type layer, E_Zone *zone);
void gadman_gadget_edit_start(E_Gadcon_Client *gcc);