Skip to content

Commit

Permalink
allow custom themes in settings
Browse files Browse the repository at this point in the history
  • Loading branch information
kjk committed Aug 8, 2024
1 parent 6b9421a commit 651de85
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 144 deletions.
10 changes: 6 additions & 4 deletions src/AppSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,6 @@ bool LoadSettings() {
// auto fontName = ToWStrTemp(gprefs->fixedPageUI.ebookFontName);
// SetDefaultEbookFont(fontName.Get(), gprefs->fixedPageUI.ebookFontSize);

SetCurrentThemeFromSettings();
if (!file::Exists(settingsPath)) {
SaveSettings();
}
ResetCachedFonts();

// re-create commands
Expand All @@ -285,6 +281,12 @@ bool LoadSettings() {
CreateSumatraAcceleratorTable();

ReCreateToolbars();

SetCurrentThemeFromSettings();
if (!file::Exists(settingsPath)) {
SaveSettings();
}

logf("LoadSettings('%s') took %.2f ms\n", settingsPath, TimeSinceInMs(timeStart));
return true;
}
Expand Down
11 changes: 11 additions & 0 deletions src/GlobalPrefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,17 @@ ParsedColor* GetParsedColor(const char* s, ParsedColor& parsed) {
return &parsed;
}

COLORREF GetParsedCOLORREF(const char* s, ParsedColor& parsed, COLORREF def) {
if (parsed.wasParsed) {
return parsed.col;
}
ParseColor(parsed, s);
if (parsed.wasParsed) {
return parsed.col;
}
return def;
}

void SetFileStatePath(FileState* fs, const char* path) {
if (fs->filePath && str::EqI(fs->filePath, path)) {
return;
Expand Down
1 change: 1 addition & 0 deletions src/GlobalPrefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ SessionData* NewSessionData();
TabState* NewTabState(FileState* fs);
void ResetSessionState(Vec<SessionData*>* sessionData);
ParsedColor* GetParsedColor(const char* s, ParsedColor& parsed);
COLORREF GetParsedCOLORREF(const char* s, ParsedColor& parsed, COLORREF def);

void SetFileStatePath(FileState* fs, const char* path);
// void SetFileStatePath(FileState* fs, const WCHAR* path);
Expand Down
206 changes: 66 additions & 140 deletions src/Theme.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,6 @@
/* Copyright 2022 the SumatraPDF project authors (see AUTHORS file).
License: GPLv3 */

/* Adding themes instructions:
Add one to kThemeCount (Theme.h)
If kThemeCount > 20, you will have to update IDM_CHANGE_THEME_LAST (resource.h)
Copy one of the theme declarations below
Rename it to whatever and change all of the properties as desired
Add a pointer to your new struct to the g_themes array below
Try not to enter a color code twice. If you use it more than once in a theme,
reference it through the theme struct the second time. See g_themeDark.document for example.
You can also use methods like AdjustLightness2 to modify existing colors. If you use a
color in multiple themes, you may want to define it in the color definitions section.This
makes themes easier to modify and update.
Note: Colors are in format 0xBBGGRR, recommended to use RgbToCOLORREF
*/

#include "utils/BaseUtil.h"
#include "utils/WinUtil.h"

Expand All @@ -33,8 +17,7 @@ Note: Colors are in format 0xBBGGRR, recommended to use RgbToCOLORREF

constexpr COLORREF kColBlack = 0x000000;
constexpr COLORREF kColWhite = 0xFFFFFF;
// #define kColWhiteish 0xEBEBF9
// #define kColDarkGray 0x424242
constexpr COLORREF kRedColor = RgbToCOLORREF(0xff0000);

static const char* themesTxt = R"(Themes [
[
Expand Down Expand Up @@ -64,143 +47,79 @@ static const char* themesTxt = R"(Themes [
]
)";

struct ThemeOld {
// Name of the theme
const char* name;

// Text color of recently added, about, and properties menus
COLORREF textColor;
// Background color of recently added, about, and properties menus
COLORREF backgroundColor;
// Background color of controls, menus, non-client areas, etc.
COLORREF controlBackgroundColor;
// Link color on recently added, about, and properties menus
COLORREF linkColor;
// Whether or not we colorize standard Windows controls and window areas
bool colorizeControls;
};

// clang-format off
static ThemeOld gThemeLight = {
// Theme Name
_TRN("Light"),

// Main Background Color
// Background color comparison:
// Adobe Reader X 0x565656 without any frame border
// Foxit Reader 5 0x9C9C9C with a pronounced frame shadow
// PDF-XChange 0xACA899 with a 1px frame and a gradient shadow
// Google Chrome 0xCCCCCC with a symmetric gradient shadow
// Evince 0xD7D1CB with a pronounced frame shadow
// SumatraPDF (old) 0xCCCCCC with a pronounced frame shadow

// Main Text Color
kColBlack,
// it's very light gray but not white so that there's contrast between
// background and thumbnail, which often have white background because
// most PDFs have white background.
RgbToCOLORREF(0xF2F2F2),
// Control background Color
kColWhite,
// Main Link Color
RgbToCOLORREF(0x0020A0),

// Colorize standard controls
false
};

static ThemeOld gThemeDark = {
// Theme Name
_TRN("Dark"),
// Main Text Color
AdjustLightness2(RgbToCOLORREF(0x263238), 150),
// Main Background Color
RgbToCOLORREF(0x263238),
// Control background Color
RgbToCOLORREF(0x263238),
// Main Link Color
AdjustLightness2(RgbToCOLORREF(0x263238), 110),

true
};

static ThemeOld gThemeDarker = {
// Theme Name
_TRN("Darker"),
// Main Text Color
AdjustLightness2(RgbToCOLORREF(0x2D2D30), 150),
// Main Background Color
RgbToCOLORREF(0x2D2D30),
// Control background Color
RgbToCOLORREF(0x2D2D30),
// Main Link Color
AdjustLightness2(RgbToCOLORREF(0x2D2D30), 110),

// Colorize standard controls
true
};
// clang-format on

static ThemeOld* gThemes[] = {
&gThemeLight,
&gThemeDark,
&gThemeDarker,
};
extern void UpdateAfterThemeChange();

constexpr const int kThemeCount = dimofi(gThemes);
int gFirstSetThemeCmdId;
int gLastSetThemeCmdId;
int gCurrSetThemeCmdId;

ThemeOld* gCurrentTheme = &gThemeLight;
static int currentThemeIndex = 0;
static Vec<Theme*>* gThemes = nullptr;
static int gThemeCount;
static int gCurrThemeIndex = 0;
static Theme* gCurrentTheme = nullptr;
static Theme* gThemeLight = nullptr;

int GetCurrentThemeIndex() {
return currentThemeIndex;
return gCurrThemeIndex;
}

extern void UpdateAfterThemeChange();
void CreateThemeCommands() {
delete gThemes;
gThemes = new Vec<Theme*>();
auto themes = ParseThemes(themesTxt);
for (Theme* theme : *themes->themes) {
gThemes->Append(theme);
}

int gFirstSetThemeCmdId;
int gLastSetThemeCmdId;
int gCurrSetThemeCmdId;
for (Theme* theme : *gGlobalPrefs->themes) {
gThemes->Append(theme);
}

gThemeCount = gThemes->Size();
if (gCurrThemeIndex >= gThemeCount) {
gCurrThemeIndex = 0;
}
gCurrentTheme = gThemes->At(gCurrThemeIndex);
gThemeLight = gThemes->At(0);

void CreateThemeCommands() {
//auto themes = ParseThemes(themesTxt);
//logf("number of themes: %d\n", themes->themes->Size());
CustomCommand* cmd;
for (int i = 0; i < kThemeCount; i++) {
const char* themeName = gThemes[i]->name;
for (int i = 0; i < gThemeCount; i++) {
Theme* theme = gThemes->At(i);
const char* themeName = theme->name;
auto args = NewStringArg(kCmdArgTheme, themeName);
cmd = CreateCustomCommand(themeName, CmdSetTheme, args);
cmd->name = str::Format("Set theme '%s'", themeName);
if (i == 0) {
gFirstSetThemeCmdId = cmd->id;
} else if (i == kThemeCount - 1) {
} else if (i == gThemeCount - 1) {
gLastSetThemeCmdId = cmd->id;
}
}
gCurrSetThemeCmdId = gFirstSetThemeCmdId + 0;
gCurrSetThemeCmdId = gFirstSetThemeCmdId + gCurrThemeIndex;
}

void SetThemeByIndex(int themeIdx) {
ReportIf((themeIdx < 0) || (themeIdx >= kThemeCount));
if (themeIdx >= kThemeCount) {
ReportIf((themeIdx < 0) || (themeIdx >= gThemeCount));
if (themeIdx >= gThemeCount) {
themeIdx = 0;
}
currentThemeIndex = themeIdx;
gCurrThemeIndex = themeIdx;
gCurrSetThemeCmdId = gFirstSetThemeCmdId + themeIdx;
gCurrentTheme = gThemes[currentThemeIndex];
gCurrentTheme = gThemes->At(gCurrThemeIndex);
str::ReplaceWithCopy(&gGlobalPrefs->theme, gCurrentTheme->name);
UpdateAfterThemeChange();
};

void SelectNextTheme() {
int newIdx = (currentThemeIndex + 1) % kThemeCount;
int newIdx = (gCurrThemeIndex + 1) % gThemeCount;
SetThemeByIndex(newIdx);
}

// not case sensitive
static int GetThemeByName(const char* name) {
for (int i = 0; i < kThemeCount; i++) {
if (str::EqI(gThemes[i]->name, name)) {
for (int i = 0; i < gThemeCount; i++) {
Theme* theme = gThemes->At(i);
if (str::EqI(theme->name, name)) {
return i;
}
}
Expand All @@ -218,7 +137,7 @@ void SetTheme(const char* name) {
int idx = GetThemeByName(name);
if (idx < 0) {
// invalid name, reset to light theme
str::ReplaceWithCopy(&gGlobalPrefs->theme, gThemeLight.name);
str::ReplaceWithCopy(&gGlobalPrefs->theme, gThemeLight->name);
idx = 0;
}
SetThemeByIndex(idx);
Expand All @@ -230,11 +149,11 @@ void SetCurrentThemeFromSettings() {
ParsedColor* bgParsed = GetPrefsColor(gGlobalPrefs->mainWindowBackground);
bool isDefault = IsDefaultMainWinColor(bgParsed);
if (isDefault) {
gThemeLight.colorizeControls = false;
gThemeLight.controlBackgroundColor = kColWhite;
gThemeLight->colorizeControls = false;
gThemeLight->controlBackgroundColorParsed.col = kColWhite;
} else {
gThemeLight.colorizeControls = true;
gThemeLight.controlBackgroundColor = bgParsed->col;
gThemeLight->colorizeControls = true;
gThemeLight->controlBackgroundColorParsed.col = bgParsed->col;
}
}

Expand All @@ -248,6 +167,8 @@ static COLORREF AdjustLightOrDark(COLORREF col, float n) {
return col;
}

#define GetThemeCol(name, def) GetParsedCOLORREF(name, name##Parsed, def)

COLORREF ThemeDocumentColors(COLORREF& bg) {
COLORREF text = kColBlack;
bg = kColWhite;
Expand All @@ -268,28 +189,29 @@ COLORREF ThemeDocumentColors(COLORREF& bg) {
}

// default colors
if (gCurrentTheme == &gThemeLight) {
if (gCurrentTheme == gThemeLight) {
std::swap(text, bg);
return text;
}

// if we're inverting in non-default themes, the colors
// should match the colors of the window
text = ThemeWindowTextColor();
bg = gCurrentTheme->backgroundColor;
bg = ThemeMainWindowBackgroundColor();
bg = AdjustLightOrDark(bg, 8);
return text;
}

COLORREF ThemeControlBackgroundColor() {
// note: we can change it in ThemeUpdateAfterLoadSettings()
return gCurrentTheme->controlBackgroundColor;
auto col = GetThemeCol(gCurrentTheme->controlBackgroundColor, kRedColor);
return col;
}

// TODO: migrate from prefs to theme.
COLORREF ThemeMainWindowBackgroundColor() {
COLORREF bgColor = gCurrentTheme->backgroundColor;
if (currentThemeIndex == 0) {
COLORREF bgColor = GetThemeCol(gCurrentTheme->backgroundColor, kRedColor);
if (gCurrThemeIndex == 0) {
// Special behavior for light theme.
ParsedColor* bgParsed = GetPrefsColor(gGlobalPrefs->mainWindowBackground);
if (!IsDefaultMainWinColor(bgParsed)) {
Expand All @@ -300,35 +222,39 @@ COLORREF ThemeMainWindowBackgroundColor() {
}

COLORREF ThemeWindowBackgroundColor() {
return gCurrentTheme->backgroundColor;
auto col = GetThemeCol(gCurrentTheme->backgroundColor, kRedColor);
return col;
}

COLORREF ThemeWindowTextColor() {
return gCurrentTheme->textColor;
auto col = GetThemeCol(gCurrentTheme->textColor, kRedColor);
return col;
}

COLORREF ThemeWindowTextDisabledColor() {
auto col = gCurrentTheme->textColor;
auto col = ThemeWindowTextColor();
// TODO: probably add textDisabledColor
auto col2 = AdjustLightOrDark(col, 0x7f);
return col2;
}

COLORREF ThemeWindowControlBackgroundColor() {
return gCurrentTheme->controlBackgroundColor;
auto col = GetThemeCol(gCurrentTheme->controlBackgroundColor, kRedColor);
return col;
}

COLORREF ThemeWindowLinkColor() {
return gCurrentTheme->linkColor;
auto col = GetThemeCol(gCurrentTheme->linkColor, kRedColor);
return col;
}

COLORREF ThemeNotificationsBackgroundColor() {
auto col = gCurrentTheme->backgroundColor;
auto col = ThemeWindowBackgroundColor();
return AdjustLightness2(col, 10);
}

COLORREF ThemeNotificationsTextColor() {
return gCurrentTheme->textColor;
return ThemeWindowTextColor();
}

COLORREF ThemeNotificationsHighlightColor() {
Expand All @@ -340,7 +266,7 @@ COLORREF ThemeNotificationsHighlightTextColor() {
}

COLORREF ThemeNotificationsProgressColor() {
return gCurrentTheme->linkColor;
return ThemeWindowLinkColor();
}

bool ThemeColorizeControls() {
Expand Down

0 comments on commit 651de85

Please sign in to comment.