Terminal: load themes from data and settings folders.

* Uses the same format as the Terminal settings file
* Adds an additional key, "Theme name", to settings for themes,
  which needs to be present for a theme to be loaded, else it
  will be skipped
* Loads themes from Terminal/Themes in the data and settings
  directories, searching data first, then settings second,
  allowing a theme to be tweaked by putting a copy in a
  settings folder

Change-Id: I8cadf98151459c1ae6098c38481b16eb3f2cf952
This commit is contained in:
Jessica Hamilton
2022-12-18 16:24:49 +13:00
parent 23cc5401d1
commit de2ada1f10
7 changed files with 181 additions and 252 deletions
+43 -43
View File
@@ -37,7 +37,6 @@
#define B_TRANSLATION_CONTEXT "Terminal AppearancePrefView"
// #pragma mark -
@@ -112,7 +111,7 @@ AppearancePrefView::AppearancePrefView(const char* name,
fEncodingField = new BMenuField(B_TRANSLATE("Encoding:"), encodingMenu);
BPopUpMenu* schemesPopUp = _MakeColorSchemeMenu(MSG_COLOR_SCHEME_CHANGED,
gPredefinedColorSchemes, gPredefinedColorSchemes[0]);
gColorSchemes);
fColorSchemeField = new BMenuField(B_TRANSLATE("Color scheme:"),
schemesPopUp);
@@ -453,38 +452,17 @@ AppearancePrefView::_SetCurrentColorScheme()
{
PrefHandler* pref = PrefHandler::Default();
gCustomColorScheme.text_fore_color = pref->getRGB(PREF_TEXT_FORE_COLOR);
gCustomColorScheme.text_back_color = pref->getRGB(PREF_TEXT_BACK_COLOR);
gCustomColorScheme.select_fore_color = pref->getRGB(PREF_SELECT_FORE_COLOR);
gCustomColorScheme.select_back_color = pref->getRGB(PREF_SELECT_BACK_COLOR);
gCustomColorScheme.cursor_fore_color = pref->getRGB(PREF_CURSOR_FORE_COLOR);
gCustomColorScheme.cursor_back_color = pref->getRGB(PREF_CURSOR_BACK_COLOR);
gCustomColorScheme.ansi_colors.black = pref->getRGB(PREF_ANSI_BLACK_COLOR);
gCustomColorScheme.ansi_colors.red = pref->getRGB(PREF_ANSI_RED_COLOR);
gCustomColorScheme.ansi_colors.green = pref->getRGB(PREF_ANSI_GREEN_COLOR);
gCustomColorScheme.ansi_colors.yellow = pref->getRGB(PREF_ANSI_YELLOW_COLOR);
gCustomColorScheme.ansi_colors.blue = pref->getRGB(PREF_ANSI_BLUE_COLOR);
gCustomColorScheme.ansi_colors.magenta =
pref->getRGB(PREF_ANSI_MAGENTA_COLOR);
gCustomColorScheme.ansi_colors.cyan = pref->getRGB(PREF_ANSI_CYAN_COLOR);
gCustomColorScheme.ansi_colors.white = pref->getRGB(PREF_ANSI_WHITE_COLOR);
gCustomColorScheme.ansi_colors_h.black = pref->getRGB(PREF_ANSI_BLACK_HCOLOR);
gCustomColorScheme.ansi_colors_h.red = pref->getRGB(PREF_ANSI_RED_HCOLOR);
gCustomColorScheme.ansi_colors_h.green = pref->getRGB(PREF_ANSI_GREEN_HCOLOR);
gCustomColorScheme.ansi_colors_h.yellow =
pref->getRGB(PREF_ANSI_YELLOW_HCOLOR);
gCustomColorScheme.ansi_colors_h.blue = pref->getRGB(PREF_ANSI_BLUE_HCOLOR);
gCustomColorScheme.ansi_colors_h.magenta =
pref->getRGB(PREF_ANSI_MAGENTA_HCOLOR);
gCustomColorScheme.ansi_colors_h.cyan = pref->getRGB(PREF_ANSI_CYAN_HCOLOR);
gCustomColorScheme.ansi_colors_h.white = pref->getRGB(PREF_ANSI_WHITE_HCOLOR);
pref->LoadColorScheme(&gCustomColorScheme);
const char* currentSchemeName = NULL;
for (const color_scheme** schemes = gPredefinedColorSchemes;
*schemes != NULL; schemes++) {
if (gCustomColorScheme == **schemes) {
currentSchemeName = (*schemes)->name;
int32 i = 0;
while (i < gColorSchemes->CountItems()) {
const color_scheme *item = gColorSchemes->ItemAt(i);
i++;
if (gCustomColorScheme == *item) {
currentSchemeName = item->name;
break;
}
}
@@ -655,25 +633,47 @@ AppearancePrefView::_MakeMenu(uint32 msg, const char** items,
}
/*static*/ void
AppearancePrefView::_MakeColorSchemeMenuItem(uint32 msg, const color_scheme *item,
BPopUpMenu *menu)
{
if (item == NULL)
return;
BMessage* message = new BMessage(msg);
message->AddPointer("color_scheme", (const void*)item);
menu->AddItem(new BMenuItem(item->name, message));
}
/*static*/ BPopUpMenu*
AppearancePrefView::_MakeColorSchemeMenu(uint32 msg, const color_scheme** items,
const color_scheme* defaultItemName)
AppearancePrefView::_MakeColorSchemeMenu(uint32 msg, BObjectList<const color_scheme> *items)
{
BPopUpMenu* menu = new BPopUpMenu("");
int32 i = 0;
while (*items) {
if (strcmp((*items)->name, "") == 0)
menu->AddSeparatorItem();
else {
BMessage* message = new BMessage(msg);
message->AddPointer("color_scheme", (const void*)*items);
menu->AddItem(new BMenuItem((*items)->name, message));
}
FindColorSchemeByName comparator("Default");
items++;
const color_scheme* defaultItem = items->FindIf(comparator);
_MakeColorSchemeMenuItem(msg, defaultItem, menu);
int32 i = 0;
while (i < items->CountItems()) {
const color_scheme *item = items->ItemAt(i);
i++;
if (strcmp(item->name, "") == 0)
menu->AddSeparatorItem();
else if (item == defaultItem)
continue;
else
_MakeColorSchemeMenuItem(msg, item, menu);
}
// Add the custom item at the very end
menu->AddSeparatorItem();
_MakeColorSchemeMenuItem(msg, &gCustomColorScheme, menu);
return menu;
}
+5 -2
View File
@@ -10,6 +10,7 @@
#include <GroupView.h>
#include <Messenger.h>
#include <ObjectList.h>
#include <String.h>
@@ -71,8 +72,10 @@ private:
const char* defaultItem);
static BPopUpMenu* _MakeColorSchemeMenu(uint32 msg,
const color_scheme** schemes,
const color_scheme* defaultItemName);
BObjectList<const color_scheme> *items);
static void _MakeColorSchemeMenuItem(uint32 msg,
const color_scheme *item,
BPopUpMenu* menu);
void _MarkSelectedFont(const char* family,
const char* style, const char* size);
+2 -205
View File
@@ -23,215 +23,12 @@
#define B_TRANSLATION_CONTEXT "Terminal colors scheme"
// Standard colors
const rgb_color kBlack = { 0, 0, 0, 255 };
const rgb_color kGreen = { 0, 255, 0, 255 };
const rgb_color kWhite = { 255, 255, 255, 255 };
const rgb_color kYellow = { 255, 255, 0, 255 };
const struct ansi_color_scheme kAnsiColorSchemeDefault = {
{ 40, 40, 40, 255 },
{ 204, 0, 0, 255 },
{ 78, 154, 6, 255 },
{ 218, 168, 0, 255 },
{ 51, 102, 152, 255 },
{ 115, 68, 123, 255 },
{ 6, 152, 154, 255 },
{ 245, 245, 245, 255 }
};
/* The 'bright' colors palette, relates to the existing
PREF_ANSI_<color>_HCOLOR macros used elsewhere */
const struct ansi_color_scheme kAnsiColorHSchemeDefault = {
{ 128, 128, 128, 255 },
{ 255, 0, 0, 255 },
{ 0, 255, 0, 255 },
{ 255, 255, 0, 255 },
{ 0, 0, 255, 255 },
{ 255, 0, 255, 255 },
{ 0, 255, 255, 255 },
{ 255, 255, 255, 255 }
};
const struct color_scheme kColorSchemeDefault = {
B_TRANSLATE("Default"),
kBlack,
kWhite,
kWhite,
kBlack,
kWhite,
kBlack,
kAnsiColorSchemeDefault,
kAnsiColorHSchemeDefault
};
const struct color_scheme kColorSchemeBlue = {
B_TRANSLATE("Blue"),
kYellow,
{ 0, 0, 139, 255 },
kBlack,
kYellow,
kBlack,
{ 0, 139, 139, 255 },
kAnsiColorSchemeDefault,
kAnsiColorHSchemeDefault
};
const struct color_scheme kColorSchemeMidnight = {
B_TRANSLATE("Midnight"),
kWhite,
kBlack,
kBlack,
kWhite,
kBlack,
kWhite,
kAnsiColorSchemeDefault,
kAnsiColorHSchemeDefault
};
const struct color_scheme kColorSchemeProfessional = {
B_TRANSLATE("Professional"),
kWhite,
{ 8, 8, 8, 255 },
{ 50, 50, 50, 255 },
kWhite,
kWhite,
{ 50, 50, 50, 255 },
kAnsiColorSchemeDefault,
kAnsiColorHSchemeDefault
};
const struct color_scheme kColorSchemeRetro = {
B_TRANSLATE("Retro"),
kGreen,
kBlack,
kBlack,
kGreen,
kBlack,
kGreen,
kAnsiColorSchemeDefault,
kAnsiColorHSchemeDefault
};
const struct color_scheme kColorSchemeSlate = {
B_TRANSLATE("Slate"),
kWhite,
{ 20, 20, 28, 255 },
{ 70, 70, 70, 255 },
{ 255, 200, 0, 255 },
kWhite,
{ 70, 70, 70, 255 },
kAnsiColorSchemeDefault,
kAnsiColorHSchemeDefault
};
const struct color_scheme kColorSchemeSolarizedDark = {
B_TRANSLATE("Solarized Dark"),
{ 131, 148, 150, 255 },
{ 0, 43, 54, 255 },
{ 0, 46, 57, 255 },
{ 120, 137, 139, 255 },
{ 238, 232, 213, 255 },
{ 88, 110, 117, 255 },
{
{ 7, 54, 66, 255 },
{ 220, 50, 47, 255 },
{ 133, 153, 0, 255 },
{ 181, 137, 0, 255 },
{ 38, 139, 210, 255 },
{ 211, 54, 130, 255 },
{ 42, 161, 152, 255 },
{ 238, 232, 213, 255 }
},
{
{ 0, 43, 54, 255 },
{ 203, 75, 22, 255 },
{ 88, 110, 117, 255 },
{ 101, 123, 131, 255 },
{ 131, 148, 150, 255 },
{ 108, 113, 196, 255 },
{ 147, 161, 161, 255 },
{ 253, 246, 227, 255 }
}
};
const struct color_scheme kColorSchemeSolarizedLight = {
B_TRANSLATE("Solarized Light"),
{ 101, 123, 131, 255 },
{ 253, 246, 227, 255 },
{ 236, 228, 207, 255 },
{ 90, 112, 120, 255 },
{ 147, 161, 161, 255 },
{ 7, 54, 66, 255 },
{
{ 7, 54, 66, 255 },
{ 220, 50, 47, 255 },
{ 133, 153, 0, 255 },
{ 181, 137, 0, 255 },
{ 38, 139, 210, 255 },
{ 211, 54, 130, 255 },
{ 42, 161, 152, 255 },
{ 238, 232, 213, 255 }
},
{
{ 0, 43, 54, 255 },
{ 203, 75, 22, 255 },
{ 88, 110, 117, 255 },
{ 101, 123, 131, 255 },
{ 131, 148, 150, 255 },
{ 108, 113, 196, 255 },
{ 147, 161, 161, 255 },
{ 253, 246, 227, 255 }
}
};
const struct color_scheme kColorSchemeRelaxed = {
B_TRANSLATE("Relaxed"),
{ 217, 217, 217, 255 },
{ 53, 58, 68, 255 },
{ 27, 27, 27, 255 },
{ 255, 203, 0, 255 },
{ 53, 58, 68, 255 },
{ 217, 217, 217, 255 },
{
{ 21, 21, 21, 255 },
{ 188, 86, 83, 255 },
{ 144, 157, 99, 255 },
{ 235, 193, 122, 255 },
{ 106, 135, 153, 255 },
{ 176, 102, 152, 255 },
{ 201, 223, 255, 255 },
{ 217, 217, 217, 255 }
},
{
{ 99, 99, 99, 255 },
{ 188, 86, 83, 255 },
{ 160, 172, 119, 255 },
{ 235, 192, 122, 255 },
{ 126, 170, 199, 255 },
{ 176, 102, 152, 255 },
{ 172, 187, 208, 255 },
{ 247, 247, 247, 255 }
}
};
struct color_scheme gCustomColorScheme = {
B_TRANSLATE("Custom")
};
const color_scheme* gPredefinedColorSchemes[] = {
&kColorSchemeDefault,
&kColorSchemeBlue,
&kColorSchemeMidnight,
&kColorSchemeProfessional,
&kColorSchemeRetro,
&kColorSchemeSlate,
&kColorSchemeSolarizedDark,
&kColorSchemeSolarizedLight,
&kColorSchemeRelaxed,
&gCustomColorScheme,
NULL
};
BObjectList<const color_scheme>* gColorSchemes = NULL;
bool
+18 -1
View File
@@ -11,6 +11,7 @@
#include <InterfaceDefs.h>
#include <ObjectList.h>
struct ansi_color_scheme {
@@ -38,8 +39,24 @@ struct color_scheme {
bool operator==(const color_scheme& color);
};
struct FindColorSchemeByName : public UnaryPredicate<const color_scheme> {
FindColorSchemeByName() : scheme_name("") {}
FindColorSchemeByName(const char* name)
: scheme_name(name)
{
}
int operator()(const color_scheme* item) const
{
return strcmp(item->name, scheme_name);
}
const char* scheme_name;
};
extern color_scheme gCustomColorScheme;
extern const color_scheme* gPredefinedColorSchemes[];
extern BObjectList<const color_scheme> *gColorSchemes;
const uint kANSIColorCount = 16;
const uint kTermColorCount = 256;
+105 -1
View File
@@ -21,18 +21,20 @@
#include <string.h>
#include <unistd.h>
#include <AutoDeleter.h>
#include <Catalog.h>
#include <Directory.h>
#include <Entry.h>
#include <File.h>
#include <FindDirectory.h>
#include <Font.h>
#include <GraphicsDefs.h>
#include <Locale.h>
#include <Message.h>
#include <NodeInfo.h>
#include <Path.h>
#include <PathFinder.h>
#include "Colors.h"
#include "Globals.h"
#include "TermConst.h"
@@ -110,6 +112,11 @@ PrefHandler::PrefHandler(bool loadSettings)
BPath path;
GetDefaultPath(path);
OpenText(path.Path());
// Add the builtin schemes
if (gColorSchemes == NULL) {
LoadThemes();
}
}
// TODO: If no fixed font is available, be_fixed_font
@@ -253,6 +260,60 @@ PrefHandler::SaveAsText(const char *path, const char *mimetype,
}
static int
SortByName(const color_scheme *lhs, const color_scheme *rhs)
{
return strcmp(lhs->name, rhs->name);
}
void
PrefHandler::LoadThemes()
{
gColorSchemes = new BObjectList<const color_scheme>(10, true);
BStringList paths;
if (BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY,
"Terminal/Themes/", B_FIND_PATH_EXISTING_ONLY, paths) == B_OK)
paths.DoForEach(PrefHandler::_LoadThemesFromDirectory);
if (BPathFinder::FindPaths(B_FIND_PATH_SETTINGS_DIRECTORY,
"Terminal/Themes/", B_FIND_PATH_EXISTING_ONLY, paths) == B_OK)
paths.DoForEach(PrefHandler::_LoadThemesFromDirectory);
gColorSchemes->SortItems(SortByName);
}
void
PrefHandler::LoadColorScheme(color_scheme* scheme)
{
scheme->text_fore_color = getRGB(PREF_TEXT_FORE_COLOR);
scheme->text_back_color = getRGB(PREF_TEXT_BACK_COLOR);
scheme->select_fore_color = getRGB(PREF_SELECT_FORE_COLOR);
scheme->select_back_color = getRGB(PREF_SELECT_BACK_COLOR);
scheme->cursor_fore_color = getRGB(PREF_CURSOR_FORE_COLOR);
scheme->cursor_back_color = getRGB(PREF_CURSOR_BACK_COLOR);
scheme->ansi_colors.black = getRGB(PREF_ANSI_BLACK_COLOR);
scheme->ansi_colors.red = getRGB(PREF_ANSI_RED_COLOR);
scheme->ansi_colors.green = getRGB(PREF_ANSI_GREEN_COLOR);
scheme->ansi_colors.yellow = getRGB(PREF_ANSI_YELLOW_COLOR);
scheme->ansi_colors.blue = getRGB(PREF_ANSI_BLUE_COLOR);
scheme->ansi_colors.magenta = getRGB(PREF_ANSI_MAGENTA_COLOR);
scheme->ansi_colors.cyan = getRGB(PREF_ANSI_CYAN_COLOR);
scheme->ansi_colors.white = getRGB(PREF_ANSI_WHITE_COLOR);
scheme->ansi_colors_h.black = getRGB(PREF_ANSI_BLACK_HCOLOR);
scheme->ansi_colors_h.red = getRGB(PREF_ANSI_RED_HCOLOR);
scheme->ansi_colors_h.green = getRGB(PREF_ANSI_GREEN_HCOLOR);
scheme->ansi_colors_h.yellow = getRGB(PREF_ANSI_YELLOW_HCOLOR);
scheme->ansi_colors_h.blue = getRGB(PREF_ANSI_BLUE_HCOLOR);
scheme->ansi_colors_h.magenta = getRGB(PREF_ANSI_MAGENTA_HCOLOR);
scheme->ansi_colors_h.cyan = getRGB(PREF_ANSI_CYAN_HCOLOR);
scheme->ansi_colors_h.white = getRGB(PREF_ANSI_WHITE_HCOLOR);
}
int32
PrefHandler::getInt32(const char *key)
{
@@ -483,3 +544,46 @@ PrefHandler::_LoadFromTextFile(const char * path)
fclose(file);
return B_OK;
}
bool
PrefHandler::_LoadThemesFromDirectory(const BString &directory)
{
BDirectory *themes = new BDirectory(directory.String());
if (themes == NULL)
return false;
BEntry entry;
BPath path;
FindColorSchemeByName comparator;
while (themes->GetNextEntry(&entry) == B_OK)
{
if (entry.GetPath(&path) != B_OK)
continue;
PrefHandler *themeHandler = new PrefHandler(false);
ObjectDeleter<PrefHandler> themeHandlerDeleter(themeHandler);
themeHandler->_LoadFromTextFile(path.Path());
const char *name = themeHandler->fContainer.GetString(PREF_THEME_NAME, NULL);
if (name == NULL || strlen(name) == 0)
continue;
comparator.scheme_name = name;
const color_scheme *scheme = gColorSchemes->FindIf(comparator);
if (scheme != NULL) {
// Scheme with this name exists, replace with this version instead
gColorSchemes->RemoveItem(scheme);
}
color_scheme *newScheme = new color_scheme();
newScheme->name = strdup(name);
themeHandler->LoadColorScheme(newScheme);
gColorSchemes->AddItem(newScheme);
}
return false;
}
+7
View File
@@ -18,11 +18,14 @@
#include <SupportDefs.h>
#include <GraphicsDefs.h>
#include <Message.h>
#include <String.h>
class BFont;
class BPath;
struct color_scheme;
struct pref_defaults {
const char *key;
const char *item;
@@ -71,10 +74,14 @@ class PrefHandler {
static status_t GetDefaultPath(BPath& path);
void LoadThemes();
void LoadColorScheme(color_scheme* scheme);
private:
void _ConfirmFont(const BFont *fallbackFont);
status_t _LoadFromDefault(const pref_defaults* defaults = NULL);
status_t _LoadFromTextFile(const char * path);
static bool _LoadThemesFromDirectory(const BString &directory);
BMessage fContainer;
+1
View File
@@ -91,6 +91,7 @@ static const uint32 MSG_GET_TERMINAL_COLOR = 'getc';
// Preference Read/Write Keys
static const char* const PREF_THEME_NAME = "Theme name";
static const char* const PREF_HALF_FONT_FAMILY = "Half Font Family";
static const char* const PREF_HALF_FONT_STYLE = "Half Font Style";
static const char* const PREF_HALF_FONT_SIZE = "Half Font Size";