netstar pushed a commit to branch master.

http://git.enlightenment.org/apps/evisum.git/commit/?id=e24890f736f7d080da050827f30dc55ba162b428

commit e24890f736f7d080da050827f30dc55ba162b428
Author: Alastair Poole <m...@alastairpoole.com>
Date:   Tue Nov 2 19:50:19 2021 +0000

    WIP: this needs work...
    
    but 2 visuals.
---
 src/bin/evisum_config.c                        |  64 +-
 src/bin/evisum_config.h                        |   3 +-
 src/bin/evisum_server.c                        |   1 +
 src/bin/ui/evisum_ui.c                         |  53 ++
 src/bin/ui/evisum_ui.h                         |   1 +
 src/bin/ui/meson.build                         |   2 +
 src/bin/ui/ui_cpu.c                            | 876 +++++--------------------
 src/bin/ui/ui_cpu.h                            |  50 ++
 src/bin/ui/ui_process_list.c                   |   3 +
 src/bin/ui/visuals/cpu_basic.c                 | 130 ++++
 src/bin/ui/visuals/cpu_basic.h                 |   9 +
 src/bin/ui/{ui_cpu.c => visuals/cpu_default.c} | 507 ++++----------
 src/bin/ui/visuals/cpu_default.h               |   9 +
 src/bin/ui/visuals/meson.build                 |   6 +
 src/bin/ui/visuals/visuals.x                   |   7 +
 15 files changed, 627 insertions(+), 1094 deletions(-)

diff --git a/src/bin/evisum_config.c b/src/bin/evisum_config.c
index abb63f0..4d8050c 100644
--- a/src/bin/evisum_config.c
+++ b/src/bin/evisum_config.c
@@ -6,6 +6,8 @@
 
 Evisum_Config *_evisum_config;
 
+static Eet_Data_Descriptor *_evisum_conf_descriptor = NULL;
+
 static const char *
 _config_file_path(void)
 {
@@ -22,7 +24,60 @@ _config_file_path(void)
 void
 config_init(void)
 {
+   Eet_Data_Descriptor_Class eddc;
    efreet_init();
+
+   EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Evisum_Config);
+   _evisum_conf_descriptor = eet_data_descriptor_stream_new(&eddc);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"version", version, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"effects", effects, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"backgrounds", backgrounds, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.width", proc.width, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.height", proc.height, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.x", proc.x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.y", proc.y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.restart", proc.restart, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.show_kthreads", proc.show_kthreads, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.show_user", proc.show_user, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.sort_type", proc.sort_type, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.sort_reverse", proc.sort_reverse, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.poll_delay", proc.poll_delay, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.fields", proc.fields, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.show_statusbar", proc.show_statusbar, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.show_scroller", proc.show_scroller, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.transparent", proc.transparent, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"proc.alpha", proc.alpha, EET_T_UCHAR);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"cpu.width", cpu.width, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"cpu.height", cpu.height, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"cpu.x", cpu.x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"cpu.y", cpu.y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"cpu.restart", cpu.restart, EET_T_UCHAR);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"cpu.visual", cpu.visual, EET_T_STRING);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"mem.width", mem.width, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"mem.height", mem.height, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"mem.x", mem.x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"mem.y", mem.y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"mem.restart", mem.restart, EET_T_UCHAR);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"disk.width", disk.width, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"disk.height", disk.height, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"disk.x", disk.x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"disk.y", disk.y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"disk.restart", disk.restart, EET_T_UCHAR);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"sensors.width", sensors.width, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"sensors.height", sensors.height, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"sensors.x", sensors.x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"sensors.y", sensors.y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"sensors.restart", sensors.restart, EET_T_UCHAR);
+
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"network.width", network.width, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"network.height", network.height, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"network.x", network.x, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"network.y", network.y, EET_T_INT);
+   EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, 
"network.restart", network.restart, EET_T_UCHAR);
 }
 
 void
@@ -67,6 +122,8 @@ _config_init()
    cfg->proc.fields = 0xffffe24f;
    cfg->proc.alpha = 100;
 
+   cfg->cpu.visual = strdup("default");
+
    return cfg;
 }
 
@@ -74,7 +131,6 @@ Evisum_Config *
 config_load(void)
 {
    Eet_File *f;
-   int size;
    Evisum_Config *cfg = NULL;
 
    const char *path = _config_file_path();
@@ -84,14 +140,14 @@ config_load(void)
 
         f = eet_open(path, EET_FILE_MODE_WRITE);
         if (!f) _config_fail("create");
-        eet_write(f, "Config", cfg, sizeof(Evisum_Config), 0);
+        eet_data_write(f, _evisum_conf_descriptor, "Config", cfg, EINA_TRUE);
         eet_close(f);
      }
    else
      {
         f = eet_open(path, EET_FILE_MODE_READ);
         if (!f) _config_fail("read");
-        cfg = eet_read(f, "Config", &size);
+        cfg = eet_data_read(f, _evisum_conf_descriptor, "Config");
 
         if (cfg->version < CONFIG_VERSION)
           {
@@ -116,7 +172,7 @@ config_save(Evisum_Config *cfg)
    const char *path = _config_file_path();
    f = eet_open(path, EET_FILE_MODE_WRITE);
    if (!f) exit(127);
-   eet_write(f, "Config", cfg, sizeof(Evisum_Config), 0);
+   eet_data_write(f, _evisum_conf_descriptor, "Config", cfg, EINA_TRUE);
    eet_close(f);
 
    return 1;
diff --git a/src/bin/evisum_config.h b/src/bin/evisum_config.h
index 0d54096..2819172 100644
--- a/src/bin/evisum_config.h
+++ b/src/bin/evisum_config.h
@@ -3,7 +3,7 @@
 
 #include "ui/evisum_ui.h"
 
-#define CONFIG_VERSION 0x0012
+#define CONFIG_VERSION 0x0013
 
 typedef struct _Evisum_Config
 {
@@ -39,6 +39,7 @@ typedef struct _Evisum_Config
       int height;
       int x, y;
       Eina_Bool    restart;
+      char        *visual;
    } cpu;
 
    struct
diff --git a/src/bin/evisum_server.c b/src/bin/evisum_server.c
index eb4cf13..326aff0 100644
--- a/src/bin/evisum_server.c
+++ b/src/bin/evisum_server.c
@@ -7,6 +7,7 @@
 #include <Ecore_Con.h>
 #include "evisum_server.h"
 #include "src/bin/ui/evisum_ui.h"
+#include "evisum_config.h"
 
 #define LISTEN_SOCKET_NAME "evisum_server"
 #define WANTED "bonjour monde"
diff --git a/src/bin/ui/evisum_ui.c b/src/bin/ui/evisum_ui.c
index d183a60..84a01f4 100644
--- a/src/bin/ui/evisum_ui.c
+++ b/src/bin/ui/evisum_ui.c
@@ -67,6 +67,7 @@ evisum_ui_config_save(Evisum_Ui *ui)
         config()->cpu.x = ui->cpu.x;
         config()->cpu.y = ui->cpu.y;
         config()->cpu.restart = ui->cpu.restart;
+        config()->cpu.visual = ui->cpu.visual;
      }
 
    if (ui->mem.win)
@@ -153,6 +154,7 @@ evisum_ui_config_load(Evisum_Ui *ui)
    ui->cpu.x = config()->cpu.x;
    ui->cpu.y = config()->cpu.y;
    ui->cpu.restart = config()->cpu.restart;
+   ui->cpu.visual = strdup(config()->cpu.visual);
 
    ui->mem.width = config()->mem.width;
    ui->mem.height = config()->mem.height;
@@ -408,6 +410,21 @@ _main_menu_focus_timer_cb(void *data)
    return 0;
 }
 
+static void
+_cpu_visual_clicked_cb(void *data EINA_UNUSED, Evas_Object *obj,
+                       void *event_info EINA_UNUSED)
+{
+   Evisum_Ui *ui;
+   const char *txt;
+
+   ui = data;
+   txt = elm_object_text_get(obj);
+
+   if (ui->cpu.visual) free(ui->cpu.visual);
+   ui->cpu.visual = strdup(txt);
+   evisum_ui_restart(ui);
+}
+
 Evas_Object *
 evisum_ui_main_menu_create(Evisum_Ui *ui, Evas_Object *parent, Evas_Object 
*obj)
 {
@@ -530,6 +547,40 @@ evisum_ui_main_menu_create(Evisum_Ui *ui, Evas_Object 
*parent, Evas_Object *obj)
    evas_object_move(o, ox + (ow / 2), oy + oh);
    evas_object_show(o);
 
+
+   if (parent == ui->cpu.win)
+     {
+        fr = elm_frame_add(o);
+        evas_object_size_hint_weight_set(fr, EXPAND, EXPAND);
+        evas_object_size_hint_align_set(fr, FILL, FILL);
+        elm_object_text_set(fr, _("Visuals"));
+        elm_box_pack_end(obx, fr);
+        evas_object_show(fr);
+
+        bx = elm_box_add(o);
+        evas_object_size_hint_weight_set(bx, EXPAND, EXPAND);
+        evas_object_size_hint_align_set(bx, FILL, FILL);
+        elm_object_content_set(fr, bx);
+        evas_object_show(bx);
+
+        Eina_List *visuals = ui_cpu_visuals_get();
+        char *name;
+
+        EINA_LIST_FREE(visuals, name)
+          {
+             btn = elm_button_add(o);
+             evas_object_size_hint_weight_set(btn, EXPAND, 0);
+             evas_object_size_hint_align_set(btn, FILL, FILL);
+             elm_object_text_set(btn, name);
+             if (!strcmp(name, ui->cpu.visual)) elm_object_disabled_set(btn, 
1);
+             elm_box_pack_end(bx, btn);
+             evas_object_show(btn);
+             evas_object_smart_callback_add(btn, "clicked", 
_cpu_visual_clicked_cb, ui);
+          }
+
+        return o;
+     }
+
    if (parent != ui->proc.win) return o;
 
    fr = elm_frame_add(o);
@@ -768,6 +819,7 @@ evisum_ui_shutdown(Evisum_Ui *ui)
    ecore_thread_cancel(ui->background_poll_thread);
    ecore_thread_wait(ui->background_poll_thread, 0.5);
 
+   if (ui->cpu.visual) free(ui->cpu.visual);
    free(ui);
 }
 
@@ -785,6 +837,7 @@ evisum_ui_init(void)
 
    EVISUM_EVENT_CONFIG_CHANGED = ecore_event_type_new();
 
+   config_init();
    evisum_ui_config_load(ui);
 
    _ui_init_system_probe(ui);
diff --git a/src/bin/ui/evisum_ui.h b/src/bin/ui/evisum_ui.h
index 2a73fc1..fa6e18e 100644
--- a/src/bin/ui/evisum_ui.h
+++ b/src/bin/ui/evisum_ui.h
@@ -65,6 +65,7 @@ typedef struct _Evisum_Ui
       int           height;
       int           x, y;
       Eina_Bool     restart;
+      char         *visual;
    } cpu;
 
    struct
