Quellcode durchsuchen

Merge pull request #720 from oltaco/newui-multiclick-toggles

new-ui: add double/triple clicks, buzzer and gps toggle functions
ripplebiz vor 11 Monaten
Ursprung
Commit
5782c2e799

+ 53 - 12
examples/companion_radio/ui-new/UITask.cpp

@@ -225,11 +225,11 @@ public:
   }
 
   bool handleInput(char c) override {
-    if (c == KEY_LEFT) {
+    if (c == KEY_LEFT || c == KEY_PREV) {
       _page = (_page + HomePage::Count - 1) % HomePage::Count;
       return true;
     }
-    if (c == KEY_RIGHT || c == KEY_SELECT) {
+    if (c == KEY_NEXT || c == KEY_RIGHT) {
       _page = (_page + 1) % HomePage::Count;
       if (_page == HomePage::RECENT) {
         _task->showAlert("Recent adverts", 800);
@@ -331,7 +331,7 @@ public:
   }
 
   bool handleInput(char c) override {
-    if (c == KEY_SELECT || c == KEY_RIGHT) {
+    if (c == KEY_NEXT || c == KEY_RIGHT) {
       num_unread--;
       if (num_unread == 0) {
         _task->gotoHomeScreen();
@@ -494,9 +494,13 @@ void UITask::loop() {
 #if defined(PIN_USER_BTN)
   int ev = user_btn.check();
   if (ev == BUTTON_EVENT_CLICK) {
-    c = checkDisplayOn(KEY_SELECT);
+    c = checkDisplayOn(KEY_NEXT);
   } else if (ev == BUTTON_EVENT_LONG_PRESS) {
     c = handleLongPress(KEY_ENTER);
+  } else if (ev == BUTTON_EVENT_DOUBLE_CLICK) {
+    c = handleDoubleClick(KEY_PREV);
+  } else if (ev == BUTTON_EVENT_TRIPLE_CLICK) {
+    c = handleTripleClick(KEY_SELECT);
   }
 #endif
 #if defined(WIO_TRACKER_L1)
@@ -516,9 +520,13 @@ void UITask::loop() {
 #if defined(PIN_USER_BTN_ANA)
   ev = analog_btn.check();
   if (ev == BUTTON_EVENT_CLICK) {
-    c = checkDisplayOn(KEY_SELECT);
+    c = checkDisplayOn(KEY_NEXT);
   } else if (ev == BUTTON_EVENT_LONG_PRESS) {
     c = handleLongPress(KEY_ENTER);
+  } else if (ev == BUTTON_EVENT_DOUBLE_CLICK) {
+    c = handleDoubleClick(KEY_PREV);
+  } else if (ev == BUTTON_EVENT_TRIPLE_CLICK) {
+    c = handleTripleClick(KEY_SELECT);
   }
 #endif
 #if defined(DISP_BACKLIGHT) && defined(BACKLIGHT_BTN)
@@ -615,20 +623,53 @@ char UITask::handleLongPress(char c) {
   return c;
 }
 
-/*
-void UITask::handleButtonTriplePress() {
-  MESH_DEBUG_PRINTLN("UITask: triple press triggered");
-  // Toggle buzzer quiet mode
+char UITask::handleDoubleClick(char c) {
+  MESH_DEBUG_PRINTLN("UITask: double click triggered");
+  checkDisplayOn(c);
+  return c;
+}
+
+char UITask::handleTripleClick(char c) {
+  MESH_DEBUG_PRINTLN("UITask: triple click triggered");
+  checkDisplayOn(c);
+  toggleBuzzer();
+  c = 0;
+  return c;
+}
+
+void UITask::toggleGPS() {
+    if (_sensors != NULL) {
+    // toggle GPS on/off
+    int num = _sensors->getNumSettings();
+    for (int i = 0; i < num; i++) {
+      if (strcmp(_sensors->getSettingName(i), "gps") == 0) {
+        if (strcmp(_sensors->getSettingValue(i), "1") == 0) {
+          _sensors->setSettingValue("gps", "0");
+          soundBuzzer(UIEventType::ack);
+          showAlert("GPS: Disabled", 800);
+        } else {
+          _sensors->setSettingValue("gps", "1");
+          soundBuzzer(UIEventType::ack);
+          showAlert("GPS: Enabled", 800);
+        }
+        _next_refresh = 0;
+        break;
+      }
+    }
+  }
+}
+
+void UITask::toggleBuzzer() {
+    // Toggle buzzer quiet mode
   #ifdef PIN_BUZZER
     if (buzzer.isQuiet()) {
       buzzer.quiet(false);
       soundBuzzer(UIEventType::ack);
-      showAlert("Buzzer: ON", 600);
+      showAlert("Buzzer: ON", 800);
     } else {
       buzzer.quiet(true);
-      showAlert("Buzzer: OFF", 600);
+      showAlert("Buzzer: OFF", 800);
     }
     _next_refresh = 0;  // trigger refresh
   #endif
 }
-*/

+ 6 - 0
examples/companion_radio/ui-new/UITask.h

@@ -43,6 +43,8 @@ class UITask : public AbstractUITask {
   // Button action handlers
   char checkDisplayOn(char c);
   char handleLongPress(char c);
+  char handleDoubleClick(char c);
+  char handleTripleClick(char c);
 
   void setCurrScreen(UIScreen* c);
 
@@ -61,6 +63,10 @@ public:
   bool hasDisplay() const { return _display != NULL; }
   bool isButtonPressed() const;
 
+  void toggleBuzzer();
+  void toggleGPS();
+
+
   // from AbstractUITask
   void msgRead(int msgcount) override;
   void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) override;

+ 58 - 4
src/helpers/ui/MomentaryButton.cpp

@@ -1,5 +1,7 @@
 #include "MomentaryButton.h"
 
+#define MULTI_CLICK_WINDOW_MS  280
+
 MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, bool reverse, bool pulldownup) { 
   _pin = pin;
   _reverse = reverse;
@@ -9,6 +11,10 @@ MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, bool reverse
   cancel = 0;
   _long_millis = long_press_millis;
   _threshold = 0;
+  _click_count = 0;
+  _last_click_time = 0;
+  _multi_click_window = MULTI_CLICK_WINDOW_MS;
+  _pending_click = false;
 }
 
 MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, int analog_threshold) {
@@ -20,6 +26,10 @@ MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, int analog_t
   cancel = 0;
   _long_millis = long_press_millis;
   _threshold = analog_threshold;
+  _click_count = 0;
+  _last_click_time = 0;
+  _multi_click_window = MULTI_CLICK_WINDOW_MS;
+  _pending_click = false;
 }
 
 void MomentaryButton::begin() {
@@ -35,6 +45,10 @@ bool  MomentaryButton::isPressed() const {
 
 void MomentaryButton::cancelClick() {
   cancel = 1;
+  down_at = 0;
+  _click_count = 0;
+  _last_click_time = 0;
+  _pending_click = false;
 }
 
 bool MomentaryButton::isPressed(int level) const {
@@ -60,13 +74,20 @@ int MomentaryButton::check(bool repeat_click) {
       // button UP
       if (_long_millis > 0) {
         if (down_at > 0 && (unsigned long)(millis() - down_at) < _long_millis) {  // only a CLICK if still within the long_press millis
-          event = BUTTON_EVENT_CLICK;
+            _click_count++;
+            _last_click_time = millis();
+            _pending_click = true;
         }
       } else {
-        event = BUTTON_EVENT_CLICK;  // any UP results in CLICK event when NOT using long_press feature
+          _click_count++;
+          _last_click_time = millis();
+          _pending_click = true;
       }
       if (event == BUTTON_EVENT_CLICK && cancel) {
         event = BUTTON_EVENT_NONE;
+        _click_count = 0;
+        _last_click_time = 0;
+        _pending_click = false;
       }
       down_at = 0;
     }
@@ -77,8 +98,16 @@ int MomentaryButton::check(bool repeat_click) {
   }
 
   if (_long_millis > 0 && down_at > 0 && (unsigned long)(millis() - down_at) >= _long_millis) {
-    event = BUTTON_EVENT_LONG_PRESS;
-    down_at = 0;
+    if (_pending_click) {
+      // long press during multi-click detection - cancel pending clicks
+      cancelClick();
+    } else {
+      event = BUTTON_EVENT_LONG_PRESS;
+      down_at = 0;
+      _click_count = 0;
+      _last_click_time = 0;
+      _pending_click = false;
+    }
   }
   if (down_at > 0 && repeat_click) {
     unsigned long diff = (unsigned long)(millis() - down_at);
@@ -87,5 +116,30 @@ int MomentaryButton::check(bool repeat_click) {
     }
   }
 
+  if (_pending_click && (millis() - _last_click_time) >= _multi_click_window) {
+    if (down_at > 0) {
+      // still pressed - wait for button release before processing clicks
+      return event;
+    }
+    switch (_click_count) {
+      case 1:
+        event = BUTTON_EVENT_CLICK;
+        break;
+      case 2:
+        event = BUTTON_EVENT_DOUBLE_CLICK;
+        break;
+      case 3:
+        event = BUTTON_EVENT_TRIPLE_CLICK;
+        break;
+      default:
+        // For 4+ clicks, treat as triple click?
+        event = BUTTON_EVENT_TRIPLE_CLICK;
+        break;
+    }
+    _click_count = 0;
+    _last_click_time = 0;
+    _pending_click = false;
+  }
+
   return event;
 }

+ 6 - 0
src/helpers/ui/MomentaryButton.h

@@ -5,6 +5,8 @@
 #define BUTTON_EVENT_NONE        0
 #define BUTTON_EVENT_CLICK       1
 #define BUTTON_EVENT_LONG_PRESS  2
+#define BUTTON_EVENT_DOUBLE_CLICK 3
+#define BUTTON_EVENT_TRIPLE_CLICK 4
 
 class MomentaryButton {
   int8_t _pin;
@@ -13,6 +15,10 @@ class MomentaryButton {
   int _long_millis;
   int _threshold;  // analog mode
   unsigned long down_at;
+  uint8_t _click_count;
+  unsigned long _last_click_time;
+  int _multi_click_window;
+  bool _pending_click;
 
   bool isPressed(int level) const;
 

+ 11 - 7
src/helpers/ui/UIScreen.h

@@ -2,13 +2,17 @@
 
 #include "DisplayDriver.h"
 
-#define KEY_LEFT     0xB4
-#define KEY_UP       0xB5
-#define KEY_DOWN     0xB6
-#define KEY_RIGHT    0xB7
-#define KEY_SELECT     10
-#define KEY_ENTER      13
-#define KEY_BACK       27   // Esc
+#define KEY_LEFT           0xB4
+#define KEY_UP             0xB5
+#define KEY_DOWN           0xB6
+#define KEY_RIGHT          0xB7
+#define KEY_SELECT           10
+#define KEY_ENTER            13
+#define KEY_CANCEL           27   // Esc
+#define KEY_HOME           0xF0
+#define KEY_NEXT           0xF1
+#define KEY_PREV           0xF2
+#define KEY_CONTEXT_MENU   0xF3
 
 class UIScreen {
 protected: