From b456c18008705477832879f749d0f127fecd4b57 Mon Sep 17 00:00:00 2001 From: Netro <146584182+iNetro@users.noreply.github.com> Date: Thu, 19 Jun 2025 01:21:54 -0400 Subject: [PATCH] Modified Text Editor to handle long presses. (#2698) --- firmware/application/apps/ble_tx_app.cpp | 23 +++- firmware/application/apps/ble_tx_app.hpp | 3 - firmware/application/apps/ui_text_editor.cpp | 116 ++++++++++++++++--- firmware/application/apps/ui_text_editor.hpp | 7 ++ 4 files changed, 124 insertions(+), 25 deletions(-) diff --git a/firmware/application/apps/ble_tx_app.cpp b/firmware/application/apps/ble_tx_app.cpp index affe64b9a..b0ade7b1a 100644 --- a/firmware/application/apps/ble_tx_app.cpp +++ b/firmware/application/apps/ble_tx_app.cpp @@ -319,7 +319,8 @@ void BLETxView::on_tx_progress(const bool done) { BLETxView::BLETxView(NavigationView& nav) : nav_{nav} { - add_children({&button_open, + add_children({&dataEditView, + &button_open, &text_filename, &progressbar, &check_rand_mac, @@ -340,7 +341,6 @@ BLETxView::BLETxView(NavigationView& nav) &label_mac_address, &text_mac_address, &label_data_packet, - &dataEditView, &button_clear_marked, &button_save_packet, &button_switch}); @@ -430,6 +430,23 @@ BLETxView::BLETxView(NavigationView& nav) } }; + dataEditView.on_change = [this](uint8_t value) { + // Reject setting newline at index 29. + if (cursor_pos.col != 29) { + uint16_t dataBytePos = (cursor_pos.line * 29) + cursor_pos.col; + + packets[current_packet].advertisementData[dataBytePos] = uint_to_char(value, 16); + + update_current_packet(packets[current_packet], current_packet); + } + }; + + dataEditView.on_cursor_moved = [this]() { + // Save last selected cursor. + cursor_pos.line = dataEditView.line(); + cursor_pos.col = dataEditView.col(); + }; + button_clear_marked.on_select = [this](Button&) { marked_counter = 0; markedBytes.clear(); @@ -531,7 +548,6 @@ void BLETxView::update_current_packet(BLETxPacket packet, uint32_t currentIndex) for (const std::string& str : strings) { dataFile.write(str.c_str(), str.size()); dataFile.write("\n", 1); - ; } dataFile.~File(); @@ -546,6 +562,7 @@ void BLETxView::update_current_packet(BLETxPacket packet, uint32_t currentIndex) dataEditView.set_font_zoom(true); dataEditView.set_file(*dataFileWrapper); dataEditView.redraw(true, true); + dataEditView.cursor_set(cursor_pos.line, cursor_pos.col); } void BLETxView::set_parent_rect(const Rect new_parent_rect) { diff --git a/firmware/application/apps/ble_tx_app.hpp b/firmware/application/apps/ble_tx_app.hpp index 678450155..0d8c34bc0 100644 --- a/firmware/application/apps/ble_tx_app.hpp +++ b/firmware/application/apps/ble_tx_app.hpp @@ -287,9 +287,6 @@ class BLETxView : public View { Labels label_data_packet{ {{0 * 8, 9 * 16}, "Packet Data:", Theme::getInstance()->fg_light->foreground}}; - Console console{ - {0, 9 * 18, screen_width, screen_height - 80}}; - TextViewer dataEditView{ {0, 9 * 18, screen_width, screen_height - 80}}; diff --git a/firmware/application/apps/ui_text_editor.cpp b/firmware/application/apps/ui_text_editor.cpp index 7128757f3..ac05f5bf5 100644 --- a/firmware/application/apps/ui_text_editor.cpp +++ b/firmware/application/apps/ui_text_editor.cpp @@ -26,6 +26,7 @@ #include "log_file.hpp" #include "string_format.hpp" +#include "irq_controls.hpp" using namespace portapack; namespace fs = std::filesystem; @@ -81,21 +82,75 @@ void TextViewer::paint(Painter& painter) { paint_cursor(painter); } +void TextViewer::enable_long_press() { + // Enable long press on "Select". + SwitchesState config; + config[toUType(Switch::Sel)] = true; + set_switches_long_press_config(config); +} + +void TextViewer::on_focus() { + enable_long_press(); +} + bool TextViewer::on_key(const KeyEvent key) { int16_t delta_col = 0; int16_t delta_line = 0; - if (key == KeyEvent::Left) - delta_col = -1; - else if (key == KeyEvent::Right) - delta_col = 1; - else if (key == KeyEvent::Up) - delta_line = -1; - else if (key == KeyEvent::Down) - delta_line = 1; - else if (key == KeyEvent::Select && on_select) { - on_select(); - return true; + if (key == KeyEvent::Select) { + // Toggle 'digit' mode with long-press. + if (digit_mode_ || key_is_long_pressed(key)) { + digit_mode_ = !digit_mode_; + set_dirty(); + return true; + } + } + + if (digit_mode_) { + switch (key) { + case KeyEvent::Left: + delta_col = -1; + break; + case KeyEvent::Right: + delta_col = 1; + break; + case KeyEvent::Up: + set_value(value_ == 0x0F ? 0x00 : value_ + 1); + break; + case KeyEvent::Down: + set_value(value_ == 0x00 ? 0x0F : value_ - 1); + break; + default: + return false; + } + + if (delta_col == 0 && delta_line == 0) { + return true; + } + } else { + switch (key) { + case KeyEvent::Left: + delta_col = -1; + break; + case KeyEvent::Right: + delta_col = 1; + break; + case KeyEvent::Up: + delta_line = -1; + break; + case KeyEvent::Down: + delta_line = 1; + break; + case KeyEvent::Select: { + if (on_select) { + on_select(); + return true; + } + break; + } + default: + return false; + } } // Always allow cursor direction to be updated. @@ -111,19 +166,42 @@ bool TextViewer::on_key(const KeyEvent key) { bool TextViewer::on_encoder(EncoderEvent delta) { bool updated = false; - if (cursor_.dir == ScrollDirection::Horizontal) - updated = apply_scrolling_constraints(0, delta); - else { - delta *= 16; - updated = apply_scrolling_constraints(delta, 0); + if (digit_mode_) { + if (delta > 0) { + set_value(value_ == 0x0F ? 0x00 : value_ + 1); + } else if (delta < 0) { + set_value(value_ == 0x00 ? 0x0F : value_ - 1); + } + + updated = true; + } else { + if (cursor_.dir == ScrollDirection::Horizontal) { + updated = apply_scrolling_constraints(0, delta); + } else { + delta *= 16; + updated = apply_scrolling_constraints(delta, 0); + } + + if (updated) { + redraw(); + } } - if (updated) - redraw(); - return updated; } +void TextViewer::set_value(uint8_t new_value) { + if (new_value != value_) { + value_ = new_value; + + if (on_change) { + on_change(value_); + } + + set_dirty(); + } +} + void TextViewer::redraw(bool redraw_text, bool redraw_marked) { paint_state_.redraw_text = redraw_text; paint_state_.redraw_marked = redraw_marked; diff --git a/firmware/application/apps/ui_text_editor.hpp b/firmware/application/apps/ui_text_editor.hpp index 18fdeb654..d40fcaeef 100644 --- a/firmware/application/apps/ui_text_editor.hpp +++ b/firmware/application/apps/ui_text_editor.hpp @@ -54,10 +54,13 @@ class TextViewer : public Widget { std::function on_select{}; std::function on_cursor_moved{}; + std::function on_change{}; void paint(Painter& painter) override; bool on_key(KeyEvent key) override; bool on_encoder(EncoderEvent delta) override; + void set_value(uint8_t new_value); + void on_focus() override; void redraw(bool redraw_text = false, bool redraw_marked = false); @@ -74,6 +77,7 @@ class TextViewer : public Widget { void cursor_set(uint16_t line, uint16_t col); void cursor_mark_selected(); void cursor_clear_marked(); + void enable_long_press(); typedef std::pair LineColPair; std::vector lineColPair{}; @@ -95,6 +99,9 @@ class TextViewer : public Widget { int8_t char_height{}; uint8_t max_line{}; uint8_t max_col{}; + bool digit_mode_{false}; + uint8_t value_{0}; + bool allow_digit_mode_{true}; /* Returns true if the cursor was updated. */ bool apply_scrolling_constraints(