Add support for gestures and integrate it with the vertical scrolling transition.
This commit is contained in:
		
							parent
							
								
									968f18f472
								
							
						
					
					
						commit
						35e221078b
					
				@ -33,6 +33,7 @@ DisplayApp::DisplayApp(Pinetime::Drivers::St7789& lcd,
 | 
			
		||||
        currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController) },
 | 
			
		||||
        systemTask{systemTask} {
 | 
			
		||||
  msgQueue = xQueueCreate(queueSize, itemSize);
 | 
			
		||||
  onClockApp = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DisplayApp::Start() {
 | 
			
		||||
@ -112,24 +113,44 @@ void DisplayApp::Refresh() {
 | 
			
		||||
      case Messages::UpdateBatteryLevel:
 | 
			
		||||
//        clockScreen.SetBatteryPercentRemaining(batteryController.PercentRemaining());
 | 
			
		||||
        break;
 | 
			
		||||
      case Messages::TouchEvent:
 | 
			
		||||
      case Messages::TouchEvent: {
 | 
			
		||||
        if (state != States::Running) break;
 | 
			
		||||
        OnTouchEvent();
 | 
			
		||||
        auto gesture = OnTouchEvent();
 | 
			
		||||
        switch (gesture) {
 | 
			
		||||
          case DisplayApp::TouchEvents::SwipeUp:
 | 
			
		||||
            currentScreen->OnButtonPushed();
 | 
			
		||||
            lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::Up);
 | 
			
		||||
            break;
 | 
			
		||||
          case DisplayApp::TouchEvents::SwipeDown:
 | 
			
		||||
            currentScreen->OnButtonPushed();
 | 
			
		||||
            lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::Down);
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
        break;
 | 
			
		||||
      case Messages::ButtonPushed:
 | 
			
		||||
//        if(!currentScreen->OnButtonPushed()) {
 | 
			
		||||
//          systemTask.PushMessage(System::SystemTask::Messages::GoToSleep);
 | 
			
		||||
//        }
 | 
			
		||||
        lvgl.SetFullRefresh();
 | 
			
		||||
        lv_disp_set_direction(lv_disp_get_default(), 0);
 | 
			
		||||
        currentScreen.reset(nullptr);
 | 
			
		||||
        if(toggle) {
 | 
			
		||||
          currentScreen.reset(new Screens::Tile(this));
 | 
			
		||||
          toggle = false;
 | 
			
		||||
        if(onClockApp)
 | 
			
		||||
          systemTask.PushMessage(System::SystemTask::Messages::GoToSleep);
 | 
			
		||||
        else {
 | 
			
		||||
          auto buttonUsedByApp = currentScreen->OnButtonPushed();
 | 
			
		||||
          if (!buttonUsedByApp) {
 | 
			
		||||
            systemTask.PushMessage(System::SystemTask::Messages::GoToSleep);
 | 
			
		||||
          } else {
 | 
			
		||||
          currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController));
 | 
			
		||||
          toggle = true;
 | 
			
		||||
            lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::Up);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//        lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::Down);
 | 
			
		||||
//        currentScreen.reset(nullptr);
 | 
			
		||||
//        if(toggle) {
 | 
			
		||||
//          currentScreen.reset(new Screens::Tile(this));
 | 
			
		||||
//          toggle = false;
 | 
			
		||||
//        } else {
 | 
			
		||||
//          currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController));
 | 
			
		||||
//          toggle = true;
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
@ -140,12 +161,15 @@ void DisplayApp::RunningState() {
 | 
			
		||||
//  clockScreen.SetCurrentDateTime(dateTimeController.CurrentDateTime());
 | 
			
		||||
 | 
			
		||||
  if(!currentScreen->Refresh()) {
 | 
			
		||||
    lvgl.SetFullRefresh();
 | 
			
		||||
    currentScreen.reset(nullptr);
 | 
			
		||||
    onClockApp = false;
 | 
			
		||||
    switch(nextApp) {
 | 
			
		||||
      case Apps::None:
 | 
			
		||||
      case Apps::Launcher: currentScreen.reset(new Screens::Tile(this)); break;
 | 
			
		||||
      case Apps::Clock: currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController)); break;
 | 
			
		||||
      case Apps::Clock:
 | 
			
		||||
        currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController));
 | 
			
		||||
        onClockApp = true;
 | 
			
		||||
        break;
 | 
			
		||||
      case Apps::Test: currentScreen.reset(new Screens::Message(this)); break;
 | 
			
		||||
      case Apps::Meter: currentScreen.reset(new Screens::Meter(this)); break;
 | 
			
		||||
      case Apps::Gauge: currentScreen.reset(new Screens::Gauge(this)); break;
 | 
			
		||||
@ -169,14 +193,32 @@ void DisplayApp::PushMessage(DisplayApp::Messages msg) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint16_t pointColor = 0x07e0;
 | 
			
		||||
void DisplayApp::OnTouchEvent() {
 | 
			
		||||
//  auto info = touchPanel.GetTouchInfo();
 | 
			
		||||
//
 | 
			
		||||
//  if(info.isTouch) {
 | 
			
		||||
//    lcd.DrawPixel(info.x, info.y, pointColor);
 | 
			
		||||
//    pointColor+=10;
 | 
			
		||||
//  }
 | 
			
		||||
DisplayApp::TouchEvents DisplayApp::OnTouchEvent() {
 | 
			
		||||
  auto info = touchPanel.GetTouchInfo();
 | 
			
		||||
  if(info.isTouch) {
 | 
			
		||||
    switch(info.gesture) {
 | 
			
		||||
      case Pinetime::Drivers::Cst816S::Gestures::SingleTap:
 | 
			
		||||
        // TODO set x,y to LittleVgl
 | 
			
		||||
        lvgl.SetNewTapEvent(info.x, info.y);
 | 
			
		||||
        return DisplayApp::TouchEvents::Tap;
 | 
			
		||||
      case Pinetime::Drivers::Cst816S::Gestures::LongPress:
 | 
			
		||||
        return DisplayApp::TouchEvents::LongTap;
 | 
			
		||||
      case Pinetime::Drivers::Cst816S::Gestures::DoubleTap:
 | 
			
		||||
        return DisplayApp::TouchEvents::DoubleTap;
 | 
			
		||||
      case Pinetime::Drivers::Cst816S::Gestures::SlideRight:
 | 
			
		||||
        return DisplayApp::TouchEvents::SwipeRight;
 | 
			
		||||
      case Pinetime::Drivers::Cst816S::Gestures::SlideLeft:
 | 
			
		||||
        return DisplayApp::TouchEvents::SwipeLeft;
 | 
			
		||||
      case Pinetime::Drivers::Cst816S::Gestures::SlideDown:
 | 
			
		||||
        return DisplayApp::TouchEvents::SwipeDown;
 | 
			
		||||
      case Pinetime::Drivers::Cst816S::Gestures::SlideUp:
 | 
			
		||||
        return DisplayApp::TouchEvents::SwipeUp;
 | 
			
		||||
      case Pinetime::Drivers::Cst816S::Gestures::None:
 | 
			
		||||
      default:
 | 
			
		||||
        return DisplayApp::TouchEvents::None;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return DisplayApp::TouchEvents::None;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DisplayApp::StartApp(DisplayApp::Apps app) {
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,8 @@ namespace Pinetime {
 | 
			
		||||
      public:
 | 
			
		||||
        enum class States {Idle, Running};
 | 
			
		||||
        enum class Messages : uint8_t {GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent, SwitchScreen,ButtonPushed} ;
 | 
			
		||||
        enum class TouchEvents { None, Tap, SwipeLeft, SwipeRight, SwipeUp, SwipeDown, LongTap, DoubleTap
 | 
			
		||||
        };
 | 
			
		||||
        DisplayApp(Pinetime::Drivers::St7789& lcd,
 | 
			
		||||
                   Pinetime::Components::LittleVgl& lvgl,
 | 
			
		||||
                   Pinetime::Drivers::Cst816S&,
 | 
			
		||||
@ -59,7 +61,7 @@ namespace Pinetime {
 | 
			
		||||
        Pinetime::Controllers::DateTime& dateTimeController;
 | 
			
		||||
 | 
			
		||||
        Pinetime::Drivers::Cst816S& touchPanel;
 | 
			
		||||
        void OnTouchEvent();
 | 
			
		||||
        TouchEvents OnTouchEvent();
 | 
			
		||||
 | 
			
		||||
        std::unique_ptr<Screens::Screen> currentScreen;
 | 
			
		||||
        static constexpr uint8_t pinLcdBacklight1 = 14;
 | 
			
		||||
@ -70,6 +72,7 @@ namespace Pinetime {
 | 
			
		||||
 | 
			
		||||
        Pinetime::System::SystemTask& systemTask;
 | 
			
		||||
        Apps nextApp = Apps::None;
 | 
			
		||||
        bool onClockApp = false; // TODO find a better way to know that we should handle gestures and button differently for the Clock app.
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -64,8 +64,10 @@ void LittleVgl::InitTouchpad() {
 | 
			
		||||
  lv_indev_drv_register(&indev_drv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LittleVgl::SetFullRefresh() {
 | 
			
		||||
  fullRefresh = true;
 | 
			
		||||
void LittleVgl::SetFullRefresh(FullRefreshDirections direction) {
 | 
			
		||||
  scrollDirection = direction;
 | 
			
		||||
  if(scrollDirection == FullRefreshDirections::Down)
 | 
			
		||||
    lv_disp_set_direction(lv_disp_get_default(), 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LittleVgl::FlushDisplay(const lv_area_t *area, lv_color_t *color_p) {
 | 
			
		||||
@ -74,8 +76,7 @@ void LittleVgl::FlushDisplay(const lv_area_t *area, lv_color_t *color_p) {
 | 
			
		||||
  // TODO refactore and remove duplicated code
 | 
			
		||||
 | 
			
		||||
  uint16_t x, y, y1, y2, width, height = 0;
 | 
			
		||||
  if(fullRefresh) {
 | 
			
		||||
    if(scrollDirection == LittleVgl::ScrollDirections::Down) {
 | 
			
		||||
  if(scrollDirection == LittleVgl::FullRefreshDirections::Down) {
 | 
			
		||||
    if(area->y2 == visibleNbLines-1) {
 | 
			
		||||
        writeOffset = ((writeOffset + totalNbLines) - visibleNbLines) % totalNbLines;
 | 
			
		||||
    }
 | 
			
		||||
@ -91,7 +92,7 @@ void LittleVgl::FlushDisplay(const lv_area_t *area, lv_color_t *color_p) {
 | 
			
		||||
      uint16_t toScroll = 0;
 | 
			
		||||
        if(area->y1 == 0) {
 | 
			
		||||
        toScroll = height*2;
 | 
			
		||||
          fullRefresh = false;
 | 
			
		||||
        scrollDirection = FullRefreshDirections::None;
 | 
			
		||||
        lv_disp_set_direction(lv_disp_get_default(), 0);
 | 
			
		||||
      } else {
 | 
			
		||||
        toScroll = height;
 | 
			
		||||
@ -111,7 +112,7 @@ void LittleVgl::FlushDisplay(const lv_area_t *area, lv_color_t *color_p) {
 | 
			
		||||
    lcd.BeginDrawBuffer(x, y, width, height);
 | 
			
		||||
    lcd.NextDrawBuffer(reinterpret_cast<const uint8_t *>(color_p), width * height*2) ;
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
  } else if(scrollDirection == FullRefreshDirections::Up) {
 | 
			
		||||
    if(area->y1 == 0) {
 | 
			
		||||
      writeOffset = (writeOffset + visibleNbLines) % totalNbLines;
 | 
			
		||||
    }
 | 
			
		||||
@ -127,7 +128,7 @@ void LittleVgl::FlushDisplay(const lv_area_t *area, lv_color_t *color_p) {
 | 
			
		||||
    if(area->y1 > 0) {
 | 
			
		||||
      if(area->y2 == visibleNbLines -1) {
 | 
			
		||||
        scrollOffset += (height * 2);
 | 
			
		||||
          fullRefresh = false;
 | 
			
		||||
        scrollDirection = FullRefreshDirections::None;
 | 
			
		||||
        lv_disp_set_direction(lv_disp_get_default(), 0);
 | 
			
		||||
      } else {
 | 
			
		||||
        scrollOffset += height;
 | 
			
		||||
@ -139,21 +140,50 @@ void LittleVgl::FlushDisplay(const lv_area_t *area, lv_color_t *color_p) {
 | 
			
		||||
 | 
			
		||||
    lcd.BeginDrawBuffer(x, y, width, height);
 | 
			
		||||
    lcd.NextDrawBuffer(reinterpret_cast<const uint8_t *>(color_p), width * height*2);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    x = area->x1;
 | 
			
		||||
    y = area->y1;
 | 
			
		||||
    width = (area->x2 - area->x1) + 1;
 | 
			
		||||
    height = (area->y2 - area->y1) + 1;
 | 
			
		||||
    y1 = (area->y1 + writeOffset) % totalNbLines;
 | 
			
		||||
    y2 = (area->y2 + writeOffset) % totalNbLines;
 | 
			
		||||
    y = y1;
 | 
			
		||||
    height = (y2 - y1) + 1;
 | 
			
		||||
 | 
			
		||||
    if (y2 < y1) {
 | 
			
		||||
      height = (totalNbLines - 1) - y1;
 | 
			
		||||
      lcd.BeginDrawBuffer(x, y1, width, height);
 | 
			
		||||
      lcd.NextDrawBuffer(reinterpret_cast<const uint8_t *>(color_p), width * height * 2);
 | 
			
		||||
      ulTaskNotifyTake(pdTRUE, 500);
 | 
			
		||||
      height = y2;
 | 
			
		||||
      lcd.BeginDrawBuffer(x, 0, width, height);
 | 
			
		||||
      lcd.NextDrawBuffer(reinterpret_cast<const uint8_t *>(color_p), width * height * 2);
 | 
			
		||||
    } else {
 | 
			
		||||
      lcd.BeginDrawBuffer(x, y, width, height);
 | 
			
		||||
      lcd.NextDrawBuffer(reinterpret_cast<const uint8_t *>(color_p), width * height * 2);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* IMPORTANT!!!
 | 
			
		||||
   * Inform the graphics library that you are ready with the flushing*/
 | 
			
		||||
  lv_disp_flush_ready(&disp_drv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LittleVgl::SetNewTapEvent(uint16_t x, uint16_t y) {
 | 
			
		||||
  tap_x = x;
 | 
			
		||||
  tap_y = y;
 | 
			
		||||
  tapped = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool LittleVgl::GetTouchPadInfo(lv_indev_data_t *ptr) {
 | 
			
		||||
  if(tapped) {
 | 
			
		||||
    ptr->point.x = tap_x;
 | 
			
		||||
    ptr->point.y = tap_y;
 | 
			
		||||
    ptr->state = LV_INDEV_STATE_PR;
 | 
			
		||||
    tapped = false;
 | 
			
		||||
  } else {
 | 
			
		||||
    ptr->state = LV_INDEV_STATE_REL;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
  /*
 | 
			
		||||
  auto info = touchPanel.GetTouchInfo();
 | 
			
		||||
 | 
			
		||||
  if((previousClick.x != info.x || previousClick.y != info.y) &&
 | 
			
		||||
@ -173,6 +203,7 @@ bool LittleVgl::GetTouchPadInfo(lv_indev_data_t *ptr) {
 | 
			
		||||
  ptr->point.x = info.x;
 | 
			
		||||
  ptr->point.y = info.y;
 | 
			
		||||
  return false;
 | 
			
		||||
   */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LittleVgl::InitTheme() {
 | 
			
		||||
@ -790,3 +821,5 @@ void LittleVgl::InitThemeWindow() {
 | 
			
		||||
//  theme.style.win.btn.pr  = &win_btn_pr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@ namespace Pinetime {
 | 
			
		||||
  namespace Components {
 | 
			
		||||
    class LittleVgl {
 | 
			
		||||
      public:
 | 
			
		||||
        enum class FullRefreshDirections { None, Up, Down };
 | 
			
		||||
        LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel);
 | 
			
		||||
 | 
			
		||||
        LittleVgl(const LittleVgl&) = delete;
 | 
			
		||||
@ -23,7 +24,9 @@ namespace Pinetime {
 | 
			
		||||
 | 
			
		||||
        void FlushDisplay(const lv_area_t * area, lv_color_t * color_p);
 | 
			
		||||
        bool GetTouchPadInfo(lv_indev_data_t *ptr);
 | 
			
		||||
        void SetFullRefresh();
 | 
			
		||||
        void SetFullRefresh(FullRefreshDirections direction);
 | 
			
		||||
        void SetNewTapEvent(uint16_t x, uint16_t y);
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
        void InitDisplay();
 | 
			
		||||
        void InitTouchpad();
 | 
			
		||||
@ -99,15 +102,17 @@ namespace Pinetime {
 | 
			
		||||
        lv_style_t win_btn_pr;
 | 
			
		||||
 | 
			
		||||
        bool firstTouch = true;
 | 
			
		||||
        bool fullRefresh = false;
 | 
			
		||||
        static constexpr uint8_t nbWriteLines = 4;
 | 
			
		||||
        static constexpr uint16_t totalNbLines = 320;
 | 
			
		||||
        static constexpr uint16_t visibleNbLines = 240;
 | 
			
		||||
        static constexpr uint8_t MaxScrollOffset() { return LV_VER_RES_MAX - nbWriteLines; }
 | 
			
		||||
        enum class ScrollDirections {Unknown, Up, Down};
 | 
			
		||||
        ScrollDirections scrollDirection = ScrollDirections::Up;
 | 
			
		||||
        FullRefreshDirections scrollDirection = FullRefreshDirections::None;
 | 
			
		||||
        uint16_t writeOffset = 0;
 | 
			
		||||
        uint16_t scrollOffset = 0;
 | 
			
		||||
 | 
			
		||||
        uint16_t tap_x = 0;
 | 
			
		||||
        uint16_t tap_y = 0;
 | 
			
		||||
        bool tapped = false;
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -184,7 +184,8 @@ void Clock::OnObjectEvent(lv_obj_t *obj, lv_event_t event) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Clock::OnButtonPushed() {
 | 
			
		||||
  return Screen::OnButtonPushed();
 | 
			
		||||
  running = false;
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user