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,490 @@
1
+ #include "menu.h"
2
+
3
+
4
+ #include <string>
5
+ #include <vector>
6
+ #include <xot/time.h>
7
+ #include "reflex/exception.h"
8
+ #include "reflex/event.h"
9
+ #include "reflex/view.h"
10
+ #include "../rays.h"
11
+ #include "window.h"
12
+ #include "screen.h"
13
+
14
+
15
+ namespace Reflex
16
+ {
17
+
18
+
19
+ static UINT
20
+ next_menu_id ()
21
+ {
22
+ static UINT id = 100;
23
+ return id++;
24
+ }
25
+
26
+ static HMENU
27
+ create_hmenu (Menu* menu, bool menubar)
28
+ {
29
+ HMENU hmenu = menubar ? CreateMenu() : CreatePopupMenu();
30
+ if (!hmenu)
31
+ system_error(__FILE__, __LINE__);
32
+
33
+ MENUINFO mi = {sizeof(mi)};
34
+ mi.fMask = MIM_MENUDATA | MIM_STYLE;
35
+ mi.dwMenuData = (ULONG_PTR) menu;
36
+ mi.dwStyle = MNS_NOTIFYBYPOS;
37
+ SetMenuInfo(hmenu, &mi);
38
+
39
+ return hmenu;
40
+ }
41
+
42
+ static void
43
+ destroy_hmenu (HMENU hmenu)
44
+ {
45
+ if (!hmenu || !IsMenu(hmenu)) return;
46
+
47
+ while (GetMenuItemCount(hmenu) > 0)
48
+ RemoveMenu(hmenu, 0, MF_BYPOSITION);
49
+
50
+ DestroyMenu(hmenu);
51
+ }
52
+
53
+
54
+ struct MenuData : public Menu::Data
55
+ {
56
+
57
+ UINT id = next_menu_id();
58
+
59
+ HMENU hparent = NULL;
60
+
61
+ HMENU hsubmenu = NULL;
62
+
63
+ bool menubar = false;
64
+
65
+ bool modified = false;
66
+
67
+ Image image;
68
+
69
+ std::shared_ptr<HBITMAP__> hbitmap;
70
+
71
+ virtual ~MenuData ()
72
+ {
73
+ destroy_hmenu(hsubmenu);
74
+ }
75
+
76
+ HMENU get_hsubmenu (Menu* menu, bool menubar = false);
77
+
78
+ HBITMAP get_hbitmap (const Image& image)
79
+ {
80
+ if (image != this->image)
81
+ {
82
+ this->image = image;
83
+ if (image)
84
+ hbitmap.reset(Rays::Bitmap_get_hbitmap(image.bitmap()), DeleteObject);
85
+ else
86
+ hbitmap.reset();
87
+ }
88
+ return hbitmap.get();
89
+ }
90
+
91
+ };// MenuData
92
+
93
+
94
+ static MenuData&
95
+ get_data (Menu* menu)
96
+ {
97
+ if (!menu)
98
+ argument_error(__FILE__, __LINE__);
99
+
100
+ return (MenuData&) *menu->self;
101
+ }
102
+
103
+ static Menu*
104
+ get_root (Menu* menu)
105
+ {
106
+ while (menu->parent()) menu = menu->parent();
107
+ return menu;
108
+ }
109
+
110
+ static void
111
+ set_modified (Menu* menu)
112
+ {
113
+ get_data(get_root(menu)).modified = true;
114
+ }
115
+
116
+ static Menu*
117
+ get_item_owner (HMENU hparent, uint index)
118
+ {
119
+ if (!hparent) return NULL;
120
+
121
+ MENUITEMINFOW mii = {sizeof(mii)};
122
+ mii.fMask = MIIM_DATA;
123
+ if (!GetMenuItemInfoW(hparent, index, TRUE, &mii))
124
+ return NULL;
125
+
126
+ return (Menu*) mii.dwItemData;
127
+ }
128
+
129
+ static Menu*
130
+ get_submenu_owner (HMENU hsubmenu)
131
+ {
132
+ if (!hsubmenu) return NULL;
133
+
134
+ MENUINFO mi = {sizeof(mi)};
135
+ mi.fMask = MIM_MENUDATA;
136
+ if (!GetMenuInfo(hsubmenu, &mi))
137
+ return NULL;
138
+
139
+ return (Menu*) mi.dwMenuData;
140
+ }
141
+
142
+ static void
143
+ insert_item (HMENU hparent, Menu* item, int index)
144
+ {
145
+ MenuData& self = get_data(item);
146
+
147
+ MENUITEMINFOW mii = {sizeof(mii)};
148
+ mii.fMask = MIIM_ID | MIIM_DATA | MIIM_FTYPE | MIIM_STRING;
149
+ mii.fType = MFT_STRING;
150
+ mii.wID = self.id;
151
+ mii.dwItemData = (ULONG_PTR) item;
152
+ mii.dwTypeData = (LPWSTR) L"";
153
+
154
+ if (!InsertMenuItemW(hparent, (UINT) index, TRUE, &mii))
155
+ system_error(__FILE__, __LINE__);
156
+
157
+ self.hparent = hparent;
158
+
159
+ Menu_update(item);
160
+ }
161
+
162
+ Menu::Data*
163
+ Menu_create_data ()
164
+ {
165
+ return new MenuData();
166
+ }
167
+
168
+ void
169
+ Menu_validate_shortcut_modifiers (uint modifiers)
170
+ {
171
+ static const uint SUPPORTED =
172
+ MOD_SHIFT | MOD_CONTROL | MOD_ALT | MOD_OPTION;
173
+
174
+ if (modifiers & ~SUPPORTED)
175
+ {
176
+ argument_error(
177
+ __FILE__, __LINE__,
178
+ "modifiers 0x%X can not be used for a shortcut on Windows.",
179
+ modifiers & ~SUPPORTED);
180
+ }
181
+ }
182
+
183
+ static String
184
+ get_shortcut_key_name (int key)
185
+ {
186
+ if (key < 0) return "";
187
+
188
+ UINT vsc = MapVirtualKeyW((UINT) key, MAPVK_VK_TO_VSC_EX);
189
+ if (vsc == 0) return "";
190
+
191
+ LONG lparam = (LONG) ((vsc & 0xff) << 16);
192
+ if (vsc & 0xff00) lparam |= 1 << 24;// extended key
193
+
194
+ wchar_t name[64] = {0};
195
+ int len = GetKeyNameTextW(lparam, name, (int) (sizeof(name) / sizeof(*name)));
196
+ if (len <= 0) return "";
197
+
198
+ return String(name, (size_t) len);
199
+ }
200
+
201
+ static String
202
+ make_item_string (const Menu* menu)
203
+ {
204
+ String str = menu->label();
205
+ String key = menu->empty() ? get_shortcut_key_name(menu->shortcut_key()) : "";
206
+ if (!key.empty())
207
+ {
208
+ str += '\t';
209
+ uint mods = menu->shortcut_modifiers();
210
+ if (mods & MOD_CONTROL) str += "Ctrl+";
211
+ if (mods & MOD_SHIFT) str += "Shift+";
212
+ if (mods & (MOD_ALT | MOD_OPTION)) str += "Alt+";
213
+ str += key;
214
+ }
215
+ return str;
216
+ }
217
+
218
+ void
219
+ Menu_update (Menu* menu)
220
+ {
221
+ MenuData& self = get_data(menu);
222
+
223
+ if (!self.hparent) return;
224
+
225
+ MENUITEMINFOW mii = {sizeof(mii)};
226
+ mii.fMask =
227
+ MIIM_ID | MIIM_DATA | MIIM_FTYPE | MIIM_STATE | MIIM_BITMAP | MIIM_SUBMENU;
228
+ mii.wID = self.id;
229
+ mii.dwItemData = (ULONG_PTR) menu;
230
+
231
+ std::wstring label;
232
+ if (menu->is_separator())
233
+ mii.fType = MFT_SEPARATOR;
234
+ else
235
+ {
236
+ label = make_item_string(menu).to_wstr();
237
+
238
+ mii.fMask |= MIIM_STRING;
239
+ mii.fType = MFT_STRING;
240
+ mii.dwTypeData = (LPWSTR) label.c_str();
241
+ mii.fState =
242
+ (menu->is_enabled() ? MFS_ENABLED : MFS_GRAYED) |
243
+ (menu->is_checked() ? MFS_CHECKED : MFS_UNCHECKED);
244
+ mii.hbmpItem = self.get_hbitmap(menu->image());
245
+ mii.hSubMenu = menu->empty() ? NULL : self.hsubmenu;
246
+ }
247
+
248
+ SetMenuItemInfoW(self.hparent, self.id, FALSE, &mii);
249
+
250
+ set_modified(menu);
251
+ }
252
+
253
+ void
254
+ Menu_popup (Menu* menu, View* view, coord x, coord y)
255
+ {
256
+ Menu_cancel_active_pointers_for_popup(view);
257
+
258
+ MenuData& self = get_data(menu);
259
+
260
+ HMENU hmenu = self.get_hsubmenu(menu);
261
+ if (!hmenu)
262
+ invalid_state_error(__FILE__, __LINE__);
263
+
264
+ HWND hwnd = NULL;
265
+ POINT pos = Screen_to_native_coord(x, y);
266
+
267
+ if (view)
268
+ {
269
+ Window* win = view->window();
270
+ if (!win)
271
+ invalid_state_error(__FILE__, __LINE__);
272
+
273
+ hwnd = Window_get_hwnd(win);
274
+ if (!hwnd)
275
+ invalid_state_error(__FILE__, __LINE__);
276
+
277
+ pos = Window_to_native_coord(*win, view->to_window(Point(x, y)));
278
+ ClientToScreen(hwnd, &pos);
279
+ }
280
+ else
281
+ hwnd = GetActiveWindow();
282
+
283
+ if (!hwnd) return;
284
+
285
+ Menu_track_popup(
286
+ hmenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, pos, hwnd);
287
+ }
288
+
289
+ void
290
+ Menu_child_added (Menu* parent, Menu* child, int index)
291
+ {
292
+ MenuData& c = get_data(child);
293
+
294
+ if (c.hparent)
295
+ invalid_state_error(__FILE__, __LINE__);
296
+
297
+ insert_item(get_data(parent).get_hsubmenu(parent), child, index);
298
+ }
299
+
300
+ void
301
+ Menu_child_removed (Menu* parent, Menu* child)
302
+ {
303
+ MenuData& p = get_data(parent);
304
+ MenuData& c = get_data(child);
305
+
306
+ if (!p.hsubmenu)
307
+ invalid_state_error(__FILE__, __LINE__);
308
+ if (c.hparent != p.hsubmenu)
309
+ invalid_state_error(__FILE__, __LINE__);
310
+
311
+ RemoveMenu(p.hsubmenu, c.id, MF_BYCOMMAND);
312
+ c.hparent = NULL;
313
+
314
+ set_modified(parent);
315
+ }
316
+
317
+
318
+ void
319
+ Menu_track_popup (HMENU hmenu, UINT flags, POINT pos, HWND owner)
320
+ {
321
+ double start = Xot::time();
322
+
323
+ // TrackPopupMenu needs the owner window in the foreground
324
+ SetForegroundWindow(owner);
325
+
326
+ TrackPopupMenu(hmenu, flags, pos.x, pos.y, 0, owner, NULL);
327
+
328
+ // the documented workaround for the menu not closing
329
+ // on the first outside click
330
+ PostMessageW(owner, WM_NULL, 0, 0);
331
+
332
+ Window_skip_update_time_of_all(Xot::time() - start);
333
+ }
334
+
335
+ HMENU
336
+ Menu_get_hmenu (Menu* menu, bool menubar)
337
+ {
338
+ return menu ? get_data(menu).get_hsubmenu(menu, menubar) : NULL;
339
+ }
340
+
341
+ bool
342
+ Menu_is_modified (Menu* menu)
343
+ {
344
+ return menu && get_data(menu).modified;
345
+ }
346
+
347
+ static void
348
+ collect_accels (std::vector<ACCEL>* accels, Menu* menu)
349
+ {
350
+ for (auto& child : *menu)
351
+ {
352
+ Menu* item = child.get();
353
+ if (!item) continue;
354
+
355
+ int key = item->shortcut_key();
356
+ if (key >= 0 && item->empty())
357
+ {
358
+ uint mods = item->shortcut_modifiers();
359
+
360
+ ACCEL accel = {0};
361
+ accel.key = (WORD) key;// KeyCode == VK
362
+ accel.cmd = (WORD) get_data(item).id;
363
+ accel.fVirt = (BYTE) (FVIRTKEY |
364
+ (mods & MOD_CONTROL ? FCONTROL : 0) |
365
+ (mods & MOD_SHIFT ? FSHIFT : 0) |
366
+ (mods & (MOD_ALT | MOD_OPTION) ? FALT : 0));
367
+ accels->emplace_back(accel);
368
+ }
369
+
370
+ collect_accels(accels, item);
371
+ }
372
+ }
373
+
374
+ HACCEL
375
+ Menu_create_accelerator_table (Menu* menu)
376
+ {
377
+ if (!menu) return NULL;
378
+
379
+ get_data(menu).modified = false;
380
+
381
+ std::vector<ACCEL> accels;
382
+ collect_accels(&accels, menu);
383
+ if (accels.empty()) return NULL;
384
+
385
+ return CreateAcceleratorTableW(accels.data(), (int) accels.size());
386
+ }
387
+
388
+ static Menu*
389
+ find_item (Menu* menu, UINT id)
390
+ {
391
+ for (auto& child : *menu)
392
+ {
393
+ Menu* item = child.get();
394
+ if (!item || !item->is_enabled()) continue;
395
+
396
+ if (get_data(item).id == id) return item;
397
+
398
+ Menu* found = find_item(item, id);
399
+ if (found) return found;
400
+ }
401
+ return NULL;
402
+ }
403
+
404
+ void
405
+ Menu_call_command_event (Menu* menu, uint id)
406
+ {
407
+ if (!menu) return;
408
+
409
+ Menu* item = find_item(menu, (UINT) id);
410
+ if (!item) return;
411
+
412
+ Event e;
413
+ Menu_call_click_event(item, &e);
414
+ }
415
+
416
+ void
417
+ Menu_call_command_event (HMENU hmenu, uint index)
418
+ {
419
+ Menu* menu = get_item_owner(hmenu, index);
420
+ if (!menu) return;
421
+
422
+ Event e;
423
+ Menu_call_click_event(menu, &e);
424
+ }
425
+
426
+ void
427
+ Menu_call_open_event (HMENU hmenu)
428
+ {
429
+ Menu* menu = get_submenu_owner(hmenu);
430
+ if (!menu) return;
431
+
432
+ Event e;
433
+ Menu_call_open_submenu_event(menu, &e);
434
+
435
+ int count = GetMenuItemCount(hmenu);
436
+ for (int i = 0; i < count; ++i)
437
+ {
438
+ Menu* child = get_item_owner(hmenu, i);
439
+ if (!child) continue;
440
+
441
+ Event ce;
442
+ Menu_call_show_event(child, &ce);
443
+ }
444
+ }
445
+
446
+ void
447
+ Menu_call_close_event (HMENU hmenu)
448
+ {
449
+ Menu* menu = get_submenu_owner(hmenu);
450
+ if (!menu) return;
451
+
452
+ int count = GetMenuItemCount(hmenu);
453
+ for (int i = 0; i < count; ++i)
454
+ {
455
+ Menu* child = get_item_owner(hmenu, i);
456
+ if (!child) continue;
457
+
458
+ Event ce;
459
+ Menu_call_hide_event(child, &ce);
460
+ }
461
+
462
+ Event e;
463
+ Menu_call_close_submenu_event(menu, &e);
464
+ }
465
+
466
+
467
+ HMENU
468
+ MenuData::get_hsubmenu (Menu* menu, bool menubar)
469
+ {
470
+ if (!hsubmenu)
471
+ {
472
+ hsubmenu = create_hmenu(menu, menubar);
473
+ this->menubar = menubar;
474
+ }
475
+ else if (menubar != this->menubar)
476
+ {
477
+ HMENU old = hsubmenu;
478
+ hsubmenu = create_hmenu(menu, menubar);
479
+ this->menubar = menubar;
480
+
481
+ int index = 0;
482
+ for (auto it = menu->begin(); it != menu->end(); ++it, ++index)
483
+ insert_item(hsubmenu, it->get(), index);
484
+ destroy_hmenu(old);
485
+ }
486
+ return hsubmenu;
487
+ }
488
+
489
+
490
+ }// Reflex
data/src/win32/menu.h ADDED
@@ -0,0 +1,35 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __REFLEX_SRC_WIN32_MENU_H__
4
+ #define __REFLEX_SRC_WIN32_MENU_H__
5
+
6
+
7
+ #include <xot/windows.h>
8
+ #include "../menu.h"
9
+
10
+
11
+ namespace Reflex
12
+ {
13
+
14
+
15
+ void Menu_track_popup (HMENU hmenu, UINT flags, POINT pos, HWND owner);
16
+
17
+ HMENU Menu_get_hmenu (Menu* menu, bool menubar = false);
18
+
19
+ bool Menu_is_modified (Menu* menu);
20
+
21
+ HACCEL Menu_create_accelerator_table (Menu* menu);
22
+
23
+ void Menu_call_command_event (Menu* menu, uint id);
24
+
25
+ void Menu_call_command_event (HMENU hmenu, uint index);
26
+
27
+ void Menu_call_open_event (HMENU hmenu);
28
+
29
+ void Menu_call_close_event (HMENU hmenu);
30
+
31
+
32
+ }// Reflex
33
+
34
+
35
+ #endif//EOH
data/src/win32/opengl.cpp CHANGED
@@ -3,14 +3,7 @@
3
3
 