diff --git a/src/bin/ui/meson.build b/src/bin/ui/meson.build
index 35a8caf..bf638f9 100644
--- a/src/bin/ui/meson.build
+++ b/src/bin/ui/meson.build
@@ -1,3 +1,5 @@
+subdir('visuals')
+
 src += files([
    'gettext.h',
    'evisum_ui.h',
diff --git a/src/bin/ui/ui_cpu.c b/src/bin/ui/ui_cpu.c
index 681c572..19e65cd 100644
--- a/src/bin/ui/ui_cpu.c
+++ b/src/bin/ui/ui_cpu.c
@@ -1,67 +1,26 @@
 #include "ui_cpu.h"
 #include "config.h"
 
-typedef struct {
-   short id;
-   short percent;
-   unsigned int freq;
-   unsigned int temp;
-} Core;
-
-typedef struct {
-   Ecore_Thread   *thread;
-
-   Evas_Object    *win;
-   Evas_Object    *menu;
-   Elm_Layout     *btn_menu;
-   Eina_Bool       btn_visible;
-   Evas_Object    *bg;
-   Evas_Object    *obj;
-
-   Evas_Object    *colors;
-   int             cpu_count;
-   int            *cpu_order;
-
-   Eina_Bool       show_cpufreq;
-   // Have cpu scaling
-   Eina_Bool       cpu_freq;
-   int             freq_min;
-   int             freq_max;
-
-   Eina_Bool       show_cputemp;
-   // Have temp readings.
-   Eina_Bool       cpu_temp;
-   int             temp_min;
-   int             temp_max;
-
-   Eina_Bool       confused;
-   Eina_List      *explainers;
-
-   Evisum_Ui      *ui;
-} Animate;
-
-typedef struct _Color_Point {
-   unsigned int val;
-   unsigned int color;
-} Color_Point;
+// Templates for visualisations.
+#include "visuals/visuals.x"
 
 // config for colors/sizing
 #define COLOR_CPU_NUM 5
 static const Color_Point cpu_colormap_in[] = {
-   {   0, 0xff202020 }, // 0
-   {  25, 0xff2030a0 }, // 1
-   {  50, 0xffa040a0 }, // 2
-   {  75, 0xffff9040 }, // 3
-   { 100, 0xffffffff }, // 4
-   { 256, 0xffffffff }  // overflow to avoid if's
+   {   0, 0xff202020 },
+   {  25, 0xff2030a0 },
+   {  50, 0xffa040a0 },
+   {  75, 0xffff9040 },
+   { 100, 0xffffffff },
+   { 256, 0xffffffff }
 };
 #define COLOR_FREQ_NUM 4
 static const Color_Point freq_colormap_in[] = {
-   {   0, 0xff202020 }, // 0
-   {  33, 0xff285020 }, // 1
-   {  67, 0xff30a060 }, // 2
-   { 100, 0xffa0ff80 }, // 3
-   { 256, 0xffa0ff80 }  // overflow to avoid if's
+   {   0, 0xff202020 },
+   {  33, 0xff285020 },
+   {  67, 0xff30a060 },
+   { 100, 0xffa0ff80 },
+   { 256, 0xffa0ff80 }
 };
 
 #define COLOR_TEMP_NUM 5
@@ -74,281 +33,82 @@ static const Color_Point temp_colormap_in[] = {
    { 256, 0xffdd776e }
 };
 
-#define BAR_HEIGHT    3
-#define COLORS_HEIGHT 32
-#define CORES_MANY    16
-
-// stored colormap tables
-static unsigned int cpu_colormap[256];
-static unsigned int freq_colormap[256];
-static unsigned int temp_colormap[256];
-
-// handy macros to access argb values from pixels
-#define AVAL(x) (((x) >> 24) & 0xff)
-#define RVAL(x) (((x) >> 16) & 0xff)
-#define GVAL(x) (((x) >>  8) & 0xff)
-#define BVAL(x) (((x)      ) & 0xff)
-#define ARGB(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+unsigned int cpu_colormap[256];
+unsigned int freq_colormap[256];
+unsigned int temp_colormap[256];
 
 static void
-_color_init(const Color_Point *col_in, unsigned int n, unsigned int *col)
-{
-   unsigned int pos, interp, val, dist, d;
-   unsigned int a, r, g, b;
-   unsigned int a1, r1, g1, b1, v1;
-   unsigned int a2, r2, g2, b2, v2;
-
-   // wal colormap_in until colormap table is full
-   for (pos = 0, val = 0; pos < n; pos++)
-     {
-        // get first color and value position
-        v1 = col_in[pos].val;
-        a1 = AVAL(col_in[pos].color);
-        r1 = RVAL(col_in[pos].color);
-        g1 = GVAL(col_in[pos].color);
-        b1 = BVAL(col_in[pos].color);
-        // get second color and valuje position
-        v2 = col_in[pos + 1].val;
-        a2 = AVAL(col_in[pos + 1].color);
-        r2 = RVAL(col_in[pos + 1].color);
-        g2 = GVAL(col_in[pos + 1].color);
-        b2 = BVAL(col_in[pos + 1].color);
-        // get distance between values (how many entires to fill)
-        dist = v2 - v1;
-        // walk over the span of colors from point a to point b
-        for (interp = v1; interp < v2; interp++)
-          {
-             // distance from starting point
-             d = interp - v1;
-             // calculate linear interpolation between start and given d
-             a = ((d * a2) + ((dist - d) * a1)) / dist;
-             r = ((d * r2) + ((dist - d) * r1)) / dist;
-             g = ((d * g2) + ((dist - d) * g1)) / dist;
-             b = ((d * b2) + ((dist - d) * b1)) / dist;
-             // write out resulting color value
-             col[val] = ARGB(a, r, g, b);
-             val++;
-          }
-     }
-}
-
-static void
-_core_times_main_cb(void *data, Ecore_Thread *thread)
+_win_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
-   Animate *ad = data;
-   int ncpu;
-
-   if (!system_cpu_frequency_min_max_get(&ad->freq_min, &ad->freq_max))
-     ad->cpu_freq = 1;
+   Evas_Coord w, h;
+   Evas_Event_Mouse_Move *ev;
+   Cpu_Visual *vis = data;
 
-   system_cpu_temperature_min_max_get(&ad->temp_min, &ad->temp_max);
-   if ((system_cpu_n_temperature_get(0)) != -1)
-     ad->cpu_temp = 1;
+   ev = event_info;
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
 
-   while (!ecore_thread_check(thread))
+   if ((ev->cur.canvas.x >= (w - 128)) && (ev->cur.canvas.y <= 128))
      {
-        cpu_core_t **cores = system_cpu_usage_delayed_get(&ncpu, 100000);
-        Core *cores_out = calloc(ncpu, sizeof(Core));
-
-        if (cores_out)
-          {
-             for (int n = 0; n < ncpu; n++)
-               {
-                  int id = ad->cpu_order[n];
-                  Core *core = &(cores_out[n]);
-                  core->id = id;
-                  core->percent = cores[id]->percent;
-                  if (ad->cpu_freq)
-                    core->freq = system_cpu_n_frequency_get(id);
-                  if (ad->cpu_temp)
-                    core->temp = system_cpu_n_temperature_get(id);
-                  free(cores[id]);
-               }
-             ecore_thread_feedback(thread, cores_out);
-          }
-        free(cores);
+       if (!vis->btn_visible)
+         {
+            elm_object_signal_emit(vis->btn_menu, "menu,show", "evisum/menu");
+            vis->btn_visible = 1;
+         }
      }
+   else if ((vis->btn_visible) && (!vis->menu))
+    {
+       elm_object_signal_emit(vis->btn_menu, "menu,hide", "evisum/menu");
+       vis->btn_visible = 0;
+    }
 }
 
 static void
-_update(Animate *ad, Core *cores)
+_win_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
-   Evas_Object *obj = ad->obj;
-   unsigned int *pixels, *pix;
-   Evas_Coord x, y, w, h;
-   int iw, stride;
-   Eina_Bool clear = 0;
-
-   evas_object_geometry_get(obj, &x, &y, &w, &h);
-   evas_object_image_size_get(obj, &iw, NULL);
-   // if image pixel size doesn't match geom - we need to resize, so set
-   // new size and mark it for clearing when we fill
-   if (iw != w)
-     {
-        evas_object_image_size_set(obj, w, ad->cpu_count * 3);
-        clear = 1;
-     }
-
-   // get pixel data ptr
-   pixels = evas_object_image_data_get(obj, 1);
-   if (!pixels) return;
-   // get stride (# of bytes per line)
-   stride = evas_object_image_stride_get(obj);
-
-   for (y = 0; y < ad->cpu_count; y++)
-     {
-        Core *core = &(cores[y]);
-        unsigned int c1, c2;
+   Evas_Event_Key_Down *ev;
+   Evisum_Ui *ui;
 
-        // our pix ptr is the pixel row and y is both y pixel coord and core
-        if (clear)
-          {
-             // clear/fill with 0 value from colormap
-             pix = &(pixels[(y * 3) * (stride / 4)]);
-             for (x = 0; x < (w - 1); x++) pix[x] = cpu_colormap[0];
-             pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
-             for (x = 0; x < (w - 1); x++) pix[x] = freq_colormap[0];
-             pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
-             for (x = 0; x < (w - 1); x++) pix[x] = cpu_colormap[0];
-          }
-        else
-          {
-             // scroll pixels 1 to the left
-             pix = &(pixels[(y * 3) * (stride / 4)]);
-             for (x = 0; x < (w - 1); x++) pix[x] = pix[x + 1];
-             pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
-             for (x = 0; x < (w - 1); x++) pix[x] = pix[x + 1];
-             pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
-             for (x = 0; x < (w - 1); x++) pix[x] = pix[x + 1];
-          }
-        // final pixel on end of each row... set it to a new value
-        // get color from cpu colormap
-        // last pixel == resulting pixel color
-        c1 = cpu_colormap[core->percent & 0xff];
-        pix = &(pixels[(y * 3) * (stride / 4)]);
-        pix[x] = c1;
-        // 2nd row of pixles for freq
-        if ((ad->show_cpufreq) && (ad->cpu_freq))
-          {
-             int v = core->freq - ad->freq_min;
-             int d = ad->freq_max - ad->freq_min;
-
-             // if there is a difference between min and max ... a range
-             if (d > 0)
-               {
-                  v = (100 * v) / d;
-                  if (v < 0) v = 0;
-                  else if (v > 100) v = 100;
-                  // v now is 0->100 as a percentage of possible frequency
-                  // the cpu can do
-                  c2 = freq_colormap[v & 0xff];
-               }
-             else c2 = freq_colormap[0];
-             pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
-             pix[x] = c2;
-          }
+   ui = data;
+   ev = event_info;
 
-        if (ad->show_cputemp && ad->cpu_temp)
-          {
-             pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
-             pix[x] = temp_colormap[core->temp & 0xff];
-          }
+   if (!ev || !ev->keyname)
+     return;
 
-        if (!ad->show_cpufreq)
-          {
-             // no freq show - then just repeat cpu usage color
-             pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
-             pix[x] = c1;
-          }
-        if (!ad->show_cputemp)
-          {
-             pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
-             pix[x] = c1;
-          }
+   if (!strcmp(ev->keyname, "Escape"))
+     {
+        evas_object_del(ui->cpu.win);
      }
-   // hand back pixel data ptr so evas knows we are done with it
-   evas_object_image_data_set(obj, pixels);
-   // now add update region for all pixels in the image at the end as we
-   // changed everything
-   evas_object_image_data_update_add(obj, 0, 0, w, ad->cpu_count * 3);
 }
 
-typedef struct
-{
-   Evas_Object *lb;
-   Evas_Object *rec;
-} Explainer;
-
 static void
-_explain(Animate *ad, Core *cores)
+_btn_menu_clicked_cb(void *data, Evas_Object *obj,
+                     void *event_info EINA_UNUSED)
 {
-   Eina_Strbuf *buf;
-   Explainer *exp;
-   Evas_Object *lb, *rec;
-
-   if (!ad->explainers) return;
-
-   buf = eina_strbuf_new();
+   Evisum_Ui *ui;
+   Cpu_Visual *vis = data;
 
-   for (int i = 0; i < ad->cpu_count; i++)
+   ui = vis->ui;
+   if (!vis->menu)
+     vis->menu = evisum_ui_main_menu_create(ui, ui->cpu.win, obj);
+   else
      {
-        Core *core = &(cores[i]);
-        exp = eina_list_nth(ad->explainers, i);
-
-        lb = exp->lb;
-        rec = exp->rec;
-        if (!ad->confused)
-          {
-             evas_object_hide(rec);
-             evas_object_hide(lb);
-          }
-        else
-          {
-             eina_strbuf_append_printf(buf, "<b><color=#fff>%i%% ", 
core->percent);
-             if (ad->cpu_freq)
-               eina_strbuf_append_printf(buf, "%1.1fGHz ", (double) core->freq 
/ 1000000);
-             if (ad->cpu_temp)
-               eina_strbuf_append_printf(buf, "%i°C", core->temp);
-             eina_strbuf_append(buf, "</></>");
-
-             elm_object_text_set(lb, eina_strbuf_string_get(buf));
-             eina_strbuf_reset(buf);
-             evas_object_show(rec);
-             evas_object_show(lb);
-          }
+        evas_object_del(vis->menu);
+        vis->menu = NULL;
      }
-   eina_strbuf_free(buf);
 }
 
 static void
-_core_times_feedback_cb(void *data, Ecore_Thread *thread EINA_UNUSED, void 
*msgdata)
+_win_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
-   Animate *ad;
-   Core *cores;
-   static Eina_Bool was_confused = 0;
-
-   ad = data;
-   cores = msgdata;
-
-   _update(ad, cores);
-
-   if (ad->confused || was_confused)
-     {
-        _explain(ad, cores);
-        was_confused = 1;
-     }
+   Evisum_Ui *ui = data;
 
-   free(cores);
+   evas_object_geometry_get(obj, NULL, NULL, &ui->cpu.width, &ui->cpu.height);
 }
 
 static void
 _win_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void 
