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
data/src/menu.h ADDED
@@ -0,0 +1,81 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __REFLEX_SRC_MENU_H__
4
+ #define __REFLEX_SRC_MENU_H__
5
+
6
+
7
+ #include <memory>
8
+ #include <rays/image.h>
9
+ #include "reflex/menu.h"
10
+ #include "selector.h"
11
+
12
+
13
+ namespace Reflex
14
+ {
15
+
16
+
17
+ struct Menu::Data
18
+ {
19
+
20
+ Xot::WeakRef<Menu> parent;
21
+
22
+ String label;
23
+
24
+ Image image;
25
+
26
+ KeyCode key = KEY_NONE;
27
+
28
+ uint modifiers = MOD_NONE;
29
+
30
+ bool enabled = true;
31
+
32
+ bool checked = false;
33
+
34
+ bool separator = false;
35
+
36
+ std::unique_ptr<ChildList> pchildren;
37
+
38
+ SelectorPtr pselector;
39
+
40
+ Data ();
41
+
42
+ virtual ~Data ();
43
+
44
+ ChildList* children ()
45
+ {
46
+ if (!pchildren) pchildren.reset(new ChildList);
47
+ return pchildren.get();
48
+ }
49
+
50
+ };// Menu::Data
51
+
52
+
53
+ Menu::Data* Menu_create_data ();
54
+
55
+ void Menu_validate_shortcut_modifiers (uint modifiers);
56
+
57
+ void Menu_update (Menu* menu);
58
+
59
+ void Menu_popup (Menu* menu, View* view, coord x, coord y);
60
+
61
+ void Menu_child_added (Menu* parent, Menu* child, int index);
62
+
63
+ void Menu_child_removed (Menu* parent, Menu* child);
64
+
65
+ void Menu_cancel_active_pointers_for_popup (View* view);
66
+
67
+ void Menu_call_click_event (Menu* menu, Event* event);
68
+
69
+ void Menu_call_show_event (Menu* menu, Event* event);
70
+
71
+ void Menu_call_hide_event (Menu* menu, Event* event);
72
+
73
+ void Menu_call_open_submenu_event (Menu* menu, Event* event);
74
+
75
+ void Menu_call_close_submenu_event (Menu* menu, Event* event);
76
+
77
+
78
+ }// Reflex
79
+
80
+
81
+ #endif//EOH
data/src/midi.cpp CHANGED
@@ -40,23 +40,24 @@ namespace Reflex
40
40
 
41
41
  enum Type {UNKNOWN, MESSAGE, ERROR};
42
42
 
43
- Type type = UNKNOWN;
43
+ Type type = UNKNOWN;
44
44
 
45
- MIDI::Ref midi;
45
+ MIDI* midi = NULL;
46
46
 
47
47
  Message message;
48
48
 
49
49
  RtMidiError error;
50
50
 
51
- double time = 0;
51
+ double time = 0, delta_time = 0;
52
52
 
53
53
  RtMidiEvent ()
54
54
  : error("")
55
55
  {
56
56
  }
57
57
 
58
- RtMidiEvent (MIDI* midi, const Message& message, double time)
59
- : type(MESSAGE), midi(midi), message(message), error(""), time(time)
58
+ RtMidiEvent (MIDI* midi, const Message& message, double time, double delta_time)
59
+ : type(MESSAGE), midi(midi), message(message), error(""),
60
+ time(time), delta_time(delta_time)
60
61
  {
61
62
  }
62
63
 
@@ -104,13 +105,34 @@ namespace Reflex
104
105
 
105
106
  call_midi_event(midi, event);
106
107
 
107
- Window* win = Window_get_active();
108
- if (!win) return;
108
+ for (auto& win : Window_all())
109
+ {
110
+ MIDIEvent e = event.dup();
111
+ Window_call_midi_event(win, &e);
112
+ }
113
+ }
114
+
115
+ static MIDI::List midis;
109
116
 
