Date and time display widget

Disabled handwriting text input (not that useful for now)
Bugfix: Trim long filenames in fileman
Slight cleanup of 7-seg display widget
This commit is contained in:
furrtek 2017-09-20 07:50:59 +01:00
parent 37ce81383d
commit c0f51c2690
11 changed files with 162 additions and 143 deletions

View File

@ -177,7 +177,7 @@ set(CPPSRC
ui_font_fixed_8x16.cpp ui_font_fixed_8x16.cpp
ui_freqman.cpp ui_freqman.cpp
ui_geomap.cpp ui_geomap.cpp
ui_handwrite.cpp # ui_handwrite.cpp
ui_jammer.cpp ui_jammer.cpp
ui_lcr.cpp ui_lcr.cpp
ui_menu.cpp ui_menu.cpp

View File

@ -36,6 +36,7 @@ void FileManBaseView::load_directory_contents(const std::filesystem::path& dir_p
entry_list.clear(); entry_list.clear();
// List all directories and files, put directories up top
for (const auto& entry : std::filesystem::directory_iterator(dir_path, u"*")) { for (const auto& entry : std::filesystem::directory_iterator(dir_path, u"*")) {
if (std::filesystem::is_regular_file(entry.status())) { if (std::filesystem::is_regular_file(entry.status())) {
entry_list.push_back({ entry.path(), (uint32_t)entry.size(), false }); entry_list.push_back({ entry.path(), (uint32_t)entry.size(), false });
@ -45,14 +46,14 @@ void FileManBaseView::load_directory_contents(const std::filesystem::path& dir_p
} }
} }
std::filesystem::path FileManBaseView::get_absolute_path() { std::filesystem::path FileManBaseView::get_selected_path() {
std::string current_path_str = current_path.string(); std::string selected_path_str = current_path.string();
if (current_path_str.back() != '/') if (selected_path_str.back() != '/')
current_path_str += '/'; selected_path_str += '/';
current_path_str += (entry_list[menu_view.highlighted()].entry_path.string()); selected_path_str += (entry_list[menu_view.highlighted()].entry_path.string());
return current_path_str; return selected_path_str;
} }
FileManBaseView::FileManBaseView( FileManBaseView::FileManBaseView(
@ -62,7 +63,7 @@ FileManBaseView::FileManBaseView(
load_directory_contents(current_path); load_directory_contents(current_path);
if (!entry_list.size()) if (!entry_list.size())
error_ = true; empty_root = true;
add_children({ add_children({
&labels, &labels,
@ -70,14 +71,22 @@ FileManBaseView::FileManBaseView(
&button_exit &button_exit
}); });
// Go back one level on left
menu_view.on_left = [&nav, this]() {
std::string current_path_str = current_path.string();
current_path_str = current_path_str.substr(0, current_path_str.find_last_of('/'));
load_directory_contents(current_path_str);
refresh_list();
};
button_exit.on_select = [this, &nav](Button&) { button_exit.on_select = [this, &nav](Button&) {
nav.pop(); nav.pop();
}; };
}; };
void FileManBaseView::focus() { void FileManBaseView::focus() {
if (empty_root) {
if (error_) {
button_exit.focus(); button_exit.focus();
nav_.display_modal("Error", "No files in root.", ABORT, nullptr); nav_.display_modal("Error", "No files in root.", ABORT, nullptr);
} else { } else {
@ -91,16 +100,18 @@ void FileManBaseView::refresh_list() {
size_t file_size; size_t file_size;
if (!entry_list.size()) { if (!entry_list.size()) {
// Hide widgets, show warning
if (on_refresh_widgets) if (on_refresh_widgets)
on_refresh_widgets(true); on_refresh_widgets(true);
} else { } else {
// Hide warning, show widgets
if (on_refresh_widgets) if (on_refresh_widgets)
on_refresh_widgets(false); on_refresh_widgets(false);
menu_view.clear(); menu_view.clear();
for (size_t n = 0; n < entry_list.size(); n++) { for (size_t n = 0; n < entry_list.size(); n++) {
auto entry_name = entry_list[n].entry_path.filename().string(); auto entry_name = entry_list[n].entry_path.filename().string().substr(0, 20);
if (entry_list[n].is_directory) { if (entry_list[n].is_directory) {
@ -145,47 +156,28 @@ void FileManBaseView::refresh_list() {
} }
} }
void FileSaveView::on_save_name() { /*void FileSaveView::on_save_name() {
/*text_prompt(nav_, &filename_buffer, 8, [this](std::string * buffer) { text_prompt(nav_, &filename_buffer, 8, [this](std::string * buffer) {
//database.entries.push_back({ value_, "", *buffer });
//save_freqman_file(entry_list[current_category_id], database);
nav_.pop(); nav_.pop();
});*/ });
}
void FileSaveView::on_tick_second() {
rtcGetTime(&RTCD1, &datetime);
str_timestamp = to_string_dec_uint(datetime.month(), 2, '0') + "/" + to_string_dec_uint(datetime.day(), 2, '0') + " " +
to_string_dec_uint(datetime.hour(), 2, '0') + ":" + to_string_dec_uint(datetime.minute(), 2, '0');
text_timestamp.set(str_timestamp);
}
FileSaveView::~FileSaveView() {
rtc_time::signal_tick_second -= signal_token_tick_second;
} }
FileSaveView::FileSaveView( FileSaveView::FileSaveView(
NavigationView& nav NavigationView& nav
) : FileManBaseView(nav) ) : FileManBaseView(nav)
{ {
filename_buffer.reserve(8); name_buffer.clear();
signal_token_tick_second = rtc_time::signal_tick_second += [this]() {
this->on_tick_second();
};
add_children({ add_children({
&text_save, &text_save,
&button_save_name, &button_save_name,
&text_timestamp &live_timestamp
}); });
on_tick_second();
button_save_name.on_select = [this, &nav](Button&) { button_save_name.on_select = [this, &nav](Button&) {
on_save_name(); on_save_name();
}; };
} }*/
void FileLoadView::refresh_widgets(const bool v) { void FileLoadView::refresh_widgets(const bool v) {
menu_view.hidden(v); menu_view.hidden(v);
@ -224,15 +216,15 @@ FileLoadView::FileLoadView(
} }
void FileManagerView::on_rename(NavigationView& nav) { void FileManagerView::on_rename(NavigationView& nav) {
text_prompt(nav, &filename_buffer, 12, [this](std::string * buffer) { text_prompt(nav, &name_buffer, 12, [this](std::string * buffer) {
rename_file(get_absolute_path(), *buffer); rename_file(get_selected_path(), *buffer);
load_directory_contents(current_path); load_directory_contents(current_path);
refresh_list(); refresh_list();
}); });
} }
void FileManagerView::on_delete() { void FileManagerView::on_delete() {
delete_file(get_absolute_path()); delete_file(get_selected_path());
load_directory_contents(current_path); load_directory_contents(current_path);
refresh_list(); refresh_list();
} }
@ -259,7 +251,6 @@ FileManagerView::FileManagerView(
}; };
add_children({ add_children({
//&labels,
&menu_view, &menu_view,
&text_empty, &text_empty,
&button_rename, &button_rename,
@ -267,29 +258,20 @@ FileManagerView::FileManagerView(
&button_delete &button_delete
}); });
// Go back one level on left
menu_view.on_left = [&nav, this]() {
std::string current_path_str = current_path.string();
current_path_str = current_path_str.substr(0, current_path_str.find_last_of('/'));
load_directory_contents(current_path_str);
refresh_list();
};
refresh_list(); refresh_list();
on_select_entry = [this]() { on_select_entry = [this]() {
if (entry_list[menu_view.highlighted()].is_directory) { if (entry_list[menu_view.highlighted()].is_directory) {
load_directory_contents(get_absolute_path()); load_directory_contents(get_selected_path());
refresh_list(); refresh_list();
} else } else
button_rename.focus(); button_rename.focus();
}; };
button_new_dir.on_select = [this, &nav](Button&) { button_new_dir.on_select = [this, &nav](Button&) {
filename_buffer = ""; name_buffer.clear();
text_prompt(nav, &filename_buffer, 12, [this](std::string * buffer) { text_prompt(nav, &name_buffer, 12, [this](std::string * buffer) {
std::string path_str = *buffer; std::string path_str = *buffer;
make_new_directory(current_path.string() + '/' + path_str); make_new_directory(current_path.string() + '/' + path_str);
@ -300,7 +282,7 @@ FileManagerView::FileManagerView(
button_rename.on_select = [this, &nav](Button&) { button_rename.on_select = [this, &nav](Button&) {
if (!entry_list[menu_view.highlighted()].is_directory) { if (!entry_list[menu_view.highlighted()].is_directory) {
filename_buffer = entry_list[menu_view.highlighted()].entry_path.filename().string(); name_buffer = entry_list[menu_view.highlighted()].entry_path.filename().string();
on_rename(nav); on_rename(nav);
} }
}; };

View File

@ -27,7 +27,6 @@
#include "file.hpp" #include "file.hpp"
#include "ui_navigation.hpp" #include "ui_navigation.hpp"
#include "ui_textentry.hpp" #include "ui_textentry.hpp"
#include "rtc_time.hpp"
namespace ui { namespace ui {
@ -46,7 +45,7 @@ public:
void focus() override; void focus() override;
void load_directory_contents(const std::filesystem::path& dir_path); void load_directory_contents(const std::filesystem::path& dir_path);
std::filesystem::path get_absolute_path(); std::filesystem::path get_selected_path();
std::string title() const override { return "File manager"; }; std::string title() const override { return "File manager"; };
@ -55,7 +54,7 @@ protected:
const std::string suffix[5] = { "B", "kB", "MB", "GB", "??" }; const std::string suffix[5] = { "B", "kB", "MB", "GB", "??" };
bool error_ { false }; bool empty_root { false };
std::function<void(void)> on_select_entry { nullptr }; std::function<void(void)> on_select_entry { nullptr };
std::function<void(bool)> on_refresh_widgets { nullptr }; std::function<void(bool)> on_refresh_widgets { nullptr };
std::vector<fileman_entry> entry_list { }; std::vector<fileman_entry> entry_list { };
@ -87,20 +86,15 @@ protected:
}; };
}; };
class FileSaveView : public FileManBaseView { /*class FileSaveView : public FileManBaseView {
public: public:
FileSaveView(NavigationView& nav); FileSaveView(NavigationView& nav);
~FileSaveView(); ~FileSaveView();
private: private:
std::string filename_buffer { }; std::string name_buffer { };
rtc::RTC datetime { };
std::string str_timestamp { };
void on_save_name(); void on_save_name();
void on_tick_second();
SignalToken signal_token_tick_second { };
Text text_save { Text text_save {
{ 4 * 8, 15 * 8, 8 * 8, 16 }, { 4 * 8, 15 * 8, 8 * 8, 16 },
@ -110,11 +104,10 @@ private:
{ 4 * 8, 18 * 8, 12 * 8, 32 }, { 4 * 8, 18 * 8, 12 * 8, 32 },
"Name (set)" "Name (set)"
}; };
Text text_timestamp { LiveDateTime live_timestamp {
{ 17 * 8, 24 * 8, 11 * 8, 16 }, { 17 * 8, 24 * 8, 11 * 8, 16 }
"MM/DD HH:MM",
};
}; };
};*/
class FileLoadView : public FileManBaseView { class FileLoadView : public FileManBaseView {
public: public:
@ -132,16 +125,12 @@ public:
~FileManagerView(); ~FileManagerView();
private: private:
std::string filename_buffer { }; std::string name_buffer { };
void refresh_widgets(const bool v); void refresh_widgets(const bool v);
void on_rename(NavigationView& nav); void on_rename(NavigationView& nav);
void on_delete(); void on_delete();
/*Labels labels {
{ { 4 * 8 + 4, 26 * 8 }, "Edit:", Color::light_grey() }
};*/
Button button_rename { Button button_rename {
{ 0 * 8, 28 * 8, 14 * 8, 32 }, { 0 * 8, 28 * 8, 14 * 8, 32 },
"Rename" "Rename"

View File

@ -134,22 +134,11 @@ void FrequencySaveView::on_save_name() {
} }
void FrequencySaveView::on_save_timestamp() { void FrequencySaveView::on_save_timestamp() {
database.entries.push_back({ value_, "", str_timestamp }); database.entries.push_back({ value_, "", live_timestamp.string() });
save_freqman_file(file_list[current_category_id], database); save_freqman_file(file_list[current_category_id], database);
nav_.pop(); nav_.pop();
} }
void FrequencySaveView::on_tick_second() {
rtcGetTime(&RTCD1, &datetime);
str_timestamp = to_string_dec_uint(datetime.month(), 2, '0') + "/" + to_string_dec_uint(datetime.day(), 2, '0') + " " +
to_string_dec_uint(datetime.hour(), 2, '0') + ":" + to_string_dec_uint(datetime.minute(), 2, '0');
text_timestamp.set(str_timestamp);
}
FrequencySaveView::~FrequencySaveView() {
rtc_time::signal_tick_second -= signal_token_tick_second;
}
FrequencySaveView::FrequencySaveView( FrequencySaveView::FrequencySaveView(
NavigationView& nav, NavigationView& nav,
const rf::Frequency value const rf::Frequency value
@ -166,20 +155,14 @@ FrequencySaveView::FrequencySaveView(
} }
}*/ }*/
signal_token_tick_second = rtc_time::signal_tick_second += [this]() {
this->on_tick_second();
};
add_children({ add_children({
&labels,
&big_display, &big_display,
&text_save,
&button_save_name, &button_save_name,
&button_save_timestamp, &button_save_timestamp,
&text_timestamp &live_timestamp
}); });
on_tick_second();
big_display.set(value); big_display.set(value);
button_save_name.on_select = [this, &nav](Button&) { button_save_name.on_select = [this, &nav](Button&) {

View File

@ -28,7 +28,6 @@
#include "ui_receiver.hpp" #include "ui_receiver.hpp"
#include "ui_textentry.hpp" #include "ui_textentry.hpp"
#include "freqman.hpp" #include "freqman.hpp"
#include "rtc_time.hpp"
namespace ui { namespace ui {
@ -89,40 +88,33 @@ protected:
class FrequencySaveView : public FreqManBaseView { class FrequencySaveView : public FreqManBaseView {
public: public:
FrequencySaveView(NavigationView& nav, const rf::Frequency value); FrequencySaveView(NavigationView& nav, const rf::Frequency value);
~FrequencySaveView();
private: private:
std::string desc_buffer { }; std::string desc_buffer { };
rtc::RTC datetime { };
rf::Frequency value_ { }; rf::Frequency value_ { };
std::string str_timestamp { };
void on_save_name(); void on_save_name();
void on_save_timestamp(); void on_save_timestamp();
void on_tick_second();
SignalToken signal_token_tick_second { };
BigFrequency big_display { BigFrequency big_display {
{ 4, 2 * 16, 28 * 8, 32 }, { 4, 2 * 16, 28 * 8, 32 },
0 0
}; };
Text text_save { Labels labels {
{ 4 * 8, 15 * 8, 8 * 8, 16 }, { { 2 * 8, 14 * 8 }, "Save as:", Color::white() }
"Save as:",
}; };
Button button_save_name { Button button_save_name {
{ 4 * 8, 18 * 8, 12 * 8, 32 }, { 2 * 8, 17 * 8, 14 * 8, 48 },
"Name (set)" "Name (set)"
}; };
Button button_save_timestamp { Button button_save_timestamp {
{ 4 * 8, 23 * 8, 12 * 8, 32 }, { 2 * 8, 25 * 8, 14 * 8, 48 },
"Timestamp:" "Timestamp:"
}; };
Text text_timestamp { LiveDateTime live_timestamp {
{ 17 * 8, 24 * 8, 11 * 8, 16 }, { 17 * 8, 27 * 8, 11 * 8, 16 }
"MM/DD HH:MM",
}; };
}; };

View File

@ -87,7 +87,7 @@ SystemStatusView::SystemStatusView() {
&button_back, &button_back,
&title, &title,
&button_stealth, &button_stealth,
&button_textentry, //&button_textentry,
&button_camera, &button_camera,
&button_sleep, &button_sleep,
&sd_card_status_view, &sd_card_status_view,
@ -96,10 +96,10 @@ SystemStatusView::SystemStatusView() {
button_back.id = -1; // Special ID used by FocusManager button_back.id = -1; // Special ID used by FocusManager
title.set_style(&style_systemstatus); title.set_style(&style_systemstatus);
if (!portapack::persistent_memory::ui_config_textentry()) /*if (!portapack::persistent_memory::ui_config_textentry())
button_textentry.set_bitmap(&bitmap_icon_keyboard); button_textentry.set_bitmap(&bitmap_icon_keyboard);
else else
button_textentry.set_bitmap(&bitmap_icon_unistroke); button_textentry.set_bitmap(&bitmap_icon_unistroke);*/
if (portapack::persistent_memory::stealth_mode()) if (portapack::persistent_memory::stealth_mode())
button_stealth.set_foreground(ui::Color::green()); button_stealth.set_foreground(ui::Color::green());
@ -113,9 +113,9 @@ SystemStatusView::SystemStatusView() {
this->on_stealth(); this->on_stealth();
}; };
button_textentry.on_select = [this](ImageButton&) { /*button_textentry.on_select = [this](ImageButton&) {
this->on_textentry(); this->on_textentry();
}; };*/
button_camera.on_select = [this](ImageButton&) { button_camera.on_select = [this](ImageButton&) {
this->on_camera(); this->on_camera();
@ -154,7 +154,7 @@ void SystemStatusView::on_stealth() {
button_stealth.set_dirty(); button_stealth.set_dirty();
} }
void SystemStatusView::on_textentry() { /*void SystemStatusView::on_textentry() {
uint8_t cfg; uint8_t cfg;
cfg = portapack::persistent_memory::ui_config_textentry(); cfg = portapack::persistent_memory::ui_config_textentry();
@ -164,7 +164,7 @@ void SystemStatusView::on_textentry() {
button_textentry.set_bitmap(&bitmap_icon_unistroke); button_textentry.set_bitmap(&bitmap_icon_unistroke);
else else
button_textentry.set_bitmap(&bitmap_icon_keyboard); button_textentry.set_bitmap(&bitmap_icon_keyboard);
} }*/
void SystemStatusView::on_camera() { void SystemStatusView::on_camera() {
auto path = next_filename_stem_matching_pattern(u"SCR_????"); auto path = next_filename_stem_matching_pattern(u"SCR_????");

View File

@ -83,18 +83,18 @@ private:
}; };
ImageButton button_stealth { ImageButton button_stealth {
{ 152, 0, 2 * 8, 1 * 16 }, { 170, 0, 2 * 8, 1 * 16 },
&bitmap_icon_stealth, &bitmap_icon_stealth,
Color::light_grey(), Color::light_grey(),
Color::dark_grey() Color::dark_grey()
}; };
ImageButton button_textentry { /*ImageButton button_textentry {
{ 170, 0, 2 * 8, 1 * 16 }, { 170, 0, 2 * 8, 1 * 16 },
&bitmap_icon_unistroke, &bitmap_icon_unistroke,
Color::white(), Color::white(),
Color::dark_grey() Color::dark_grey()
}; };*/
ImageButton button_camera { ImageButton button_camera {
{ 188, 0, 2 * 8, 1 * 16 }, { 188, 0, 2 * 8, 1 * 16 },
@ -115,7 +115,7 @@ private:
}; };
void on_stealth(); void on_stealth();
void on_textentry(); //void on_textentry();
void on_camera(); void on_camera();
}; };
@ -143,7 +143,7 @@ public:
void pop_modal(); void pop_modal();
void display_modal(const std::string& title, const std::string& message); void display_modal(const std::string& title, const std::string& message);
void display_modal(const std::string& title, const std::string& message, const modal_t type, const std::function<void(bool)> on_choice); void display_modal(const std::string& title, const std::string& message, const modal_t type, const std::function<void(bool)> on_choice = nullptr);
void focus() override; void focus() override;

View File

@ -21,28 +21,28 @@
*/ */
#include "ui_textentry.hpp" #include "ui_textentry.hpp"
#include "portapack_persistent_memory.hpp" //#include "portapack_persistent_memory.hpp"
#include "ui_handwrite.hpp"
#include "ui_alphanum.hpp" #include "ui_alphanum.hpp"
//#include "ui_handwrite.hpp"
using namespace portapack; using namespace portapack;
namespace ui { namespace ui {
void text_prompt(NavigationView& nav, std::string * str, const size_t max_length, const std::function<void(std::string *)> on_done) { void text_prompt(NavigationView& nav, std::string * str, const size_t max_length, const std::function<void(std::string *)> on_done) {
if (persistent_memory::ui_config_textentry() == 0) { //if (persistent_memory::ui_config_textentry() == 0) {
auto te_view = nav.push<AlphanumView>(str, max_length); auto te_view = nav.push<AlphanumView>(str, max_length);
te_view->on_changed = [on_done](std::string * value) { te_view->on_changed = [on_done](std::string * value) {
if (on_done) if (on_done)
on_done(value); on_done(value);
}; };
} else { /*} else {
auto te_view = nav.push<HandWriteView>(str, max_length); auto te_view = nav.push<HandWriteView>(str, max_length);
te_view->on_changed = [on_done](std::string * value) { te_view->on_changed = [on_done](std::string * value) {
if (on_done) if (on_done)
on_done(value); on_done(value);
}; };
} }*/
} }
void TextEntryView::update_text() { void TextEntryView::update_text() {

View File

@ -405,6 +405,45 @@ void Labels::paint(Painter& painter) {
} }
} }
/* LiveDateTime **********************************************************/
void LiveDateTime::on_tick_second() {
rtcGetTime(&RTCD1, &datetime);
text = to_string_dec_uint(datetime.month(), 2, '0') + "/" + to_string_dec_uint(datetime.day(), 2, '0') + " " +
to_string_dec_uint(datetime.hour(), 2, '0') + ":" + to_string_dec_uint(datetime.minute(), 2, '0');
set_dirty();
}
LiveDateTime::LiveDateTime(
Rect parent_rect
) : Widget { parent_rect }
{
signal_token_tick_second = rtc_time::signal_tick_second += [this]() {
this->on_tick_second();
};
}
LiveDateTime::~LiveDateTime() {
rtc_time::signal_tick_second -= signal_token_tick_second;
}
void LiveDateTime::paint(Painter& painter) {
const auto rect = screen_rect();
const auto s = style();
on_tick_second();
painter.fill_rectangle(rect, s.background);
painter.draw_string(
rect.location(),
s,
text
);
}
/* BigFrequency **********************************************************/ /* BigFrequency **********************************************************/
BigFrequency::BigFrequency( BigFrequency::BigFrequency(
@ -422,9 +461,9 @@ void BigFrequency::set(const rf::Frequency frequency) {
void BigFrequency::paint(Painter& painter) { void BigFrequency::paint(Painter& painter) {
uint32_t i, digit_def; uint32_t i, digit_def;
char digits[7]; std::array<char, 7> digits;
char digit; char digit;
Coord digit_x, digit_y; Point digit_pos;
ui::Color segment_color; ui::Color segment_color;
const auto rect = screen_rect(); const auto rect = screen_rect();
@ -432,11 +471,12 @@ void BigFrequency::paint(Painter& painter) {
// Erase // Erase
painter.fill_rectangle({ { 0, rect.location().y() }, { 240, 52 } }, ui::Color::black()); painter.fill_rectangle({ { 0, rect.location().y() }, { 240, 52 } }, ui::Color::black());
// Prepare digits
if (!_frequency) { if (!_frequency) {
for (i = 0; i < 7; i++) // ----.------ digits.fill(10); // ----.---
digits[i] = 10; digit_pos = { 0, rect.location().y() };
} else { } else {
_frequency /= 1000; // GMMM.KKKuuu _frequency /= 1000; // GMMM.KKK(uuu)
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
digits[6 - i] = _frequency % 10; digits[6 - i] = _frequency % 10;
@ -444,37 +484,38 @@ void BigFrequency::paint(Painter& painter) {
} }
// Remove leading zeros // Remove leading zeros
for (i = 0; i < 7; i++) { for (i = 0; i < 3; i++) {
if (!digits[i]) if (!digits[i])
digits[i] = 16; // "Don't draw" code digits[i] = 16; // "Don't draw" code
else else
break; break;
} }
digit_pos = { (240 - ((7 * digit_width) + 8) - (i * digit_width)) / 2, rect.location().y() };
} }
segment_color = style().foreground; segment_color = style().foreground;
// Draw // Draw
digit_x = rect.location().x(); // 7 * 32 + 8 = 232 (4 px margins)
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
digit = digits[i]; digit = digits[i];
digit_y = rect.location().y();
if (digit < 16) { if (digit < 16) {
digit_def = segment_font[(uint8_t)digit]; digit_def = segment_font[(uint8_t)digit];
if (digit_def & 0x01) painter.fill_rectangle({{digit_x + 4, digit_y}, {20, 4}}, segment_color);
if (digit_def & 0x02) painter.fill_rectangle({{digit_x + 24, digit_y + 4}, {4, 20}}, segment_color); for (size_t s = 0; s < 7; s++) {
if (digit_def & 0x04) painter.fill_rectangle({{digit_x + 24, digit_y + 28}, {4, 20}}, segment_color); if (digit_def & 1)
if (digit_def & 0x08) painter.fill_rectangle({{digit_x + 4, digit_y + 48}, {20, 4}}, segment_color); painter.fill_rectangle({ digit_pos + segments[s].location(), segments[s].size() }, segment_color);
if (digit_def & 0x10) painter.fill_rectangle({{digit_x, digit_y + 28}, {4, 20}}, segment_color); digit_def >>= 1;
if (digit_def & 0x20) painter.fill_rectangle({{digit_x, digit_y + 4}, {4, 20}}, segment_color);
if (digit_def & 0x40) painter.fill_rectangle({{digit_x + 4, digit_y + 24}, {20, 4}}, segment_color);
} }
}
if (i == 3) { if (i == 3) {
// Dot // Dot
painter.fill_rectangle({{digit_x + 34, digit_y + 48}, {4, 4}}, segment_color); painter.fill_rectangle({ digit_pos + Point(34, 48), { 4, 4 } }, segment_color);
digit_x += 40; digit_pos += { (digit_width + 8), 0 };
} else { } else {
digit_x += 32; digit_pos += { digit_width, 0 };
} }
} }
} }

View File

@ -28,6 +28,7 @@
#include "ui_painter.hpp" #include "ui_painter.hpp"
#include "ui_focus.hpp" #include "ui_focus.hpp"
#include "ui_font_fixed_8x16.hpp" #include "ui_font_fixed_8x16.hpp"
#include "rtc_time.hpp"
#include "radio.hpp" #include "radio.hpp"
#include "portapack.hpp" #include "portapack.hpp"
@ -235,6 +236,25 @@ private:
std::vector<Label> labels_; std::vector<Label> labels_;
}; };
class LiveDateTime : public Widget {
public:
LiveDateTime(Rect parent_rect);
~LiveDateTime();
void paint(Painter& painter) override;
std::string& string() {
return text;
}
private:
void on_tick_second();
rtc::RTC datetime { };
SignalToken signal_token_tick_second { };
std::string text { };
};
class BigFrequency : public Widget { class BigFrequency : public Widget {
public: public:
BigFrequency(Rect parent_rect, rf::Frequency frequency); BigFrequency(Rect parent_rect, rf::Frequency frequency);
@ -246,6 +266,8 @@ public:
private: private:
rf::Frequency _frequency; rf::Frequency _frequency;
static constexpr Dim digit_width = 32;
const uint8_t segment_font[11] = { const uint8_t segment_font[11] = {
0b00111111, // 0: ABCDEF 0b00111111, // 0: ABCDEF
0b00000110, // 1: AB 0b00000110, // 1: AB
@ -259,6 +281,16 @@ private:
0b01101111, // 9: ABCDFG 0b01101111, // 9: ABCDFG
0b01000000 // -: G 0b01000000 // -: G
}; };
const Rect segments[7] = {
{{4, 0}, {20, 4}},
{{24, 4}, {4, 20}},
{{24, 28}, {4, 20}},
{{4, 48}, {20, 4}},
{{0, 28}, {4, 20}},
{{0, 4}, {4, 20}},
{{4, 24}, {20, 4}}
};
}; };
class ProgressBar : public Widget { class ProgressBar : public Widget {

Binary file not shown.