davemds pushed a commit to branch master.

http://git.enlightenment.org/enlightenment/modules/edgar.git/commit/?id=205a16700ea643ea23cb081c401ab21e6a5367a4

commit 205a16700ea643ea23cb081c401ab21e6a5367a4
Author: Dave Andreoli <d...@gurumeditation.it>
Date:   Tue Mar 6 11:04:45 2018 +0100

    Add support for new E gadgets infra
    
    Edgar gadgets can now live on both shelves and bryces.
---
 src/e_mod_edgar.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/e_mod_edgar.h |   2 +-
 src/e_mod_main.c  |   2 +-
 src/e_mod_main.h  |   2 +-
 4 files changed, 283 insertions(+), 4 deletions(-)

diff --git a/src/e_mod_edgar.c b/src/e_mod_edgar.c
index 5a47525..9ed32a5 100644
--- a/src/e_mod_edgar.c
+++ b/src/e_mod_edgar.c
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2008-2014 Davide Andreoli (see AUTHORS)
+/*  Copyright (C) 2008-2018 Davide Andreoli (see AUTHORS)
  *
  *  This file is part of edgar.
  *  edgar is free software: you can redistribute it and/or modify
@@ -23,6 +23,18 @@
 #include "efl.eo_api.h"
 
 
+#ifdef EFL_VERSION_1_21
+#define EDGAR_GADGETS_DOMAIN "Edgar"
+#endif
+
+
+/* TODO:
+
+ - correctly manage the new bryce orientations
+ - change popups to be elm based, no more edje for them
+
+*/
+
 /* Local typedefs */
 typedef struct {
    const char *name;      // ex: "ruler" (from folder name)
@@ -53,6 +65,14 @@ static const char *_edgar_gc_id_new(const 
E_Gadcon_Client_Class *client_class);
 static void _edgar_gc_id_del(const E_Gadcon_Client_Class *client_class, const 
char *id);
 static Evas_Object *_edgar_gc_icon(const E_Gadcon_Client_Class *client_class, 
Evas *evas);
 
+#ifdef EDGAR_GADGETS_DOMAIN
+/* Local Gadget/Bryce Prototypes */
+EINTERN Evas_Object *edgar_bryce_create_cb(Evas_Object *parent, const char 
*type, int *id, E_Gadget_Site_Orient orient);
+EINTERN char        *edgar_bryce_name_cb(const char *type);
+static Evas_Object  *edgar_bryce_popup_new(Edgar_Py_Gadget *gadget, 
Evas_Object *gadget_object);
+static void          edgar_bryce_popup_del(Edgar_Py_Gadget *gadget, 
Evas_Object *ctx_popup);
+#endif
+
 /* Python eapi module proto */
 PyMODINIT_FUNC PyInit_eapi(void);
 
@@ -293,6 +313,14 @@ edgar_gadget_load(const char *name, const char *path)
    e_gadcon_provider_register(cclass);
    eina_hash_add(edgar_gadgets, name, gadget);
 
+#ifdef EDGAR_GADGETS_DOMAIN
+   // add the gadget to the bryce gadgets system
+   e_gadget_external_type_add(EDGAR_GADGETS_DOMAIN, name,
+                              edgar_bryce_create_cb, NULL);
+   e_gadget_external_type_name_cb_set(EDGAR_GADGETS_DOMAIN, name,
+                                      edgar_bryce_name_cb);
+#endif
+
    return gadget;
 }
 
@@ -308,6 +336,11 @@ edgar_gadget_unload(Edgar_Py_Gadget *gadget)
    EINA_LIST_FOREACH_SAFE(gadget->pops_obj, l, l2, popup_content)
       E_FREE_FUNC(popup_content, evas_object_del);
 
+#ifdef EDGAR_GADGETS_DOMAIN
+   // remove the gadget from the bryce gadgets system
+   e_gadget_external_type_del(EDGAR_GADGETS_DOMAIN, gadget->name);
+#endif
+
    // Free the gadcon client class
    e_gadcon_provider_unregister(gadget->cclass);
    eina_stringshare_del(gadget->cclass->name);