110
- Window_call_midi_event(win, &event);
117
+ static MIDI::Ref
118
+ find_midi (MIDI* midi)
119
+ {
120
+ auto it = std::find_if(
121
+ midis.begin(), midis.end(),
122
+ [=](const MIDI::Ref& ref) {return ref.get() == midi;});
123
+ return it == midis.end() ? MIDI::Ref() : *it;
111
124
  }
112
125
 
113
- static Queue<RtMidiEvent> queue;
126
+ static double
127
+ apply_time (MIDI* midi, const RtMidiEvent& event)
128
+ {
129
+ MIDI::Data* self = midi->self.get();
130
+ if (self->time == 0)
131
+ self->time = event.time;
132
+ else
133
+ self->time += event.delta_time;
134
+ return self->time;
135
+ }
114
136
 
115
137
  static void
116
138
  dispatch_midi_event (RtMidiEvent* event)
@@ -118,8 +140,12 @@ namespace Reflex
118
140
  switch (event->type)
119
141
  {
120
142
  case RtMidiEvent::MESSAGE:
121
- call_events(event->midi, &event->message[0], event->time);
143
+ {
144
+ MIDI::Ref midi = find_midi(event->midi);
145
+ if (midi)
146
+ call_events(midi, event->message.data(), apply_time(midi, *event));
122
147
  break;
148
+ }
123
149
 
124
150
  case RtMidiEvent::ERROR:
125
151
  system_error(
@@ -132,6 +158,8 @@ namespace Reflex
132
158
  }
133
159
  }
134
160
 
161
+ static Queue<RtMidiEvent> queue;
162
+
135
163
  static void
136
164
  process_midi_events ()
137
165
  {
@@ -143,23 +171,13 @@ namespace Reflex
143
171
  static void
144
172
  event_callback (double dt, RtMidiEvent::Message* message, void* data)
145
173
  {
146
- MIDI* midi = (MIDI*) data;
147
- MIDI::Data* self = midi->self.get();
148
-
149
- if (self->time == 0)
150
- self->time = Xot::time();
151
- else
152
- self->time += dt;
153
-
154
- queue.push(RtMidiEvent(midi, *message, self->time));
174
+ queue.push(RtMidiEvent((MIDI*) data, *message, Xot::time(), dt));
155
175
  }
156
176
 
157
177
  static void
158
178
  error_callback (RtMidiError::Type type, const std::string& message, void* data)
159
179
  {
160
- MIDI* midi = (MIDI*) data;
161
-
162
- queue.push(RtMidiEvent(midi, RtMidiError(message, type)));
180
+ queue.push(RtMidiEvent((MIDI*) data, RtMidiError(message, type)));
163
181
  }
164
182
 
165
183
  static MIDI_CreateFun midi_create_fun = NULL;
@@ -191,13 +209,11 @@ namespace Reflex
191
209
  self->name = name;
192
210
  }
193
211
 
194
- static MIDI::List midis;
195
-
196
212
  static void
197
213
  add_midi (MIDI* midi)
198
214
  {
199
215
  midis.emplace_back(midi);
200
- Application_call_device_connect(app(), midi);
216
+ Application_call_device_connect_event(app(), midi);
201
217
  }
202
218
 
203
219
  static void
@@ -208,7 +224,7 @@ namespace Reflex
208
224
  if (it == midis.end()) return;
209
225
 
210
226
  midis.erase(it);
211
- Application_call_device_disconnect(app(), ref);
227
+ Application_call_device_disconnect_event(app(), ref);
212
228
  }
213
229
 
214
230
 
@@ -227,7 +243,7 @@ namespace Reflex
227
243
  ~MIDIDeviceManager ()
228
244
  {
229
245
  for (auto& midi : midis)
230
- Application_call_device_disconnect(app(), midi);
246
+ Application_call_device_disconnect_event(app(), midi);
231
247
  }
232
248
 
233
249
  void update ()
@@ -308,8 +324,10 @@ namespace Reflex
308
324
  return;
309
325
  #endif
310
326
 
