Skip to content

Commit 88378aa

Browse files
committed
flickable
1 parent ed4bef2 commit 88378aa

File tree

4 files changed

+191
-135
lines changed

4 files changed

+191
-135
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#include "flickable.hpp"
2+
3+
using namespace ruis::touch;
4+
5+
bool flickable::on_mouse_button(const mouse_button_event& event)
6+
{
7+
if (event.button != mouse_button::left) {
8+
return false;
9+
}
10+
11+
// Single touch mode.
12+
if (this->cur_state != state::idle) {
13+
if (this->cur_pointer_id != event.pointer_id) {
14+
return false;
15+
}
16+
}
17+
18+
utki::assert(this->cur_state == state::idle || event.pointer_id == this->cur_pointer_id, SL);
19+
20+
switch (this->cur_state) {
21+
default:
22+
utki::assert(false, SL);
23+
[[fallthrough]];
24+
case state::idle:
25+
utki::assert(event.is_down, SL);
26+
27+
this->cur_state = state::within_scroll_threshold;
28+
this->prev_touch_point = event.pos;
29+
this->cur_pointer_id = event.pointer_id;
30+
31+
// std::cout << "withtin scroll threshold\n";
32+
33+
this->flickable_on_mouse_button(event);
34+
return true;
35+
case state::not_scrolling:
36+
[[fallthrough]];
37+
case state::within_scroll_threshold:
38+
utki::assert(!event.is_down, SL);
39+
this->cur_state = state::idle;
40+
41+
// std::cout << "idle\n";
42+
43+
return this->flickable_on_mouse_button(event);
44+
case state::scrolling:
45+
utki::assert(!event.is_down, SL);
46+
this->cur_state = state::idle;
47+
48+
// std::cout << "idle\n";
49+
50+
return true;
51+
}
52+
}
53+
54+
bool flickable::on_mouse_move(const mouse_move_event& event)
55+
{
56+
// Single touch mode.
57+
if (this->cur_state != state::idle) {
58+
if (event.pointer_id != this->cur_pointer_id) {
59+
return this->flickable_on_mouse_move(event);
60+
}
61+
}
62+
63+
switch (this->cur_state) {
64+
default:
65+
utki::assert(false, SL);
66+
[[fallthrough]];
67+
case state::idle:
68+
return this->flickable_on_mouse_move(event);
69+
case state::within_scroll_threshold:
70+
{
71+
bool consumed = this->flickable_on_mouse_move(event);
72+
if (consumed) {
73+
this->cur_state = state::not_scrolling;
74+
75+
// std::cout << "mouse move: consumed, not scrolling\n";
76+
77+
return true;
78+
}
79+
vec2 delta = event.pos - this->prev_touch_point;
80+
vec2 abs_delta = abs(delta);
81+
82+
// std::cout << "mouse move: within scroll threshold, delta: " << delta << ", abs_delta: " << abs_delta << "\n";
83+
84+
if (abs_delta.x() > this->scroll_threshold_px || abs_delta.y() > this->scroll_threshold_px) {
85+
this->cur_state = state::scrolling;
86+
87+
// std::cout << "scrolling\n";
88+
89+
this->prev_touch_point = event.pos;
90+
91+
// send mouse button up event out of widget area to cancel any ongoing interactions
92+
{
93+
ruis::mouse_button_event mbe{
94+
false, // is_down
95+
[]() {
96+
using std::numeric_limits;
97+
98+
if constexpr (numeric_limits<ruis::real>::has_infinity) {
99+
return -numeric_limits<ruis::real>::infinity();
100+
} else {
101+
return numeric_limits<ruis::real>::min();
102+
}
103+
}(),
104+
mouse_button::left,
105+
this->cur_pointer_id
106+
};
107+
this->flickable_on_mouse_button(mbe);
108+
}
109+
110+
this->flickable_scroll_by(-delta);
111+
}
112+
}
113+
return true;
114+
case state::not_scrolling:
115+
// std::cout << "mouse move: not scrolling\n";
116+
return this->flickable_on_mouse_move(event);
117+
case state::scrolling:
118+
{
119+
auto delta = event.pos - this->prev_touch_point;
120+
121+
// std::cout << "mouse move: scrolling, delta: " << delta << "\n";
122+
this->flickable_scroll_by(-delta);
123+
this->prev_touch_point = event.pos;
124+
return true;
125+
}
126+
}
127+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#pragma once
2+
3+
#include "../../widget.hpp"
4+
5+
namespace ruis::touch {
6+
7+
class flickable : virtual public ruis::widget
8+
{
9+
constexpr static auto scroll_threshold_pp = 5;
10+
11+
// TODO: convert from scroll_threshold_pp in on_reload()?
12+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers, "constant value")
13+
real scroll_threshold_px = 10;
14+
15+
enum class state {
16+
idle,
17+
within_scroll_threshold,
18+
not_scrolling,
19+
scrolling
20+
} cur_state = state::idle;
21+
22+
vec2 prev_touch_point;
23+
24+
// Scroll area only works in single touch mode.
25+
// This variable holds the pointer ID of the current touch.
26+
unsigned cur_pointer_id = std::numeric_limits<unsigned>::max();
27+
28+
public:
29+
bool on_mouse_button(const mouse_button_event& event) override;
30+
bool on_mouse_move(const mouse_move_event& event) override;
31+
32+
protected:
33+
// TODO: doxygen
34+
virtual bool flickable_on_mouse_button(const mouse_button_event& event) = 0;
35+
36+
virtual bool flickable_on_mouse_move(const mouse_move_event& event) = 0;
37+
38+
virtual void flickable_scroll_by(const vec2& delta) = 0;
39+
};
40+
41+
} // namespace ruis::touch

