reflexion 0.5.3 → 0.7.0

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 (309) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/reflex/application.cpp +56 -7
  3. data/.doc/ext/reflex/capture_event.cpp +1 -1
  4. data/.doc/ext/reflex/chase_constraint.cpp +84 -0
  5. data/.doc/ext/reflex/clipboard.cpp +65 -0
  6. data/.doc/ext/reflex/color_event.cpp +76 -0
  7. data/.doc/ext/reflex/color_picker.cpp +113 -0
  8. data/.doc/ext/reflex/constraint.cpp +135 -0
  9. data/.doc/ext/reflex/contact_event.cpp +1 -1
  10. data/.doc/ext/reflex/control_change_event.cpp +1 -1
  11. data/.doc/ext/reflex/device.cpp +1 -1
  12. data/.doc/ext/reflex/device_event.cpp +1 -1
  13. data/.doc/ext/reflex/draw_event.cpp +1 -1
  14. data/.doc/ext/reflex/ellipse_shape.cpp +1 -1
  15. data/.doc/ext/reflex/event.cpp +1 -1
  16. data/.doc/ext/reflex/file_dialog.cpp +181 -0
  17. data/.doc/ext/reflex/file_event.cpp +103 -0
  18. data/.doc/ext/reflex/filter.cpp +1 -1
  19. data/.doc/ext/reflex/focus_event.cpp +1 -1
  20. data/.doc/ext/reflex/frame_event.cpp +1 -1
  21. data/.doc/ext/reflex/gamepad.cpp +48 -0
  22. data/.doc/ext/reflex/image_view.cpp +1 -1
  23. data/.doc/ext/reflex/key_event.cpp +1 -274
  24. data/.doc/ext/reflex/line_shape.cpp +1 -1
  25. data/.doc/ext/reflex/link_constraint.cpp +178 -0
  26. data/.doc/ext/reflex/menu.cpp +303 -0
  27. data/.doc/ext/reflex/midi.cpp +9 -2
  28. data/.doc/ext/reflex/midi_event.cpp +1 -1
  29. data/.doc/ext/reflex/motion_event.cpp +1 -1
  30. data/.doc/ext/reflex/native.cpp +40 -10
  31. data/.doc/ext/reflex/note_event.cpp +1 -1
  32. data/.doc/ext/reflex/pin.cpp +156 -0
  33. data/.doc/ext/reflex/pointer.cpp +3 -1
  34. data/.doc/ext/reflex/pointer_event.cpp +3 -3
  35. data/.doc/ext/reflex/polygon_shape.cpp +1 -1
  36. data/.doc/ext/reflex/rect_shape.cpp +1 -1
  37. data/.doc/ext/reflex/reflex.cpp +606 -237
  38. data/.doc/ext/reflex/screen.cpp +27 -1
  39. data/.doc/ext/reflex/scroll_event.cpp +1 -1
  40. data/.doc/ext/reflex/selector.cpp +5 -5
  41. data/.doc/ext/reflex/shape.cpp +1 -1
  42. data/.doc/ext/reflex/snap_constraint.cpp +125 -0
  43. data/.doc/ext/reflex/style.cpp +1 -1
  44. data/.doc/ext/reflex/style_length.cpp +4 -3
  45. data/.doc/ext/reflex/text_event.cpp +104 -0
  46. data/.doc/ext/reflex/timer.cpp +1 -1
  47. data/.doc/ext/reflex/timer_event.cpp +1 -1
  48. data/.doc/ext/reflex/update_event.cpp +1 -1
  49. data/.doc/ext/reflex/view.cpp +206 -79
  50. data/.doc/ext/reflex/wheel_constraint.cpp +142 -0
  51. data/.doc/ext/reflex/wheel_event.cpp +1 -1
  52. data/.doc/ext/reflex/window.cpp +282 -31
  53. data/.github/workflows/release-gem.yml +2 -40
  54. data/.github/workflows/tag.yml +5 -28
  55. data/.github/workflows/test.yml +1 -28
  56. data/ChangeLog.md +79 -0
  57. data/Gemfile.lock +13 -8
  58. data/README.md +1 -0
  59. data/Rakefile +13 -2
  60. data/Reflex.podspec +2 -2
  61. data/VERSION +1 -1
  62. data/ext/reflex/application.cpp +62 -7
  63. data/ext/reflex/capture_event.cpp +1 -1
  64. data/ext/reflex/chase_constraint.cpp +89 -0
  65. data/ext/reflex/clipboard.cpp +69 -0
  66. data/ext/reflex/color_event.cpp +80 -0
  67. data/ext/reflex/color_picker.cpp +121 -0
  68. data/ext/reflex/constraint.cpp +146 -0
  69. data/ext/reflex/contact_event.cpp +1 -1
  70. data/ext/reflex/control_change_event.cpp +1 -1
  71. data/ext/reflex/device.cpp +1 -1
  72. data/ext/reflex/device_event.cpp +1 -1
  73. data/ext/reflex/draw_event.cpp +1 -1
  74. data/ext/reflex/ellipse_shape.cpp +1 -1
  75. data/ext/reflex/event.cpp +1 -1
  76. data/ext/reflex/extconf.rb +4 -2
  77. data/ext/reflex/file_dialog.cpp +194 -0
  78. data/ext/reflex/file_event.cpp +108 -0
  79. data/ext/reflex/filter.cpp +1 -1
  80. data/ext/reflex/focus_event.cpp +1 -1
  81. data/ext/reflex/frame_event.cpp +1 -1
  82. data/ext/reflex/gamepad.cpp +50 -0
  83. data/ext/reflex/image_view.cpp +1 -1
  84. data/ext/reflex/key_event.cpp +1 -275
  85. data/ext/reflex/line_shape.cpp +1 -1
  86. data/ext/reflex/link_constraint.cpp +194 -0
  87. data/ext/reflex/menu.cpp +331 -0
  88. data/ext/reflex/midi.cpp +11 -3
  89. data/ext/reflex/midi_event.cpp +1 -1
  90. data/ext/reflex/motion_event.cpp +1 -1
  91. data/ext/reflex/native.cpp +40 -10
  92. data/ext/reflex/note_event.cpp +1 -1
  93. data/ext/reflex/pin.cpp +165 -0
  94. data/ext/reflex/pointer.cpp +3 -1
  95. data/ext/reflex/pointer_event.cpp +3 -3
  96. data/ext/reflex/polygon_shape.cpp +1 -1
  97. data/ext/reflex/rect_shape.cpp +1 -1
  98. data/ext/reflex/reflex.cpp +608 -237
  99. data/ext/reflex/screen.cpp +31 -2
  100. data/ext/reflex/scroll_event.cpp +1 -1
  101. data/ext/reflex/selector.cpp +5 -5
  102. data/ext/reflex/selector.h +10 -10
  103. data/ext/reflex/shape.cpp +1 -1
  104. data/ext/reflex/snap_constraint.cpp +135 -0
  105. data/ext/reflex/style.cpp +1 -1
  106. data/ext/reflex/style_length.cpp +4 -3
  107. data/ext/reflex/text_event.cpp +111 -0
  108. data/ext/reflex/timer.cpp +1 -1
  109. data/ext/reflex/timer_event.cpp +1 -1
  110. data/ext/reflex/update_event.cpp +1 -1
  111. data/ext/reflex/view.cpp +236 -96
  112. data/ext/reflex/wheel_constraint.cpp +154 -0
  113. data/ext/reflex/wheel_event.cpp +1 -1
  114. data/ext/reflex/window.cpp +318 -40
  115. data/include/reflex/application.h +19 -0
  116. data/include/reflex/clipboard.h +53 -0
  117. data/include/reflex/color_picker.h +65 -0
  118. data/include/reflex/constraint.h +275 -0
  119. data/include/reflex/defs.h +204 -195
  120. data/include/reflex/event.h +180 -88
  121. data/include/reflex/file_dialog.h +73 -0
  122. data/include/reflex/gamepad.h +3 -0
  123. data/include/reflex/menu.h +120 -0
  124. data/include/reflex/midi.h +3 -0
  125. data/include/reflex/pin.h +68 -0
  126. data/include/reflex/pointer.h +4 -0
  127. data/include/reflex/reflex.h +2 -0
  128. data/include/reflex/ruby/application.h +6 -1
  129. data/include/reflex/ruby/clipboard.h +23 -0
  130. data/include/reflex/ruby/color_picker.h +89 -0
  131. data/include/reflex/ruby/constraint.h +94 -0
  132. data/include/reflex/ruby/event.h +62 -29
  133. data/include/reflex/ruby/file_dialog.h +89 -0
  134. data/include/reflex/ruby/gamepad.h +46 -0
  135. data/include/reflex/ruby/menu.h +103 -0
  136. data/include/reflex/ruby/pin.h +40 -0
  137. data/include/reflex/ruby/reflex.h +3 -0
  138. data/include/reflex/ruby/view.h +123 -39
  139. data/include/reflex/ruby/window.h +96 -19
  140. data/include/reflex/ruby.h +3 -0
  141. data/include/reflex/screen.h +11 -2
  142. data/include/reflex/view.h +66 -27
  143. data/include/reflex/window.h +57 -12
  144. data/include/reflex.h +8 -0
  145. data/lib/reflex/application.rb +5 -5
  146. data/lib/reflex/autoinit.rb +3 -1
  147. data/lib/reflex/button.rb +3 -3
  148. data/lib/reflex/chase_constraint.rb +15 -0
  149. data/lib/reflex/clipboard.rb +19 -0
  150. data/lib/reflex/color_event.rb +16 -0
  151. data/lib/reflex/color_picker.rb +45 -0
  152. data/lib/reflex/constraint.rb +29 -0
  153. data/lib/reflex/control_change_event.rb +17 -0
  154. data/lib/reflex/extension.rb +1 -1
  155. data/lib/reflex/file_dialog.rb +70 -0
  156. data/lib/reflex/file_event.rb +37 -0
  157. data/lib/reflex/helper.rb +79 -0
  158. data/lib/reflex/key_event.rb +14 -14
  159. data/lib/reflex/link_constraint.rb +31 -0
  160. data/lib/reflex/menu.rb +92 -0
  161. data/lib/reflex/model.rb +19 -19
  162. data/lib/reflex/note_event.rb +1 -1
  163. data/lib/reflex/pin.rb +39 -0
  164. data/lib/reflex/pointer.rb +30 -1
  165. data/lib/reflex/pointer_event.rb +13 -2
  166. data/lib/reflex/reflex.rb +5 -0
  167. data/lib/reflex/shape.rb +14 -14
  168. data/lib/reflex/snap_constraint.rb +28 -0
  169. data/lib/reflex/style.rb +16 -16
  170. data/lib/reflex/text_event.rb +40 -0
  171. data/lib/reflex/timer.rb +3 -3
  172. data/lib/reflex/view.rb +85 -18
  173. data/lib/reflex/wheel_constraint.rb +28 -0
  174. data/lib/reflex/wheel_event.rb +19 -1
  175. data/lib/reflex/window.rb +25 -13
  176. data/lib/reflex.rb +23 -8
  177. data/pod.rake +1 -1
  178. data/reflex.gemspec +4 -4
  179. data/samples/constraint.rb +152 -0
  180. data/samples/ime.rb +100 -0
  181. data/samples/ios/hello/hello.xcodeproj/project.pbxproj +236 -224
  182. data/samples/menu.rb +32 -0
  183. data/samples/model.rb +3 -3
  184. data/samples/test/alert.rb +93 -0
  185. data/samples/test/always_on.rb +76 -0
  186. data/samples/test/app_background.rb +51 -0
  187. data/samples/test/boundary.rb +75 -0
  188. data/samples/test/callback_exception.rb +101 -0
  189. data/samples/test/cancel.rb +53 -0
  190. data/samples/test/color_picker.rb +63 -0
  191. data/samples/test/file_dialog.rb +102 -0
  192. data/samples/window_style.rb +156 -0
  193. data/src/application.cpp +180 -20
  194. data/src/application.h +95 -5
  195. data/src/clipboard.cpp +81 -0
  196. data/src/color_picker.cpp +113 -0
  197. data/src/color_picker.h +36 -0
  198. data/src/constraint.cpp +1662 -0
  199. data/src/constraint.h +64 -0
  200. data/src/event.cpp +416 -252
  201. data/src/event.h +13 -2
  202. data/src/file_dialog.cpp +163 -0
  203. data/src/file_dialog.h +52 -0
  204. data/src/gamepad.cpp +42 -5
  205. data/src/gamepad.h +4 -0
  206. data/src/ios/app_delegate.mm +5 -3
  207. data/src/ios/application.mm +29 -0
  208. data/src/ios/clipboard.mm +44 -0
  209. data/src/ios/color_picker.mm +19 -0
  210. data/src/ios/event.h +6 -2
  211. data/src/ios/event.mm +31 -12
  212. data/src/ios/file_dialog.mm +21 -0
  213. data/src/ios/gamepad.mm +4 -4
  214. data/src/ios/menu.mm +41 -0
  215. data/src/ios/reflex.mm +8 -0
  216. data/src/ios/screen.mm +26 -0
  217. data/src/ios/view_controller.mm +47 -42
  218. data/src/ios/window.mm +44 -9
  219. data/src/menu.cpp +387 -0
  220. data/src/menu.h +81 -0
  221. data/src/midi.cpp +61 -31
  222. data/src/osx/app_delegate.h +4 -0
  223. data/src/osx/app_delegate.mm +168 -139
  224. data/src/osx/application.mm +103 -5
  225. data/src/osx/clipboard.mm +45 -0
  226. data/src/osx/color_picker.mm +112 -0
  227. data/src/osx/event.h +10 -0
  228. data/src/osx/event.mm +114 -30
  229. data/src/osx/file_dialog.mm +168 -0
  230. data/src/osx/gamepad.mm +2 -2
  231. data/src/osx/gamepad_hid.mm +1 -1
  232. data/src/osx/menu.h +25 -0
  233. data/src/osx/menu.mm +516 -0
  234. data/src/osx/native_window.h +16 -2
  235. data/src/osx/native_window.mm +141 -57
  236. data/src/osx/opengl_view.h +2 -1
  237. data/src/osx/opengl_view.mm +229 -37
  238. data/src/osx/reflex.mm +38 -0
  239. data/src/osx/screen.mm +36 -0
  240. data/src/osx/window.mm +117 -24
  241. data/src/pin.cpp +137 -0
  242. data/src/pointer.cpp +36 -16
  243. data/src/pointer.h +10 -0
  244. data/src/rays.h +46 -0
  245. data/src/sdl/application.cpp +73 -8
  246. data/src/sdl/clipboard.cpp +39 -0
  247. data/src/sdl/color_picker.cpp +18 -0
  248. data/src/sdl/event.cpp +44 -6
  249. data/src/sdl/event.h +18 -3
  250. data/src/sdl/file_dialog.cpp +20 -0
  251. data/src/sdl/gamepad.cpp +3 -7
  252. data/src/sdl/menu.cpp +40 -0
  253. data/src/sdl/reflex.cpp +20 -0
  254. data/src/sdl/screen.cpp +36 -0
  255. data/src/sdl/window.cpp +168 -37
  256. data/src/shape.cpp +15 -10
  257. data/src/view.cpp +583 -233
  258. data/src/view.h +22 -4
  259. data/src/vk.h +416 -0
  260. data/src/win32/application.cpp +167 -12
  261. data/src/win32/application.h +20 -0
  262. data/src/win32/clipboard.cpp +210 -0
  263. data/src/win32/color_picker.cpp +82 -0
  264. data/src/win32/event.cpp +123 -11
  265. data/src/win32/event.h +22 -3
  266. data/src/win32/file_dialog.cpp +226 -0
  267. data/src/win32/gamepad.cpp +9 -2
  268. data/src/win32/menu.cpp +490 -0
  269. data/src/win32/menu.h +35 -0
  270. data/src/win32/opengl.cpp +2 -9
  271. data/src/win32/reflex.cpp +44 -3
  272. data/src/win32/screen.cpp +164 -3
  273. data/src/win32/screen.h +8 -0
  274. data/src/win32/tray.cpp +191 -0
  275. data/src/win32/tray.h +22 -0
  276. data/src/win32/vk.cpp +11 -0
  277. data/src/win32/window.cpp +858 -135
  278. data/src/win32/window.h +9 -0
  279. data/src/window.cpp +929 -183
  280. data/src/window.h +77 -33
  281. data/src/world.cpp +86 -15
  282. data/src/world.h +9 -2
  283. data/test/helper.rb +24 -0
  284. data/test/test_application.rb +101 -1
  285. data/test/test_chase_constraint.rb +122 -0
  286. data/test/test_clipboard.rb +54 -0
  287. data/test/test_color_event.rb +36 -0
  288. data/test/test_color_picker.rb +62 -0
  289. data/test/test_constraint.rb +184 -0
  290. data/test/test_event.rb +1 -1
  291. data/test/test_file_dialog.rb +48 -0
  292. data/test/test_file_event.rb +43 -0
  293. data/test/test_has_text_preedit.rb +54 -0
  294. data/test/test_key_event.rb +23 -2
  295. data/test/test_link_constraint.rb +237 -0
  296. data/test/test_menu.rb +237 -0
  297. data/test/test_pin.rb +65 -0
  298. data/test/test_pointer.rb +50 -26
  299. data/test/test_pointer_event.rb +25 -10
  300. data/test/test_reflex.rb +36 -0
  301. data/test/test_screen.rb +24 -2
  302. data/test/test_snap_constraint.rb +140 -0
  303. data/test/test_text_event.rb +54 -0
  304. data/test/test_view.rb +152 -25
  305. data/test/test_wheel_constraint.rb +125 -0
  306. data/test/test_wheel_event.rb +24 -10
  307. data/test/test_window.rb +205 -43
  308. metadata +154 -10
  309. data/.github/workflows/utils.rb +0 -127