*event_info EINA_UNUSED)
 {
-   Animate *ad;
-   Evisum_Ui *ui;
-
-   ad = data;
-   ui = ad->ui;
+   Evisum_Ui *ui = data;
 
    evas_object_geometry_get(obj, &ui->cpu.x, &ui->cpu.y, NULL, NULL);
 }
@@ -356,444 +116,102 @@ _win_move_cb(void *data, Evas *e EINA_UNUSED, 
Evas_Object *obj, void *event_info
 static void
 _win_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA_UNUSED)
 {
-   Explainer *exp;
-   Animate *ad = data;
-   Evisum_Ui *ui = ad->ui;
+   Cpu_Visual *vis = data;
+   Evisum_Ui *ui = vis->ui;
 
    evisum_ui_config_save(ui);
-   ecore_thread_cancel(ad->thread);
-   ecore_thread_wait(ad->thread, 0.5);
+   ecore_thread_cancel(vis->thread);
+   ecore_thread_wait(vis->thread, 0.5);
 
-   EINA_LIST_FREE(ad->explainers, exp)
-     {
-        free(exp);
-     }
+   if (vis->ext_free_cb)
+      vis->ext_free_cb(vis->ext);
 
-   ad->explainers = NULL;
-   free(ad->cpu_order);
-   free(ad);
+   free(vis);
    ui->cpu.win = NULL;
 }
 
 static void
-_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
-                  void *event_info EINA_UNUSED)
-{
-   Animate *ad = data;
-
-   ad->show_cpufreq = elm_check_state_get(obj);
-}
-
-static void
-_temp_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
-                       void *event_info EINA_UNUSED)
-{
-   Animate *ad = data;
-
-   ad->show_cputemp = elm_check_state_get(obj);
-}
-
-static void
-_confused_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED,
-                           void *event_info EINA_UNUSED)
-{
-   Animate *ad = data;
-
-   ad->confused = elm_check_state_get(obj);
-}
-
-static void
-_colors_fill(Evas_Object *colors)
-{
-   // fill a 3 pixel high (and 100 wide) image with 3 gradients matching
-   // the colormaps we calculated as a legend
-   int x, stride;
-   unsigned int *pixels;
-
-   evas_object_image_size_set(colors, 101, 3);
-   pixels = evas_object_image_data_get(colors, 1);
-   if (!pixels) return;
-   stride = evas_object_image_stride_get(colors);
-   // cpu percent (first row)
-   for (x = 0; x <= 100; x++) pixels[x] = cpu_colormap[x];
-   // cpu freq (next row)
-   for (x = 0; x <= 100; x++) pixels[x + (stride / 4)] = freq_colormap[x];
-   // cpu temp (next row)
-   for (x = 0; x <= 100; x++) pixels[x + (stride / 2)] = temp_colormap[x];
-
-   evas_object_image_data_set(colors, pixels);
-   evas_object_image_data_update_add(colors, 0, 0, 101, 1);
-}
-
-static void
-_win_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+_color_init(const Color_Point *col_in, unsigned int n, unsigned int *col)
 {
-   Evas_Coord w, h;
-   Evas_Event_Mouse_Move *ev;
-   Animate *ad = data;
-
-   ev = event_info;
-   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+   unsigned int pos, interp, val, dist, d;
+   unsigned int a, r, g, b;
+   unsigned int a1, r1, g1, b1, v1;
+   unsigned int a2, r2, g2, b2, v2;
 
-   if ((ev->cur.canvas.x >= (w - 128)) && (ev->cur.canvas.y <= 128))
+   // wal colormap_in until colormap table is full
+   for (pos = 0, val = 0; pos < n; pos++)
      {
-       if (!ad->btn_visible)
-         {
-            elm_object_signal_emit(ad->btn_menu, "menu,show", "evisum/menu");
-            ad->btn_visible = 1;
-         }
+        // get first color and value position
+        v1 = col_in[pos].val;
+        a1 = AVAL(col_in[pos].color);
+        r1 = RVAL(col_in[pos].color);
+        g1 = GVAL(col_in[pos].color);
+        b1 = BVAL(col_in[pos].color);
+        // get second color and valuje position
+        v2 = col_in[pos + 1].val;
+        a2 = AVAL(col_in[pos + 1].color);
+        r2 = RVAL(col_in[pos + 1].color);
+        g2 = GVAL(col_in[pos + 1].color);
+        b2 = BVAL(col_in[pos + 1].color);
+        // get distance between values (how many entires to fill)
+        dist = v2 - v1;
+        // walk over the span of colors from point a to point b
+        for (interp = v1; interp < v2; interp++)
+          {
+             // distance from starting point
+             d = interp - v1;
+             // calculate linear interpolation between start and given d
+             a = ((d * a2) + ((dist - d) * a1)) / dist;
+             r = ((d * r2) + ((dist - d) * r1)) / dist;
+             g = ((d * g2) + ((dist - d) * g1)) / dist;
+             b = ((d * b2) + ((dist - d) * b1)) / dist;
+             // write out resulting color value
+             col[val] = ARGB(a, r, g, b);
+             val++;
+          }
      }
-   else if ((ad->btn_visible) && (!ad->menu))
-    {
-       elm_object_signal_emit(ad->btn_menu, "menu,hide", "evisum/menu");
-       ad->btn_visible = 0;
-    }
 }
 
-static void
-_win_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+Eina_List *
+ui_cpu_visuals_get(void)
 {
-   Evas_Event_Key_Down *ev;
-   Animate *ad;
+   Eina_List *l = NULL;
 
-   ad = data;
-   ev = event_info;
-
-   if (!ev || !ev->keyname)
-     return;
-
-   if (!strcmp(ev->keyname, "Escape"))
-     evas_object_del(ad->ui->cpu.win);
-}
-
-static void
-_btn_menu_clicked_cb(void *data, Evas_Object *obj,
-                     void *event_info EINA_UNUSED)
-{
-   Evisum_Ui *ui;
-   Animate *ad = data;
-
-   ui = ad->ui;
-   if (!ad->menu)
-     ad->menu = evisum_ui_main_menu_create(ui, ui->cpu.win, obj);
-   else
+   for (int i = 0; (i < sizeof(visualizations) / sizeof(Visualization)); i++)
      {
-        evas_object_del(ad->menu);
-        ad->menu = NULL;
+        l = eina_list_append(l, strdup(visualizations[i].name));
      }
+
+   return l;
 }
 
-static Animate *
-_graph(Evisum_Ui *ui, Evas_Object *parent)
+Visualization *
+ui_cpu_visual_by_name(const char *name)
 {
-   Evas_Object *tbl, *tbl2, *box, *obj, *ic, *lb, *rec;
-   Evas_Object *fr, *bx, *hbx, *colors, *check, *btn;
-   Elm_Layout *lay;
-   int i, f;
-   char buf[128];
-   Eina_Bool show_icons = 1;
-
-   Animate *ad = calloc(1, sizeof(Animate));
-   if (!ad) return NULL;
-
-   ad->win = ui->cpu.win;
-   ad->cpu_count = system_cpu_count_get();
-   if (!system_cpu_frequency_min_max_get(&ad->freq_min, &ad->freq_max))
-     ad->cpu_freq = 1;
-
-   system_cpu_temperature_min_max_get(&ad->temp_min, &ad->temp_max);
-   if ((system_cpu_n_temperature_get(0)) != -1)
-     ad->cpu_temp = 1;
-
-   ad->cpu_order = malloc((ad->cpu_count) * sizeof(int));
-   for (i = 0; i < ad->cpu_count; i++)
-     ad->cpu_order[i] = i;
-   system_cpu_topology_get(ad->cpu_order, ad->cpu_count);
-
-   // init colormaps from a small # of points
-   _color_init(cpu_colormap_in, COLOR_CPU_NUM, cpu_colormap);
-   _color_init(freq_colormap_in, COLOR_FREQ_NUM, freq_colormap);
-   _color_init(temp_colormap_in, COLOR_TEMP_NUM, temp_colormap);
-
-   box = parent;
-
-   tbl = elm_table_add(box);
-   evas_object_size_hint_align_set(tbl, FILL, FILL);
-   evas_object_size_hint_weight_set(tbl, EXPAND, EXPAND);
-   evas_object_show(tbl);
-
-   obj = evas_object_image_add(evas_object_evas_get(parent));
-   evas_object_size_hint_align_set(obj, FILL, FILL);
-   evas_object_size_hint_weight_set(obj, EXPAND, EXPAND);
-   evas_object_image_smooth_scale_set(obj, 0);
-   evas_object_image_filled_set(obj, 1);
-   evas_object_image_alpha_set(obj, 0);
-   evas_object_show(obj);
-
-   elm_table_pack(tbl, obj, 0, 0, 5, ad->cpu_count);
-
-   if (ad->cpu_count > CORES_MANY)
-     show_icons = 0;
-
-   if (show_icons)
-     {
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
-        evas_object_size_hint_align_set(rec, FILL, FILL);
-        evas_object_size_hint_weight_set(rec, EXPAND, EXPAND);
-        evas_object_color_set(rec, 0, 0, 0, 64);
-        evas_object_show(rec);
-        elm_table_pack(tbl, rec, 0, 0, 4, ad->cpu_count);
-     }
-
-   for (i = 0; show_icons && (i < ad->cpu_count); i++)
+   for (int i = 0; (i < sizeof(visualizations) / sizeof(Visualization)); i++)
      {
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
-        evas_object_color_set(rec, 0, 0, 0, 0);
-        evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(8), 
ELM_SCALE_SIZE(8));
-        evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
-        elm_table_pack(tbl, rec, 0, i, 1, 1);
-
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
-        evas_object_color_set(rec, 0, 0, 0, 0);
-        evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(24), 
ELM_SCALE_SIZE(24));
-        evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
-        elm_table_pack(tbl, rec, 1, i, 1, 1);
-
-        ic = elm_icon_add(parent);
-        elm_icon_standard_set(ic, evisum_icon_path_get("cpu"));
-        evas_object_size_hint_align_set(ic, FILL, FILL);
-        evas_object_size_hint_weight_set(ic, 0.0, EXPAND);
-        elm_table_pack(tbl, ic, 1, i, 1, 1);
-        evas_object_show(ic);
-
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
-        evas_object_color_set(rec, 0, 0, 0, 0);
-        evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(8), 
ELM_SCALE_SIZE(8));
-        evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
-        elm_table_pack(tbl, rec, 2, i, 1, 1);
-
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
-        evas_object_color_set(rec, 0, 0, 0, 0);
-        evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(16), 
ELM_SCALE_SIZE(16));
-        evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
-        elm_table_pack(tbl, rec, 3, i, 1, 1);
-
-        lb = elm_label_add(parent);
-        snprintf(buf, sizeof(buf), "<b><color=#fff>%i</></>", 
ad->cpu_order[i]);
-        elm_object_text_set(lb, buf);
-        evas_object_size_hint_align_set(lb, 0.0, 0.5);
-        evas_object_size_hint_weight_set(lb, 0.0, EXPAND);
-        elm_table_pack(tbl, lb, 3, i, 1, 1);
-        evas_object_show(lb);
-
-        // Begin explainer label overlay.
-
-        tbl2 = elm_table_add(parent);
-        evas_object_size_hint_align_set(tbl2, 0.7, 0.5);
-        evas_object_size_hint_weight_set(tbl2, EXPAND, EXPAND);
-        evas_object_show(tbl2);
-
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
-        evas_object_color_set(rec, 0, 0, 0, 128);
-        evas_object_size_hint_align_set(rec, FILL, FILL);
-        evas_object_size_hint_weight_set(rec, EXPAND, EXPAND);
-        elm_table_pack(tbl2, rec, 0, 0, 1, 1);
-
-        lb = elm_label_add(parent);
-        evas_object_size_hint_align_set(lb, FILL, FILL);
-        evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
-        elm_object_text_set(lb, buf);
-        elm_table_pack(tbl2, lb, 0, 0, 1, 1);
-        elm_table_pack(tbl, tbl2, 4, i, 1, 1);
-
-        Explainer *exp = malloc(sizeof(Explainer));
-        exp->rec = rec;
-        exp->lb = lb;
-
-        ad->explainers = eina_list_append(ad->explainers, exp);
+        if (!strcmp(name, visualizations[i].name))
+          return &visualizations[i];
      }