311
- if (manager)
312
- invalid_state_error(__FILE__, __LINE__);
327
+ if (!app)
328
+ argument_error(__FILE__, __LINE__);
329
+
330
+ if (manager) return;
313
331
 
314
332
  manager.reset(new MIDIDeviceManager());
315
333
  }
@@ -317,8 +335,10 @@ namespace Reflex
317
335
  void
318
336
  MIDI_fin (Application* app)
319
337
  {
320
- if (!manager)
321
- invalid_state_error(__FILE__, __LINE__);
338
+ if (!app)
339
+ argument_error(__FILE__, __LINE__);
340
+
341
+ if (!manager) return;
322
342
 
323
343
  midis.clear();
324
344
  manager.reset();
@@ -337,6 +357,16 @@ namespace Reflex
337
357
  }
338
358
  }
339
359
 
360
+ void
361
+ enable_midi ()
362
+ {
363
+ Application* app_ = app();
364
+ if (!app_)
365
+ invalid_state_error(__FILE__, __LINE__);
366
+
367
+ MIDI_init(app_);
368
+ }
369
+
340
370
 
341
371
  MIDI::MIDI ()
342
372
  {
@@ -9,4 +9,8 @@
9
9
 
10
10
  - (BOOL) callOnStart;
11
11
 
12
+ - (BOOL) isLaunched;
13
+
14
+ - (void) updateStatusItem;
15
+
12
16
  @end// ReflexAppDelegate
@@ -6,13 +6,86 @@
6
6
  #import <Cocoa/Cocoa.h>
7
7
  #include "reflex/event.h"
8
8
  #include "reflex/exception.h"
9
+ #include "../application.h"
10
+ #include "../rays.h"
11
+ #include "menu.h"
12
+
13
+
14
+ static Reflex::Menu::Ref
15
+ create_menu (
16
+ const char* label, const char* name, SEL action = NULL,
17
+ Reflex::KeyCode key = Reflex::KEY_NONE, uint modifiers = Reflex::MOD_COMMAND)
18
+ {
19
+ Reflex::Menu* item = new Reflex::Menu(label);
20
+ item->set_name(name);
21
+ if (key != Reflex::KEY_NONE) item->set_shortcut(key, modifiers);
22
+ Reflex::Menu_set_native_action(item, action);
23
+ return item;
24
+ }
25
+
26
+ static Reflex::Menu::Ref
27
+ create_sep ()
28
+ {
29
+ return new Reflex::Menu("-");
30
+ }
31
+
32
+ static Reflex::Menu::Ref
33
+ create_application_menu (Reflex::Application* application)
34
+ {
35
+ using namespace Reflex;
36
+
37
+ String name = application->name();
38
+ if (!name.empty()) name = " " + name;
39
+
40
+ Menu::Ref app = create_menu("Application", "application");
41
+ Menu::Ref services = create_menu("Services", "services");
42
+
43
+ app->add_child(create_menu(("About" + name).c_str(), "about", @selector(showAbout)));
44
+ app->add_child(create_sep());
45
+ app->add_child(create_menu("Preferences", "preferences", @selector(showPreference), KEY_COMMA));
46
+ app->add_child(create_sep());
47
+ app->add_child(services.get());
48
+ app->add_child(create_sep());
49
+ app->add_child(create_menu(("Hide" + name).c_str(), "hide", @selector(hide:), KEY_H));
50
+ app->add_child(create_menu(
51
+ "Hide Others", "hide_others", @selector(hideOtherApplications:),
52
+ KEY_H, MOD_OPTION | MOD_COMMAND));
53
+ app->add_child(create_menu("ShowAll", "show_all", @selector(unhideAllApplications:)));
54
+ app->add_child(create_sep());
55
+ app->add_child(create_menu(("Quit" + name).c_str(), "quit", @selector(quit), KEY_Q));
56
+
57
+ [NSApp setServicesMenu: Menu_get_nssubmenu(services)];
58
+ if ([NSApp respondsToSelector: @selector(setAppleMenu:)])
59
+ [NSApp performSelector: @selector(setAppleMenu:) withObject: Menu_get_nssubmenu(app)];
60
+
61
+ return app;
62
+ }
63
+
64
+ static Reflex::Menu::Ref
65
+ create_window_menu ()
66
+ {
67
+ using namespace Reflex;
68
+
69
+ Reflex::Menu::Ref win = create_menu("Window", "window");
70
+
71
+ win->add_child(create_menu("Minimize", "minimize", @selector(performMiniaturize:), KEY_M));
72
+ win->add_child(create_menu("Zoom", "zoom", @selector(performZoom:)));
73
+ win->add_child(create_sep());
74
+ win->add_child(create_menu(
75
+ "Bring All to Front", "bring_all_to_front", @selector(arrangeInFront:)));
76
+
77
+ [NSApp setWindowsMenu: Menu_get_nssubmenu(win)];
78
+
79
+ return win;
80
+ }
9
81
 
10
82
 
11
83
  @implementation ReflexAppDelegate
12
84
 
13
85
  {
14
86
  Reflex::Application* application;
15
- bool started;
87
+ NSStatusItem* status_item;
88
+ bool launched;
16
89
  }
17
90
 
18
91
  - (id) init
@@ -21,7 +94,8 @@
21
94
  if (!self) return nil;
22
95
 
23
96
  application = NULL;
24
- started = false;
97
+ status_item = nil;
98
+ launched = false;
25
99
 
26
100
  return self;
27
101
  }