@@ -3,16 +3,20 @@ require_relative 'helper'
3
3
 
4
4
  class TestPointerEvent < Test::Unit::TestCase
5
5
 
6
- TYPE_NONE = Reflex::Pointer::TYPE_NONE
7
- TOUCH = Reflex::Pointer::TOUCH
8
- PEN = Reflex::Pointer::PEN
6
+ R = Reflex
9
7
 
10
- ACTION_NONE = Reflex::Pointer::ACTION_NONE
11
- DOWN = Reflex::Pointer::DOWN
12
- UP = Reflex::Pointer::UP
8
+ TYPE_NONE = R::Pointer::TYPE_NONE
9
+ MOUSE = R::Pointer::MOUSE
10
+ LEFT = R::Pointer::MOUSE_LEFT
11
+ TOUCH = R::Pointer::TOUCH
12
+ PEN = R::Pointer::PEN
13
+
14
+ ACTION_NONE = R::Pointer::ACTION_NONE
15
+ DOWN = R::Pointer::DOWN
16
+ UP = R::Pointer::UP
13
17
 
14
18
  def event(*args, **kwargs)
15
- Reflex::PointerEvent.new(*args, **kwargs)
19
+ R::PointerEvent.new(*args, **kwargs)
16
20
  end
17
21
 
