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
@@ -1,19 +1,151 @@
1
- #include "../application.h"
1
+ #include "application.h"
2
2
 
3
3
 
4
+ #include <vector>
4
5
  #include <xot/windows.h>
5
6
  #include "reflex/exception.h"
6
7
  #include "window.h"
8
+ #include "tray.h"
7
9
 
8
10
 
9
11
  namespace Reflex
10
12
  {
11
13
 
12
14
 
15
+ struct ApplicationData : public Application::Data
16
+ {
17
+
18
+ bool quit = false;
19
+
20
+ };// ApplicationData
21
+
22
+
23
+ static ApplicationData*
24
+ get_data (Application* app)
25
+ {
26
+ return (ApplicationData*) app->self.get();
27
+ }
28
+
13
29
  Application::Data*
14
30
  Application_create_data ()
15
31
  {
16
- return new Application::Data();
32
+ return new ApplicationData();
33
+ }
34
+
35
+ static std::wstring
36
+ get_app_executable_path ()
37
+ {
38
+ std::wstring path(MAX_PATH, L'\0');
39
+ while (true)
40
+ {
41
+ DWORD len = GetModuleFileNameW(NULL, &path[0], (DWORD) path.size());
42
+ if (len < path.size())
43
+ {
44
+ path.resize(len);
45
+ break;
46
+ }
47
+ path.resize(path.size() * 2);
48
+ }
49
+ return path;
50
+ }
51
+
52
+ static String
53
+ get_product_name (const wchar_t* path)
54
+ {
55
+ DWORD size = GetFileVersionInfoSizeW(path, NULL);
56
+ if (size == 0) return "";
57
+
58
+ std::vector<BYTE> info(size);
59
+ if (!GetFileVersionInfoW(path, 0, size, &info[0]))
60
+ return "";
61
+
62
+ struct Translation {WORD lang, codepage;};
63
+ Translation* translations = NULL;
64
+ UINT bytes = 0;
65
+ if (
66
+ !VerQueryValueW(
67
+ &info[0], L"\\VarFileInfo\\Translation", (void**) &translations, &bytes) ||
68
+ bytes < sizeof(Translation))
69
+ {
70
+ return "";
71
+ }
72
+
73
+ LANGID deflang = GetUserDefaultUILanguage();
74
+ const Translation* found = &translations[0];
75
+ for (size_t i = 0; i < bytes / sizeof(Translation); ++i)
76
+ {
77
+ const Translation& t = translations[i];
78
+ if (t.lang == deflang)
79
+ {
80
+ found = &t;
81
+ break;
82
+ }
83
+ if (
84
+ PRIMARYLANGID(t.lang) == PRIMARYLANGID(deflang) &&
85
+ found == &translations[0])
86
+ {
87
+ found = &t;
88
+ }
89
+ }
90
+
91
+ wchar_t key[64];
92
+ swprintf(
93
+ key, 64, L"\\StringFileInfo\\%04x%04x\\ProductName",
94
+ found->lang, found->codepage);
95
+
96
+ wchar_t* name = NULL;
97
+ if (!VerQueryValueW(&info[0], key, (void**) &name, &bytes) || bytes <= 1)
98
+ return "";
99
+
100
+ return String(name, wcslen(name));
101
+ }
102
+
103
+ String
104
+ Application_get_default_name ()
105
+ {
106
+ std::wstring path = get_app_executable_path();
107
+ if (path.empty())
108
+ return "";
109
+
110
+ String name = get_product_name(path.c_str());
111
+ if (!name.empty())
112
+ return name;
113
+
114
+ std::wstring file = path.substr(path.find_last_of(L"\\/") + 1);
115
+ size_t dot = file.find_last_of(L'.');
116
+ if (dot != std::wstring::npos) file.resize(dot);
117
+ return String(file.c_str(), file.size());
118
+ }
119
+
120
+ void
121
+ Application_stop (Application* app)
122
+ {
123
+ get_data(app)->quit = true;
124
+ }
125
+
126
+ void
127
+ Application_set_menu (Application* app, Menu* menu)
128
+ {
129
+ Tray_update_icon(app);
130
+ }
131
+
132
+ void
133
+ Application_set_background (Application* app, bool state)
134
+ {
135
+ Tray_update_icon(app);
136
+ }
137
+
138
+ void
139
+ Application_set_background_menu (Application* app, Menu* menu)
140
+ {
141
+ Tray_update_icon(app);
142
+ }
143
+
144
+ void
145
+ Application_quit_if_should ()
146
+ {
147
+ if (Application_should_quit(app()))
148
+ Application_call_quit(app());
17
149
  }
18
150
 
19
151
 
@@ -41,21 +173,34 @@ namespace Reflex
41
173
  void
42
174
  Application::start ()
43
175
  {
176
+ ApplicationData* self = get_data(this);
177
+ self->quit = false;
178
+ self->quitting = false;
179
+ self->started = false;
180
+ self->running = true;
181
+
182
+ Tray_update_icon(this);
183
+
44
184
  Event e;
45
- Application_call_start(this, &e);
185
+ Application_call_start_event(this, &e);
46
186
 
47
187
  timeBeginPeriod(1);
48
188
 
49
189
  double prev = get_time();
50
190
 
51
- MSG msg;
52
- while (true)
191
+ MSG msg = {0};
192
+ while (!self->quit)
53
193
  {
54
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
194
+ if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
55
195
  {
56
- if (msg.message == WM_QUIT) break;
196
+ if (msg.message == WM_QUIT)
197
+ break;
198
+
199
+ if (Window_translate_accelerator(&msg))
200
+ continue;
201
+
57
202
  TranslateMessage(&msg);
58
- DispatchMessage(&msg);
203
+ DispatchMessageW(&msg);
59
204
  }
60
205
  else
61
206
  {
@@ -70,14 +215,24 @@ namespace Reflex
70
215
  continue;
71
216
  }
72
217
 
73
- update_all_windows(this);
218
+ // guarded here too, since rays can throw while drawing
219
+ Application_guard([&]()
220
+ {
221
+ update_all_windows(this);
222
+ });
74
223
  prev = now;
75
224
  }
76
225
  }
77
226
 
78
227
  timeEndPeriod(1);
79
228
 
80
- if (msg.wParam != 0)
229
+ self->running = false;
230
+
231
+ Tray_remove_icon();
232
+ Application_cleanup(this);
233
+ Application_throw_exception(this);
234
+
235
+ if (msg.message == WM_QUIT && msg.wParam != 0)
81
236
  reflex_error(__FILE__, __LINE__, "WM_QUIT with wParam %d.", msg.wParam);
82
237
  }
