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
@@ -0,0 +1,156 @@
1
+ %w[xot rays reflex]
2
+ .map {|s| File.expand_path "../../#{s}/lib", __dir__}
3
+ .each {|s| $:.unshift s if !$:.include?(s) && File.directory?(s)}
4
+
5
+ require 'reflex'
6
+
7
+
8
+ # How a window can look and behave: which parts of the titlebar it shows,
9
+ # whether it draws a shadow, whether the alpha you draw with lets the desktop
10
+ # show through, and whether it can be closed, minimized or resized.
11
+ #
12
+ # Hiding a part of the titlebar takes its function away too. With the
13
+ # background hidden the window can no longer be dragged or zoomed by the strip
14
+ # the titlebar sat on, since the window itself draws there and gets the mouse
15
+ # events.
16
+ #
17
+ # The two windows differ only in what they draw behind the circles, so a
18
+ # see-through background and a translucent one can be compared. On macOS the
19
+ # shadow of a see-through window is made from what was drawn, so it follows
20
+ # the circles. Windows draws it around the frame instead.
21
+ #
22
+ # A window that lets the pointer through gets no pointer events at all. It
23
+ # cannot be clicked, dragged or activated, and the click reaches whatever sits
24
+ # behind it. Drag the two windows over each other to see where a click lands,
25
+ # the counter says which one got it. Only one window at a time can do it, so
26
+ # there is always another one left to click on.
27
+ #
28
+ # Pressing 9 again keeps the pointer going through only where the window
29
+ # drew little: with pointer_through_alpha at 0.5, the see-through window takes
30
+ # a click on its circles and passes one on its empty background, and the
31
+ # translucent window passes clicks through its 0.3 background too. The
32
+ # titlebar always takes the pointer. A third press turns it off.
33
+ #
34
+ # An unlisted window is still there on screen, but it leaves the window
35
+ # overviews: Mission Control on macOS, the taskbar and alt-tab on Windows.
36
+ # Toggle it and open the overview to watch the window drop out of the list
37
+ # while staying right where it is.
38
+ #
39
+ # Not every platform can do all of this, and the ones that cannot say so.
40
+ #
41
+ # 1: titlebar buttons, 2: titlebar background, 3: both
42
+ # 4: shadow, 5: transparent
43
+ # 6: closable, 7: minimizable, 8: resizable
44
+ # 9: pointer through, 0: unlisted
45
+ # ESC: quit
46
+ class StyledWindow < Reflex::Window
47
+
48
+ PARTS = [:buttons, :background]
49
+
50
+ @@message = nil
51
+
52
+ def initialize (title, x, alpha)
53
+ super title: title, frame: [x, 100, 360, 360], transparent: true
54
+ @alpha = alpha
55
+ @t = 0.0
56
+ @clicks = 0
57
+ painter.font = Reflex::Font.new nil, 16
58
+ end
59
+
60
+ def on_draw (e)
61
+ @t += 0.03
62
+ p = e.painter
63
+
64
+ # the alpha here is what lets the desktop show through
65
+ p.background 0, 0, 0, @alpha
66
+
67
+ 8.times do |i|
68
+ a = @t + i * Math::PI / 4
69
+ x = 180 + Math.cos(a) * 100
70
+ y = 180 + Math.sin(a) * 100
71
+ p.fill((Math.sin(@t + i) + 1) / 2, 0.6, 1)
72
+ p.ellipse x - 20, y - 20, 40, 40
73
+ end
74
+
75
+ # something that stays put, to aim a click at
76
+ p.fill 1, 0.8, 0.2
77
+ p.ellipse 150, 150, 60, 60
78
+
79
+ p.fill 1
80
+ p.text "titlebar: #{titlebar.inspect}", 10, 10
81
+ p.text "shadow: #{shadow?}, transparent: #{transparent?}, " \
82
+ "unlisted: #{unlisted?}", 10, 30
83
+ p.text "closable: #{closable?}, minimizable: #{minimizable?}, " \
84
+ "resizable: #{resizable?}", 10, 50
85
+ p.text "pointer through: #{pointer_through_state}, clicks: #{@clicks}", 10, 70
86
+ p.text "#{e.fps.to_i} FPS", 10, 90
87
+ p.text '1: buttons, 2: background, 3: both', 10, 110
88
+ p.text '4: shadow, 5: transparent', 10, 130
89
+ p.text '6: closable, 7: minimizable, 8: resizable', 10, 150
90
+ p.text '9: pointer through, 0: unlisted, ESC: quit', 10, 170
91
+
92
+ if @@message
93
+ p.fill 1, 0.4, 0.4
94
+ p.text @@message, 10, 190
95
+ end
96
+ end
97
+
98
+ def on_update (e) = redraw
99
+
100
+ def on_pointer_down (e)
101
+ @clicks += 1
102
+ end
103
+
104
+ def on_key_down (e)
105
+ case e.chars
106
+ when '1' then change {|w| w.toggle_titlebar :buttons}
107
+ when '2' then change {|w| w.toggle_titlebar :background}
108
+ when '3' then change {|w| w.titlebar = w.titlebar.empty? ? PARTS : []}
109
+ when '4' then change {|w| w.shadow = !w.shadow?}
110
+ when '5' then change {|w| w.transparent = !w.transparent?}
111
+ when '6' then change {|w| w.closable = !w.closable?}
112
+ when '7' then change {|w| w.minimizable = !w.minimizable?}
113
+ when '8' then change {|w| w.resizable = !w.resizable?}
114
+ when '9' then change {|w| w.cycle_pointer_through w.equal?(self)}
115
+ when '0' then change {|w| w.unlisted = !w.unlisted?}
116
+ end
117
+ Reflex.quit if e.key == :escape
118
+ end
119
+
120
+ def toggle_titlebar (part)
121
+ parts = titlebar
122
+ self.titlebar = parts.include?(part) ? parts - [part] : parts + [part]
123
+ end
124
+
125
+ # off -> everything through -> only the pixels at alpha 0.5 or less -> off
126
+ def cycle_pointer_through (mine)
127
+ if !mine || (pointer_through? && pointer_through_alpha < 1)
128
+ self.pointer_through = false
129
+ elsif !pointer_through?
130
+ self.pointer_through = true
131
+ self.pointer_through_alpha = 1
132
+ else
133
+ self.pointer_through_alpha = 0.5
134
+ end
135
+ end
136
+
137
+ def pointer_through_state ()
138
+ return 'false' if !pointer_through?
139
+ return 'all' if pointer_through_alpha >= 1
140
+ return "alpha <= #{pointer_through_alpha}"
141
+ end
142
+
143
+ def change (&block)
144
+ @@message = nil
145
+ Reflex::Application.instance.windows.each(&block)
146
+ rescue ArgumentError, NotImplementedError => e
147
+ @@message = e.message
148
+ end
149
+
150
+ end# StyledWindow
151
+
152
+
153
+ Reflex.start do
154
+ StyledWindow.new('see-through', 100, 0.0).show
155
+ StyledWindow.new('translucent', 500, 0.3).show
156
+ end
data/src/application.cpp CHANGED
@@ -4,8 +4,8 @@
4
4
  #include "reflex/exception.h"