18
22
  def pointer(
@@ -20,8 +24,7 @@ class TestPointerEvent < Test::Unit::TestCase
20
24
  position: 0, modifiers: 0, click_count: 0, drag: false,
21
25
  time: 0)
22
26
 
23
- Reflex::Pointer.new(
24
- id, type, action, position, modifiers, click_count, drag, time)
27
+ R::Pointer.new(id, type, action, position, modifiers, click_count, drag, time)
25
28
  end
26
29
 
27
30
  def test_initialize()
@@ -50,7 +53,7 @@ class TestPointerEvent < Test::Unit::TestCase
50
53
  assert_equal [2, 3], e.pos .to_a
51
54
  assert_equal 2, e.x
52
55
  assert_equal 3, e.y
53
- assert_equal 4, e.modifiers
56
+ assert_equal [:shift], e.modifiers
54
57
  assert_equal 5, e.click_count
55
58
  assert_equal true, e.drag?
56
59
  assert_equal 6, e.time
@@ -89,4 +92,16 @@ class TestPointerEvent < Test::Unit::TestCase
89
92
  assert_nil e[-4]
90
93
  end
91
94
 
95
+ def test_inspect()
96
+ assert_equal(
97
+ "#<Reflex::PointerEvent id:1 [:mouse, :mouse_left] :down (2.0, 3.0) mod:[:shift, :control] click:5 drag:true time:4.0>",
98
+ event(
99
+ pointer(
100
+ id: 1, type: MOUSE | LEFT, action: DOWN,
101
+ position: [2, 3], modifiers: 6, drag: true, click_count: 5,
102
+ time: 4),
103
+ pointer(id: 10, type: TOUCH, action: UP)
104
+ ).inspect)
105
+ end
106
+
92
107
  end# TestPointerEvent