-
-   btn = elm_button_add(parent);
-   ic = elm_icon_add(btn);
-   elm_icon_standard_set(ic, evisum_icon_path_get("menu"));
-   elm_object_part_content_set(btn, "icon", ic);
-   evas_object_show(ic);
-   elm_object_focus_allow_set(btn, 0);
-   evas_object_size_hint_min_set(btn, ELM_SCALE_SIZE(BTN_HEIGHT), 
ELM_SCALE_SIZE(BTN_HEIGHT));
-   evas_object_smart_callback_add(btn, "clicked", _btn_menu_clicked_cb, ad);
-
-   ad->btn_menu = lay = elm_layout_add(parent);
-   evas_object_size_hint_weight_set(lay, 1.0, 1.0);
-   evas_object_size_hint_align_set(lay, 0.99, 0.01);
-   elm_layout_file_set(lay, PACKAGE_DATA_DIR "/themes/evisum.edj", "cpu");
-   elm_layout_content_set(lay, "evisum/menu", btn);
-   elm_table_pack(tbl, lay, 0, 0, 5, ad->cpu_count);
-   evas_object_show(lay);
-
-   bx = elm_box_add(box);
-   evas_object_size_hint_align_set(bx, FILL, FILL);
-   evas_object_size_hint_weight_set(bx, EXPAND, EXPAND);
-   evas_object_show(bx);
-   elm_box_pack_end(bx, tbl);
-
-   // Set the main content.
-   elm_box_pack_end(box, bx);
-
-   tbl = elm_table_add(box);
-   evas_object_size_hint_align_set(tbl, FILL, FILL);
-   evas_object_size_hint_weight_set(tbl, EXPAND, 0);
-   evas_object_show(tbl);
-
-   fr = elm_frame_add(box);
-   evas_object_size_hint_align_set(fr, FILL, FILL);
-   evas_object_size_hint_weight_set(fr, EXPAND, 0);
-   evas_object_show(fr);
-   elm_object_text_set(fr, _("Legend"));
-   elm_object_content_set(fr, tbl);
-
-   colors = evas_object_image_add(evas_object_evas_get(fr));
-   evas_object_size_hint_min_set
-     (colors, 100, COLORS_HEIGHT * elm_config_scale_get());
-   evas_object_size_hint_align_set(colors, FILL, FILL);
-   evas_object_size_hint_weight_set(colors, EXPAND, EXPAND);
-   evas_object_image_smooth_scale_set(colors, 0);
-   evas_object_image_filled_set(colors, 1);
-   evas_object_image_alpha_set(colors, 0);
-   _colors_fill(colors);
-   elm_table_pack(tbl, colors, 0, 0, 2, 3);
-   evas_object_show(colors);
-
-   lb = elm_label_add(parent);
-   elm_object_text_set(lb, "<b><color=#fff> 0%</></>");
-   evas_object_size_hint_align_set(lb, 0.0, 0.5);
-   evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
-   elm_table_pack(tbl, lb, 0, 0, 1, 1);
-   evas_object_show(lb);
-
-   lb = elm_label_add(parent);
-   f = (ad->freq_min + 500) / 1000;
-   if (f < 1000)
-     snprintf(buf, sizeof(buf), "<b><color=#fff> %iMHz</></>", f);
-   else
-     snprintf(buf, sizeof(buf), "<b><color=#fff> %1.1fGHz</></>", ((double)f + 
0.05) / 1000.0);
-   elm_object_text_set(lb, buf);
-   evas_object_size_hint_align_set(lb, 0.0, 0.5);
-   evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
-   elm_table_pack(tbl, lb, 0, 1, 1, 1);
-   evas_object_show(lb);
-
-   lb = elm_label_add(parent);
-   elm_object_text_set(lb, "<b><color=#fff>100%</></>");
-   evas_object_size_hint_align_set(lb, 0.99, 0.5);
-   evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
-   elm_table_pack(tbl, lb, 1, 0, 1, 1);
-   evas_object_show(lb);
-
-   lb = elm_label_add(parent);
-   f = (ad->freq_max + 500) / 1000;
-   if (f < 1000)
-     snprintf(buf, sizeof(buf), "<b><color=#fff>%iMHz</></>", f);
-   else
-     snprintf(buf, sizeof(buf), "<b><color=#fff>%1.1fGHz</></>", ((double)f + 
0.05) / 1000.0);
-   elm_object_text_set(lb, buf);
-   evas_object_size_hint_align_set(lb, 0.99, 0.5);
-   evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
-   elm_table_pack(tbl, lb, 1, 1, 1, 1);
-   evas_object_show(lb);
-
-   lb = elm_label_add(parent);
-   snprintf(buf, sizeof(buf), "<b><color=#fff> %i°C</></>", ad->temp_min);
-   elm_object_text_set(lb, buf);
-   evas_object_size_hint_align_set(lb, 0.0, 0.5);
-   evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
-   elm_table_pack(tbl, lb, 0, 2, 1, 1);
-   evas_object_show(lb);
-
-   lb = elm_label_add(parent);
-   snprintf(buf, sizeof(buf), "<b><color=#fff>%i°C</></>", ad->temp_max);
-   elm_object_text_set(lb, buf);
-   evas_object_size_hint_align_set(lb, 0.99, 0.5);
-   evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
-   elm_table_pack(tbl, lb, 1, 2, 1, 1);
-   evas_object_show(lb);
-
-   elm_box_pack_end(box, fr);
-
-   fr = elm_frame_add(box);
-   elm_frame_autocollapse_set(fr, 1);
-   evas_object_size_hint_align_set(fr, FILL, FILL);
-   evas_object_size_hint_weight_set(fr, EXPAND, 0);
-   evas_object_show(fr);
-   elm_frame_collapse_set(fr, 0);
-   elm_object_text_set(fr, _("Options"));
-   elm_box_pack_end(box, fr);
-
-   hbx = elm_box_add(fr);
-   evas_object_size_hint_align_set(hbx, FILL, FILL);
-   evas_object_size_hint_weight_set(hbx, EXPAND, 0);
-   elm_box_horizontal_set(hbx, 1);
-   evas_object_show(hbx);
-   elm_object_content_set(fr, hbx);
-
-   check = elm_check_add(fr);
-   evas_object_size_hint_align_set(check, FILL, FILL);
-   evas_object_size_hint_weight_set(check, EXPAND, 0);
-   elm_object_text_set(check, _("Overlay CPU frequency?"));
-   if (!ad->cpu_freq) elm_object_disabled_set(check, 1);
-   evas_object_show(check);
-   elm_box_pack_end(hbx, check);
-   evas_object_smart_callback_add(check, "changed", _check_changed_cb, ad);
-
-   check = elm_check_add(fr);
-   evas_object_size_hint_align_set(check, FILL, FILL);
-   evas_object_size_hint_weight_set(check, EXPAND, 0);
-   elm_object_text_set(check, _("Overlay CPU temperatures?"));
-   if (!ad->cpu_temp) elm_object_disabled_set(check, 1);
-   evas_object_smart_callback_add(check, "changed", _temp_check_changed_cb, 
ad);
-   evas_object_show(check);
-   elm_box_pack_end(hbx, check);
-
-   check = elm_check_add(fr);
-   evas_object_size_hint_align_set(check, FILL, FILL);
-   evas_object_size_hint_weight_set(check, EXPAND, 0);
-   elm_object_text_set(check, _("Confused?"));
-   evas_object_smart_callback_add(check, "changed", 
_confused_check_changed_cb, ad);
-   evas_object_show(check);
-   elm_box_pack_end(hbx, check);
-
-   ad->obj = obj;
-   ad->ui = ui;
-   ad->colors = colors;
-
-   // min size of cpu color graph to show all cores.
-   evas_object_size_hint_min_set
-     (obj, 100, (BAR_HEIGHT * ad->cpu_count) * elm_config_scale_get());
-
-   evas_object_event_callback_add(ui->cpu.win, EVAS_CALLBACK_DEL, _win_del_cb, 
ad);
-   evas_object_event_callback_add(ui->cpu.win, EVAS_CALLBACK_MOVE, 
_win_move_cb, ad);
-
-   // run a feedback thread that sends feedback to the mainloop
-   ad->thread = ecore_thread_feedback_run(_core_times_main_cb,
-                                          _core_times_feedback_cb,
-                                          NULL,
-                                          NULL,
-                                          ad, 1);
-   return ad;
+   return NULL;
 }
 
- static void
-_win_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+void
+ui_cpu_win_restart(Evisum_Ui *ui)
 {
-   Evisum_Ui *ui = data;
-
-   evas_object_geometry_get(obj, NULL, NULL, &ui->cpu.width, &ui->cpu.height);
+   evas_object_del(ui->cpu.win);
+   ui_cpu_win_add(ui);
 }
 
 void
 ui_cpu_win_add(Evisum_Ui *ui)
 {
-   Animate *ad;
-   Evas_Object *win, *box, *scr;
+   Cpu_Visual *vis;
+   Evas_Object *win, *box, *scr, *btn, *ic;
+   Evas_Object *tb;
+   Elm_Layout *lay;
+   Visualization *visualization;
+   static Eina_Bool init = 0;
 
    if (ui->cpu.win)
      {
@@ -801,13 +219,20 @@ ui_cpu_win_add(Evisum_Ui *ui)
         return;
      }
 
+   if (!init)
+     {
+        // init colormaps from a small # of points
+        _color_init(cpu_colormap_in, COLOR_CPU_NUM, cpu_colormap);
+        _color_init(freq_colormap_in, COLOR_FREQ_NUM, freq_colormap);
+        _color_init(temp_colormap_in, COLOR_TEMP_NUM, temp_colormap);
+        init = 1;
+     }
+
    ui->cpu.win = win = elm_win_util_standard_add("evisum",
                    _("CPU Activity"));
    elm_win_autodel_set(win, 1);
    evas_object_size_hint_weight_set(win, EXPAND, EXPAND);
    evas_object_size_hint_align_set(win, FILL, FILL);
-   evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE,
-                                  _win_resize_cb, ui);
 
    scr = elm_scroller_add(win);
    evas_object_size_hint_weight_set(scr, EXPAND, EXPAND);
