mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
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:
parent
37ce81383d
commit
c0f51c2690
@ -177,7 +177,7 @@ set(CPPSRC
|
||||
ui_font_fixed_8x16.cpp
|
||||
ui_freqman.cpp
|
||||
ui_geomap.cpp
|
||||
ui_handwrite.cpp
|
||||
# ui_handwrite.cpp
|
||||
ui_jammer.cpp
|
||||
ui_lcr.cpp
|
||||
ui_menu.cpp
|
||||
|
@ -36,6 +36,7 @@ void FileManBaseView::load_directory_contents(const std::filesystem::path& dir_p
|
||||
|
||||
entry_list.clear();
|
||||
|
||||
// List all directories and files, put directories up top
|
||||
for (const auto& entry : std::filesystem::directory_iterator(dir_path, u"*")) {
|
||||
if (std::filesystem::is_regular_file(entry.status())) {
|
||||
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::string current_path_str = current_path.string();
|
||||
std::filesystem::path FileManBaseView::get_selected_path() {
|
||||
std::string selected_path_str = current_path.string();
|
||||
|
||||
if (current_path_str.back() != '/')
|
||||
current_path_str += '/';
|
||||
current_path_str += (entry_list[menu_view.highlighted()].entry_path.string());
|
||||
if (selected_path_str.back() != '/')
|
||||
selected_path_str += '/';
|
||||
selected_path_str += (entry_list[menu_view.highlighted()].entry_path.string());
|
||||
|
||||
return current_path_str;
|
||||
return selected_path_str;
|
||||
}
|
||||
|
||||
FileManBaseView::FileManBaseView(
|
||||
@ -62,13 +63,22 @@ FileManBaseView::FileManBaseView(
|
||||
load_directory_contents(current_path);
|
||||
|
||||
if (!entry_list.size())
|
||||
error_ = true;
|
||||
empty_root = true;
|
||||
|
||||
add_children({
|
||||
&labels,
|
||||
&text_current,
|
||||
&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&) {
|
||||
nav.pop();
|
||||
@ -76,8 +86,7 @@ FileManBaseView::FileManBaseView(
|
||||
};
|
||||
|
||||
void FileManBaseView::focus() {
|
||||
|
||||
if (error_) {
|
||||
if (empty_root) {
|
||||
button_exit.focus();
|
||||
nav_.display_modal("Error", "No files in root.", ABORT, nullptr);
|
||||
} else {
|
||||
@ -91,16 +100,18 @@ void FileManBaseView::refresh_list() {
|
||||
size_t file_size;
|
||||
|
||||
if (!entry_list.size()) {
|
||||
// Hide widgets, show warning
|
||||
if (on_refresh_widgets)
|
||||
on_refresh_widgets(true);
|
||||
} else {
|
||||
// Hide warning, show widgets
|
||||
if (on_refresh_widgets)
|
||||
on_refresh_widgets(false);
|
||||
|
||||
menu_view.clear();
|
||||
|
||||
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) {
|
||||
|
||||
@ -145,47 +156,28 @@ void FileManBaseView::refresh_list() {
|
||||
}
|
||||
}
|
||||
|
||||
void FileSaveView::on_save_name() {
|
||||
/*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);
|
||||
/*void FileSaveView::on_save_name() {
|
||||
text_prompt(nav_, &filename_buffer, 8, [this](std::string * buffer) {
|
||||
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(
|
||||
NavigationView& nav
|
||||
) : FileManBaseView(nav)
|
||||
{
|
||||
filename_buffer.reserve(8);
|
||||
|
||||
signal_token_tick_second = rtc_time::signal_tick_second += [this]() {
|
||||
this->on_tick_second();
|
||||
};
|
||||
name_buffer.clear();
|
||||
|
||||
add_children({
|
||||
&text_save,
|
||||
&button_save_name,
|
||||
&text_timestamp
|
||||
&live_timestamp
|
||||
});
|
||||
|
||||
on_tick_second();
|
||||
|
||||
button_save_name.on_select = [this, &nav](Button&) {
|
||||
on_save_name();
|
||||
};
|
||||
}
|
||||
}*/
|
||||
|
||||
void FileLoadView::refresh_widgets(const bool v) {
|
||||
menu_view.hidden(v);
|
||||
@ -224,15 +216,15 @@ FileLoadView::FileLoadView(
|
||||
}
|
||||
|
||||
void FileManagerView::on_rename(NavigationView& nav) {
|
||||
text_prompt(nav, &filename_buffer, 12, [this](std::string * buffer) {
|
||||
rename_file(get_absolute_path(), *buffer);
|
||||
text_prompt(nav, &name_buffer, 12, [this](std::string * buffer) {
|
||||
rename_file(get_selected_path(), *buffer);
|
||||
load_directory_contents(current_path);
|
||||
refresh_list();
|
||||
});
|
||||
}
|
||||
|
||||
void FileManagerView::on_delete() {
|
||||
delete_file(get_absolute_path());
|
||||
delete_file(get_selected_path());
|
||||
load_directory_contents(current_path);
|
||||
refresh_list();
|
||||
}
|
||||
@ -259,7 +251,6 @@ FileManagerView::FileManagerView(
|
||||
};
|
||||
|
||||
add_children({
|
||||
//&labels,
|
||||
&menu_view,
|
||||
&text_empty,
|
||||
&button_rename,
|
||||
@ -267,29 +258,20 @@ FileManagerView::FileManagerView(
|
||||
&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();
|
||||
|
||||
on_select_entry = [this]() {
|
||||
if (entry_list[menu_view.highlighted()].is_directory) {
|
||||
load_directory_contents(get_absolute_path());
|
||||
load_directory_contents(get_selected_path());
|
||||
refresh_list();
|
||||
} else
|
||||
button_rename.focus();
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
make_new_directory(current_path.string() + '/' + path_str);
|
||||
@ -300,7 +282,7 @@ FileManagerView::FileManagerView(
|
||||
|
||||
button_rename.on_select = [this, &nav](Button&) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "file.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_textentry.hpp"
|
||||
#include "rtc_time.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@ -46,7 +45,7 @@ public:
|
||||
void focus() override;
|
||||
|
||||
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"; };
|
||||
|
||||
@ -55,7 +54,7 @@ protected:
|
||||
|
||||
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(bool)> on_refresh_widgets { nullptr };
|
||||
std::vector<fileman_entry> entry_list { };
|
||||
@ -87,20 +86,15 @@ protected:
|
||||
};
|
||||
};
|
||||
|
||||
class FileSaveView : public FileManBaseView {
|
||||
/*class FileSaveView : public FileManBaseView {
|
||||
public:
|
||||
FileSaveView(NavigationView& nav);
|
||||
~FileSaveView();
|
||||
|
||||
private:
|
||||
std::string filename_buffer { };
|
||||
rtc::RTC datetime { };
|
||||
std::string str_timestamp { };
|
||||
std::string name_buffer { };
|
||||
|
||||
void on_save_name();
|
||||
void on_tick_second();
|
||||
|
||||
SignalToken signal_token_tick_second { };
|
||||
|
||||
Text text_save {
|
||||
{ 4 * 8, 15 * 8, 8 * 8, 16 },
|
||||
@ -110,11 +104,10 @@ private:
|
||||
{ 4 * 8, 18 * 8, 12 * 8, 32 },
|
||||
"Name (set)"
|
||||
};
|
||||
Text text_timestamp {
|
||||
{ 17 * 8, 24 * 8, 11 * 8, 16 },
|
||||
"MM/DD HH:MM",
|
||||
LiveDateTime live_timestamp {
|
||||
{ 17 * 8, 24 * 8, 11 * 8, 16 }
|
||||
};
|
||||
};
|
||||
};*/
|
||||
|
||||
class FileLoadView : public FileManBaseView {
|
||||
public:
|
||||
@ -132,16 +125,12 @@ public:
|
||||
~FileManagerView();
|
||||
|
||||
private:
|
||||
std::string filename_buffer { };
|
||||
std::string name_buffer { };
|
||||
|
||||
void refresh_widgets(const bool v);
|
||||
void on_rename(NavigationView& nav);
|
||||
void on_delete();
|
||||
|
||||
/*Labels labels {
|
||||
{ { 4 * 8 + 4, 26 * 8 }, "Edit:", Color::light_grey() }
|
||||
};*/
|
||||
|
||||
Button button_rename {
|
||||
{ 0 * 8, 28 * 8, 14 * 8, 32 },
|
||||
"Rename"
|
||||
|
@ -134,22 +134,11 @@ void FrequencySaveView::on_save_name() {
|
||||
}
|
||||
|
||||
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);
|
||||
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(
|
||||
NavigationView& nav,
|
||||
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({
|
||||
&labels,
|
||||
&big_display,
|
||||
&text_save,
|
||||
&button_save_name,
|
||||
&button_save_timestamp,
|
||||
&text_timestamp
|
||||
&live_timestamp
|
||||
});
|
||||
|
||||
on_tick_second();
|
||||
|
||||
big_display.set(value);
|
||||
|
||||
button_save_name.on_select = [this, &nav](Button&) {
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_textentry.hpp"
|
||||
#include "freqman.hpp"
|
||||
#include "rtc_time.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@ -89,40 +88,33 @@ protected:
|
||||
class FrequencySaveView : public FreqManBaseView {
|
||||
public:
|
||||
FrequencySaveView(NavigationView& nav, const rf::Frequency value);
|
||||
~FrequencySaveView();
|
||||
|
||||
private:
|
||||
std::string desc_buffer { };
|
||||
rtc::RTC datetime { };
|
||||
rf::Frequency value_ { };
|
||||
std::string str_timestamp { };
|
||||
|
||||
void on_save_name();
|
||||
void on_save_timestamp();
|
||||
void on_tick_second();
|
||||
|
||||
SignalToken signal_token_tick_second { };
|
||||
|
||||
BigFrequency big_display {
|
||||
{ 4, 2 * 16, 28 * 8, 32 },
|
||||
0
|
||||
};
|
||||
|
||||
Text text_save {
|
||||
{ 4 * 8, 15 * 8, 8 * 8, 16 },
|
||||
"Save as:",
|
||||
Labels labels {
|
||||
{ { 2 * 8, 14 * 8 }, "Save as:", Color::white() }
|
||||
};
|
||||
|
||||
Button button_save_name {
|
||||
{ 4 * 8, 18 * 8, 12 * 8, 32 },
|
||||
{ 2 * 8, 17 * 8, 14 * 8, 48 },
|
||||
"Name (set)"
|
||||
};
|
||||
Button button_save_timestamp {
|
||||
{ 4 * 8, 23 * 8, 12 * 8, 32 },
|
||||
{ 2 * 8, 25 * 8, 14 * 8, 48 },
|
||||
"Timestamp:"
|
||||
};
|
||||
Text text_timestamp {
|
||||
{ 17 * 8, 24 * 8, 11 * 8, 16 },
|
||||
"MM/DD HH:MM",
|
||||
LiveDateTime live_timestamp {
|
||||
{ 17 * 8, 27 * 8, 11 * 8, 16 }
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -87,7 +87,7 @@ SystemStatusView::SystemStatusView() {
|
||||
&button_back,
|
||||
&title,
|
||||
&button_stealth,
|
||||
&button_textentry,
|
||||
//&button_textentry,
|
||||
&button_camera,
|
||||
&button_sleep,
|
||||
&sd_card_status_view,
|
||||
@ -96,10 +96,10 @@ SystemStatusView::SystemStatusView() {
|
||||
button_back.id = -1; // Special ID used by FocusManager
|
||||
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);
|
||||
else
|
||||
button_textentry.set_bitmap(&bitmap_icon_unistroke);
|
||||
button_textentry.set_bitmap(&bitmap_icon_unistroke);*/
|
||||
|
||||
if (portapack::persistent_memory::stealth_mode())
|
||||
button_stealth.set_foreground(ui::Color::green());
|
||||
@ -113,9 +113,9 @@ SystemStatusView::SystemStatusView() {
|
||||
this->on_stealth();
|
||||
};
|
||||
|
||||
button_textentry.on_select = [this](ImageButton&) {
|
||||
/*button_textentry.on_select = [this](ImageButton&) {
|
||||
this->on_textentry();
|
||||
};
|
||||
};*/
|
||||
|
||||
button_camera.on_select = [this](ImageButton&) {
|
||||
this->on_camera();
|
||||
@ -154,7 +154,7 @@ void SystemStatusView::on_stealth() {
|
||||
button_stealth.set_dirty();
|
||||
}
|
||||
|
||||
void SystemStatusView::on_textentry() {
|
||||
/*void SystemStatusView::on_textentry() {
|
||||
uint8_t cfg;
|
||||
|
||||
cfg = portapack::persistent_memory::ui_config_textentry();
|
||||
@ -164,7 +164,7 @@ void SystemStatusView::on_textentry() {
|
||||
button_textentry.set_bitmap(&bitmap_icon_unistroke);
|
||||
else
|
||||
button_textentry.set_bitmap(&bitmap_icon_keyboard);
|
||||
}
|
||||
}*/
|
||||
|
||||
void SystemStatusView::on_camera() {
|
||||
auto path = next_filename_stem_matching_pattern(u"SCR_????");
|
||||
|
@ -83,18 +83,18 @@ private:
|
||||
};
|
||||
|
||||
ImageButton button_stealth {
|
||||
{ 152, 0, 2 * 8, 1 * 16 },
|
||||
{ 170, 0, 2 * 8, 1 * 16 },
|
||||
&bitmap_icon_stealth,
|
||||
Color::light_grey(),
|
||||
Color::dark_grey()
|
||||
};
|
||||
|
||||
ImageButton button_textentry {
|
||||
/*ImageButton button_textentry {
|
||||
{ 170, 0, 2 * 8, 1 * 16 },
|
||||
&bitmap_icon_unistroke,
|
||||
Color::white(),
|
||||
Color::dark_grey()
|
||||
};
|
||||
};*/
|
||||
|
||||
ImageButton button_camera {
|
||||
{ 188, 0, 2 * 8, 1 * 16 },
|
||||
@ -115,7 +115,7 @@ private:
|
||||
};
|
||||
|
||||
void on_stealth();
|
||||
void on_textentry();
|
||||
//void on_textentry();
|
||||
void on_camera();
|
||||
};
|
||||
|
||||
@ -143,7 +143,7 @@ public:
|
||||
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, 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;
|
||||
|
||||
|
@ -21,28 +21,28 @@
|
||||
*/
|
||||
|
||||
#include "ui_textentry.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "ui_handwrite.hpp"
|
||||
//#include "portapack_persistent_memory.hpp"
|
||||
#include "ui_alphanum.hpp"
|
||||
//#include "ui_handwrite.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
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);
|
||||
te_view->on_changed = [on_done](std::string * value) {
|
||||
if (on_done)
|
||||
on_done(value);
|
||||
};
|
||||
} else {
|
||||
/*} else {
|
||||
auto te_view = nav.push<HandWriteView>(str, max_length);
|
||||
te_view->on_changed = [on_done](std::string * value) {
|
||||
if (on_done)
|
||||
on_done(value);
|
||||
};
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void TextEntryView::update_text() {
|
||||
|
@ -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(
|
||||
@ -422,21 +461,22 @@ void BigFrequency::set(const rf::Frequency frequency) {
|
||||
|
||||
void BigFrequency::paint(Painter& painter) {
|
||||
uint32_t i, digit_def;
|
||||
char digits[7];
|
||||
std::array<char, 7> digits;
|
||||
char digit;
|
||||
Coord digit_x, digit_y;
|
||||
Point digit_pos;
|
||||
ui::Color segment_color;
|
||||
|
||||
const auto rect = screen_rect();
|
||||
|
||||
// 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) {
|
||||
for (i = 0; i < 7; i++) // ----.------
|
||||
digits[i] = 10;
|
||||
digits.fill(10); // ----.---
|
||||
digit_pos = { 0, rect.location().y() };
|
||||
} else {
|
||||
_frequency /= 1000; // GMMM.KKKuuu
|
||||
_frequency /= 1000; // GMMM.KKK(uuu)
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
digits[6 - i] = _frequency % 10;
|
||||
@ -444,37 +484,38 @@ void BigFrequency::paint(Painter& painter) {
|
||||
}
|
||||
|
||||
// Remove leading zeros
|
||||
for (i = 0; i < 7; i++) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!digits[i])
|
||||
digits[i] = 16; // "Don't draw" code
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
digit_pos = { (240 - ((7 * digit_width) + 8) - (i * digit_width)) / 2, rect.location().y() };
|
||||
}
|
||||
|
||||
segment_color = style().foreground;
|
||||
|
||||
// Draw
|
||||
digit_x = rect.location().x(); // 7 * 32 + 8 = 232 (4 px margins)
|
||||
for (i = 0; i < 7; i++) {
|
||||
digit = digits[i];
|
||||
digit_y = rect.location().y();
|
||||
|
||||
if (digit < 16) {
|
||||
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);
|
||||
if (digit_def & 0x04) painter.fill_rectangle({{digit_x + 24, digit_y + 28}, {4, 20}}, segment_color);
|
||||
if (digit_def & 0x08) painter.fill_rectangle({{digit_x + 4, digit_y + 48}, {20, 4}}, segment_color);
|
||||
if (digit_def & 0x10) painter.fill_rectangle({{digit_x, digit_y + 28}, {4, 20}}, segment_color);
|
||||
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);
|
||||
|
||||
for (size_t s = 0; s < 7; s++) {
|
||||
if (digit_def & 1)
|
||||
painter.fill_rectangle({ digit_pos + segments[s].location(), segments[s].size() }, segment_color);
|
||||
digit_def >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 3) {
|
||||
// Dot
|
||||
painter.fill_rectangle({{digit_x + 34, digit_y + 48}, {4, 4}}, segment_color);
|
||||
digit_x += 40;
|
||||
painter.fill_rectangle({ digit_pos + Point(34, 48), { 4, 4 } }, segment_color);
|
||||
digit_pos += { (digit_width + 8), 0 };
|
||||
} else {
|
||||
digit_x += 32;
|
||||
digit_pos += { digit_width, 0 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "ui_painter.hpp"
|
||||
#include "ui_focus.hpp"
|
||||
#include "ui_font_fixed_8x16.hpp"
|
||||
#include "rtc_time.hpp"
|
||||
#include "radio.hpp"
|
||||
|
||||
#include "portapack.hpp"
|
||||
@ -235,6 +236,25 @@ private:
|
||||
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 {
|
||||
public:
|
||||
BigFrequency(Rect parent_rect, rf::Frequency frequency);
|
||||
@ -246,6 +266,8 @@ public:
|
||||
private:
|
||||
rf::Frequency _frequency;
|
||||
|
||||
static constexpr Dim digit_width = 32;
|
||||
|
||||
const uint8_t segment_font[11] = {
|
||||
0b00111111, // 0: ABCDEF
|
||||
0b00000110, // 1: AB
|
||||
@ -259,6 +281,16 @@ private:
|
||||
0b01101111, // 9: ABCDFG
|
||||
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 {
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user