Skip to content

Commit

Permalink
Expose GUI theme (#1187)
Browse files Browse the repository at this point in the history
* Make GUI colors and Font configurable

- Added struct to hold values
- Extracted default values to struct
- Added try/catch block when opening font in ShowMessage, in case the font isn't found

* Save and Parse GUI theme options

- Use amiberry.conf for storing and parsing values
- Better handling of the default values
  • Loading branch information
midwan authored Nov 25, 2023
1 parent 77b9997 commit 9c1cfcf
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 14 deletions.
17 changes: 17 additions & 0 deletions src/include/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "uae/types.h"

#include "traps.h"
#include "guisan/color.hpp"

#define UAEMAJOR 5
#define UAEMINOR 6
Expand Down Expand Up @@ -1190,6 +1191,16 @@ struct amiberry_hotkey
hotkey_modifiers modifiers;
};

struct amiberry_gui_theme
{
gcn::Color base_color;
gcn::Color selector_inactive;
gcn::Color selector_active;
gcn::Color textbox_background;
std::string font_name;
int font_size;
};

struct amiberry_options
{
bool quickstart_start = true;
Expand Down Expand Up @@ -1249,6 +1260,12 @@ struct amiberry_options
char default_vkbd_style[128] = "Original";
int default_vkbd_transparency;
char default_vkbd_toggle[128] = "guide";
char gui_theme_font_name[128] = "AmigaTopaz.ttf";
int gui_theme_font_size = 15;
char gui_theme_base_color[128] = "170, 170, 170";
char gui_theme_selector_inactive[128] = "170, 170, 170";
char gui_theme_selector_active[128] = "103, 136, 187";
char gui_theme_textbox_background[128] = "220, 220, 220";
};

extern struct amiberry_options amiberry_options;
Expand Down
148 changes: 147 additions & 1 deletion src/osdep/amiberry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ int relativepaths = 0;
int saveimageoriginalpath = 0;

struct amiberry_options amiberry_options = {};
struct amiberry_gui_theme gui_theme = {};
amiberry_hotkey enter_gui_key;
SDL_GameControllerButton enter_gui_button;
amiberry_hotkey quit_key;
Expand Down Expand Up @@ -134,6 +135,17 @@ std::string get_sdl2_version_string()
return sdl_compiled.str();
}

std::vector<int> parse_color_string(std::string input)
{
std::vector<int> result;
std::stringstream ss(input);
std::string token;
while (std::getline(ss, token, ',')) {
result.push_back(std::stoi(token));
}
return result;
}

amiberry_hotkey get_hotkey_from_config(std::string config_option)
{
amiberry_hotkey hotkey = {};
Expand Down Expand Up @@ -2085,6 +2097,110 @@ void target_default_options(struct uae_prefs* p, int type)
_tcscpy(p->vkbd_style, ""); // This will use the default theme.
p->vkbd_transparency = amiberry_options.default_vkbd_transparency;
_tcscpy(p->vkbd_toggle, amiberry_options.default_vkbd_toggle);

//
// GUI Theme section
//
// Font name
if (amiberry_options.gui_theme_font_name[0])
gui_theme.font_name = std::string(amiberry_options.gui_theme_font_name);
else
gui_theme.font_name = "AmigaTopaz.ttf";

// Font size
gui_theme.font_size = amiberry_options.gui_theme_font_size > 0 ? amiberry_options.gui_theme_font_size : 15;

// Base Color
if (amiberry_options.gui_theme_base_color[0])
{
// parse string as comma-separated numbers
std::vector<int> result = parse_color_string(amiberry_options.gui_theme_base_color);
if (result.size() == 3)
{
gui_theme.base_color = gcn::Color(result[0], result[1], result[2]);
}
else if (result.size() == 4)
{
gui_theme.base_color = gcn::Color(result[0], result[1], result[2], result[3]);
}
else
{
gui_theme.base_color = gcn::Color(170, 170, 170);
}
}
else
{
gui_theme.base_color = gcn::Color(170, 170, 170);
}

// Selector Inactive
if (amiberry_options.gui_theme_selector_inactive[0])
{
// parse string as comma-separated numbers
std::vector<int> result = parse_color_string(amiberry_options.gui_theme_selector_inactive);
if (result.size() == 3)
{
gui_theme.selector_inactive = gcn::Color(result[0], result[1], result[2]);
}
else if (result.size() == 4)
{
gui_theme.selector_inactive = gcn::Color(result[0], result[1], result[2], result[3]);
}
else
{
gui_theme.selector_inactive = gcn::Color(170, 170, 170);
}
}
else
{
gui_theme.selector_inactive = gcn::Color(170, 170, 170);
}

// Selector Active
if (amiberry_options.gui_theme_selector_active[0])
{
// parse string as comma-separated numbers
std::vector<int> result = parse_color_string(amiberry_options.gui_theme_selector_active);
if (result.size() == 3)
{
gui_theme.selector_active = gcn::Color(result[0], result[1], result[2]);
}
else if (result.size() == 4)
{
gui_theme.selector_active = gcn::Color(result[0], result[1], result[2], result[3]);
}
else
{
gui_theme.selector_active = gcn::Color(103, 136, 187);
}
}
else
{
gui_theme.selector_active = gcn::Color(103, 136, 187);
}

// Textbox Background
if (amiberry_options.gui_theme_textbox_background[0])
{
// parse string as comma-separated numbers
std::vector<int> result = parse_color_string(amiberry_options.gui_theme_textbox_background);
if (result.size() == 3)
{
gui_theme.textbox_background = gcn::Color(result[0], result[1], result[2]);
}
else if (result.size() == 4)
{
gui_theme.textbox_background = gcn::Color(result[0], result[1], result[2], result[3]);
}
else
{
gui_theme.textbox_background = gcn::Color(220, 220, 220);
}
}
else
{
gui_theme.textbox_background = gcn::Color(220, 220, 220);
}
}