@@ -0,0 +1,36 @@
1
+ require_relative 'helper'
2
+
3
+
4
+ class TestReflex < Test::Unit::TestCase
5
+
6
+ R = Reflex
7
+
8
+ def test_all_keys_have_symbol()
9
+ R::KEYS.each do |key|
10
+ assert_not_nil R.get_key_symbol!(key), "no symbol for keycode 0x%X" % key
11
+ end
12
+ end
13
+
14
+ def test_all_keys_are_on_this_platform()
15
+ R::KEYS.each do |key|
16
+ assert_operator key, :>=, 0, "keycode 0x%X is not on this platform" % key
17
+ end
18
+ end
19
+
20
+ def test_unsided_modifiers_have_symbol()
21
+ omit 'no command or option key here' unless Xot.osx? || Xot.win32?
22
+ assert_equal :command, R.get_key_symbol!(R::KEY_COMMAND)
23
+ assert_equal :option, R.get_key_symbol!(R::KEY_OPTION)
24
+ end
25
+
26
+ def test_key_symbol_representative()
27
+ # Several keycodes share one symbol; the reverse lookup returns the
28
+ # first-defined keycode (KEY_SHIFT is listed before KEY_LSHIFT/KEY_RSHIFT).
29
+ assert_equal :shift, R.get_key_symbol!(R::KEY_SHIFT)
30
+ assert_equal :shift, R.get_key_symbol!(R::KEY_LSHIFT)
31
+ assert_equal :shift, R.get_key_symbol!(R::KEY_RSHIFT)
32
+
33
+ assert_equal R::KEY_SHIFT, R::KEYS.find {:shift == R.get_key_symbol!(_1)}
34
+ end
35
+
36
+ end# TestReflex
data/test/test_screen.rb CHANGED
@@ -3,12 +3,34 @@ require_relative 'helper'
3
3
 
4
4
  class TestScreen < Test::Unit::TestCase
5
5
 
