From a583013bab2d5a2d121fbe8fb2486850dcd91b02 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Sun, 5 Apr 2015 16:02:00 -0400 Subject: [PATCH] add colorclass editor the colorclass editor can be used to live edit the color classes in any running application. @feature --- legacy/elementary/data/themes/Makefile.am | 1 + legacy/elementary/data/themes/default.edc | 1 + .../data/themes/edc/elm/colorclass.edc | 259 ++++++++++++++++ legacy/elementary/src/lib/Elementary.h.in | 1 + legacy/elementary/src/lib/Makefile.am | 2 + legacy/elementary/src/lib/elm_color_class.c | 284 ++++++++++++++++++ legacy/elementary/src/lib/elm_color_class.h | 30 ++ 7 files changed, 578 insertions(+) create mode 100644 legacy/elementary/data/themes/edc/elm/colorclass.edc create mode 100644 legacy/elementary/src/lib/elm_color_class.c create mode 100644 legacy/elementary/src/lib/elm_color_class.h diff --git a/legacy/elementary/data/themes/Makefile.am b/legacy/elementary/data/themes/Makefile.am index affbf76775..8237c67b41 100644 --- a/legacy/elementary/data/themes/Makefile.am +++ b/legacy/elementary/data/themes/Makefile.am @@ -101,6 +101,7 @@ edc/elm/calendar.edc \ edc/elm/check.edc \ edc/elm/clock.edc \ edc/elm/colorsel.edc \ +edc/elm/colorclass.edc \ edc/elm/conform.edc \ edc/elm/ctxpopup.edc \ edc/elm/cursor.edc \ diff --git a/legacy/elementary/data/themes/default.edc b/legacy/elementary/data/themes/default.edc index 953de8b401..b7903e4952 100644 --- a/legacy/elementary/data/themes/default.edc +++ b/legacy/elementary/data/themes/default.edc @@ -50,6 +50,7 @@ collections { #include "edc/elm/photocam.edc" #include "edc/elm/tooltip.edc" #include "edc/elm/colorsel.edc" +#include "edc/elm/colorclass.edc" #include "edc/elm/segment_control.edc" #include "edc/elm/flipselector.edc" #include "edc/elm/notify.edc" diff --git a/legacy/elementary/data/themes/edc/elm/colorclass.edc b/legacy/elementary/data/themes/edc/elm/colorclass.edc new file mode 100644 index 0000000000..f7f11b5560 --- /dev/null +++ b/legacy/elementary/data/themes/edc/elm/colorclass.edc @@ -0,0 +1,259 @@ +group { "elm/layout/colorclass/base"; program_source: "elm"; nobroadcast; + parts { + swallow { "elm.swallow.list"; } + rect { "fader"; + desc { hid; + color: 0 0 0 0; + } + desc { "vis"; + color: 0 0 0 192; + } + program { signal: "mouse,down,1"; source: "fader"; + action: SIGNAL_EMIT "elm,colorclass,deactivate" "elm"; + } + } + rect { "bg"; nomouse; + desc { hid; + rel1.to: "colors"; + rel2.to: "colors"; + color: 0 0 0 0; + } + desc { "vis"; + rel1.to: "colors"; + rel2.to: "colors"; + color: 0 0 0 225; + } + } + alias: "elm.swallow.colors" "colors:colors"; + group { "colors"; source: "colorclass/colors"; + desc { hid; align: 0 0; + rel1.relative: 1.1 0.1; + rel2.relative: 1.9 0; + fixed: 1 1; + } + desc { "vis"; align: 0 0; + rel1.relative: 0.1 0.1; + rel2.relative: 0.9 0; + fixed: 1 1; + } + } + swallow { "elm.swallow.reset"; + desc { hid; min: 40 24; max: 40 24; + align: 0.5 1; + rel1.relative: 1.0 0.0; + rel2.relative: 2.0 1.0; + fixed: 1 1; + } + desc { "vis"; inherit: "default"; vis; + rel1.relative: 0.0 0.0; + rel2.relative: 1.0 1.0; + } + } + program { signal: "elm,colors,hide"; + action: STATE_SET "default"; + transition: LINEAR 0.2; + targets: "fader" "colors" "elm.swallow.reset" "bg"; + } + program { signal: "elm,colors,show"; + transition: LINEAR 0.2; + action: STATE_SET "vis"; + targets: "fader" "colors" "elm.swallow.reset" "bg"; + } + program { signal: "select,1"; source: "colors:elm"; + action: SIGNAL_EMIT "elm,colorclass,select,1" "elm"; + } + program { signal: "select,2"; source: "colors:elm"; + action: SIGNAL_EMIT "elm,colorclass,select,2" "elm"; + } + program { signal: "select,3"; source: "colors:elm"; + action: SIGNAL_EMIT "elm,colorclass,select,3" "elm"; + } + } +} + +group { "colorclass/colors"; program_source: "elm"; nobroadcast; + parts { + group { "color1"; source: "colorclass/color1"; + desc { min: 1 1; max: 1 1; hid; + link.base: "hide" ""; + } + desc { "vis"; align: 0 0; + rel1.to_x: "colors"; + rel2.to_x: "color2"; + rel2.relative: 0 0; + rel2.offset: -3 -1; + fixed: 1 1; + min: SOURCE; + link.base: "show" ""; + } + program { signal: "mouse,down,1"; source: "color1"; + action: SIGNAL_EMIT "select,1" "elm"; + } + } + group { "color2"; source: "colorclass/color2"; + desc { min: 1 1; max: 1 1; hid; + link.base: "hide" ""; + } + desc { "vis"; align: 0.5 0; + rel1.relative: 1 0; + rel2.relative: 0 0; + fixed: 1 1; + min: SOURCE; + link.base: "show" ""; + } + program { signal: "mouse,down,1"; source: "color2"; + action: SIGNAL_EMIT "select,2" "elm"; + } + } + group { "color3"; source: "colorclass/color3"; + desc { min: 1 1; max: 1 1; hid; + link.base: "hide" ""; + } + desc { "vis"; align: 1 0; + rel1.relative: 1 0; + rel2.to_x: "colors"; + rel2.relative: 1 0; + fixed: 1 1; + min: SOURCE; + link.base: "show" ""; + } + program { signal: "mouse,down,1"; source: "color3"; + action: SIGNAL_EMIT "select,3" "elm"; + } + } + swallow { "colors"; + desc { align: 0 0; + rel1.to_y: "color1"; + rel1.relative: 0 1; + rel1.offset: 0 10; + rel2.relative: 1 0; + fixed: 1 1; + } + } + text { "colortext"; + scale; + desc { align: 0 0; + rel1.to_y: "colors"; + rel1.relative: 0 1; + rel1.offset: 0 10; + rel2.relative: 1 0; + fixed: 1 1; + color_class: "elm_colorclass_text"; + text { font: FNBD; size: 12; + min: 1 1; + ellipsis: -1; + text: "ABC123abc!@#"; + } + } + } + } +} + +group { "colorclass/color1"; nomouse; nobroadcast; + images.image: "inset_shadow.png" COMP; + images.image: "bevel_in.png" COMP; + parts { + rect { "event"; mouse; + desc { color: 0 0 0 0; fixed: 1 1; } + } + rect { "bg"; + desc { + rel1.to: "color"; + rel2.to: "color"; + color: 48 48 48 255; + fixed: 1 1; + } + } + image { "pat"; + desc { + rel1.to: "bg"; + rel2.to: "bg"; + image.normal: "dot_pattern.png"; + TILED_PATTERN(256, 256) + fixed: 1 1; + } + } + rect { "color"; + desc { align: 0 0; + min: 40 20; + max: 40 20; + color: 255 255 255 255; + color_class: "elm_colorclass_color1"; + fixed: 1 1; + } + } + image { "shadow"; + desc { + image.normal: "inset_shadow.png"; + image.border: 5 5 7 3; + image.middle: 0; + rel1.to: "bg"; + rel2.to: "bg"; + fill.smooth: 0; + color: 255 255 255 128; + fixed: 1 1; + } + } + image { "inset"; + desc { + image.normal: "bevel_in.png"; + image.border: 1 1 1 1; + image.middle: 0; + rel1.to: "bg"; + rel1.offset: -1 -1; + rel2.to: "bg"; + rel2.offset: 0 0; + fill.smooth: 0; + fixed: 1 1; + } + } + text { "text"; + effect: SHADOW BOTTOM; + scale: 1; + desc { align: 0 0.5; + rel1.offset: 2 2; + rel1.to_x: "color"; + rel1.relative: 1.0 0.0; + rel2.offset: -3 -1; + rel2.relative: 0 1; + color: 255 255 255 255; + text { font: FN; size: 10; + min: 1 1; + ellipsis: -1; + text_class: "radio"; + text: "Base"; + } + } + } + } +} + +group { "colorclass/color2"; inherit: "colorclass/color1"; + parts { + rect { "color"; + desc { "default"; + color_class: "elm_colorclass_color2"; + } + } + text { "text"; + desc { "default"; + text.text: "Outline"; + } + } + } +} + +group { "colorclass/color3"; inherit: "colorclass/color1"; + parts { + rect { "color"; + desc { "default"; + color_class: "elm_colorclass_color3"; + } + } + text { "text"; + desc { "default"; + text.text: "Shadow"; + } + } + } +} diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index 92e0adc92e..3ec825996f 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -198,6 +198,7 @@ EAPI extern Elm_Version *elm_version; #include #include #include +#include #include #include #include diff --git a/legacy/elementary/src/lib/Makefile.am b/legacy/elementary/src/lib/Makefile.am index cad85948f1..c25fd53fe9 100644 --- a/legacy/elementary/src/lib/Makefile.am +++ b/legacy/elementary/src/lib/Makefile.am @@ -186,6 +186,7 @@ elm_colorselector.h \ elm_colorselector_eo.h \ elm_colorselector_legacy.h \ elm_colorselector_common.h \ +elm_color_class.h \ elm_config.h \ elm_conform.h \ elm_conform_eo.h \ @@ -419,6 +420,7 @@ elm_check.c \ elm_clock.c \ elm_cnp.c \ elm_colorselector.c \ +elm_color_class.c \ elm_config.c \ elm_conform.c \ elm_container.c \ diff --git a/legacy/elementary/src/lib/elm_color_class.c b/legacy/elementary/src/lib/elm_color_class.c new file mode 100644 index 0000000000..bc55cd048f --- /dev/null +++ b/legacy/elementary/src/lib/elm_color_class.c @@ -0,0 +1,284 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include + +#include "elm_priv.h" + + + +typedef struct Colorclass +{ + Eina_Stringshare *name; + struct { + unsigned char r, g, b, a; + } color[3]; + Eina_Stringshare *desc; +} Colorclass; + +typedef struct Colorclass_UI +{ + Evas_Object *ly; + Evas_Object *gl; + Evas_Object *reset; + Evas_Object *cs; + Elm_Color_Class_Name_Cb cb; + + Colorclass *current; //actually Elm_Color_Overlay + unsigned int num; //color[num] + Eina_Bool changed : 1; + Eina_Bool change_reset : 1; + Eina_Bool exist : 1; +} Colorclass_UI; + +static void +_colorclass_cc_update(Colorclass_UI *cc, int num) +{ + char buf[128]; + + snprintf(buf, sizeof(buf), "elm_colorclass_color%d", num + 1); + edje_color_class_set(buf, + cc->current->color[num].r, cc->current->color[num].g, cc->current->color[num].b, cc->current->color[num].a, + 0, 0, 0, 0, + 0, 0, 0, 0); +} + +static void +_colorclass_select(void *data, Evas_Object *obj EINA_UNUSED, const char *sig, const char *src EINA_UNUSED) +{ + Colorclass_UI *cc = data; + const char *s; + + s = sig + sizeof("elm,colorclass,select,") - 1; + switch (s[0]) + { + case '1': + cc->num = 0; + break; + case '2': + cc->num = 1; + break; + case '3': + cc->num = 2; + break; + } + elm_colorselector_color_set(cc->cs, cc->current->color[cc->num].r, cc->current->color[cc->num].g, + cc->current->color[cc->num].b, cc->current->color[cc->num].a); +} + +static void +_colorclass_changed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Colorclass_UI *cc = data; + + 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); + 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, + cc->current->color[2].r, cc->current->color[2].g, cc->current->color[2].b, cc->current->color[2].a); + _colorclass_cc_update(cc, cc->num); + cc->change_reset = 0; + cc->changed = 1; +} + +static void +_colorclass_reset(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Colorclass_UI *cc = data; + Colorclass color; + + if (!cc->current) return; + edje_color_class_del(cc->current->name); + edje_color_class_get(cc->current->name, + (int*)&color.color[0].r, (int*)&color.color[0].g, (int*)&color.color[0].b, (int*)&color.color[0].a, + (int*)&color.color[1].r, (int*)&color.color[1].g, (int*)&color.color[1].b, (int*)&color.color[1].a, + (int*)&color.color[2].r, (int*)&color.color[2].g, (int*)&color.color[2].b, (int*)&color.color[2].a); + cc->changed = !!memcmp(color.color, cc->current->color, sizeof(color.color)); + cc->change_reset = 1; + memcpy(cc->current->color, color.color, sizeof(color.color)); + edje_color_class_set("elm_colorclass_text", + color.color[0].r, color.color[0].g, color.color[0].b, color.color[0].a, + color.color[1].r, color.color[1].g, color.color[1].b, color.color[1].a, + color.color[2].r, color.color[2].g, color.color[2].b, color.color[2].a); + elm_colorselector_color_set(cc->cs, color.color[cc->num].r, color.color[cc->num].g, + color.color[cc->num].b, color.color[cc->num].a); + _colorclass_cc_update(cc, 0); + _colorclass_cc_update(cc, 1); + _colorclass_cc_update(cc, 2); +} + +static void +_colorclass_activate(void *data, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + Colorclass_UI *cc = data; + Elm_Object_Item *it = event_info; + Edje_Color_Class *ecc; + Colorclass *lcc; + Eina_List *l; + + ecc = elm_object_item_data_get(it); + EINA_LIST_FOREACH(_elm_config->color_overlays, l, lcc) + { + if (!eina_streq(lcc->name, ecc->name)) continue; + cc->current = lcc; + break; + } + if (cc->current) + { + _elm_config->color_overlays = eina_list_remove_list(_elm_config->color_overlays, l); + cc->exist = 1; + } + else + { + cc->current = malloc(sizeof(Elm_Color_Overlay)); + memcpy(cc->current, ecc, sizeof(Elm_Color_Overlay)); + cc->current->name = eina_stringshare_ref(ecc->name); + } + _colorclass_cc_update(cc, 0); + _colorclass_cc_update(cc, 1); + _colorclass_cc_update(cc, 2); + 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, + cc->current->color[2].r, cc->current->color[2].g, cc->current->color[2].b, cc->current->color[2].a); + elm_colorselector_color_set(cc->cs, cc->current->color[0].r, cc->current->color[0].g, + cc->current->color[0].b, cc->current->color[0].a); + elm_layout_signal_emit(cc->ly, "elm,colors,show", "elm"); +} + +static void +_colorclass_apply(Colorclass_UI *cc) +{ + if (cc->changed && (!cc->change_reset)) + _elm_config->color_overlays = eina_list_prepend(_elm_config->color_overlays, cc->current); + else + { + eina_stringshare_del(cc->current->name); + free(cc->current); + } +} + +static void +_colorclass_save(Colorclass_UI *cc) +{ + if (cc->current) + { + _colorclass_apply(cc); + if (cc->changed || (cc->exist && cc->change_reset)) + elm_config_save(); + } +} + +static void +_colorclass_deactivate(void *data, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED) +{ + Colorclass_UI *cc = data; + + _colorclass_save(cc); + cc->exist = cc->change_reset = cc->changed = 0; + cc->current = NULL; + cc->num = 0; + elm_layout_signal_emit(cc->ly, "elm,colors,hide", "elm"); + elm_genlist_item_selected_set(elm_genlist_selected_item_get(cc->gl), 0); +} + +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); + 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); + return strdup(ecc->name ?: ""); +} + +static void +_colorclass_item_del(Edje_Color_Class *ecc, Evas_Object *obj EINA_UNUSED) +{ + eina_stringshare_del(ecc->name); + eina_stringshare_del(ecc->desc); + free(ecc); +} + +EAPI Evas_Object * +elm_color_class_editor_add(Evas_Object *obj, Elm_Color_Class_Name_Cb cb) +{ + Evas_Object *ly, *bt, *gl, *cs; + Colorclass_UI *cc; + Edje_Color_Class *ecc, *ecc2; + Eina_Iterator *it; + 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) + { + 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); + } + eina_iterator_free(it); + 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); + evas_object_event_callback_add(ly, EVAS_CALLBACK_DEL, _colorclass_del, cc); + + cc->gl = gl = elm_genlist_add(ly); + elm_genlist_homogeneous_set(gl, 1); + elm_scroller_bounce_set(gl, 0, 0); + elm_scroller_policy_set(gl, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); + elm_genlist_mode_set(gl, ELM_LIST_COMPRESS); + elm_object_part_content_set(ly, "elm.swallow.list", gl); + evas_object_smart_callback_add(gl, "selected", _colorclass_activate, cc); + + cc->reset = bt = elm_button_add(ly); + elm_object_style_set(bt, "colorclass"); + 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); + + cc->cs = cs = elm_colorselector_add(ly); + elm_colorselector_mode_set(cs, ELM_COLORSELECTOR_COMPONENTS); + elm_object_part_content_set(ly, "elm.swallow.colors", cs); + evas_object_smart_callback_add(cs, "changed,user", _colorclass_changed, cc); + + EINA_LIST_FREE(ccs, ecc) + elm_genlist_item_append(gl, &itc, ecc, NULL, 0, NULL, NULL); + + return ly; +} diff --git a/legacy/elementary/src/lib/elm_color_class.h b/legacy/elementary/src/lib/elm_color_class.h new file mode 100644 index 0000000000..7a21be035f --- /dev/null +++ b/legacy/elementary/src/lib/elm_color_class.h @@ -0,0 +1,30 @@ +/** + * @defgroup Elm_Color_Class_Group Color Class Editor + * @ingroup Elm_Color_Class_Group + * @brief This group provides a UI for editing color classes in applications. + * + * @{ + */ + +/** + * @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 *); +/** + * @brief Create a new color class editor + * @param obj The parent object + * @param cb The translation callback to use + * + * 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. + * + * 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); + +/** }@ */