Text entry should be more stable

Text entry now allows for strings greater than 28 chars
Frequency manager save with name bugfix
This commit is contained in:
furrtek 2017-06-11 02:53:06 +01:00
parent b3aa4bf0b9
commit 042d271a9f
15 changed files with 116 additions and 125 deletions

View File

@ -136,7 +136,7 @@ ADSBTxView::ADSBTxView(NavigationView& nav) {
generate_frame(); generate_frame();
}; };
button_callsign.on_select = [this, &nav](Button&) { button_callsign.on_select = [this, &nav](Button&) {
text_entry(nav, callsign, 9); text_entry(nav, &callsign, 9);
}; };
field_altitude.set_value(11000); field_altitude.set_value(11000);

View File

@ -27,31 +27,30 @@
#include "portapack_shared_memory.hpp" #include "portapack_shared_memory.hpp"
#include <cstring> #include <cstring>
#include <algorithm>
using namespace hackrf::one; using namespace hackrf::one;
namespace ui { namespace ui {
void AlphanumView::paint(Painter&) { void AlphanumView::paint(Painter&) {
move_cursor(); draw_cursor();
} }
AlphanumView::AlphanumView( AlphanumView::AlphanumView(
NavigationView& nav, NavigationView& nav,
std::string& txt, std::string * str,
size_t max_length size_t max_length
) : _max_length(max_length) ) : _max_length(max_length),
_str(str)
{ {
size_t n; size_t n;
txtidx = txt.length(); // Trim from right
txtinput = txt; _str->erase(std::find_if(_str->rbegin(), _str->rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), _str->end());
cursor_pos = _str->length();
n = txtidx; _str->resize(_max_length, 0);
while (n && (txtinput[n - 1] == ' ')) {
txtinput[--n] = 0;
txtidx--;
}
add_children({ add_children({
&text_input, &text_input,
@ -76,39 +75,40 @@ AlphanumView::AlphanumView(
add_child(&button); add_child(&button);
n++; n++;
} }
set_mode(mode); set_mode(mode);
button_mode.on_select = [this, &nav](Button&) { button_mode.on_select = [this](Button&) {
set_mode(mode + 1); set_mode(mode + 1);
}; };
field_raw.set_value('0'); field_raw.set_value('0');
field_raw.on_select = [this, &nav](NumberField&) { field_raw.on_select = [this](NumberField&) {
char_add(field_raw.value()); char_add(field_raw.value());
update_text(); update_text();
}; };
button_ok.on_select = [this, &nav, &txt, max_length](Button&) { button_ok.on_select = [this, &nav](Button&) {
txt = txtinput; if (on_changed)
if (on_changed) on_changed(this->value()); on_changed(_str);
nav.pop(); nav.pop();
}; };
update_text(); update_text();
} }
void AlphanumView::move_cursor() { void AlphanumView::draw_cursor() {
Point cursor_pos; 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}; text_input.screen_rect().location().y() + 16};
portapack::display.fill_rectangle( 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() Color::black()
); );
portapack::display.fill_rectangle( portapack::display.fill_rectangle(
{cursor_pos, {8, 4}}, {draw_pos, {8, 4}},
Color::white() Color::white()
); );
} }
@ -121,7 +121,7 @@ void AlphanumView::set_mode(const uint32_t new_mode) {
else else
mode = 0; mode = 0;
const char * key_list = pages[mode].second; const char * key_list = key_sets[mode].second;
for (auto& button : buttons) { for (auto& button : buttons) {
const std::string label { const std::string label {
@ -132,48 +132,47 @@ void AlphanumView::set_mode(const uint32_t new_mode) {
} }
if (mode < 2) if (mode < 2)
button_mode.set_text(pages[mode + 1].first); button_mode.set_text(key_sets[mode + 1].first);
else else
button_mode.set_text(pages[0].first); button_mode.set_text(key_sets[0].first);
} }
void AlphanumView::focus() { void AlphanumView::focus() {
button_ok.focus(); button_ok.focus();
} }
std::string AlphanumView::value() {
txtinput[txtidx] = 0;
return txtinput;
}
void AlphanumView::on_button(Button& button) { void AlphanumView::on_button(Button& button) {
const auto s = button.text(); const auto c = button.text()[0];
if (s == "<") if (c == '<')
char_delete(); char_delete();
else else
char_add(s[0]); char_add(c);
update_text(); update_text();
} }
void AlphanumView::char_add(const char c) { void AlphanumView::char_add(const char c) {
if (txtidx >= _max_length) return; if (cursor_pos >= _max_length) return;
txtinput[txtidx] = c; _str->replace(cursor_pos, 1, 1, c);
txtidx++; cursor_pos++;
} }
void AlphanumView::char_delete() { void AlphanumView::char_delete() {
if (!txtidx) return; if (!cursor_pos) return;
txtidx--; cursor_pos--;
txtinput[txtidx] = 0; _str->replace(cursor_pos, 1, 1, 0);
} }
void AlphanumView::update_text() { void AlphanumView::update_text() {
text_input.set(std::string(txtinput) + std::string(_max_length - txtinput.length(), ' ')); if (cursor_pos <= 28)
move_cursor(); text_input.set(' ' + *_str + std::string(_max_length - _str->length(), ' '));
else
text_input.set('<' + _str->substr(cursor_pos - 28, 28));
draw_cursor();
} }
} }

View File

@ -34,21 +34,18 @@ namespace ui {
class AlphanumView : public View { class AlphanumView : public View {
public: public:
std::function<void(std::string)> on_changed { }; std::function<void(std::string*)> 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(const AlphanumView&) = delete;
AlphanumView(AlphanumView&&) = delete; AlphanumView(AlphanumView&&) = delete;
AlphanumView& operator=(const AlphanumView&) = delete; AlphanumView& operator=(const AlphanumView&) = delete;
AlphanumView& operator=(AlphanumView&&) = delete; AlphanumView& operator=(AlphanumView&&) = delete;
void paint(Painter& painter) override; void paint(Painter& painter) override;
void focus() override; void focus() override;
std::string value();
std::string title() const override { return "Text entry"; }; std::string title() const override { return "Text entry"; };
private: private:
@ -56,26 +53,26 @@ private:
const char * const keys_lower = "abcdefghijklmnopqrstuvwxyz' .<"; const char * const keys_lower = "abcdefghijklmnopqrstuvwxyz' .<";
const char * const keys_digit = "0123456789!\"#'()*+-/:;=>?@[\\]<"; const char * const keys_digit = "0123456789!\"#'()*+-/:;=>?@[\\]<";
const std::pair<std::string, const char *> pages[3] = { const std::pair<std::string, const char *> key_sets[3] = {
{ "Upper", keys_upper }, { "Upper", keys_upper },
{ "Lower", keys_lower }, { "Lower", keys_lower },
{ "Digit", keys_digit } { "Digit", keys_digit }
}; };
size_t _max_length { }; size_t _max_length { };
uint32_t txtidx { 0 }; uint32_t cursor_pos { 0 };
uint32_t mode = 0; // Upper uint32_t mode = 0; // Uppercase
std::string txtinput { "" }; // 28 chars max std::string * _str { };
void char_add(const char c); void char_add(const char c);
void char_delete(); void char_delete();
void set_mode(const uint32_t new_mode); void set_mode(const uint32_t new_mode);
void move_cursor(); void draw_cursor();
void on_button(Button& button); void on_button(Button& button);
void update_text(); void update_text();
Text text_input { Text text_input {
{ 8, 0, 232, 16 } { 0, 0, 240, 16 }
}; };
std::array<Button, 30> buttons { }; std::array<Button, 30> buttons { };

View File

@ -25,15 +25,17 @@
#include "portapack.hpp" #include "portapack.hpp"
#include "event_m0.hpp" #include "event_m0.hpp"
#include <cstring> //#include <cstring>
using namespace portapack; using namespace portapack;
namespace ui { namespace ui {
void FrequencySaveView::on_save_name(std::string& name) { void FrequencySaveView::on_save_name() {
database.entries.push_back({ value_, "", name, (int32_t)options_category.selected_index_value() }); text_entry(nav_, &desc_buffer, 7, [this](std::string * buffer) {
nav_.pop(); database.entries.push_back({ value_, "", *buffer, (int32_t)options_category.selected_index_value() });
nav_.pop();
});
} }
void FrequencySaveView::on_save_timestamp() { void FrequencySaveView::on_save_timestamp() {
@ -78,6 +80,8 @@ FrequencySaveView::FrequencySaveView(
File freqs_file; File freqs_file;
size_t n; size_t n;
desc_buffer.reserve(28);
if (!load_freqman_file(database)) { if (!load_freqman_file(database)) {
if (!create_freqman_file(freqs_file)) { if (!create_freqman_file(freqs_file)) {
error = ERROR_ACCESS; error = ERROR_ACCESS;
@ -119,9 +123,7 @@ FrequencySaveView::FrequencySaveView(
big_display.set(value); big_display.set(value);
button_save_name.on_select = [this, &nav](Button&) { button_save_name.on_select = [this, &nav](Button&) {
text_entry(nav, desc_buffer, 28, [this](std::string buffer) { on_save_name();
on_save_name(buffer);
});
}; };
button_save_timestamp.on_select = [this, &nav](Button&) { button_save_timestamp.on_select = [this, &nav](Button&) {
on_save_timestamp(); on_save_timestamp();
@ -207,8 +209,8 @@ void FreqManView::on_edit_freq(rf::Frequency f) {
} }
void FreqManView::on_edit_desc(NavigationView& nav) { void FreqManView::on_edit_desc(NavigationView& nav) {
text_entry(nav, desc_buffer, 28, [this](std::string buffer) { text_entry(nav, &desc_buffer, 28, [this](std::string * buffer) {
database.entries[menu_view.highlighted()].description = buffer; database.entries[menu_view.highlighted()].description = *buffer;
//setup_list(); //setup_list();
}); });
} }

View File

@ -44,13 +44,13 @@ public:
private: private:
NavigationView& nav_; NavigationView& nav_;
freqman_error error { NO_ERROR }; freqman_error error { NO_ERROR };
std::string desc_buffer { "-" }; std::string desc_buffer { };
rtc::RTC datetime { }; rtc::RTC datetime { };
rf::Frequency value_ { }; rf::Frequency value_ { };
std::string str_timestamp { }; std::string str_timestamp { };
//int32_t category_id_ { -1 }; //int32_t category_id_ { -1 };
void on_save_name(std::string& name); void on_save_name();
void on_save_timestamp(); void on_save_timestamp();
void on_tick_second(); void on_tick_second();
@ -139,7 +139,7 @@ private:
NavigationView& nav_; NavigationView& nav_;
freqman_error error { NO_ERROR }; freqman_error error { NO_ERROR };
std::string desc_buffer { "-" }; std::string desc_buffer { };
void on_frequency_select(); void on_frequency_select();
void on_edit_freq(rf::Frequency f); void on_edit_freq(rf::Frequency f);

View File

@ -38,24 +38,22 @@ void HandWriteView::paint(Painter& painter) {
HandWriteView::HandWriteView( HandWriteView::HandWriteView(
NavigationView& nav, NavigationView& nav,
std::string& txt, std::string * str,
size_t max_length size_t max_length
) : _max_length(max_length) ) : _max_length(max_length),
_str(str)
{ {
const char special_chars[5] = {'\'', '.', '?', '!', '='};
size_t n; size_t n;
// Trim from right
_str->erase(std::find_if(_str->rbegin(), _str->rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), _str->end());
cursor_pos = _str->length();
_str->resize(_max_length, 0);
// Handwriting alphabet definition here // Handwriting alphabet definition here
handwriting = &handwriting_unistroke; handwriting = &handwriting_unistroke;
txtidx = txt.length();
txtinput = txt;
n = txtidx;
while (n && (txtinput[n - 1] == ' ')) {
txtinput[--n] = 0;
txtidx--;
}
add_children({ add_children({
&text_input, &text_input,
&button_case, &button_case,
@ -110,9 +108,9 @@ HandWriteView::HandWriteView(
} }
}; };
button_ok.on_select = [this, &nav, &txt, max_length](Button&) { button_ok.on_select = [this, &nav](Button&) {
txt = txtinput; if (on_changed)
if (on_changed) on_changed(this->value()); on_changed(_str);
nav.pop(); nav.pop();
}; };
@ -226,9 +224,9 @@ void HandWriteView::guess_letter() {
char_add('A' + symbol - 1); char_add('A' + symbol - 1);
clear_zone(Color::green(), true); // Green flash clear_zone(Color::green(), true); // Green flash
} else { } else {
if (txtidx) { if (cursor_pos) {
txtidx--; cursor_pos--;
txtinput[txtidx] = 0; // Erase _str->replace(cursor_pos, 1, 1, 0);
clear_zone(Color::yellow(), true); // Yellow flash clear_zone(Color::yellow(), true); // Yellow flash
} else { } else {
clear_zone(Color::red(), true); // Red flash clear_zone(Color::red(), true); // Red flash
@ -261,19 +259,19 @@ void HandWriteView::sample_pen() {
// Blink cursor // Blink cursor
if (!(sample_skip & 15)) { 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}; text_input.screen_rect().location().y() + 16 - 4};
if (cursor) { if (cursor) {
display.fill_rectangle( 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() Color::black()
); );
} else { } else {
display.fill_rectangle( display.fill_rectangle(
{cursor_pos, {8, 4}}, {draw_pos, {8, 4}},
Color::white() Color::white()
); );
} }
@ -382,25 +380,23 @@ void HandWriteView::on_show() {
clear_zone(Color::black(), false); clear_zone(Color::black(), false);
} }
std::string HandWriteView::value() {
txtinput[txtidx] = 0;
return txtinput;
}
void HandWriteView::on_button(Button& button) { void HandWriteView::on_button(Button& button) {
char_add(button.id); char_add(button.id);
update_text(); update_text();
} }
void HandWriteView::char_add(const char c) { void HandWriteView::char_add(const char c) {
if (txtidx >= _max_length) return; if (cursor_pos >= _max_length) return;
txtinput[txtidx] = c; _str->replace(cursor_pos, 1, 1, c);
txtidx++; cursor_pos++;
} }
void HandWriteView::update_text() { 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));
} }
} }

View File

@ -33,9 +33,9 @@ namespace ui {
class HandWriteView : public View { class HandWriteView : public View {
public: public:
std::function<void(std::string)> on_changed { }; std::function<void(std::string*)> 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(const HandWriteView&) = delete;
HandWriteView(HandWriteView&&) = delete; HandWriteView(HandWriteView&&) = delete;
@ -46,18 +46,18 @@ public:
void on_show() override; void on_show() override;
bool on_touch(const TouchEvent event) override; bool on_touch(const TouchEvent event) override;
std::string value();
std::string title() const override { return "Text entry"; }; std::string title() const override { return "Text entry"; };
private: private:
const char special_chars[5] = {'\'', '.', '?', '!', '='};
const HandWriting * handwriting { }; const HandWriting * handwriting { };
Painter * _painter { }; Painter * _painter { };
size_t _max_length; size_t _max_length;
uint8_t dir_cnt { 0 }; uint8_t dir_cnt { 0 };
uint8_t dir_prev { 0 }; uint8_t dir_prev { 0 };
uint8_t flash_timer { 0 }; uint8_t flash_timer { 0 };
uint8_t txtidx { 0 }; uint32_t cursor_pos { 0 };
bool cursor { false }; bool cursor { false };
bool tracing { false }; bool tracing { false };
uint8_t stroke_index { 0 }; uint8_t stroke_index { 0 };
@ -65,7 +65,7 @@ private:
uint8_t stroke_list[8]; uint8_t stroke_list[8];
Point start_pos { }, current_pos { }, last_pos { }; Point start_pos { }, current_pos { }, last_pos { };
bool _lowercase = false; bool _lowercase = false;
std::string txtinput { "" }; // 28 chars max std::string * _str { };
void sample_pen(); void sample_pen();
void add_stroke(uint8_t dir); void add_stroke(uint8_t dir);

View File

@ -186,7 +186,7 @@ void LCRView::start_tx(const bool scan) {
} }
void LCRView::on_button_setam(NavigationView& nav, Button& button) { 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) { LCRView::LCRView(NavigationView& nav) {
@ -247,7 +247,7 @@ LCRView::LCRView(NavigationView& nav) {
rectangle.set_parent_rect({ rectangle.set_parent_rect({
static_cast<Coord>(98), static_cast<Coord>(98),
static_cast<Coord>(n * 32 + 68 - 2), static_cast<Coord>(n * 32 + 68 - 2),
64, 20 68, 20
}); });
rectangle.set_color(ui::Color::grey()); rectangle.set_color(ui::Color::grey());
rectangle.set_outline(true); rectangle.set_outline(true);
@ -263,7 +263,7 @@ LCRView::LCRView(NavigationView& nav) {
button_scan.set_style(&style_val); button_scan.set_style(&style_val);
button_setrgsb.on_select = [this,&nav](Button&) { button_setrgsb.on_select = [this,&nav](Button&) {
text_entry(nav, rgsb, 4); text_entry(nav, &rgsb, 4);
}; };
button_txsetup.on_select = [&nav](Button&) { button_txsetup.on_select = [&nav](Button&) {

View File

@ -81,7 +81,7 @@ private:
tx_modes tx_mode = IDLE; tx_modes tx_mode = IDLE;
uint8_t scan_count { 0 }, scan_index { 0 }; uint8_t scan_count { 0 }, scan_index { 0 };
uint32_t scan_progress { 0 }; uint32_t scan_progress { 0 };
std::string litteral[5] { " " }; std::string litteral[5] { { " " } };
std::string rgsb { " " }; std::string rgsb { " " };
char lcr_message[512]; char lcr_message[512];
uint16_t lcr_message_data[256]; uint16_t lcr_message_data[256];
@ -107,7 +107,7 @@ private:
Labels labels { Labels labels {
{ { 2 * 8, 4 }, "EC:", Color::light_grey() }, { { 2 * 8, 4 }, "EC:", Color::light_grey() },
{ { 88, 268 }, "Scan list:", Color::light_grey() } { { 84, 268 }, "Scan list:", Color::light_grey() }
}; };
std::array<Button, 5> buttons { }; std::array<Button, 5> buttons { };
@ -158,10 +158,9 @@ private:
}; };
OptionsField options_scanlist { OptionsField options_scanlist {
{ 88, 284 }, { 84, 284 },
6, 6,
{ {
{ "Lille ", 0 },
{ "Reims ", 1 } { "Reims ", 1 }
} }
}; };

View File

@ -71,7 +71,7 @@ static msg_t ookthread_fn(void * arg) {
} }
void MorseView::on_set_text(NavigationView& nav) { void MorseView::on_set_text(NavigationView& nav) {
text_entry(nav, buffer, 28); text_entry(nav, &buffer, 28);
} }
void MorseView::focus() { void MorseView::focus() {

View File

@ -22,12 +22,13 @@
#include "ui_navigation.hpp" #include "ui_navigation.hpp"
#include "modules.h" //#include "modules.h"
#include "portapack.hpp" #include "portapack.hpp"
#include "event_m0.hpp" #include "event_m0.hpp"
#include "bmp_splash.hpp" #include "bmp_splash.hpp"
#include "bmp_modal_warning.hpp" #include "bmp_modal_warning.hpp"
#include "portapack_persistent_memory.hpp"
#include "ui_about.hpp" #include "ui_about.hpp"
#include "ui_adsbtx.hpp" #include "ui_adsbtx.hpp"

View File

@ -124,7 +124,7 @@ void POCSAGTXView::paint(Painter&) {
} }
void POCSAGTXView::on_set_text(NavigationView& nav) { void POCSAGTXView::on_set_text(NavigationView& nav) {
text_entry(nav, buffer, 16); text_entry(nav, &buffer, 16);
} }
POCSAGTXView::POCSAGTXView( POCSAGTXView::POCSAGTXView(

View File

@ -136,11 +136,11 @@ RDSView::RDSView(NavigationView& nav) {
options_coverage.set_selected_index(0); // Local options_coverage.set_selected_index(0); // Local
button_editpsn.on_select = [this, &nav](Button&) { button_editpsn.on_select = [this, &nav](Button&) {
text_entry(nav, PSN, 8); text_entry(nav, &PSN, 8);
}; };
button_editradiotext.on_select = [this, &nav](Button&){ button_editradiotext.on_select = [this, &nav](Button&){
text_entry(nav, RadioText, 24); text_entry(nav, &RadioText, 24);
}; };
} }

View File

@ -21,26 +21,24 @@
*/ */
#include "ui_textentry.hpp" #include "ui_textentry.hpp"
#include "portapack_persistent_memory.hpp"
namespace ui { namespace ui {
bool text_entry(NavigationView& nav, std::string& str, const size_t max_length, const std::function<void(std::string)> on_done) { void text_entry(NavigationView& nav, std::string * str, const size_t max_length, const std::function<void(std::string *)> on_done) {
if (portapack::persistent_memory::ui_config_textentry() == 0) { if (portapack::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 = [str, max_length, on_done](std::string value) { te_view->on_changed = [on_done](std::string * value) {
//memcpy(str, value, max_length + 1); 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 = [str, max_length, on_done](std::string value) { te_view->on_changed = [on_done](std::string * value) {
//memcpy(str, value, max_length + 1); if (on_done)
if (on_done) on_done(value); on_done(value);
}; };
} }
return true;
} }
} /* namespace ui */ } /* namespace ui */

View File

@ -27,11 +27,10 @@
#include "ui_navigation.hpp" #include "ui_navigation.hpp"
#include "ui_handwrite.hpp" #include "ui_handwrite.hpp"
#include "ui_alphanum.hpp" #include "ui_alphanum.hpp"
#include "portapack_persistent_memory.hpp"
namespace ui { namespace ui {
bool text_entry(NavigationView& nav, std::string& str, size_t max_length, const std::function<void(std::string)> on_done = nullptr); void text_entry(NavigationView& nav, std::string * str, size_t max_length, const std::function<void(std::string*)> on_done = nullptr);
} /* namespace ui */ } /* namespace ui */