6
+ include HasWindow
7
+
8
+ R = Reflex
9
+ S = R::Screen
10
+
6
11
  def screen()
7
- Reflex::Window.new.screen
12
+ window.screen
8
13
  end
9
14
 
10
15
  def test_initialize()
11
- assert_raise(Reflex::ReflexError) {Reflex::Screen.new}
16
+ assert_raise(R::ReflexError) {S.new}
17
+ end
18
+
19
+ def test_name()
20
+ S.all.each {assert_kind_of String, _1.name}
21
+ end
22
+
23
+ def test_pixel_density()
24
+ S.all.each {assert_operator _1.pixel_density, :>=, 1}
25
+ end
26
+
27
+ def test_all()
28
+ all = S.all
29
+ assert_true all.all? {_1.is_a? S}
30
+
31
+ omit 'no screen here' if all.empty?
32
+
33
+ assert_equal [0, 0], all.first.frame.position.to_a(2)
12
34
  end
13
35
 
14
36
  end# TestScreen
@@ -0,0 +1,140 @@
1
+ require_relative 'helper'
2
+
3
+
4
+ class TestSnapConstraint < Test::Unit::TestCase
5
+
6
+ include HasWindow
7
+
8
+ def view(x = 0, y = 0, w = 50, h = 50, **options, &block)
9
+ Reflex::View.new(
10
+ frame: [x, y, w, h],
11
+ shape: Reflex::RectShape.new(density: 1),
12
+ **options, &block)
13
+ end
14
+
15
+ def point(...)
16
+ Reflex::Point.new(...)
17
+ end
18
+
19
+ def setup_views(win = window)
20
+ v1 = view 100, 100, dynamic: true
21
+ v2 = view 200, 100, static: true
22
+ win&.add v1
23
+ win&.add v2
24
+ [v1, v2, win, win&.root]
25
+ end
26
+
27
+ def test_initial_state()
28
+ v1, v2, = setup_views
29
+
30
+ assert_equal v1, v1.snap(v2) .pins[0].view
31
+ assert_equal v2, v1.snap(v2) .pins[1].view
32
+ assert_nil v1.snap(v2) .angle
33
+ assert_equal 1..1, v1.snap(v2, angle: 1) .angle
34
+ assert_equal 2..3, v1.snap(v2, angle: 2..3) .angle
35
+ assert_nil v1.snap(v2) .motor
36
+ assert_equal 4, v1.snap(v2, motor: 4) .motor
37
+ assert_nil v1.snap(v2) .force
38
+ assert_equal 6, v1.snap(v2, force: 6) .force
39
+ assert_nil v1.snap(v2) .spring
40
+ assert_equal 5, v1.snap(v2, spring: 5) .spring
41
+ assert_in_delta 0.7, v1.snap(v2) .damping
42
+ assert_in_delta 0.1, v1.snap(v2, damping: 0.1).damping
43
+ assert_false v1.snap(v2) .collide?
44
+ assert_true v1.snap(v2) .active?
45
+ assert_false v1.snap(v2) .removed?
46
+ end
47
+
48
+ def test_snap_keeps_positions()
49
+ v1, v2, _, root = setup_views
50
+ v1.angle = 45
51
+
52
+ v1.snap v2 # nothing moves
53
+
54
+ 10.times {root.update_world}
55
+ assert_equal_point point(0), v1.linear_velocity
56
+ end
57
+
58
+ def test_snap_pulls_together()
59
+ v1, v2, _, root = setup_views
60
+
61
+ v1.pin(25, 25).snap v2.pin(25, 25), angle: 0, spring: 4
62
+
63
+ root.update_world
64
+ assert_operator v1.linear_velocity.x, :>, 0
65
+ end
66
+
67
+ def test_snap_to_world()
68
+ v1, _, _, root = setup_views
69
+ root.gravity 0, 900
70
+
71
+ c = v1.snap
72
+ assert_nil c.pins[1].view
73
+
74
+ 60.times {root.update_world}
75
+ assert_in_delta 100, v1.frame.y, 0.01 # hangs against gravity
76
+ end
77
+
78
+ def test_weld_fixes_angle()
79
+ v1, v2, _, root = setup_views
80
+
81
+ v1.snap v2, angle: 0 # welds and fixes the angle
82
+ v1.angular_velocity = 90
83
+
84
+ 10.times {root.update_world}
85
+ assert_in_delta 0, v1.angular_velocity
86
+ end
87
+
88
+ def test_angle()
89
+ v1, v2, = setup_views
90
+
91
+ c = v1.snap v2, angle: -30..90
92
+ assert_equal(-30..90, c.angle)
93
+
94
+ c.angle = 0
95
+ assert_equal 0..0, c.angle
96
+
97
+ c.angle = nil
98
+ assert_nil c.angle
99
+
100
+ assert_raise(ArgumentError) {c.angle = 'invalid'}
101
+ end
102
+
103
+ def test_motor()
104
+ v1, v2, _, root = setup_views
105
+
106
+ c = v1.snap v2, motor: 90
107
+ assert_equal 90, c.motor
108
+
109
+ 3.times {root.update_world}
110
+ assert_in_delta 90, v1.angular_velocity
111
+
112
+ c.motor = nil
113
+ assert_nil c.motor
114
+ end
115
+
116
+ def test_force()
117
+ v1, v2, = setup_views
118
+
119
+ c = v1.snap v2, motor: 90, force: 500
120
+ assert_equal 500, c.force
121
+
122
+ c.force = nil
123
+ assert_nil c.force
124
+
125
+ c.force = 100
126
+ assert_equal 100, c.force
127
+
128
+ assert_raise(ArgumentError) {c.force = -1}
129
+ end
130
+
131
+ def test_force_limits_the_motor()
132
+ v1, v2, _, root = setup_views
133
+
134
+ v1.snap v2, motor: 90, force: 0 # a powerless motor can not spin
135
+
136
+ 3.times {root.update_world}
137
+ assert_in_delta 0, v1.angular_velocity
138
+ end
139
+
140
+ end# TestSnapConstraint
@@ -0,0 +1,54 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative 'helper'
3
+
4
+
5
+ class TestTextEvent < Test::Unit::TestCase
6
+
7
+ PREEDIT, COMMIT = Reflex::TextEvent::PREEDIT, Reflex::TextEvent::COMMIT
8
+
9
+ def event(*args)
10
+ Reflex::TextEvent.new(*args)
11
+ end
12
+
13
+ def test_initialize()
14
+ assert_equal :preedit, event(PREEDIT, 'あ', 1, 2).action
15
+ assert_equal 'あ', event(PREEDIT, 'あ', 1, 2).text
16
+ assert_equal 1...3, event(PREEDIT, 'あ', 1, 2).selection
17
+ end
18
+
19
+ def test_dup()
20
+ assert_equal :preedit, event(PREEDIT, 'あ', 1, 2).dup.action
21
+ assert_equal 'あ', event(PREEDIT, 'あ', 1, 2).dup.text
22
+ assert_equal 1...3, event(PREEDIT, 'あ', 1, 2).dup.selection
23
+
24
+ e1 = event PREEDIT, 'あ', 1, 2
25
+ e2 = e1.dup
26
+ e1.block
27
+ e3 = e1.dup
28
+ assert_true e1.blocked?
29
+ assert_false e2.blocked?
30
+ assert_true e3.blocked?
31
+ end
32
+
33
+ def test_preedit_commit()
34
+ assert_true event(PREEDIT, 'あ', 1, 2).preedit?
35
+ assert_false event(PREEDIT, 'あ', 1, 2).commit?
36
+ assert_false event(COMMIT, 'あ', 1, 2).preedit?
37
+ assert_true event(COMMIT, 'あ', 1, 2).commit?
38
+ end
39
+
40
+ def test_text()
41
+ assert_equal '', event(PREEDIT, '', 1, 2).text
42
+ assert_equal '', event(PREEDIT, nil, 1, 2).text
43
+ assert_equal Encoding::UTF_8, event(PREEDIT, 'あいう', 1, 2).text.encoding
44
+ assert_equal 3, event(PREEDIT, 'あい😁', 1, 2).text.size
45
+ end
46
+
47
+ def test_selection()
48
+ assert_nil event(PREEDIT, 'あいうえ', -1, 0).selection
49
+ assert_equal 0...0, event(PREEDIT, 'あいうえ', 0, 0).selection
50
+ assert_equal 1...1, event(PREEDIT, 'あいうえ', 1, 0).selection
51
+ assert_equal 'いう', 'あいうえ'[event(PREEDIT, 'あいうえ', 1, 2).selection]
52
+ end
53
+
54
+ end# TestTextEvent
data/test/test_view.rb CHANGED
@@ -3,14 +3,12 @@ require_relative 'helper'
3
3
 