83
238
 
@@ -85,10 +240,10 @@ namespace Reflex
85
240
  Application::quit ()
86
241
  {
87
242
  Event e;
88
- Application_call_quit(this, &e);
243
+ Application_call_quit_event(this, &e);
89
244
  if (e.is_blocked()) return;
90
245
 
91
- PostQuitMessage(0);
246
+ Application_stop(this);
92
247
  }
93
248
 
94
249
  void
@@ -0,0 +1,20 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __REFLEX_SRC_WIN32_APPLICATION_H__
4
+ #define __REFLEX_SRC_WIN32_APPLICATION_H__
5
+
6
+
7
+ #include "../application.h"
8
+
9
+
10
+ namespace Reflex
11
+ {
12
+
13
+
14
+ void Application_quit_if_should ();
15
+
16
+
17
+ }// Reflex
18
+
19
+
20
+ #endif//EOH
@@ -0,0 +1,210 @@
1
+ #include "reflex/clipboard.h"
2
+
3
+
4
+ #include <string.h>
5
+ #include <wchar.h>
6
+ #include <xot/noncopyable.h>
7
+ #include <xot/windows.h>
8
+ #include "reflex/exception.h"
9
+
10
+
11
+ namespace Reflex
12
+ {
13
+
14
+
15
+ class ClipboardLock : public Xot::NonCopyable
16
+ {
17
+
18
+ enum
19
+ {
20
+
21
+ RETRY_COUNT = 3,
22
+
23
+ RETRY_INTERVAL = 30// milliseconds
24
+
25
+ };
26
+
27
+ public:
28
+
29
+ ClipboardLock ()
30
+ : opened(false)
31
+ {
32
+ // OpenClipboard fails while another process has the clipboard open
33
+ for (int i = 0; i < RETRY_COUNT; ++i)
34
+ {
35
+ if (i > 0) Sleep(RETRY_INTERVAL);
36
+
37
+ opened = OpenClipboard(NULL) != FALSE;
38
+ if (opened) break;
39
+ }
40
+ }
41
+
42
+ ~ClipboardLock ()
43
+ {
44
+ if (opened) CloseClipboard();
45
+ }
46
+
47
+ operator bool () const
48
+ {
49
+ return opened;
50
+ }
51
+
52
+ private:
53
+
54
+ bool opened;
55
+
56
+ };// ClipboardLock
57
+
58
+
59
+ class GlobalMemory : public Xot::NonCopyable
60
+ {
61
+
62
+ public:
63
+
64
+ GlobalMemory (HGLOBAL handle, bool owner = false)
65
+ : handle(handle), owner(owner), pointer(NULL)
66
+ {
67
+ }
68
+
69
+ ~GlobalMemory ()
70
+ {
71
+ unlock();
72
+ if (handle && owner) GlobalFree(handle);
73
+ }
74
+
75
+ void* lock ()
76
+ {
77
+ if (!pointer && handle) pointer = GlobalLock(handle);
78
+ return pointer;
79
+ }
80
+
81
+ void unlock ()
82
+ {
83
+ if (!pointer) return;
84
+ GlobalUnlock(handle);
85
+ pointer = NULL;
86
+ }
87
+
88
+ HGLOBAL release ()
89
+ {
90
+ owner = false;
91
+ return handle;
92
+ }
93
+
94
+ HGLOBAL get () const
95
+ {
96
+ return handle;
97
+ }
98
+
99
+ operator bool () const
100
+ {
101
+ return handle != NULL;
102
+ }
103
+
104
+ private:
105
+
106
+ HGLOBAL handle;
107
+
108
+ bool owner;
109
+
110
+ void* pointer;
111
+
112
+ };// GlobalMemory
113
+
114
+
115
+ static String
116
+ to_crlf (const char* text)
117
+ {
118
+ String result;
119
+ for (const char* p = text; *p; ++p)
120
+ {
121
+ if (*p == '\r' || *p == '\n')
122
+ {
123
+ result += "\r\n";
124
+ if (*p == '\r' && *(p + 1) == '\n') ++p;
125
+ continue;
126
+ }
127
+ result += *p;
128
+ }
129
+ return result;
130
+ }
131
+
132
+ static String
133
+ to_lf (const String& text)
134
+ {
135
+ size_t size = text.size();
136
+ String result;
137
+ result.reserve(size);
138
+ for (size_t i = 0; i < size; ++i)
139
+ {
140
+ char c = text[i];
141
+ if (c == '\r')
142
+ {
143
+ if ((i + 1) < size && text[i + 1] == '\n') continue;
144
+ c = '\n';
145
+ }
146
+ result += c;
147
+ }
148
+ return result;
149
+ }
150
+
151
+ static HGLOBAL
152
+ create_text_handle (const char* text)
153
+ {
154
+ std::wstring wtext = to_crlf(text).to_wstr();
155
+ size_t size = (wtext.size() + 1) * sizeof(wchar_t);
156
+
157
+ GlobalMemory mem(GlobalAlloc(GMEM_MOVEABLE, size), true);
158
+ if (!mem)
159
+ system_error(__FILE__, __LINE__);
160
+
161
+ void* buffer = mem.lock();
162
+ if (!buffer)
163
+ system_error(__FILE__, __LINE__);
164
+
165
+ memcpy(buffer, wtext.c_str(), size);
166
+ mem.unlock();
167
+
168
+ return mem.release();
169
+ }
170
+
171
+ void
172
+ set_clipboard (const Clipboard& clipboard)
173
+ {
174
+ const char* text = clipboard.text();
175
+ GlobalMemory textmem(text ? create_text_handle(text) : NULL, true);
176
+
177
+ ClipboardLock lock;
178
+ if (!lock)
179
+ system_error(__FILE__, __LINE__);
180
+
181
+ if (!EmptyClipboard())
182
+ system_error(__FILE__, __LINE__);
183
+
184
+ if (textmem)
185
+ {
186
+ if (!SetClipboardData(CF_UNICODETEXT, textmem.get()))
187
+ system_error(__FILE__, __LINE__);
188
+ textmem.release();
189
+ }
190
+ }
191
+
192
+ Clipboard
193
+ get_clipboard ()
194
+ {
195
+ ClipboardLock lock;
196
+ if (!lock)
197
+ system_error(__FILE__, __LINE__);
198
+
199
+ Clipboard clipboard;
200
+
201
+ GlobalMemory textmem(GetClipboardData(CF_UNICODETEXT));
202
+ const wchar_t* text = (const wchar_t*) textmem.lock();
203
+ if (text)
204
+ clipboard.set_text(to_lf(String(text, wcslen(text))).c_str());
205
+
206
+ return clipboard;
207
+ }
208
+
209
+
210
+ }// Reflex
@@ -0,0 +1,82 @@
1
+ #include "../color_picker.h"
2
+
3
+
4
+ #include <xot/windows.h>
5
+ #include <commdlg.h>
6
+ #include "reflex/exception.h"
7
+ #include "window.h"
8
+
9
+
10
+ namespace Reflex
11
+ {
12
+
13
+
14
+ // the custom color slots of the dialog live as long as the process
15
+ static COLORREF custom_colors[16] =
16
+ {
17
+ RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255),
18
+ RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255),
19
+ RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255),
20
+ RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255), RGB(255, 255, 255)
21
+ };
22
+
23
+
24
+ static BYTE
25
+ to_byte (float value)
26
+ {
27
+ if (value < 0) value = 0;
28
+ if (value > 1) value = 1;
29
+ return (BYTE) (value * 255 + 0.5f);
30
+ }
31
+
32
+ static COLORREF
33
+ to_colorref (const Color& color)
34
+ {
35
+ return RGB(to_byte(color.red), to_byte(color.green), to_byte(color.blue));
36
+ }
37
+
38
+ static Color
39
+ to_color (COLORREF colorref)
40
+ {
41
+ return Color(
42
+ GetRValue(colorref) / 255.f,
43
+ GetGValue(colorref) / 255.f,
44
+ GetBValue(colorref) / 255.f);
45
+ }
46
+
47
+ void
48
+ ColorPicker_show (ColorPicker* ppicker, const Color* initial)
49
+ {
50
+ if (!ppicker)
51
+ argument_error(__FILE__, __LINE__);
52
+
53
+ ColorPicker::Ref picker = ppicker;
54
+
55
+ Window* owner = picker->owner();
56
+ CHOOSECOLORW cc = {0};
57
+ cc.lStructSize = sizeof(cc);
58
+ cc.hwndOwner = owner ? Window_get_hwnd(owner) : NULL;
59
+ cc.lpCustColors = custom_colors;
60
+ cc.Flags = CC_FULLOPEN | CC_ANYCOLOR;
61
+ if (initial)
62
+ {
63
+ cc.rgbResult = to_colorref(*initial);
64
+ cc.Flags |= CC_RGBINIT;
65
+ }
66
+
67
+ // the dialog has no alpha, so the picked color always has alpha 1
68
+ BOOL picked = ChooseColorW(&cc);// runs a modal loop
69
+ if (picked)
70
+ {
71
+ ColorEvent e(to_color(cc.rgbResult));
72
+ ColorPicker_call_color_event(picker, &e);
73
+ }
74
+ else if (CommDlgExtendedError() != 0)
75
+ system_error(__FILE__, __LINE__);
76
+
77
+ Event e;
78
+ ColorPicker_call_close_event(picker, &e);
79
+ }
80
+
81
+
82
+ }// Reflex