From c216fe5072d6362944ce07e34bd03c1382f7c83b Mon Sep 17 00:00:00 2001
From: Phil Mitchell <phil.a.mitchell@gmail.com>
Date: Mon, 27 Feb 2023 14:32:23 +1100
Subject: [PATCH] Add scroll bar to mode settings/config pages and screen
 settings pages.

---
 radio/src/gui/colorlcd/curveedit.cpp          |  7 +--
 radio/src/gui/colorlcd/curveedit.h            |  2 -
 radio/src/gui/colorlcd/input_edit.cpp         |  1 +
 radio/src/gui/colorlcd/model_curves.cpp       |  4 ++
 radio/src/gui/colorlcd/model_inputs.cpp       |  5 +-
 .../gui/colorlcd/model_logical_switches.cpp   |  5 +-
 .../src/gui/colorlcd/model_mixer_scripts.cpp  |  1 +
 radio/src/gui/colorlcd/model_mixes.cpp        |  9 +--
 radio/src/gui/colorlcd/model_outputs.cpp      | 14 ++---
 radio/src/gui/colorlcd/model_setup.cpp        | 60 ++++---------------
 radio/src/gui/colorlcd/model_telemetry.cpp    |  8 ++-
 radio/src/gui/colorlcd/module_setup.cpp       |  3 +
 radio/src/gui/colorlcd/preflight_checks.cpp   |  3 +-
 radio/src/gui/colorlcd/screen_setup.cpp       |  9 ++-
 .../gui/colorlcd/screen_user_interface.cpp    |  9 ++-
 radio/src/gui/colorlcd/timer_setup.cpp        |  3 +
 16 files changed, 67 insertions(+), 76 deletions(-)

diff --git a/radio/src/gui/colorlcd/curveedit.cpp b/radio/src/gui/colorlcd/curveedit.cpp
index 3d0ff9e9b44..bb7e6dfd4c4 100644
--- a/radio/src/gui/colorlcd/curveedit.cpp
+++ b/radio/src/gui/colorlcd/curveedit.cpp
@@ -33,6 +33,8 @@ CurveDataEdit::CurveDataEdit(Window * parent, const rect_t & rect, uint8_t index
   Window(parent, rect, FORM_FORWARD_FOCUS),
   index(index)
 {
+  lv_obj_set_style_bg_color(lvobj, makeLvColor(COLOR_THEME_SECONDARY3), 0);
+  lv_obj_set_scrollbar_mode(lvobj, LV_SCROLLBAR_MODE_AUTO);
 }
 
 #if LCD_W > LCD_H
@@ -169,11 +171,6 @@ void CurveDataEdit::update()
   }
 }
 
-void CurveDataEdit::paint(BitmapBuffer* dc)
-{
-  dc->clear(COLOR_THEME_SECONDARY3);
-}
-
 void CurveEdit::SetCurrentSource(uint32_t source)
 {
   CurveEdit::currentSource = source;
diff --git a/radio/src/gui/colorlcd/curveedit.h b/radio/src/gui/colorlcd/curveedit.h
index 774a31b777a..50e7fcf8a31 100644
--- a/radio/src/gui/colorlcd/curveedit.h
+++ b/radio/src/gui/colorlcd/curveedit.h
@@ -79,8 +79,6 @@ class CurveDataEdit : public Window
       update();
     }
 
-    void paint(BitmapBuffer * dc) override;
-
     void update();
 
   protected:
diff --git a/radio/src/gui/colorlcd/input_edit.cpp b/radio/src/gui/colorlcd/input_edit.cpp
index aa432d7fe31..1eaf9e2c390 100644
--- a/radio/src/gui/colorlcd/input_edit.cpp
+++ b/radio/src/gui/colorlcd/input_edit.cpp
@@ -58,6 +58,7 @@ InputEditWindow::InputEditWindow(int8_t input, uint8_t index) :
   auto box = new Window(&body, rect_t{});
   auto box_obj = box->getLvObj();
   lv_obj_set_flex_grow(box_obj, 2);