static const TCHAR* scsimode[] = { _T("SCSIEMU"), _T("SPTI"), _T("SPTI+SCSISCAN"), NULL };
Expand Down Expand Up @@ -3013,6 +3129,30 @@ void save_amiberry_settings(void)
snprintf(buffer, MAX_DPATH, "default_vkbd_toggle=%s\n", amiberry_options.default_vkbd_toggle);
fputs(buffer, f);

// GUI Theme: Font name
snprintf(buffer, MAX_DPATH, "gui_theme_font_name=%s\n", amiberry_options.gui_theme_font_name);
fputs(buffer, f);

// GUI Theme: Font size
snprintf(buffer, MAX_DPATH, "gui_theme_font_size=%d\n", amiberry_options.gui_theme_font_size);
fputs(buffer, f);

// GUI Theme: Base color
snprintf(buffer, MAX_DPATH, "gui_theme_base_color=%s\n", amiberry_options.gui_theme_base_color);
fputs(buffer, f);

// GUI Theme: Selector Inactive color
snprintf(buffer, MAX_DPATH, "gui_theme_selector_inactive=%s\n", amiberry_options.gui_theme_selector_inactive);
fputs(buffer, f);

// GUI Theme: Selector Active color
snprintf(buffer, MAX_DPATH, "gui_theme_selector_active=%s\n", amiberry_options.gui_theme_selector_active);
fputs(buffer, f);

// GUI Theme: Textbox Background color
snprintf(buffer, MAX_DPATH, "gui_theme_textbox_background=%s\n", amiberry_options.gui_theme_textbox_background);
fputs(buffer, f);

// Paths
snprintf(buffer, MAX_DPATH, "path=%s\n", current_dir);
fputs(buffer, f);
Expand Down Expand Up @@ -3205,7 +3345,7 @@ static int parse_amiberry_settings_line(const char *path, char *linea)
ret |= cfgfile_string(option, value, "inputrecordings_dir", input_dir, sizeof input_dir);
ret |= cfgfile_string(option, value, "screenshot_dir", screenshot_dir, sizeof screenshot_dir);
ret |= cfgfile_string(option, value, "nvram_dir", nvram_dir, sizeof nvram_dir);
// NOTE: amiberry_config is a "read only", ie. it's not written in
// NOTE: amiberry_config is a "read only", i.e. it's not written in
// save_amiberry_settings(). It's purpose is to provide -o amiberry_config=path
// command line option.
ret |= cfgfile_string(option, value, "amiberry_config", amiberry_conf_file, sizeof amiberry_conf_file);
Expand Down Expand Up @@ -3266,6 +3406,12 @@ static int parse_amiberry_settings_line(const char *path, char *linea)
ret |= cfgfile_string(option, value, "default_vkbd_style", amiberry_options.default_vkbd_style, sizeof amiberry_options.default_vkbd_style);
ret |= cfgfile_intval(option, value, "default_vkbd_transparency", &amiberry_options.default_vkbd_transparency, 1);
ret |= cfgfile_string(option, value, "default_vkbd_toggle", amiberry_options.default_vkbd_toggle, sizeof amiberry_options.default_vkbd_toggle);
ret |= cfgfile_string(option, value, "gui_theme_font_name", amiberry_options.gui_theme_font_name, sizeof amiberry_options.gui_theme_font_name);
ret |= cfgfile_intval(option, value, "gui_theme_font_size", &amiberry_options.gui_theme_font_size, 1);
ret |= cfgfile_string(option, value, "gui_theme_base_color", amiberry_options.gui_theme_base_color, sizeof amiberry_options.gui_theme_base_color);
ret |= cfgfile_string(option, value, "gui_theme_selector_inactive", amiberry_options.gui_theme_selector_inactive, sizeof amiberry_options.gui_theme_selector_inactive);
ret |= cfgfile_string(option, value, "gui_theme_selector_active", amiberry_options.gui_theme_selector_active, sizeof amiberry_options.gui_theme_selector_active);
ret |= cfgfile_string(option, value, "gui_theme_textbox_background", amiberry_options.gui_theme_textbox_background, sizeof amiberry_options.gui_theme_textbox_background);
}
return ret;
}
Expand Down
22 changes: 17 additions & 5 deletions src/osdep/gui/ShowMessage.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>