4
4
  #include <rays/rays.h>
5
5
  #include "reflex/exception.h"
6
-
7
-
8
- namespace Rays
9
- {
10
-
11
- const PIXELFORMATDESCRIPTOR* get_pixel_format_descriptor ();
12
-
13
- }// Rays
6
+ #include "../rays.h"
14
7
 
15
8
 
16
9
  namespace Reflex
@@ -40,7 +33,7 @@ namespace Reflex
40
33
  if (!hdc)
41
34
  system_error(__FILE__, __LINE__);
42
35
 
43
- const auto* pfd = Rays::get_pixel_format_descriptor();
36
+ const auto* pfd = Rays::OpenGL_get_pixel_format_descriptor();
44
37
  int pf = ChoosePixelFormat(hdc, pfd);
45
38
  if (pf == 0)
46
39
  system_error(__FILE__, __LINE__);
data/src/win32/reflex.cpp CHANGED
@@ -1,17 +1,38 @@
1
1
  #include "reflex/reflex.h"
2
2
 
3
3
 
4
+ #include <xot/windows.h>
4
5
  #include "reflex/exception.h"
6
+ #include "../rays.h"
5
7
 
6
8
 
7
9
  namespace Reflex
8
10
  {
9
11
 
10
12
 
13
+ static struct ReflexLoaded
14
+ {
15
+ ReflexLoaded ()
16
+ {
17
+ Rays::Rays_set_pre_init_fun(pre_init);
18
+ }
19
+
20
+ static void pre_init ()
21
+ {
22
+ // enable High DPI: before Rays makes the hidden window for its OpenGL
23
+ // context, as Windows takes no declaration after a window
24
+ SetProcessDPIAware();
25
+ }
26
+
27
+ } reflex_loaded;
28
+
29
+
11
30
  namespace global
12
31
  {
13
32
 
14
- static bool initialized = false;
33
+ static bool initialized = false;
34
+
35
+ static bool com_initialized = false;
15
36
 
16
37
  }// global
17
38
 
@@ -21,8 +42,10 @@ namespace Reflex
21
42
  {
22
43
  if (global::initialized)
23
44
  reflex_error(__FILE__, __LINE__, "already initialized.");
24
-
25
45
  global::initialized = true;
46
+
47
+ global::com_initialized =
48
+ SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
26
49
  }
27
50
 
28
51
  void
@@ -30,8 +53,26 @@ namespace Reflex
30
53
  {
31
54
  if (!global::initialized)
32
55
  reflex_error(__FILE__, __LINE__, "not initialized.");
33
-
34
56
  global::initialized = false;
57
+
58
+ if (global::com_initialized)
59
+ {
60
+ CoUninitialize();
61
+ global::com_initialized = false;
62
+ }
63
+ }
64
+
65
+ void
66
+ alert (const char* message, const char* title)
67
+ {
68
+ if (!message)
69
+ argument_error(__FILE__, __LINE__);
70
+
71
+ MessageBoxW(
72
+ GetActiveWindow(),
73
+ String(message) .to_wstr().c_str(),
74
+ String(title ? title : "").to_wstr().c_str(),
75
+ MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
35
76
  }
36
77
 
37
78