@@ -30,9 +104,20 @@
30
104
  {
31
105
  assert(!application);
32
106
 
107
+ [self clearStatusItem];
108
+
33
109
  [super dealloc];
34
110
  }
35
111
 
112
+ - (void) clearStatusItem
113
+ {
114
+ if (!status_item) return;
115
+
116
+ [NSStatusBar.systemStatusBar removeStatusItem: status_item];
117
+ [status_item release];
118
+ status_item = nil;
119
+ }
120
+
36
121
  - (void) bind: (Reflex::Application*) app
37
122
  {
38
123
  if (!app)
@@ -65,21 +150,59 @@
65
150
 
66
151
  - (BOOL) callOnStart
67
152
  {
68
- if (!application || started)
153
+ if (!application)
69
154
  return YES;
70
155
 
71
156
  Reflex::Event e;
72
- Application_call_start(application, &e);
73
- started = true;
157
+ Application_call_start_event(application, &e);
74
158
 
75
159
  if (e.is_blocked()) [self quit];
76
160
  return !e.is_blocked();
77
161
  }
78
162
 
163
+ - (BOOL) isLaunched
164
+ {
165
+ return launched;
166
+ }
167
+
168
+ - (void) updateStatusItem
169
+ {
170
+ Reflex::Menu* menu = application ? application->background_menu() : NULL;
171
+ if (!menu && application && application->background())
172
+ menu = application->menu();
173
+ if (!menu)
174
+ return [self clearStatusItem];
175
+
176
+ if (!status_item)
177
+ {
178
+ status_item =
179
+ [[NSStatusBar.systemStatusBar statusItemWithLength: NSVariableStatusItemLength]
180
+ retain];
181
+ }
182
+
183
+ NSImage* image =
184
+ menu->image() ? Rays::Bitmap_get_nsimage(menu->image().bitmap()) : nil;
185
+ [image setTemplate: YES];
186
+
187
+ NSString* title = @"";
188
+ if (!image)
189
+ {
190
+ Reflex::String label = menu->label();
191
+ if (label.empty()) label = application->name();
192
+ title = !label.empty()
193
+ ? [NSString stringWithUTF8String: label]
194
+ : NSProcessInfo.processInfo.processName;
195
+ }
196
+
197
+ status_item.button.image = image;
198
+ status_item.button.title = title;
199
+ status_item.menu = Reflex::Menu_get_nssubmenu(menu);
200
+ }
201
+
79
202
  - (void) quit
80
203
  {
81
204
  if (application)
82
- application->quit();
205
+ Application_call_quit(application);
83
206
  else
84
207
  [NSApp terminate: nil];
85
208
  }
@@ -89,7 +212,7 @@
89
212
  if (!application) return;
90
213
 
91
214
  Reflex::Event e;
92
- application->on_preference(&e);
215
+ Application_call_preference_event(application, &e);
93
216
  }
