reflexion 0.1.22 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/reflex/event.cpp +9 -1
  3. data/.doc/ext/reflex/key_event.cpp +3 -3
  4. data/.doc/ext/reflex/native.cpp +2 -0
  5. data/.doc/ext/reflex/pointer.cpp +158 -0
  6. data/.doc/ext/reflex/pointer_event.cpp +29 -88
  7. data/.doc/ext/reflex/selector.cpp +8 -0
  8. data/.doc/ext/reflex/view.cpp +57 -0
  9. data/.doc/ext/reflex/window.cpp +24 -0
  10. data/VERSION +1 -1
  11. data/ext/reflex/event.cpp +11 -2
  12. data/ext/reflex/key_event.cpp +3 -3
  13. data/ext/reflex/native.cpp +2 -0
  14. data/ext/reflex/pointer.cpp +170 -0
  15. data/ext/reflex/pointer_event.cpp +29 -94
  16. data/ext/reflex/selector.cpp +9 -0
  17. data/ext/reflex/view.cpp +67 -3
  18. data/ext/reflex/window.cpp +30 -3
  19. data/include/reflex/defs.h +0 -18
  20. data/include/reflex/event.h +26 -27
  21. data/include/reflex/pointer.h +107 -0
  22. data/include/reflex/ruby/pointer.h +41 -0
  23. data/include/reflex/ruby/view.h +9 -0
  24. data/include/reflex/ruby/window.h +9 -0
  25. data/include/reflex/selector.h +1 -1
  26. data/include/reflex/view.h +6 -4
  27. data/include/reflex/window.h +10 -8
  28. data/lib/reflex/key_event.rb +1 -1
  29. data/lib/reflex/pointer.rb +107 -0
  30. data/lib/reflex/pointer_event.rb +16 -54
  31. data/lib/reflex.rb +1 -0
  32. data/reflex.gemspec +5 -5
  33. data/src/event.cpp +189 -37
  34. data/src/event.h +32 -0
  35. data/src/ios/event.h +15 -3
  36. data/src/ios/event.mm +126 -11
  37. data/src/ios/view_controller.mm +49 -21
  38. data/src/osx/event.h +6 -3
  39. data/src/osx/event.mm +40 -22
  40. data/src/osx/native_window.mm +79 -16
  41. data/src/pointer.cpp +203 -0
  42. data/src/pointer.h +26 -0
  43. data/src/selector.cpp +1 -1
  44. data/src/view.cpp +83 -72
  45. data/src/view.h +0 -4
  46. data/src/window.cpp +321 -97
  47. data/src/window.h +22 -3
  48. data/test/test_event.rb +16 -2
  49. data/test/test_pointer.rb +149 -0
  50. data/test/test_pointer_event.rb +70 -104
  51. data/test/test_selector.rb +7 -0
  52. data/test/test_view.rb +38 -11
  53. data/test/test_window.rb +27 -25
  54. metadata +46 -35
data/src/window.cpp CHANGED
@@ -1,14 +1,25 @@
1
1
  #include "window.h"
2
2
 
3
3
 
4
+ #include <set>
4
5
  #include "reflex/exception.h"
5
6
  #include "view.h"
7
+ #include "event.h"
6
8
 
7
9
 
8
10
  namespace Reflex
9
11
  {
10
12
 
11
13
 
14
+ using ViewList = std::vector<View::Ref>;
15
+
16
+ using PointerMap = std::map<Pointer::ID, Pointer>;
17
+
18
+ using ExtractedPointerIDSet = std::set<Pointer::ID>;
19
+
20
+ using CaptureTargetIDList = Window::Data::CaptureTargetIDList;
21
+
22
+
12
23
  void
13
24
  Window_set_focus (Window* window, View* view)
14
25
  {
@@ -36,6 +47,80 @@ namespace Reflex
36
47
  }
37
48
  }
38
49
 