5
5
  #include "reflex/debug.h"
6
6
  #include "window.h"
7
- #include "gamepad.h"
8
7
  #include "midi.h"
8
+ #include "gamepad.h"
9
9
 
10
10
 
11
11
  namespace Reflex
@@ -20,49 +20,149 @@ namespace Reflex
20
20
  }// global
21
21
 
22
22
 
23
+ bool
24
+ Application_should_quit (Application* app)
25
+ {
26
+ if (!app || !app->self->started)
27
+ return false;
28
+
29
+ if (app->background_menu())
30
+ return false;
31
+
32
+ if (app->background() && app->menu())
33
+ return false;
34
+
35
+ return Reflex::Window_all().empty();
36
+ }
37
+
23
38
  void
24
- Application_call_start (Application* app, Event* e)
39
+ Application_cleanup (Application* app)
25
40
  {
26
- app->on_start(e);
41
+ MIDI_fin(app);
42
+ Gamepad_fin(app);
43
+ }
44
+
45
+ void
46
+ Application_call_quit (Application* app)
47
+ {
48
+ Application_guard([&]()
49
+ {
50
+ app->quit();
51
+ });
52
+ }
27
53
 
28
- Gamepad_init(app);
29
- MIDI_init(app);
54
+ void
55
+ Application_call_start_event (Application* app, Event* e)
56
+ {
57
+ if (app->self->started) return;
58
+
59
+ Application_guard([&]()
60
+ {
61
+ app->on_start(e);
62
+ app->self->started = true;
63
+ });
30
64
  }