@@ -816,17 +241,48 @@ ui_cpu_win_add(Evisum_Ui *ui)
                            ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
    evas_object_show(scr);
 
+   tb = elm_table_add(win);
+   evas_object_size_hint_align_set(tb, FILL, FILL);
+   evas_object_size_hint_weight_set(tb, EXPAND, EXPAND);
+   evas_object_show(tb);
+
    box = elm_box_add(win);
    evas_object_size_hint_align_set(box, FILL, FILL);
    evas_object_size_hint_weight_set(box, EXPAND, EXPAND);
    evas_object_show(box);
 
-   ad = _graph(ui, box);
-   evas_object_event_callback_add(scr, EVAS_CALLBACK_KEY_DOWN, 
_win_key_down_cb, ad);
-   evas_object_event_callback_add(scr, EVAS_CALLBACK_MOUSE_MOVE, 
_win_mouse_move_cb, ad);
-   elm_object_content_set(scr, box);
+   elm_table_pack(tb, box, 0, 0, 1, 1);
+
+   visualization = ui_cpu_visual_by_name(ui->cpu.visual);
+   vis = visualization->func(box);
+   vis->ui = ui;
+
+   elm_object_content_set(scr, tb);
    elm_object_content_set(win, scr);
 
+   btn = elm_button_add(win);
+   ic = elm_icon_add(btn);
+   elm_icon_standard_set(ic, evisum_icon_path_get("menu"));
+   elm_object_part_content_set(btn, "icon", ic);
+   evas_object_show(ic);
+   elm_object_focus_allow_set(btn, 0);
+   evas_object_size_hint_min_set(btn, ELM_SCALE_SIZE(BTN_HEIGHT), 
ELM_SCALE_SIZE(BTN_HEIGHT));
+   evas_object_smart_callback_add(btn, "clicked", _btn_menu_clicked_cb, vis);
+
+   vis->btn_menu = lay = elm_layout_add(win);
+   evas_object_size_hint_weight_set(lay, 1.0, 1.0);
+   evas_object_size_hint_align_set(lay, 0.99, 0.01);
+   elm_layout_file_set(lay, PACKAGE_DATA_DIR "/themes/evisum.edj", "cpu");
+   elm_layout_content_set(lay, "evisum/menu", btn);
+   elm_table_pack(tb, lay, 0, 0, 1, 1);
+   evas_object_show(lay);
+
+   evas_object_event_callback_add(scr, EVAS_CALLBACK_MOUSE_MOVE, 
_win_mouse_move_cb, vis);
+   evas_object_event_callback_add(scr, EVAS_CALLBACK_KEY_DOWN, 
_win_key_down_cb, ui);
+   evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE, _win_resize_cb, 
ui);
+   evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE,  _win_move_cb, 
ui);
+   evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _win_del_cb, vis);
+
    if ((ui->cpu.width > 0) && (ui->cpu.height > 0))
      evas_object_resize(win, ui->cpu.width, ui->cpu.height);
    else
diff --git a/src/bin/ui/ui_cpu.h b/src/bin/ui/ui_cpu.h
index bffbcc0..9f31a6b 100644
--- a/src/bin/ui/ui_cpu.h
+++ b/src/bin/ui/ui_cpu.h
@@ -4,7 +4,57 @@
 #include "evisum_ui.h"
 #include "../system/machine.h"
 
+typedef struct _Color_Point {
+   unsigned int val;
+   unsigned int color;
+} Color_Point;
+
+extern unsigned int cpu_colormap[256];
+extern unsigned int freq_colormap[256];
+extern unsigned int temp_colormap[256];
+
+#define AVAL(x) (((x) >> 24) & 0xff)
+#define RVAL(x) (((x) >> 16) & 0xff)
+#define GVAL(x) (((x) >>  8) & 0xff)
+#define BVAL(x) (((x)      ) & 0xff)
+#define ARGB(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+
+typedef struct {
+   short id;
+   short percent;
+   unsigned int freq;
+   unsigned int temp;
+} Core;
+
+typedef struct {
+   Evisum_Ui      *ui;
+   Ecore_Thread   *thread;
+
+   Evas_Object    *menu;
+   Elm_Layout     *btn_menu;
+   Eina_Bool       btn_visible;
+
+   // Callback to free user data.
+   void (*ext_free_cb)(void *);
+   void               *ext;
+
+} Cpu_Visual;
+
+typedef struct {
+   const char *name;
+   Cpu_Visual *(*func)(Evas_Object *parent);
+} Visualization;
+
 void
 ui_cpu_win_add(Evisum_Ui *ui);
 
+void
+ui_cpu_win_restart(Evisum_Ui *ui);
+
+Eina_List *
+ui_cpu_visuals_get(void);
+
+Visualization *
+ui_cpu_visual_by_name(const char *name);
+
 #endif
diff --git a/src/bin/ui/ui_process_list.c b/src/bin/ui/ui_process_list.c
index 01fe399..b9cead5 100644
--- a/src/bin/ui/ui_process_list.c
+++ b/src/bin/ui/ui_process_list.c
@@ -2317,6 +2317,9 @@ _win_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED,
 
    evisum_ui_config_save(ui);
 
+   if (wd->fields_timer)
+     ecore_timer_del(wd->fields_timer);
+
    if (wd->search.timer)
      ecore_timer_del(wd->search.timer);
 
diff --git a/src/bin/ui/visuals/cpu_basic.c b/src/bin/ui/visuals/cpu_basic.c
new file mode 100644
index 0000000..a69ac28
--- /dev/null
+++ b/src/bin/ui/visuals/cpu_basic.c
@@ -0,0 +1,130 @@
+#include "cpu_basic.h"
+
+typedef struct {
+   int        cpu_count;
+   int       *cpu_order;
+   Eina_List *objects;
+} Ext;
+
+static void
+_core_times_main_cb(void *data, Ecore_Thread *thread)
+{
+   int ncpu;
+   Cpu_Visual *vis = data;
+   Ext *ext = vis->ext;
+
+   while (!ecore_thread_check(thread))
+     {
+        cpu_core_t **cores = system_cpu_usage_delayed_get(&ncpu, 100000);
+        Core *cores_out = calloc(ncpu, sizeof(Core));
+
+        if (cores_out)
+          {
+             for (int n = 0; n < ncpu; n++)
+               {
+                  int id = ext->cpu_order[n];
+                  Core *core = &(cores_out[n]);
+                  core->id = id;
+                  core->percent = cores[id]->percent;
+                  free(cores[id]);
+               }
+             ecore_thread_feedback(thread, cores_out);
+          }
+        free(cores);
+     }
+}
+
+static void
+_core_times_feedback_cb(void *data, Ecore_Thread *thread EINA_UNUSED, void 
*msgdata)
+{
+   Cpu_Visual *vis;
+   Core *cores;
+   Ext *ext;
+
+   vis = data;
+   ext = vis->ext;
+   cores = msgdata;
+
+   for (int i = 0; i < ext->cpu_count; i++)
+     {
+        Core *core = &cores[i];
+        Evas_Object *lb = eina_list_nth(ext->objects, i);
+        Evas_Object *rec = evas_object_data_get(lb, "r");
+        int c = cpu_colormap[core->percent & 0xff];
+        evas_object_color_set(rec, RVAL(c), GVAL(c), BVAL(c), AVAL(c));
+  
+        elm_object_text_set(lb, eina_slstr_printf("%d%%", core->percent));
+     }
+
+   free(cores);
+}
+
+static void
+_cb_free(void *data)
+{
+   Ext *ext = data;
+   
+   eina_list_free(ext->objects);
+
+   free(ext->cpu_order);
+   free(ext);
+}
+
+Cpu_Visual *
+cpu_visual_basic(Evas_Object *parent_bx)
+{
+   Evas_Object *tb;
+   Ext *ext;
+
+   Cpu_Visual *vis = calloc(1, sizeof(Cpu_Visual));
+   if (!vis) return NULL;
+
+   vis->ext = ext = calloc(1, sizeof(Ext));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ext, NULL);
+   vis->ext_free_cb = _cb_free;
+
+   /* Populate lookup table to match id with topology core id */
+   ext->cpu_count = system_cpu_count_get();
+   ext->cpu_order = malloc((ext->cpu_count) * sizeof(int));
+   for (int i = 0; i < ext->cpu_count; i++)
+     ext->cpu_order[i] = i;
+   system_cpu_topology_get(ext->cpu_order, ext->cpu_count);
+
+   tb = elm_table_add(parent_bx);
+   evas_object_size_hint_weight_set(tb, EXPAND, EXPAND);
+   evas_object_size_hint_align_set(tb, 0.5, 0.5);
+   evas_object_show(tb);
+
+   int row = 0, col = 0;
+   int w = sqrt(ext->cpu_count);
+   for (int i = 0; i < ext->cpu_count; i++)
+     {
+        if (!(i % w))
+          {
+             row++;
+             col = 0;
+          }
+        else col++;
+        Evas_Object *rec = evas_object_rectangle_add(evas_object_evas_get(tb));
+        evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(64), 
ELM_SCALE_SIZE(64));
+        elm_table_pack(tb, rec, col, row, 1, 1);
+        evas_object_show(rec);
+        Evas_Object *lb = elm_label_add(tb);
+        evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
+        evas_object_size_hint_align_set(lb, FILL, FILL);
+        elm_table_pack(tb, lb, col, row, 1, 1);
+        evas_object_show(lb);
+        evas_object_data_set(lb, "r", rec);
+        ext->objects = eina_list_append(ext->objects, lb);
+     }
+
+   elm_box_pack_end(parent_bx, tb);
+
+   vis->thread = ecore_thread_feedback_run(_core_times_main_cb,
+                                           _core_times_feedback_cb,
+                                           NULL,
+                                           NULL,
+                                           vis, 1);
+   return vis;
+}
+
diff --git a/src/bin/ui/visuals/cpu_basic.h b/src/bin/ui/visuals/cpu_basic.h
new file mode 100644
index 0000000..c3c6396
--- /dev/null
+++ b/src/bin/ui/visuals/cpu_basic.h
@@ -0,0 +1,9 @@
+#ifndef CPU_BASIC_H
+#define CPU_BASIC_H
+
+#include "ui/ui_cpu.h"
+
+Cpu_Visual *
+cpu_visual_basic(Evas_Object *parent);
+
+#endif
diff --git a/src/bin/ui/ui_cpu.c b/src/bin/ui/visuals/cpu_default.c
similarity index 54%
copy from src/bin/ui/ui_cpu.c
copy to src/bin/ui/visuals/cpu_default.c
index 681c572..e39f135 100644
--- a/src/bin/ui/ui_cpu.c
+++ b/src/bin/ui/visuals/cpu_default.c
@@ -1,26 +1,14 @@
-#include "ui_cpu.h"
-#include "config.h"
+#include "cpu_default.h"
 
