colorclass: add subsystem for remotely editing colorclasses over dbus
authorMike Blumenkrantz <zmike@osg.samsung.com>
Sun, 5 Apr 2015 20:02:05 +0000 (16:02 -0400)
committerMike Blumenkrantz <zmike@osg.samsung.com>
Sun, 5 Apr 2015 20:26:18 +0000 (16:26 -0400)
the winid should match the e_pixmap id

also various theme improvements

legacy/elementary/data/themes/edc/elm/colorclass.edc
legacy/elementary/src/bin/test_colorclass.c
legacy/elementary/src/lib/Makefile.am
legacy/elementary/src/lib/elm_color_class.c
legacy/elementary/src/lib/elm_color_class.h
legacy/elementary/src/lib/elm_color_class.xml [new file with mode: 0644]
legacy/elementary/src/lib/elm_main.c
legacy/elementary/src/lib/elm_priv.h

index f7f11b5..ee9746b 100644 (file)
@@ -1,6 +1,34 @@
 group { "elm/layout/colorclass/base"; program_source: "elm"; nobroadcast;
    parts {
-      swallow { "elm.swallow.list"; }
+      rect { "clip"; }
+      rect { "remote_fader";
+         desc { hid;
+            color: 0 0 0 0;
+         }
+         desc { "vis";
+            color: 0 0 0 192;
+            link.base: "elm,state,remote";
+         }
+         program { signal: "mouse,down,1"; source: "remote_fader";
+            action: SIGNAL_EMIT "elm,colorclass,dismiss" "elm";
+         }
+      }
+      rect { "list_bg";
+         desc {
+            color: 64 64 64 255;
+            color_class: "dialog_base";
+            rel1.to: "elm.swallow.list";
+            rel2.to: "elm.swallow.list";
+         }
+      }
+      swallow { "elm.swallow.list";
+         desc {}
+         desc { "remote";
+            rel1.relative: 0.1 0.1;
+            rel2.relative: 0.9 0.9;
+            link.base: "elm,state,remote";
+         }
+      }
       rect { "fader";
          desc { hid;
             color: 0 0 0 0;
@@ -20,24 +48,26 @@ group { "elm/layout/colorclass/base"; program_source: "elm"; nobroadcast;
          }
          desc { "vis";
             rel1.to: "colors";
-            rel2.to: "colors";
+            rel2.to_x: "colors";
             color: 0 0 0 225;
          }
       }
       alias: "elm.swallow.colors" "colors:colors";
-      group { "colors"; source: "colorclass/colors";
+      group { "colors"; source: "colorclass/colors"; clip: "clip";
          desc { hid; align: 0 0;
             rel1.relative: 1.1 0.1;
             rel2.relative: 1.9 0;
+            rel2.to_y: "elm.swallow.reset";
             fixed: 1 1;
          }
          desc { "vis"; align: 0 0;
             rel1.relative: 0.1 0.1;
             rel2.relative: 0.9 0;
+            rel2.to_y: "elm.swallow.reset";
             fixed: 1 1;
          }
       }
-      swallow { "elm.swallow.reset";
+      swallow { "elm.swallow.reset"; clip: "clip";
          desc { hid; min: 40 24; max: 40 24;
             align: 0.5 1;
             rel1.relative: 1.0 0.0;
@@ -49,10 +79,48 @@ group { "elm/layout/colorclass/base"; program_source: "elm"; nobroadcast;
             rel2.relative: 1.0 1.0;
          }         
       }
+      rect { "text_bg";
+         desc { hid;
+            color: 64 64 64 255;
+            color_class: "dialog_base";
+            rel1.relative: 0.5 0.5;
+            rel2.relative: 0.5 0.5;
+         }
+         desc { "vis";
+            color: 64 64 64 255;
+            color_class: "dialog_base";
+            rel1.to: "elm.swallow.list";
+            rel2.to: "elm.swallow.list";
+         }
+      }
+      text { "elm.text";
+         scale;
+         desc { hid;
+            color: FN_COL_DEFAULT_BASIC;
+            rel1.relative: 0.1 0.1;
+            rel2.relative: 0.9 0.9;
+            text { font: FN; size: 10;
+              min: 1 1;
+              ellipsis: -1;
+              fit: 1 0;
+            }
+         }
+         desc { "vis"; inherit: "default"; vis; }
+      }
+      program { signal: "elm,state,info";
+         action: STATE_SET "vis";
+         transition: LINEAR 0.2;
+         targets: "text_bg" "elm.text";
+      }
+      program { signal: "elm,state,loaded";
+         action: STATE_SET "default";
+         transition: LINEAR 0.2;
+         targets: "text_bg" "elm.text";
+      }
       program { signal: "elm,colors,hide";
-            action: STATE_SET "default";
-            transition: LINEAR 0.2;
-            targets: "fader" "colors" "elm.swallow.reset" "bg";
+         action: STATE_SET "default";
+         transition: LINEAR 0.2;
+         targets: "fader" "colors" "elm.swallow.reset" "bg";
       }
       program { signal: "elm,colors,show";
          transition: LINEAR 0.2;
@@ -216,7 +284,7 @@ group { "colorclass/color1"; nomouse; nobroadcast;
             rel1.relative: 1.0 0.0;
             rel2.offset: -3 -1;
             rel2.relative: 0 1;
-            color: 255 255 255 255;
+            color: FN_COL_DEFAULT_BASIC;
             text { font: FN; size: 10;
               min: 1 1;
               ellipsis: -1;
index b363af0..cac557e 100644 (file)
@@ -17,7 +17,8 @@ test_colorclass()
    win = elm_win_util_standard_add("colorclass", "Color Classes");
    elm_win_autodel_set(win, EINA_TRUE);
 
-   cc = elm_color_class_editor_add(win, tl_cb);
+   elm_color_class_translate_cb_set(tl_cb);
+   cc = elm_color_class_editor_add(win, 0);
    elm_win_resize_object_add(win, cc);
    evas_object_size_hint_weight_set(cc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    evas_object_size_hint_align_set(cc, EVAS_HINT_FILL, EVAS_HINT_FILL);
index c25fd53..6b1a96c 100644 (file)
@@ -388,6 +388,11 @@ elm_win_legacy.h \
 elm_helper.h
 includesubdir = $(includedir)/elementary-@VMAJ@/
 
+COLORCLASS_GEN = \
+eldbus_elementary_colorclass.c \
+eldbus_elementary_colorclass.h \
+eldbus_utils.h
+
 libelementary_la_SOURCES = \
 elm_priv.h \
 els_box.h \
@@ -502,7 +507,8 @@ elm_helper.c \
 els_box.c \
 els_cursor.c \
 els_tooltip.c \
-elu_ews_wm.c
+elu_ews_wm.c \
+$(COLORCLASS_GEN)
 
 libelementary_la_CFLAGS = @ELEMENTARY_CFLAGS@
 libelementary_la_LIBADD = \
@@ -512,10 +518,17 @@ libelementary_la_LIBADD = \
 libelementary_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
 
 EXTRA_DIST = \
+elm_color_class.xml \
 elm_factory.h \
 elm_factory.c \
 elm_intro.h.in
 
+$(COLORCLASS_GEN): elm_color_class.xml
+       @cd $(top_builddir)/src/lib && \
+       eldbus-codegen $(abs_top_srcdir)/src/lib/elm_color_class.xml
+elm_color_class.c: $(COLORCLASS_GEN)
+
+
 elm_eolian_files = \
 elm_access.eo \
 elm_actionslider.eo \
@@ -772,3 +785,4 @@ endif
 
 
 
+MAINTAINERCLEANFILES += $(COLORCLASS_GEN)
index bc55cd0..e34c051 100644 (file)
@@ -3,10 +3,13 @@
 #endif
 
 #include <Elementary.h>
-
 #include "elm_priv.h"
+#include "elm_color_class.h"
+#include "eldbus_elementary_colorclass.h"
 
-
+static Eldbus_Proxy *cc_proxy;
+static Ecore_Event_Handler *h1;
+static Ecore_Event_Handler *h2;
 
 typedef struct Colorclass
 {
@@ -19,11 +22,14 @@ typedef struct Colorclass
 
 typedef struct Colorclass_UI
 {
+   EINA_INLIST;
    Evas_Object *ly;
    Evas_Object *gl;
    Evas_Object *reset;
    Evas_Object *cs;
-   Elm_Color_Class_Name_Cb cb;
+
+   uint64_t winid;
+   Ecore_Timer *timer;
 
    Colorclass *current; //actually Elm_Color_Overlay
    unsigned int num; //color[num]
@@ -32,6 +38,24 @@ typedef struct Colorclass_UI
    Eina_Bool exist : 1;
 } Colorclass_UI;
 
+typedef enum
+{
+   COLORCLASS_SIGNAL_EDIT,
+   COLORCLASS_SIGNAL_CHANGED,
+} Colorclass_Signals;
+
+static const Eldbus_Signal colorclass_editor_signals[] =
+{
+   [COLORCLASS_SIGNAL_EDIT] = {"Edit", ELDBUS_ARGS({"t", "Window ID"}), 0},
+   [COLORCLASS_SIGNAL_CHANGED] = {"Changed", ELDBUS_ARGS({"t", "Window ID"}, {"s", "Color class name"}, {"a(iiii)", "Colors"}), 0},
+   {NULL, NULL, 0}
+};
+
+static Eina_Inlist *remote_ccuis;
+static Eldbus_Service_Interface *remote_iface;
+static Elm_Color_Class_Name_Cb tl_cb;
+static Elm_Color_Class_List_Cb list_cb;
+
 static void
 _colorclass_cc_update(Colorclass_UI *cc, int num)
 {
@@ -45,6 +69,29 @@ _colorclass_cc_update(Colorclass_UI *cc, int num)
 }
 
 static void
+_dbus_signal_changed(Colorclass_UI *cc)
+{
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter, *array, *struc;
+   int x;
+
+   msg = eldbus_service_signal_new(remote_iface, COLORCLASS_SIGNAL_CHANGED);
+   eldbus_message_arguments_append(msg, "t", cc->winid);
+   eldbus_message_arguments_append(msg, "s", cc->current->name);
+   iter = eldbus_message_iter_get(msg);
+   array = eldbus_message_iter_container_new(iter, 'a', "(iiii)");
+   for (x = 0; x < 3; x++)
+     {
+        eldbus_message_iter_arguments_append(array, "(iiii)", &struc);
+        eldbus_message_iter_arguments_append(struc, "iiii",
+          cc->current->color[x].r, cc->current->color[x].g, cc->current->color[x].b, cc->current->color[x].a);
+        eldbus_message_iter_container_close(array, struc);
+     }
+   eldbus_message_iter_container_close(iter, array);
+   eldbus_service_signal_send(remote_iface, msg);
+}
+
+static void
 _colorclass_select(void *data, Evas_Object *obj EINA_UNUSED, const char *sig, const char *src EINA_UNUSED)
 {
    Colorclass_UI *cc = data;
@@ -74,10 +121,13 @@ _colorclass_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info E
 
    elm_colorselector_color_get(cc->cs, (int*)&cc->current->color[cc->num].r, (int*)&cc->current->color[cc->num].g,
                                (int*)&cc->current->color[cc->num].b, (int*)&cc->current->color[cc->num].a);
-   edje_color_class_set(cc->current->name,
-                        cc->current->color[0].r, cc->current->color[0].g, cc->current->color[0].b, cc->current->color[0].a,
-                        cc->current->color[1].r, cc->current->color[1].g, cc->current->color[1].b, cc->current->color[1].a,
-                        cc->current->color[2].r, cc->current->color[2].g, cc->current->color[2].b, cc->current->color[2].a);
+   if (remote_iface)
+     _dbus_signal_changed(cc);
+   else
+     edje_color_class_set(cc->current->name,
+                          cc->current->color[0].r, cc->current->color[0].g, cc->current->color[0].b, cc->current->color[0].a,
+                          cc->current->color[1].r, cc->current->color[1].g, cc->current->color[1].b, cc->current->color[1].a,
+                          cc->current->color[2].r, cc->current->color[2].g, cc->current->color[2].b, cc->current->color[2].a);
    edje_color_class_set("elm_colorclass_text",
                         cc->current->color[0].r, cc->current->color[0].g, cc->current->color[0].b, cc->current->color[0].a,
                         cc->current->color[1].r, cc->current->color[1].g, cc->current->color[1].b, cc->current->color[1].a,
@@ -111,6 +161,8 @@ _colorclass_reset(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EIN
    _colorclass_cc_update(cc, 0);
    _colorclass_cc_update(cc, 1);
    _colorclass_cc_update(cc, 2);
+   if (remote_iface)
+     _dbus_signal_changed(cc);
 }
 
 static void
@@ -189,18 +241,37 @@ _colorclass_deactivate(void *data, Evas_Object *obj EINA_UNUSED, const char *sig
 }
 
 static void
+_colorclass_dismiss(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
+{
+   Colorclass_UI *cc = data;
+
+   evas_object_smart_callback_call(cc->ly, "dismissed", NULL);
+}
+
+static void
 _colorclass_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
 {
    Colorclass_UI *cc = data;
 
    _colorclass_save(cc);
+   if (cc->winid)
+     remote_ccuis = eina_inlist_remove(remote_ccuis, EINA_INLIST_GET(cc));
+   if (remote_iface && (!remote_ccuis))
+     {
+        Eldbus_Connection *conn;
+
+        conn = eldbus_service_connection_get(remote_iface);
+        eldbus_name_release(conn, ELM_COLOR_CLASS_METHOD_BASE, NULL, NULL);
+        ELM_SAFE_FREE(remote_iface, eldbus_service_interface_unregister);
+        eldbus_connection_unref(conn);
+     }
    free(cc);
 }
 
 static char *
 _colorclass_text_get(Edje_Color_Class *ecc, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED)
 {
-   if (ecc->desc) return strdup(ecc->desc);
+   if (ecc->desc && ecc->desc[0]) return strdup(ecc->desc);
    return strdup(ecc->name ?: "");
 }
 
@@ -212,50 +283,366 @@ _colorclass_item_del(Edje_Color_Class *ecc, Evas_Object *obj EINA_UNUSED)
    free(ecc);
 }
 
+static void
+_dbus_request_name_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
+{
+   unsigned int flag;
+   Colorclass_UI *cc = data;
+
+   if (eldbus_message_error_get(msg, NULL, NULL) ||
+       (!eldbus_message_arguments_get(msg, "u", &flag)) ||
+       (!(flag & ELDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER)))
+     {
+        /* FIXME: translate */
+        elm_object_text_set(cc->ly, "The color editor could not assume ownership of the DBus interface.");
+        elm_object_signal_emit(cc->ly, "elm,state,info", "elm");
+        return;
+     }
+   if (remote_ccuis)
+     eldbus_service_signal_emit(remote_iface, COLORCLASS_SIGNAL_EDIT, cc->winid);
+}
+
+static Evas_Object *
+_colorclass_find_win(uint64_t winid)
+{
+   Evas_Object *win;
+   Eina_List *l;
+   pid_t pid = getpid();
+
+   EINA_LIST_FOREACH(_elm_win_list, l, win)
+     {
+        Ecore_Evas *ee;
+        const char *engine_name;
+        uint64_t id = elm_win_window_id_get(win);
+
+        ee = ecore_evas_ecore_evas_get(evas_object_evas_get(win));
+        engine_name = ecore_evas_engine_name_get(ee);
+        if (!strncmp(engine_name, "wayland", sizeof("wayland") - 1))
+          id = ((uint64_t)id << 32) + pid;
+        if (id == winid) return win;
+     }
+   return NULL;
+}
+
+static void
+_dbus_edit_helper(Eldbus_Message_Iter *array, Colorclass *lcc)
+{
+   Eldbus_Message_Iter *struc, *array2, *struc2;
+   int x;
+   char *desc = "";
+
+   eldbus_message_iter_arguments_append(array, "(ssa(iiii))", &struc);
+   if (lcc)
+     {
+        if (lcc->desc && lcc->desc[0])
+          desc = tl_cb ? tl_cb((char*)lcc->desc) : (char*)lcc->desc;
+        eldbus_message_iter_arguments_append(struc, "ss", lcc->name, desc);
+     }
+   else
+     eldbus_message_iter_arguments_append(struc, "ss", "", desc);
+   array2 = eldbus_message_iter_container_new(struc, 'a', "(iiii)");
+   for (x = 0; x < 3; x++)
+     {
+        eldbus_message_iter_arguments_append(array2, "(iiii)", &struc2);
+        if (lcc)
+          eldbus_message_iter_arguments_append(struc2, "iiii",
+            lcc->color[x].r, lcc->color[x].g, lcc->color[x].b, lcc->color[x].a);
+        else
+          eldbus_message_iter_arguments_append(struc2, "iiii", 0, 0, 0, 0);
+        eldbus_message_iter_container_close(array2, struc2);
+     }
+   eldbus_message_iter_container_close(struc, array2);
+   eldbus_message_iter_container_close(array, struc);
+}
+
+static Eina_Bool
+_dbus_edit(void *d EINA_UNUSED, int t EINA_UNUSED, Elementary_Colorclass_Edit_Data *ev)
+{
+   Evas_Object *win;
+   Eldbus_Message *msg;
+   Eldbus_Message_Iter *iter, *array;
+   Eina_Iterator *it;
+   Eina_List *eccs = NULL;
+
+   win = _colorclass_find_win(ev->winid);
+   if (!win) return ECORE_CALLBACK_RENEW;
+
+   msg = eldbus_proxy_method_call_new(cc_proxy, "SendCC");
+   iter = eldbus_message_iter_get(msg);
+   eldbus_message_arguments_append(msg, "t", ev->winid);
+   iter = eldbus_message_iter_get(msg);
+   array = eldbus_message_iter_container_new(iter, 'a', "(ssa(iiii))");
+   if (list_cb)
+     eccs = list_cb();
+   it = edje_color_class_active_iterator_new();
+   if (it || eccs)
+     {
+        Edje_Color_Class *ecc;
+        Eina_Hash *test = NULL;
+
+        if (it && eccs)
+          test = eina_hash_string_superfast_new(NULL);
+        if (it)
+          {
+             EINA_ITERATOR_FOREACH(it, ecc)
+               {
+                  if (test)
+                    eina_hash_add(test, ecc->name, ecc);
+                  _dbus_edit_helper(array, (Colorclass*)ecc);
+               }
+          }
+        EINA_LIST_FREE(eccs, ecc)
+          {
+             if (test && (!eina_hash_find(test, ecc->name)))
+               {
+                  eina_hash_add(test, ecc->name, ecc);
+                  _dbus_edit_helper(array, (Colorclass*)ecc);
+               }
+          }
+        eina_hash_free(test);
+     }
+   else
+     _dbus_edit_helper(array, NULL);
+   eldbus_message_iter_container_close(iter, array);
+   eina_iterator_free(it);
+   eldbus_proxy_send(cc_proxy, msg, NULL, NULL, -1);
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_dbus_changed(void *d EINA_UNUSED, int t EINA_UNUSED, Elementary_Colorclass_Changed_Data *ev)
+{
+   Eina_Value idv, array;
+   uint64_t id;
+   char *name;
+   Evas_Object *win;
+   unsigned int i;
+   int color[3][4];
+
+   eina_value_struct_value_get(ev->value, "arg0", &idv);
+   eina_value_get(&idv, &id);
+   win = _colorclass_find_win(id);
+   eina_value_flush(&idv);
+   if (!win) return ECORE_CALLBACK_RENEW;
+   eina_value_struct_value_get(ev->value, "arg1", &idv);
+   eina_value_get(&idv, &name);
+   eina_value_struct_value_get(ev->value, "arg2", &array);
+   if (eina_value_array_count(&array) != 3)
+     {
+        ERR("Someone is failing at sending color class data over dbus!");
+        goto out;
+     }
+   for (i = 0; i < eina_value_array_count(&array); i++)
+     {
+        Eina_Value struc2, c;
+
+        eina_value_array_value_get(&array, i, &struc2);
+        eina_value_struct_value_get(&struc2, "arg0", &c);
+        eina_value_get(&c, &color[i][0]);
+        eina_value_struct_value_get(&struc2, "arg1", &c);
+        eina_value_get(&c, &color[i][1]);
+        eina_value_struct_value_get(&struc2, "arg2", &c);
+        eina_value_get(&c, &color[i][2]);
+        eina_value_struct_value_get(&struc2, "arg3", &c);
+        eina_value_get(&c, &color[i][3]);
+        eina_value_flush(&c);
+        eina_value_flush(&struc2);
+     }
+   edje_color_class_set(name, color[0][0], color[0][1], color[0][2], color[0][3],
+                        color[1][0], color[1][1], color[1][2], color[1][3],
+                        color[2][0], color[2][1], color[2][2], color[2][3]);
+out:
+   eina_value_flush(&idv);
+   eina_value_flush(&array);
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Elm_Genlist_Item_Class itc =
+{
+   .item_style = "default",
+   .func = {
+        .text_get = (Elm_Genlist_Item_Text_Get_Cb)_colorclass_text_get,
+        .del = (Elm_Genlist_Item_Del_Cb)_colorclass_item_del
+   },
+   .version = ELM_GENLIST_ITEM_CLASS_VERSION
+};
+
+static Colorclass_UI *
+_dbus_ccui_find(uint64_t winid)
+{
+   Colorclass_UI *cc;
+
+   EINA_INLIST_FOREACH(remote_ccuis, cc)
+     if (cc->winid == winid)
+       return cc;
+   return NULL;
+}
+
+static Eldbus_Message *
+_dbus_close(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+   Colorclass_UI *cc;
+   uint64_t winid;
+
+   if (!eldbus_message_arguments_get(msg, "t", &winid))
+     return eldbus_message_method_return_new(msg);
+   cc = _dbus_ccui_find(winid);
+   if (cc)
+     {
+        evas_object_smart_callback_call(cc->ly, "application_closed", NULL);
+        ELM_SAFE_FREE(cc->timer, ecore_timer_del);
+     }
+   return eldbus_message_method_return_new(msg);
+}
+
+static Eldbus_Message *
+_dbus_send_cc(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+   Colorclass_UI *cc;
+   Eldbus_Message_Iter *array, *struc;
+   uint64_t winid;
+
+   if (!eldbus_message_arguments_get(msg, "ta(ssa(iiii))", &winid, &array))
+     return eldbus_message_method_return_new(msg);
+   cc = _dbus_ccui_find(winid);
+   if (!cc)
+     return eldbus_message_method_return_new(msg);
+   ELM_SAFE_FREE(cc->timer, ecore_timer_del);
+   while (eldbus_message_iter_get_and_next(array, 'r', &struc))
+     {
+        Colorclass *ecc;
+        const char *name, *desc;
+        Eldbus_Message_Iter *array2, *struc2;
+        int i = 0;
+
+        eldbus_message_iter_arguments_get(struc, "ssa(iiii)", &name, &desc, &array2);
+        if ((!name[0]) && (!desc[0]) && (!elm_genlist_items_count(cc->gl)))
+          break;
+        ecc = malloc(sizeof(Colorclass));
+        ecc->name = eina_stringshare_add(name);
+        ecc->desc = eina_stringshare_add(desc);
+        while (eldbus_message_iter_get_and_next(array2, 'r', &struc2))
+          {
+             if (i > 2)
+               {
+                  ERR("Someone failed at trying to send color class data!");
+                  break;
+               }
+             eldbus_message_iter_arguments_get(struc2, "iiii",
+               &ecc->color[i].r, &ecc->color[i].g, &ecc->color[i].b, &ecc->color[i].a);
+             i++;
+          }
+        elm_genlist_item_append(cc->gl, &itc, ecc, NULL, 0, NULL, NULL);
+     }
+   if (elm_genlist_items_count(cc->gl))
+     elm_object_signal_emit(cc->ly, "elm,state,loaded", "elm");
+   else
+     elm_object_text_set(cc->ly, "No color scheme available!");
+
+   return eldbus_message_method_return_new(msg);
+}
+
+static Eina_Bool
+_dbus_timeout(Colorclass_UI *cc)
+{
+   ELM_SAFE_FREE(cc->timer, ecore_timer_del);
+   evas_object_smart_callback_call(cc->ly, "timeout", NULL);
+   /* FIXME: translate */
+   elm_object_text_set(cc->ly, "Application was unable to provide color scheme info");
+   return EINA_FALSE;
+}
+
+/* internal */ void
+elm_color_class_init(void)
+{
+   cc_proxy = elementary_colorclass_proxy_get(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION), ELM_COLOR_CLASS_METHOD_BASE, NULL);
+   h1 = ecore_event_handler_add(ELEMENTARY_COLORCLASS_EDIT_EVENT, (Ecore_Event_Handler_Cb)_dbus_edit, NULL);
+   h2 = ecore_event_handler_add(ELEMENTARY_COLORCLASS_CHANGED_EVENT, (Ecore_Event_Handler_Cb)_dbus_changed, NULL);
+}
+
+void
+elm_color_class_shutdown(void)
+{
+   Eldbus_Connection *conn = eldbus_object_connection_get(eldbus_proxy_object_get(cc_proxy));
+   ELM_SAFE_FREE(cc_proxy, eldbus_proxy_unref);
+   eldbus_connection_unref(conn);
+   ecore_event_handler_del(h1);
+   ecore_event_handler_del(h2);
+   h1 = h2 = NULL;
+}
+
+static const Eldbus_Method colorclass_editor_methods[] =
+{
+      { "SendCC", ELDBUS_ARGS({"t", "Window ID"}, {"a(ssa(iiii))", "Array of color classes"}), NULL, _dbus_send_cc, 0},
+      { "Close", ELDBUS_ARGS({"t", "Window ID"}), NULL, _dbus_close, 0},
+      {NULL, NULL, NULL, NULL, 0}
+};
+
+static const Eldbus_Service_Interface_Desc base_desc =
+{
+   ELM_COLOR_CLASS_METHOD_BASE, colorclass_editor_methods, colorclass_editor_signals, NULL, NULL, NULL
+};
+
 EAPI Evas_Object *
-elm_color_class_editor_add(Evas_Object *obj, Elm_Color_Class_Name_Cb cb)
+elm_color_class_editor_add(Evas_Object *obj, uint64_t winid)
 {
    Evas_Object *ly, *bt, *gl, *cs;
    Colorclass_UI *cc;
    Edje_Color_Class *ecc, *ecc2;
    Eina_Iterator *it;
+   Eina_Hash *test = NULL;
    Eina_List *ccs = NULL;
-   static Elm_Genlist_Item_Class itc =
-   {
-      .item_style = "default",
-      .func = {
-           .text_get = (Elm_Genlist_Item_Text_Get_Cb)_colorclass_text_get,
-           .del = (Elm_Genlist_Item_Del_Cb)_colorclass_item_del
-      },
-      .version = ELM_GENLIST_ITEM_CLASS_VERSION
-   };
 
    cc = calloc(1, sizeof(Colorclass_UI));
    if (!cc) return NULL;
-   it = edje_color_class_active_iterator_new();
-   EINA_ITERATOR_FOREACH(it, ecc)
+   if (!winid)
      {
-        Colorclass *lcc;
-
-        ecc2 = malloc(sizeof(Edje_Color_Class));
-        memcpy(ecc2, ecc, sizeof(Edje_Color_Class));
-        ecc2->name = eina_stringshare_add(ecc->name);
-        if (cb)
-          ecc2->desc = eina_stringshare_add(cb((char*)ecc->desc));
-        else
-          ecc2->desc = eina_stringshare_add(ecc->desc);
-        lcc = (Colorclass*)ecc;
-        edje_color_class_set(lcc->name,
-                        lcc->color[0].r, lcc->color[0].g, lcc->color[0].b, lcc->color[0].a,
-                        lcc->color[1].r, lcc->color[1].g, lcc->color[1].b, lcc->color[1].a,
-                        lcc->color[2].r, lcc->color[2].g, lcc->color[2].b, lcc->color[2].a);
-        ccs = eina_list_append(ccs, ecc2);
+        it = edje_color_class_active_iterator_new();
+        EINA_ITERATOR_FOREACH(it, ecc)
+          {
+             Colorclass *lcc;
+
+             ecc2 = malloc(sizeof(Edje_Color_Class));
+             memcpy(ecc2, ecc, sizeof(Edje_Color_Class));
+             ecc2->name = eina_stringshare_add(ecc->name);
+             if (tl_cb)
+               ecc2->desc = eina_stringshare_add(tl_cb((char*)ecc->desc));
+             else
+               ecc2->desc = eina_stringshare_add(ecc->desc);
+             if (list_cb && (!test))
+               test = eina_hash_string_superfast_new(NULL);
+             if (test)
+               eina_hash_add(test, ecc->name, ecc2);
+             lcc = (Colorclass*)ecc;
+             edje_color_class_set(lcc->name,
+                             lcc->color[0].r, lcc->color[0].g, lcc->color[0].b, lcc->color[0].a,
+                             lcc->color[1].r, lcc->color[1].g, lcc->color[1].b, lcc->color[1].a,
+                             lcc->color[2].r, lcc->color[2].g, lcc->color[2].b, lcc->color[2].a);
+             ccs = eina_list_append(ccs, ecc2);
+          }
+        eina_iterator_free(it);
      }
-   eina_iterator_free(it);
+   else
+     {
+        if (!remote_iface)
+          {
+             Eldbus_Connection *dbus_conn;
+
+             dbus_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+             eldbus_name_request(dbus_conn, ELM_COLOR_CLASS_METHOD_BASE, ELDBUS_NAME_REQUEST_FLAG_DO_NOT_QUEUE,
+                                 _dbus_request_name_cb, cc);
+             remote_iface = eldbus_service_interface_register(dbus_conn, "/", &base_desc);
+          }
+        cc->timer = ecore_timer_add(1.5, (Ecore_Task_Cb)_dbus_timeout, cc);
+        remote_ccuis = eina_inlist_append(remote_ccuis, EINA_INLIST_GET(cc));
+     }
+   cc->winid = winid;
    cc->ly = ly = elm_layout_add(obj);
    elm_layout_theme_set(ly, "layout", "colorclass", "base");
    elm_layout_signal_callback_add(ly, "elm,colorclass,select,*", "elm", _colorclass_select, cc);
    elm_layout_signal_callback_add(ly, "elm,colorclass,deactivate", "elm", _colorclass_deactivate, cc);
+   elm_layout_signal_callback_add(ly, "elm,colorclass,dismiss", "elm", _colorclass_dismiss, cc);
    evas_object_event_callback_add(ly, EVAS_CALLBACK_DEL, _colorclass_del, cc);
 
    cc->gl = gl = elm_genlist_add(ly);
@@ -268,6 +655,7 @@ elm_color_class_editor_add(Evas_Object *obj, Elm_Color_Class_Name_Cb cb)
 
    cc->reset = bt = elm_button_add(ly);
    elm_object_style_set(bt, "colorclass");
+   /* FIXME: translate */
    elm_object_text_set(bt, "Reset");
    elm_object_part_content_set(ly, "elm.swallow.reset", bt);
    evas_object_smart_callback_add(bt, "clicked", _colorclass_reset, cc);
@@ -280,5 +668,38 @@ elm_color_class_editor_add(Evas_Object *obj, Elm_Color_Class_Name_Cb cb)
    EINA_LIST_FREE(ccs, ecc)
      elm_genlist_item_append(gl, &itc, ecc, NULL, 0, NULL, NULL);
 
+   if (winid)
+     {
+        /* FIXME: translate */
+        elm_object_text_set(ly, "Loading color scheme...");
+        elm_object_signal_emit(ly, "elm,state,info", "elm");
+        elm_object_signal_emit(ly, "elm,state,remote", "elm");
+     }
+   else if (list_cb)
+     {
+        ccs = list_cb();
+        EINA_LIST_FREE(ccs, ecc)
+          {
+             if (test)
+               {
+                  if (eina_hash_find(test, ecc->name)) continue;
+                  eina_hash_add(test, ecc->name, ecc2);
+               }
+             elm_genlist_item_append(gl, &itc, ecc, NULL, 0, NULL, NULL);
+          }
+     }
+
    return ly;
 }
+
+EAPI void
+elm_color_class_translate_cb_set(Elm_Color_Class_Name_Cb cb)
+{
+   tl_cb = cb;
+}
+
+EAPI void
+elm_color_class_list_cb_set(Elm_Color_Class_List_Cb cb)
+{
+   list_cb = cb;
+}
index 7a21be0..1d2c3ad 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef ELM_COLOR_CLASS_H
+# define ELM_COLOR_CLASS_H
+
 /**
  * @defgroup Elm_Color_Class_Group Color Class Editor
  * @ingroup Elm_Color_Class_Group
@@ -6,25 +9,65 @@
  * @{
  */
 
+#define ELM_COLOR_CLASS_METHOD_BASE "org.elementary.colorclass"
+
 /**
  * @typedef Elm_Color_Class_Name_Cb
  * @brief A callback used to translate color class descriptions
  * @since 1.14
  */
 typedef char *(*Elm_Color_Class_Name_Cb)(char *);
+
+/**
+ * @typedef Elm_Color_Class_List_Cb
+ * @brief A callback used to provide a list of allocated Edje_Color_Class structs used by an application
+ * @since 1.14
+ *
+ * The list and its members will be freed internally.
+ */
+typedef Eina_List *(*Elm_Color_Class_List_Cb)(void);
+
 /**
  * @brief Create a new color class editor
  * @param obj The parent object
- * @param cb The translation callback to use
+ * @param winid The remote window id to edit
  *
  * A color class editor is a visual representation of the color schemes in an application.
  * Values changed in the editor are stored in Elementary's config and will remain until they
- * are reset or the config is cleared.
+ * are reset or the config is cleared. By default, the editor will load only the currently active
+ * color classes in an application.
+ *
+ * If @p winid is provided the editor will run in remote mode, managing color classes over DBus
+ * for applications which provide the required interfaces.
  *
- * Passing a @c NULL param for @p cb will cause the editor to work in remote mode, using dbus
- * signals to message between the target application.
  * @since 1.14
  */
-EAPI Evas_Object *elm_color_class_editor_add(Evas_Object *obj, Elm_Color_Class_Name_Cb cb);
+EAPI Evas_Object *elm_color_class_editor_add(Evas_Object *obj, uint64_t winid);
+
+/**
+ * @brief Set a callback to provide translations for color class descriptions
+ * @param cb The callback to use
+ *
+ * This callback will be called globally by the application to translate any available color class
+ * description strings from the theme's color classes.
+ *
+ * @since 1.14
+ **/
+EAPI void elm_color_class_translate_cb_set(Elm_Color_Class_Name_Cb cb);
+
+/**
+ * @brief Set a callback to provide a list of supplementary color classes
+ * @param cb The callback to use
+ *
+ * This callback will be called globally by the application to provide extra color classes
+ * that an application may use but which may not be currently loaded.
+ *
+ * @see Elm_Color_Class_List_Cb
+ *
+ * @since 1.14
+ **/
+EAPI void elm_color_class_list_cb_set(Elm_Color_Class_List_Cb cb);
 
 /** }@ */
+
+#endif
diff --git a/legacy/elementary/src/lib/elm_color_class.xml b/legacy/elementary/src/lib/elm_color_class.xml
new file mode 100644 (file)
index 0000000..4e000e5
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/">
+   <interface name="org.elementary.colorclass">
+      <method name="SendCC">
+         <arg type="t" name="winid" direction="in" />
+         <arg type="a(ssa(iiii))" name="Array of color classes" direction="in" />
+         <annotation name="org.freedesktop.DBus.Method.NoReply" value="true" />
+      </method>
+      <method name="Close">
+         <arg type="t" name="winid" direction="in" />
+         <annotation name="org.freedesktop.DBus.Method.NoReply" value="true" />
+      </method>
+      <signal name="Edit">
+         <arg type="t" name="winid" direction="out" />
+      </signal>
+      <signal name="Changed">
+         <arg type="t" name="winid" direction="out" />
+         <arg type="s" name="Color class name" direction="out" />
+         <arg type="a(iiii)" name="Colors" direction="out" />
+      </signal>
+   </interface>
+</node>
+
index 268a32e..c1f57c7 100644 (file)
@@ -696,6 +696,7 @@ elm_quicklaunch_sub_init(int    argc,
         ecore_con_url_init();
         _elm_prefs_init();
         _elm_ews_wm_init();
+        elm_color_class_init();
      }
    return _elm_sub_init_count;
 }
@@ -744,6 +745,7 @@ elm_quicklaunch_shutdown(void)
    ELM_SAFE_FREE(_elm_appname, free);
 
    _elm_config_shutdown();
+   elm_color_class_shutdown();
 
    ELM_SAFE_FREE(_elm_exit_handler, ecore_event_handler_del);
 
index 2c0876b..1378d9b 100644 (file)
@@ -417,7 +417,8 @@ void                 _elm_config_reload(void);
 size_t               _elm_config_user_dir_snprintf(char *dst, size_t size,
                                                    const char *fmt, ...)
                                                    EINA_PRINTF(3, 4);
-
+void                 elm_color_class_init(void);
+void                 elm_color_class_shutdown(void);
 void                 _elm_recache(void);
 
 const char          *_elm_config_current_profile_get(void);