31
65
 
32
66
  static void
33
67
  close_all_windows (Application* app)
34
68
  {
35
- for (auto it = app->window_begin(), end = app->window_end(); it != end; ++it)
36
- (*it)->close(true);
69
+ for (auto& window : Application::WindowList(app->window_begin(), app->window_end()))
70
+ window->close(true);
37
71
  }
38
72
 
39
73
  void
40
- Application_call_quit (Application* app, Event* e)
74
+ Application_call_quit_event (Application* app, Event* e)
41
75
  {
42
76
  if (app->self->quitting) return;
43
77
 
44
- app->on_quit(e);
45
- if (e->is_blocked()) return;
78
+ Application_guard([&]()
79
+ {
80
+ app->on_quit(e);
81
+ if (e->is_blocked()) return;
46
82
 
47
- app->self->quitting = true;
83
+ app->self->quitting = true;
48
84
 
49
- close_all_windows(app);
50
- MIDI_fin(app);
51
- Gamepad_fin(app);
85
+ close_all_windows(app);
86
+ });
52
87
  }
53
88
 
54
89
  void
55
- Application_call_device_connect (Application* app, Device* device)
90
+ Application_call_device_connect_event (Application* app, Device* device)
91
+ {
92
+ Application_guard([&]()
93
+ {
94
+ DeviceEvent e(device);
95
+ app->on_device_connect(&e);
96
+ });
97
+ }
98
+
99
+ void
100
+ Application_call_device_disconnect_event (Application* app, Device* device)
101
+ {
102
+ Application_guard([&]()
103
+ {
104
+ DeviceEvent e(device);
105
+ app->on_device_disconnect(&e);
106
+ });
107
+ }
108
+
109
+ void
110
+ Application_call_motion_event (Application* app, MotionEvent* e)
111
+ {
112
+ Application_guard([&]()
113
+ {
114
+ app->on_motion(e);
115
+ });
116
+ }
117
+
118
+ void
119
+ Application_call_preference_event (Application* app, Event* e)
120
+ {
121
+ Application_guard([&]()
122
+ {
123
+ app->on_preference(e);
124
+ });
125
+ }
126
+
127
+ void
128
+ Application_call_about_event (Application* app, Event* e)
129
+ {
130
+ Application_guard([&]()
131
+ {
132
+ app->on_about(e);
133
+ });
134
+ }
135
+
136
+ bool
137
+ Application_has_exception ()
56
138
  {
57
- DeviceEvent e(device);
58
- app->on_device_connect(&e);
139
+ Application* app = global::instance;
140
+ return app && app->self->exception;
141
+ }
142
+
143
+ bool
144
+ Application_keep_exception (std::exception_ptr exception)
145
+ {
146
+ Application* app = global::instance;
147
+ if (!app || !app->self->running)
148
+ return false;
149
+
150
+ // the first one is the cause, so keep it and drop the rest
151
+ if (!app->self->exception)
152
+ app->self->exception = exception;
153
+
154
+ Application_stop(app);
155
+ return true;
59
156
  }
60
157
 
61
158
  void
62
- Application_call_device_disconnect (Application* app, Device* device)
159
+ Application_throw_exception (Application* app)
63
160
  {
64
- DeviceEvent e(device);
65
- app->on_device_disconnect(&e);
161
+ std::exception_ptr exception = app->self->exception;
162
+ if (!exception) return;
163
+
164
+ app->self->exception = NULL;
165
+ std::rethrow_exception(exception);
66
166
  }