4
4
  class TestView < Test::Unit::TestCase
5
5
 
6
+ include HasWindow
7
+
6
8
  def view(*a, **k, &b)
7
9
  Reflex::View.new(*a, **k, &b)
8
10
  end
9
11
 
10
- def window(*a, **k, &b)
11
- Reflex::Window.new(*a, **k, &b)
12
- end
13
-
14
12
  def style(*a, **k, &b)
15
13
  Reflex::Style.new(*a, **k, &b)
16
14
  end
@@ -85,12 +83,36 @@ class TestView < Test::Unit::TestCase
85
83
  end
86
84
 
87
85
  def test_add_child()
86
+ view.tap do |v|
87
+ v.add view(name: :a)
88
+ v.add view(name: :b)
89
+ v.add view(name: :c), index: 1
90
+ assert_equal %w[a c b], v.children.map(&:name)
91
+ end
92
+
93
+ view.tap do |v|
94
+ v.add view(name: :a)
95
+ v.add view(name: :b), index: 0
96
+ v.add view(name: :c), index: v.children.to_a.size
97
+ assert_equal %w[b a c], v.children.map(&:name)
98
+ end
99
+
100
+ view.tap do |v|
101
+ v.add view(name: :a)
102
+ v.add view(name: :b), index: 99
103
+ v.add view(name: :c), index: -1
104
+ v.add view(name: :d), index: nil
105
+ assert_equal %w[a b c d], v.children.map(&:name)
106
+ end
107
+
108
+ view.tap do |v|
109
+ assert_nothing_raised {v.add_child view}
110
+ assert_raise(ArgumentError) {v.add_child v}
111
+ end
112
+
88
113
  assert_raise(ArgumentError) {view.add_child}
89
- assert_raise(TypeError) {view.add_child nil}
90
- assert_raise(TypeError) {view.add_child 1}
91
- v = view
92
- assert_raise(ArgumentError) {v.add_child v}
93
- assert_nothing_raised {v.add_child view}
114
+ assert_raise(TypeError) {view.add_child nil}
115
+ assert_raise(TypeError) {view.add_child 1}
94
116
  end
95
117
 
96
118
  def test_remove_child()
@@ -144,6 +166,18 @@ class TestView < Test::Unit::TestCase
144
166
  assert_not_includes v.find_styles(selector name: :N), s
145
167
  end
146
168
 
169
+ def test_find_styles()
170
+ v, s = view, style(name: :N1, tag: :T1)
171
+ s.add_tag :T2
172
+ v.add_style s
173
+
174
+ assert_includes v.find_styles(:N1), s
175
+ assert_includes v.find_styles(selector tag: :T1), s
176
+ assert_includes v.find_styles(selector tags: [:T1, :T2]), s
177
+ assert_empty v.find_styles(selector tags: [:T1, :X])
178
+ assert_empty v.find_styles(selector tag: :X)
179
+ end
180
+
147
181
  def test_shape()
