comparison dw.hpp @ 2882:99311a9091af

C++: Add lambda support via Connect functions on C++11, on older compilers use traditional function pointers instead. Also added inital menu support although it is incomplete as of this commit.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Thu, 22 Dec 2022 13:59:46 +0000
parents 2ba0959eb3cf
children 06e475feaac0
comparison
equal deleted inserted replaced
2881:ac404083dc6b 2882:99311a9091af
7 #define _HPP_DW 7 #define _HPP_DW
8 #include <dw.h> 8 #include <dw.h>
9 9
10 // Attempt to support compilers without nullptr type literal 10 // Attempt to support compilers without nullptr type literal
11 #if __cplusplus >= 201103L 11 #if __cplusplus >= 201103L
12 #define DW_CPP11
12 #define DW_NULL nullptr 13 #define DW_NULL nullptr
14 #include <functional>
13 #else 15 #else
14 #define DW_NULL NULL 16 #define DW_NULL NULL
15 #endif 17 #endif
16 18
17 // Attempt to allow compilation on GCC older than 4.7 19 // Attempt to allow compilation on GCC older than 4.7
19 #define override 21 #define override
20 #endif 22 #endif
21 23
22 namespace DW 24 namespace DW
23 { 25 {
26
27 // Forward declare these so they can be referenced
28 class Render;
29 class Pixmap;
30 class MenuItem;
31
24 32
25 // Base handle class which allows opaque access to 33 // Base handle class which allows opaque access to
26 // The base system handles 34 // The base system handles
27 class Handle 35 class Handle
28 { 36 {
103 111
104 // TODO: Find a way to implement this cross platform... 112 // TODO: Find a way to implement this cross platform...
105 // That way we can skip adding unused signal handlers 113 // That way we can skip adding unused signal handlers
106 #define IsOverridden(a, b) true 114 #define IsOverridden(a, b) true
107 115
116 // Base class for several types of widgets including buttons and menu items
117 class Clickable : virtual public Widget
118 {
119 private:
120 bool ClickedConnected;
121 #ifdef DW_CPP11
122 std::function<int()> _ConnectClicked;
123 #else
124 int (*_ConnectClicked)();
125 #endif
126 static int _OnClicked(HWND window, void *data) {
127 if(reinterpret_cast<Clickable *>(data)->_ConnectClicked)
128 return reinterpret_cast<Clickable *>(data)->_ConnectClicked();
129 return reinterpret_cast<Clickable *>(data)->OnClicked(); }
130 protected:
131 void Setup() {
132 if(IsOverridden(Clickable::OnClicked, this)) {
133 dw_signal_connect(hwnd, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_OnClicked), this);
134 ClickedConnected = true;
135 }
136 }
137 // Our signal handler functions to be overriden...
138 // If they are not overridden and an event is generated, remove the unused handler
139 virtual int OnClicked() {
140 dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_CLICKED);
141 ClickedConnected = false;
142 return FALSE;
143 }
144 public:
145 #ifdef DW_CPP11
146 void ConnectClicked(std::function<int()> userfunc)
147 #else
148 void ConnectClicked(int (*userfunc)())
149 #endif
150 {
151 _ConnectClicked = userfunc;
152 if(!ClickedConnected) {
153 dw_signal_connect(hwnd, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_OnClicked), this);
154 ClickedConnected = true;
155 }
156 }
157 };
158
159 class Menus : public Handle
160 {
161 protected:
162 void SetHMENUI(HMENUI newmenu) {
163 menu = newmenu;
164 SetHandle(reinterpret_cast<void *>(newmenu));
165 }
166 HMENUI menu;
167 public:
168 // User functions
169 HMENUI GetHMENUI() { return menu; }
170 };
171
172 class Menu : public Menus
173 {
174 public:
175 // Constructors
176 Menu(HWND location) { SetHMENUI(dw_menubar_new(location)); }
177 Menu(unsigned long id) { SetHMENUI(dw_menu_new(id)); }
178 Menu() { SetHMENUI(dw_menu_new(0)); }
179 };
180
181 class MenuItem : public Clickable
182 {
183 public:
184 // Constructors
185 MenuItem(Menus *menu, const char *title, unsigned long id, unsigned long flags, int end, int check, Menus *submenu) {
186 SetHWND(dw_menu_append_item(menu->GetHMENUI(), title, id, flags, end, check, submenu ? submenu->GetHMENUI() : DW_NULL));
187 }
188
189 // User functions
190 void SetState(unsigned long flags) { dw_window_set_style(hwnd, flags, flags); }
191 void SetStyle(unsigned long flags, unsigned long mask) { dw_window_set_style(hwnd, flags, mask); }
192 };
193
108 // Top-level window class is packable 194 // Top-level window class is packable
109 class Window : public Boxes 195 class Window : public Boxes
110 { 196 {
111 private: 197 private:
198 bool DeleteConnected, ConfigureConnected;
199 #ifdef DW_CPP11
200 std::function<int()> _ConnectDelete;
201 std::function<int(int, int)> _ConnectConfigure;
202 #else
203 int (*_ConnectDelete)();
204 int (*_ConnectConfigure)(int width, int height);
205 #endif
112 void Setup() { 206 void Setup() {
113 if(IsOverridden(Window::OnDelete, this)) 207 if(IsOverridden(Window::OnDelete, this)) {
114 dw_signal_connect(hwnd, DW_SIGNAL_DELETE, DW_SIGNAL_FUNC(_OnDelete), this); 208 dw_signal_connect(hwnd, DW_SIGNAL_DELETE, DW_SIGNAL_FUNC(_OnDelete), this);
115 if(IsOverridden(Window::OnConfigure, this)) 209 DeleteConnected = true;
210 }
211 if(IsOverridden(Window::OnConfigure, this)) {
116 dw_signal_connect(hwnd, DW_SIGNAL_CONFIGURE, DW_SIGNAL_FUNC(_OnConfigure), this); 212 dw_signal_connect(hwnd, DW_SIGNAL_CONFIGURE, DW_SIGNAL_FUNC(_OnConfigure), this);
117 } 213 ConfigureConnected = true;
118 static int _OnDelete(HWND window, void *data) { return reinterpret_cast<Window *>(data)->OnDelete(); } 214 }
119 static int _OnConfigure(HWND window, int width, int height, void *data) { return reinterpret_cast<Window *>(data)->OnConfigure(width, height); } 215 }
216 static int _OnDelete(HWND window, void *data) {
217 if(reinterpret_cast<Window *>(data)->_ConnectDelete)
218 return reinterpret_cast<Window *>(data)->_ConnectDelete();
219 return reinterpret_cast<Window *>(data)->OnDelete(); }
220 static int _OnConfigure(HWND window, int width, int height, void *data) {
221 if(reinterpret_cast<Window *>(data)->_ConnectConfigure)
222 return reinterpret_cast<Window *>(data)->_ConnectConfigure(width, height);
223 return reinterpret_cast<Window *>(data)->OnConfigure(width, height); }
224 Menu *menu;
120 public: 225 public:
121 // Constructors 226 // Constructors
122 Window(HWND owner, const char *title, unsigned long style) { SetHWND(dw_window_new(owner, title, style)); Setup(); } 227 Window(HWND owner, const char *title, unsigned long style) { SetHWND(dw_window_new(owner, title, style)); Setup(); }
123 Window(const char *title, unsigned long style) { SetHWND(dw_window_new(HWND_DESKTOP, title, style)); Setup(); } 228 Window(const char *title, unsigned long style) { SetHWND(dw_window_new(HWND_DESKTOP, title, style)); Setup(); }
124 Window(unsigned long style) { SetHWND(dw_window_new(HWND_DESKTOP, "", style)); Setup(); } 229 Window(unsigned long style) { SetHWND(dw_window_new(HWND_DESKTOP, "", style)); Setup(); }
138 int Raise() { return dw_window_raise(hwnd); } 243 int Raise() { return dw_window_raise(hwnd); }
139 int Lower() { return dw_window_lower(hwnd); } 244 int Lower() { return dw_window_lower(hwnd); }
140 void Redraw() { dw_window_redraw(hwnd); } 245 void Redraw() { dw_window_redraw(hwnd); }
141 void Default(Widget *defaultitem) { if(defaultitem) dw_window_default(hwnd, defaultitem->GetHWND()); } 246 void Default(Widget *defaultitem) { if(defaultitem) dw_window_default(hwnd, defaultitem->GetHWND()); }
142 void SetIcon(HICN icon) { dw_window_set_icon(hwnd, icon); } 247 void SetIcon(HICN icon) { dw_window_set_icon(hwnd, icon); }
248 Menu *MenuBar() { if(menu == DW_NULL) menu = new Menu(hwnd); return menu; }
249 #ifdef DW_CPP11
250 void ConnectDelete(std::function<int()> userfunc)
251 #else
252 void ConnectDelete(int (*userfunc)())
253 #endif
254 {
255 _ConnectDelete = userfunc;
256 if(!DeleteConnected) {
257 dw_signal_connect(hwnd, DW_SIGNAL_DELETE, DW_SIGNAL_FUNC(_OnDelete), this);
258 DeleteConnected = true;
259 }
260 }
261 #ifdef DW_CPP11
262 void ConnectConfigure(std::function<int(int, int)> userfunc)
263 #else
264 void ConnectConfigure(int (*userfunc)(int, int))
265 #endif
266 {
267 _ConnectConfigure = userfunc;
268 if(!ConfigureConnected) {
269 dw_signal_connect(hwnd, DW_SIGNAL_CONFIGURE, DW_SIGNAL_FUNC(_OnConfigure), this);
270 ConfigureConnected = true;
271 }
272 }
143 protected: 273 protected:
144 // Our signal handler functions to be overriden... 274 // Our signal handler functions to be overriden...
145 // If they are not overridden and an event is generated, remove the unused handler 275 // If they are not overridden and an event is generated, remove the unused handler
146 virtual int OnDelete() { dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_DELETE); return FALSE; } 276 virtual int OnDelete() {
147 virtual int OnConfigure(int width, int height) { dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_CONFIGURE); return FALSE; }; 277 dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_DELETE);
278 DeleteConnected = false;
279 return FALSE;
280 }
281 virtual int OnConfigure(int width, int height) {
282 dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_CONFIGURE);
283 ConfigureConnected = false;
284 return FALSE;
285 };
148 }; 286 };
149 287
150 // Class for focusable widgets 288 // Class for focusable widgets
151 class Focusable : virtual public Widget 289 class Focusable : virtual public Widget
152 { 290 {
154 void Enable() { dw_window_enable(hwnd); } 292 void Enable() { dw_window_enable(hwnd); }
155 void Disable() { dw_window_disable(hwnd); } 293 void Disable() { dw_window_disable(hwnd); }
156 void SetFocus() { dw_window_set_focus(hwnd); } 294 void SetFocus() { dw_window_set_focus(hwnd); }
157 }; 295 };
158 296
159 // Base class for several types of buttons
160 class Buttons : virtual public Focusable
161 {
162 private:
163 static int _OnClicked(HWND window, void *data) { return reinterpret_cast<Buttons *>(data)->OnClicked(); }
164 protected:
165 void Setup() {
166 if(IsOverridden(Buttons::OnClicked, this))
167 dw_signal_connect(hwnd, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_OnClicked), this);
168 }
169 // Our signal handler functions to be overriden...
170 // If they are not overridden and an event is generated, remove the unused handler
171 virtual int OnClicked() { dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_CLICKED); return FALSE; }
172 };
173
174 // Text based button 297 // Text based button
175 class TextButton : public Buttons 298 class TextButton : public Clickable, public Focusable
176 { 299 {
177 public: 300 public:
178 // User functions 301 // User functions
179 void SetText(const char *text) { dw_window_set_text(hwnd, text); } 302 void SetText(const char *text) { dw_window_set_text(hwnd, text); }
180 char *GetText() { return dw_window_get_text(hwnd); } 303 char *GetText() { return dw_window_get_text(hwnd); }
189 Button(const char *text) { SetHWND(dw_button_new(text, 0)); Setup(); } 312 Button(const char *text) { SetHWND(dw_button_new(text, 0)); Setup(); }
190 Button() { SetHWND(dw_button_new("", 0)); Setup(); } 313 Button() { SetHWND(dw_button_new("", 0)); Setup(); }
191 }; 314 };
192 315
193 // Image based button 316 // Image based button
194 class BitmapButton : public Buttons 317 class BitmapButton : public Clickable, public Focusable
195 { 318 {
196 public: 319 public:
197 // Constructors 320 // Constructors
198 BitmapButton(const char *text, unsigned long id) { SetHWND(dw_bitmapbutton_new(text, id)); Setup(); } 321 BitmapButton(const char *text, unsigned long id) { SetHWND(dw_bitmapbutton_new(text, id)); Setup(); }
199 BitmapButton(unsigned long id) { SetHWND(dw_bitmapbutton_new("", id)); Setup(); } 322 BitmapButton(unsigned long id) { SetHWND(dw_bitmapbutton_new("", id)); Setup(); }
290 // User functions 413 // User functions
291 void GetData(unsigned int *year, unsigned int *month, unsigned int *day) { dw_calendar_get_date(hwnd, year, month, day); } 414 void GetData(unsigned int *year, unsigned int *month, unsigned int *day) { dw_calendar_get_date(hwnd, year, month, day); }
292 void SetData(unsigned int year, unsigned int month, unsigned int day) { dw_calendar_set_date(hwnd, year, month, day); } 415 void SetData(unsigned int year, unsigned int month, unsigned int day) { dw_calendar_set_date(hwnd, year, month, day); }
293 }; 416 };
294 417
295
296 // Forward declare these so our Drawable abstract class can reference
297 class Render;
298 class Pixmap;
299 418
300 // Abstract class that defines drawing, either to screen or picture (pixmap) 419 // Abstract class that defines drawing, either to screen or picture (pixmap)
301 class Drawable 420 class Drawable
302 { 421 {
303 public: 422 public:
317 }; 436 };
318 437
319 class Render : public Drawable, public Widget 438 class Render : public Drawable, public Widget
320 { 439 {
321 private: 440 private:
441 bool ExposeConnected, ConfigureConnected;
442 #ifdef DW_CPP11
443 std::function<int(DWExpose *)> _ConnectExpose;
444 std::function<int(int, int)> _ConnectConfigure;
445 #else
446 int (*_ConnectExpose)(DWExpose *);
447 int (*_ConnectConfigure)(int width, int height);
448 #endif
322 void Setup() { 449 void Setup() {
323 if(IsOverridden(Render::OnExpose, this)) 450 if(IsOverridden(Render::OnExpose, this)) {
324 dw_signal_connect(hwnd, DW_SIGNAL_EXPOSE, DW_SIGNAL_FUNC(_OnExpose), this); 451 dw_signal_connect(hwnd, DW_SIGNAL_EXPOSE, DW_SIGNAL_FUNC(_OnExpose), this);
325 if(IsOverridden(Render::OnConfigure, this)) 452 ExposeConnected = true;
453 }
454 if(IsOverridden(Render::OnConfigure, this)) {
326 dw_signal_connect(hwnd, DW_SIGNAL_CONFIGURE, DW_SIGNAL_FUNC(_OnConfigure), this); 455 dw_signal_connect(hwnd, DW_SIGNAL_CONFIGURE, DW_SIGNAL_FUNC(_OnConfigure), this);
327 } 456 ConfigureConnected = true;
328 static int _OnExpose(HWND window, DWExpose *exp, void *data) { return reinterpret_cast<Render *>(data)->OnExpose(exp); } 457 }
329 static int _OnConfigure(HWND window, int width, int height, void *data) { return reinterpret_cast<Render *>(data)->OnConfigure(width, height); } 458 }
459 static int _OnExpose(HWND window, DWExpose *exp, void *data) {
460 if(reinterpret_cast<Render *>(data)->_ConnectExpose)
461 return reinterpret_cast<Render *>(data)->_ConnectExpose(exp);
462 return reinterpret_cast<Render *>(data)->OnExpose(exp); }
463 static int _OnConfigure(HWND window, int width, int height, void *data) {
464 if(reinterpret_cast<Render *>(data)->_ConnectConfigure)
465 return reinterpret_cast<Render *>(data)->_ConnectConfigure(width, height);
466 return reinterpret_cast<Render *>(data)->OnConfigure(width, height); }
330 public: 467 public:
331 // Constructors 468 // Constructors
332 Render(unsigned long id) { SetHWND(dw_render_new(id)); Setup(); } 469 Render(unsigned long id) { SetHWND(dw_render_new(id)); Setup(); }
333 Render() { SetHWND(dw_render_new(0)); Setup(); } 470 Render() { SetHWND(dw_render_new(0)); Setup(); }
334 471
349 void BitBlt(int xdest, int ydest, int width, int height, Pixmap *src, int xsrc, int ysrc); 486 void BitBlt(int xdest, int ydest, int width, int height, Pixmap *src, int xsrc, int ysrc);
350 int SetFont(const char *fontname) { return dw_window_set_font(hwnd, fontname); } 487 int SetFont(const char *fontname) { return dw_window_set_font(hwnd, fontname); }
351 void GetTextExtents(const char *text, int *width, int *height) { dw_font_text_extents_get(hwnd, DW_NULL, text, width, height); } 488 void GetTextExtents(const char *text, int *width, int *height) { dw_font_text_extents_get(hwnd, DW_NULL, text, width, height); }
352 char *GetFont() { return dw_window_get_font(hwnd); } 489 char *GetFont() { return dw_window_get_font(hwnd); }
353 void Redraw() { dw_render_redraw(hwnd); } 490 void Redraw() { dw_render_redraw(hwnd); }
491 #ifdef DW_CPP11
492 void ConnectExpose(std::function<int(DWExpose *)> userfunc)
493 #else
494 void ConnectExpose(int (*userfunc)(DWExpose *))
495 #endif
496 {
497 _ConnectExpose = userfunc;
498 if(!ExposeConnected) {
499 dw_signal_connect(hwnd, DW_SIGNAL_EXPOSE, DW_SIGNAL_FUNC(_OnExpose), this);
500 ExposeConnected = true;
501 }
502 }
503 #ifdef DW_CPP11
504 void ConnectConfigure(std::function<int(int, int)> userfunc)
505 #else
506 void ConnectConfigure(int (*userfunc)(int, int))
507 #endif
508 {
509 _ConnectConfigure = userfunc;
510 if(!ConfigureConnected) {
511 dw_signal_connect(hwnd, DW_SIGNAL_CONFIGURE, DW_SIGNAL_FUNC(_OnConfigure), this);
512 ConfigureConnected = true;
513 }
514 }
354 protected: 515 protected:
355 // Our signal handler functions to be overriden... 516 // Our signal handler functions to be overriden...
356 // If they are not overridden and an event is generated, remove the unused handler 517 // If they are not overridden and an event is generated, remove the unused handler
357 virtual int OnExpose(DWExpose *exp) { dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_EXPOSE); return FALSE; } 518 virtual int OnExpose(DWExpose *exp) {
358 virtual int OnConfigure(int width, int height) { dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_CONFIGURE); return FALSE; }; 519 dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_EXPOSE);
520 ExposeConnected = false;
521 return FALSE;
522 }
523 virtual int OnConfigure(int width, int height) {
524 dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_CONFIGURE);
525 ConfigureConnected = false;
526 return FALSE;
527 };
359 }; 528 };
360 529
361 class Pixmap : public Drawable, public Handle 530 class Pixmap : public Drawable, public Handle
362 { 531 {
363 private: 532 private:
408 577
409 // Class for the HTML rendering widget 578 // Class for the HTML rendering widget
410 class HTML : public Widget 579 class HTML : public Widget
411 { 580 {
412 private: 581 private:
582 bool ChangedConnected, ResultConnected;
583 #ifdef DW_CPP11
584 std::function<int(int, char *)> _ConnectChanged;
585 std::function<int(int, char *, void *)> _ConnectResult;
586 #else
587 int (*_ConnectChanged)(int status, char *url);
588 int (*_ConnectResult)(int status, char *result, void *scriptdata);
589 #endif
413 void Setup() { 590 void Setup() {
414 if(IsOverridden(HTML::OnChanged, this)) 591 if(IsOverridden(HTML::OnChanged, this)) {
415 dw_signal_connect(hwnd, DW_SIGNAL_HTML_CHANGED, DW_SIGNAL_FUNC(_OnChanged), this); 592 dw_signal_connect(hwnd, DW_SIGNAL_HTML_CHANGED, DW_SIGNAL_FUNC(_OnChanged), this);
416 if(IsOverridden(HTML::OnResult, this)) 593 ChangedConnected = true;
594 }
595 if(IsOverridden(HTML::OnResult, this)) {
417 dw_signal_connect(hwnd, DW_SIGNAL_HTML_CHANGED, DW_SIGNAL_FUNC(_OnResult), this); 596 dw_signal_connect(hwnd, DW_SIGNAL_HTML_CHANGED, DW_SIGNAL_FUNC(_OnResult), this);
418 } 597 ResultConnected = true;
419 static int _OnChanged(HWND window, int status, char *url, void *data) { return reinterpret_cast<HTML *>(data)->OnChanged(status, url); } 598 }
420 static int _OnResult(HWND window, int status, char *result, void *scriptdata, void *data) { return reinterpret_cast<HTML *>(data)->OnResult(status, result, scriptdata); } 599 }
600 static int _OnChanged(HWND window, int status, char *url, void *data) {
601 if(reinterpret_cast<HTML *>(data)->_ConnectChanged)
602 return reinterpret_cast<HTML *>(data)->_ConnectChanged(status, url);
603 return reinterpret_cast<HTML *>(data)->OnChanged(status, url); }
604 static int _OnResult(HWND window, int status, char *result, void *scriptdata, void *data) {
605 if(reinterpret_cast<HTML *>(data)->_ConnectResult)
606 return reinterpret_cast<HTML *>(data)->_ConnectResult(status, result, scriptdata);
607 return reinterpret_cast<HTML *>(data)->OnResult(status, result, scriptdata); }
421 public: 608 public:
422 // Constructors 609 // Constructors
423 HTML(unsigned long id) { SetHWND(dw_html_new(id)); Setup(); } 610 HTML(unsigned long id) { SetHWND(dw_html_new(id)); Setup(); }
424 HTML() { SetHWND(dw_html_new(0)); Setup(); } 611 HTML() { SetHWND(dw_html_new(0)); Setup(); }
425 612
426 // User functions 613 // User functions
427 void Action(int action) { dw_html_action(hwnd, action); } 614 void Action(int action) { dw_html_action(hwnd, action); }
428 int JavascriptRun(const char *script, void *scriptdata) { return dw_html_javascript_run(hwnd, script, scriptdata); } 615 int JavascriptRun(const char *script, void *scriptdata) { return dw_html_javascript_run(hwnd, script, scriptdata); }
429 int Raw(const char *buffer) { return dw_html_raw(hwnd, buffer); } 616 int Raw(const char *buffer) { return dw_html_raw(hwnd, buffer); }
430 int URL(const char *url) { return dw_html_url(hwnd, url); } 617 int URL(const char *url) { return dw_html_url(hwnd, url); }
618 #ifdef DW_CPP11
619 void ConnectChanged(std::function<int(int, char *)> userfunc)
620 #else
621 void ConnectChanged(int (*userfunc)(int, char *))
622 #endif
623 {
624 _ConnectChanged = userfunc;
625 if(!ChangedConnected) {
626 dw_signal_connect(hwnd, DW_SIGNAL_HTML_CHANGED, DW_SIGNAL_FUNC(_OnChanged), this);
627 ChangedConnected = true;
628 }
629 }
630 #ifdef DW_CPP11
631 void ConnectResult(std::function<int(int, char *, void *)> userfunc)
632 #else
633 void ConnectResult(int (*userfunc)(int, char *, void *))
634 #endif
635 {
636 _ConnectResult = userfunc;
637 if(!ResultConnected) {
638 dw_signal_connect(hwnd, DW_SIGNAL_HTML_CHANGED, DW_SIGNAL_FUNC(_OnResult), this);
639 ResultConnected = true;
640 }
641 }
431 protected: 642 protected:
432 // Our signal handler functions to be overriden... 643 // Our signal handler functions to be overriden...
433 // If they are not overridden and an event is generated, remove the unused handler 644 // If they are not overridden and an event is generated, remove the unused handler
434 virtual int OnChanged(int status, char *url) { dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_HTML_CHANGED); return FALSE; } 645 virtual int OnChanged(int status, char *url) {
435 virtual int OnResult(int status, char *result, void *scriptdata) { dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_HTML_RESULT); return FALSE; }; 646 dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_HTML_CHANGED);
647 ChangedConnected = false;
648 return FALSE;
649 }
650 virtual int OnResult(int status, char *result, void *scriptdata) {
651 dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_HTML_RESULT);
652 ResultConnected = false;
653 return FALSE;
654 };
436 }; 655 };
437 656
438 // Base class for several widgets that allow text entry 657 // Base class for several widgets that allow text entry
439 class TextEntry : virtual public Focusable, virtual public TextWidget 658 class TextEntry : virtual public Focusable, virtual public TextWidget
440 { 659 {
465 684
466 // Base class for several widgets that have a list of elements 685 // Base class for several widgets that have a list of elements
467 class ListBoxes : virtual public Focusable 686 class ListBoxes : virtual public Focusable
468 { 687 {
469 private: 688 private:
689 bool ListSelectConnected;
690 #ifdef DW_CPP11
691 std::function<int(int)> _ConnectListSelect;
692 #else
693 int (*_ConnectListSelect)(int index);
694 #endif
470 void Setup() { 695 void Setup() {
471 if(IsOverridden(ListBoxes::OnListSelect, this)) 696 if(IsOverridden(ListBoxes::OnListSelect, this)) {
472 dw_signal_connect(hwnd, DW_SIGNAL_LIST_SELECT, DW_SIGNAL_FUNC(_OnListSelect), this); 697 dw_signal_connect(hwnd, DW_SIGNAL_LIST_SELECT, DW_SIGNAL_FUNC(_OnListSelect), this);
473 } 698 ListSelectConnected = true;
474 static int _OnListSelect(HWND window, int index, void *data) { return reinterpret_cast<ListBoxes *>(data)->OnListSelect(index); } 699 }
700 }
701 static int _OnListSelect(HWND window, int index, void *data) {
702 if(reinterpret_cast<ListBoxes *>(data)->_ConnectListSelect)
703 return reinterpret_cast<ListBoxes *>(data)->_ConnectListSelect(index);
704 return reinterpret_cast<ListBoxes *>(data)->OnListSelect(index);
705 }
475 public: 706 public:
476 // User functions 707 // User functions
477 void Append(const char *text) { dw_listbox_append(hwnd, text); } 708 void Append(const char *text) { dw_listbox_append(hwnd, text); }
478 void Clear() { dw_listbox_clear(hwnd); } 709 void Clear() { dw_listbox_clear(hwnd); }
479 int Count() { return dw_listbox_count(hwnd); } 710 int Count() { return dw_listbox_count(hwnd); }
484 void ListAppend(char **text, int count) { dw_listbox_list_append(hwnd, text, count); } 715 void ListAppend(char **text, int count) { dw_listbox_list_append(hwnd, text, count); }
485 void Select(int index, int state) { dw_listbox_select(hwnd, index, state); } 716 void Select(int index, int state) { dw_listbox_select(hwnd, index, state); }
486 int Selected() { return dw_listbox_selected(hwnd); } 717 int Selected() { return dw_listbox_selected(hwnd); }
487 int Selected(int where) { return dw_listbox_selected_multi(hwnd, where); } 718 int Selected(int where) { return dw_listbox_selected_multi(hwnd, where); }
488 void SetTop(int top) { dw_listbox_set_top(hwnd, top); } 719 void SetTop(int top) { dw_listbox_set_top(hwnd, top); }
720 #ifdef DW_CPP11
721 void ConnectListSelect(std::function<int(int)> userfunc)
722 #else
723 void ConnectListSelect(int (*userfunc)(int))
724 #endif
725 {
726 _ConnectListSelect = userfunc;
727 if(!ListSelectConnected) {
728 dw_signal_connect(hwnd, DW_SIGNAL_LIST_SELECT, DW_SIGNAL_FUNC(_OnListSelect), this);
729 ListSelectConnected = true;
730 }
731 }
489 protected: 732 protected:
490 // Our signal handler functions to be overriden... 733 // Our signal handler functions to be overriden...
491 // If they are not overridden and an event is generated, remove the unused handler 734 // If they are not overridden and an event is generated, remove the unused handler
492 virtual int OnListSelect(int index) { dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_LIST_SELECT); return FALSE; } 735 virtual int OnListSelect(int index) {
736 dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_LIST_SELECT);
737 ListSelectConnected = false;
738 return FALSE;
739 }
493 }; 740 };
494 741
495 class Combobox : public TextEntry, public ListBoxes 742 class Combobox : public TextEntry, public ListBoxes
496 { 743 {
497 public: 744 public:
514 761
515 // Base class for several ranged type widgets 762 // Base class for several ranged type widgets
516 class Ranged : virtual public Widget 763 class Ranged : virtual public Widget
517 { 764 {
518 private: 765 private:
519 static int _OnValueChanged(HWND window, int value, void *data) { return reinterpret_cast<Ranged *>(data)->OnValueChanged(value); } 766 bool ValueChangedConnected;
767 #ifdef DW_CPP11
768 std::function<int(int)> _ConnectValueChanged;
769 #else
770 int (*_ConnectValueChanged)(int value);
771 #endif
772 static int _OnValueChanged(HWND window, int value, void *data) {
773 if(reinterpret_cast<Ranged *>(data)->_ConnectValueChanged)
774 return reinterpret_cast<Ranged *>(data)->_ConnectValueChanged(value);
775 return reinterpret_cast<Ranged *>(data)->OnValueChanged(value);
776 }
520 protected: 777 protected:
521 void Setup() { 778 void Setup() {
522 if(IsOverridden(Ranged::OnValueChanged, this)) 779 if(IsOverridden(Ranged::OnValueChanged, this)) {
523 dw_signal_connect(hwnd, DW_SIGNAL_VALUE_CHANGED, DW_SIGNAL_FUNC(_OnValueChanged), this); 780 dw_signal_connect(hwnd, DW_SIGNAL_VALUE_CHANGED, DW_SIGNAL_FUNC(_OnValueChanged), this);
781 ValueChangedConnected = true;
782 }
524 } 783 }
525 // Our signal handler functions to be overriden... 784 // Our signal handler functions to be overriden...
526 // If they are not overridden and an event is generated, remove the unused handler 785 // If they are not overridden and an event is generated, remove the unused handler
527 virtual int OnValueChanged(int value) { dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_VALUE_CHANGED); return FALSE; } 786 virtual int OnValueChanged(int value) {
787 dw_signal_disconnect_by_name(hwnd, DW_SIGNAL_VALUE_CHANGED);
788 ValueChangedConnected = false;
789 return FALSE;
790 }
791 public:
792 #ifdef DW_CPP11
793 void ConnectValueChanged(std::function<int(int)> userfunc)
794 #else
795 void ConnectValueChanged(int (*userfunc)(int))
796 #endif
797 {
798 _ConnectValueChanged = userfunc;
799 if(!ValueChangedConnected) {
800 dw_signal_connect(hwnd, DW_SIGNAL_VALUE_CHANGED, DW_SIGNAL_FUNC(_OnValueChanged), this);
801 ValueChangedConnected = true;
802 }
803 }
528 }; 804 };
529 805
530 class Slider : public Ranged 806 class Slider : public Ranged
531 { 807 {
532 public: 808 public:
596 protected: 872 protected:
597 App() { } 873 App() { }
598 static App *_app; 874 static App *_app;
599 public: 875 public:
600 // Allow the code to compile if handicapped on older compilers 876 // Allow the code to compile if handicapped on older compilers
601 #if __cplusplus >= 201103L 877 #ifdef DW_CPP11
602 // Singletons should not be cloneable. 878 // Singletons should not be cloneable.
603 App(App &other) = delete; 879 App(App &other) = delete;
604 // Singletons should not be assignable. 880 // Singletons should not be assignable.
605 void operator=(const App &) = delete; 881 void operator=(const App &) = delete;
606 #endif 882 #endif
610 static App *Init(const char *appid, const char *appname) { if(!_app) { _app = new App(); dw_app_id_set(appid, appname); dw_init(TRUE, 0, DW_NULL); } return _app; } 886 static App *Init(const char *appid, const char *appname) { if(!_app) { _app = new App(); dw_app_id_set(appid, appname); dw_init(TRUE, 0, DW_NULL); } return _app; }
611 static App *Init(int argc, char *argv[]) { if(!_app) { _app = new App(); dw_init(TRUE, argc, argv); } return _app; } 887 static App *Init(int argc, char *argv[]) { if(!_app) { _app = new App(); dw_init(TRUE, argc, argv); } return _app; }
612 static App *Init(int argc, char *argv[], const char *appid) { if(!_app) { _app = new App(); dw_app_id_set(appid, DW_NULL); dw_init(TRUE, argc, argv); } return _app; } 888 static App *Init(int argc, char *argv[], const char *appid) { if(!_app) { _app = new App(); dw_app_id_set(appid, DW_NULL); dw_init(TRUE, argc, argv); } return _app; }
613 static App *Init(int argc, char *argv[], const char *appid, const char *appname) { if(!_app) { _app = new App(); dw_app_id_set(appid, appname); dw_init(TRUE, argc, argv); } return _app; } 889 static App *Init(int argc, char *argv[], const char *appid, const char *appname) { if(!_app) { _app = new App(); dw_app_id_set(appid, appname); dw_init(TRUE, argc, argv); } return _app; }
614 890
891 // User functions
615 void Main() { dw_main(); } 892 void Main() { dw_main(); }
616 void MainIteration() { dw_main_iteration(); } 893 void MainIteration() { dw_main_iteration(); }
617 void MainQuit() { dw_main_quit(); } 894 void MainQuit() { dw_main_quit(); }
618 void Exit(int exitcode) { dw_exit(exitcode); } 895 void Exit(int exitcode) { dw_exit(exitcode); }
896 int MessageBox(const char *title, int flags, const char *format) { return dw_messagebox(title, flags, format); }
619 }; 897 };
620 898
621 // Static singleton reference declared outside of the class 899 // Static singleton reference declared outside of the class
622 App* App::_app = DW_NULL; 900 App* App::_app = DW_NULL;
623 901