InfiniTime.git

commit 7d3af600bd056e0f4be7d31122cc2dbb352cef70

Author: JF <jf@codingfield.com>

Add TouchModes : in Gestures mode, only 1 event is processed for each touchevent. This allows to recognize gesture and handle them in Screens or in DisplayApp.
In Polling mode, X/Y positions are sent continuously to lvgl, allowing to scroll inside a dropdown menu for example.

 src/CMakeLists.txt | 4 +
 src/DisplayApp/DisplayApp.cpp | 13 +++++
 src/DisplayApp/DisplayApp.h | 4 +
 src/DisplayApp/Screens/DropDownDemo.cpp | 64 +++++++++++++++++++++++++++
 src/DisplayApp/Screens/DropDownDemo.h | 29 ++++++++++++


diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 63bb05912e727bae45578829d67fad2ee233a964..dbd919bc81b87d3307333b928d67fc83f637306e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -287,6 +287,8 @@   libs/lvgl/src/lv_objx/lv_bar.c
   libs/lvgl/src/lv_objx/lv_bar.h
   libs/lvgl/src/lv_objx/lv_slider.h
   libs/lvgl/src/lv_objx/lv_slider.c
+    libs/lvgl/src/lv_objx/lv_ddlist.c
+    libs/lvgl/src/lv_objx/lv_ddlist.h
   )
 
 list(APPEND IMAGE_FILES
@@ -327,6 +329,7 @@   DisplayApp/Screens/Clock.cpp
   DisplayApp/Screens/Tile.cpp
   DisplayApp/Screens/Meter.cpp
   DisplayApp/Screens/Gauge.cpp
+  DisplayApp/Screens/DropDownDemo.cpp
   DisplayApp/Screens/Modal.cpp
   DisplayApp/Screens/BatteryIcon.cpp
   DisplayApp/Screens/BleIcon.cpp
@@ -400,6 +403,7 @@   DisplayApp/Screens/Clock.h
   DisplayApp/Screens/Tile.h
   DisplayApp/Screens/Meter.h
   DisplayApp/Screens/Gauge.h
+  DisplayApp/Screens/DropDownDemo.h
   DisplayApp/Screens/Modal.h
   DisplayApp/Screens/BatteryIcon.h
   DisplayApp/Screens/BleIcon.cpp




diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp
index 175bdc802d492a2aab7c8d7d08c8ef6faa2cdaef..6de746cc168e4396ccb8b3fb1a194ee06be30da9 100644
--- a/src/DisplayApp/DisplayApp.cpp
+++ b/src/DisplayApp/DisplayApp.cpp
@@ -171,6 +171,12 @@
         break;
     }
   }
+
+  if(touchMode == TouchModes::Polling) {
+    auto info = touchPanel.GetTouchInfo();
+    if(info.action == 2) // 2 = contact
+      lvgl.SetNewTapEvent(info.x, info.y);
+  }
 }
 
 void DisplayApp::RunningState() {
@@ -219,7 +225,8 @@   auto info = touchPanel.GetTouchInfo();
   if(info.isTouch) {
     switch(info.gesture) {
       case Pinetime::Drivers::Cst816S::Gestures::SingleTap:
-        lvgl.SetNewTapEvent(info.x, info.y);
+        if(touchMode == TouchModes::Gestures)
+          lvgl.SetNewTapEvent(info.x, info.y);
         return TouchEvents::Tap;
       case Pinetime::Drivers::Cst816S::Gestures::LongPress:
         return TouchEvents::LongTap;
@@ -257,3 +264,7 @@     default: break;
   }
 
 }
+
+void DisplayApp::SetTouchMode(DisplayApp::TouchModes mode) {
+  touchMode = mode;
+}




diff --git a/src/DisplayApp/DisplayApp.h b/src/DisplayApp/DisplayApp.h
index 478953c8452667d28f3c346b1b4d269558dc49d8..345e06d4d12b43cb13e5dc4f13539e8a65dbd1ee 100644
--- a/src/DisplayApp/DisplayApp.h
+++ b/src/DisplayApp/DisplayApp.h
@@ -34,6 +34,7 @@         enum class Messages : uint8_t {GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent, ButtonPushed,
             NewNotification, BleFirmwareUpdateStarted };
 
         enum class FullRefreshDirections { None, Up, Down };
+        enum class TouchModes { Gestures, Polling };
 
         DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Drivers::Cst816S &,
                    Controllers::Battery &batteryController, Controllers::Ble &bleController,
@@ -46,6 +47,8 @@
         void StartApp(Apps app);
 
         void SetFullRefresh(FullRefreshDirections direction);
+        void SetTouchMode(TouchModes mode);
+
       private:
         TaskHandle_t taskHandle;
         static void Process(void* instance);
@@ -81,6 +84,7 @@         Controllers::BrightnessController brightnessController;
         std::unique_ptr<Screens::Modal> modal;
         Pinetime::Controllers::NotificationManager& notificationManager;
         Pinetime::Controllers::FirmwareValidator validator;
+        TouchModes touchMode = TouchModes::Gestures;
     };
   }
 }