50
+ namespace global
51
+ {
52
+
53
+ static Window_CreateRootViewFun create_root_view_fun = NULL;
54
+
55
+ }// global
56
+
57
+ void
58
+ Window_set_create_root_view_fun (Window_CreateRootViewFun fun)
59
+ {
60
+ global::create_root_view_fun = fun;
61
+ }
62
+
63
+ static View*
64
+ create_root_view ()
65
+ {
66
+ return global::create_root_view_fun
67
+ ? global::create_root_view_fun()
68
+ : new View();
69
+ }
70
+
71
+ void
72
+ Window_register_capture (Window* window, View* view, Pointer::ID target)
73
+ {
74
+ assert(window);
75
+
76
+ if (!view)
77
+ argument_error(__FILE__, __LINE__);
78
+
79
+ if (view->window() != window)
80
+ invalid_state_error(__FILE__, __LINE__);
81
+
82
+ if (target < 0) return;
83
+
84
+ auto& targets = window->self->captures[view];
85
+ if (std::find(targets.begin(), targets.end(), target) != targets.end())
86
+ return;
87
+
88
+ targets.insert(
89
+ target == CAPTURE_ALL ? targets.begin() : targets.end(),
90
+ target);
91
+ }
92
+
93
+ void
94
+ Window_unregister_capture (Window* window, View* view, Pointer::ID target)
95
+ {
96
+ assert(window);
97
+
98
+ if (!view)
99
+ argument_error(__FILE__, __LINE__);
100
+
101
+ auto captures_it = window->self->captures.find(view);
102
+ if (captures_it == window->self->captures.end()) return;
103
+
104
+ auto& targets = captures_it->second;
105
+ auto targets_it = std::find(targets.begin(), targets.end(), target);
106
+ if (targets_it == targets.end()) return;
107
+
108
+ targets.erase(targets_it);
109
+ }
110
+
111
+ static void
112
+ cleanup_captures (Window* window)
113
+ {
114
+ assert(window);
115
+
116
+ auto& caps = window->self->captures;
117
+ for (auto it = caps.begin(), end = caps.end(); it != end;)
118
+ {
119
+ auto t = it++;
120
+ if (t->second.empty()) caps.erase(t);
121
+ }
122
+ }
123
+
39
124
  void
40
125
  Window_call_draw_event (Window* window, DrawEvent* event)
41
126
  {
@@ -63,66 +148,252 @@ namespace Reflex
63
148
  painter->end();
64
149
  }
65
150
 
66
- namespace global
151
+ static bool
152
+ is_capturing (
153
+ const View* view, const CaptureTargetIDList& targets, View::Capture type)
67
154
  {
155
+ return
156
+ !targets.empty() &&
157
+ targets[0] == CAPTURE_ALL &&
158
+ (view->capture() & type) == type;
159
+ }
68
160
 
69
- static Window_CreateRootViewFun create_root_view_fun = NULL;
161
+ void
162
+ Window_call_key_event (Window* window, KeyEvent* event)
163
+ {
164
+ assert(window);
70
165
 
71
- }// global
166
+ if (!event)
167
+ argument_error(__FILE__, __LINE__);
72
168
 
73
- void
74
- Window_set_create_root_view_fun (Window_CreateRootViewFun fun)
169
+ window->on_key(event);
170
+
171
+ switch (event->type)
172
+ {
173
+ case KeyEvent::DOWN: window->on_key_down(event); break;
174
+ case KeyEvent::UP: window->on_key_up(event); break;
175
+ default: break;
176
+ }
177
+
178
+ for (auto& [view, targets] : window->self->captures)
179
+ {
180
+ if (!is_capturing(view.get(), targets, View::CAPTURE_KEY))
181
+ continue;
182
+
183
+ KeyEvent e = *event;
184
+ e.captured = true;
185
+ View_call_key_event(const_cast<View*>(view.get()), e);
186
+ }
187
+
188
+ if (window->self->focus)
189
+ View_call_key_event(window->self->focus.get(), *event);
190
+
191
+ cleanup_captures(window);
192
+ }
193
+
194
+ static void
195
+ get_views_capturing_all_pointers (Window* window, ViewList* result)
75
196
  {
76
- global::create_root_view_fun = fun;
197
+ assert(window && result);
198
+
199
+ result->clear();
200
+ for (const auto& [view, targets] : window->self->captures)
201
+ {
202
+ if (is_capturing(view.get(), targets, View::CAPTURE_POINTER))
203
+ result->emplace_back(view);
204
+ }
77
205
  }
78
206
 
79
- static View*
80
- create_root_view ()
207
+ static void
208
+ capture_all_pointers (
209
+ Window* window, const PointerEvent& event, ViewList& views_capturing_all)
81
210
  {
82
- return global::create_root_view_fun
83
- ? global::create_root_view_fun()
84
- : new View();
211
+ assert(window);
212
+
213
+ if (views_capturing_all.empty()) return;
214
+
215
+ PointerEvent_each_pointer(&event, [&](const auto& pointer)
216
+ {
217
+ if (pointer.action() == Pointer::DOWN)
218
+ {
219
+ for (auto& view : views_capturing_all)
220
+ Window_register_capture(window, view, pointer.id());
221
+ }
222
+ });
85
223
  }
86
224
 