148
182
  s = shape
149
183
  assert_equal 0, s.density
@@ -194,26 +228,80 @@ class TestView < Test::Unit::TestCase
194
228
  end
195
229
 
196
230
  def test_add_remove_shape()
197
- s = shape name: :S
198
- s.density = 1
199
- assert_equal 1, s.density
231
+ view.tap do |v|
232
+ s = shape name: :S
233
+ s.density = 1
234
+ assert_equal 1, s.density
235
+
236
+ assert_equal 0, v.shapes.to_a.size
237
+
238
+ v.add_shape s
239
+ assert_equal 1, v.shapes.to_a.size
240
+ assert_includes v.find_shapes(selector name: :S), s
241
+ assert_equal 1, v.find_shapes(selector name: :S).first.density
242
+
243
+ v.remove_shape s
244
+ assert_equal 0, v.shapes.to_a.size
245
+ assert_not_includes v.find_shapes(selector name: :S), s
246
+
247
+ v.add_shape s
248
+ assert_equal 1, v.shapes.to_a.size
249
+ v.clear_shapes
250
+ assert_equal 0, v.shapes.to_a.size
251
+ end
252
+
253
+ view.tap do |v|
254
+ v.add_shape shape(name: :a)
255
+ v.add_shape shape(name: :b)
256
+ v.add_shape shape(name: :c), index: 1
257
+ assert_equal %w[a c b], v.shapes.map(&:name)
258
+ end
259
+
260
+ view.tap do |v|
261
+ v.add_shape shape(name: :a)
262
+ v.add_shape shape(name: :b), index: 0
263
+ v.add_shape shape(name: :c), index: v.shapes.to_a.size
264
+ assert_equal %w[b a c], v.shapes.map(&:name)
265
+ end
266
+
267
+ view.tap do |v|
268
+ v.add_shape shape(name: :a)
269
+ v.add_shape shape(name: :b), index: 99
270
+ v.add_shape shape(name: :c), index: -1
271
+ v.add_shape shape(name: :d), index: nil
272
+ assert_equal %w[a b c d], v.shapes.map(&:name)
273
+ end
274
+ end
275
+
276
+ def test_find_shapes()
277
+ v, s = view, shape(name: :N1, tag: :T1)
278
+ s.add_tag :T2
279
+ v.add_shape s
200
280
 
201
- v = view
202
- assert_equal 0, v.shapes.to_a.size
281
+ assert_includes v.find_shapes(:N1), s
282
+ assert_includes v.find_shapes(selector tag: :T1), s
283
+ assert_includes v.find_shapes(selector tags: [:T1, :T2]), s
284
+ assert_empty v.find_shapes(selector tags: [:T1, :X])
285
+ assert_empty v.find_shapes(selector tag: :X)
286
+ end
203
287
 
204
- v.add_shape s
205
- assert_equal 1, v.shapes.to_a.size
206
- assert_includes v.find_shapes(selector name: :S), s
207
- assert_equal 1, v.find_shapes(selector name: :S).first.density
288
+ def test_find_constraints()
289
+ win = window
290
+ v1 = view frame: [100, 100, 50, 50], shape: shape(density: 1), dynamic: true
291
+ v2 = view frame: [200, 100, 50, 50], shape: shape(density: 1), static: true
292
+ win.add v1
293
+ win.add v2
208
294
 
209
- v.remove_shape s
210
- assert_equal 0, v.shapes.to_a.size
211
- assert_not_includes v.find_shapes(selector name: :S), s
295
+ c = v1.link v2, name: :N1, tag: :T1
296
+ c.add_tag :T2
212
297
 
213
- v.add_shape s
214
- assert_equal 1, v.shapes.to_a.size
215
- v.clear_shapes
216
- assert_equal 0, v.shapes.to_a.size
298
+ [v1, v2].each do |v|
299
+ assert_includes v.find_constraints(:N1), c
300
+ assert_includes v.find_constraints(selector tag: :T1), c
301
+ assert_includes v.find_constraints(selector tags: [:T1, :T2]), c
302
+ assert_empty v.find_constraints(selector tags: [:T2, :X])
303
+ assert_empty v.find_constraints(selector tags: [:X])
304
+ end
217
305
  end
218
306
 
219
307
  def test_name()
@@ -396,6 +484,45 @@ class TestView < Test::Unit::TestCase
396
484
  v.capture += []; assert_equal [], v.capture
397
485
  end
398
486
 
487
+ def test_accepts_text_input()
488
+ assert_false view .accepts_text_input?
489
+ assert_true view.tap {_1.text_input = true} .accepts_text_input?
490
+ assert_true view.tap {_1.text_input = true; _1.on(:text) {}}.accepts_text_input?
491
+ assert_false view.tap {_1.text_input = false} .accepts_text_input?
492
+ assert_false view.tap {_1.text_input = false; _1.on(:text) {}}.accepts_text_input?
493
+ assert_false view.tap {_1.text_input = nil} .accepts_text_input?
494
+ assert_true view.tap {_1.text_input = nil; _1.on(:text) {}}.accepts_text_input?
495
+
496
+ new_class = -> hook = nil {
497
+ Class.new(Reflex::View) {define_method(hook) {|*|} if hook}
498
+ }
499
+
500
+ assert_true new_class.call(:on_text).new .accepts_text_input?
501
+ assert_false new_class.call(:on_text).new.hide .accepts_text_input?
502
+ assert_true new_class.call(:on_text).new.hide.show.accepts_text_input?
503
+
504
+ %w[on_text on_text_preedit on_text_commit].each do |hook|
505
+ on_less = hook.sub 'on_', ''
506
+ assert_true new_class.call(hook).new .accepts_text_input?, hook
507
+ assert_true view.tap {_1.on(on_less) {|*|}}.accepts_text_input?, hook
508
+ assert_true view.tap {_1.before(hook) {|*|}}.accepts_text_input?, hook
509
+ assert_true view.tap {_1.after(hook) {|*|}}.accepts_text_input?, hook
510
+ end
511
+ end
512
+
513
+ def test_text_input()
514
+ v = view; assert_nil v.text_input
515
+ v.text_input = true; assert_true v.text_input
516
+ v.text_input = false; assert_false v.text_input
517
+ v.text_input = nil; assert_nil v.text_input
518
+ end
519
+
520
+ def test_text_input_bounds()
521
+ v = view
522
+ v.frame = [10, 20, 30, 40]
523
+ assert_equal Reflex::Bounds.new(0, 0, 30, 40), v.text_input_bounds
524
+ end
525
+
399
526
  def test_capturing()
