High Contrast Styles Dialog Overhaul + New Design Implementation

This commit is contained in:
Arjun Taneja 2021-07-19 17:34:34 +05:30 committed by Arjun Taneja
parent 3f7e80f12d
commit b994272b4f
15 changed files with 200 additions and 44 deletions

View file

@ -57,10 +57,12 @@ PreferencesPage {
CheckBox {
id: highContrastEnable
width: 200
checked: appearanceModel.enableHighContrastChecked()
text: "Enable High-Contrast"
onClicked: {
checked = !checked
highContrastEnable.checked ? appearanceModel.loadLastUsedHighContrastTheme() : appearanceModel.loadLastUsedGeneralTheme()
}
}

View file

@ -42,7 +42,6 @@ void AppearancePreferencesModel::init()
{
uiConfiguration()->currentThemeChanged().onNotify(this, [this]() {
emit themesChanged();
emit backgroundColorChanged();
});
uiConfiguration()->fontChanged().onNotify(this, [this]() {
@ -94,19 +93,33 @@ QStringList AppearancePreferencesModel::accentColors() const
return uiConfiguration()->possibleAccentColors();
}
//void AppearancePreferencesModel::load()
//{
// uiConfiguration()->currentThemeChanged().onNotify(this, [this]() {
// emit themesChanged();
// });
//}
void AppearancePreferencesModel::resetThemeToDefault()
{
uiConfiguration()->resetCurrentThemeToDefault(currentTheme().codeKey);
notationConfiguration()->resetCurrentBackgroundColorToDefault();
emit backgroundColorChanged();
emit themesChanged();
}
bool AppearancePreferencesModel::enableHighContrastChecked()
{
if (isCurrentThemeHighContrast()) {
return true;
} else {
return false;
}
}
void AppearancePreferencesModel::loadLastUsedGeneralTheme()
{
uiConfiguration()->loadLastUsedGeneralTheme();
}
void AppearancePreferencesModel::loadLastUsedHighContrastTheme()
{
uiConfiguration()->loadLastUsedHighContrastTheme();
}
void AppearancePreferencesModel::setNewColor(const QColor& newColor, const QString& propertyName)
{
//! NOTE: Considered using a "switch()" statement here, but it would require a type conversion
@ -170,6 +183,17 @@ ThemeList AppearancePreferencesModel::allThemes() const
return uiConfiguration()->themes();
}
bool AppearancePreferencesModel::isCurrentThemeHighContrast() const
{
return uiConfiguration()->currentTheme().codeKey == HIGH_CONTRAST_BLACK_THEME_CODE
|| uiConfiguration()->currentTheme().codeKey == HIGH_CONTRAST_WHITE_THEME_CODE;
}
bool AppearancePreferencesModel::isCurrentThemeGeneral() const
{
return uiConfiguration()->currentTheme().codeKey == LIGHT_THEME_CODE || uiConfiguration()->currentTheme().codeKey == DARK_THEME_CODE;
}
int AppearancePreferencesModel::currentFontIndex() const
{
QString currentFont = QString::fromStdString(uiConfiguration()->fontFamily());
@ -217,20 +241,6 @@ void AppearancePreferencesModel::setCurrentThemeCode(const QString& themeCode)
return;
}
// ThemeList genThemes;
// for (const ThemeInfo& theme : allThemes()) {
// if (theme.codeKey == LIGHT_THEME_CODE || theme.codeKey == DARK_THEME_CODE) {
// genThemes.push_back(theme);
// }
// }
// for (const ThemeInfo& theme : genThemes) {
// if (themeCode == QString::fromStdString(theme.codeKey)) {
// uiConfiguration()->setCurrentTheme(theme.codeKey);
// }
// }
for (const ThemeInfo& theme : allThemes()) {
if (themeCode == QString::fromStdString(theme.codeKey)) {
uiConfiguration()->setCurrentTheme(theme.codeKey);

View file

@ -81,8 +81,10 @@ public:
QColor foregroundColor() const;
QString foregroundWallpaperPath() const;
//Q_INVOKABLE void load();
Q_INVOKABLE void resetThemeToDefault();
Q_INVOKABLE bool enableHighContrastChecked();
Q_INVOKABLE void loadLastUsedGeneralTheme();
Q_INVOKABLE void loadLastUsedHighContrastTheme();
Q_INVOKABLE void setNewColor(const QColor& newColor, const QString& propertyName);
Q_INVOKABLE QStringList allFonts() const;
Q_INVOKABLE QString wallpaperPathFilter() const;
@ -114,6 +116,8 @@ signals:
private:
ui::ThemeInfo currentTheme() const;
ui::ThemeList allThemes() const;
bool isCurrentThemeHighContrast() const;
bool isCurrentThemeGeneral() const;
};
}

View file

@ -37,6 +37,8 @@ using namespace mu::framework;
using namespace mu::async;
static const Settings::Key UI_THEMES_KEY("ui", "ui/application/themes");
static const Settings::Key UI_PREVIOUS_GENERAL_THEME("ui", "ui/application/previousGeneralTheme");
static const Settings::Key UI_PREVIOUS_HIGH_CONTRAST_THEME("ui", "ui/application/previousHighContrastTheme");
static const Settings::Key UI_CURRENT_THEME_CODE_KEY("ui", "ui/application/currentThemeCode");
static const Settings::Key UI_FONT_FAMILY_KEY("ui", "ui/theme/fontFamily");
static const Settings::Key UI_FONT_SIZE_KEY("ui", "ui/theme/fontSize");
@ -104,19 +106,19 @@ static const QMap<ThemeStyleKey, QVariant> HIGH_CONTRAST_BLACK_THEME_VALUES {
{ ACCENT_COLOR, "#0071DA" },
{ STROKE_COLOR, "#FFFFFF" },
{ BUTTON_COLOR, "#000000" },
{ BORDER_WIDTH, 5.0 },
{ BORDER_WIDTH, 1.0 },
{ FONT_PRIMARY_COLOR, "#FFFD38" },
{ FONT_SECONDARY_COLOR, "#BDBDBD" },
{ LINK_COLOR, "#70AFEA" },
{ FOCUS_COLOR, "#75507b" },
{ ACCENT_OPACITY_NORMAL, 0.3 },
{ ACCENT_OPACITY_HOVER, 0.15 },
{ ACCENT_OPACITY_NORMAL, 0.8 },
{ ACCENT_OPACITY_HOVER, 1.0 },
{ ACCENT_OPACITY_HIT, 0.5 },
{ BUTTON_OPACITY_NORMAL, 0.7 },
{ BUTTON_OPACITY_HOVER, 0.5 },
{ BUTTON_OPACITY_HIT, 1.0 },
{ BUTTON_OPACITY_HOVER, 1.0 },
{ BUTTON_OPACITY_HIT, 0.5 },
{ ITEM_OPACITY_DISABLED, 0.3 }
};
@ -129,7 +131,7 @@ static const QMap<ThemeStyleKey, QVariant> HIGH_CONTRAST_WHITE_THEME_VALUES {
{ ACCENT_COLOR, "#00D87D" },
{ STROKE_COLOR, "#000000" },
{ BUTTON_COLOR, "#FFFFFF" },
{ BORDER_WIDTH, 5.0 },
{ BORDER_WIDTH, 1.0 },
{ FONT_PRIMARY_COLOR, "#1E0073" },
{ FONT_SECONDARY_COLOR, "#000000" },
{ LINK_COLOR, "#70AFEA" },
@ -149,6 +151,8 @@ static const QMap<ThemeStyleKey, QVariant> HIGH_CONTRAST_WHITE_THEME_VALUES {
void UiConfiguration::init()
{
settings()->setDefaultValue(UI_CURRENT_THEME_CODE_KEY, Val(LIGHT_THEME_CODE));
settings()->setDefaultValue(UI_PREVIOUS_GENERAL_THEME, Val(LIGHT_THEME_CODE));
settings()->setDefaultValue(UI_PREVIOUS_HIGH_CONTRAST_THEME, Val(HIGH_CONTRAST_BLACK_THEME_CODE));
settings()->setDefaultValue(UI_FONT_FAMILY_KEY, Val("Fira Sans"));
settings()->setDefaultValue(UI_FONT_SIZE_KEY, Val(12));
settings()->setDefaultValue(UI_ICONS_FONT_FAMILY_KEY, Val("MusescoreIcon"));
@ -417,8 +421,24 @@ ThemeCode UiConfiguration::currentThemeCodeKey() const
return preferredThemeCode.empty() ? LIGHT_THEME_CODE : preferredThemeCode;
}
bool UiConfiguration::isCurrentThemeHighContrast() const
{
return currentThemeCodeKey() == HIGH_CONTRAST_BLACK_THEME_CODE || currentThemeCodeKey() == HIGH_CONTRAST_WHITE_THEME_CODE;
}
bool UiConfiguration::isCurrentThemeGeneral() const
{
return currentThemeCodeKey() == LIGHT_THEME_CODE || currentThemeCodeKey() == DARK_THEME_CODE;
}
void UiConfiguration::setCurrentTheme(const ThemeCode& codeKey)
{
if (isCurrentThemeGeneral()) {
settings()->setSharedValue(UI_PREVIOUS_GENERAL_THEME, Val(currentThemeCodeKey()));
} else {
settings()->setSharedValue(UI_PREVIOUS_HIGH_CONTRAST_THEME, Val(currentThemeCodeKey()));
}
settings()->setSharedValue(UI_CURRENT_THEME_CODE_KEY, Val(codeKey));
}
@ -446,6 +466,16 @@ Notification UiConfiguration::currentThemeChanged() const
return m_currentThemeChanged;
}
void UiConfiguration::loadLastUsedGeneralTheme()
{
setCurrentTheme(settings()->value(UI_PREVIOUS_GENERAL_THEME).toQString().QString::toStdString());
}
void UiConfiguration::loadLastUsedHighContrastTheme()
{
setCurrentTheme(settings()->value(UI_PREVIOUS_HIGH_CONTRAST_THEME).toQString().QString::toStdString());
}
std::string UiConfiguration::fontFamily() const
{
return settings()->value(UI_FONT_FAMILY_KEY).toString();

View file

@ -53,6 +53,8 @@ public:
const ThemeInfo& currentTheme() const override;
void setCurrentTheme(const ThemeCode& codeKey) override;
void setCurrentThemeStyleValue(ThemeStyleKey key, const Val& val) override;
void loadLastUsedGeneralTheme() override;
void loadLastUsedHighContrastTheme() override;
async::Notification currentThemeChanged() const override;
std::string fontFamily() const override;
@ -99,6 +101,8 @@ private:
void updateCurrentTheme();
void updateThemes();
bool isCurrentThemeHighContrast() const;
bool isCurrentThemeGeneral() const;
ThemeCode currentThemeCodeKey() const;
ThemeInfo makeStandardTheme(const ThemeCode& codeKey) const;

View file

@ -51,6 +51,8 @@ public:
virtual const ThemeInfo& currentTheme() const = 0;
virtual void setCurrentTheme(const ThemeCode& codeKey) = 0;
virtual void setCurrentThemeStyleValue(ThemeStyleKey key, const Val& val) = 0;
virtual void loadLastUsedGeneralTheme() = 0;
virtual void loadLastUsedHighContrastTheme() = 0;
virtual async::Notification currentThemeChanged() const = 0;
virtual std::string fontFamily() const = 0;

View file

@ -43,7 +43,7 @@ static const QBrush NO_FILL(Qt::transparent);
static const int GROUP_BOX_LABEL_SPACING = 2;
//! NOTE In QML, a border is drawn _inside_ a rectangle.
//! NOTE In QML, a border is drawn _inside_ a rectangle.
//! In C++, a border would normally be drawn half inside the rectangle, half outside.
//! In this function, we exactly replicate the behaviour from QML.
static void drawRoundedRect(QPainter* painter, const QRectF& rect, const qreal radius, const QBrush& brush = NO_FILL,
@ -428,6 +428,17 @@ void UiTheme::notifyAboutThemeChanged()
emit themeChanged();
}
bool UiTheme::isCurrentThemeHighContrast() const
{
return configuration()->currentTheme().codeKey == HIGH_CONTRAST_BLACK_THEME_CODE
|| configuration()->currentTheme().codeKey == HIGH_CONTRAST_WHITE_THEME_CODE;
}
bool UiTheme::isCurrentThemeGeneral() const
{
return configuration()->currentTheme().codeKey == LIGHT_THEME_CODE || configuration()->currentTheme().codeKey == DARK_THEME_CODE;
}
// ====================================================
// QStyle
// ====================================================
@ -516,7 +527,7 @@ void UiTheme::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption
// GroupBox
case QStyle::PE_FrameGroupBox: {
drawRoundedRect(painter, option->rect, 3, QBrush("#03000000"), QPen(strokeColor(), 1));
drawRoundedRect(painter, option->rect, 3, QBrush("#03000000"), QPen(strokeColor(), borderWidth()));
} break;
// Menu
@ -524,7 +535,7 @@ void UiTheme::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption
drawRoundedRect(painter, option->rect, 3, backgroundPrimaryColor());
} break;
case QStyle::PE_FrameMenu: {
drawRoundedRect(painter, option->rect, 3, NO_FILL, QPen(strokeColor(), 1));
drawRoundedRect(painter, option->rect, 3, NO_FILL, QPen(strokeColor(), borderWidth()));
} break;
default:
@ -535,6 +546,46 @@ void UiTheme::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption
painter->restore();
}
void UiTheme::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const
{
const bool enabled = option->state & State_Enabled;
const bool hovered = option->state & State_MouseOver;
const bool pressed = option->state & State_Sunken;
switch (control) {
case CC_ScrollBar: {
QProxyStyle::drawComplexControl(control, option, painter, widget);
QRect scrollBarHandle = QProxyStyle::subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
if (isCurrentThemeHighContrast()) {
QColor handleColor = fontPrimaryColor();
handleColor.setAlphaF(
!enabled ? buttonOpacityNormal()
* itemOpacityDisabled() : pressed ? buttonOpacityHit() : hovered ? buttonOpacityHover() : buttonOpacityNormal());
drawRoundedRect(painter, option->rect, 1, NO_FILL, QPen(strokeColor(), borderWidth()));
drawRoundedRect(painter, scrollBarHandle, 1, handleColor, NO_BORDER);
}
} break;
case CC_SpinBox: {
QProxyStyle::drawComplexControl(control, option, painter, widget);
if (enabled) {
QRect spinBoxFrame = QProxyStyle::subControlRect(CC_SpinBox, option, SC_SpinBoxFrame, widget);
QColor penBorderColor(strokeColor());
penBorderColor.setAlphaF(pressed ? buttonOpacityHit() : hovered ? buttonOpacityHover() : buttonOpacityNormal());
drawRoundedRect(painter, spinBoxFrame, 3, NO_FILL, QPen(penBorderColor, borderWidth()));
}
} break;
default: QProxyStyle::drawComplexControl(control, option, painter, widget);
}
}
QRect UiTheme::subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex* option, QStyle::SubControl subControl,
const QWidget* widget) const
{
@ -711,8 +762,18 @@ void UiTheme::drawButtonBackground(QPainter* painter, const QRect& rect, bool en
: !flat ? buttonOpacityNormal()
: 0);
//drawRoundedRect(painter, rect, 3, backgroundColor);
drawRoundedRect(painter, rect, 3, backgroundColor, QPen(strokeColor(), borderWidth()));
if (enabled) {
if (isCurrentThemeHighContrast()) {
QColor penBorderColor(strokeColor());
penBorderColor.setAlphaF(pressed ? buttonOpacityHit() : hovered ? buttonOpacityHover() : buttonOpacityNormal());
drawRoundedRect(painter, rect, 3, backgroundColor, QPen(penBorderColor, borderWidth()));
} else {
drawRoundedRect(painter, rect, 3, backgroundColor, NO_BORDER);
}
} else {
drawRoundedRect(painter, rect, 3, backgroundColor, NO_BORDER);
}
}
void UiTheme::drawCheckboxIndicator(QPainter* painter, const QRect& rect, bool enabled, bool hovered, bool pressed, bool checked,
@ -725,14 +786,21 @@ void UiTheme::drawCheckboxIndicator(QPainter* painter, const QRect& rect, bool e
: hovered ? buttonOpacityHover()
: buttonOpacityNormal());
QColor borderColor = enabled && (hovered || pressed) ? strokeColor() : Qt::transparent;
borderColor.setAlphaF(enabled && pressed ? buttonOpacityHit()
: enabled && hovered ? buttonOpacityHover()
: 0);
if (isCurrentThemeGeneral()) {
QColor penBorderColor;
penBorderColor.setAlphaF(pressed ? buttonOpacityHit() : hovered ? buttonOpacityHover() : buttonOpacityNormal());
//const int borderWidth = enabled && (hovered || pressed) ? 1 : 0;
//drawRoundedRect(painter, rect, 2, backgroundColor, QPen(borderColor, borderWidth));
drawRoundedRect(painter, rect, 2, backgroundColor, QPen(strokeColor(), borderWidth()));
const int penBorderWidth = enabled && (hovered || pressed) ? borderWidth() : 0;
drawRoundedRect(painter, rect, 2, backgroundColor, QPen(penBorderColor, penBorderWidth));
} else {
QColor penBorderColor = strokeColor();
penBorderColor.setAlphaF(pressed ? buttonOpacityHit() : hovered ? buttonOpacityHover() : buttonOpacityNormal());
const int penBorderWidth = enabled ? borderWidth() : 0;
drawRoundedRect(painter, rect, 2, backgroundColor, QPen(penBorderColor, penBorderWidth));
}
}
if (checked || indeterminate) {
@ -804,6 +872,7 @@ void UiTheme::drawIndicatorIcon(QPainter* painter, const QRect& rect, bool enabl
}
painter->drawText(rect, Qt::AlignCenter, iconCodeToChar(code));
drawRoundedRect(painter, rect, 1, NO_FILL, QPen(strokeColor(), borderWidth())); //does nothing apparently
}
void UiTheme::drawListViewItemBackground(QPainter* painter, const QRect& rect, bool enabled, bool hovered, bool pressed,
@ -824,6 +893,10 @@ void UiTheme::drawListViewItemBackground(QPainter* painter, const QRect& rect, b
}
painter->fillRect(rect, backgroundColor);
if (isCurrentThemeHighContrast()) {
drawRoundedRect(painter, rect, 1, NO_FILL, QPen(strokeColor(), borderWidth()));
}
}
void UiTheme::drawToolbarGrip(QPainter* painter, const QRect& rect, bool horizontal) const

View file

@ -122,6 +122,8 @@ public:
void unpolish(QWidget* widget) override;
void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override;
void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter,
const QWidget* widget = nullptr) const override;
QRect subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex* option, QStyle::SubControl subControl,
const QWidget* widget = nullptr) const override;
int pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const override;
@ -148,6 +150,9 @@ private:
void notifyAboutThemeChanged();
bool isCurrentThemeHighContrast() const;
bool isCurrentThemeGeneral() const;
void drawButtonBackground(QPainter* painter, const QRect& rect, bool enabled, bool hovered, bool pressed, bool accentButton,
bool flat) const;
void drawCheckboxIndicator(QPainter* painter, const QRect& rect, bool enabled, bool hovered, bool pressed, bool checked,

View file

@ -73,7 +73,7 @@ FocusScope {
height: 20
width: 20
border.width: ui.theme.borderWidth > 0 ? 1 : ui.theme.borderWidth
border.width: ui.theme.borderWidth
border.color: ui.theme.strokeColor
color: ui.theme.buttonColor

View file

@ -101,7 +101,7 @@ FocusScope {
color: ui.theme.textFieldColor
radius: 4
border.color: navCtrl.active ? ui.theme.focusColor : ui.theme.strokeColor
border.width: navCtrl.active ? 2 : 1
border.width: navCtrl.active ? 2 : ui.theme.borderWidth
}
RowLayout {

View file

@ -41,6 +41,7 @@ public:
virtual QColor backgroundColor() const = 0;
virtual void setBackgroundColor(const QColor& color) = 0;
virtual void resetCurrentBackgroundColorToDefault() = 0;
virtual io::path backgroundWallpaperPath() const = 0;
virtual void setBackgroundWallpaperPath(const io::path& path) = 0;

View file

@ -109,6 +109,11 @@ void NotationConfiguration::init()
// m_backgroundChanged.notify();
// });
uiConfiguration()->currentThemeChanged().onNotify(this, [this]()
{
m_backgroundChanged.notify();
});
settings()->setDefaultValue(LIGHT_SCORE_BACKGROUND_COLOR, Val(QColor("#385f94")));
settings()->valueChanged(LIGHT_SCORE_BACKGROUND_COLOR).onReceive(nullptr, [this](const Val&) {
m_backgroundChanged.notify();
@ -259,6 +264,19 @@ void NotationConfiguration::setBackgroundColor(const QColor& color)
}
}
void NotationConfiguration::resetCurrentBackgroundColorToDefault()
{
if (uiConfiguration()->currentTheme().codeKey == LIGHT_THEME_CODE) {
settings()->setSharedValue(LIGHT_SCORE_BACKGROUND_COLOR, settings()->defaultValue(LIGHT_SCORE_BACKGROUND_COLOR));
} else if (uiConfiguration()->currentTheme().codeKey == DARK_THEME_CODE) {
settings()->setSharedValue(DARK_SCORE_BACKGROUND_COLOR, settings()->defaultValue(DARK_SCORE_BACKGROUND_COLOR));
} else if (uiConfiguration()->currentTheme().codeKey == HIGH_CONTRAST_BLACK_THEME_CODE) {
settings()->setSharedValue(HC_BLACK_SCORE_BACKGROUND_COLOR, settings()->defaultValue(HC_BLACK_SCORE_BACKGROUND_COLOR));
} else {
settings()->setSharedValue(HC_WHITE_SCORE_BACKGROUND_COLOR, settings()->defaultValue(HC_WHITE_SCORE_BACKGROUND_COLOR));
}
}
io::path NotationConfiguration::backgroundWallpaperPath() const
{
return settings()->value(BACKGROUND_WALLPAPER_PATH).toString();

View file

@ -46,6 +46,7 @@ public:
QColor backgroundColor() const override;
void setBackgroundColor(const QColor& color) override;
void resetCurrentBackgroundColorToDefault() override;
io::path backgroundWallpaperPath() const override;
void setBackgroundWallpaperPath(const io::path& path) override;

View file

@ -392,6 +392,12 @@ void NotationPaintView::paintBackground(const RectF& rect, draw::Painter* painte
{
QString wallpaperPath = configuration()->backgroundWallpaperPath().toQString();
qDebug("NotationPaintView::paintBackground ACCESSED!");
qDebug("NotationPaintView::paintBackground ACCESSED!");
qDebug("NotationPaintView::paintBackground ACCESSED!");
qDebug("NotationPaintView::paintBackground ACCESSED!");
qDebug("NotationPaintView::paintBackground ACCESSED!");
if (configuration()->backgroundUseColor() || wallpaperPath.isEmpty()) {
painter->fillRect(rect, configuration()->backgroundColor());
} else {

View file

@ -46,7 +46,7 @@ GridView {
width: root.cellWidth
itemBorderColor: ui.theme.strokeColor
itemBorderWidth: ui.theme.borderWidth > 0 ? 1 : ui.theme.borderWidth
itemBorderWidth: ui.theme.borderWidth
radius: 3
isSelected: modelData.titleMajor === currentSignature.titleMajor