diff --git a/src/DisplayApp/Screens/DropDownDemo.cpp b/src/DisplayApp/Screens/DropDownDemo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..735a0ccedecbcc71b51825830b919677eb7f28ea
--- /dev/null
+++ b/src/DisplayApp/Screens/DropDownDemo.cpp
@@ -0,0 +1,64 @@
+#include <libs/lvgl/lvgl.h>
+#include <libraries/log/nrf_log.h>
+#include "DropDownDemo.h"
+#include "../DisplayApp.h"
+
+using namespace Pinetime::Applications::Screens;
+extern lv_font_t jetbrains_mono_extrabold_compressed;
+extern lv_font_t jetbrains_mono_bold_20;
+
+DropDownDemo::DropDownDemo(Pinetime::Applications::DisplayApp *app) : Screen(app) {
+  // Create the dropdown object, with many item, and fix its height
+  ddlist = lv_ddlist_create(lv_scr_act(), NULL);
+  lv_ddlist_set_options(ddlist, "Apple\n"
+                                "Banana\n"
+                                "Orange\n"
+                                "Melon\n"
+                                "Grape\n"
+                                "Raspberry\n"
+                                "A\n"
+                                "B\n"
+                                "C\n"
+                                "D\n"
+                                "E");
+  lv_ddlist_set_fix_width(ddlist, 150);
+  lv_ddlist_set_draw_arrow(ddlist, true);
+  lv_ddlist_set_fix_height(ddlist, 150);
+  lv_obj_align(ddlist, NULL, LV_ALIGN_IN_TOP_MID, 0, 20);
+}
+
+DropDownDemo::~DropDownDemo() {
+  // Reset the touchmode
+  app->SetTouchMode(DisplayApp::TouchModes::Gestures);
+  lv_obj_clean(lv_scr_act());
+}
+
+bool DropDownDemo::Refresh() {
+  auto* list = static_cast<lv_ddlist_ext_t *>(ddlist->ext_attr);
+
+  // Switch touchmode to Polling if the dropdown is opened. This will allow to scroll inside the
+  // dropdown while it is opened.
+  // Disable the polling mode when the dropdown is closed to be able to handle the gestures.
+  if(list->opened)
+    app->SetTouchMode(DisplayApp::TouchModes::Polling);
+  else
+    app->SetTouchMode(DisplayApp::TouchModes::Gestures);
+  return running;
+}
+
+bool DropDownDemo::OnButtonPushed() {
+  running = false;
+  return true;
+}
+
+bool DropDownDemo::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
+  // If the dropdown is opened, notify Display app that it doesn't need to handle the event
+  // (this will prevent displayApp from going back to the menu or clock scree).
+  auto* list = static_cast<lv_ddlist_ext_t *>(ddlist->ext_attr);
+  if(list->opened) {
+    return true;
+  } else {
+    return false;
+  }
+}
+




diff --git a/src/DisplayApp/Screens/DropDownDemo.h b/src/DisplayApp/Screens/DropDownDemo.h
new file mode 100644
index 0000000000000000000000000000000000000000..7c75efc029f327787a85b275770f5795217dcf3e
--- /dev/null
+++ b/src/DisplayApp/Screens/DropDownDemo.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <cstdint>
+#include "Screen.h"
+#include <bits/unique_ptr.h>
+#include <libs/lvgl/src/lv_core/lv_style.h>
+#include <libs/lvgl/src/lv_core/lv_obj.h>
+
+namespace Pinetime {
+  namespace Applications {
+    namespace Screens {
+
+      class DropDownDemo : public Screen{
+        public:
+          DropDownDemo(DisplayApp* app);
+          ~DropDownDemo() override;
+
+          bool Refresh() override;
+          bool OnButtonPushed() override;
+          bool OnTouchEvent(TouchEvents event) override;
+
+        private:
+          lv_obj_t * ddlist;
+          bool running = true;
+          bool isDropDownOpened = false;
+      };
+    }
+  }
+}