400
527
  v, w = view, window
401
528
  w.add v
@@ -0,0 +1,125 @@
1
+ require_relative 'helper'
2
+
3
+
4
+ class TestWheelConstraint < Test::Unit::TestCase
5
+
6
+ include HasWindow
7
+
8
+ def view(x = 0, y = 0, w = 50, h = 50, **options, &block)
9
+ Reflex::View.new(
10
+ frame: [x, y, w, h],
11
+ shape: Reflex::RectShape.new(density: 1),
12
+ **options, &block)
13
+ end
14
+
15
+ def point(...)
16
+ Reflex::Point.new(...)
17
+ end
18
+
19
+ def setup_views(win = window)
20
+ v1 = view 100, 100, dynamic: true
21
+ v2 = view 200, 100, static: true
22
+ win&.add v1
23
+ win&.add v2
24
+ [v1, v2, win, win&.root]
25
+ end
26
+
27
+ def test_initial_state()
28
+ v1, v2, = setup_views
29
+
30
+ assert_equal v1, v1.wheel(v2) .pins[0].view
31
+ assert_equal v2, v1.wheel(v2) .pins[1].view
32
+ assert_equal_point point(0, 1), v1.wheel(v2) .axis
33
+ assert_equal_point point(1, 0), v1.wheel(v2, axis: [1, 0]).axis
34
+ assert_nil v1.wheel(v2) .range
35
+ assert_equal 2..3, v1.wheel(v2, range: 2..3) .range
36
+ assert_nil v1.wheel(v2) .motor
37
+ assert_equal 4, v1.wheel(v2, motor: 4) .motor
38
+ assert_nil v1.wheel(v2) .force
39
+ assert_equal 6, v1.wheel(v2, force: 6) .force
40
+ assert_nil v1.wheel(v2) .spring
41
+ assert_equal 5, v1.wheel(v2, spring: 5) .spring
42
+ assert_in_delta 0.7, v1.wheel(v2) .damping
43
+ assert_false v1.wheel(v2) .collide?
44
+ assert_true v1.wheel(v2) .active?
45
+ assert_false v1.wheel(v2) .removed?
46
+ end
47
+
48
+ def test_rotation_is_free()
49
+ win = window
50
+ wheeled = view 100, 100, dynamic: true
51
+ railed = view 300, 100, dynamic: true
52
+ anchor = view 200, 100, static: true
53
+ [wheeled, railed, anchor].each {|v| win.add v}
54
+
55
+ wheeled.wheel anchor, axis: [1, 0] # a wheel leaves the rotation free
56
+ railed .link anchor, axis: [1, 0] # a rail locks it
57
+
58
+ wheeled.angular_velocity = 90
59
+ railed .angular_velocity = 90
60
+ 3.times {win.root.update_world}
61
+
62
+ assert_in_delta 0, railed.angular_velocity
63
+ assert_operator wheeled.angular_velocity.abs, :>, railed.angular_velocity.abs
64
+ end
65
+
66
+ def test_motor_spins_the_wheel()
67
+ v1, v2, _, root = setup_views
68
+
69
+ c = v1.wheel v2, axis: [1, 0], motor: 90
70
+ assert_equal 90, c.motor
71
+
72
+ root.update_world
73
+ assert_operator v1.angular_velocity, :>, 0
74
+
75
+ c.motor = nil
76
+ assert_nil c.motor
77
+ end
78
+
79
+ def test_force()
80
+ v1, v2, = setup_views
81
+
82
+ c = v1.wheel v2, motor: 90, force: 500
83
+ assert_equal 500, c.force
84
+
85
+ c.force = nil
86
+ assert_nil c.force
87
+
88
+ c.force = 100
89
+ assert_equal 100, c.force
90
+
91
+ assert_raise(ArgumentError) {c.force = -1}
92
+ end
93
+
94
+ def test_slides_along_axis()
95
+ v1, v2, _, root = setup_views
96
+ root.gravity 900, 900
97
+
98
+ c = v1.wheel v2, axis: [1, 0]
99
+ assert_equal_point point(1, 0), c.axis
100
+
101
+ root.update_world
102
+ assert_operator v1.linear_velocity.x, :>, 0 # suspension slides along the axis
103
+ assert_in_delta 0, v1.linear_velocity.y
104
+
105
+ c.axis = [0, 1]
106
+ assert_equal_point point(0, 1), c.axis
107
+ end
108
+
109
+ def test_range()
110
+ v1, v2, _, root = setup_views
111
+ root.gravity 0, 900
112
+
113
+ c = v1.pin(25, 25).wheel v2.pin(25, 25), axis: [0, 1], range: 100..200
114
+ assert_equal 100..200, c.range
115
+
116
+ 60.times {root.update_world}
117
+ assert_equal_point point(200, 300), v1.pos
118
+
119
+ c.range = nil
120
+ assert_nil c.range
121
+
122
+ assert_raise(ArgumentError) {c.range = 'invalid'}
123
+ end
124
+
125
+ end# TestWheelConstraint