94
217
 
95
218
  - (void) showAbout
@@ -97,7 +220,7 @@
97
220
  if (application)
98
221
  {
99
222
  Reflex::Event e;
100
- application->on_about(&e);
223
+ Application_call_about_event(application, &e);
101
224
  }
102
225
  else
103
226
  [NSApp orderFrontStandardAboutPanel: nil];
@@ -105,161 +228,67 @@
105
228
 
106
229
  - (void) applicationWillFinishLaunching: (NSNotification*) notification
107
230
  {
108
- [self setupMenu];
231
+ if (!application || [NSApp mainMenu]) return;
232
+
233
+ Reflex::Menu::Ref menu = new Reflex::Menu();
234
+ menu->add_child(create_application_menu(application));
235
+ menu->add_child(create_window_menu());
236
+ application->set_menu(menu);
109
237
  }
110
238
 
111
239
  - (void) applicationDidFinishLaunching: (NSNotification*) notification
112
240
  {
113
- [NSApp setActivationPolicy: NSApplicationActivationPolicyRegular];
114
- [NSApp activateIgnoringOtherApps: YES];
241
+ if (application)
242
+ Application_set_background(application, application->background());
115
243
 
244
+ launched = true;
116
245
  [self callOnStart];
117
246
  }
118
247
 
119
248
  - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication*) application
120
249
  {
121
- if (self->application)
250
+ Reflex::Application* app = self->application;
251
+ if (!app) return NSTerminateNow;
252
+
253
+ if (app->self->running && !self.isQuitBySystem)
122
254
  {
123
- Reflex::Event e;
124
- Application_call_quit(self->application, &e);
125
- if (e.is_blocked()) return NSTerminateCancel;
255
+ Application_call_quit(app);
256
+ return NSTerminateCancel;
126
257
  }
127
258
 
128
- return NSTerminateNow;
129
- }
130
-
131
- - (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*) application
132
- {
133
- return YES;
134
- }
259
+ Reflex::Event e;
260
+ Application_call_quit_event(app, &e);
261
+ if (e.is_blocked()) return NSTerminateCancel;
135
262
 
136
- - (void) applicationWillTerminate: (NSNotification*) notification
137
- {
138
- [self unbind];
263
+ return NSTerminateNow;
139
264
  }
140
265
 
