From fff99b14e87e57bd395b493ea3113de348cad05d Mon Sep 17 00:00:00 2001
From: Jonathan Wilkes <jon.w.wilkes@gmail.com>
Date: Tue, 13 Apr 2021 16:39:17 +0000
Subject: [PATCH] allow default iemgui colors to inherit colors from GUI
 presets

---
 pd/nw/css/c64.css                |  44 +++++---
 pd/nw/css/default.css            |  31 +++++-
 pd/nw/css/extended.css           |  29 ++++-
 pd/nw/css/footgun.css            |  42 +++++---
 pd/nw/css/inverted.css           |  44 +++++---
 pd/nw/css/solarized.css          |  38 +++++--
 pd/nw/css/solarized_inverted.css |  40 +++++--
 pd/nw/css/strongbad.css          |  40 +++++--
 pd/nw/css/subdued.css            |  38 +++++--
 pd/nw/css/vanilla.css            |  31 +++++-
 pd/nw/css/vanilla_inverted.css   |  39 +++++--
 pd/nw/pdgui.js                   | 179 ++++++++++++++++++++++---------
 pd/src/g_bang.c                  |  10 +-
 pd/src/g_vumeter.c               |   2 +-
 14 files changed, 462 insertions(+), 145 deletions(-)

diff --git a/pd/nw/css/c64.css b/pd/nw/css/c64.css
index 94a36f267..14aaf9338 100644
--- a/pd/nw/css/c64.css
+++ b/pd/nw/css/c64.css
@@ -357,9 +357,36 @@ text {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] labels */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: #a49aea;
+}
+
+.iem_fg {
+    fill: #7569d7;
+}
+
+.iem_bg {
+    fill: #3e32a2;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: #7569d7;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
-    fill: blue;
+.iemgui:not(.mycanvas) .iemgui_label_selected {
+    fill: #cc9933;
 }
 
 /* test of xlet hover animation... this should 
@@ -414,19 +441,10 @@ text {
 #save_before_quit {
     color: white;
     background-color: #3e32a2;
-    border:3px solid #cc9933;
-    padding: 12px;
-    margin: 12px;
-    box-shadow: 7px 7px 5px black;
-}
-
-/* Dialog to ask to save the patch before quitting */
-#save_before_quit {
-    background-color: #f3f3f3;
-    border:1px solid #f3f3f3;
+    border:1px solid #cc9933;
     padding: 12px;
     /* margin: 12px; */
-    /*box-shadow: 7px 7px 5px grey;*/
+    /*box-shadow: 7px 7px 5px black;*/
     width: 70%;
     left: 50%;
     top: 50%;
diff --git a/pd/nw/css/default.css b/pd/nw/css/default.css
index 187e5e2d6..b0ce74f82 100644
--- a/pd/nw/css/default.css
+++ b/pd/nw/css/default.css
@@ -511,8 +511,35 @@ text.activated {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] labels */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: black;
+}
+
+.iem_fg {
+    fill: black;
+}
+
+.iem_bg {
+    fill: #fcfcfc;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: black;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
+.iemgui:not(.mycanvas) .iemgui_label_selected {
     fill: #e87216;
 }
 
@@ -920,4 +947,4 @@ input[type="color"] {
 .label_color span {
     position: relative;
     bottom: 2px;
-}
\ No newline at end of file
+}
diff --git a/pd/nw/css/extended.css b/pd/nw/css/extended.css
index ca5e3834c..aa3f50072 100644
--- a/pd/nw/css/extended.css
+++ b/pd/nw/css/extended.css
@@ -347,8 +347,35 @@ text {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] labels */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: black;
+}
+
+.iem_fg {
+    fill: black;
+}
+
+.iem_bg {
+    fill: #fcfcfc;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: black;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
+.iemgui:not(.mycanvas) .iemgui_label_selected {
     fill: blue;
 }
 
diff --git a/pd/nw/css/footgun.css b/pd/nw/css/footgun.css
index 32c25a2e0..e56b3ab6a 100644
--- a/pd/nw/css/footgun.css
+++ b/pd/nw/css/footgun.css
@@ -442,7 +442,7 @@ text {
 
 /* text inside selected objects */
 :not(.gop).selected text {
-    fill: blue;
+    fill: #e87216;
 }
 
 /* for an object that didn't create */
@@ -473,9 +473,36 @@ text {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] label */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: black;
+}
+
+.iem_fg {
+    fill: black;
+}
+
+.iem_bg {
+    fill: #fcfcfc;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: black;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
-    fill: blue;
+.iemgui:not(.mycanvas) .iemgui_label_selected {
+    fill: #e87216;
 }
 
 /* test of xlet hover animation... this should 
@@ -535,15 +562,6 @@ text {
     background-color: #f3f3f3;
     border:1px solid #bbb;
     padding: 12px;
-    margin: 12px;
-    box-shadow: 7px 7px 5px grey;
-}
-
-/* Dialog to ask to save the patch before quitting */
-#save_before_quit {
-    background-color: #f3f3f3;
-    border:1px solid #f3f3f3;
-    padding: 12px;
     /* margin: 12px; */
     /*box-shadow: 7px 7px 5px grey;*/
     width: 70%;
diff --git a/pd/nw/css/inverted.css b/pd/nw/css/inverted.css
index 7f8262e5a..09fed7747 100644
--- a/pd/nw/css/inverted.css
+++ b/pd/nw/css/inverted.css
@@ -383,9 +383,36 @@ text.activated {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] label */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: white;
+}
+
+.iem_fg {
+    fill: white;
+}
+
+.iem_bg {
+    fill: #030303;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: white;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
-    fill: blue;
+.iemgui:not(.mycanvas) .iemgui_label_selected {
+    fill: #ffff00;
 }
 
 /* test of xlet hover animation... this should 
@@ -460,19 +487,6 @@ text.activated {
     color: white;
 }
 
-/* Dialog to ask to save the patch before quitting */
-#save_before_quit {
-    background-color: #f3f3f3;
-    border:1px solid #f3f3f3;
-    padding: 12px;
-    /* margin: 12px; */
-    /*box-shadow: 7px 7px 5px grey;*/
-    width: 70%;
-    left: 50%;
-    top: 50%;
-    transform: translate(-50%, -50%);
-}
-
 /* Search dialog */
 
 .search_body {
diff --git a/pd/nw/css/solarized.css b/pd/nw/css/solarized.css
index d52614a4e..4ea3dc8ca 100644
--- a/pd/nw/css/solarized.css
+++ b/pd/nw/css/solarized.css
@@ -363,8 +363,35 @@ text {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] label */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: #657b83;
+}
+
+.iem_fg {
+    fill: #93a1a1;
+}
+
+.iem_bg {
+    fill: #fdf6e3;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: #93a1a1;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
+.iemgui:not(.mycanvas) .iemgui_label_selected {
     fill: #268bd2;
 }
 
@@ -422,15 +449,6 @@ text {
     background-color: #fdf6e3;
     border:1px solid #eee8d5;
     padding: 12px;
-    margin: 12px;
-    box-shadow: 7px 7px 5px grey;
-}
-
-/* Dialog to ask to save the patch before quitting */
-#save_before_quit {
-    background-color: #f3f3f3;
-    border:1px solid #f3f3f3;
-    padding: 12px;
     /* margin: 12px; */
     /*box-shadow: 7px 7px 5px grey;*/
     width: 70%;
diff --git a/pd/nw/css/solarized_inverted.css b/pd/nw/css/solarized_inverted.css
index 7838bcd6e..e6862ce20 100644
--- a/pd/nw/css/solarized_inverted.css
+++ b/pd/nw/css/solarized_inverted.css
@@ -363,9 +363,36 @@ text {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] label */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: #839496;
+}
+
+.iem_fg {
+    fill: #586e75;
+}
+
+.iem_bg {
+    fill: #002b36;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: #586e75;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
-    fill: #268bd2;
+.iemgui:not(.mycanvas) .iemgui_label_selected {
+    fill: #b58900;
 }
 
 /* test of xlet hover animation... this should 
@@ -423,15 +450,6 @@ text {
     background-color: #002b36;
     border:1px solid #839496;
     padding: 12px;
-    margin: 12px;
-    box-shadow: 7px 7px 5px grey;
-}
-
-/* Dialog to ask to save the patch before quitting */
-#save_before_quit {
-    background-color: #f3f3f3;
-    border:1px solid #f3f3f3;
-    padding: 12px;
     /* margin: 12px; */
     /*box-shadow: 7px 7px 5px grey;*/
     width: 70%;
diff --git a/pd/nw/css/strongbad.css b/pd/nw/css/strongbad.css
index 24a1fc44c..cb4b4dc65 100644
--- a/pd/nw/css/strongbad.css
+++ b/pd/nw/css/strongbad.css
@@ -323,13 +323,13 @@ text {
       canvas.
 */
 :not(.gop).selected .border {
-    stroke: green;
+    stroke: yellow;
     display: inline;
 }
 
 /* text inside selected objects */
 :not(.gop).selected text {
-    fill: green;
+    fill: yellow;
 }
 
 /* for an object that didn't create */
@@ -360,9 +360,36 @@ text {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] label */
+.iem_label {
+    fill: #4bd046;
+}
+
+.iem_fg {
+    fill: #0b560b;
+}
+
+.iem_bg {
+    fill: black;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: #0b560b;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
-    fill: blue;
+.iemgui:not(.mycanvas) .iemgui_label_selected {
+    fill: yellow;
 }
 
 /* test of xlet hover animation... this should 
@@ -415,8 +442,9 @@ text {
 
 /* Dialog to ask to save the patch before quitting */
 #save_before_quit {
-    background-color: #f3f3f3;
-    border:1px solid #f3f3f3;
+    color: #53b83b;
+    background-color: black;
+    border:1px solid green;
     padding: 12px;
     /* margin: 12px; */
     /*box-shadow: 7px 7px 5px grey;*/
diff --git a/pd/nw/css/subdued.css b/pd/nw/css/subdued.css
index fbcacf0e1..4a4e06043 100644
--- a/pd/nw/css/subdued.css
+++ b/pd/nw/css/subdued.css
@@ -354,8 +354,35 @@ text {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] label */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: black;
+}
+
+.iem_fg {
+    fill: black;
+}
+
+.iem_bg {
+    fill: #9fc79f;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: black;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
+.iemgui:not(.mycanvas) .iemgui_label_selected {
     fill: blue;
 }
 
@@ -412,15 +439,6 @@ text {
     background-color: #c0dcc0;
     border:1px solid black;
     padding: 12px;
-    margin: 12px;
-    box-shadow: 7px 7px 5px grey;
-}
-
-/* Dialog to ask to save the patch before quitting */
-#save_before_quit {
-    background-color: #f3f3f3;
-    border:1px solid #f3f3f3;
-    padding: 12px;
     /* margin: 12px; */
     /*box-shadow: 7px 7px 5px grey;*/
     width: 70%;
diff --git a/pd/nw/css/vanilla.css b/pd/nw/css/vanilla.css
index 34cd28cdb..0c8949df9 100644
--- a/pd/nw/css/vanilla.css
+++ b/pd/nw/css/vanilla.css
@@ -292,7 +292,7 @@ text {
 
 /* text inside selected objects */
 :not(.gop).selected text {
-    fill: black;
+    fill: blue;
 }
 
 .graph .border {
@@ -347,8 +347,35 @@ text {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] label */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: black;
+}
+
+.iem_fg {
+    fill: black;
+}
+
+.iem_bg {
+    fill: #fcfcfc;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: black;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
+.iemgui:not(.mycanvas) .iemgui_label_selected {
     fill: blue;
 }
 
diff --git a/pd/nw/css/vanilla_inverted.css b/pd/nw/css/vanilla_inverted.css
index e4400e5ea..faafae11a 100644
--- a/pd/nw/css/vanilla_inverted.css
+++ b/pd/nw/css/vanilla_inverted.css
@@ -309,7 +309,7 @@ text {
 
 /* text inside selected objects */
 :not(.gop).selected text {
-    fill: white;
+    fill: yellow;
 }
 
 .graph .border {
@@ -364,9 +364,36 @@ text {
     stroke-width: 1;
 }
 
+/* default label, foreground, and background colors for iemguis.
+   These classes get set only if the colors sent from the backend
+   are the black or white default colors for the widget.
+
+   By using the class we allow iemguis with default colors to inherit
+   from CSS. However, if the user changes these colors then the tag
+   is removed and the given SVG fill/stroke attribute applies. */
+
+    /* special case for [cnv] label */
+.iemgui:not(.mycanvas) .iem_label {
+    fill: white;
+}
+
+.iem_fg {
+    fill: white;
+}
+
+.iem_bg {
+    fill: #030303;
+}
+
+/* special case for inner strokes that should match the border-- things like
+   [bng] circle stroke, etc. */
+.iem_stroke {
+    stroke: white;
+}
+
 /* text label for an iemgui */
-.iemgui_label_selected {
-    fill: blue;
+.iemgui:not(.mycanvas) .iemgui_label_selected {
+    fill: yellow;
 }
 
 /* test of xlet hover animation... this should 
@@ -416,12 +443,6 @@ text {
     color: white;
     background-color: black;
     border:1px solid white;
-}
-
-/* Dialog to ask to save the patch before quitting */
-#save_before_quit {
-    background-color: #f3f3f3;
-    border:1px solid #f3f3f3;
     padding: 12px;
     /* margin: 12px; */
     /*box-shadow: 7px 7px 5px grey;*/
diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index 367550ee2..c1adc561e 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -1445,10 +1445,47 @@ function create_svg_lock(cid) {
 // the same grid with a lower opacity. That way the edit mode is always
 // visually distinct from run mode.
 var create_editmode_bg = function(cid, svg_elem) {
-    var data, cell_data_str, opacity_str, grid, size, pos;
+    var data, cell_data_str, opacity_str, grid, size, pos,
+        cc, // cell color
+        gc; // grid color
     grid = showgrid[cid];
     size = gridsize[cid];
     pos = get_grid_coords(cid, svg_elem);
+
+        // Annoying crap because SVG img data can't
+        // call into an external style sheet...
+    switch(skin.get()) {
+        case "default":
+        case "footgun":
+        case "vanilla":
+        case "extended":
+        case "solarized":
+            cc = "#ddd";
+            gc = "#bbb";
+            break;
+        case "inverted":
+        case "vanilla_inverted":
+        case "extended_inverted":
+            cc = "#222";
+            gc = "#444";
+            break;
+        case "c64":
+            cc = "#5347b5";
+            gc = "#6458c6";
+            break;
+        case "strongbad":
+            cc = "#222";
+            gc = "#333";
+            break;
+        case "subdued":
+            cc = "#bdc9bd";
+            gc = "#a6c1a6";
+            break;
+        case "solarized_inverted":
+            cc = "#444";
+            gc = "#555";
+            break;
+    }
     // if snap-to-grid isn't turned on, just use cell size of 10 and make the
     // grid partially transparent
     size = grid ? size : 10;
@@ -1461,13 +1498,13 @@ var create_editmode_bg = function(cid, svg_elem) {
               '<defs>',
                 '<pattern id="cell" patternUnits="userSpaceOnUse" ',
                          'width="', size, '" height="', size, '">',
-                  '<path fill="none" stroke="#ddd" stroke-width="1" ',
+                  '<path fill="none" stroke="', cc, '" stroke-width="1" ',
                         'd=', cell_data_str,'/>',
                 '</pattern>',
                 '<pattern id="grid" patternUnits="userSpaceOnUse" ',
                     'width="100" height="100" x="', pos.x, '" y="', pos.y, '">',
                   '<rect width="500" height="500" fill="url(#cell)" />',
-                  '<path fill="none" stroke="#bbb" stroke-width="1" ',
+                  '<path fill="none" stroke="', gc, '" stroke-width="1" ',
                         'd="M 500 0 L 0 0 0 500"/>',
                 '</pattern>',
               '</defs>',
@@ -3293,18 +3330,22 @@ function gui_bng_new(cid, tag, cx, cy, radius) {
             r: radius,
             "shape-rendering": "auto",
             fill: "none",
-            stroke: "black",
             "stroke-width": 1,
             id: tag + "button"
         });
+            // For some reason the user was never allowed to change the color
+            // of the circle stroke. So we just set the color in a way that
+            // guarantees we will inherit the default iemgui stroke color
+            // as defined in the current GUI preset.
+        iemgui_set_color(circle, "stroke", "#000000");
         frag.appendChild(circle);
         return frag;
     });
 }
 
 function gui_bng_button_color(cid, tag, color) {
-    gui(cid).get_elem(tag + "button", {
-        fill: color
+    gui(cid).get_elem(tag + "button", function(e) {
+        iemgui_set_color(e, "fg", color);
     });
 }
 
@@ -3315,6 +3356,9 @@ function gui_bng_configure(cid, tag, color, cx, cy, r) {
         r: r,
         fill: color
     });
+    gui(cid).get_elem(tag + "button", function(e) {
+        iemgui_set_color(e, "fg", color);
+    });
 }
 
 function gui_toggle_new(cid, tag, color, width, state, p1,p2,p3,p4,p5,p6,p7,p8,basex,basey) {
@@ -3325,7 +3369,6 @@ function gui_toggle_new(cid, tag, color, width, state, p1,p2,p3,p4,p5,p6,p7,p8,b
         ].join(" ");
         var cross1 = create_item(cid, "polyline", {
             points: points,
-            stroke: color,
             fill: "none",
             id: tag + "cross1",
             display: state ? "inline" : "none",
@@ -3342,6 +3385,8 @@ function gui_toggle_new(cid, tag, color, width, state, p1,p2,p3,p4,p5,p6,p7,p8,b
             display: state ? "inline" : "none",
             "stroke-width": width
         });
+        iemgui_set_color(cross1, "stroke", color);
+        iemgui_set_color(cross2, "stroke", color);
         frag.appendChild(cross1);
         frag.appendChild(cross2);
         return frag;
@@ -3369,14 +3414,14 @@ function gui_toggle_resize_cross(cid,tag,w,p1,p2,p3,p4,p5,p6,p7,p8,basex,basey)
 function gui_toggle_update(cid, tag, state, color) {
     var disp = !!state ? "inline" : "none";
     gui(cid)
-    .get_elem(tag + "cross1", {
-        display: disp,
-        stroke: color
-    })
-    .get_elem(tag + "cross2", {
-        display: disp,
-        stroke: color
+    .get_elem(tag + "cross1", function(e) {
+        iemgui_set_color(e, "stroke", color);
+        configure_item(e, { display: disp });
     })
+    .get_elem(tag + "cross2", function(e) {
+        iemgui_set_color(e, "stroke", color);
+        configure_item(e, { display: disp });
+    });
 }
 
 function numbox_data_string_frame(w, h) {
@@ -3405,21 +3450,21 @@ function gui_numbox_new(cid, tag, color, x, y, w, h, drawstyle, is_toplevel) {
         var g = gui_gobj_new(cid, tag, "iemgui", x, y, is_toplevel);
         var border = create_item(cid, "path", {
             d: numbox_data_string_frame(w, h),
-            fill: color,
-            stroke: "black",
             "stroke-width": (drawstyle < 2 ? 1 : 0),
             id: (tag + "border"),
             "class": "border"
         });
+        iemgui_set_color(border, "stroke", "#000000");
+        iemgui_set_color(border, "bg", color);
         g.appendChild(border);
         var triangle = create_item(cid, "path", {
             d: numbox_data_string_triangle(w, h),
-            fill: color,
-            stroke: "black",
+            fill: "none",
             "stroke-width": (drawstyle == 0 || drawstyle ==  2 ? 1 : 0),
             id: (tag + "triangle"),
             "class": "border"
         });
+        iemgui_set_color(triangle, "stroke", "#000000");
         g.appendChild(triangle);
     });
 }
@@ -3445,24 +3490,21 @@ function gui_numbox_draw_text(cid,tag,text,font_size,color,xpos,ypos,basex,basey
                         (xpos - basex) + "," +
                         ((ypos - basey + (ypos - basey) * 0.5)|0) + ")",
             "font-size": font_size,
-            fill: color,
             id: tag + "text"
         }),
         text_node = w.document.createTextNode(text);
+        iemgui_set_color(svg_text, "fg", color);
         svg_text.appendChild(text_node);
         frag.appendChild(svg_text);
         return frag;
     });
 }
 
-function gui_numbox_update(cid, tag, fcolor, bgcolor, num_font_size, font_name, font_size, font_weight) {
+function gui_numbox_update(cid, tag, fgcolor, bgcolor, num_font_size, font_name, font_size, font_weight) {
     gui(cid)
-    .get_elem(tag + "border", {
-        fill: bgcolor
-    })
-    .get_elem(tag + "text", {
-        fill: fcolor,
-        "font-size": num_font_size
+    .get_elem(tag + "text", function(e) {
+        configure_item(e, { "font-size": num_font_size });
+        iemgui_set_color(e, "fg", fgcolor);
     })
     // label may or may not exist, but that's covered by the API
     .get_elem(tag + "label", function() {
@@ -3484,11 +3526,11 @@ function gui_slider_new(cid, tag, color, p1, p2, p3, p4, basex, basey) {
             y1: p2 - basey,
             x2: p3 - basex,
             y2: p4 - basey,
-            stroke: color,
             "stroke-width": 3,
             fill: "none",
             id: tag + "indicator"
         });
+        iemgui_set_color(indicator, "stroke", color);
         frag.appendChild(indicator);
         return frag;
     });
@@ -3504,8 +3546,8 @@ function gui_slider_update(cid, tag, p1, p2, p3, p4, basex, basey) {
 }
 
 function gui_slider_indicator_color(cid, tag, color) {
-    gui(cid).get_elem(tag + "indicator", {
-        stroke: color
+    gui(cid).get_elem(tag + "indicator", function(e) {
+        iemgui_set_color(e, "stroke", color);
     });
 }
 
@@ -3517,12 +3559,11 @@ function gui_radio_new(cid, tag, p1, p2, p3, p4, i, basex, basey) {
             y1: p2 - basey,
             x2: p3 - basex,
             y2: p4 - basey,
-            // stroke is just black for now
-            stroke: "black",
             "stroke-width": 1,
             fill: "none",
             id: tag + "cell_" + i
         });
+        iemgui_set_color(cell, "stroke", "#000000");
         frag.appendChild(cell);
         return frag;
     });
@@ -3536,11 +3577,10 @@ function gui_radio_create_buttons(cid,tag,color,p1,p2,p3,p4,basex,basey,i,state)
             y: p2 - basey,
             width: p3 - p1,
             height: p4 - p2,
-            stroke: color,
-            fill: color,
             id: tag + "button_" + i,
             display: state ? "inline" : "none"
         });
+        iemgui_set_color(b, "fg", color);
         frag.appendChild(b);
         return frag;
     });
@@ -3572,10 +3612,9 @@ function gui_radio_update(cid, tag, fgcolor, prev, next) {
     .get_elem(tag + "button_" + prev, {
         display: "none"
     })
-    .get_elem(tag + "button_" + next, {
-        display: "inline",
-        fill: fgcolor,
-        stroke: fgcolor
+    .get_elem(tag + "button_" + next, function(e) {
+        configure_item(e, { display: "inline" });
+        iemgui_set_color(e, "fg", fgcolor);
     });
 }
 
@@ -3591,6 +3630,7 @@ function gui_vumeter_draw_text(cid,tag,color,xpos,ypos,text,index,basex,basey, f
             id: tag + "text_" + index
         }),
         text_node = w.document.createTextNode(text);
+        iemgui_set_color(svg_text, "label", color);
         svg_text.appendChild(text_node);
         frag.appendChild(svg_text);
         return frag;
@@ -3607,8 +3647,8 @@ function gui_vumeter_draw_text(cid,tag,color,xpos,ypos,text,index,basex,basey, f
 // To get on to other work we just parrot the insanity here,
 // and silently ignore calls to update non-existent text.
 function gui_vumeter_update_text(cid, tag, text, font, selected, color, i) {
-    gui(cid).get_elem(tag + "text_" + i, {
-        fill: color
+    gui(cid).get_elem(tag + "text_" + i, function(e) {
+        iemgui_set_color(e, "label", color);
     });
 }
 
@@ -3734,10 +3774,41 @@ function gui_vumeter_update_peak(cid,tag,color,p1,p2,p3,p4,basex,basey) {
     });
 }
 
+    // set a color for an iemgui. We go through contortions to compare the
+    // color to a stated "default_color." If it's the same, we set a CSS
+    // class so the element can inherit from the GUI preset. If not, we just
+    // set the SVG fill attribute. If our CSS class is set it will override
+    // the SVG attribute because CSS props *always* override SVG attrs.
+function iemgui_set_color(elem, which, color) {
+    var obj = {},
+        default_color,
+        color_class,
+        prop;
+    // default fg, stroke, and label color for iemguis are all black.
+    // the default background for all iemguis (except vumeter) is #fcfcfc.
+    // No idea why it's not "#ffffff" but that's what we're stuck with.
+    default_color = (which === "bg" ? "#fcfcfc" : "#000000");
+
+    // For custom colors we set the stroke attr for "stroke", and we use the
+    // fill attr for everything else.
+    prop = (which == "stroke" ? "stroke" : "fill");
+
+    // our class is just `which` prepended with iem_
+    color_class = "iem_" + which;
+
+    if (color === default_color) {
+        elem.classList.add(color_class);
+    } else {
+        elem.classList.remove(color_class);
+        obj[prop] = color;
+        configure_item(elem, obj);
+    }
+}
+
 function gui_iemgui_base_color(cid, tag, color) {
     gui(cid).get_gobj(tag)
-    .q(".border", {
-        fill: color
+    .q(".border", function(e) {
+        iemgui_set_color(e, "bg", color);
     });
 }
 
@@ -3805,7 +3876,6 @@ function gui_iemgui_label_new(cid, tag, x, y, color, text, fontname, fontweight,
             // for some reason the font looks bold in Pd-Vanilla-- not sure why
             "font-weight": fontweight,
             "font-size": fontsize + "px",
-            fill: color,
             // Iemgui labels are anchored "w" (left-aligned to non-tclers).
             // For no good reason, they are also centered vertically, unlike
             // object box text. Since svg text uses the baseline as a reference
@@ -3820,6 +3890,8 @@ function gui_iemgui_label_new(cid, tag, x, y, color, text, fontname, fontweight,
                 iemgui_font_height(fontname, fontsize) / 2 + ")",
             id: tag + "label"
         });
+            // now set the color
+        iemgui_set_color(svg_text, "label", color);
         var text_node = w.document.createTextNode(text);
         svg_text.appendChild(text_node);
         frag.appendChild(svg_text);
@@ -3841,14 +3913,8 @@ function gui_iemgui_label_coords(cid, tag, x, y) {
 }
 
 function gui_iemgui_label_color(cid, tag, color) {
-    gui(cid).get_elem(tag + "label", {
-        fill: color
-    });
-}
-
-function gui_iemgui_label_color(cid, tag, color) {
-    gui(cid).get_elem(tag + "label", {
-        fill: color
+    gui(cid).get_elem(tag + "label", function(e) {
+        iemgui_set_color(e, "label", color);
     });
 }
 
@@ -3971,6 +4037,14 @@ function gui_iemgui_label_displace_drag_handle(cid, tag, dx, dy) {
 }
 
 function gui_mycanvas_new(cid,tag,color,x1,y1,x2_vis,y2_vis,x2,y2) {
+    gui(cid).get_gobj(tag, {
+        // ag: We need to be able to distinguish this case easily in theme
+        // files, in order to suppress the default label coloring for
+        // iemguis. I'm not sure whether this is the best way to do this, but
+        // if we don't want to change the existing JS API, this seems to be
+        // the only call where we can be certain that a gobj is a canvas object.
+        class: "iemgui mycanvas"
+    });
     gui(cid).get_gobj(tag)
     .append(function(frag) {
         var rect_vis, rect, g;
@@ -6296,10 +6370,13 @@ var skin = exports.skin = (function () {
             .setAttribute("href", dir + preset + ".css");
     }
     return {
-        get: function () {
+        debug: function () {
             post("getting preset: " + dir + preset + ".css");
             return dir + preset + ".css";
         },
+        get: function() {
+            return preset;
+	},
         set: function (name) {
             // ag: if the preset doesn't exist (e.g., user preset that
             // has disappeared), just stick to the default
diff --git a/pd/src/g_bang.c b/pd/src/g_bang.c
index c32084841..d67754666 100644
--- a/pd/src/g_bang.c
+++ b/pd/src/g_bang.c
@@ -26,7 +26,10 @@ void bng_draw_update(t_gobj *xgobj, t_glist *glist)
 {
     t_bng *x = (t_bng *)xgobj;
     char cbuf[8];
-    sprintf(cbuf, "#%6.6x", x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol);
+    if (x->x_flashed)
+        sprintf(cbuf, "#%6.6x", x->x_gui.x_fcol);
+    else
+        sprintf(cbuf, "none");
     if (x->x_gui.x_changed != x->x_flashed && glist_isvisible(glist))
     {
         gui_vmess("gui_bng_button_color", "xxs",
@@ -88,7 +91,10 @@ void bng_draw_config(t_bng* x, t_glist* glist)
 {
     t_canvas *canvas=glist_getcanvas(glist);
     char cbuf[8];
-    sprintf(cbuf, "#%6.6x", x->x_flashed ? x->x_gui.x_fcol : x->x_gui.x_bcol);
+    if (x->x_flashed)
+        sprintf(cbuf, "#%6.6x", x->x_gui.x_fcol);
+    else
+        sprintf(cbuf, "none");
     iemgui_base_draw_config(&x->x_gui);
     gui_vmess("gui_bng_button_color", "xxs",
         canvas,
diff --git a/pd/src/g_vumeter.c b/pd/src/g_vumeter.c
index 7b6f46ecd..8b468123a 100644
--- a/pd/src/g_vumeter.c
+++ b/pd/src/g_vumeter.c
@@ -244,7 +244,7 @@ static void vu_draw_config(t_vu* x, t_glist* glist)
         {
             int isselected = x->x_gui.x_selected == canvas &&
                 x->x_gui.x_glist == canvas && x->x_scale;
-            gui_vmess("gui_vumeter_update_text", "xxssixi",
+            gui_vmess("gui_vumeter_update_text", "xxssisi",
                 canvas, x, iemgui_vu_scale_str[i/4],
                 iemgui_font(&x->x_gui), isselected, cbuf, i);
         }
-- 
GitLab