refactor(settings): take colours from the colour provider

main
reionwong 2 weeks ago
parent 6966c10a52
commit 2c9367c84c

@ -36,6 +36,7 @@ endforeach()
# registration, which a linker would drop from an archive.
add_library(settings-ui OBJECT
src/widgets/card.cpp
src/widgets/colors.cpp
src/widgets/formdialog.cpp
src/widgets/iconbutton.cpp
src/widgets/imageselectionitem.cpp

@ -11,6 +11,7 @@
#include <unicode/utf16.h>
#include "ui/animation.h"
#include "ui/color_provider.h"
#include "ui/icon.h"
#include "ui/image_view.h"
#include "ui/label.h"
@ -19,6 +20,7 @@
#include "ui/painter.h"
#include "ui/theme.h"
#include "ui/window.h"
#include "widgets/colors.h"
#include "widgets/metrics.h"
#include "widgets/standardbutton.h"
@ -53,18 +55,17 @@ public:
protected:
void paint(Painter& painter) override
{
const Theme& theme = Theme::current();
const Rect box = painter.deviceRect(localRect());
const int icon = int(std::lround(m_iconSize * painter.scale()));
if (isEnabled() && (m_hovered || m_pressed)) {
const double alpha = m_pressed ? (theme.darkMode ? 0.06 : 0.21) : (theme.darkMode ? 0.12 : 0.11);
const int margin = int(std::lround(std::round(m_size * 0.1) * painter.scale()));
int plate = std::min(box.width, box.height) - 2 * margin;
if ((plate - icon) % 2 != 0)
plate -= 1;
painter.fillDeviceRoundedRect({box.x + (box.width - plate) / 2, box.y + (box.height - plate) / 2, plate,
plate},
plate / 2.0, theme.text.withAlpha(alpha));
plate / 2.0,
color(m_pressed ? ColorId::RoundButtonPressed : ColorId::RoundButtonHovered));
}
}
@ -357,8 +358,7 @@ UserCard::~UserCard() = default;
void UserCard::layout()
{
const Theme& theme = Theme::current();
const Color background = theme.darkMode ? Color::rgb(0x363636) : theme.background;
const Color background = color(SettingsColor::UserCardButtonBackground);
m_password->setBackgroundColor(background);
m_delete->setBackgroundColor(background);
Card::layout();

@ -12,11 +12,13 @@
#include "base/locale.h"
#include "pages/battery/timeformat.h"
#include "ui/animation.h"
#include "ui/color_provider.h"
#include "ui/label.h"
#include "ui/painter.h"
#include "ui/cell_layout.h"
#include "ui/theme.h"
#include "ui/window.h"
#include "widgets/colors.h"
#include "widgets/metrics.h"
using namespace cutefish;
@ -208,11 +210,9 @@ protected:
void paint(Painter& painter) override
{
const Theme& theme = Theme::current();
const RectF rect = localRect();
painter.drawRoundedRect(rect, {.radius = rect.height / 2},
theme.darkMode ? theme.alternateBackground : theme.background, 1 / painter.scale(),
tint(theme.text, theme.darkMode ? 0.1 : 0.08));
painter.drawRoundedRect(rect, {.radius = rect.height / 2}, color(SettingsColor::BatteryChipBackground),
1 / painter.scale(), color(SettingsColor::BatteryChipBorder));
}
private:
@ -593,8 +593,8 @@ void HistoryGraph::paint(Painter& painter)
const Theme& theme = Theme::current();
const double scale = painter.scale();
const double hairline = 1 / scale;
const Color gridColor = theme.darkMode ? tint(Color::rgb(0xFFFFFF), 0.08) : tint(Color::rgb(0), 0.06);
const Color baselineColor = theme.darkMode ? tint(Color::rgb(0xFFFFFF), 0.18) : tint(Color::rgb(0), 0.14);
const Color gridColor = color(SettingsColor::GraphGrid);
const Color baselineColor = color(SettingsColor::GraphBaseline);
painter.save();
painter.translate({m_plot.x, m_plot.y});
@ -632,7 +632,7 @@ void HistoryGraph::paint(Painter& painter)
painter.restore();
if (m_probe && m_reveal >= 1) {
const Color probeColor = theme.darkMode ? tint(Color::rgb(0xFFFFFF), 0.28) : tint(Color::rgb(0), 0.2);
const Color probeColor = color(SettingsColor::GraphProbe);
const double top = m_headerHeight - m_plot.y;
painter.drawRoundedRect({m_probe->x - hairline / 2, top, hairline, m_plot.height - top}, {}, probeColor);

@ -9,6 +9,7 @@
#include "base/event_loop.h"
#include "ui/animation.h"
#include "ui/color_provider.h"
#include "ui/dialog_window.h"
#include "ui/icon.h"
#include "ui/keys.h"
@ -23,6 +24,7 @@
#include "ui/window.h"
#include "ui/window_header.h"
#include "widgets/card.h"
#include "widgets/colors.h"
#include "widgets/metrics.h"
#include "widgets/picture.h"
#include "window/settingswindow.h"
@ -207,6 +209,17 @@ public:
bool current = false;
std::function<void(int index)> onPicked;
void setCurrent(bool isCurrent)
{
if (isCurrent == current)
return;
current = isCurrent;
// The labels take their colours from it as they lay out.
for (StyledLabel* label : {m_name, m_region, m_time, m_detail})
label->requestLayout();
requestPaint();
}
SizeF sizeHint() const override { return {0, kResultHeight}; }
bool acceptsPointer() const override { return true; }
@ -282,9 +295,7 @@ public:
m_current = index;
for (const auto& child : m_rows->children()) {
auto* row = static_cast<ResultRow*>(child.get());
row->current = row->index == index;
row->requestLayout();
row->requestPaint();
row->setCurrent(row->index == index);
}
if (index >= 0)
m_scroll->ensureVisible({0, index * kResultHeight, 1, kResultHeight});
@ -502,8 +513,7 @@ protected:
painter.multiplyOpacity(0.8);
painter.strokeRoundedRect(ring, 6, theme.highlight, painter.borderWidth(2));
painter.restore();
const Color pill = theme.darkMode ? Color::rgb(0x000000).withAlpha(0.6) : Color::rgb(0xFFFFFF).withAlpha(0.9);
painter.fillRoundedRect(m_pill, m_pill.height / 2, pill, panelCorners());
painter.fillRoundedRect(m_pill, m_pill.height / 2, color(SettingsColor::TimeZoneMapPill), panelCorners());
}
private:
@ -740,8 +750,8 @@ protected:
void paint(Painter& painter) override
{
const Theme& theme = Theme::current();
const Color fill = theme.darkMode ? Color::rgb(0xFFFFFF).withAlpha(0.04) : Color::rgb(0x000000).withAlpha(0.03);
painter.fillRoundedRect(localRect(), theme.bigRadius, fill, panelCorners());
painter.fillRoundedRect(localRect(), theme.bigRadius, color(SettingsColor::TimeZoneMapBackground),
panelCorners());
}
};
@ -871,6 +881,10 @@ protected:
{
m_header->setGeometry({0, 0, geometry().width, kHeaderHeight});
m_column->setGeometry(localRect());
}
void childrenLaidOut() override
{
// Wider than the field: each result carries a time and a day.
const RectF field = search->geometry();
const PointF band = m_band->geometry().topLeft();

@ -8,6 +8,7 @@
#include <cmath>
#include "pages/language/language.h"
#include "ui/color_provider.h"
#include "ui/keys.h"
#include "ui/label.h"
#include "ui/layout.h"
@ -17,6 +18,7 @@
#include "ui/scroll_view.h"
#include "ui/theme.h"
#include "ui/window.h"
#include "widgets/colors.h"
#include "widgets/metrics.h"
using namespace cutefish;
@ -69,9 +71,8 @@ protected:
void paint(Painter& painter) override
{
const Theme& theme = Theme::current();
const RectF rect = localRect();
painter.fillRoundedRect(rect, rect.height / 2, theme.highlight.withAlpha(theme.darkMode ? 0.2 : 0.12));
painter.fillRoundedRect(rect, rect.height / 2, color(SettingsColor::PreferredLanguageTag));
}
private:
@ -212,8 +213,7 @@ protected:
if (m_last)
return;
// One device pixel at any scale.
const Theme& theme = Theme::current();
const Color line = theme.disabledText.withAlpha(theme.darkMode ? 0.3 : 0.1);
const Color line = color(ColorId::Separator);
painter.drawHorizontalLine(0, geometry().height - 1 / painter.scale(), geometry().width, line);
}