87
- void
88
- View_register_capture (View* view)
225
+ static void
226
+ extract_pointer (
227
+ PointerEvent* event, ExtractedPointerIDSet* extracteds,
228
+ const Pointer& pointer)
89
229
  {
90
- if (!view)
91
- argument_error(__FILE__, __LINE__);
230
+ assert(event && extracteds);
231
+
232
+ PointerEvent_add_pointer(event, pointer);
233
+ extracteds->insert(pointer.id());
234
+ }
92
235
 
93
- const Window* window = view->window();
94
- if (!window)
95
- invalid_state_error(__FILE__, __LINE__, "this view does not belong to any Window.");
236
+ static void
237
+ extract_targeted_pointers (
238
+ PointerEvent* event, ExtractedPointerIDSet* extracteds,
239
+ const CaptureTargetIDList& targets, const PointerMap& pointers)
240
+ {
241
+ assert(event && event->empty() && extracteds);
96
242
 
97
- window->self->capturing_views[view] = true;
243
+ for (auto pointer_id : targets)
244
+ {
245
+ auto it = pointers.find(pointer_id);
246
+ if (it != pointers.end())
247
+ extract_pointer(event, extracteds, it->second);
248
+ }
98
249
  }
99
250
 
100
- void
101
- View_unregister_capture (View* view)
251
+ static void
252
+ capture_targeted_pointers_and_call_events (
253
+ ExtractedPointerIDSet* extracteds,
254
+ Window* window, const PointerMap& pointers)
102
255
  {
103
- if (!view)
104
- argument_error(__FILE__, __LINE__);
256
+ assert(extracteds && window);
105
257
 
106
- const Window* window = view->window();
107
- if (!window) return;
258
+ for (auto& [view, targets] : window->self->captures)
259
+ {
260
+ if (targets.empty()) continue;
108
261
 
109
- auto it = window->self->capturing_views.find(view);
110
- if (it == window->self->capturing_views.end()) return;
262
+ PointerEvent e(true);
263
+ extract_targeted_pointers(&e, extracteds, targets, pointers);
264
+ if (e.empty()) continue;
111
265
 
112
- it->second = false;
266
+ PointerEvent_update_for_capturing_view(&e, view);
267
+ View_call_pointer_event(const_cast<View*>(view.get()), e);
268
+ }
113
269
  }
114
270
 
115
271
  static void
116
- cleanup_capturing_views (Window* window)
272
+ extract_hovering_pointers (
273
+ PointerEvent* event, ExtractedPointerIDSet* extracteds,
274
+ const PointerMap& pointers)
117
275
  {
118
- auto end = window->self->capturing_views.end();
119
- for (auto it = window->self->capturing_views.begin(); it != end;)
276
+ assert(event && event->empty() && extracteds);
277
+
278
+ for (const auto& [_, pointer] : pointers)
120
279
  {
121
- auto t = it++;
122
- if (!t->second) window->self->capturing_views.erase(t);
280
+ // dragging pointers is captured as a targeted
281
+ if (pointer.is_drag()) continue;
282
+
283
+ extract_pointer(event, extracteds, pointer);
284
+ }
285
+ }
286
+
287
+ static void
288
+ capture_hovering_pointers_and_call_events (
289
+ ExtractedPointerIDSet* extracteds,
290
+ const ViewList& views_capturing_all, const PointerMap& pointers)
291
+ {
292
+ assert(extracteds);
293
+
294
+ if (views_capturing_all.empty()) return;
295
+
296
+ PointerEvent event(true);
297
+ extract_hovering_pointers(&event, extracteds, pointers);
298
+ if (event.empty()) return;
299
+
300
+ for (auto& view : views_capturing_all)
301
+ {
302
+ PointerEvent e = event;
303
+ PointerEvent_update_for_capturing_view(&e, view);
304
+ View_call_pointer_event(const_cast<View*>(view.get()), e);
123
305
  }
124
306
  }
125
307
 