141
- - (BOOL) setupApplicationMenu: (NSMenu*) parent
266
+ - (BOOL) isQuitBySystem
142
267
  {
143
- if (!application || !parent) return NO;
144
-
145
- NSMenu* menu = [[[NSMenu alloc]
146
- initWithTitle: @"Application"]
147
- autorelease];
148
- if ([NSApp respondsToSelector: @selector(setAppleMenu:)])
149
- [NSApp performSelector: @selector(setAppleMenu:) withObject: menu];
150
-
151
- NSString* name = !application->self->name.empty() ?
152
- [NSString stringWithUTF8String: application->self->name.c_str()] : @"";
153
- if ([name length] > 0)
154
- name = [@" " stringByAppendingString: name];
155
-
156
- NSMenu* submenu = nil;
157
- NSMenuItem* item = nil;
158
-
159
- [menu
160
- addItemWithTitle: [@"About" stringByAppendingString: name]
161
- action: @selector(showAbout)
162
- keyEquivalent: @""];
163
-
164
- [menu addItem: [NSMenuItem separatorItem]];
165
-
166
- [menu
167
- addItemWithTitle: @"Preferences"
168
- action: @selector(showPreference)
169
- keyEquivalent: @","];
170
-
171
- [menu addItem: [NSMenuItem separatorItem]];
172
-
173
- item = [menu
174
- addItemWithTitle: @"Services"
175
- action: nil
176
- keyEquivalent: @""];
177
- submenu = [[[NSMenu alloc] initWithTitle: @"Services"] autorelease];
178
- [item setSubmenu: submenu];
179
- [NSApp setServicesMenu: submenu];
180
-
181
- [menu addItem: [NSMenuItem separatorItem]];
182
-
183
- [menu
184
- addItemWithTitle: [@"Hide" stringByAppendingString: name]
185
- action: @selector(hide:)
186
- keyEquivalent: @"h"];
187
-
188
- item = [menu
189
- addItemWithTitle: @"Hide Others"
190
- action: @selector(hideOtherApplications:)
191
- keyEquivalent: @"h"];
192
- [item setKeyEquivalentModifierMask: NSAlternateKeyMask | NSCommandKeyMask];
193
-
194
- [menu
195
- addItemWithTitle: @"ShowAll"
196
- action: @selector(unhideAllApplications:)
197
- keyEquivalent: @""];
198
-
199
- [menu addItem: [NSMenuItem separatorItem]];
200
-
201
- [menu
202
- addItemWithTitle: [@"Quit" stringByAppendingString: name]
203
- action: @selector(quit)
204
- keyEquivalent: @"q"];
205
-
206
- item =
207
- [parent addItemWithTitle: @"Application" action: nil keyEquivalent: @""];
208
- [parent setSubmenu: menu forItem: item];
209
-
210
- return YES;
268
+ // log out, shut down and restart put a reason on the quit event,
269
+ // while a quit from the dock or a script comes without one
270
+ NSAppleEventDescriptor* event =
271
+ NSAppleEventManager.sharedAppleEventManager.currentAppleEvent;
272
+ return
273
+ event &&
274
+ event.eventClass == kCoreEventClass &&
275
+ event.eventID == kAEQuitApplication &&
276
+ [event attributeDescriptorForKeyword: kAEQuitReason];
211
277
  }
212
278
 
213
- - (BOOL) setupWindowMenu: (NSMenu*) parent
279
+ - (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*) application
214
280
  {
215
- if (!parent) return NO;
216
-
217
- NSMenu* menu = [[[NSMenu alloc]
218
- initWithTitle: @"Window"]
219
- autorelease];
220
-
221
- [menu
222
- addItemWithTitle: @"Minimize"
223
- action: @selector(performMiniaturize:)
224
- keyEquivalent: @"m"];
225
-
226
- [menu
227
- addItemWithTitle: @"Zoom"
228
- action: @selector(performZoom:)
229
- keyEquivalent: @""];
230
-
231
- [menu addItem: [NSMenuItem separatorItem]];
232
-
233
- [menu
234
- addItemWithTitle: @"Bring All to Front"
235
- action: @selector(arrangeInFront:)
236
- keyEquivalent: @""];
237
-
238
- NSMenuItem* item =
239
- [parent addItemWithTitle: @"Window" action: nil keyEquivalent: @""];
240
- [parent setSubmenu: menu forItem: item];
241
-
242
- [NSApp setWindowsMenu: menu];
243
-
244
- return YES;
281
+ if (Application_should_quit(self->application))
282
+ [self quit];
283
+ return NO;
245
284
  }
246
285
 
247
- - (BOOL) setupMenu
286
+ - (void) applicationWillTerminate: (NSNotification*) notification
248
287
  {
249
- if ([NSApp mainMenu]) return NO;
250
-
251
- NSMenu* menu = [[[NSMenu alloc] initWithTitle: @"MainMenu"] autorelease];
252
-
253
- if (
254
- ![self setupApplicationMenu: menu] ||
255
- ![self setupWindowMenu: menu])
256
- {
257
- return NO;
258
- }
259
-
260
- [NSApp setMainMenu: menu];
288
+ if (application)
289
+ Application_cleanup(application);
261
290
 
262
- return YES;
291
+ [self unbind];
263
292
  }
264
293
 
265
294
  @end// ReflexAppDelegate