From 042d271a9f3c14467b2d40bfd7e3990a25eb10da Mon Sep 17 00:00:00 2001 From: furrtek Date: Sun, 11 Jun 2017 02:53:06 +0100 Subject: [PATCH] Text entry should be more stable Text entry now allows for strings greater than 28 chars Frequency manager save with name bugfix --- firmware/application/ui_adsbtx.cpp | 2 +- firmware/application/ui_alphanum.cpp | 79 +++++++++++++------------- firmware/application/ui_alphanum.hpp | 19 +++---- firmware/application/ui_freqman.cpp | 22 +++---- firmware/application/ui_freqman.hpp | 6 +- firmware/application/ui_handwrite.cpp | 56 +++++++++--------- firmware/application/ui_handwrite.hpp | 12 ++-- firmware/application/ui_lcr.cpp | 6 +- firmware/application/ui_lcr.hpp | 7 +-- firmware/application/ui_morse.cpp | 2 +- firmware/application/ui_navigation.cpp | 3 +- firmware/application/ui_pocsag_tx.cpp | 2 +- firmware/application/ui_rds.cpp | 4 +- firmware/application/ui_textentry.cpp | 18 +++--- firmware/application/ui_textentry.hpp | 3 +- 15 files changed, 116 insertions(+), 125 deletions(-) diff --git a/firmware/application/ui_adsbtx.cpp b/firmware/application/ui_adsbtx.cpp index 7ae4298d..b2e1c569 100644 --- a/firmware/application/ui_adsbtx.cpp +++ b/firmware/application/ui_adsbtx.cpp @@ -136,7 +136,7 @@ ADSBTxView::ADSBTxView(NavigationView& nav) { generate_frame(); }; button_callsign.on_select = [this, &nav](Button&) { - text_entry(nav, callsign, 9); + text_entry(nav, &callsign, 9); }; field_altitude.set_value(11000); diff --git a/firmware/application/ui_alphanum.cpp b/firmware/application/ui_alphanum.cpp index 42e7c660..f5d7c470 100644 --- a/firmware/application/ui_alphanum.cpp +++ b/firmware/application/ui_alphanum.cpp @@ -27,31 +27,30 @@ #include "portapack_shared_memory.hpp" #include +#include using namespace hackrf::one; namespace ui { void AlphanumView::paint(Painter&) { - move_cursor(); + draw_cursor(); } - + AlphanumView::AlphanumView( NavigationView& nav, - std::string& txt, + std::string * str, size_t max_length -) : _max_length(max_length) +) : _max_length(max_length), + _str(str) { size_t n; - txtidx = txt.length(); - txtinput = txt; + // Trim from right + _str->erase(std::find_if(_str->rbegin(), _str->rend(), std::not1(std::ptr_fun(std::isspace))).base(), _str->end()); + cursor_pos = _str->length(); - n = txtidx; - while (n && (txtinput[n - 1] == ' ')) { - txtinput[--n] = 0; - txtidx--; - } + _str->resize(_max_length, 0); add_children({ &text_input, @@ -76,39 +75,40 @@ AlphanumView::AlphanumView( add_child(&button); n++; } + set_mode(mode); - button_mode.on_select = [this, &nav](Button&) { + button_mode.on_select = [this](Button&) { set_mode(mode + 1); }; field_raw.set_value('0'); - field_raw.on_select = [this, &nav](NumberField&) { + field_raw.on_select = [this](NumberField&) { char_add(field_raw.value()); update_text(); }; - button_ok.on_select = [this, &nav, &txt, max_length](Button&) { - txt = txtinput; - if (on_changed) on_changed(this->value()); + button_ok.on_select = [this, &nav](Button&) { + if (on_changed) + on_changed(_str); nav.pop(); }; update_text(); } -void AlphanumView::move_cursor() { - Point cursor_pos; +void AlphanumView::draw_cursor() { + Point draw_pos; - cursor_pos = {text_input.screen_rect().location().x() + (Coord)(txtidx * 8), + draw_pos = {text_input.screen_rect().location().x() + 8 + std::min((Coord)cursor_pos, (Coord)28) * 8, text_input.screen_rect().location().y() + 16}; portapack::display.fill_rectangle( - {{text_input.screen_rect().location().x(), cursor_pos.y()}, {text_input.screen_rect().size().width(), 4}}, + {{text_input.screen_rect().location().x(), draw_pos.y()}, {text_input.screen_rect().size().width(), 4}}, Color::black() ); portapack::display.fill_rectangle( - {cursor_pos, {8, 4}}, + {draw_pos, {8, 4}}, Color::white() ); } @@ -121,7 +121,7 @@ void AlphanumView::set_mode(const uint32_t new_mode) { else mode = 0; - const char * key_list = pages[mode].second; + const char * key_list = key_sets[mode].second; for (auto& button : buttons) { const std::string label { @@ -132,48 +132,47 @@ void AlphanumView::set_mode(const uint32_t new_mode) { } if (mode < 2) - button_mode.set_text(pages[mode + 1].first); + button_mode.set_text(key_sets[mode + 1].first); else - button_mode.set_text(pages[0].first); + button_mode.set_text(key_sets[0].first); } void AlphanumView::focus() { button_ok.focus(); } -std::string AlphanumView::value() { - txtinput[txtidx] = 0; - return txtinput; -} - void AlphanumView::on_button(Button& button) { - const auto s = button.text(); + const auto c = button.text()[0]; - if (s == "<") + if (c == '<') char_delete(); else - char_add(s[0]); + char_add(c); update_text(); } void AlphanumView::char_add(const char c) { - if (txtidx >= _max_length) return; + if (cursor_pos >= _max_length) return; - txtinput[txtidx] = c; - txtidx++; + _str->replace(cursor_pos, 1, 1, c); + cursor_pos++; } void AlphanumView::char_delete() { - if (!txtidx) return; + if (!cursor_pos) return; - txtidx--; - txtinput[txtidx] = 0; + cursor_pos--; + _str->replace(cursor_pos, 1, 1, 0); } void AlphanumView::update_text() { - text_input.set(std::string(txtinput) + std::string(_max_length - txtinput.length(), ' ')); - move_cursor(); + if (cursor_pos <= 28) + text_input.set(' ' + *_str + std::string(_max_length - _str->length(), ' ')); + else + text_input.set('<' + _str->substr(cursor_pos - 28, 28)); + + draw_cursor(); } } diff --git a/firmware/application/ui_alphanum.hpp b/firmware/application/ui_alphanum.hpp index 4d347de4..b3b62558 100644 --- a/firmware/application/ui_alphanum.hpp +++ b/firmware/application/ui_alphanum.hpp @@ -34,21 +34,18 @@ namespace ui { class AlphanumView : public View { public: - std::function on_changed { }; + std::function on_changed { }; - AlphanumView(NavigationView& nav, std::string& txt, size_t max_length); + AlphanumView(NavigationView& nav, std::string * str, size_t max_length); AlphanumView(const AlphanumView&) = delete; AlphanumView(AlphanumView&&) = delete; AlphanumView& operator=(const AlphanumView&) = delete; AlphanumView& operator=(AlphanumView&&) = delete; - void paint(Painter& painter) override; void focus() override; - std::string value(); - std::string title() const override { return "Text entry"; }; private: @@ -56,26 +53,26 @@ private: const char * const keys_lower = "abcdefghijklmnopqrstuvwxyz' .<"; const char * const keys_digit = "0123456789!\"#'()*+-/:;=>?@[\\]<"; - const std::pair pages[3] = { + const std::pair key_sets[3] = { { "Upper", keys_upper }, { "Lower", keys_lower }, { "Digit", keys_digit } }; size_t _max_length { }; - uint32_t txtidx { 0 }; - uint32_t mode = 0; // Upper - std::string txtinput { "" }; // 28 chars max + uint32_t cursor_pos { 0 }; + uint32_t mode = 0; // Uppercase + std::string * _str { }; void char_add(const char c); void char_delete(); void set_mode(const uint32_t new_mode); - void move_cursor(); + void draw_cursor(); void on_button(Button& button); void update_text(); Text text_input { - { 8, 0, 232, 16 } + { 0, 0, 240, 16 } }; std::array buttons { }; diff --git a/firmware/application/ui_freqman.cpp b/firmware/application/ui_freqman.cpp index f87c6f04..fbff9609 100644 --- a/firmware/application/ui_freqman.cpp +++ b/firmware/application/ui_freqman.cpp @@ -25,15 +25,17 @@ #include "portapack.hpp" #include "event_m0.hpp" -#include +//#include using namespace portapack; namespace ui { -void FrequencySaveView::on_save_name(std::string& name) { - database.entries.push_back({ value_, "", name, (int32_t)options_category.selected_index_value() }); - nav_.pop(); +void FrequencySaveView::on_save_name() { + text_entry(nav_, &desc_buffer, 7, [this](std::string * buffer) { + database.entries.push_back({ value_, "", *buffer, (int32_t)options_category.selected_index_value() }); + nav_.pop(); + }); } void FrequencySaveView::on_save_timestamp() { @@ -78,6 +80,8 @@ FrequencySaveView::FrequencySaveView( File freqs_file; size_t n; + desc_buffer.reserve(28); + if (!load_freqman_file(database)) { if (!create_freqman_file(freqs_file)) { error = ERROR_ACCESS; @@ -119,9 +123,7 @@ FrequencySaveView::FrequencySaveView( big_display.set(value); button_save_name.on_select = [this, &nav](Button&) { - text_entry(nav, desc_buffer, 28, [this](std::string buffer) { - on_save_name(buffer); - }); + on_save_name(); }; button_save_timestamp.on_select = [this, &nav](Button&) { on_save_timestamp(); @@ -207,8 +209,8 @@ void FreqManView::on_edit_freq(rf::Frequency f) { } void FreqManView::on_edit_desc(NavigationView& nav) { - text_entry(nav, desc_buffer, 28, [this](std::string buffer) { - database.entries[menu_view.highlighted()].description = buffer; + text_entry(nav, &desc_buffer, 28, [this](std::string * buffer) { + database.entries[menu_view.highlighted()].description = *buffer; //setup_list(); }); } @@ -264,7 +266,7 @@ FreqManView::FreqManView( using options_t = std::vector; options_t categories; size_t n; - + if (!load_freqman_file(database)) { error = ERROR_ACCESS; return; diff --git a/firmware/application/ui_freqman.hpp b/firmware/application/ui_freqman.hpp index bfdfab76..50bc7306 100644 --- a/firmware/application/ui_freqman.hpp +++ b/firmware/application/ui_freqman.hpp @@ -44,13 +44,13 @@ public: private: NavigationView& nav_; freqman_error error { NO_ERROR }; - std::string desc_buffer { "-" }; + std::string desc_buffer { }; rtc::RTC datetime { }; rf::Frequency value_ { }; std::string str_timestamp { }; //int32_t category_id_ { -1 }; - void on_save_name(std::string& name); + void on_save_name(); void on_save_timestamp(); void on_tick_second(); @@ -139,7 +139,7 @@ private: NavigationView& nav_; freqman_error error { NO_ERROR }; - std::string desc_buffer { "-" }; + std::string desc_buffer { }; void on_frequency_select(); void on_edit_freq(rf::Frequency f); diff --git a/firmware/application/ui_handwrite.cpp b/firmware/application/ui_handwrite.cpp index 3108cf10..02aa1405 100644 --- a/firmware/application/ui_handwrite.cpp +++ b/firmware/application/ui_handwrite.cpp @@ -38,23 +38,21 @@ void HandWriteView::paint(Painter& painter) { HandWriteView::HandWriteView( NavigationView& nav, - std::string& txt, + std::string * str, size_t max_length -) : _max_length(max_length) +) : _max_length(max_length), + _str(str) { - const char special_chars[5] = {'\'', '.', '?', '!', '='}; size_t n; + // Trim from right + _str->erase(std::find_if(_str->rbegin(), _str->rend(), std::not1(std::ptr_fun(std::isspace))).base(), _str->end()); + cursor_pos = _str->length(); + + _str->resize(_max_length, 0); + // Handwriting alphabet definition here handwriting = &handwriting_unistroke; - - txtidx = txt.length(); - txtinput = txt; - n = txtidx; - while (n && (txtinput[n - 1] == ' ')) { - txtinput[--n] = 0; - txtidx--; - } add_children({ &text_input, @@ -110,9 +108,9 @@ HandWriteView::HandWriteView( } }; - button_ok.on_select = [this, &nav, &txt, max_length](Button&) { - txt = txtinput; - if (on_changed) on_changed(this->value()); + button_ok.on_select = [this, &nav](Button&) { + if (on_changed) + on_changed(_str); nav.pop(); }; @@ -226,9 +224,9 @@ void HandWriteView::guess_letter() { char_add('A' + symbol - 1); clear_zone(Color::green(), true); // Green flash } else { - if (txtidx) { - txtidx--; - txtinput[txtidx] = 0; // Erase + if (cursor_pos) { + cursor_pos--; + _str->replace(cursor_pos, 1, 1, 0); clear_zone(Color::yellow(), true); // Yellow flash } else { clear_zone(Color::red(), true); // Red flash @@ -261,19 +259,19 @@ void HandWriteView::sample_pen() { // Blink cursor if (!(sample_skip & 15)) { - Point cursor_pos; + Point draw_pos; - cursor_pos = {text_input.screen_rect().location().x() + (txtidx * 8), + draw_pos = {text_input.screen_rect().location().x() + 8 + std::min((Coord)cursor_pos, (Coord)28) * 8, text_input.screen_rect().location().y() + 16 - 4}; if (cursor) { display.fill_rectangle( - {cursor_pos, {text_input.screen_rect().size().width() - cursor_pos.x(), 4}}, + {draw_pos, {text_input.screen_rect().size().width() - draw_pos.x(), 4}}, Color::black() ); } else { display.fill_rectangle( - {cursor_pos, {8, 4}}, + {draw_pos, {8, 4}}, Color::white() ); } @@ -382,25 +380,23 @@ void HandWriteView::on_show() { clear_zone(Color::black(), false); } -std::string HandWriteView::value() { - txtinput[txtidx] = 0; - return txtinput; -} - void HandWriteView::on_button(Button& button) { char_add(button.id); update_text(); } void HandWriteView::char_add(const char c) { - if (txtidx >= _max_length) return; + if (cursor_pos >= _max_length) return; - txtinput[txtidx] = c; - txtidx++; + _str->replace(cursor_pos, 1, 1, c); + cursor_pos++; } void HandWriteView::update_text() { - text_input.set(txtinput); + if (cursor_pos <= 28) + text_input.set(' ' + *_str + std::string(_max_length - _str->length(), ' ')); + else + text_input.set('<' + _str->substr(cursor_pos - 28, 28)); } } diff --git a/firmware/application/ui_handwrite.hpp b/firmware/application/ui_handwrite.hpp index 026cc0fb..35ba1220 100644 --- a/firmware/application/ui_handwrite.hpp +++ b/firmware/application/ui_handwrite.hpp @@ -33,9 +33,9 @@ namespace ui { class HandWriteView : public View { public: - std::function on_changed { }; + std::function on_changed { }; - HandWriteView(NavigationView& nav, std::string& txt, size_t max_length); + HandWriteView(NavigationView& nav, std::string * str, size_t max_length); HandWriteView(const HandWriteView&) = delete; HandWriteView(HandWriteView&&) = delete; @@ -45,19 +45,19 @@ public: void paint(Painter& painter) override; void on_show() override; bool on_touch(const TouchEvent event) override; - - std::string value(); std::string title() const override { return "Text entry"; }; private: + const char special_chars[5] = {'\'', '.', '?', '!', '='}; + const HandWriting * handwriting { }; Painter * _painter { }; size_t _max_length; uint8_t dir_cnt { 0 }; uint8_t dir_prev { 0 }; uint8_t flash_timer { 0 }; - uint8_t txtidx { 0 }; + uint32_t cursor_pos { 0 }; bool cursor { false }; bool tracing { false }; uint8_t stroke_index { 0 }; @@ -65,7 +65,7 @@ private: uint8_t stroke_list[8]; Point start_pos { }, current_pos { }, last_pos { }; bool _lowercase = false; - std::string txtinput { "" }; // 28 chars max + std::string * _str { }; void sample_pen(); void add_stroke(uint8_t dir); diff --git a/firmware/application/ui_lcr.cpp b/firmware/application/ui_lcr.cpp index 2e74a0c4..16046c83 100644 --- a/firmware/application/ui_lcr.cpp +++ b/firmware/application/ui_lcr.cpp @@ -186,7 +186,7 @@ void LCRView::start_tx(const bool scan) { } void LCRView::on_button_setam(NavigationView& nav, Button& button) { - text_entry(nav, litteral[button.id], 7); + text_entry(nav, &litteral[button.id], 7); } LCRView::LCRView(NavigationView& nav) { @@ -247,7 +247,7 @@ LCRView::LCRView(NavigationView& nav) { rectangle.set_parent_rect({ static_cast(98), static_cast(n * 32 + 68 - 2), - 64, 20 + 68, 20 }); rectangle.set_color(ui::Color::grey()); rectangle.set_outline(true); @@ -263,7 +263,7 @@ LCRView::LCRView(NavigationView& nav) { button_scan.set_style(&style_val); button_setrgsb.on_select = [this,&nav](Button&) { - text_entry(nav, rgsb, 4); + text_entry(nav, &rgsb, 4); }; button_txsetup.on_select = [&nav](Button&) { diff --git a/firmware/application/ui_lcr.hpp b/firmware/application/ui_lcr.hpp index 88eaf5e1..b1cfd469 100644 --- a/firmware/application/ui_lcr.hpp +++ b/firmware/application/ui_lcr.hpp @@ -81,7 +81,7 @@ private: tx_modes tx_mode = IDLE; uint8_t scan_count { 0 }, scan_index { 0 }; uint32_t scan_progress { 0 }; - std::string litteral[5] { " " }; + std::string litteral[5] { { " " } }; std::string rgsb { " " }; char lcr_message[512]; uint16_t lcr_message_data[256]; @@ -107,7 +107,7 @@ private: Labels labels { { { 2 * 8, 4 }, "EC:", Color::light_grey() }, - { { 88, 268 }, "Scan list:", Color::light_grey() } + { { 84, 268 }, "Scan list:", Color::light_grey() } }; std::array buttons { }; @@ -158,10 +158,9 @@ private: }; OptionsField options_scanlist { - { 88, 284 }, + { 84, 284 }, 6, { - { "Lille ", 0 }, { "Reims ", 1 } } }; diff --git a/firmware/application/ui_morse.cpp b/firmware/application/ui_morse.cpp index dddca2bb..b3864c58 100644 --- a/firmware/application/ui_morse.cpp +++ b/firmware/application/ui_morse.cpp @@ -71,7 +71,7 @@ static msg_t ookthread_fn(void * arg) { } void MorseView::on_set_text(NavigationView& nav) { - text_entry(nav, buffer, 28); + text_entry(nav, &buffer, 28); } void MorseView::focus() { diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index b4d1bfda..0df94e87 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -22,12 +22,13 @@ #include "ui_navigation.hpp" -#include "modules.h" +//#include "modules.h" #include "portapack.hpp" #include "event_m0.hpp" #include "bmp_splash.hpp" #include "bmp_modal_warning.hpp" +#include "portapack_persistent_memory.hpp" #include "ui_about.hpp" #include "ui_adsbtx.hpp" diff --git a/firmware/application/ui_pocsag_tx.cpp b/firmware/application/ui_pocsag_tx.cpp index d2a9326d..6ae794bb 100644 --- a/firmware/application/ui_pocsag_tx.cpp +++ b/firmware/application/ui_pocsag_tx.cpp @@ -124,7 +124,7 @@ void POCSAGTXView::paint(Painter&) { } void POCSAGTXView::on_set_text(NavigationView& nav) { - text_entry(nav, buffer, 16); + text_entry(nav, &buffer, 16); } POCSAGTXView::POCSAGTXView( diff --git a/firmware/application/ui_rds.cpp b/firmware/application/ui_rds.cpp index 9546532d..3429ddb6 100644 --- a/firmware/application/ui_rds.cpp +++ b/firmware/application/ui_rds.cpp @@ -136,11 +136,11 @@ RDSView::RDSView(NavigationView& nav) { options_coverage.set_selected_index(0); // Local button_editpsn.on_select = [this, &nav](Button&) { - text_entry(nav, PSN, 8); + text_entry(nav, &PSN, 8); }; button_editradiotext.on_select = [this, &nav](Button&){ - text_entry(nav, RadioText, 24); + text_entry(nav, &RadioText, 24); }; } diff --git a/firmware/application/ui_textentry.cpp b/firmware/application/ui_textentry.cpp index 514e95d3..5631aca1 100644 --- a/firmware/application/ui_textentry.cpp +++ b/firmware/application/ui_textentry.cpp @@ -21,26 +21,24 @@ */ #include "ui_textentry.hpp" +#include "portapack_persistent_memory.hpp" namespace ui { -bool text_entry(NavigationView& nav, std::string& str, const size_t max_length, const std::function on_done) { - +void text_entry(NavigationView& nav, std::string * str, const size_t max_length, const std::function on_done) { if (portapack::persistent_memory::ui_config_textentry() == 0) { auto te_view = nav.push(str, max_length); - te_view->on_changed = [str, max_length, on_done](std::string value) { - //memcpy(str, value, max_length + 1); - if (on_done) on_done(value); + te_view->on_changed = [on_done](std::string * value) { + if (on_done) + on_done(value); }; } else { auto te_view = nav.push(str, max_length); - te_view->on_changed = [str, max_length, on_done](std::string value) { - //memcpy(str, value, max_length + 1); - if (on_done) on_done(value); + te_view->on_changed = [on_done](std::string * value) { + if (on_done) + on_done(value); }; } - - return true; } } /* namespace ui */ diff --git a/firmware/application/ui_textentry.hpp b/firmware/application/ui_textentry.hpp index b10e8119..39985197 100644 --- a/firmware/application/ui_textentry.hpp +++ b/firmware/application/ui_textentry.hpp @@ -27,11 +27,10 @@ #include "ui_navigation.hpp" #include "ui_handwrite.hpp" #include "ui_alphanum.hpp" -#include "portapack_persistent_memory.hpp" namespace ui { -bool text_entry(NavigationView& nav, std::string& str, size_t max_length, const std::function on_done = nullptr); +void text_entry(NavigationView& nav, std::string * str, size_t max_length, const std::function on_done = nullptr); } /* namespace ui */