-typedef struct {
-   short id;
-   short percent;
-   unsigned int freq;
-   unsigned int temp;
-} Core;
+#define BAR_HEIGHT    3
+#define COLORS_HEIGHT 32
+#define CORES_MANY    16
 
 typedef struct {
-   Ecore_Thread   *thread;
-
-   Evas_Object    *win;
-   Evas_Object    *menu;
-   Elm_Layout     *btn_menu;
-   Eina_Bool       btn_visible;
-   Evas_Object    *bg;
    Evas_Object    *obj;
-
+   Evas_Object    *bg;
    Evas_Object    *colors;
    int             cpu_count;
-   int            *cpu_order;
 
    Eina_Bool       show_cpufreq;
    // Have cpu scaling
@@ -29,121 +17,29 @@ typedef struct {
    int             freq_max;
 
    Eina_Bool       show_cputemp;
-   // Have temp readings.
+   // Have temp readings
    Eina_Bool       cpu_temp;
    int             temp_min;
    int             temp_max;
 
-   Eina_Bool       confused;
    Eina_List      *explainers;
-
-   Evisum_Ui      *ui;
-} Animate;
-
-typedef struct _Color_Point {
-   unsigned int val;
-   unsigned int color;
-} Color_Point;
-
-// config for colors/sizing
-#define COLOR_CPU_NUM 5
-static const Color_Point cpu_colormap_in[] = {
-   {   0, 0xff202020 }, // 0
-   {  25, 0xff2030a0 }, // 1
-   {  50, 0xffa040a0 }, // 2
-   {  75, 0xffff9040 }, // 3
-   { 100, 0xffffffff }, // 4
-   { 256, 0xffffffff }  // overflow to avoid if's
-};
-#define COLOR_FREQ_NUM 4
-static const Color_Point freq_colormap_in[] = {
-   {   0, 0xff202020 }, // 0
-   {  33, 0xff285020 }, // 1
-   {  67, 0xff30a060 }, // 2
-   { 100, 0xffa0ff80 }, // 3
-   { 256, 0xffa0ff80 }  // overflow to avoid if's
-};
-
-#define COLOR_TEMP_NUM 5
-static const Color_Point temp_colormap_in[] = {
-   {  0,  0xff57bb8a },
-   {  25, 0xffa4c073 },
-   {  50, 0xfff5ce62 },
-   {  75, 0xffe9a268 },
-   { 100, 0xffdd776e },
-   { 256, 0xffdd776e }
-};
-
-#define BAR_HEIGHT    3
-#define COLORS_HEIGHT 32
-#define CORES_MANY    16
-
-// stored colormap tables
-static unsigned int cpu_colormap[256];
-static unsigned int freq_colormap[256];
-static unsigned int temp_colormap[256];
-
-// handy macros to access argb values from pixels
-#define AVAL(x) (((x) >> 24) & 0xff)
-#define RVAL(x) (((x) >> 16) & 0xff)
-#define GVAL(x) (((x) >>  8) & 0xff)
-#define BVAL(x) (((x)      ) & 0xff)
-#define ARGB(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
-
-static void
-_color_init(const Color_Point *col_in, unsigned int n, unsigned int *col)
-{
-   unsigned int pos, interp, val, dist, d;
-   unsigned int a, r, g, b;
-   unsigned int a1, r1, g1, b1, v1;
-   unsigned int a2, r2, g2, b2, v2;
-
-   // wal colormap_in until colormap table is full
-   for (pos = 0, val = 0; pos < n; pos++)
-     {
-        // get first color and value position
-        v1 = col_in[pos].val;
-        a1 = AVAL(col_in[pos].color);
-        r1 = RVAL(col_in[pos].color);
-        g1 = GVAL(col_in[pos].color);
-        b1 = BVAL(col_in[pos].color);
-        // get second color and valuje position
-        v2 = col_in[pos + 1].val;
-        a2 = AVAL(col_in[pos + 1].color);
-        r2 = RVAL(col_in[pos + 1].color);
-        g2 = GVAL(col_in[pos + 1].color);
-        b2 = BVAL(col_in[pos + 1].color);
-        // get distance between values (how many entires to fill)
-        dist = v2 - v1;
-        // walk over the span of colors from point a to point b
-        for (interp = v1; interp < v2; interp++)
-          {
-             // distance from starting point
-             d = interp - v1;
-             // calculate linear interpolation between start and given d
-             a = ((d * a2) + ((dist - d) * a1)) / dist;
-             r = ((d * r2) + ((dist - d) * r1)) / dist;
-             g = ((d * g2) + ((dist - d) * g1)) / dist;
-             b = ((d * b2) + ((dist - d) * b1)) / dist;
-             // write out resulting color value
-             col[val] = ARGB(a, r, g, b);
-             val++;
-          }
-     }
-}
+   int            *cpu_order;
+   Eina_Bool       confused;
+} Ext;
 
 static void
 _core_times_main_cb(void *data, Ecore_Thread *thread)
 {
-   Animate *ad = data;
+   Cpu_Visual *vis = data;
    int ncpu;
+   Ext *ext = vis->ext;
 
-   if (!system_cpu_frequency_min_max_get(&ad->freq_min, &ad->freq_max))
-     ad->cpu_freq = 1;
+   if (!system_cpu_frequency_min_max_get(&ext->freq_min, &ext->freq_max))
+     ext->cpu_freq = 1;
 
-   system_cpu_temperature_min_max_get(&ad->temp_min, &ad->temp_max);
+   system_cpu_temperature_min_max_get(&ext->temp_min, &ext->temp_max);
    if ((system_cpu_n_temperature_get(0)) != -1)
-     ad->cpu_temp = 1;
+     ext->cpu_temp = 1;
 
    while (!ecore_thread_check(thread))
      {
@@ -154,13 +50,13 @@ _core_times_main_cb(void *data, Ecore_Thread *thread)
           {
              for (int n = 0; n < ncpu; n++)
                {
-                  int id = ad->cpu_order[n];
+                  int id = ext->cpu_order[n];
                   Core *core = &(cores_out[n]);
                   core->id = id;
                   core->percent = cores[id]->percent;
-                  if (ad->cpu_freq)
+                  if (ext->cpu_freq)
                     core->freq = system_cpu_n_frequency_get(id);
-                  if (ad->cpu_temp)
+                  if (ext->cpu_temp)
                     core->temp = system_cpu_n_temperature_get(id);
                   free(cores[id]);
                }
@@ -171,13 +67,15 @@ _core_times_main_cb(void *data, Ecore_Thread *thread)
 }
 
 static void
-_update(Animate *ad, Core *cores)
+_update(Cpu_Visual *vis, Core *cores)
 {
-   Evas_Object *obj = ad->obj;
+   Evas_Object *obj;
    unsigned int *pixels, *pix;
    Evas_Coord x, y, w, h;
    int iw, stride;
    Eina_Bool clear = 0;
+   Ext *ext = vis->ext;
+   obj = ext->obj;
 
    evas_object_geometry_get(obj, &x, &y, &w, &h);
    evas_object_image_size_get(obj, &iw, NULL);
@@ -185,7 +83,7 @@ _update(Animate *ad, Core *cores)
    // new size and mark it for clearing when we fill
    if (iw != w)
      {
-        evas_object_image_size_set(obj, w, ad->cpu_count * 3);
+        evas_object_image_size_set(obj, w, ext->cpu_count * 3);
         clear = 1;
      }
 
@@ -195,7 +93,7 @@ _update(Animate *ad, Core *cores)
    // get stride (# of bytes per line)
    stride = evas_object_image_stride_get(obj);
 
-   for (y = 0; y < ad->cpu_count; y++)
+   for (y = 0; y < ext->cpu_count; y++)
      {
         Core *core = &(cores[y]);
         unsigned int c1, c2;
@@ -228,10 +126,10 @@ _update(Animate *ad, Core *cores)
         pix = &(pixels[(y * 3) * (stride / 4)]);
         pix[x] = c1;
         // 2nd row of pixles for freq
-        if ((ad->show_cpufreq) && (ad->cpu_freq))
+        if ((ext->show_cpufreq) && (ext->cpu_freq))
           {
-             int v = core->freq - ad->freq_min;
-             int d = ad->freq_max - ad->freq_min;
+             int v = core->freq - ext->freq_min;
+             int d = ext->freq_max - ext->freq_min;
 
              // if there is a difference between min and max ... a range
              if (d > 0)
@@ -248,19 +146,19 @@ _update(Animate *ad, Core *cores)
              pix[x] = c2;
           }
 
-        if (ad->show_cputemp && ad->cpu_temp)
+        if (ext->show_cputemp && ext->cpu_temp)
           {
              pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
              pix[x] = temp_colormap[core->temp & 0xff];
           }
 
-        if (!ad->show_cpufreq)
+        if (!ext->show_cpufreq)
           {
              // no freq show - then just repeat cpu usage color
              pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
              pix[x] = c1;
           }
-        if (!ad->show_cputemp)
+        if (!ext->show_cputemp)
           {
              pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
              pix[x] = c1;
@@ -268,9 +166,9 @@ _update(Animate *ad, Core *cores)
      }
    // hand back pixel data ptr so evas knows we are done with it
    evas_object_image_data_set(obj, pixels);
-   // now add update region for all pixels in the image at the end as we
+   // now visd update region for all pixels in the image at the end as we
    // changed everything
-   evas_object_image_data_update_add(obj, 0, 0, w, ad->cpu_count * 3);
+   evas_object_image_data_update_add(obj, 0, 0, w, ext->cpu_count * 3);
 }
 
 typedef struct
@@ -280,24 +178,27 @@ typedef struct
 } Explainer;
 
 static void
-_explain(Animate *ad, Core *cores)
+_explain(Cpu_Visual *vis, Core *cores)
 {
    Eina_Strbuf *buf;
    Explainer *exp;
+   Ext *ext;
    Evas_Object *lb, *rec;
 
-   if (!ad->explainers) return;
+   ext = vis->ext;
+
+   if (!ext->explainers) return;
 
    buf = eina_strbuf_new();
 
-   for (int i = 0; i < ad->cpu_count; i++)
+   for (int i = 0; i < ext->cpu_count; i++)
      {
         Core *core = &(cores[i]);
-        exp = eina_list_nth(ad->explainers, i);
+        exp = eina_list_nth(ext->explainers, i);
 
         lb = exp->lb;
         rec = exp->rec;
-        if (!ad->confused)
+        if (!ext->confused)
           {
              evas_object_hide(rec);
              evas_object_hide(lb);
@@ -305,9 +206,9 @@ _explain(Animate *ad, Core *cores)
         else
           {
              eina_strbuf_append_printf(buf, "<b><color=#fff>%i%% ", 
core->percent);
-             if (ad->cpu_freq)
+             if (ext->cpu_freq)
                eina_strbuf_append_printf(buf, "%1.1fGHz ", (double) core->freq 
/ 1000000);
-             if (ad->cpu_temp)
+             if (ext->cpu_temp)
                eina_strbuf_append_printf(buf, "%i°C", core->temp);
              eina_strbuf_append(buf, "</></>");
 
@@ -323,18 +224,20 @@ _explain(Animate *ad, Core *cores)
 static void
 _core_times_feedback_cb(void *data, Ecore_Thread *thread EINA_UNUSED, void 
*msgdata)
 {
-   Animate *ad;
+   Cpu_Visual *vis;
    Core *cores;
+   Ext *ext;
    static Eina_Bool was_confused = 0;
 
-   ad = data;
+   vis = data;
+   ext = vis->ext;
    cores = msgdata;
 
-   _update(ad, cores);
+   _update(vis, cores);
 
-   if (ad->confused || was_confused)
+   if (ext->confused || was_confused)
      {
-        _explain(ad, cores);
+        _explain(vis, cores);
         was_confused = 1;
      }
 
@@ -342,70 +245,53 @@ _core_times_feedback_cb(void *data, Ecore_Thread *thread 
EINA_UNUSED, void *msgd
 }
 
 static void
-_win_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void 
*event_info EINA_UNUSED)
-{
-   Animate *ad;
-   Evisum_Ui *ui;
-
-   ad = data;
-   ui = ad->ui;
-
-   evas_object_geometry_get(obj, &ui->cpu.x, &ui->cpu.y, NULL, NULL);
-}
-
-static void
-_win_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA_UNUSED)
+_cb_free(void *data)
 {
    Explainer *exp;
-   Animate *ad = data;
-   Evisum_Ui *ui = ad->ui;
+   Ext *ext = data;
 
-   evisum_ui_config_save(ui);
-   ecore_thread_cancel(ad->thread);
-   ecore_thread_wait(ad->thread, 0.5);
+   EINA_LIST_FREE(ext->explainers, exp)
+     free(exp);
 
-   EINA_LIST_FREE(ad->explainers, exp)
-     {
-        free(exp);
-     }
+   free(ext->cpu_order);
 
-   ad->explainers = NULL;
-   free(ad->cpu_order);
-   free(ad);
-   ui->cpu.win = NULL;
+   free(ext);
 }
 
 static void
 _check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
                   void *event_info EINA_UNUSED)
 {
-   Animate *ad = data;
+   Cpu_Visual *vis = data;
+   Ext *ext = vis->ext;
 
-   ad->show_cpufreq = elm_check_state_get(obj);
+   ext->show_cpufreq = elm_check_state_get(obj);
 }
 
 static void
 _temp_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
                        void *event_info EINA_UNUSED)
 {
-   Animate *ad = data;
+   Cpu_Visual *vis = data;
+   Ext *ext = vis->ext;
 
-   ad->show_cputemp = elm_check_state_get(obj);
+   ext->show_cputemp = elm_check_state_get(obj);
 }
 
 static void
 _confused_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED,
                            void *event_info EINA_UNUSED)
 {
-   Animate *ad = data;
+   Cpu_Visual *vis = data;
+   Ext *ext = vis->ext;
 
-   ad->confused = elm_check_state_get(obj);
+   ext->confused = elm_check_state_get(obj);
 }
 
 static void
 _colors_fill(Evas_Object *colors)
 {
-   // fill a 3 pixel high (and 100 wide) image with 3 gradients matching
+   // fill a 3 pixel high (and 100 wide) image with 3 grvisients matching
    // the colormaps we calculated as a legend
    int x, stride;
    unsigned int *pixels;
@@ -425,104 +311,44 @@ _colors_fill(Evas_Object *colors)
    evas_object_image_data_update_add(colors, 0, 0, 101, 1);
 }
 
-static void
-_win_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
-{
-   Evas_Coord w, h;
-   Evas_Event_Mouse_Move *ev;
-   Animate *ad = data;
-
-   ev = event_info;
-   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
-
-   if ((ev->cur.canvas.x >= (w - 128)) && (ev->cur.canvas.y <= 128))
-     {
-       if (!ad->btn_visible)
-         {
-            elm_object_signal_emit(ad->btn_menu, "menu,show", "evisum/menu");
-            ad->btn_visible = 1;
-         }
-     }
-   else if ((ad->btn_visible) && (!ad->menu))
-    {
-       elm_object_signal_emit(ad->btn_menu, "menu,hide", "evisum/menu");
-       ad->btn_visible = 0;
-    }
-}
-
-static void
-_win_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
-{
-   Evas_Event_Key_Down *ev;
-   Animate *ad;
-
-   ad = data;
-   ev = event_info;
-
-   if (!ev || !ev->keyname)
-     return;
-
-   if (!strcmp(ev->keyname, "Escape"))
-     evas_object_del(ad->ui->cpu.win);
-}
-
-static void
-_btn_menu_clicked_cb(void *data, Evas_Object *obj,
-                     void *event_info EINA_UNUSED)
-{
-   Evisum_Ui *ui;
-   Animate *ad = data;
-
-   ui = ad->ui;
-   if (!ad->menu)
-     ad->menu = evisum_ui_main_menu_create(ui, ui->cpu.win, obj);
-   else
-     {
-        evas_object_del(ad->menu);
-        ad->menu = NULL;
-     }
-}
-
-static Animate *
-_graph(Evisum_Ui *ui, Evas_Object *parent)
+Cpu_Visual *
+cpu_visual_default(Evas_Object *parent_box)
 {
    Evas_Object *tbl, *tbl2, *box, *obj, *ic, *lb, *rec;
-   Evas_Object *fr, *bx, *hbx, *colors, *check, *btn;
-   Elm_Layout *lay;
+   Evas_Object *fr, *bx, *hbx, *colors, *check;
+   Ext *ext;
+   int *cpu_order;
    int i, f;
    char buf[128];
    Eina_Bool show_icons = 1;
 
-   Animate *ad = calloc(1, sizeof(Animate));
-   if (!ad) return NULL;
+   Cpu_Visual *vis = calloc(1, sizeof(Cpu_Visual));
+   if (!vis) return NULL;
 
-   ad->win = ui->cpu.win;
-   ad->cpu_count = system_cpu_count_get();
-   if (!system_cpu_frequency_min_max_get(&ad->freq_min, &ad->freq_max))
-     ad->cpu_freq = 1;
+   vis->ext = ext = calloc(1, sizeof(Ext));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ext, NULL);
 
-   system_cpu_temperature_min_max_get(&ad->temp_min, &ad->temp_max);
-   if ((system_cpu_n_temperature_get(0)) != -1)
-     ad->cpu_temp = 1;
+   ext->cpu_count = system_cpu_count_get();
+   if (!system_cpu_frequency_min_max_get(&ext->freq_min, &ext->freq_max))
+     ext->cpu_freq = 1;
 
-   ad->cpu_order = malloc((ad->cpu_count) * sizeof(int));
-   for (i = 0; i < ad->cpu_count; i++)
-     ad->cpu_order[i] = i;
-   system_cpu_topology_get(ad->cpu_order, ad->cpu_count);
+   system_cpu_temperature_min_max_get(&ext->temp_min, &ext->temp_max);
+   if ((system_cpu_n_temperature_get(0)) != -1)
+     ext->cpu_temp = 1;
 
-   // init colormaps from a small # of points
-   _color_init(cpu_colormap_in, COLOR_CPU_NUM, cpu_colormap);
-   _color_init(freq_colormap_in, COLOR_FREQ_NUM, freq_colormap);
-   _color_init(temp_colormap_in, COLOR_TEMP_NUM, temp_colormap);
+   ext->cpu_order = cpu_order = malloc((ext->cpu_count) * sizeof(int));
+   for (i = 0; i < ext->cpu_count; i++)
+     cpu_order[i] = i;
+   system_cpu_topology_get(cpu_order, ext->cpu_count);
 
-   box = parent;
+   box = parent_box;
 
    tbl = elm_table_add(box);
    evas_object_size_hint_align_set(tbl, FILL, FILL);
    evas_object_size_hint_weight_set(tbl, EXPAND, EXPAND);
    evas_object_show(tbl);
 
-   obj = evas_object_image_add(evas_object_evas_get(parent));
+   obj = evas_object_image_add(evas_object_evas_get(box));
    evas_object_size_hint_align_set(obj, FILL, FILL);
    evas_object_size_hint_weight_set(obj, EXPAND, EXPAND);
    evas_object_image_smooth_scale_set(obj, 0);
@@ -530,56 +356,56 @@ _graph(Evisum_Ui *ui, Evas_Object *parent)
    evas_object_image_alpha_set(obj, 0);
    evas_object_show(obj);
 
-   elm_table_pack(tbl, obj, 0, 0, 5, ad->cpu_count);
+   elm_table_pack(tbl, obj, 0, 0, 5, ext->cpu_count);
 
-   if (ad->cpu_count > CORES_MANY)
+   if (ext->cpu_count > CORES_MANY)
      show_icons = 0;
 
    if (show_icons)
      {
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
+        rec = evas_object_rectangle_add(evas_object_evas_get(box));
         evas_object_size_hint_align_set(rec, FILL, FILL);
         evas_object_size_hint_weight_set(rec, EXPAND, EXPAND);
         evas_object_color_set(rec, 0, 0, 0, 64);
         evas_object_show(rec);
-        elm_table_pack(tbl, rec, 0, 0, 4, ad->cpu_count);
+        elm_table_pack(tbl, rec, 0, 0, 4, ext->cpu_count);
      }
 
-   for (i = 0; show_icons && (i < ad->cpu_count); i++)
+   for (i = 0; show_icons && (i < ext->cpu_count); i++)
      {
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
+        rec = evas_object_rectangle_add(evas_object_evas_get(box));
         evas_object_color_set(rec, 0, 0, 0, 0);
         evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(8), 
ELM_SCALE_SIZE(8));
         evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
         elm_table_pack(tbl, rec, 0, i, 1, 1);
 
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
+        rec = evas_object_rectangle_add(evas_object_evas_get(box));
         evas_object_color_set(rec, 0, 0, 0, 0);
         evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(24), 
ELM_SCALE_SIZE(24));
         evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
         elm_table_pack(tbl, rec, 1, i, 1, 1);
 
-        ic = elm_icon_add(parent);
+        ic = elm_icon_add(box);
         elm_icon_standard_set(ic, evisum_icon_path_get("cpu"));
         evas_object_size_hint_align_set(ic, FILL, FILL);
         evas_object_size_hint_weight_set(ic, 0.0, EXPAND);
         elm_table_pack(tbl, ic, 1, i, 1, 1);
         evas_object_show(ic);
 
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
+        rec = evas_object_rectangle_add(evas_object_evas_get(box));
         evas_object_color_set(rec, 0, 0, 0, 0);
         evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(8), 
ELM_SCALE_SIZE(8));
         evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
         elm_table_pack(tbl, rec, 2, i, 1, 1);
 
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
+        rec = evas_object_rectangle_add(evas_object_evas_get(box));
         evas_object_color_set(rec, 0, 0, 0, 0);
         evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(16), 