308
+ static void
309
+ erase_extracted_pointers (
310
+ PointerMap* pointers, const ExtractedPointerIDSet& extracteds)
311
+ {
312
+ assert(pointers);
313
+
314
+ for (auto id : extracteds)
315
+ {
316
+ auto it = pointers->find(id);
317
+ if (it != pointers->end()) pointers->erase(it);
318
+ }
319
+ }
320
+
321
+ static void
322
+ erase_extracted_pointers (
323
+ PointerEvent* event, const ExtractedPointerIDSet& extracteds)
324
+ {
325
+ assert(event);
326
+
327
+ for (auto id : extracteds)
328
+ PointerEvent_erase_pointer(event, id);
329
+ }
330
+
331
+ static void
332
+ call_captured_pointer_events (Window* window, PointerEvent* event)
333
+ {
334
+ assert(window && event);
335
+
336
+ ViewList views_capturing_all;
337
+ get_views_capturing_all_pointers(window, &views_capturing_all);
338
+ capture_all_pointers(window, *event, views_capturing_all);
339
+
340
+ PointerMap pointers;
341
+ PointerEvent_each_pointer(event, [&](const auto& pointer)
342
+ {
343
+ if (pointer.id() >= 0) pointers[pointer.id()] = pointer;
344
+ });
345
+
346
+ ExtractedPointerIDSet extracteds;
347
+ capture_targeted_pointers_and_call_events(&extracteds, window, pointers);
348
+ erase_extracted_pointers(&pointers, extracteds);
349
+
350
+ capture_hovering_pointers_and_call_events(&extracteds, views_capturing_all, pointers);
351
+ erase_extracted_pointers(event, extracteds);
352
+ }
353
+
354
+ void
355
+ Window_call_pointer_event (Window* window, PointerEvent* event)
356
+ {
357
+ assert(window);
358
+
359
+ if (!event)
360
+ argument_error(__FILE__, __LINE__);
361
+
362
+ window->on_pointer(event);
363
+
364
+ switch ((*event)[0].action())
365
+ {
366
+ case Pointer::DOWN: window->on_pointer_down(event); break;
367
+ case Pointer::UP: window->on_pointer_up(event); break;
368
+ case Pointer::MOVE: window->on_pointer_move(event); break;
369
+ case Pointer::CANCEL: window->on_pointer_cancel(event); break;
370
+ default: break;
371
+ }
372
+
373
+ call_captured_pointer_events(window, event);
374
+
375
+ if (!event->empty())
376
+ {
377
+ PointerEvent_update_for_child_view(event, window->root());
378
+ View_call_pointer_event(window->root(), *event);
379
+ }
380
+
381
+ cleanup_captures(window);
382
+ }
383
+
384
+ void
385
+ Window_call_wheel_event (Window* window, WheelEvent* event)
386
+ {
387
+ assert(window);
388
+
389
+ if (!event)
390
+ argument_error(__FILE__, __LINE__);
391
+
392
+ window->on_wheel(event);
393
+
394
+ View_call_wheel_event(window->root(), *event);
395
+ }
396
+
126
397
 
127
398
  Window::Window ()
128
399
  : self(Window_create_data())
@@ -191,6 +462,18 @@ namespace Reflex
191
462
  self->redraw = true;
192
463
  }
193
464
 
465
+ Point
466
+ Window::from_screen (const Point& point) const
467
+ {
468
+ return point - frame().position();
469
+ }
470
+
471
+ Point
472
+ Window::to_screen (const Point& point) const
473
+ {
474
+ return point + frame().position();
475
+ }
476
+
194
477
  void
195
478
  Window::set_title (const char* title)
196
479
  {
@@ -275,20 +558,6 @@ namespace Reflex
275
558
  return const_cast<Window*>(this)->painter();
276
559
  }
277
560
 
278
- Point
279
- Window::from_screen (const Point& point) const
280
- {
281
- not_implemented_error(__FILE__, __LINE__);
282
- return 0;
283
- }
284
-
285
- Point
286
- Window::to_screen (const Point& point) const
287
- {
288
- not_implemented_error(__FILE__, __LINE__);
289
- return 0;
290
- }
291
-
292
561
  void
293
562
  Window::on_show (Event* e)
294
563
  {
@@ -327,28 +596,6 @@ namespace Reflex
327
596
  void
328
597
  Window::on_key (KeyEvent* e)
329
598
  {
330
- if (!e)
331
- argument_error(__FILE__, __LINE__);
332
-
333
- switch (e->type)
334
- {
335
- case KeyEvent::DOWN: on_key_down(e); break;
336
- case KeyEvent::UP: on_key_up(e); break;
337
- case KeyEvent::NONE: break;
338
- }
339
-
340
- auto end = self->capturing_views.end();
341
- for (auto it = self->capturing_views.begin(); it != end; ++it)
342
- {
343
- KeyEvent event = *e;
344
- event.capture = true;
345
- View_call_key_event(const_cast<View*>(it->first.get()), event);
346
- }
347
-
348
- if (self->focus)
349
- View_call_key_event(self->focus.get(), *e);
350
-
351
- cleanup_capturing_views(this);
352
599
  }
353
600
 
354
601
  void
@@ -364,30 +611,6 @@ namespace Reflex
364
611
  void
365
612
  Window::on_pointer (PointerEvent* e)
366
613
  {
367
- if (!e)
368
- argument_error(__FILE__, __LINE__);
369
-
370
- switch (e->type)
371
- {
372
- case PointerEvent::DOWN: on_pointer_down(e); break;
373
- case PointerEvent::UP: on_pointer_up(e); break;
374
- case PointerEvent::MOVE: on_pointer_move(e); break;
375
- case PointerEvent::NONE: break;
376
- }
377
-
378
- auto end = self->capturing_views.end();
379
- for (auto it = self->capturing_views.begin(); it != end; ++it)
380
- {
381
- PointerEvent event = *e;
382
- event.capture = true;
383
- for (size_t i = 0; i < event.size; ++i)
384
- event[i] = it->first.get()->from_window(event[i]);
385
- View_call_pointer_event(const_cast<View*>(it->first.get()), event);
386
- }
387
-
388
- View_call_pointer_event(root(), *e);
389
-
390
- cleanup_capturing_views(this);
391
614
  }
392
615
 
393
616
  void
@@ -406,12 +629,13 @@ namespace Reflex
406
629
  }