67
167
 
68
168
  Application*
@@ -72,6 +172,12 @@ namespace Reflex
72
172
  }
73
173
 
74
174
 
175
+ Application::Data::Data ()
176
+ : name(Application_get_default_name())
177
+ {
178
+ }
179
+
180
+
75
181
  Application::Application ()
76
182
  : self(Application_create_data())
77
183
  {
@@ -101,6 +207,60 @@ namespace Reflex
101
207
  return self->name.c_str();
102
208
  }
103
209
 
210
+ void
211
+ Application::set_menu (Menu* menu)
212
+ {
213
+ self->menu = menu;
214
+ Application_set_menu(this, menu);
215
+ }
216
+
217
+ Menu*
218
+ Application::menu ()
219
+ {
220
+ return self->menu.get();
221
+ }
222
+
223
+ const Menu*
224
+ Application::menu () const
225
+ {
226
+ return const_cast<Application*>(this)->menu();
227
+ }
228
+
229
+ void
230
+ Application::set_background (bool state)
231
+ {
232
+ if (state == self->background)
233
+ return;
234
+
235
+ self->background = state;
236
+ Application_set_background(this, state);
237
+ }
238
+
239
+ bool
240
+ Application::background () const
241
+ {
242
+ return self->background;
243
+ }
244
+
245
+ void
246
+ Application::set_background_menu (Menu* menu)
247
+ {
248
+ self->background_menu = menu;
249
+ Application_set_background_menu(this, menu);
250
+ }
251
+
252
+ Menu*
253
+ Application::background_menu ()
254
+ {
255
+ return self->background_menu.get();
256
+ }
257
+
258
+ const Menu*
259
+ Application::background_menu () const
260
+ {
261
+ return const_cast<Application*>(this)->background_menu();
262
+ }
263
+
104
264
  Application::window_iterator
105
265
  Application::window_begin ()
106
266
  {
data/src/application.h CHANGED
@@ -4,7 +4,11 @@
4
4
  #define __REFLEX_SRC_APPLICATION_H__
5
5
 
6
6
 
7
+ #include <exception>
8
+ #include <type_traits>
9
+ #include <utility>
7
10
  #include "reflex/application.h"
11
+ #include "reflex/menu.h"
8
12
 
9
13
 
10
14
  namespace Reflex
@@ -16,21 +20,107 @@ namespace Reflex
16
20
 
17
21
  String name;
18
22
 
19
- bool quitting = false;
23
+ Menu::Ref menu, background_menu;
24
+
25
+ bool background = false;
26
+
27
+ bool started = false;
28
+
29
+ bool running = false;
30
+
31
+ bool quitting = false;
32
+
33
+ std::exception_ptr exception;
34
+
35
+ Data ();
20
36
 
21
37
  };// Application::Data
22
38
 
23
39
 
40
+ bool Application_should_quit (Application* app);
41
+
42
+ void Application_cleanup (Application* app);
43
+
44
+ void Application_call_quit (Application* app);
45
+
46
+ void Application_call_start_event (Application* app, Event* e);
47
+
48
+ void Application_call_quit_event (Application* app, Event* e);
49
+
50
+ void Application_call_device_connect_event (Application* app, Device* device);
51
+
52
+ void Application_call_device_disconnect_event (Application* app, Device* device);
53
+
54
+ void Application_call_motion_event (Application* app, MotionEvent* e);
55
+
56
+ void Application_call_preference_event (Application* app, Event* e);
57
+
58
+ void Application_call_about_event (Application* app, Event* e);
59
+
60
+ bool Application_has_exception ();
61
+
62
+ bool Application_keep_exception (std::exception_ptr exception);
63
+
64
+ void Application_throw_exception (Application* app);
65
+
66
+
24
67
  Application::Data* Application_create_data ();
25
68
 
69
+ String Application_get_default_name ();
70
+
71
+ void Application_stop (Application* app);
26
72
 
27
- void Application_call_start (Application* app, Event* e);
73
+ void Application_set_menu (Application* app, Menu* menu);
28
74
 