@@ -583,6 +616,252 @@ edgar_mouse_down1_cb(void *data, Evas *e, Evas_Object 
*obj, void *event_info)
 }
 
 
+#ifdef EDGAR_GADGETS_DOMAIN
+/*****************************************************************************/
+/*****  Gadget/Bryce Pupup   *************************************************/
+/*****************************************************************************/
+static void
+edgar_bryce_ctxpopup_dismissed_cb(void *data, Evas_Object *obj, void *info 
EINA_UNUSED)
+{
+   Edgar_Py_Gadget *gadget = data;
+   edgar_bryce_popup_del(gadget, obj);
+}
+
+static Evas_Object *
+edgar_bryce_popup_new(Edgar_Py_Gadget *gadget, Evas_Object *gadget_object)
+{
+   Evas_Object *ctxpopup, *content;
+
+   DBG("EDGAR: Bryce popup for gadget:%s", gadget->name);
+
+   // create the popup content from the e/gadgets/name/popup group
+   content = edje_object_add(evas_object_evas_get(gadget_object));
+   if (!edgar_theme_object_set(gadget, content, "popup"))
+   {
+      DBG("EDGAR: Bryce no popup found for gadget:%s", gadget->name);
+      evas_object_del(content);
+      return NULL;
+   }
+   // tell edje to propagate sizes to the ctxpopup
+   edje_object_update_hints_set(content, EINA_TRUE);
+
+   // call the popup_created() method of the gadget.
+   PyObject *pyobj = object_from_instance(content);
+   PyObject *ret = PyObject_CallMethod(gadget->instance, "popup_created",
+                                       "(S)", pyobj);
+   PY_ON_ERROR_RETURN(!ret, NULL, "Cannot call popup_created()");
+   Py_DECREF(pyobj);
+   Py_DECREF(ret);
+
+   // put the popup content in an elm ctxpopup
+   ctxpopup = elm_ctxpopup_add(e_gadget_site_get(gadget_object));
+   elm_object_style_set(ctxpopup, "noblock");
+   elm_object_content_set(ctxpopup, content);
+   evas_object_smart_callback_add(ctxpopup, "dismissed",
+                                  edgar_bryce_ctxpopup_dismissed_cb, gadget);
+   e_gadget_util_ctxpopup_place(gadget_object, ctxpopup, NULL);
+   evas_object_show(ctxpopup);
+
+   // keep track of the popup
+   gadget->pops_obj = eina_list_append(gadget->pops_obj, content);
+   evas_object_data_set(gadget_object, "edgar-ctxpopup", ctxpopup);
+   evas_object_data_set(ctxpopup, "edgar-ctxpopup-owner", gadget_object);
+
+   return ctxpopup;
+}
+
+static void
+edgar_bryce_popup_del(Edgar_Py_Gadget *gadget, Evas_Object *ctxpopup)
+{
+   Evas_Object *popup_content = elm_object_content_get(ctxpopup);
+   Evas_Object *gadget_object = evas_object_data_get(ctxpopup, 
"edgar-ctxpopup-owner");
+
+   DBG("EDGAR: Bryce popup delete for gadget:%s", gadget->name);
+
+   // call the popup_destoyed() method of the gadget.
+   PyObject *pyobj = object_from_instance(popup_content);
+   PyObject *ret = PyObject_CallMethod(gadget->instance, "popup_destroyed",
+                                       "(S)", pyobj);
+   PY_ON_ERROR_RETURN(!ret, , "Cannot call popup_destroyed()");
+   Py_DECREF(pyobj);
+   Py_DECREF(ret);
+
+   // remove popup references
+   gadget->pops_obj = eina_list_remove(gadget->pops_obj, popup_content);
+   evas_object_data_del(gadget_object, "edgar-ctxpopup");
+   evas_object_data_del(ctxpopup, "edgar-ctxpopup-owner");
+
+   // delete the ctxpopup itself and the content object
+   evas_object_del(ctxpopup);
+}
+
+
+/*****************************************************************************/
+/*****  Gadget/Bryce Menu   *************************************************/
+/*****************************************************************************/
+static void
+edgar_bryce_menu_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Edgar_Py_Gadget *gadget = data;
+   E_Menu *m = event_info;
+   E_Menu_Item *mi;
+
+   DBG("EDGAR: Bryce menu for gadget:%s", gadget->name);
+   e_menu_title_set(m, gadget->label);
+
+   mi = e_menu_item_new(m);
+   e_menu_item_label_set(mi, "Gadget info");
+   e_util_menu_item_theme_icon_set(mi, "help-about");
+   e_menu_item_callback_set(mi, edgar_menu_info_cb, gadget);
+}
+
+static void
+edgar_bryce_mouse_down_cb(void *data, Evas *evas EINA_UNUSED, Evas_Object 
*obj, void *event)
+{
+   Edgar_Py_Gadget *gadget = data;
+   Evas_Event_Mouse_Down *ev = event;
+   Eina_Bool pop_on_desk = (uintptr_t)evas_object_data_get(obj, 
"edgar-pop-on-desk");
+
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+
+   if (ev->button == 1 && !pop_on_desk)  // left button (gadget popup)
+   {
+      Evas_Object *ctxpopup;
+
+      if ((ctxpopup = evas_object_data_get(obj, "edgar-ctxpopup")))
+        elm_ctxpopup_dismiss(ctxpopup);
+      else if ((ctxpopup = edgar_bryce_popup_new(gadget, obj)))
+        ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   }
+   else if (ev->button == 3)  // right button (TODO)
+   {
+      // e_gadget_configure(inst->o_clock);
+      ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+   }
+}
+
+
+/*****************************************************************************/
+/*****  Gadget/Bryce IFace   *************************************************/
+/*****************************************************************************/
+static void
+edgar_bryce_delete_cb(void *data, const Efl_Event *event)
+{
+   Edgar_Py_Gadget *gadget = data;
+   Evas_Object *gadget_object = event->object;
+   Evas_Object *ctxpopup;
+   PyObject *pyobj, *ret;
+   Eina_Bool pop_on_desk = (uintptr_t)evas_object_data_get(gadget_object,
+                                                           
"edgar-pop-on-desk");
+
+   DBG("EDGAR: Bryce instance del for gadget:%s", gadget->name);
+
+   // is there a popup opened for this gadget object?
+   if ((ctxpopup = evas_object_data_get(gadget_object, "edgar-ctxpopup")))
+     edgar_bryce_popup_del(gadget, ctxpopup);
+
+   // call the correct method in the python gadget
+   pyobj = object_from_instance(gadget_object);
+   if (pop_on_desk)
+   {
+      ret = PyObject_CallMethod(gadget->instance, "popup_destroyed",
+                                "(S)", pyobj);
+      PY_ON_ERROR_RETURN(!ret, , "Cannot call popup_destroyed()");
+   }
+   else
+   {
+      ret = PyObject_CallMethod(gadget->instance, "instance_destroyed",
+                                "(S)", pyobj);
+      PY_ON_ERROR_RETURN(!ret, , "Cannot call instance_destroyed()");
+   }
+   Py_XDECREF(ret);
+   Py_XDECREF(pyobj);
+}
+
+EINTERN Evas_Object *
+edgar_bryce_create_cb(Evas_Object *parent, const char *type, int *id, 
E_Gadget_Site_Orient orient)
+{
+   Edgar_Py_Gadget *gadget;
+   Evas_Object *obj;
+   Eina_Bool pop_on_desk = EINA_FALSE;
+
+   gadget = eina_hash_find(edgar_gadgets, type);
+   if (!gadget) return NULL;
+
+   DBG("EDGAR: Bryce create type:%s id:%d (orient:%d) (edjefile:%s)",
+       type, *id, orient, gadget->edjefile);
+
+   // create the python Gadget class instance (if not already done)
+   if (!gadget->instance)
+   {
+      DBG("EDGAR:   Instantiate the python class");
+      gadget->instance = PyObject_CallMethod(gadget->mod, "Gadget", "");
+      PY_ON_ERROR_RETURN(!gadget->instance, NULL, "Cannot create the Gadget 
instance");
+   }
+
+   // do we want the popup expanded on desktop ?
+   if (gadget->opt_pop_on_desk && orient == E_GADGET_SITE_ORIENT_NONE && *id 
>= 0)
+      pop_on_desk = EINA_TRUE;
+
+   // create the edje object (main or popup)
+   obj = edje_object_add(evas_object_evas_get(parent));
+   if (!edgar_theme_object_set(gadget, obj, pop_on_desk ? "popup" : "main"))
+   {
+      DBG("EDGAR:   ERROR, cannot find a theme for the gadget: '%s'", type);
+      evas_object_del(obj);
+      return NULL;
+   }
+   evas_object_data_set(obj, "edgar-pop-on-desk", 
(void*)(uintptr_t)pop_on_desk);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                  edgar_bryce_mouse_down_cb, gadget);
+   evas_object_smart_callback_add(obj, "gadget_menu",
+                                  edgar_bryce_menu_cb, gadget);
+   // keep track of this instance lifetime (I would have really preferred an 
explicit callback here!!)
+   // NOTE: del cb with priority to be called before the python-efl one.
+   //       Otherwise python-efl delete the python obj too soon.
+   efl_event_callback_priority_add(obj, EFL_EVENT_DEL,
+                                   EFL_CALLBACK_PRIORITY_BEFORE,
+                                   edgar_bryce_delete_cb, gadget);
+
+   // call the correct method in the python gadget
+   PyObject *pyobj = object_from_instance(obj);
+   PyObject *ret = NULL;
+   if (pop_on_desk)
+   {
+      ret = PyObject_CallMethod(gadget->instance, "popup_created",
+                                "(S)", pyobj);
+      PY_ON_ERROR_RETURN(!ret, NULL, "Cannot call popup_created()");
+   }
+   else
+   {
+      ret = PyObject_CallMethod(gadget->instance, "instance_created",
+                                // "(Si)", pyobj, gc->location->site);
+                                "(Si)", pyobj, 0);  // TODO PASS THE CORRECT 
ORIENT !!
+      PY_ON_ERROR_RETURN(!ret, NULL, "Cannot call instance_created()");
+   }
+   Py_XDECREF(ret);
+   Py_XDECREF(pyobj);
+
+   return obj;
+}
+
+EINTERN char *
+edgar_bryce_name_cb(const char *type)
+{
+   Edgar_Py_Gadget *gadget;
+   Eina_Strbuf *buf = eina_strbuf_new();
+
+   if (!buf) return NULL;
+   gadget = eina_hash_find(edgar_gadgets, type);
+   if (!gadget) return NULL;
+
+   eina_strbuf_append_printf(buf, "%s (python)", gadget->label);
+
+   return eina_strbuf_release(buf);
+}
+#endif
+
+
 /*****************************************************************************/
 /*****  Gadcon IFace   *******************************************************/
 /*****************************************************************************/