ELM_SCALE_SIZE(16));
         evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
         elm_table_pack(tbl, rec, 3, i, 1, 1);
 
-        lb = elm_label_add(parent);
-        snprintf(buf, sizeof(buf), "<b><color=#fff>%i</></>", 
ad->cpu_order[i]);
+        lb = elm_label_add(box);
+        snprintf(buf, sizeof(buf), "<b><color=#fff>%i</></>", cpu_order[i]);
         elm_object_text_set(lb, buf);
         evas_object_size_hint_align_set(lb, 0.0, 0.5);
         evas_object_size_hint_weight_set(lb, 0.0, EXPAND);
@@ -588,18 +414,18 @@ _graph(Evisum_Ui *ui, Evas_Object *parent)
 
         // Begin explainer label overlay.
 
-        tbl2 = elm_table_add(parent);
+        tbl2 = elm_table_add(box);
         evas_object_size_hint_align_set(tbl2, 0.7, 0.5);
         evas_object_size_hint_weight_set(tbl2, EXPAND, EXPAND);
         evas_object_show(tbl2);
 
-        rec = evas_object_rectangle_add(evas_object_evas_get(parent));
+        rec = evas_object_rectangle_add(evas_object_evas_get(box));
         evas_object_color_set(rec, 0, 0, 0, 128);
         evas_object_size_hint_align_set(rec, FILL, FILL);
         evas_object_size_hint_weight_set(rec, EXPAND, EXPAND);
         elm_table_pack(tbl2, rec, 0, 0, 1, 1);
 
