Hello,
I just started getting into modules with Python.
I have a module called “UIThemeColors” I am importing into my main script.
This module takes an argument called “dark_mode”
dark_mode is set based on the Rhino document theme change and a custom toggle button.
In UIThemeColors, I have variables like “foreground_color”, “highlight_color” and these values get updated when the them changes.
So foreground_color will be charcoal for dark mode and white for light mode as an example.
This part seems to work fine ^
My question is, where is the best place to call this update so that I am dynamically updating the colors to be used throughout all my classes?
I have about 5 Eto.Forms.Drawable classes right now that are various forms of “buttons/toggles” and each of these need to have the colors updated when the theme changes.
Here’s the code of the UIThemeColors module:
#! python3
# UIThemeColors.py
import Rhino
import Eto.Drawing
# Determine if the current theme is dark mode
dark_mode = Rhino.Runtime.HostUtils.RunningInDarkMode
# Define color variables based on the theme
bg_color_light = Eto.Drawing.Color(10, 10, 10)
bg_color_dark = Eto.Drawing.Color(220, 220, 220)
mg_color_light = Eto.Drawing.Color(1, 1, 1)
mg_color_dark = Eto.Drawing.Color(240, 240, 240)
fg_color_light = Eto.Drawing.Color(1, 1, 1)
fg_color_dark = Eto.Drawing.Color(180, 180, 180)
b_color_light = Eto.Drawing.Color(40, 40, 40)
b_color_dark = Eto.Drawing.Color(240, 240, 240)
s_color_light = Eto.Drawing.Colors.LightGrey # Shadow Color To Replace Color Highlight When In Light Mode
s_color_dark = Eto.Drawing.Color(240, 240, 240)
e_color_light = Eto.Drawing.Color(20, 20, 20)
e_color_dark = Eto.Drawing.Color(250, 250, 250)
d_color_light = fg_color_light
d_color_dark = Eto.Drawing.Color(210, 210, 210)
def GetThemeColors(dark_mode):
if dark_mode:
# Define theme colors for dark mode
theme_colors = {
"bg_color": bg_color_dark,
"mg_color": mg_color_dark,
"fg_color": fg_color_dark,
"b_color": b_color_dark,
"s_color": s_color_dark,
"e_color": e_color_dark,
"d_color": d_color_dark,
"t_color": fg_color_light
}
else:
# Define theme colors for light mode
theme_colors = {
"bg_color": bg_color_light,
"mg_color": mg_color_light,
"fg_color": fg_color_light,
"b_color": b_color_light,
"s_color": s_color_light,
"e_color": e_color_light,
"d_color": d_color_light,
"t_color": fg_color_dark
}
return theme_colors
Here’s my import:
import UIThemeColors
Here’s the function at the start of the script:
# Determine if the current theme is dark mode
dark_mode = Rhino.Runtime.HostUtils.RunningInDarkMode
def GetCurrentThemeColors(dark_mode):
global theme_colors
# Dynamically fetch the current theme colors
theme_colors = UIThemeColors.GetThemeColors(dark_mode)
bg_color, mg_color, fg_color, b_color, s_color, e_color, d_color, t_color = (theme_colors[key] for key in ["bg_color", "mg_color", "fg_color", "b_color", "s_color", "e_color", "d_color", "t_color"])
# Rhino.RhinoApp.WriteLine("dark mode: " + str(dark_mode), str(theme_colors))
return bg_color, mg_color, fg_color, b_color, s_color, e_color, d_color, t_color
GetCurrentThemeColors(dark_mode)
bg_color, mg_color, fg_color, b_color, s_color, e_color, d_color, t_color = (theme_colors[key] for key in ["bg_color", "mg_color", "fg_color", "b_color", "s_color", "e_color", "d_color", "t_color"])
If I place this code in the OnPaint event of each class, it works as expected, the theme colors dynamically update.
def OnPaint(self, e):
# Get the current theme colors
bg_color, mg_color, fg_color, b_color, s_color, e_color, d_color, t_color = GetCurrentThemeColors(dark_mode)
try:
# rest of the code here
Is OnPaint really the best place to call this? I’ve tried so many other methods, classes, passing arguments, creating definitions that set the color variables as self. to be called within each custom button drawable class, etc. and for the life of me cannot get it to update dynamically unless I place the above code in my OnPaint def of each drawable button class.
Before I pulled the theme color code out into a module, I set the color variables like this at the beginning of my script before I declared any classes:
# Script Level Variables
dark_mode = Rhino.Runtime.HostUtils.RunningInDarkMode # Get Current Rhino Theme For Custom Dark Mode UI Functions On Script Initialization
bg_color_light = Eto.Drawing.Color(10, 10, 10)
bg_color_dark = Eto.Drawing.Color(220, 220, 220)
mg_color_light = Eto.Drawing.Color(1, 1, 1)
mg_color_dark = Eto.Drawing.Color(240, 240, 240)
fg_color_light = Eto.Drawing.Color(1, 1, 1)
fg_color_dark = Eto.Drawing.Color(180, 180, 180)
b_color_light = Eto.Drawing.Color(40, 40, 40)
b_color_dark = Eto.Drawing.Color(240, 240, 240)
s_color_light = Eto.Drawing.Colors.LightGrey # Shadow Color To Replace Color Highlight When In Light Mode
s_color_dark = Eto.Drawing.Color(240, 240, 240)
e_color_light = Eto.Drawing.Color(20, 20, 20)
e_color_dark = Eto.Drawing.Color(250, 250, 250)
d_color_light = fg_color_light
d_color_dark = Eto.Drawing.Color(210, 210, 210)
t_color_dark = fg_color_light
t_color_light = fg_color_dark
This worked perfectly fine because I could call these variables from any class as they are “script level”. I didn’t need any additional functions anywhere, no code applied within the OnPaint def of each class, etc. It just worked perfectly fine.
However, I want to set these colors in the UIThemeColors module so that I can reuse these colors across other UI scripts.
Classes, Modules, etc. are very new to me so I appreciate any guidance you can provide to me. I am stumped.
Please let me know if you need to see additional parts of the code.
Thank you all for your help!