[gnome-system-monitor] Generate CPU colors randomly (fixes #92, fixes #52)



commit 68bd2712b631ca697665b5f759fbdcb43547ac15
Author: Benoît Dejean <bdejean gmail com>
Date:   Mon Oct 19 23:13:21 2020 +0300

    Generate CPU colors randomly (fixes #92, fixes #52)

 src/application.cpp |  9 +++----
 src/util.cpp        | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util.h          |  4 ++++
 3 files changed, 75 insertions(+), 6 deletions(-)
---
diff --git a/src/application.cpp b/src/application.cpp
index e42fd8a1..878f5e8d 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -94,6 +94,8 @@ apply_cpu_color_settings(Gio::Settings& settings, GsmApplication* app)
 
     g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
 
+    std::vector<std::string> random_colors = procman::generate_colors(app->config.num_cpus);
+
     for (guint i = 0; i < static_cast<guint>(app->config.num_cpus); i++) {
         if(i < n) {
             child = g_variant_get_child_value ( cpu_colors_var, i );
@@ -101,12 +103,7 @@ apply_cpu_color_settings(Gio::Settings& settings, GsmApplication* app)
             g_variant_builder_add_value ( &builder, child);
             g_variant_unref (child);
         } else {
-            // Choose bytes less than 0xff because light colors are hard to see.
-            unsigned int r = rand() % 0xdd + 1;
-            unsigned int g = rand() % 0xdd + 1;
-            unsigned int b = rand() % 0xdd + 1;
-
-            color = g_strdup_printf("#%02x%02x%02x", r, g, b);
+            color = g_strdup (random_colors[i].c_str());
             g_variant_builder_add(&builder, "(us)", i, color);
         }
         gdk_rgba_parse(&app->config.cpu_color[i], color);
diff --git a/src/util.cpp b/src/util.cpp
index eaa8320b..54704ac5 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1,6 +1,14 @@
 /* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 #include <config.h>
 
+#include <algorithm>
+#include <cmath>
+#include <cstdint>
+#include <cstdio>
+#include <random>
+#include <tuple>
+#include <vector>
+
 #include <glib/gi18n.h>
 #include <glib.h>
 #include <gtk/gtk.h>
@@ -311,9 +319,68 @@ procman_debug_real(const char *file, int line, const char *func,
 }
 
 
+    // h is in [0.0; 1.0] (and not [0°; 360°] )
+    // s is in [0.0; 1.0]
+    // v is in [0.0; 1.0]
+    // https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
+    std::tuple<double, double, double> hsv_to_rgb(double h, double s, double v)
+    {
+        const double c = v * s;
+        const double hp = h * 6; // 360° / 60°
+        const double x = c * (1 - std::abs(std::fmod(hp, 2.0) - 1));
+
+        double r1 = 0 , g1 = 0, b1 = 0;
+
+        switch (int(hp)) {
+        case 0: r1 = c; g1 = x; b1 = 0; break;
+        case 1: r1 = x; g1 = c; b1 = 0; break;
+        case 2: r1 = 0; g1 = c; b1 = x; break;
+        case 3: r1 = 0; g1 = x; b1 = c; break;
+        case 4: r1 = x; g1 = 0; b1 = c; break;
+        case 5: r1 = c; g1 = 0; b1 = x; break;
+        }
+
+        const double m = v - c;
+
+        return {r1 + m, g1 + m, b1 + m};
+    }
+
+
+    std::string rgb_to_color_string(const std::tuple<double, double, double> &t)
+    {
+        char b[14];
+        auto c = [](double d) { return (unsigned short)(0xffff * d); };
+        std::snprintf(b, sizeof b, "#%04x%04x%04x", c(std::get<0>(t)), c(std::get<1>(t)), c(std::get<2>(t)));
+        return {b, 13};
+    }
+
+
 
 namespace procman
 {
+
+    // http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
+    std::vector<std::string> generate_colors(unsigned n)
+    {
+        constexpr double golden_ration_conjugate = 0.618033988749894848204586834;
+
+        std::vector<std::string> values;
+
+        std::random_device re;
+        std::uniform_real_distribution<> dist(0.0, 1.0);
+
+        double h = dist(re);
+
+        for (unsigned i = 0; i < n; i++) {
+            h = CLAMP(h, 0.0, 1.0);
+            auto rgb = hsv_to_rgb(h, 0.5, 0.95);
+            values.push_back(rgb_to_color_string(rgb));
+            h = std::fmod(h + golden_ration_conjugate, 1.0);
+        }
+
+        return values;
+    }
+
     void size_cell_data_func(GtkTreeViewColumn *, GtkCellRenderer *renderer,
                              GtkTreeModel *model, GtkTreeIter *iter,
                              gpointer user_data)
@@ -690,3 +757,4 @@ make_tnum_attr_list (void)
 
     return attrs;
 }
+
diff --git a/src/util.h b/src/util.h
index ff3fa670..e596cf88 100644
--- a/src/util.h
+++ b/src/util.h
@@ -4,6 +4,7 @@
 
 #include <gtkmm.h>
 #include <string>
+#include <vector>
 
 using std::string;
 
@@ -43,6 +44,9 @@ inline string make_string(char *c_str)
 
 namespace procman
 {
+    // create a list of n color strings
+    std::vector<std::string> generate_colors(unsigned n);
+
     char* format_duration_for_display(unsigned centiseconds);
 
     void size_cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]