From de2ada1f106c1c43ceeebef638d503d5049b88ca Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Sat, 10 Jul 2021 03:44:22 +0000 Subject: [PATCH] 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 --- src/apps/terminal/AppearPrefView.cpp | 86 +++++------ src/apps/terminal/AppearPrefView.h | 7 +- src/apps/terminal/Colors.cpp | 207 +-------------------------- src/apps/terminal/Colors.h | 19 ++- src/apps/terminal/PrefHandler.cpp | 106 +++++++++++++- src/apps/terminal/PrefHandler.h | 7 + src/apps/terminal/TermConst.h | 1 + 7 files changed, 181 insertions(+), 252 deletions(-) diff --git a/src/apps/terminal/AppearPrefView.cpp b/src/apps/terminal/AppearPrefView.cpp index b7ae0490c1..256df2d7c4 100644 --- a/src/apps/terminal/AppearPrefView.cpp +++ b/src/apps/terminal/AppearPrefView.cpp @@ -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 *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; } diff --git a/src/apps/terminal/AppearPrefView.h b/src/apps/terminal/AppearPrefView.h index 05dd7e39c9..95630491ba 100644 --- a/src/apps/terminal/AppearPrefView.h +++ b/src/apps/terminal/AppearPrefView.h @@ -10,6 +10,7 @@ #include #include +#include #include @@ -71,8 +72,10 @@ private: const char* defaultItem); static BPopUpMenu* _MakeColorSchemeMenu(uint32 msg, - const color_scheme** schemes, - const color_scheme* defaultItemName); + BObjectList *items); + static void _MakeColorSchemeMenuItem(uint32 msg, + const color_scheme *item, + BPopUpMenu* menu); void _MarkSelectedFont(const char* family, const char* style, const char* size); diff --git a/src/apps/terminal/Colors.cpp b/src/apps/terminal/Colors.cpp index 0961b3d0b5..4c4d6f771d 100644 --- a/src/apps/terminal/Colors.cpp +++ b/src/apps/terminal/Colors.cpp @@ -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__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* gColorSchemes = NULL; bool diff --git a/src/apps/terminal/Colors.h b/src/apps/terminal/Colors.h index db744b2870..090efb8d1f 100644 --- a/src/apps/terminal/Colors.h +++ b/src/apps/terminal/Colors.h @@ -11,6 +11,7 @@ #include +#include struct ansi_color_scheme { @@ -38,8 +39,24 @@ struct color_scheme { bool operator==(const color_scheme& color); }; +struct FindColorSchemeByName : public UnaryPredicate { + 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 *gColorSchemes; const uint kANSIColorCount = 16; const uint kTermColorCount = 256; diff --git a/src/apps/terminal/PrefHandler.cpp b/src/apps/terminal/PrefHandler.cpp index b2f10f5cb0..e572996fc1 100644 --- a/src/apps/terminal/PrefHandler.cpp +++ b/src/apps/terminal/PrefHandler.cpp @@ -21,18 +21,20 @@ #include #include +#include #include #include #include #include -#include #include #include #include #include #include #include +#include +#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(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 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; +} diff --git a/src/apps/terminal/PrefHandler.h b/src/apps/terminal/PrefHandler.h index 4335643023..6c1922dd32 100644 --- a/src/apps/terminal/PrefHandler.h +++ b/src/apps/terminal/PrefHandler.h @@ -18,11 +18,14 @@ #include #include #include +#include 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; diff --git a/src/apps/terminal/TermConst.h b/src/apps/terminal/TermConst.h index 6903a945bb..31cb7f4d2d 100644 --- a/src/apps/terminal/TermConst.h +++ b/src/apps/terminal/TermConst.h @@ -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";