+  lv_obj_set_scrollbar_mode(box->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
 
 #if LCD_H > LCD_W // portrait
   box->setWidth(body.width() - 2*lv_dpx(8));
diff --git a/radio/src/gui/colorlcd/model_curves.cpp b/radio/src/gui/colorlcd/model_curves.cpp
index fd83898f024..25362add33a 100644
--- a/radio/src/gui/colorlcd/model_curves.cpp
+++ b/radio/src/gui/colorlcd/model_curves.cpp
@@ -202,8 +202,12 @@ void ModelCurvesPage::build(FormWindow * window)
 #endif
   static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
 
+  window->padAll(0);
+  lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
+
   auto form = new FormWindow(window, rect_t{});
   form->setFlexLayout();
+  form->padAll(6);
 
   FlexGridLayout grid(col_dsc, row_dsc);
   
diff --git a/radio/src/gui/colorlcd/model_inputs.cpp b/radio/src/gui/colorlcd/model_inputs.cpp
index 0016b5d1423..9090cd017d8 100644
--- a/radio/src/gui/colorlcd/model_inputs.cpp
+++ b/radio/src/gui/colorlcd/model_inputs.cpp
@@ -442,11 +442,12 @@ void ModelInputsPage::pasteInputAfter(uint8_t dst_idx)
 
 void ModelInputsPage::build(FormWindow *window)
 {
-  window->setFlexLayout();
-  window->padRow(lv_dpx(8));
+  window->padAll(0);
+  lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
   
   form = new FormGroup(window, rect_t{});
   form->setFlexLayout();
+  form->padAll(lv_dpx(8));
   form->padRow(lv_dpx(4));
 
   auto form_obj = form->getLvObj();
diff --git a/radio/src/gui/colorlcd/model_logical_switches.cpp b/radio/src/gui/colorlcd/model_logical_switches.cpp
index 85dbbbf9785..71a1974ba28 100644
--- a/radio/src/gui/colorlcd/model_logical_switches.cpp
+++ b/radio/src/gui/colorlcd/model_logical_switches.cpp
@@ -563,11 +563,12 @@ void ModelLogicalSwitchesPage::build(FormWindow* window)
 {
   static const lv_coord_t l_col_dsc[] = {LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
 
-  window->padAll(4);
+  window->padAll(0);
+  lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
 
   auto form = new FormWindow(window, rect_t{});
   form->setFlexLayout();
-  form->padAll(0);
+  form->padAll(4);
 
   FlexGridLayout grid(l_col_dsc, row_dsc, 2);
 
diff --git a/radio/src/gui/colorlcd/model_mixer_scripts.cpp b/radio/src/gui/colorlcd/model_mixer_scripts.cpp
index 36222e3ecbe..62d71a87b99 100644
--- a/radio/src/gui/colorlcd/model_mixer_scripts.cpp
+++ b/radio/src/gui/colorlcd/model_mixer_scripts.cpp
@@ -290,6 +290,7 @@ void ModelMixerScriptsPage::rebuild(FormWindow * window, int8_t focusIdx)
 void ModelMixerScriptsPage::build(FormWindow * window, int8_t focusIdx)
 {
   window->padAll(0);
+  lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
 
   auto form = new FormWindow(window, rect_t{});
   form->setFlexLayout();
diff --git a/radio/src/gui/colorlcd/model_mixes.cpp b/radio/src/gui/colorlcd/model_mixes.cpp
index a94fbad53d6..24ed36b0527 100644
--- a/radio/src/gui/colorlcd/model_mixes.cpp
+++ b/radio/src/gui/colorlcd/model_mixes.cpp
@@ -512,11 +512,12 @@ void ModelMixesPage::pasteMixAfter(uint8_t dst_idx)
 void ModelMixesPage::build(FormWindow * window)
 {
   scroll_win = window->getParent();
-  window->setFlexLayout();
-  window->padRow(lv_dpx(8));
+  window->padAll(0);
+  lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
 
   form = new FormGroup(window, rect_t{});
   form->setFlexLayout();
+  form->padAll(lv_dpx(8));
   form->padRow(lv_dpx(4));
 
   auto form_obj = form->getLvObj();
@@ -547,7 +548,7 @@ void ModelMixesPage::build(FormWindow * window)
     }
   }
 
-  auto box = new FormGroup(window, rect_t{});
+  auto box = new FormGroup(form, rect_t{});
   box->setFlexLayout(LV_FLEX_FLOW_ROW, lv_dpx(8));
   box->padLeft(lv_dpx(8));
 
@@ -560,7 +561,7 @@ void ModelMixesPage::build(FormWindow * window)
       box, rect_t{}, [=]() { return showMonitors; },
       [=](uint8_t val) { enableMonitors(val); });
 
-  auto btn = new TextButton(window, rect_t{}, LV_SYMBOL_PLUS, [=]() {
+  auto btn = new TextButton(form, rect_t{}, LV_SYMBOL_PLUS, [=]() {
     newMix();
     return 0;
   });
diff --git a/radio/src/gui/colorlcd/model_outputs.cpp b/radio/src/gui/colorlcd/model_outputs.cpp
index 70c9e09020b..e0b78a09f8a 100644
--- a/radio/src/gui/colorlcd/model_outputs.cpp
+++ b/radio/src/gui/colorlcd/model_outputs.cpp
@@ -291,20 +291,20 @@ ModelOutputsPage::ModelOutputsPage() :
 
 void ModelOutputsPage::build(FormWindow *window)
 {
-  window->setFlexLayout();
-  window->padRow(lv_dpx(4));
+  window->padAll(0);
+  lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
 
   auto form = new FormGroup(window, rect_t{});
   form->setFlexLayout(LV_FLEX_FLOW_ROW_WRAP, lv_dpx(16));
-  form->padRow(lv_dpx(8));
-  form->padBottom(lv_dpx(4));
+  form->padAll(lv_dpx(8));
+  form->padRow(lv_dpx(4));
 
   auto form_obj = form->getLvObj();
   lv_obj_set_style_flex_cross_place(form_obj, LV_FLEX_ALIGN_CENTER, 0);
 
   new TextButton(form, rect_t{}, STR_ADD_ALL_TRIMS_TO_SUBTRIMS, [=]() {
     moveTrimsToOffsets();
-    window->invalidate();
+    form->invalidate();
     return 0;
   });
 
@@ -321,7 +321,7 @@ void ModelOutputsPage::build(FormWindow *window)
   for (uint8_t ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) {
 
     // Channel settings
-    auto btn = new OutputLineButton(window, ch);
+    auto btn = new OutputLineButton(form, ch);
 #if LCD_W > LCD_H
     // Initial scroll height is incorrect without this??? (Issue #3186)
     btn->setHeight(35);
@@ -329,7 +329,7 @@ void ModelOutputsPage::build(FormWindow *window)
 
     LimitData* output = limitAddress(ch);
     btn->setPressHandler([=]() -> uint8_t {
-      Menu *menu = new Menu(window);
+      Menu *menu = new Menu(form);
       menu->addLine(STR_EDIT, [=]() {
           editOutput(ch, btn);
       });
diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp
index 0e5295c58a0..61a821cb407 100644
--- a/radio/src/gui/colorlcd/model_setup.cpp
+++ b/radio/src/gui/colorlcd/model_setup.cpp
@@ -88,12 +88,6 @@ struct ModelBitmapEdit : public FileChoice {
   }
 };
 
-struct TimerBtnMatrix : public ButtonMatrix {
-  TimerBtnMatrix(Window* parent, const rect_t& rect);
-  void onPress(uint8_t btn_id) override;
-  bool isActive(uint8_t btn_id) override;
-};
-
 class SubScreenButton : public Button
 {
   std::string text;
@@ -229,22 +223,27 @@ static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
 
 void ModelSetupPage::build(FormWindow * window)
 {
-  window->setFlexLayout();
+  window->padAll(0);
+  lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
+
+  auto wform = new FormWindow(window, rect_t{});
+  wform->setFlexLayout();
+  wform->padAll(4);
 
   FlexGridLayout grid(line_col_dsc, line_row_dsc, 2);
 
   // Model name
-  auto line = window->newLine(&grid);
+  auto line = wform->newLine(&grid);
   new StaticText(line, rect_t{}, STR_MODELNAME, 0, COLOR_THEME_PRIMARY1);
   new ModelNameEdit(line, rect_t{});
 
   // Model labels
-  line = window->newLine(&grid);
+  line = wform->newLine(&grid);
   new StaticText(line, rect_t{}, STR_LABELS, 0, COLOR_THEME_PRIMARY1);
   auto curmod = modelslist.getCurrentModel();
   labelTextButton =
     new TextButton(line, rect_t{}, modelslabels.getBulletLabelString(curmod ,STR_UNLABELEDMODEL), [=] () {
-       Menu *menu = new Menu(window, true);
+       Menu *menu = new Menu(wform, true);
        menu->setTitle(STR_LABELS);
        for (auto &label: modelslabels.getLabels()) {
          menu->addLineBuffered(label,
@@ -266,18 +265,18 @@ void ModelSetupPage::build(FormWindow * window)
      });
 
   // Bitmap
-  line = window->newLine(&grid);
+  line = wform->newLine(&grid);
   new StaticText(line, rect_t{}, STR_BITMAP, 0, COLOR_THEME_PRIMARY1);
   // TODO: show bitmap thumbnail instead?
   new ModelBitmapEdit(line, rect_t{});
 
   // Global functions
-  line = window->newLine(&grid);
+  line = wform->newLine(&grid);
   new StaticText(line, rect_t{}, STR_USE_GLOBAL_FUNCS, 0, COLOR_THEME_PRIMARY1);
   new CheckBox(line, rect_t{}, GET_SET_INVERTED(g_model.noGlobalFunctions));
 
   // Model ADC jitter filter
-  line = window->newLine(&grid);
+  line = wform->newLine(&grid);
   new StaticText(line, rect_t{}, STR_JITTER_FILTER, 0, COLOR_THEME_PRIMARY1);
   new Choice(line, rect_t{}, STR_ADCFILTERVALUES, 0, 2,
              GET_SET_DEFAULT(g_model.jitterFilter));
@@ -285,7 +284,7 @@ void ModelSetupPage::build(FormWindow * window)
   static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
   static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
 
-  auto oform = new FormGroup(window, rect_t{});
+  auto oform = new FormGroup(wform, rect_t{});
   oform->setFlexLayout(LV_FLEX_FLOW_COLUMN, lv_dpx(PAGE_PADDING));
   oform->padAll(PAGE_PADDING);
 
@@ -330,36 +329,3 @@ void ModelSetupPage::build(FormWindow * window)
   btn = new SubScreenButton(form, STR_THROTTLE_LABEL, []() { new ThrottleParams(); });
   lv_obj_set_grid_cell(btn->getLvObj(), LV_GRID_ALIGN_STRETCH, 2, 1, LV_GRID_ALIGN_CENTER, 0, 1);
 }
-
-#define MAX_SUBSCREEN_BTNS 9
-
-TimerBtnMatrix::TimerBtnMatrix(Window* parent, const rect_t& r) :
-  ButtonMatrix(parent, r)
-{
-  initBtnMap(3, MAX_TIMERS);
-  setText(0, TR_TIMER "1");
-  setText(1, TR_TIMER "2");
-  setText(2, TR_TIMER "3");
-  update();
-
-  lv_btnmatrix_set_btn_width(lvobj, 3, 2);
-  lv_obj_set_width(lvobj, lv_pct(100));
-  lv_obj_set_height(lvobj, LV_DPI_DEF / 2);
-
-  lv_obj_set_style_bg_opa(lvobj, LV_OPA_0, 0);
-  lv_obj_set_style_pad_all(lvobj, lv_dpx(8), 0);
-
-  lv_obj_set_style_pad_row(lvobj, lv_dpx(8), 0);
-  lv_obj_set_style_pad_column(lvobj, lv_dpx(8), 0);
-}
-
-void TimerBtnMatrix::onPress(uint8_t btn_id)
-{
-  if (btn_id >= MAX_TIMERS) return;
-  new TimerWindow((uint8_t)(btn_id));
-}
-
-bool TimerBtnMatrix::isActive(uint8_t btn_id)
-{
-  return false;
-}
diff --git a/radio/src/gui/colorlcd/model_telemetry.cpp b/radio/src/gui/colorlcd/model_telemetry.cpp
index e2cacf8036f..cc566c28d26 100644
--- a/radio/src/gui/colorlcd/model_telemetry.cpp
+++ b/radio/src/gui/colorlcd/model_telemetry.cpp
@@ -482,6 +482,9 @@ class SensorEditWindow : public Page {
 
     void buildBody(FormWindow * window)
     {
+      window->padAll(0);
+      lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
+
       // Sensor one
       auto form = new FormWindow(window, rect_t{});
       form->setFlexLayout();
@@ -558,13 +561,14 @@ void ModelTelemetryPage::editSensor(FormWindow * window, uint8_t index)
 
 void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex)
 {
-  window->padAll(4);
+  window->padAll(0);
+  lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
 
   this->window = window;
 
   auto form = new FormWindow(window, rect_t{});
   form->setFlexLayout();
-  form->padAll(0);
+  form->padAll(4);
 
   FlexGridLayout grid(col_dsc, row_dsc, 2);
   FlexGridLayout grid2(col_dsc2, row_dsc, 2);
diff --git a/radio/src/gui/colorlcd/module_setup.cpp b/radio/src/gui/colorlcd/module_setup.cpp
index 57fdf0e0f9c..621048646de 100644
--- a/radio/src/gui/colorlcd/module_setup.cpp
+++ b/radio/src/gui/colorlcd/module_setup.cpp
@@ -736,6 +736,9 @@ ModulePage::ModulePage(uint8_t moduleIdx) : Page(ICON_MODEL_SETUP)
     STR_INTERNALRF : STR_EXTERNALRF;
   header.setTitle(title);
 
+  body.padAll(0);
+  lv_obj_set_scrollbar_mode(body.getLvObj(), LV_SCROLLBAR_MODE_AUTO);
+
   auto form = new FormGroup(&body, rect_t{});
   form->setFlexLayout();
   form->padAll(lv_dpx(8));
diff --git a/radio/src/gui/colorlcd/preflight_checks.cpp b/radio/src/gui/colorlcd/preflight_checks.cpp
index 02bed9eb896..1c5618aef83 100644
--- a/radio/src/gui/colorlcd/preflight_checks.cpp
+++ b/radio/src/gui/colorlcd/preflight_checks.cpp
@@ -108,7 +108,8 @@ PreflightChecks::PreflightChecks() : Page(ICON_MODEL_SETUP)
 
   auto form = new FormWindow(&body, rect_t{});
   form->setFlexLayout();
-  FlexGridLayout grid(line_col_dsc, line_row_dsc, 4);
+  form->padAll(4);
+  FlexGridLayout grid(line_col_dsc, line_row_dsc, 2);
 
   // Display checklist
   auto line = form->newLine(&grid);
diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp
index cc4fa1b900d..63b3e0d2b60 100644
--- a/radio/src/gui/colorlcd/screen_setup.cpp
+++ b/radio/src/gui/colorlcd/screen_setup.cpp
@@ -216,10 +216,15 @@ ScreenSetupPage::ScreenSetupPage(ScreenMenu* menu, unsigned pageIndex,
 {
 }
 
-void ScreenSetupPage::build(FormWindow * form)
+void ScreenSetupPage::build(FormWindow * oform)
 {
-  FlexGridLayout grid(line_col_dsc, line_row_dsc);
+  oform->padAll(0);
+  lv_obj_set_scrollbar_mode(oform->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
+
+  auto form = new FormWindow(oform, rect_t{});
   form->setFlexLayout();
+  form->padAll(4);
+  FlexGridLayout grid(line_col_dsc, line_row_dsc);
 
   // Layout choice...
   auto line = form->newLine(&grid);
diff --git a/radio/src/gui/colorlcd/screen_user_interface.cpp b/radio/src/gui/colorlcd/screen_user_interface.cpp
index bce9a4962b3..f10da2ec78f 100644
--- a/radio/src/gui/colorlcd/screen_user_interface.cpp
+++ b/radio/src/gui/colorlcd/screen_user_interface.cpp
@@ -91,10 +91,15 @@ ScreenUserInterfacePage::ScreenUserInterfacePage(ScreenMenu* menu):
 {
 }
 
-void ScreenUserInterfacePage::build(FormWindow* form)
+void ScreenUserInterfacePage::build(FormWindow* oform)
 {
-  FlexGridLayout grid(line_col_dsc, line_row_dsc);
+  oform->padAll(0);
+  lv_obj_set_scrollbar_mode(oform->getLvObj(), LV_SCROLLBAR_MODE_AUTO);
+
+  auto form = new FormWindow(oform, rect_t{});
   form->setFlexLayout();
+  form->padAll(4);
+  FlexGridLayout grid(line_col_dsc, line_row_dsc);
 
   // Top Bar
   auto line = form->newLine(&grid);
diff --git a/radio/src/gui/colorlcd/timer_setup.cpp b/radio/src/gui/colorlcd/timer_setup.cpp
index 3000b2df3b4..3eee8752213 100644
--- a/radio/src/gui/colorlcd/timer_setup.cpp
+++ b/radio/src/gui/colorlcd/timer_setup.cpp
@@ -59,6 +59,9 @@ TimerWindow::TimerWindow(uint8_t timer) : Page(ICON_STATS_TIMERS)
   std::string title = std::string(STR_TIMER) + std::to_string(timer + 1);
   header.setTitle(title);
 
+  body.padAll(0);
+  lv_obj_set_scrollbar_mode(body.getLvObj(), LV_SCROLLBAR_MODE_AUTO);
+
   auto form = new FormGroup(&body, rect_t{});
   form->setFlexLayout();
   form->padAll(lv_dpx(8));