Merge pull request #816 from jpcima/theme-selector.2
UI: Theme selector
This commit is contained in:
commit
a838dc3dbd
9 changed files with 366 additions and 57 deletions
|
|
@ -20,6 +20,7 @@ set(EDITOR_RESOURCES
|
||||||
Fonts/sfizz-fluentui-system-f20.ttf
|
Fonts/sfizz-fluentui-system-f20.ttf
|
||||||
Fonts/sfizz-misc-icons.ttf
|
Fonts/sfizz-misc-icons.ttf
|
||||||
Fonts/Roboto-Regular.ttf
|
Fonts/Roboto-Regular.ttf
|
||||||
|
Themes/Default/theme.xml
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
|
||||||
function(copy_editor_resources SOURCE_DIR DESTINATION_DIR)
|
function(copy_editor_resources SOURCE_DIR DESTINATION_DIR)
|
||||||
|
|
@ -50,6 +51,8 @@ add_library(sfizz_editor STATIC EXCLUDE_FROM_ALL
|
||||||
src/editor/GUIPiano.cpp
|
src/editor/GUIPiano.cpp
|
||||||
src/editor/DlgAbout.h
|
src/editor/DlgAbout.h
|
||||||
src/editor/DlgAbout.cpp
|
src/editor/DlgAbout.cpp
|
||||||
|
src/editor/Theme.h
|
||||||
|
src/editor/Theme.cpp
|
||||||
src/editor/ColorHelpers.h
|
src/editor/ColorHelpers.h
|
||||||
src/editor/ColorHelpers.cpp
|
src/editor/ColorHelpers.cpp
|
||||||
src/editor/ImageHelpers.h
|
src/editor/ImageHelpers.h
|
||||||
|
|
@ -104,7 +107,8 @@ else()
|
||||||
target_include_directories(sfizz_editor PRIVATE ${sfizz-gio_INCLUDE_DIRS})
|
target_include_directories(sfizz_editor PRIVATE ${sfizz-gio_INCLUDE_DIRS})
|
||||||
target_link_libraries(sfizz_editor PRIVATE ${sfizz-gio_LIBRARIES})
|
target_link_libraries(sfizz_editor PRIVATE ${sfizz-gio_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(sfizz_editor PRIVATE sfizz::colorspaces sfizz::stb_image sfizz::bit_array sfizz::filesystem)
|
target_link_libraries(sfizz_editor PRIVATE sfizz::colorspaces sfizz::stb_image
|
||||||
|
sfizz::bit_array sfizz::filesystem sfizz::pugixml)
|
||||||
|
|
||||||
# layout tool
|
# layout tool
|
||||||
if(NOT CMAKE_CROSSCOMPILING)
|
if(NOT CMAKE_CROSSCOMPILING)
|
||||||
|
|
|
||||||
|
|
@ -356,6 +356,17 @@ widget_class mainView {open
|
||||||
class ValueMenu
|
class ValueMenu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Fl_Group {} {
|
||||||
|
label Theme open
|
||||||
|
xywh {40 270 105 100} box ROUNDED_BOX labelsize 12 align 17 hide
|
||||||
|
class TitleGroup
|
||||||
|
} {
|
||||||
|
Fl_Spinner themeMenu_ {
|
||||||
|
comment {tag=kTagThemeMenu}
|
||||||
|
xywh {60 330 65 25} labelsize 12 textsize 12
|
||||||
|
class OptionMenu
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Fl_Box piano_ {
|
Fl_Box piano_ {
|
||||||
xywh {5 400 790 70} labelsize 12
|
xywh {5 400 790 70} labelsize 12
|
||||||
|
|
|
||||||
34
plugins/editor/resources/Themes/Default/theme.xml
Normal file
34
plugins/editor/resources/Themes/Default/theme.xml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<sfizz-theme>
|
||||||
|
<color name="frameBackground">#d3d7cf</color>
|
||||||
|
<palette name="normal">
|
||||||
|
<color name="boxBackground">#babdb6</color>
|
||||||
|
<color name="text">#000000</color>
|
||||||
|
<color name="inactiveText">#b2b2b2</color>
|
||||||
|
<color name="highlightedText">#fd9800</color>
|
||||||
|
<color name="titleBoxText">#ffffff</color>
|
||||||
|
<color name="titleBoxBackground">#2e3436</color>
|
||||||
|
<color name="icon">#000000</color>
|
||||||
|
<color name="iconHighlight">#fd9800</color>
|
||||||
|
<color name="valueText">#ffffff</color>
|
||||||
|
<color name="valueBackground">#2e3436</color>
|
||||||
|
<color name="knobActiveTrack">#00b62a</color>
|
||||||
|
<color name="knobInactiveTrack">#303030</color>
|
||||||
|
<color name="knobLineIndicator">#000000</color>
|
||||||
|
</palette>
|
||||||
|
<palette name="inverted">
|
||||||
|
<color name="boxBackground">#2e3436</color>
|
||||||
|
<color name="text">#ffffff</color>
|
||||||
|
<color name="inactiveText">#b2b2b2</color>
|
||||||
|
<color name="highlightedText">#fd9800</color>
|
||||||
|
<color name="titleBoxText">#000000</color>
|
||||||
|
<color name="titleBoxBackground">#babdb6</color>
|
||||||
|
<color name="icon">#b2b2b2</color>
|
||||||
|
<color name="iconHighlight">#fd9800</color>
|
||||||
|
<color name="valueText">#000000</color>
|
||||||
|
<color name="valueBackground">#9a9a9a</color>
|
||||||
|
<color name="knobActiveTrack">#00b62a</color>
|
||||||
|
<color name="knobInactiveTrack">#606060</color>
|
||||||
|
<color name="knobLineIndicator">#ffffff</color>
|
||||||
|
</palette>
|
||||||
|
</sfizz-theme>
|
||||||
|
|
@ -44,3 +44,38 @@ SColorHCY::SColorHCY(const SColorRGB &rgb)
|
||||||
y = vhcy[2];
|
y = vhcy[2];
|
||||||
a = rgb.a;
|
a = rgb.a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hexDigitFromChar(char c)
|
||||||
|
{
|
||||||
|
return (c >= '0' && c <= '9') ? (c - '0') :
|
||||||
|
(c >= 'a' && c <= 'z') ? (c - 'a' + 10) :
|
||||||
|
(c >= 'A' && c <= 'Z') ? (c - 'A' + 10) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool colorFromHex(absl::string_view hex, CColor& color)
|
||||||
|
{
|
||||||
|
if (hex.empty() || hex[0] != '#')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hex = hex.substr(1, hex.size());
|
||||||
|
size_t length = hex.size();
|
||||||
|
uint32_t rgba = 0;
|
||||||
|
if (length == 6 || length == 8) {
|
||||||
|
for (size_t i = 0; i < length; ++i) {
|
||||||
|
int d = hexDigitFromChar(hex[i]);
|
||||||
|
if (d == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rgba = (rgba << 4) | d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (length == 6)
|
||||||
|
rgba = (rgba << 8) | 0xff;
|
||||||
|
|
||||||
|
color.red = rgba >> 24;
|
||||||
|
color.green = (rgba >> 16) & 0xff;
|
||||||
|
color.blue = (rgba >> 8) & 0xff;
|
||||||
|
color.alpha = rgba & 0xff;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "utility/vstgui_before.h"
|
#include "utility/vstgui_before.h"
|
||||||
#include "vstgui/lib/ccolor.h"
|
#include "vstgui/lib/ccolor.h"
|
||||||
#include "utility/vstgui_after.h"
|
#include "utility/vstgui_after.h"
|
||||||
|
#include <absl/strings/string_view.h>
|
||||||
|
|
||||||
using namespace VSTGUI;
|
using namespace VSTGUI;
|
||||||
|
|
||||||
|
|
@ -33,3 +34,5 @@ struct SColorHCY {
|
||||||
|
|
||||||
float h {}, c {}, y {}, a { 1.0 };
|
float h {}, c {}, y {}, a { 1.0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool colorFromHex(absl::string_view hex, CColor& color);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "NativeHelpers.h"
|
#include "NativeHelpers.h"
|
||||||
#include "VSTGUIHelpers.h"
|
#include "VSTGUIHelpers.h"
|
||||||
#include "BitArray.h"
|
#include "BitArray.h"
|
||||||
|
#include "Theme.h"
|
||||||
#include "plugin/MessageUtils.h"
|
#include "plugin/MessageUtils.h"
|
||||||
#include <absl/strings/string_view.h>
|
#include <absl/strings/string_view.h>
|
||||||
#include <absl/strings/match.h>
|
#include <absl/strings/match.h>
|
||||||
|
|
@ -32,6 +33,7 @@
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "utility/vstgui_before.h"
|
#include "utility/vstgui_before.h"
|
||||||
#include "vstgui/vstgui.h"
|
#include "vstgui/vstgui.h"
|
||||||
|
|
@ -50,6 +52,7 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
|
||||||
|
|
||||||
std::string currentSfzFile_;
|
std::string currentSfzFile_;
|
||||||
std::string currentScalaFile_;
|
std::string currentScalaFile_;
|
||||||
|
std::string currentThemeName_;
|
||||||
std::string userFilesDir_;
|
std::string userFilesDir_;
|
||||||
std::string fallbackFilesDir_;
|
std::string fallbackFilesDir_;
|
||||||
|
|
||||||
|
|
@ -91,6 +94,7 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
|
||||||
kTagSetCCPan,
|
kTagSetCCPan,
|
||||||
kTagChooseUserFilesDir,
|
kTagChooseUserFilesDir,
|
||||||
kTagAbout,
|
kTagAbout,
|
||||||
|
kTagThemeMenu,
|
||||||
kTagFirstChangePanel,
|
kTagFirstChangePanel,
|
||||||
kTagLastChangePanel = kTagFirstChangePanel + kNumPanels - 1,
|
kTagLastChangePanel = kTagFirstChangePanel + kNumPanels - 1,
|
||||||
};
|
};
|
||||||
|
|
@ -119,6 +123,8 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
|
||||||
CTextLabel* keyswitchLabel_ = nullptr;
|
CTextLabel* keyswitchLabel_ = nullptr;
|
||||||
CTextLabel* keyswitchInactiveLabel_ = nullptr;
|
CTextLabel* keyswitchInactiveLabel_ = nullptr;
|
||||||
CTextLabel* keyswitchBadge_ = nullptr;
|
CTextLabel* keyswitchBadge_ = nullptr;
|
||||||
|
COptionMenu* themeMenu_ = nullptr;
|
||||||
|
std::unique_ptr<Theme> theme_;
|
||||||
|
|
||||||
STitleContainer* userFilesGroup_ = nullptr;
|
STitleContainer* userFilesGroup_ = nullptr;
|
||||||
STextButton* userFilesDirButton_ = nullptr;
|
STextButton* userFilesDirButton_ = nullptr;
|
||||||
|
|
@ -590,54 +596,14 @@ void Editor::Impl::createFrameContents()
|
||||||
backgroundBitmap_ = background;
|
backgroundBitmap_ = background;
|
||||||
|
|
||||||
{
|
{
|
||||||
const CColor frameBackground = { 0xd3, 0xd7, 0xcf };
|
// Try to load the Default theme from disk or hardcoded one as fallback
|
||||||
|
Theme* theme = new Theme;
|
||||||
struct Palette {
|
theme_.reset(theme);
|
||||||
CColor boxBackground;
|
currentThemeName_ = theme->loadCurrentName();
|
||||||
CColor text;
|
theme->load(currentThemeName_);
|
||||||
CColor inactiveText;
|
|
||||||
CColor highlightedText;
|
|
||||||
CColor titleBoxText;
|
|
||||||
CColor titleBoxBackground;
|
|
||||||
CColor icon;
|
|
||||||
CColor iconHighlight;
|
|
||||||
CColor valueText;
|
|
||||||
CColor valueBackground;
|
|
||||||
CColor knobActiveTrackColor;
|
|
||||||
CColor knobInactiveTrackColor;
|
|
||||||
CColor knobLineIndicatorColor;
|
|
||||||
};
|
|
||||||
|
|
||||||
Palette normalPalette;
|
|
||||||
normalPalette.boxBackground = { 0xba, 0xbd, 0xb6 };
|
|
||||||
normalPalette.text = { 0x00, 0x00, 0x00 };
|
|
||||||
normalPalette.inactiveText = { 0xb2, 0xb2, 0xb2 };
|
|
||||||
normalPalette.highlightedText = { 0xfd, 0x98, 0x00 };
|
|
||||||
normalPalette.titleBoxText = { 0xff, 0xff, 0xff };
|
|
||||||
normalPalette.titleBoxBackground = { 0x2e, 0x34, 0x36 };
|
|
||||||
normalPalette.icon = normalPalette.text;
|
|
||||||
normalPalette.iconHighlight = { 0xfd, 0x98, 0x00 };
|
|
||||||
normalPalette.valueText = { 0xff, 0xff, 0xff };
|
|
||||||
normalPalette.valueBackground = { 0x2e, 0x34, 0x36 };
|
|
||||||
normalPalette.knobActiveTrackColor = { 0x00, 0xb6, 0x2a };
|
|
||||||
normalPalette.knobInactiveTrackColor = { 0x30, 0x30, 0x30 };
|
|
||||||
normalPalette.knobLineIndicatorColor = { 0x00, 0x00, 0x00 };
|
|
||||||
Palette invertedPalette;
|
|
||||||
invertedPalette.boxBackground = { 0x2e, 0x34, 0x36 };
|
|
||||||
invertedPalette.text = { 0xff, 0xff, 0xff };
|
|
||||||
invertedPalette.inactiveText = { 0xb2, 0xb2, 0xb2 };
|
|
||||||
invertedPalette.highlightedText = { 0xfd, 0x98, 0x00 };
|
|
||||||
invertedPalette.titleBoxText = { 0x00, 0x00, 0x00 };
|
|
||||||
invertedPalette.titleBoxBackground = { 0xba, 0xbd, 0xb6 };
|
|
||||||
invertedPalette.icon = { 0xb2, 0xb2, 0xb2 };
|
|
||||||
invertedPalette.iconHighlight = { 0xfd, 0x98, 0x00 };
|
|
||||||
invertedPalette.valueText = { 0x00, 0x00, 0x00 };
|
|
||||||
invertedPalette.valueBackground = { 0x9a, 0x9a, 0x9a };
|
|
||||||
invertedPalette.knobActiveTrackColor = { 0x00, 0xb6, 0x2a };
|
|
||||||
invertedPalette.knobInactiveTrackColor = { 0x60, 0x60, 0x60 };
|
|
||||||
invertedPalette.knobLineIndicatorColor = { 0xff, 0xff, 0xff };
|
|
||||||
Palette& defaultPalette = normalPalette;
|
|
||||||
|
|
||||||
|
Palette& invertedPalette = theme->invertedPalette;
|
||||||
|
Palette& defaultPalette = theme->normalPalette;
|
||||||
Palette* palette = &defaultPalette;
|
Palette* palette = &defaultPalette;
|
||||||
auto enterPalette = [&palette](Palette& p) { palette = &p; };
|
auto enterPalette = [&palette](Palette& p) { palette = &p; };
|
||||||
|
|
||||||
|
|
@ -697,9 +663,9 @@ void Editor::Impl::createFrameContents()
|
||||||
};
|
};
|
||||||
auto createStyledKnob = [this, &palette](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int) {
|
auto createStyledKnob = [this, &palette](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int) {
|
||||||
SStyledKnob* knob = new SStyledKnob(bounds, this, tag);
|
SStyledKnob* knob = new SStyledKnob(bounds, this, tag);
|
||||||
knob->setActiveTrackColor(palette->knobActiveTrackColor);
|
knob->setActiveTrackColor(palette->knobActiveTrack);
|
||||||
knob->setInactiveTrackColor(palette->knobInactiveTrackColor);
|
knob->setInactiveTrackColor(palette->knobInactiveTrack);
|
||||||
knob->setLineIndicatorColor(palette->knobLineIndicatorColor);
|
knob->setLineIndicatorColor(palette->knobLineIndicator);
|
||||||
return knob;
|
return knob;
|
||||||
};
|
};
|
||||||
auto createValueLabel = [&palette](const CRect& bounds, int, const char* label, CHoriTxtAlign align, int fontsize) {
|
auto createValueLabel = [&palette](const CRect& bounds, int, const char* label, CHoriTxtAlign align, int fontsize) {
|
||||||
|
|
@ -781,6 +747,18 @@ void Editor::Impl::createFrameContents()
|
||||||
vm->setRoundRectRadius(5.0);
|
vm->setRoundRectRadius(5.0);
|
||||||
return vm;
|
return vm;
|
||||||
};
|
};
|
||||||
|
auto createOptionMenu = [this, &palette](const CRect& bounds, int tag, const char*, CHoriTxtAlign align, int fontsize) {
|
||||||
|
auto* cb = new COptionMenu(bounds, this, tag);
|
||||||
|
cb->setHoriAlign(align);
|
||||||
|
auto font = makeOwned<CFontDesc>("Roboto", fontsize);
|
||||||
|
cb->setFont(font);
|
||||||
|
cb->setFontColor(palette->valueText);
|
||||||
|
cb->setBackColor(palette->valueBackground);
|
||||||
|
cb->setFrameColor(CColor(0x00, 0x00, 0x00, 0x00));
|
||||||
|
cb->setStyle(CParamDisplay::kRoundRectStyle);
|
||||||
|
cb->setRoundRectRadius(5.0);
|
||||||
|
return cb;
|
||||||
|
};
|
||||||
auto createGlyphButton = [this, &palette](UTF8StringPtr glyph, const CRect& bounds, int tag, int fontsize) {
|
auto createGlyphButton = [this, &palette](UTF8StringPtr glyph, const CRect& bounds, int tag, int fontsize) {
|
||||||
STextButton* btn = new STextButton(bounds, this, tag, glyph);
|
STextButton* btn = new STextButton(bounds, this, tag, glyph);
|
||||||
btn->setFont(makeOwned<CFontDesc>("Sfizz Fluent System F20", fontsize));
|
btn->setFont(makeOwned<CFontDesc>("Sfizz Fluent System F20", fontsize));
|
||||||
|
|
@ -821,10 +799,12 @@ void Editor::Impl::createFrameContents()
|
||||||
btn->setFont(makeOwned<CFontDesc>("Sfizz Fluent System F20", fontsize));
|
btn->setFont(makeOwned<CFontDesc>("Sfizz Fluent System F20", fontsize));
|
||||||
return btn;
|
return btn;
|
||||||
};
|
};
|
||||||
auto createPiano = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int fontsize) {
|
auto createPiano = [&palette](const CRect& bounds, int, const char*, CHoriTxtAlign, int fontsize) {
|
||||||
SPiano* piano = new SPiano(bounds);
|
SPiano* piano = new SPiano(bounds);
|
||||||
auto font = makeOwned<CFontDesc>("Roboto", fontsize);
|
auto font = makeOwned<CFontDesc>("Roboto", fontsize);
|
||||||
piano->setFont(font);
|
piano->setFont(font);
|
||||||
|
piano->setFontColor(palette->text);
|
||||||
|
piano->setBackColor(palette->boxBackground);
|
||||||
return piano;
|
return piano;
|
||||||
};
|
};
|
||||||
auto createChevronDropDown = [this, &palette](const CRect& bounds, int, const char*, CHoriTxtAlign, int fontsize) {
|
auto createChevronDropDown = [this, &palette](const CRect& bounds, int, const char*, CHoriTxtAlign, int fontsize) {
|
||||||
|
|
@ -858,7 +838,7 @@ void Editor::Impl::createFrameContents()
|
||||||
box->setNameLabelFontColor(palette->text);
|
box->setNameLabelFontColor(palette->text);
|
||||||
box->setKnobFont(font);
|
box->setKnobFont(font);
|
||||||
box->setKnobFontColor(palette->text);
|
box->setKnobFontColor(palette->text);
|
||||||
box->setKnobLineIndicatorColor(palette->knobLineIndicatorColor);
|
box->setKnobLineIndicatorColor(palette->knobLineIndicator);
|
||||||
box->setValueToStringFunction([](float value, std::string& text) -> bool {
|
box->setValueToStringFunction([](float value, std::string& text) -> bool {
|
||||||
text = std::to_string(std::lround(value * 127));
|
text = std::to_string(std::lround(value * 127));
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -877,7 +857,7 @@ void Editor::Impl::createFrameContents()
|
||||||
|
|
||||||
#include "layout/main.hpp"
|
#include "layout/main.hpp"
|
||||||
|
|
||||||
mainView->setBackgroundColor(frameBackground);
|
mainView->setBackgroundColor(theme->frameBackground);
|
||||||
|
|
||||||
#if LINUX
|
#if LINUX
|
||||||
if (!isZenityAvailable()) {
|
if (!isZenityAvailable()) {
|
||||||
|
|
@ -1111,6 +1091,19 @@ void Editor::Impl::createFrameContents()
|
||||||
}
|
}
|
||||||
|
|
||||||
applyBackgroundForCurrentPanel();
|
applyBackgroundForCurrentPanel();
|
||||||
|
|
||||||
|
if (COptionMenu* menu = themeMenu_) {
|
||||||
|
const std::vector<std::string>& names = Theme::getAvailableNames();
|
||||||
|
size_t index = ~size_t(0);
|
||||||
|
for (size_t i = 0, n = names.size(); i < n; ++i) {
|
||||||
|
const std::string& name = names[i];
|
||||||
|
menu->addEntry(UTF8String(name));
|
||||||
|
if (name == currentThemeName_)
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
if (index != ~size_t(0))
|
||||||
|
menu->setCurrent(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::Impl::chooseSfzFile()
|
void Editor::Impl::chooseSfzFile()
|
||||||
|
|
@ -1847,6 +1840,14 @@ void Editor::Impl::valueChanged(CControl* ctl)
|
||||||
Call::later([this]() { aboutDialog_->setVisible(true); });
|
Call::later([this]() { aboutDialog_->setVisible(true); });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kTagThemeMenu:
|
||||||
|
{
|
||||||
|
currentThemeName_ = Theme::getAvailableNames()[int(value)];
|
||||||
|
Theme::storeCurrentName(currentThemeName_);
|
||||||
|
// TODO: live reload theme
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (tag >= kTagFirstChangePanel && tag <= kTagLastChangePanel) {
|
if (tag >= kTagFirstChangePanel && tag <= kTagLastChangePanel) {
|
||||||
int panelId = tag - kTagFirstChangePanel;
|
int panelId = tag - kTagFirstChangePanel;
|
||||||
|
|
|
||||||
164
plugins/editor/src/editor/Theme.cpp
Normal file
164
plugins/editor/src/editor/Theme.cpp
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||||
|
// license. You should have receive a LICENSE.md file along with the code.
|
||||||
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
|
#include "Theme.h"
|
||||||
|
#include "ColorHelpers.h"
|
||||||
|
#include "VSTGUIHelpers.h"
|
||||||
|
#include "plugin/SfizzSettings.h"
|
||||||
|
#include "sfizz/utility/StringViewHelpers.h"
|
||||||
|
#include <pugixml.hpp>
|
||||||
|
#include <ghc/fs_std.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void Theme::clear() {
|
||||||
|
frameBackground = {};
|
||||||
|
normalPalette = {};
|
||||||
|
invertedPalette = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Theme::load(const std::string& name)
|
||||||
|
{
|
||||||
|
fs::path resPath = getResourceBasePath();
|
||||||
|
fs::path themePath = resPath / "Themes" / fs::u8path(name) / "theme.xml";
|
||||||
|
|
||||||
|
pugi::xml_document doc;
|
||||||
|
pugi::xml_parse_result result = doc.load_file(themePath.c_str());
|
||||||
|
if (!result) {
|
||||||
|
std::cerr << "[sfizz] cannot load theme from " << resPath << '\n';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadDocument(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Theme::loadDocument(const pugi::xml_document& doc)
|
||||||
|
{
|
||||||
|
pugi::xml_node rootNode(doc.child("sfizz-theme"));
|
||||||
|
if (!rootNode) {
|
||||||
|
std::cerr << "[sfizz] trying to load an invalid theme\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
auto loadChildColorNodes = [this](pugi::xml_node topNode, bool inverted) {
|
||||||
|
for (pugi::xml_node colorNode : topNode.children("color")) {
|
||||||
|
absl::string_view name = colorNode.attribute("name").as_string();
|
||||||
|
CColor* slot = getColorFromName(name, inverted);
|
||||||
|
if (!slot) {
|
||||||
|
std::cerr << "[sfizz] color not recognized: " << name << "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*slot = {};
|
||||||
|
|
||||||
|
absl::string_view colorText = colorNode.text().as_string();
|
||||||
|
if (!colorFromHex(colorText, *slot))
|
||||||
|
std::cerr << "[sfizz] invalid color value: " << colorText << "\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
loadChildColorNodes(rootNode, false);
|
||||||
|
|
||||||
|
for (pugi::xml_node paletteNode : rootNode.children("palette")) {
|
||||||
|
absl::string_view paletteName = paletteNode.attribute("name").as_string();
|
||||||
|
|
||||||
|
bool inverted;
|
||||||
|
if (paletteName == "normal")
|
||||||
|
inverted = false;
|
||||||
|
else if (paletteName == "inverted")
|
||||||
|
inverted = true;
|
||||||
|
else {
|
||||||
|
std::cerr << "[sfizz] palette not recognized: " << paletteName << "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadChildColorNodes(paletteNode, inverted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Theme::storeCurrentName(absl::string_view name)
|
||||||
|
{
|
||||||
|
SfizzSettings settings;
|
||||||
|
settings.store("current_theme", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Theme::loadCurrentName()
|
||||||
|
{
|
||||||
|
SfizzSettings settings;
|
||||||
|
return settings.load_or("current_theme", "Default");
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string>& Theme::getAvailableNames()
|
||||||
|
{
|
||||||
|
static const std::vector<std::string> names = extractAvailableNames();
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> Theme::extractAvailableNames()
|
||||||
|
{
|
||||||
|
fs::path themesPath = getResourceBasePath() / "Themes";
|
||||||
|
|
||||||
|
std::error_code ec;
|
||||||
|
fs::directory_iterator it(themesPath, ec);
|
||||||
|
if (ec) {
|
||||||
|
std::cerr << "[sfizz] error reading the theme directory: " << ec.message() << '\n';
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> names;
|
||||||
|
for (; !ec && it != fs::directory_iterator(); it.increment(ec)) {
|
||||||
|
const fs::directory_entry& entry = *it;
|
||||||
|
if (entry.is_directory())
|
||||||
|
names.emplace_back(entry.path().filename().u8string());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(
|
||||||
|
names.begin(), names.end(),
|
||||||
|
[](const std::string& a, const std::string& b) -> bool {
|
||||||
|
return (a == "Default") ? true : (b == "Default") ? false : a < b;
|
||||||
|
});
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
CColor* Theme::getColorFromName(absl::string_view name, bool fromInvertedPalette)
|
||||||
|
{
|
||||||
|
CColor* c = nullptr;
|
||||||
|
switch (hash(name)) {
|
||||||
|
#define COLOR_CASE(X) \
|
||||||
|
case hash(#X): \
|
||||||
|
c = &X; \
|
||||||
|
break
|
||||||
|
#define PALETTE_COLOR_CASE(X) \
|
||||||
|
case hash(#X): \
|
||||||
|
c = fromInvertedPalette ? \
|
||||||
|
&invertedPalette.X : &normalPalette.X; \
|
||||||
|
break
|
||||||
|
|
||||||
|
COLOR_CASE(frameBackground);
|
||||||
|
PALETTE_COLOR_CASE(boxBackground);
|
||||||
|
PALETTE_COLOR_CASE(highlightedText);
|
||||||
|
PALETTE_COLOR_CASE(icon);
|
||||||
|
PALETTE_COLOR_CASE(iconHighlight);
|
||||||
|
PALETTE_COLOR_CASE(inactiveText);
|
||||||
|
PALETTE_COLOR_CASE(knobActiveTrack);
|
||||||
|
PALETTE_COLOR_CASE(knobInactiveTrack);
|
||||||
|
PALETTE_COLOR_CASE(knobLineIndicator);
|
||||||
|
PALETTE_COLOR_CASE(text);
|
||||||
|
PALETTE_COLOR_CASE(titleBoxBackground);
|
||||||
|
PALETTE_COLOR_CASE(titleBoxText);
|
||||||
|
PALETTE_COLOR_CASE(valueBackground);
|
||||||
|
PALETTE_COLOR_CASE(valueText);
|
||||||
|
|
||||||
|
#undef COLOR_CASE
|
||||||
|
#undef PALETTE_COLOR_CASE
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
51
plugins/editor/src/editor/Theme.h
Normal file
51
plugins/editor/src/editor/Theme.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||||
|
// license. You should have receive a LICENSE.md file along with the code.
|
||||||
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "utility/vstgui_before.h"
|
||||||
|
#include "vstgui/vstgui.h"
|
||||||
|
#include "utility/vstgui_after.h"
|
||||||
|
#include <absl/strings/string_view.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
namespace pugi { class xml_document; }
|
||||||
|
|
||||||
|
using namespace VSTGUI;
|
||||||
|
|
||||||
|
struct Palette {
|
||||||
|
CColor boxBackground;
|
||||||
|
CColor text;
|
||||||
|
CColor inactiveText;
|
||||||
|
CColor highlightedText;
|
||||||
|
CColor titleBoxText;
|
||||||
|
CColor titleBoxBackground;
|
||||||
|
CColor icon;
|
||||||
|
CColor iconHighlight;
|
||||||
|
CColor valueText;
|
||||||
|
CColor valueBackground;
|
||||||
|
CColor knobActiveTrack;
|
||||||
|
CColor knobInactiveTrack;
|
||||||
|
CColor knobLineIndicator;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Theme {
|
||||||
|
CColor frameBackground;
|
||||||
|
Palette normalPalette {};
|
||||||
|
Palette invertedPalette {};
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void load(const std::string& name);
|
||||||
|
void loadDocument(const pugi::xml_document& doc);
|
||||||
|
|
||||||
|
static void storeCurrentName(absl::string_view name);
|
||||||
|
static std::string loadCurrentName();
|
||||||
|
static const std::vector<std::string>& getAvailableNames();
|
||||||
|
|
||||||
|
CColor* getColorFromName(absl::string_view name, bool fromInvertedPalette);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::vector<std::string> extractAvailableNames();
|
||||||
|
};
|
||||||
|
|
@ -181,6 +181,12 @@ view__66->addView(view__69);
|
||||||
auto* const view__70 = createValueMenu(CRect(100, 60, 180, 85), kTagSetOscillatorQuality, "", kCenterText, 12);
|
auto* const view__70 = createValueMenu(CRect(100, 60, 180, 85), kTagSetOscillatorQuality, "", kCenterText, 12);
|
||||||
oscillatorQualitySlider_ = view__70;
|
oscillatorQualitySlider_ = view__70;
|
||||||
view__66->addView(view__70);
|
view__66->addView(view__70);
|
||||||
auto* const view__71 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12);
|
auto* const view__71 = createTitleGroup(CRect(35, 161, 140, 261), -1, "Theme", kCenterText, 12);
|
||||||
piano_ = view__71;
|
view__46->addView(view__71);
|
||||||
view__0->addView(view__71);
|
view__71->setVisible(false);
|
||||||
|
auto* const view__72 = createOptionMenu(CRect(20, 60, 85, 85), kTagThemeMenu, "", kCenterText, 12);
|
||||||
|
themeMenu_ = view__72;
|
||||||
|
view__71->addView(view__72);
|
||||||
|
auto* const view__73 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12);
|
||||||
|
piano_ = view__73;
|
||||||
|
view__0->addView(view__73);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue