Theme system (#2164)

* Themes instead of Styles
* Colors changed to theme colors
* Reworked style management
* Theme settings app
* warn, menu dual set
* Added Aqua style
This commit is contained in:
Totoo
2024-05-27 21:02:52 +02:00
committed by GitHub
parent a8203a6372
commit ced8012783
143 changed files with 1566 additions and 1154 deletions

View File

@@ -129,13 +129,13 @@ void AlphanumView::refresh_keys() {
switch (shift_mode) {
case ShiftMode::None:
button_shift.set_color(Color::dark_grey());
button_shift.set_color(Theme::getInstance()->bg_dark->background);
break;
case ShiftMode::Shift:
button_shift.set_color(Color::black());
button_shift.set_color(Theme::getInstance()->bg_darkest->background);
break;
case ShiftMode::ShiftLock:
button_shift.set_color(Color::dark_blue());
button_shift.set_color(Theme::getInstance()->fg_blue->foreground);
break;
}
}

View File

@@ -84,12 +84,12 @@ class AlphanumView : public TextEntryView {
{192, 214, screen_width / 5, 38},
{},
&bitmap_icon_shift,
Color::dark_grey(),
Theme::getInstance()->bg_dark->background,
/*vcenter*/ true};
Labels labels{
{{1 * 8, 33 * 8}, "Raw:", Color::light_grey()},
{{1 * 8, 35 * 8}, "AKA:", Color::light_grey()}};
{{1 * 8, 33 * 8}, "Raw:", Theme::getInstance()->fg_light->foreground},
{{1 * 8, 35 * 8}, "AKA:", Theme::getInstance()->fg_light->foreground}};
NumberField field_raw{
{5 * 8, 33 * 8},

View File

@@ -106,7 +106,7 @@ void BMPViewer::get_line(ui::Color* line, uint32_t bx, uint32_t by, uint32_t cnt
void BMPViewer::paint(Painter& painter) {
if (!bmp.is_loaded()) {
painter.draw_string({48, 24}, ui::Styles::white, "Can't load BMP");
painter.draw_string({48, 24}, *ui::Theme::getInstance()->bg_darkest, "Can't load BMP");
return;
}
// get where i can paint

View File

@@ -25,7 +25,6 @@
#include "ui.hpp"
#include "ui_widget.hpp"
#include "bmpfile.hpp"
#include "ui_styles.hpp"
class BMPViewer : public Widget {
public:

View File

@@ -44,7 +44,7 @@ BtnGridView::BtnGridView(
add_child(&arrow_more);
arrow_more.set_focusable(false);
arrow_more.set_foreground(Color::black());
arrow_more.set_foreground(Theme::getInstance()->bg_darkest->background);
}
BtnGridView::~BtnGridView() {
@@ -98,9 +98,9 @@ void BtnGridView::set_arrow_enabled(bool enabled) {
void BtnGridView::on_tick_second() {
if (more && blink)
arrow_more.set_foreground(Color::white());
arrow_more.set_foreground(Theme::getInstance()->bg_darkest->foreground);
else
arrow_more.set_foreground(Color::black());
arrow_more.set_foreground(Theme::getInstance()->bg_darkest->background);
blink = !blink;

View File

@@ -98,8 +98,8 @@ class BtnGridView : public View {
Image arrow_more{
{228, 320 - 8, 8, 8},
&bitmap_more,
Color::white(),
Color::black()};
Theme::getInstance()->bg_darkest->foreground,
Theme::getInstance()->bg_darkest->background};
int button_w = 240 / rows_;
static constexpr int button_h = 48;

View File

@@ -39,17 +39,17 @@ void Channel::paint(Painter& painter) {
const Rect r0{r.left(), r.top(), x_max, r.height()};
painter.fill_rectangle(
r0,
Color::blue());
Theme::getInstance()->fg_blue->foreground);
const Rect r1{r.left() + x_max, r.top(), 1, r.height()};
painter.fill_rectangle(
r1,
Color::white());
Theme::getInstance()->bg_darkest->foreground);
const Rect r2{r.left() + x_max + 1, r.top(), r.width() - (x_max + 1), r.height()};
painter.fill_rectangle(
r2,
Color::black());
Theme::getInstance()->fg_blue->background);
}
void Channel::on_statistics_update(const ChannelStatistics& statistics) {

View File

@@ -39,14 +39,14 @@ void FreqManUIList::paint(Painter& painter) {
if (!db_ || db_->empty()) {
auto line_position = rect.location() + Point{7 * 8, 6 * 16};
painter.fill_rectangle(rect, Color::black());
painter.draw_string(line_position, Styles::white, "Empty Category");
painter.fill_rectangle(rect, Theme::getInstance()->bg_darkest->background);
painter.draw_string(line_position, *Theme::getInstance()->bg_darkest, "Empty Category");
return;
}
// Indicate when a file is too large by drawing in yellow.
auto over_max = db_->entry_count() > freqman_default_max_entries;
auto base_style = over_max ? &Styles::yellow : &Styles::white;
auto base_style = over_max ? Theme::getInstance()->fg_yellow : Theme::getInstance()->bg_darkest;
// TODO: could minimize redraw/re-read if necessary
// with better change tracking.
@@ -68,7 +68,7 @@ void FreqManUIList::paint(Painter& painter) {
// Otherwise, if 'Raw' indicate an invalid entry by color.
if (entry.type == freqman_type::Raw)
style = &Styles::light_grey;
style = Theme::getInstance()->fg_light;
}
// Pad right with ' ' so trailing chars are cleaned up.
@@ -81,7 +81,7 @@ void FreqManUIList::paint(Painter& painter) {
}
// Draw a bounding rectangle when focused.
painter.draw_rectangle(rect, (has_focus() ? Color::white() : Color::black()));
painter.draw_rectangle(rect, (has_focus() ? Theme::getInstance()->bg_darkest->foreground : Theme::getInstance()->bg_darkest->background));
}
void FreqManUIList::on_focus() {

View File

@@ -26,7 +26,6 @@
#include "ui.hpp"
#include "ui_painter.hpp"
#include "ui_styles.hpp"
#include "ui_widget.hpp"
#include "event_m0.hpp"
#include "freqman.hpp"

View File

@@ -32,7 +32,6 @@ using namespace portapack;
#include "string_format.hpp"
#include "complex.hpp"
#include "ui_styles.hpp"
#include "ui_font_fixed_5x8.hpp"
#include "file_path.hpp"
@@ -138,8 +137,8 @@ void GeoPos::focus() {
void GeoPos::hide_altandspeed() {
// Color altitude grey to indicate it's not updated in manual panning mode
field_altitude.set_style(&Styles::grey);
field_speed.set_style(&Styles::grey);
field_altitude.set_style(Theme::getInstance()->fg_medium);
field_speed.set_style(Theme::getInstance()->fg_medium);
}
void GeoPos::set_altitude(int32_t altitude) {
@@ -322,13 +321,13 @@ void GeoMap::draw_map_grid() {
if (map_zoom <= MAP_ZOOM_RESOLUTION_LIMIT)
return;
display.fill_rectangle({{0, r.top()}, {r.width(), r.height()}}, Color::black());
display.fill_rectangle({{0, r.top()}, {r.width(), r.height()}}, Theme::getInstance()->bg_darkest->background);
for (uint16_t line = y; line < r.height(); line += grid_spacing) {
display.fill_rectangle({{0, r.top() + line}, {r.width(), 1}}, Color::darker_grey());
display.fill_rectangle({{0, r.top() + line}, {r.width(), 1}}, Theme::getInstance()->bg_darker->background);
}
for (uint16_t column = x; column < r.width(); column += grid_spacing) {
display.fill_rectangle({{column, r.top()}, {1, r.height()}}, Color::darker_grey());
display.fill_rectangle({{column, r.top()}, {1, r.height()}}, Theme::getInstance()->bg_darker->background);
}
}

View File

@@ -110,12 +110,12 @@ class GeoPos : public View {
spd_unit speed_unit_{};
Labels labels_position{
{{1 * 8, 0 * 16}, "Alt:", Color::light_grey()},
{{1 * 8, 1 * 16}, "Lat: \xB0 ' \"", Color::light_grey()}, // 0xB0 is degree ° symbol in our 8x16 font
{{1 * 8, 2 * 16}, "Lon: \xB0 ' \"", Color::light_grey()},
{{1 * 8, 0 * 16}, "Alt:", Theme::getInstance()->fg_light->foreground},
{{1 * 8, 1 * 16}, "Lat: \xB0 ' \"", Theme::getInstance()->fg_light->foreground}, // 0xB0 is degree ° symbol in our 8x16 font
{{1 * 8, 2 * 16}, "Lon: \xB0 ' \"", Theme::getInstance()->fg_light->foreground},
};
Labels label_spd_position{
{{15 * 8, 0 * 16}, "Spd:", Color::light_grey()},
{{15 * 8, 0 * 16}, "Spd:", Theme::getInstance()->fg_light->foreground},
};
NumberField field_altitude{
{6 * 8, 0 * 16},

View File

@@ -98,7 +98,7 @@ MenuView::MenuView(
add_child(&arrow_more);
arrow_more.set_focusable(false);
arrow_more.set_foreground(Color::black());
arrow_more.set_foreground(Theme::getInstance()->bg_darkest->background);
}
MenuView::~MenuView() {
@@ -135,9 +135,9 @@ void MenuView::set_parent_rect(const Rect new_parent_rect) {
void MenuView::on_tick_second() {
if (more && blink)
arrow_more.set_foreground(Color::white());
arrow_more.set_foreground(Theme::getInstance()->bg_darkest->foreground);
else
arrow_more.set_foreground(Color::black());
arrow_more.set_foreground(Theme::getInstance()->bg_darkest->background);
blink = !blink;

View File

@@ -113,8 +113,8 @@ class MenuView : public View {
Image arrow_more{
{228, screen_height - 8, 8, 8},
&bitmap_more,
Color::white(),
Color::black()};
Theme::getInstance()->bg_darkest->foreground,
Theme::getInstance()->bg_darkest->background};
const size_t item_height = 24;
bool blink = false;

View File

@@ -113,7 +113,7 @@ void FrequencyField::paint(Painter& painter) {
if (digit_mode_) {
auto p = screen_pos();
p += {digit_ * char_width, 0};
painter.draw_char(p, Styles::bg_blue, str_value[digit_]);
painter.draw_char(p, *Theme::getInstance()->option_active, str_value[digit_]);
}
}

View File

@@ -69,13 +69,13 @@ void RSSI::paint(Painter& painter) {
const Rect r0{r.left(), r.top(), x_min, r.height()};
painter.fill_rectangle(
r0,
Color::blue());
Theme::getInstance()->fg_blue->foreground);
// x_avg
const Rect r1{r.left() + x_min, r.top(), x_avg - x_min, r.height()};
painter.fill_rectangle(
r1,
Color::red());
Theme::getInstance()->fg_red->foreground);
// x_avg middle marker
const Rect r2{r.left() + x_avg, r.top(), 1, r.height()};
@@ -87,20 +87,20 @@ void RSSI::paint(Painter& painter) {
const Rect r3{r.left() + x_avg + 1, r.top(), x_max - (x_avg + 1), r.height()};
painter.fill_rectangle(
r3,
Color::red());
Theme::getInstance()->fg_red->foreground);
// filling last part in black
const Rect r4{r.left() + x_max, r.top(), r.width() - x_max, r.height()};
painter.fill_rectangle(
r4,
Color::black());
Theme::getInstance()->bg_darkest->background);
// show green peak value
if (peak_enabled) {
const Rect r5{r.left() + peak - 3, r.top(), 3, r.height()};
painter.fill_rectangle(
r5,
Color::green());
Theme::getInstance()->fg_green->foreground);
}
} else {
// vertical bottom to top level meters

View File

@@ -56,7 +56,7 @@ AudioSpectrumView::AudioSpectrumView(
void AudioSpectrumView::paint(Painter& painter) {
const auto r = screen_rect();
painter.fill_rectangle(r, Color::black());
painter.fill_rectangle(r, Theme::getInstance()->bg_darkest->background);
// if( !spectrum_sampling_rate ) return;
@@ -131,14 +131,14 @@ void FrequencyScale::clear() {
}
void FrequencyScale::clear_background(Painter& painter, const Rect r) {
painter.fill_rectangle(r, Color::black());
painter.fill_rectangle(r, Theme::getInstance()->bg_darkest->background);
}
void FrequencyScale::draw_frequency_ticks(Painter& painter, const Rect r) {
const auto x_center = r.width() / 2;
const Rect tick{r.left() + x_center, r.top(), 1, r.height()};
painter.fill_rectangle(tick, Color::white());
painter.fill_rectangle(tick, Theme::getInstance()->bg_darkest->foreground);
constexpr int tick_count_max = 4;
float rough_tick_interval = float(spectrum_sampling_rate) / tick_count_max;
@@ -166,12 +166,12 @@ void FrequencyScale::draw_frequency_ticks(Painter& painter, const Rect r) {
const Coord offset_low = r.left() + x_center - pixel_offset;
const Rect tick_low{offset_low, r.top(), 1, r.height()};
painter.fill_rectangle(tick_low, Color::white());
painter.fill_rectangle(tick_low, Theme::getInstance()->bg_darkest->foreground);
painter.draw_string({offset_low + 2, r.top()}, style(), label);
const Coord offset_high = r.left() + x_center + pixel_offset;
const Rect tick_high{offset_high, r.top(), 1, r.height()};
painter.fill_rectangle(tick_high, Color::white());
painter.fill_rectangle(tick_high, Theme::getInstance()->bg_darkest->foreground);
painter.draw_string({offset_high - 2 - label_width, r.top()}, style(), label);
tick_offset += tick_interval;

View File

@@ -49,7 +49,7 @@ class AudioSpectrumView : public View {
int16_t audio_spectrum[128]{0};
Labels labels{
{{6 * 8, 0 * 16}, "Hz", Color::light_grey()}};
{{6 * 8, 0 * 16}, "Hz", Theme::getInstance()->fg_light->foreground}};
NumberField field_frequency{
{0 * 8, 0 * 16},
@@ -64,7 +64,7 @@ class AudioSpectrumView : public View {
128,
0,
false,
Color::white()};
Theme::getInstance()->bg_darkest->foreground};
};
class FrequencyScale : public Widget {

View File

@@ -1,123 +0,0 @@
/*
* Copyright (C) 2023 Kyle Reed
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ui_styles.hpp"
#include "ui_painter.hpp"
#include "ui_font_fixed_5x8.hpp"
#include "ui_font_fixed_8x16.hpp"
using namespace ui;
const Style Styles::white{
.font = ui::font::fixed_8x16,
.background = ui::Color::black(),
.foreground = ui::Color::white(),
};
const Style Styles::bg_white{
.font = ui::font::fixed_8x16,
.background = ui::Color::white(),
.foreground = ui::Color::black(),
};
const Style Styles::white_small{
.font = font::fixed_5x8,
.background = Color::black(),
.foreground = Color::white(),
};
const Style Styles::bg_white_small{
.font = ui::font::fixed_5x8,
.background = ui::Color::white(),
.foreground = ui::Color::black(),
};
const Style Styles::bg_yellow_small{
.font = ui::font::fixed_5x8,
.background = ui::Color::yellow(),
.foreground = ui::Color::black(),
};
const Style Styles::yellow{
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::yellow(),
};
const Style Styles::green{
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::green(),
};
const Style Styles::red{
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::red(),
};
const Style Styles::blue{
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::blue(),
};
const Style Styles::bg_blue{
.font = font::fixed_8x16,
.background = Color::blue(),
.foreground = Color::white(),
};
const Style Styles::bg_dark_blue{
.font = font::fixed_8x16,
.background = Color::dark_blue(),
.foreground = Color::white(),
};
const Style Styles::light_grey{
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::light_grey(),
};
const Style Styles::grey{
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::grey(),
};
const Style Styles::dark_grey{
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::dark_grey(),
};
const Style Styles::bg_dark_grey{
.font = font::fixed_8x16,
.background = Color::dark_grey(),
.foreground = Color::white(),
};
const Style Styles::orange{
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::orange(),
};

View File

@@ -1,82 +0,0 @@
/*
* Copyright (C) 2023 Kyle Reed
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __UI_STYLES_H__
#define __UI_STYLES_H__
#include "ui_painter.hpp"
namespace ui {
class Styles {
public:
/* White foreground. */
static const Style white;
/* White background. */
static const Style bg_white;
/* White foreground, small font. */
static const Style white_small;
/* White background, small font. */
static const Style bg_white_small;
/* Red background, small font. */
static const Style bg_yellow_small;
/* Yellow foreground. */
static const Style yellow;
/* Green foreground. */
static const Style green;
/* Red foreground. */
static const Style red;
/* Blue foreground. */
static const Style blue;
/* Blue background. */
static const Style bg_blue;
/* Dark blue background. */
static const Style bg_dark_blue;
/* Light grey foreground. */
static const Style light_grey;
/* Grey foreground. */
static const Style grey;
/* Dark grey foreground. */
static const Style dark_grey;
/* Dark grey background. */
static const Style bg_dark_grey;
/* Orange foreground. */
static const Style orange;
};
} // namespace ui
#endif /*__UI_STYLES_H__*/

View File

@@ -47,18 +47,18 @@ void Tab::set(
void Tab::paint(Painter& painter) {
const auto rect = screen_rect();
const Color color = highlighted() ? Color::black() : Color::grey();
const Color color = highlighted() ? Theme::getInstance()->bg_darkest->background : Theme::getInstance()->bg_medium->background;
painter.fill_rectangle({rect.left(), rect.top(), rect.width() - 8, rect.height()}, color);
if (!highlighted())
painter.draw_hline({rect.left(), rect.top()}, rect.width() - 9, Color::light_grey());
painter.draw_hline({rect.left(), rect.top()}, rect.width() - 9, Theme::getInstance()->fg_light->foreground);
painter.draw_bitmap(
{rect.right() - 8, rect.top()},
bitmap_tab_edge,
color,
Color::dark_grey());
Theme::getInstance()->bg_dark->background);
auto text_point = rect.center() - Point(4, 0) - Point(text_.size() * 8 / 2, 16 / 2);
@@ -68,7 +68,7 @@ void Tab::paint(Painter& painter) {
text_);
if (has_focus())
painter.draw_hline(text_point + Point(0, 16), text_.size() * 8, Color::white());
painter.draw_hline(text_point + Point(0, 16), text_.size() * 8, Theme::getInstance()->bg_darkest->foreground);
}
bool Tab::on_key(const KeyEvent key) {

View File

@@ -40,13 +40,13 @@ namespace ui {
/* Gets a style indicating total TX gain level. */
static const Style* get_style_for_gain(uint8_t tot_gain) {
if (tot_gain > POWER_THRESHOLD_HIGH) return &Styles::red;
if (tot_gain > POWER_THRESHOLD_HIGH) return Theme::getInstance()->fg_red;
if (tot_gain > POWER_THRESHOLD_MED)
return &Styles::orange;
return Theme::getInstance()->fg_orange;
if (tot_gain > POWER_THRESHOLD_LOW)
return &Styles::yellow;
return Theme::getInstance()->fg_yellow;
return nullptr; // Uses default.
}
@@ -61,8 +61,8 @@ void TransmitterView::paint(Painter& painter) {
painter.draw_bitmap(
pos,
bitmap_stripes,
ui::Color(191, 191, 0),
ui::Color::black());
Theme::getInstance()->fg_yellow->foreground,
Theme::getInstance()->fg_yellow->background);
if (c != 9)
pos += {24, 0};
else

View File

@@ -27,7 +27,6 @@
#include "ui_navigation.hpp"
#include "ui_painter.hpp"
#include "ui_receiver.hpp"
#include "ui_styles.hpp"
#include "ui_widget.hpp"
#include "rf_path.hpp"
@@ -69,9 +68,9 @@ class TransmitterView : public View {
void set_transmitting(const bool transmitting);
private:
const Style& style_start = Styles::green;
const Style& style_stop = Styles::red;
const Style& style_locked = Styles::dark_grey;
const Style& style_start = *Theme::getInstance()->fg_green;
const Style& style_stop = *Theme::getInstance()->fg_red;
const Style& style_locked = *Theme::getInstance()->fg_dark;
bool lock_{false};
bool transmitting_{false};

View File

@@ -50,7 +50,7 @@ class TimeScopeView : public View {
int16_t audio_spectrum[128]{0};
/*Labels labels {
{ { 6 * 8, 0 * 16 }, "Hz", Color::light_grey() }
{ { 6 * 8, 0 * 16 }, "Hz", Theme::getInstance()->fg_light->foreground }
};*/
/*
NumberField field_frequency {
@@ -67,7 +67,7 @@ class TimeScopeView : public View {
128,
0,
false,
Color::white()};
Theme::getInstance()->bg_darkest->foreground};
};
class TVView : public Widget {