diff --git a/src/e_mod_edgar.h b/src/e_mod_edgar.h
index edfb5e6..0b257a8 100644
--- a/src/e_mod_edgar.h
+++ b/src/e_mod_edgar.h
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2008 Davide Andreoli (see AUTHORS)
+/*  Copyright (C) 2008-2018 Davide Andreoli (see AUTHORS)
  *
  *  This file is part of edgar.
  *  edgar is free software: you can redistribute it and/or modify
diff --git a/src/e_mod_main.c b/src/e_mod_main.c
index e03fd04..16b897a 100644
--- a/src/e_mod_main.c
+++ b/src/e_mod_main.c
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2008-2014 Davide Andreoli (see AUTHORS)
+/*  Copyright (C) 2008-2018 Davide Andreoli (see AUTHORS)
  *
  *  This file is part of edgar.
  *  edgar is free software: you can redistribute it and/or modify
diff --git a/src/e_mod_main.h b/src/e_mod_main.h
index 2e442d9..ab4ba76 100644
--- a/src/e_mod_main.h
+++ b/src/e_mod_main.h
@@ -1,4 +1,4 @@
-/*  Copyright (C) 2008 Davide Andreoli (see AUTHORS)
+/*  Copyright (C) 2008-2018 Davide Andreoli (see AUTHORS)
  *
  *  This file is part of edgar.
  *  edgar is free software: you can redistribute it and/or modify

-- 


Reply via email to