mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2024-12-13 03:34:35 +00:00
Looking Glass - persist range/preset settings, UI tweaks (#1401)
* WIP * Add encoder support for TextField * Working settings, use TextField * Remove unneeded blanking rectangle
This commit is contained in:
parent
a476647d70
commit
dc9a16c54b
@ -74,8 +74,8 @@ rf::Frequency GlassView::get_freq_from_bin_pos(uint8_t pos) {
|
||||
|
||||
void GlassView::on_marker_change() {
|
||||
marker = get_freq_from_bin_pos(marker_pixel_index);
|
||||
button_marker.set_text(to_string_short_freq(marker));
|
||||
PlotMarker(marker_pixel_index); // Refresh marker on screen
|
||||
field_marker.set_text(to_string_short_freq(marker));
|
||||
plot_marker(marker_pixel_index); // Refresh marker on screen
|
||||
}
|
||||
|
||||
void GlassView::retune() {
|
||||
@ -87,21 +87,13 @@ void GlassView::retune() {
|
||||
baseband::spectrum_streaming_start(); // Do the RX
|
||||
}
|
||||
|
||||
void GlassView::on_lna_changed(int32_t v_db) {
|
||||
receiver_model.set_lna(v_db);
|
||||
}
|
||||
|
||||
void GlassView::on_vga_changed(int32_t v_db) {
|
||||
receiver_model.set_vga(v_db);
|
||||
}
|
||||
|
||||
void GlassView::reset_live_view(bool clear_screen) {
|
||||
max_freq_hold = 0;
|
||||
max_freq_power = -1000;
|
||||
if (clear_screen) {
|
||||
// only clear screen in peak mode
|
||||
if (live_frequency_view == 2) {
|
||||
display.fill_rectangle({{0, 108 + 16}, {SCREEN_W, 320 - (108 + 16)}}, {0, 0, 0});
|
||||
display.fill_rectangle({{0, 108 + 16}, {SCREEN_W, SCREEN_H - (108 + 16)}}, {0, 0, 0});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,15 +126,15 @@ void GlassView::add_spectrum_pixel(uint8_t power) {
|
||||
uint8_t color_gradient = (point * 255) / 212;
|
||||
// clear if not in peak view
|
||||
if (live_frequency_view != 2) {
|
||||
display.fill_rectangle({{xpos, 108 + 16}, {1, 320 - point}}, {0, 0, 0});
|
||||
display.fill_rectangle({{xpos, 108 + 16}, {1, SCREEN_H - point}}, {0, 0, 0});
|
||||
}
|
||||
display.fill_rectangle({{xpos, 320 - point}, {1, point}}, {color_gradient, 0, uint8_t(255 - color_gradient)});
|
||||
display.fill_rectangle({{xpos, SCREEN_H - point}, {1, point}}, {color_gradient, 0, uint8_t(255 - color_gradient)});
|
||||
}
|
||||
if (last_max_freq != max_freq_hold) {
|
||||
last_max_freq = max_freq_hold;
|
||||
freq_stats.set("MAX HOLD: " + to_string_short_freq(max_freq_hold));
|
||||
}
|
||||
PlotMarker(marker_pixel_index);
|
||||
plot_marker(marker_pixel_index);
|
||||
} else {
|
||||
display.draw_pixels({{0, display.scroll(1)}, {SCREEN_W, 1}}, spectrum_row); // new line at top, one less var, speedier
|
||||
}
|
||||
@ -176,7 +168,7 @@ bool GlassView::process_bins(uint8_t* powerlevel) {
|
||||
}
|
||||
|
||||
// Apparently, the spectrum object returns an array of SPEC_NB_BINS (256) bins
|
||||
// Each having the radio signal power for it's corresponding frequency slot
|
||||
// Each having the radio signal power for its corresponding frequency slot
|
||||
void GlassView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
|
||||
baseband::spectrum_streaming_stop();
|
||||
// Convert bins of this spectrum slice into a representative max_power and when enough, into pixels
|
||||
@ -231,8 +223,7 @@ void GlassView::on_range_changed() {
|
||||
looking_glass_sampling_rate = looking_glass_bandwidth;
|
||||
each_bin_size = looking_glass_bandwidth / SCREEN_W;
|
||||
looking_glass_step = looking_glass_bandwidth;
|
||||
f_center_ini = f_min + (looking_glass_bandwidth / 2); // Initial center frequency for sweep
|
||||
portapack::display.fill_rectangle({17 * 8, 4 * 16, 2 * 8, 16}, Color::black()); // Clear old marker and whole marker rectangle btw
|
||||
f_center_ini = f_min + (looking_glass_bandwidth / 2); // Initial center frequency for sweep
|
||||
} else {
|
||||
// view is made in multiple pass, use original bin picking
|
||||
mode = scan_type.selected_index_value();
|
||||
@ -253,19 +244,13 @@ void GlassView::on_range_changed() {
|
||||
}
|
||||
search_span = looking_glass_range / MHZ_DIV;
|
||||
marker_pixel_step = looking_glass_range / SCREEN_W; // Each pixel value in Hz
|
||||
//
|
||||
button_range.set_text(" "); // clear up to 6 chars
|
||||
if (locked_range) {
|
||||
button_range.set_text(">" + to_string_dec_uint(search_span) + "<");
|
||||
} else {
|
||||
button_range.set_text(" " + to_string_dec_uint(search_span) + " ");
|
||||
}
|
||||
|
||||
pixel_index = 0; // reset pixel counter
|
||||
max_power = 0; // reset save max power level
|
||||
bins_Hz_size = 0; // reset amount of Hz filled up by pixels
|
||||
//
|
||||
|
||||
on_marker_change();
|
||||
update_range_field();
|
||||
|
||||
// set the sample rate and bandwidth
|
||||
receiver_model.set_sampling_rate(looking_glass_sampling_rate);
|
||||
@ -277,7 +262,7 @@ void GlassView::on_range_changed() {
|
||||
receiver_model.set_target_frequency(f_center); // tune rx for this slice
|
||||
}
|
||||
|
||||
void GlassView::PlotMarker(uint8_t pos) {
|
||||
void GlassView::plot_marker(uint8_t pos) {
|
||||
uint8_t shift_y = 0;
|
||||
if (live_frequency_view > 0) // plot one line down when in live view
|
||||
{
|
||||
@ -289,7 +274,7 @@ void GlassView::PlotMarker(uint8_t pos) {
|
||||
portapack::display.fill_rectangle({pos, 106 + shift_y, 1, 2}, Color::red()); // Red marker bottom
|
||||
}
|
||||
|
||||
void GlassView::clip_min(int32_t v) {
|
||||
void GlassView::update_min(int32_t v) {
|
||||
int32_t min_size = steps;
|
||||
if (locked_range)
|
||||
min_size = search_span;
|
||||
@ -299,15 +284,14 @@ void GlassView::clip_min(int32_t v) {
|
||||
v = 7200 - min_size;
|
||||
}
|
||||
if (v > (field_frequency_max.value() - min_size))
|
||||
field_frequency_max.set_value(v + min_size);
|
||||
field_frequency_max.set_value(v + min_size, false);
|
||||
if (locked_range)
|
||||
field_frequency_max.set_value(v + min_size);
|
||||
field_frequency_max.set_value(v + min_size, false);
|
||||
else
|
||||
field_frequency_min.set_value(v);
|
||||
on_range_changed();
|
||||
field_frequency_min.set_value(v, false);
|
||||
}
|
||||
|
||||
void GlassView::clip_max(int32_t v) {
|
||||
void GlassView::update_max(int32_t v) {
|
||||
int32_t min_size = steps;
|
||||
if (locked_range)
|
||||
min_size = search_span;
|
||||
@ -317,12 +301,21 @@ void GlassView::clip_max(int32_t v) {
|
||||
v = min_size;
|
||||
}
|
||||
if (v < (field_frequency_min.value() + min_size))
|
||||
field_frequency_min.set_value(v - min_size);
|
||||
field_frequency_min.set_value(v - min_size, false);
|
||||
if (locked_range)
|
||||
field_frequency_min.set_value(v - min_size);
|
||||
field_frequency_min.set_value(v - min_size, false);
|
||||
else
|
||||
field_frequency_max.set_value(v);
|
||||
on_range_changed();
|
||||
field_frequency_max.set_value(v, false);
|
||||
}
|
||||
|
||||
void GlassView::update_range_field() {
|
||||
if (!locked_range) {
|
||||
field_range.set_style(&Styles::white);
|
||||
field_range.set_text(" " + to_string_dec_uint(search_span) + " ");
|
||||
} else {
|
||||
field_range.set_style(&Styles::red);
|
||||
field_range.set_text(">" + to_string_dec_uint(search_span) + "<");
|
||||
}
|
||||
}
|
||||
|
||||
GlassView::GlassView(
|
||||
@ -335,7 +328,7 @@ GlassView::GlassView(
|
||||
&field_frequency_max,
|
||||
&field_lna,
|
||||
&field_vga,
|
||||
&button_range,
|
||||
&field_range,
|
||||
&steps_config,
|
||||
&scan_type,
|
||||
&view_config,
|
||||
@ -343,69 +336,67 @@ GlassView::GlassView(
|
||||
&filter_config,
|
||||
&field_rf_amp,
|
||||
&range_presets,
|
||||
&button_marker,
|
||||
&field_marker,
|
||||
&field_trigger,
|
||||
&button_jump,
|
||||
&button_rst,
|
||||
&freq_stats});
|
||||
|
||||
load_Presets(); // Load available presets from TXT files (or default)
|
||||
load_presets(); // Load available presets from TXT files (or default).
|
||||
preset_index = clip<uint8_t>(preset_index, 0, presets_db.size());
|
||||
|
||||
field_frequency_min.set_value(f_min / MHZ_DIV);
|
||||
field_frequency_min.on_change = [this](int32_t v) {
|
||||
clip_min(v);
|
||||
range_presets.set_selected_index(0); // Manual
|
||||
update_min(v);
|
||||
on_range_changed();
|
||||
};
|
||||
field_frequency_min.set_value(presets_db[0].min); // Defaults to first preset
|
||||
field_frequency_min.set_step(steps);
|
||||
|
||||
field_frequency_min.on_select = [this, &nav](NumberField& field) {
|
||||
auto new_view = nav_.push<FrequencyKeypadView>(field_frequency_min.value() * MHZ_DIV);
|
||||
new_view->on_changed = [this, &field](rf::Frequency f) {
|
||||
clip_min(f / MHZ_DIV);
|
||||
field_frequency_min.set_value(f / MHZ_DIV);
|
||||
};
|
||||
};
|
||||
|
||||
field_frequency_max.set_value(f_max / MHZ_DIV);
|
||||
field_frequency_max.on_change = [this](int32_t v) {
|
||||
clip_max(v);
|
||||
range_presets.set_selected_index(0); // Manual
|
||||
update_max(v);
|
||||
on_range_changed();
|
||||
};
|
||||
field_frequency_max.set_value(presets_db[0].max); // Defaults to first preset
|
||||
field_frequency_max.set_step(steps);
|
||||
|
||||
field_frequency_max.on_select = [this, &nav](NumberField& field) {
|
||||
auto new_view = nav_.push<FrequencyKeypadView>(field_frequency_max.value() * MHZ_DIV);
|
||||
new_view->on_changed = [this, &field](rf::Frequency f) {
|
||||
clip_max(f / MHZ_DIV);
|
||||
field_frequency_max.set_value(f / MHZ_DIV);
|
||||
};
|
||||
};
|
||||
|
||||
field_lna.on_change = [this](int32_t v) {
|
||||
field_lna.on_change = [this](int32_t v_db) {
|
||||
reset_live_view(true);
|
||||
this->on_lna_changed(v);
|
||||
receiver_model.set_lna(v_db);
|
||||
};
|
||||
field_lna.set_value(receiver_model.lna());
|
||||
|
||||
field_vga.on_change = [this](int32_t v_db) {
|
||||
reset_live_view(true);
|
||||
this->on_vga_changed(v_db);
|
||||
receiver_model.set_vga(v_db);
|
||||
};
|
||||
field_vga.set_value(receiver_model.vga());
|
||||
|
||||
steps_config.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
steps_config.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
field_frequency_min.set_step(v);
|
||||
field_frequency_max.set_step(v);
|
||||
steps = v;
|
||||
};
|
||||
steps_config.set_selected_index(0); // default of 1 Mhz steps
|
||||
|
||||
scan_type.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
scan_type.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
mode = v;
|
||||
on_range_changed();
|
||||
};
|
||||
scan_type.set_selected_index(0); // default legacy fast scan
|
||||
|
||||
view_config.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
view_config.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
// clear between changes
|
||||
reset_live_view(true);
|
||||
if (v == 0) {
|
||||
@ -436,41 +427,37 @@ GlassView::GlassView(
|
||||
};
|
||||
view_config.set_selected_index(0); // default spectrum
|
||||
|
||||
level_integration.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
level_integration.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
reset_live_view(true);
|
||||
live_frequency_integrate = v;
|
||||
};
|
||||
level_integration.set_selected_index(3); // default integration of ( 3 * old value + new_value ) / 4
|
||||
|
||||
filter_config.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
filter_config.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
reset_live_view(true);
|
||||
min_color_power = v;
|
||||
};
|
||||
filter_config.set_selected_index(0);
|
||||
|
||||
range_presets.on_change = [this](size_t n, OptionsField::value_t v) {
|
||||
(void)n;
|
||||
range_presets.on_change = [this](size_t ix, OptionsField::value_t v) {
|
||||
preset_index = ix;
|
||||
if (ix == 0) return; // Don't update range for "Manual".
|
||||
|
||||
// NB: Don't trigger updates, presets directly set the range
|
||||
// values without applying step or range lock.
|
||||
field_frequency_min.set_value(presets_db[v].min, false);
|
||||
field_frequency_max.set_value(presets_db[v].max, false);
|
||||
on_range_changed();
|
||||
};
|
||||
range_presets.set_selected_index(preset_index);
|
||||
|
||||
button_marker.on_change = [this]() {
|
||||
if (((int)marker_pixel_index + button_marker.get_encoder_delta()) < 0) {
|
||||
marker_pixel_index = 0;
|
||||
} else if (((int)marker_pixel_index + button_marker.get_encoder_delta()) > SCREEN_W) {
|
||||
marker_pixel_index = SCREEN_W;
|
||||
} else {
|
||||
marker_pixel_index = marker_pixel_index + button_marker.get_encoder_delta();
|
||||
}
|
||||
field_marker.on_encoder_change = [this](TextField&, EncoderEvent delta) {
|
||||
marker_pixel_index = clip<uint8_t>(marker_pixel_index + delta, 0, SCREEN_W);
|
||||
on_marker_change();
|
||||
button_marker.set_encoder_delta(0);
|
||||
};
|
||||
|
||||
button_marker.on_select = [this](ButtonWithEncoder&) {
|
||||
receiver_model.set_target_frequency(marker); // Center tune rx in marker freq.
|
||||
field_marker.on_select = [this](TextField&) {
|
||||
receiver_model.set_target_frequency(marker); // Center tune rx to marker freq.
|
||||
auto settings = receiver_model.settings();
|
||||
settings.frequency_step = MHZ_DIV; // Preset a 1 MHz frequency step into RX -> AUDIO
|
||||
nav_.replace<AnalogAudioView>(settings); // Jump into audio view
|
||||
@ -481,16 +468,9 @@ GlassView::GlassView(
|
||||
};
|
||||
field_trigger.set_value(32); // Defaults to 32, as normal triggering resolution
|
||||
|
||||
button_range.on_select = [this](Button&) {
|
||||
if (locked_range) {
|
||||
locked_range = false;
|
||||
button_range.set_style(&Styles::white);
|
||||
button_range.set_text(" " + to_string_dec_uint(search_span) + " ");
|
||||
} else {
|
||||
locked_range = true;
|
||||
button_range.set_style(&Styles::red);
|
||||
button_range.set_text(">" + to_string_dec_uint(search_span) + "<");
|
||||
}
|
||||
field_range.on_select = [this](TextField&) {
|
||||
locked_range = !locked_range;
|
||||
update_range_field();
|
||||
};
|
||||
|
||||
button_jump.on_select = [this](Button&) {
|
||||
@ -506,12 +486,12 @@ GlassView::GlassView(
|
||||
|
||||
display.scroll_set_area(109, 319);
|
||||
baseband::set_spectrum(looking_glass_bandwidth, field_trigger.value()); // trigger:
|
||||
// Discord User jteich: WidebandSpectrum::on_message to set the trigger value. In WidebandSpectrum::execute ,
|
||||
// Discord User jteich: WidebandSpectrum::on_message to set the trigger value. In WidebandSpectrum::execute,
|
||||
// it keeps adding the output of the fft to the buffer until "trigger" number of calls are made,
|
||||
// at which time it pushes the buffer up with channel_spectrum.feed
|
||||
|
||||
marker_pixel_index = 120;
|
||||
on_range_changed();
|
||||
marker_pixel_index = SCREEN_W / 2;
|
||||
on_range_changed(); // Force an update.
|
||||
|
||||
receiver_model.set_sampling_rate(looking_glass_sampling_rate); // 20mhz
|
||||
receiver_model.set_baseband_bandwidth(looking_glass_bandwidth); // possible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz
|
||||
@ -519,11 +499,14 @@ GlassView::GlassView(
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
void GlassView::load_Presets() {
|
||||
void GlassView::load_presets() {
|
||||
File presets_file;
|
||||
auto error = presets_file.open("LOOKINGGLASS/PRESETS.TXT");
|
||||
presets_db.clear();
|
||||
|
||||
// Add the "Manual" entry.
|
||||
presets_db.push_back({0, 0, "Manual"});
|
||||
|
||||
if (!error) {
|
||||
auto reader = FileLineReader(presets_file);
|
||||
for (const auto& line : reader) {
|
||||
@ -546,14 +529,16 @@ void GlassView::load_Presets() {
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't load any from the file, load a default instead.
|
||||
if (presets_db.empty())
|
||||
presets_Default();
|
||||
/*
|
||||
// Didn't load any from the file, add a default.
|
||||
if (presets_db.size() == 1)
|
||||
presets_db.push_back({2320, 2560, "DEFAULT WIFI 2.4GHz"});
|
||||
*/
|
||||
|
||||
populate_Presets();
|
||||
populate_presets();
|
||||
}
|
||||
|
||||
void GlassView::populate_Presets() {
|
||||
void GlassView::populate_presets() {
|
||||
using option_t = std::pair<std::string, int32_t>;
|
||||
using options_t = std::vector<option_t>;
|
||||
options_t entries;
|
||||
@ -561,12 +546,7 @@ void GlassView::populate_Presets() {
|
||||
for (const auto& preset : presets_db)
|
||||
entries.emplace_back(preset.label, entries.size());
|
||||
|
||||
range_presets.set_options(entries);
|
||||
}
|
||||
|
||||
void GlassView::presets_Default() {
|
||||
presets_db.clear();
|
||||
presets_db.push_back({2320, 2560, "DEFAULT WIFI 2.4GHz"});
|
||||
range_presets.set_options(std::move(entries));
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -72,8 +72,18 @@ class GlassView : public View {
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{ReceiverModel::Mode::SpectrumAnalysis};
|
||||
// Settings
|
||||
rf::Frequency f_min = 260 * MHZ_DIV; // Default to 315/433 remote range.
|
||||
rf::Frequency f_max = 500 * MHZ_DIV;
|
||||
uint8_t preset_index = 0;
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_glass", app_settings::Mode::RX};
|
||||
"rx_glass"sv,
|
||||
app_settings::Mode::RX,
|
||||
{
|
||||
{"min"sv, &f_min},
|
||||
{"max"sv, &f_max},
|
||||
{"preset"sv, &preset_index},
|
||||
}};
|
||||
|
||||
struct preset_entry {
|
||||
rf::Frequency min{};
|
||||
@ -82,8 +92,9 @@ class GlassView : public View {
|
||||
};
|
||||
|
||||
std::vector<preset_entry> presets_db{};
|
||||
void clip_min(int32_t v);
|
||||
void clip_max(int32_t v);
|
||||
void update_min(int32_t v);
|
||||
void update_max(int32_t v);
|
||||
void update_range_field();
|
||||
void get_max_power(const ChannelSpectrum& spectrum, uint8_t bin, uint8_t& max_power);
|
||||
rf::Frequency get_freq_from_bin_pos(uint8_t pos);
|
||||
void on_marker_change();
|
||||
@ -94,17 +105,13 @@ class GlassView : public View {
|
||||
int64_t next_mult_of(int64_t num, int64_t multiplier);
|
||||
void adjust_range(int64_t* f_min, int64_t* f_max, int64_t width);
|
||||
void on_range_changed();
|
||||
void on_lna_changed(int32_t v_db);
|
||||
void on_vga_changed(int32_t v_db);
|
||||
void reset_live_view(bool clear_screen);
|
||||
void add_spectrum_pixel(uint8_t power);
|
||||
void PlotMarker(uint8_t pos);
|
||||
void load_Presets();
|
||||
void plot_marker(uint8_t pos);
|
||||
void load_presets();
|
||||
void txtline_process(std::string& line);
|
||||
void populate_Presets();
|
||||
void presets_Default();
|
||||
void populate_presets();
|
||||
|
||||
rf::Frequency f_min{0}, f_max{0};
|
||||
rf::Frequency search_span{0};
|
||||
rf::Frequency f_center{0};
|
||||
rf::Frequency f_center_ini{0};
|
||||
@ -113,7 +120,7 @@ class GlassView : public View {
|
||||
rf::Frequency marker_pixel_step{0};
|
||||
// size of one spectrum bin in Hz
|
||||
rf::Frequency each_bin_size{0};
|
||||
// consumed number of Hz, used to know if we have filled a 'bag' , a corresponding pixel length on screen
|
||||
// consumed number of Hz, used to know if we have filled a 'bag', a corresponding pixel length on screen
|
||||
rf::Frequency bins_Hz_size{0};
|
||||
rf::Frequency looking_glass_sampling_rate{0};
|
||||
rf::Frequency looking_glass_bandwidth{0};
|
||||
@ -141,10 +148,10 @@ class GlassView : public View {
|
||||
uint8_t ignore_dc = 0;
|
||||
|
||||
Labels labels{
|
||||
{{0, 0}, "MIN: MAX: LNA VGA ", Color::light_grey()},
|
||||
{{0, 1 * 16}, "RANGE: FILTER: AMP:", Color::light_grey()},
|
||||
{{0, 0 * 16}, "MIN: MAX: LNA VGA ", Color::light_grey()},
|
||||
{{0, 1 * 16}, "RANGE: FILTER: AMP:", Color::light_grey()},
|
||||
{{0, 2 * 16}, "PRESET:", Color::light_grey()},
|
||||
{{0, 3 * 16}, "MARKER: MHz", Color::light_grey()},
|
||||
{{0, 3 * 16}, "MARKER: MHz", Color::light_grey()},
|
||||
{{0, 4 * 16}, "RES: STEP:", Color::light_grey()}};
|
||||
|
||||
NumberField field_frequency_min{
|
||||
@ -167,8 +174,8 @@ class GlassView : public View {
|
||||
VGAGainField field_vga{
|
||||
{27 * 8, 0 * 16}};
|
||||
|
||||
Button button_range{
|
||||
{7 * 8, 1 * 16, 4 * 8, 16},
|
||||
TextField field_range{
|
||||
{6 * 8, 1 * 16, 6 * 8, 16},
|
||||
""};
|
||||
|
||||
OptionsField filter_config{
|
||||
@ -176,23 +183,21 @@ class GlassView : public View {
|
||||
4,
|
||||
{
|
||||
{"OFF ", 0},
|
||||
{"MID ", 118}, // 85 +25 (110) + a bit more to kill all blue
|
||||
{"MID ", 118}, // 85 + 25 (110) + a bit more to kill all blue
|
||||
{"HIGH", 202}, // 168 + 25 (193)
|
||||
}};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{29 * 8, 1 * 16}};
|
||||
{28 * 8, 1 * 16}};
|
||||
|
||||
OptionsField range_presets{
|
||||
{7 * 8, 2 * 16},
|
||||
20,
|
||||
{
|
||||
{" NONE (WIFI 2.4GHz)", 0},
|
||||
}};
|
||||
{}};
|
||||
|
||||
ButtonWithEncoder button_marker{
|
||||
{7 * 8, 3 * 16, 10 * 8, 16},
|
||||
" "};
|
||||
TextField field_marker{
|
||||
{7 * 8, 3 * 16, 9 * 8, 16},
|
||||
""};
|
||||
|
||||
NumberField field_trigger{
|
||||
{4 * 8, 4 * 16},
|
||||
|
@ -1764,6 +1764,15 @@ bool TextField::on_key(KeyEvent key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TextField::on_encoder(EncoderEvent delta) {
|
||||
if (on_encoder_change) {
|
||||
on_encoder_change(*this, delta);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* NumberField ***********************************************************/
|
||||
|
||||
NumberField::NumberField(
|
||||
|
@ -694,6 +694,7 @@ class TextField : public Text {
|
||||
public:
|
||||
std::function<void(TextField&)> on_select{};
|
||||
std::function<void(TextField&)> on_change{};
|
||||
std::function<void(TextField&, EncoderEvent)> on_encoder_change{};
|
||||
|
||||
TextField(Rect parent_rect, std::string text);
|
||||
|
||||
@ -701,6 +702,7 @@ class TextField : public Text {
|
||||
void set_text(std::string_view value);
|
||||
|
||||
bool on_key(KeyEvent key) override;
|
||||
bool on_encoder(EncoderEvent delta) override;
|
||||
|
||||
private:
|
||||
using Text::set;
|
||||
|
Loading…
Reference in New Issue
Block a user