29
- void Application_call_quit (Application* app, Event* e);
75
+ void Application_set_background (Application* app, bool state);
30
76
 
31
- void Application_call_device_connect (Application* app, Device* device);
77
+ void Application_set_background_menu (Application* app, Menu* menu);
32
78
 
33
- void Application_call_device_disconnect (Application* app, Device* device);
79
+
80
+ template <typename FUN, typename RET>
81
+ inline RET
82
+ Application_guard (FUN&& fun, RET fallback)
83
+ {
84
+ // Runs 'fun' so that no C++ exception gets out of it while start()
85
+ // runs the event loop. The exception is kept, the loop is stopped,
86
+ // and start() throws it again after the loop returns. Once one is
87
+ // kept, later calls return 'fallback' without running 'fun'.
88
+ //
89
+ // Where to use it:
90
+ // 1. Platform code never calls anything that reaches on_* by itself,
91
+ // not even close() or quit(). It goes through a Foo_call_* function
92
+ // in src/, and those are the places to guard.
93
+ // 2. Guard the body of Foo_call_*. The argument checks stay outside,
94
+ // a bug inside reflex should fail right there.
95
+ // 3. Two exceptions: the window procedures on windows, since an
96
+ // exception can not cross the kernel callback boundary, and the
97
+ // drawing calls of each platform loop, since rays can throw there.
98
+
99
+ if (Application_has_exception())
100
+ return fallback;
101
+
102
+ try
103
+ {
104
+ return fun();
105
+ }
106
+ catch (...)
107
+ {
108
+ if (!Application_keep_exception(std::current_exception()))
109
+ throw;
110
+ }
111
+ return fallback;
112
+ }
113
+
114
+ template <typename FUN>
115
+ inline auto
116
+ Application_guard (FUN&& fun) -> decltype(fun())
117
+ {
118
+ typedef decltype(fun()) RET;
119
+ if constexpr (std::is_void<RET>::value)
120
+ Application_guard([&]() {fun(); return 0;}, 0);
121
+ else
122
+ return Application_guard(std::forward<FUN>(fun), RET());
123
+ }
34
124
 
35
125
 
36
126
  }// Reflex
data/src/clipboard.cpp ADDED
@@ -0,0 +1,81 @@
1
+ #include "reflex/clipboard.h"
2
+
3
+
4
+ #include <map>
5
+ #include "reflex/exception.h"
6
+
7
+
8
+ namespace Reflex
9
+ {
10
+
11
+
12
+ static const char* TEXT_TYPE = "text/plain";
13
+
14
+
15
+ struct Clipboard::Data
16
+ {
17
+
18
+ std::map<String, String> types;
19
+
20
+ };// Clipboard::Data
21
+
22
+
23
+ Clipboard::Clipboard (const char* text)
24
+ {
25
+ if (text) set_text(text);
26
+ }
27
+
28
+ Clipboard::~Clipboard ()
29
+ {
30
+ }
31
+
32
+ void
33
+ Clipboard::set_text (const char* text)
34
+ {
35
+ if (!text)
36
+ argument_error(__FILE__, __LINE__);
37
+
38
+ self->types[TEXT_TYPE] = text;
39
+ }
40
+
41
+ const char*
42
+ Clipboard::text () const
43
+ {
44
+ auto it = self->types.find(TEXT_TYPE);
45
+ if (it == self->types.end())
46
+ return NULL;
47
+
48
+ return it->second.c_str();
49
+ }
50
+
51
+ void
52
+ Clipboard::set_image (const Image& image)
53
+ {
54
+ not_implemented_error(__FILE__, __LINE__);
55
+ }
56
+
57
+ const Image*
58
+ Clipboard::image () const
59
+ {
60
+ return NULL;
61
+ }
62
+
63
+ void
64
+ Clipboard::clear ()
65
+ {
66
+ self->types.clear();
67
+ }
68
+
69
+ Clipboard::operator bool () const
70
+ {
71
+ return true;
72
+ }
73
+
74
+ bool
75
+ Clipboard::operator ! () const
76
+ {
77
+ return !operator bool();
78
+ }
79
+
80
+
81
+ }// Reflex