#include <guisan.hpp>
#include <SDL_ttf.h>
Expand Down Expand Up @@ -167,20 +169,30 @@ static void InitShowMessage(const std::string& message)
{
gui_top = new gcn::Container();
gui_top->setDimension(gcn::Rectangle(0, 0, GUI_WIDTH, GUI_HEIGHT));
gui_baseCol = gcn::Color(170, 170, 170);
gui_baseCol = gui_theme.base_color;
gui_top->setBaseColor(gui_baseCol);
uae_gui->setTop(gui_top);
}
if (gui_font == nullptr)
{
TTF_Init();
#ifdef USE_OPENGL
gui_font = new gcn::ImageFont(prefix_with_data_path("rpgfont.png"), " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"");

try
{
#ifdef USE_OPENGL
gui_font = new gcn::ImageFont(prefix_with_data_path("rpgfont.png"), " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"");
#else
gui_font = new gcn::SDLTrueTypeFont(prefix_with_data_path("AmigaTopaz.ttf"), 15);
gui_font->setAntiAlias(false);
gui_font = new gcn::SDLTrueTypeFont(prefix_with_data_path(gui_theme.font_name), gui_theme.font_size);
gui_font->setAntiAlias(false);
#endif
}
catch (exception& ex)
{
cout << ex.what() << '\n';
write_log("An error occurred while trying to open the GUI font! Exception: %s\n", ex.what());
abort();
}

gcn::Widget::setGlobalFont(gui_font);
}

Expand Down
5 changes: 5 additions & 0 deletions src/osdep/gui/gui_handling.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,14 @@ extern bool gui_running;
extern ConfigCategory categories[];
extern gcn::Gui* uae_gui;
extern gcn::Container* gui_top;

// GUI Colors
extern amiberry_gui_theme gui_theme;
extern gcn::Color gui_baseCol;
extern gcn::Color colTextboxBackground;
extern gcn::Color colSelectorInactive;
extern gcn::Color colSelectorActive;

extern gcn::SDLInput* gui_input;
extern SDL_Surface* gui_screen;
extern SDL_Joystick* gui_joystick;
Expand Down
16 changes: 8 additions & 8 deletions src/osdep/gui/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,12 @@ gcn::Container* gui_top;
gcn::Container* selectors;
gcn::ScrollArea* selectorsScrollArea;

// GUI Colors
gcn::Color gui_baseCol;
gcn::Color colTextboxBackground;
gcn::Color colSelectorInactive;
gcn::Color colSelectorActive;

gcn::FocusHandler* focusHdl;
gcn::Widget* activeWidget;

Expand Down Expand Up @@ -1238,10 +1240,10 @@ void gui_widgets_init()
//-------------------------------------------------
// Define base colors
//-------------------------------------------------
gui_baseCol = gcn::Color(170, 170, 170);
colSelectorInactive = gcn::Color(170, 170, 170);
colSelectorActive = gcn::Color(103, 136, 187);
colTextboxBackground = gcn::Color(220, 220, 220);
gui_baseCol = gui_theme.base_color;
colSelectorInactive = gui_theme.selector_inactive;
colSelectorActive = gui_theme.selector_active;
colTextboxBackground = gui_theme.textbox_background;

//-------------------------------------------------
// Create container for main page
Expand All @@ -1263,7 +1265,8 @@ void gui_widgets_init()
#ifdef USE_OPENGL
gui_font = new gcn::ImageFont(prefix_with_data_path("rpgfont.png"), " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"");
#else
gui_font = new gcn::SDLTrueTypeFont(prefix_with_data_path("AmigaTopaz.ttf"), 15);
gui_font = new gcn::SDLTrueTypeFont(prefix_with_data_path(gui_theme.font_name), gui_theme.font_size);
gui_font->setAntiAlias(false);
#endif
}
catch (exception& ex)
Expand All @@ -1274,9 +1277,6 @@ void gui_widgets_init()
}

gcn::Widget::setGlobalFont(gui_font);
#ifndef USE_OPENGL
gui_font->setAntiAlias(false);
#endif

//--------------------------------------------------
// Create main buttons
Expand Down

3 comments on commit 9c1cfcf

@giantclambake
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The values are defined in amiberry.conf as ;

gui_theme_font_name=AmigaTopaz.ttf
gui_theme_font_size=15
gui_theme_base_color=170, 170, 170
gui_theme_selector_inactive=170, 170, 170
gui_theme_selector_active=103, 136, 187
gui_theme_textbox_background=220, 220, 220

When you start/quit amiberry, it modifies amiberry.conf and removes these lines.

This might be expected behavior at the moment ~ just reporting it in case that's not the case ;)

@midwan
Copy link
Collaborator Author

@midwan midwan commented on 9c1cfcf Nov 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the lines are not there in amiberry.conf, they will be saved when exiting with their default values.
If they are there already, they will be read and applied on startup.
They should not be removed in any scenario... How did you see that?

@giantclambake
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either my git pull was premature, or, I forgot to put the new binary inplace -- in any event, all good and working as expected.

Please sign in to comment.