diff --git a/src/bin/e_gadcon.c b/src/bin/e_gadcon.c index 821a4e9c3..dd6d9ed07 100644 --- a/src/bin/e_gadcon.c +++ b/src/bin/e_gadcon.c @@ -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; +} + diff --git a/src/bin/e_gadcon.h b/src/bin/e_gadcon.h index 0b97b3b54..92c315a9c 100644 --- a/src/bin/e_gadcon.h +++ b/src/bin/e_gadcon.h @@ -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 diff --git a/src/bin/e_shelf.c b/src/bin/e_shelf.c index 46cc397b9..9f795d20c 100644 --- a/src/bin/e_shelf.c +++ b/src/bin/e_shelf.c @@ -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; +} + diff --git a/src/modules/gadman/e_mod_gadman.c b/src/modules/gadman/e_mod_gadman.c index e7694e52b..615446c7c 100644 --- a/src/modules/gadman/e_mod_gadman.c +++ b/src/modules/gadman/e_mod_gadman.c @@ -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); +} + diff --git a/src/modules/gadman/e_mod_gadman.h b/src/modules/gadman/e_mod_gadman.h index 73f84cc64..af6c49254 100644 --- a/src/modules/gadman/e_mod_gadman.h +++ b/src/modules/gadman/e_mod_gadman.h @@ -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);