407
630
 
408
631
  void
409
- Window::on_wheel (WheelEvent* e)
632
+ Window::on_pointer_cancel (PointerEvent* e)
410
633
  {
411
- if (!e)
412
- argument_error(__FILE__, __LINE__);
634
+ }
413
635
 
414
- View_call_wheel_event(root(), *e);
636
+ void
637
+ Window::on_wheel (WheelEvent* e)
638
+ {
415
639
  }
416
640
 
417
641
  Window::operator bool () const
data/src/window.h CHANGED
@@ -4,22 +4,29 @@
4
4
  #define __REFLEX_SRC_WINDOW_H__
5
5
 
6
6
 
7
+ #include <vector>
7
8
  #include <map>
8
9
  #include <xot/time.h>
9
10
  #include <rays/point.h>
10
11
  #include <rays/painter.h>
11
12
  #include <reflex/window.h>
12
13
  #include <reflex/view.h>
14
+ #include "pointer.h"
13
15
 
14
16
 
15
17
  namespace Reflex
16
18
  {
17
19
 
18
20
 
21
+ enum {CAPTURE_ALL = INT_MAX};
22
+
23
+
19
24
  struct Window::Data
20
25
  {
21
26
 
22
- typedef std::map<View::Ref, bool> CapturingViews;
27
+ typedef std::vector<Pointer::ID> CaptureTargetIDList;
28
+
29
+ typedef std::map<View::Ref, CaptureTargetIDList> CaptureMap;
23
30
 
24
31
  int hide_count = 1;
25
32
 
@@ -33,7 +40,7 @@ namespace Reflex
33
40
 
34
41
  double prev_time_update, prev_time_draw, prev_fps = 0;
35
42
 
36
- CapturingViews capturing_views;
43
+ CaptureMap captures;
37
44
 
38
45
  Data ()
39
46
  {
@@ -84,7 +91,19 @@ namespace Reflex
84
91
 
85
92
  void Window_set_focus (Window* window, View* view);
86
93
 
87
- void Window_call_draw_event (Window* window, DrawEvent* event);
94
+ void Window_register_capture (
95
+ Window* window, View* view, Pointer::ID target = CAPTURE_ALL);
96
+
97
+ void Window_unregister_capture (
98
+ Window* window, View* view, Pointer::ID target = CAPTURE_ALL);
99
+
100
+ void Window_call_draw_event (Window* window, DrawEvent* event);
101
+
102
+ void Window_call_key_event (Window* window, KeyEvent* event);
103
+
104
+ void Window_call_pointer_event (Window* window, PointerEvent* event);
105
+
106
+ void Window_call_wheel_event (Window* window, WheelEvent* event);
88
107
 
89
108
  float Window_get_pixel_density (const Window& window);
90
109
 
data/test/test_event.rb CHANGED
@@ -10,11 +10,25 @@ class TestEvent < Test::Unit::TestCase
10
10
  Reflex::Event.new
11
11
  end
12
12
 
13
+ def test_dup()
14
+ e1 = event
15
+ e2 = e1.dup
16
+ e1.block
17
+ e3 = e1.dup
18
+ assert_equal true, e1.blocked?
19
+ assert_equal false, e2.blocked?
20
+ assert_equal true, e3.blocked?
21
+ end
22
+
13
23
  def test_block()
14
24
  e = event
15
- assert_equal false, e.block?
25
+ assert_equal false, e.blocked?
16
26
  e.block
17
- assert_equal true, e.block?
27
+ assert_equal true, e.blocked?
28
+ end
29
+
30
+ def test_time()
31
+ assert_in_delta Time.now.to_f, event.time, 0.001
18
32
  end
19
33
 
20
34
  end# TestEvent