src/ruis/widget/group/touch/scroll_area.cpp

Lines changed: 14 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -44,125 +44,25 @@ scroll_area::scroll_area(
4444

4545
bool scroll_area::on_mouse_button(const mouse_button_event& event)
4646
{
47-
if (event.button != mouse_button::left) {
48-
return false;
49-
}
50-
51-
// Single touch mode.
52-
if (this->cur_state != state::idle) {
53-
if (this->cur_pointer_id != event.pointer_id) {
54-
return false;
55-
}
56-
}
57-
58-
utki::assert(this->cur_state == state::idle || event.pointer_id == this->cur_pointer_id, SL);
59-
60-
switch (this->cur_state) {
61-
default:
62-
utki::assert(false, SL);
63-
[[fallthrough]];
64-
case state::idle:
65-
utki::assert(event.is_down, SL);
66-
67-
this->cur_state = state::within_scroll_threshold;
68-
this->prev_touch_point = event.pos;
69-
this->cur_pointer_id = event.pointer_id;
70-
71-
std::cout << "withtin scroll threshold\n";
72-
73-
ruis::scroll_area::on_mouse_button(event);
74-
return true;
75-
case state::not_scrolling:
76-
[[fallthrough]];
77-
case state::within_scroll_threshold:
78-
utki::assert(!event.is_down, SL);
79-
this->cur_state = state::idle;
80-
81-
std::cout << "idle\n";
82-
83-
return ruis::scroll_area::on_mouse_button(event);
84-
case state::scrolling:
85-
utki::assert(!event.is_down, SL);
86-
this->cur_state = state::idle;
87-
88-
std::cout << "idle\n";
89-
90-
return true;
91-
}
47+
return this->flickable::on_mouse_button(event);
9248
}
9349

9450
bool scroll_area::on_mouse_move(const mouse_move_event& event)
9551
{
96-
// Single touch mode.
97-
if (this->cur_state != state::idle) {
98-
if (event.pointer_id != this->cur_pointer_id) {
99-
return this->ruis::scroll_area::on_mouse_move(event);
100-
}
101-
}
102-
103-
switch (this->cur_state) {
104-
default:
105-
utki::assert(false, SL);
106-
[[fallthrough]];
107-
case state::idle:
108-
return ruis::scroll_area::on_mouse_move(event);
109-
case state::within_scroll_threshold:
110-
{
111-
bool consumed = ruis::scroll_area::on_mouse_move(event);
112-
if (consumed) {
113-
this->cur_state = state::not_scrolling;
114-
115-
std::cout << "mouse move: consumed, not scrolling\n";
116-
117-
return true;
118-
}
119-
vec2 delta = event.pos - this->prev_touch_point;
120-
vec2 abs_delta = abs(delta);
121-
122-
std::cout << "mouse move: within scroll threshold, delta: " << delta << ", abs_delta: " << abs_delta
123-
<< "\n";
124-
125-
if (abs_delta.x() > this->scroll_threshold_px || abs_delta.y() > this->scroll_threshold_px) {
126-
this->cur_state = state::scrolling;
127-
128-
std::cout << "scrolling\n";
129-
130-
this->prev_touch_point = event.pos;
131-
132-
// send mouse button up event out of widget area to cancel any ongoing interactions
133-
{
134-
ruis::mouse_button_event mbe{
135-
false, // is_down
136-
[]() {
137-
using std::numeric_limits;
52+
return this->flickable::on_mouse_move(event);
53+
}
13854

139-
if constexpr (numeric_limits<ruis::real>::has_infinity) {
140-
return -numeric_limits<ruis::real>::infinity();
141-
} else {
142-
return numeric_limits<ruis::real>::min();
143-
}
144-
}(),
145-
mouse_button::left,
146-
this->cur_pointer_id
147-
};
148-
this->ruis::scroll_area::on_mouse_button(mbe);
149-
}
55+
bool scroll_area::flickable_on_mouse_button(const mouse_button_event& event)
56+
{
57+
return this->ruis::scroll_area::on_mouse_button(event);
58+
}
15059

151-
this->scroll_by(-delta);
152-
}
153-
}
154-
return true;
155-
case state::not_scrolling:
156-
std::cout << "mouse move: not scrolling\n";
157-
return ruis::scroll_area::on_mouse_move(event);
158-
case state::scrolling:
159-
{
160-
auto delta = event.pos - this->prev_touch_point;
60+
bool scroll_area::flickable_on_mouse_move(const mouse_move_event& event)
61+
{
62+
return this->ruis::scroll_area::on_mouse_move(event);
63+
}
16164

162-
std::cout << "mouse move: scrolling, delta: " << delta << "\n";
163-
this->scroll_by(-delta);
164-
this->prev_touch_point = event.pos;
165-
return true;
166-
}
167-
}
65+
void scroll_area::flickable_scroll_by(const vec2& delta)
66+
{
67+
this->scroll_by(delta);
16868
}

src/ruis/widget/group/touch/scroll_area.hpp

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2121

2222
#pragma once
2323

24+
#include "../../base/touch/flickable.hpp"
2425
#include "../scroll_area.hpp"
2526

2627
namespace ruis::touch {
2728

28-
class scroll_area : public ruis::scroll_area
29+
class scroll_area :
30+
public ruis::scroll_area, //
31+
private touch::flickable
2932
{
30-
constexpr static auto scroll_threshold_pp = 5;
31-
32-
// TODO: convert from scroll_threshold_pp in on_reload()?
33-
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers, "constant value")
34-
real scroll_threshold_px = 10;
35-
36-
enum class state {
37-
idle,
38-
within_scroll_threshold,
39-
not_scrolling,
40-
scrolling
41-
} cur_state = state::idle;
42-
43-
vec2 prev_touch_point;
44-
45-
// Scroll area only works in single touch mode.
46-
// This variable holds the pointer ID of the current touch.
47-
unsigned cur_pointer_id = std::numeric_limits<unsigned>::max();
48-
4933
public:
5034
scroll_area(
5135
utki::shared_ref<ruis::context> context, //
@@ -54,8 +38,12 @@ class scroll_area : public ruis::scroll_area
5438
);
5539

5640
bool on_mouse_button(const mouse_button_event& event) override;
57-
5841
bool on_mouse_move(const mouse_move_event& event) override;
42+
43+
private:
44+
bool flickable_on_mouse_button(const mouse_button_event& event) override;
45+
bool flickable_on_mouse_move(const mouse_move_event& event) override;
46+
void flickable_scroll_by(const vec2& delta) override;
5947
};
6048

6149
} // namespace ruis::touch

0 commit comments

Comments
 (0)