@ -5,6 +5,7 @@
#include "pages/network/proxy/proxysettings.h"
#include "ui/button.h"
#include "ui/check_box.h"
#include "ui/color_provider.h"
#include "ui/file_chooser.h"
#include "ui/label.h"
#include "ui/layout.h"
@ -13,6 +14,7 @@
#include "ui/text_field.h"
#include "ui/theme.h"
#include "widgets/card.h"
#include "widgets/colors.h"
#include "widgets/metrics.h"
#include "window/page.h"
#include "window/pagelist.h"
@ -37,11 +39,10 @@ public:
protected:
void paint(Painter& painter) override
{
const Theme& theme = Theme::current();
// FishUI's Separator: a RoundedRectangle one device pixel high, centred.
const double height = 1 / painter.scale();
painter.drawRoundedRect({0, rounding::centeredStart(geometry().height, height), geometry().width, height}, {},
theme.disabledText.withAlpha(theme.darkMode ? 0.3 : 0.1));
color(ColorId::Separator));
}
};

@ -3,10 +3,12 @@
#include "pages/shortcuts/shortcutkeys.h"
#include "ui/color_provider.h"
#include "ui/label.h"
#include "ui/painter.h"
#include "ui/cell_layout.h"
#include "ui/theme.h"
#include "widgets/colors.h"
#include "widgets/metrics.h"
using namespace cutefish::ui;
@ -93,8 +95,7 @@ void ShortcutKeys::layout()
void ShortcutKeys::paint(Painter& painter)
{
const Theme& theme = Theme::current();
const Color cap = theme.darkMode ? theme.secondBackground.lighter(1.6) : theme.secondBackground.darker(1.08);
const Color cap = color(SettingsColor::KeyCap);
for (const Part& part : m_parts) {
painter.save();
painter.multiplyOpacity(m_dimmed ? 0.5 : 1);

@ -7,6 +7,7 @@
#include <cctype>
#include <cmath>
#include "ui/color_provider.h"
#include "ui/icon.h"
#include "ui/image_view.h"
#include "ui/keys.h"
@ -15,6 +16,7 @@
#include "ui/cell_layout.h"
#include "ui/theme.h"
#include "ui/window.h"
#include "widgets/colors.h"
#include "widgets/metrics.h"
using namespace cutefish::ui;
@ -367,7 +369,7 @@ protected:
m_addLabel->setGeometry({left, top + kPlusSize + metrics::xs, label.width, label.height});
return;
}
m_placeholder->setColor(theme.darkMode ? Color::rgb(0xFFFFFF) : Color::rgb(0xC8CAD5));
m_placeholder->setColor(color(SettingsColor::WallpaperPlaceholder));
m_placeholder->setGeometry({rounding::centeredStart(geometry().width, 32),
rounding::centeredStart(geometry().height, 32), 32, 32});
m_image->setCornerRadius(theme.bigRadius, themeCorners());

@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: 2026 Reion Wong <reionwong@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "widgets/colors.h"
#include "ui/theme.h"
using namespace cutefish::ui;
namespace settings {
static constexpr Color kWhite = Color::rgb(0xFFFFFF);
static constexpr Color kBlack = Color::rgb(0x000000);
void addSettingsColors(ColorMixer& mixer, const Theme& theme)
{
const bool dark = theme.darkMode;
mixer[SettingsColor::SidebarBackground] =
withAlpha(dark ? lighter(ColorId::Background, 1.5) : darker(ColorId::Background, 1.05), 0.7);
mixer[SettingsColor::SidebarItemCurrent] = withAlpha(ColorId::Text, dark ? 0.1 : 0.05);
mixer[SettingsColor::RowHighlight] = withAlpha(ColorId::Text, dark ? 0.05 : 0.15);
mixer[SettingsColor::RowComboBoxHovered] = withAlpha(ColorId::Text, dark ? 0.08 : 0.06);
mixer[SettingsColor::RowComboBoxOpen] = withAlpha(ColorId::Text, dark ? 0.12 : 0.1);
mixer[SettingsColor::StandardButtonBackground] = dark ? Color::rgb(0x363636) : kWhite;
mixer[SettingsColor::UserCardButtonBackground] = dark ? ColorRecipe(Color::rgb(0x363636))
: ColorRecipe(ColorId::Background);
mixer[SettingsColor::KeyCap] = dark ? lighter(ColorId::SecondBackground, 1.6)
: darker(ColorId::SecondBackground, 1.08);
mixer[SettingsColor::PreferredLanguageTag] = withAlpha(ColorId::Highlight, dark ? 0.2 : 0.12);
mixer[SettingsColor::WallpaperPlaceholder] = dark ? kWhite : Color::rgb(0xC8CAD5);
mixer[SettingsColor::TimeZoneMapBackground] = dark ? kWhite.withAlpha(0.04) : kBlack.withAlpha(0.03);
mixer[SettingsColor::TimeZoneMapPill] = dark ? kBlack.withAlpha(0.6) : kWhite.withAlpha(0.9);
mixer[SettingsColor::BatteryChipBackground] = dark ? ColorId::AlternateBackground : ColorId::Background;
mixer[SettingsColor::BatteryChipBorder] = withAlpha(ColorId::Text, dark ? 0.1 : 0.08);
mixer[SettingsColor::GraphGrid] = dark ? kWhite.withAlpha(0.08) : kBlack.withAlpha(0.06);
mixer[SettingsColor::GraphBaseline] = dark ? kWhite.withAlpha(0.18) : kBlack.withAlpha(0.14);
mixer[SettingsColor::GraphProbe] = dark ? kWhite.withAlpha(0.28) : kBlack.withAlpha(0.2);
}
} // namespace settings

@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: 2026 Reion Wong <reionwong@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <cstdint>
#include "ui/color_provider.h"
namespace settings {
// Settings' own colours, after the toolkit's; colors.cpp gives them for
// each theme. Retune the look there rather than at the use sites.
enum class SettingsColor : uint16_t {
SidebarBackground = uint16_t(cutefish::ui::ColorId::ApplicationFirst),
SidebarItemCurrent,
RowHighlight,
RowComboBoxHovered,
RowComboBoxOpen,
StandardButtonBackground,
UserCardButtonBackground,
KeyCap,
PreferredLanguageTag,
WallpaperPlaceholder,
TimeZoneMapBackground,
TimeZoneMapPill,
BatteryChipBackground,
BatteryChipBorder,
GraphGrid,
GraphBaseline,
GraphProbe,
};
void addSettingsColors(cutefish::ui::ColorMixer& mixer, const cutefish::ui::Theme& theme);
// Added before main by every program that names one of the colours.
[[maybe_unused]] inline const bool settingsColorsAdded =
(cutefish::ui::ColorProvider::addMixer(addSettingsColors), true);
} // namespace settings

@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2026 Reion Wong <reionwong@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "widgets/colors.h"
#include "widgets/listrow.h"
#include <algorithm>
@ -8,6 +9,7 @@
#include <cmath>
#include "ui/animation.h"
#include "ui/color_provider.h"
#include "ui/icon.h"
#include "ui/keys.h"
#include "ui/label.h"
@ -280,7 +282,7 @@ void ListRow::paint(Painter& painter)
painter.save();
painter.clip({0, 0, width, rowHeight});
painter.drawRoundedRect({0, top, width, bottom - top}, {radius, 0, themeCorners()},
theme.text.withAlpha(theme.darkMode ? 0.05 : 0.15));
color(SettingsColor::RowHighlight));
painter.restore();
}
@ -293,7 +295,7 @@ void ListRow::paint(Painter& painter)
const double pixel = 1 / painter.scale();
painter.drawRoundedRect({metrics::cardHorizontalPadding, height - pixel,
width - 2 * metrics::cardHorizontalPadding, pixel},
{}, theme.disabledText.withAlpha(theme.darkMode ? 0.3 : 0.1));
{}, color(ColorId::Separator));
}
}