-        lb = elm_label_add(parent);
+        lb = elm_label_add(box);
         evas_object_size_hint_align_set(lb, FILL, FILL);
         evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
         elm_object_text_set(lb, buf);
@@ -610,25 +436,11 @@ _graph(Evisum_Ui *ui, Evas_Object *parent)
         exp->rec = rec;
         exp->lb = lb;
 
-        ad->explainers = eina_list_append(ad->explainers, exp);
+        ext->explainers = eina_list_append(ext->explainers, exp);
      }
 
-   btn = elm_button_add(parent);
-   ic = elm_icon_add(btn);
-   elm_icon_standard_set(ic, evisum_icon_path_get("menu"));
-   elm_object_part_content_set(btn, "icon", ic);
-   evas_object_show(ic);
-   elm_object_focus_allow_set(btn, 0);
-   evas_object_size_hint_min_set(btn, ELM_SCALE_SIZE(BTN_HEIGHT), 
ELM_SCALE_SIZE(BTN_HEIGHT));
-   evas_object_smart_callback_add(btn, "clicked", _btn_menu_clicked_cb, ad);
-
-   ad->btn_menu = lay = elm_layout_add(parent);
-   evas_object_size_hint_weight_set(lay, 1.0, 1.0);
-   evas_object_size_hint_align_set(lay, 0.99, 0.01);
-   elm_layout_file_set(lay, PACKAGE_DATA_DIR "/themes/evisum.edj", "cpu");
-   elm_layout_content_set(lay, "evisum/menu", btn);
-   elm_table_pack(tbl, lay, 0, 0, 5, ad->cpu_count);
-   evas_object_show(lay);
+   // Callback to free anything extra we pass around via the ext pointer in 
(Cpu_Visual *).
+   vis->ext_free_cb = _cb_free;
 
    bx = elm_box_add(box);
    evas_object_size_hint_align_set(bx, FILL, FILL);
@@ -663,15 +475,15 @@ _graph(Evisum_Ui *ui, Evas_Object *parent)
    elm_table_pack(tbl, colors, 0, 0, 2, 3);
    evas_object_show(colors);
 
-   lb = elm_label_add(parent);
+   lb = elm_label_add(box);
    elm_object_text_set(lb, "<b><color=#fff> 0%</></>");
    evas_object_size_hint_align_set(lb, 0.0, 0.5);
    evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
    elm_table_pack(tbl, lb, 0, 0, 1, 1);
    evas_object_show(lb);
 
-   lb = elm_label_add(parent);
-   f = (ad->freq_min + 500) / 1000;
+   lb = elm_label_add(box);
+   f = (ext->freq_min + 500) / 1000;
    if (f < 1000)
      snprintf(buf, sizeof(buf), "<b><color=#fff> %iMHz</></>", f);
    else
@@ -682,15 +494,15 @@ _graph(Evisum_Ui *ui, Evas_Object *parent)
    elm_table_pack(tbl, lb, 0, 1, 1, 1);
    evas_object_show(lb);
 
-   lb = elm_label_add(parent);
+   lb = elm_label_add(box);
    elm_object_text_set(lb, "<b><color=#fff>100%</></>");
    evas_object_size_hint_align_set(lb, 0.99, 0.5);
    evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
    elm_table_pack(tbl, lb, 1, 0, 1, 1);
    evas_object_show(lb);
 
-   lb = elm_label_add(parent);
-   f = (ad->freq_max + 500) / 1000;
+   lb = elm_label_add(box);
+   f = (ext->freq_max + 500) / 1000;
    if (f < 1000)
      snprintf(buf, sizeof(buf), "<b><color=#fff>%iMHz</></>", f);
    else
@@ -701,16 +513,16 @@ _graph(Evisum_Ui *ui, Evas_Object *parent)
    elm_table_pack(tbl, lb, 1, 1, 1, 1);
    evas_object_show(lb);
 
-   lb = elm_label_add(parent);
-   snprintf(buf, sizeof(buf), "<b><color=#fff> %i°C</></>", ad->temp_min);
+   lb = elm_label_add(box);
+   snprintf(buf, sizeof(buf), "<b><color=#fff> %i°C</></>", ext->temp_min);
    elm_object_text_set(lb, buf);
    evas_object_size_hint_align_set(lb, 0.0, 0.5);
    evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
    elm_table_pack(tbl, lb, 0, 2, 1, 1);
    evas_object_show(lb);
 
-   lb = elm_label_add(parent);
-   snprintf(buf, sizeof(buf), "<b><color=#fff>%i°C</></>", ad->temp_max);
+   lb = elm_label_add(box);
+   snprintf(buf, sizeof(buf), "<b><color=#fff>%i°C</></>", ext->temp_max);
    elm_object_text_set(lb, buf);
    evas_object_size_hint_align_set(lb, 0.99, 0.5);
    evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
@@ -739,17 +551,17 @@ _graph(Evisum_Ui *ui, Evas_Object *parent)
    evas_object_size_hint_align_set(check, FILL, FILL);
    evas_object_size_hint_weight_set(check, EXPAND, 0);
    elm_object_text_set(check, _("Overlay CPU frequency?"));
-   if (!ad->cpu_freq) elm_object_disabled_set(check, 1);
+   if (!ext->cpu_freq) elm_object_disabled_set(check, 1);
    evas_object_show(check);
    elm_box_pack_end(hbx, check);
-   evas_object_smart_callback_add(check, "changed", _check_changed_cb, ad);
+   evas_object_smart_callback_add(check, "changed", _check_changed_cb, vis);
 
    check = elm_check_add(fr);
    evas_object_size_hint_align_set(check, FILL, FILL);
    evas_object_size_hint_weight_set(check, EXPAND, 0);
    elm_object_text_set(check, _("Overlay CPU temperatures?"));
-   if (!ad->cpu_temp) elm_object_disabled_set(check, 1);
-   evas_object_smart_callback_add(check, "changed", _temp_check_changed_cb, 
ad);
+   if (!ext->cpu_temp) elm_object_disabled_set(check, 1);
+   evas_object_smart_callback_add(check, "changed", _temp_check_changed_cb, 
vis);
    evas_object_show(check);
    elm_box_pack_end(hbx, check);
 
@@ -757,86 +569,23 @@ _graph(Evisum_Ui *ui, Evas_Object *parent)
    evas_object_size_hint_align_set(check, FILL, FILL);
    evas_object_size_hint_weight_set(check, EXPAND, 0);
    elm_object_text_set(check, _("Confused?"));
-   evas_object_smart_callback_add(check, "changed", 
_confused_check_changed_cb, ad);
+   evas_object_smart_callback_add(check, "changed", 
_confused_check_changed_cb, vis);
    evas_object_show(check);
    elm_box_pack_end(hbx, check);
 
-   ad->obj = obj;
-   ad->ui = ui;
-   ad->colors = colors;
+   ext->obj = obj;
+   ext->colors = colors;
 
    // min size of cpu color graph to show all cores.
    evas_object_size_hint_min_set
-     (obj, 100, (BAR_HEIGHT * ad->cpu_count) * elm_config_scale_get());
-
-   evas_object_event_callback_add(ui->cpu.win, EVAS_CALLBACK_DEL, _win_del_cb, 
ad);
-   evas_object_event_callback_add(ui->cpu.win, EVAS_CALLBACK_MOVE, 
_win_move_cb, ad);
+     (obj, 100, (BAR_HEIGHT * ext->cpu_count) * elm_config_scale_get());
 
    // run a feedback thread that sends feedback to the mainloop
-   ad->thread = ecore_thread_feedback_run(_core_times_main_cb,
-                                          _core_times_feedback_cb,
-                                          NULL,
-                                          NULL,
-                                          ad, 1);
-   return ad;
-}
-
- static void
-_win_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
-{
-   Evisum_Ui *ui = data;
-
-   evas_object_geometry_get(obj, NULL, NULL, &ui->cpu.width, &ui->cpu.height);
-}
-
-void
-ui_cpu_win_add(Evisum_Ui *ui)
-{
-   Animate *ad;
-   Evas_Object *win, *box, *scr;
-
-   if (ui->cpu.win)
-     {
-        elm_win_raise(ui->cpu.win);
-        return;
-     }
-
-   ui->cpu.win = win = elm_win_util_standard_add("evisum",
-                   _("CPU Activity"));
-   elm_win_autodel_set(win, 1);
-   evas_object_size_hint_weight_set(win, EXPAND, EXPAND);
-   evas_object_size_hint_align_set(win, FILL, FILL);
-   evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE,
-                                  _win_resize_cb, ui);
-
-   scr = elm_scroller_add(win);
-   evas_object_size_hint_weight_set(scr, EXPAND, EXPAND);
-   evas_object_size_hint_align_set(scr, FILL, FILL);
-   elm_scroller_policy_set(scr,
-                           ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
-   evas_object_show(scr);
-
-   box = elm_box_add(win);
-   evas_object_size_hint_align_set(box, FILL, FILL);
-   evas_object_size_hint_weight_set(box, EXPAND, EXPAND);
-   evas_object_show(box);
-
-   ad = _graph(ui, box);
-   evas_object_event_callback_add(scr, EVAS_CALLBACK_KEY_DOWN, 
_win_key_down_cb, ad);
-   evas_object_event_callback_add(scr, EVAS_CALLBACK_MOUSE_MOVE, 
_win_mouse_move_cb, ad);
-   elm_object_content_set(scr, box);
-   elm_object_content_set(win, scr);
-
-   if ((ui->cpu.width > 0) && (ui->cpu.height > 0))
-     evas_object_resize(win, ui->cpu.width, ui->cpu.height);
-   else
-     evas_object_resize(win, ELM_SCALE_SIZE(UI_CHILD_WIN_WIDTH * 1.8), 
ELM_SCALE_SIZE(UI_CHILD_WIN_HEIGHT));
-
-   if ((ui->cpu.x > 0) && (ui->cpu.y > 0))
-     evas_object_move(win, ui->cpu.x, ui->cpu.y);
-   else
-     elm_win_center(win, 1, 1);
-
-   evas_object_show(win);
+   vis->thread = ecore_thread_feedback_run(_core_times_main_cb,
+                                           _core_times_feedback_cb,
+                                           NULL,
+                                           NULL,
+                                           vis, 1);
+   return vis;
 }
 
diff --git a/src/bin/ui/visuals/cpu_default.h b/src/bin/ui/visuals/cpu_default.h
new file mode 100644
index 0000000..86e05c9
--- /dev/null
+++ b/src/bin/ui/visuals/cpu_default.h
@@ -0,0 +1,9 @@
+#ifndef CPU_VISUAL_H
+#define CPU_VISUAL_H
+
+#include "ui/ui_cpu.h"
+
+Cpu_Visual *
+cpu_visual_default(Evas_Object *parent);
+
+#endif
diff --git a/src/bin/ui/visuals/meson.build b/src/bin/ui/visuals/meson.build
new file mode 100644
index 0000000..f00a2a7
--- /dev/null
+++ b/src/bin/ui/visuals/meson.build
@@ -0,0 +1,6 @@
+src += files([
+  'cpu_default.c',
+  'cpu_default.h',
+  'cpu_basic.c',
+  'cpu_basic.h',
+])
diff --git a/src/bin/ui/visuals/visuals.x b/src/bin/ui/visuals/visuals.x
new file mode 100644
index 0000000..429d297
--- /dev/null
+++ b/src/bin/ui/visuals/visuals.x
@@ -0,0 +1,7 @@
+#include "cpu_default.h"
+#include "cpu_basic.h"
+
+Visualization visualizations[] = {
+   { .name = "default", .func = cpu_visual_default },
+   { .name = "basic", .func = cpu_visual_basic },
+};

-- 


Reply via email to