From 7b555d7c7bd9d3236e251039be950358bf318393 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 1 Sep 2016 19:46:44 +0300 Subject: [PATCH] Implement touch interactions for List It wasn't working on touchscreens at all because the touch events were passed to the list items by Container and not converted into mouse events for the list itself to process. --- source/list.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++----- source/list.h | 9 ++++++- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/source/list.cpp b/source/list.cpp index a5928ec..5a9f749 100644 --- a/source/list.cpp +++ b/source/list.cpp @@ -44,6 +44,9 @@ void List::init() max_scroll = 0; view_size = 5; ignore_slider_change = false; + dragging = false; + drag_start_x = 0; + drag_start_y = 0; observer = new DataObserver(*this); @@ -173,6 +176,13 @@ void List::set_selected_index(int i) } } +void List::set_selected_item(Widget *item) +{ + for(unsigned i=first; (iis_visible()); ++i) + if(item==items[i]) + return set_selected_index(i); +} + void List::rebuild_special(const Part &part) { if(part.get_name()=="slider") @@ -244,13 +254,60 @@ void List::button_press(int x, int y, unsigned btn) { Container::button_press(x, y, btn); if(click_focus && btn==1) + set_selected_item(click_focus); + } +} + +void List::touch_press(int x, int y, unsigned finger) +{ + if(finger==0) + { + dragging = true; + drag_start_x = x; + drag_start_y = y; + } +} + +void List::touch_release(int x, int y, unsigned finger) +{ + if(finger==0) + { + int dx = x-drag_start_x; + int dy = y-drag_start_y; + if(dx*dx+dy*dy<25) { - for(unsigned i=first; (iis_visible()); ++i) - if(click_focus==items[i]) - { - set_selected_index(i); - break; - } + Container::touch_press(drag_start_x, drag_start_y, finger); + if(touch_focus) + set_selected_item(touch_focus); + Container::touch_motion(x, y, finger); + Container::touch_release(x, y, finger); + } + dragging = false; + } +} + +void List::touch_motion(int, int y, unsigned finger) +{ + if(finger==0 && !items.empty() && dragging) + { + int dy = y-drag_start_y; + if(dy>0 && firstget_geometry().h; + if(dy>item_h) + { + drag_start_y += item_h; + slider.set_value(max_scroll-(first+1)); + } + } + else if(dy<0 && first>0) + { + int item_h = items[first-1]->get_geometry().h; + if(-dy>item_h) + { + drag_start_y -= item_h; + slider.set_value(max_scroll-(first-1)); + } } } } diff --git a/source/list.h b/source/list.h index 5a95b08..c0ea6d2 100644 --- a/source/list.h +++ b/source/list.h @@ -143,6 +143,9 @@ private: unsigned max_scroll; unsigned view_size; bool ignore_slider_change; + bool dragging; + int drag_start_x; + int drag_start_y; VSlider slider; std::vector items; @@ -184,13 +187,17 @@ public: void set_selected_index(int); int get_selected_index() const { return sel_index; } - private: + void set_selected_item(Widget *); + virtual void rebuild_special(const Part &); virtual void render_special(const Part &, GL::Renderer &) const; public: virtual void button_press(int, int, unsigned); + virtual void touch_press(int, int, unsigned); + virtual void touch_release(int, int, unsigned); + virtual void touch_motion(int, int, unsigned); virtual void focus_in(); virtual bool navigate(Navigation); private: -- 2.43.0