@ -1,10 +1,12 @@
// SPDX-FileCopyrightText: 2026 Reion Wong <reionwong@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "widgets/colors.h"
#include "widgets/rowcombobox.h"
#include <cmath>
#include "ui/color_provider.h"
#include "ui/icon.h"
#include "ui/keys.h"
#include "ui/label.h"
@ -129,8 +131,8 @@ void RowComboBox::paint(Painter& painter)
const bool open = m_menu && m_menu->isOpen();
if (!isEnabled() || !(m_hovered || open))
return;
const double alpha = open ? (theme.darkMode ? 0.12 : 0.1) : (theme.darkMode ? 0.08 : 0.06);
painter.drawRoundedRect(localRect(), {theme.smallRadius, 0, themeCorners()}, theme.text.withAlpha(alpha));
painter.drawRoundedRect(localRect(), {theme.smallRadius, 0, themeCorners()},
color(open ? SettingsColor::RowComboBoxOpen : SettingsColor::RowComboBoxHovered));
}
// The chevron's colour and fade follow the state, set in layout().

@ -8,6 +8,7 @@
#include <cmath>
#include "base/timer.h"
#include "ui/color_provider.h"
#include "ui/icon.h"
#include "ui/label.h"
#include "ui/painter.h"
@ -77,9 +78,7 @@ protected:
void paint(Painter& painter) override
{
const Theme& theme = Theme::current();
const Color tick = theme.darkMode ? Color::rgb(0xFFFFFF).withAlpha(0.55)
: Color::rgb(0x000000).withAlpha(0.35);
const Color tick = color(ColorId::SliderTickMark);
if (!m_left->text().empty()) {
const double span = std::min(m_left->sizeHint().width, m_leftReference->sizeHint().width);
painter.drawRoundedRect({std::round((span - 1) / 2), 0, 1, kTickHeight}, {}, tick);

@ -1,10 +1,12 @@
// SPDX-FileCopyrightText: 2026 Reion Wong <reionwong@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "widgets/colors.h"
#include "widgets/standardbutton.h"
#include <algorithm>
#include "ui/color_provider.h"
#include "ui/keys.h"
#include "ui/label.h"
#include "ui/painter.h"
@ -38,7 +40,7 @@ void StandardButton::setBackgroundColor(std::optional<Color> color)
Color StandardButton::backgroundColor() const
{
return m_background.value_or(Theme::current().darkMode ? Color::rgb(0x363636) : Color::rgb(0xFFFFFF));
return m_background.value_or(color(SettingsColor::StandardButtonBackground));
}
SizeF StandardButton::sizeHint() const

@ -10,6 +10,7 @@
#include "base/event_loop.h"
#include "base/timer.h"
#include "ui/application.h"
#include "ui/color_provider.h"
#include "ui/event.h"
#include "ui/header_backdrop.h"
#include "ui/header_button.h"
@ -232,7 +233,8 @@ SettingsWindow::SettingsWindow()
};
m_window->onActiveChanged = [this] {
updateBackground();
m_root->requestLayout();
// Views colour their text by it as they lay out.
m_window->requestLayout();
m_root->requestPaint();
activeChanged.emit();
};
@ -378,10 +380,8 @@ void SettingsWindow::updateBackground()
{
const Theme& theme = Theme::current();
const bool active = m_window->isActive();
// Inactive windows keep the blur and halve the see-through instead of going opaque.
const double alpha = theme.darkMode ? (active ? 0.85 : 0.92) : (active ? 0.8 : 0.9);
const Color background = theme.background.withAlpha(alpha);
m_window->setBackgroundColor(background);
m_window->setBackgroundColor(
color(active ? ColorId::TranslucentWindowBackground : ColorId::TranslucentWindowBackgroundInactive));
m_root->backdropBase = theme.background;
if (m_root->backdrop)
m_root->backdrop->setBaseColor(theme.background);

@ -6,6 +6,7 @@
#include <algorithm>
#include <cmath>
#include "ui/color_provider.h"
#include "ui/keys.h"
#include "ui/label.h"
#include "ui/painter.h"
@ -13,6 +14,7 @@
#include "ui/theme.h"
#include "ui/window.h"
#include "widgets/card.h"
#include "widgets/colors.h"
#include "widgets/metrics.h"
#include "widgets/rowicon.h"
#include "widgets/searchfield.h"
@ -88,13 +90,11 @@ protected:
// as the Qt version's list did.
if (m_current)
painter.drawRoundedRect(localRect(), {theme.mediumRadius, 0, themeCorners()}, theme.text.withAlpha(0.05));
double alpha = 0;
if (m_pressed)
alpha = theme.darkMode ? 0.05 : 0.1;
else if (m_current)
alpha = theme.darkMode ? 0.1 : 0.05;
if (alpha > 0)
painter.drawSmoothRectangle(localRect(), theme.mediumRadius, theme.text.withAlpha(alpha));
if (m_pressed || m_current) {
painter.drawSmoothRectangle(
localRect(), theme.mediumRadius,
m_pressed ? color(ColorId::ItemPressed) : color(SettingsColor::SidebarItemCurrent));
}
}
void pointerPress(const PointerEvent& event) override
@ -560,9 +560,7 @@ void Sidebar::layout()
void Sidebar::paint(Painter& painter)
{
const Theme& theme = Theme::current();
const Color base = theme.darkMode ? theme.background.lighter(1.5) : theme.background.darker(1.05);
painter.fillRect(localRect(), base.withAlpha(0.7 * base.a / 255.0));
painter.fillRect(localRect(), color(SettingsColor::SidebarBackground));
}
} // namespace settings

Loading…
Cancel
Save