wxruby3 0.9.3 → 0.9.5

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/INSTALL.md +1 -1
  3. data/README.md +2 -2
  4. data/ext/wxruby3/include/wxruby-ComboPopup.h +777 -0
  5. data/ext/wxruby3/include/wxruby-Config.h +23 -5
  6. data/ext/wxruby3/include/wxruby-Persistence.h +79 -0
  7. data/ext/wxruby3/swig/memory_management.i +6 -0
  8. data/lib/wx/core/book_ctrl_base.rb +16 -0
  9. data/lib/wx/core/combo_ctrl.rb +171 -0
  10. data/lib/wx/core/config.rb +454 -83
  11. data/lib/wx/core/notebook.rb +10 -8
  12. data/lib/wx/core/peristent_object.rb +15 -0
  13. data/lib/wx/core/persistence_manager.rb +39 -0
  14. data/lib/wx/core/persistent_window.rb +16 -0
  15. data/lib/wx/core/top_level_window.rb +16 -0
  16. data/lib/wx/core/treebook.rb +18 -0
  17. data/lib/wx/core.rb +4 -0
  18. data/lib/wx/doc/book_ctrl_base.rb +19 -0
  19. data/lib/wx/doc/comboctrl.rb +128 -3
  20. data/lib/wx/doc/config.rb +101 -41
  21. data/lib/wx/doc/extra/14_config.md +101 -0
  22. data/lib/wx/doc/extra/15_persistence.md +148 -0
  23. data/lib/wx/doc/owner_drawn_combobox.rb +5 -1
  24. data/lib/wx/doc/persistence_manager.rb +36 -0
  25. data/lib/wx/doc/persistent_object.rb +27 -0
  26. data/lib/wx/doc/top_level_window.rb +19 -0
  27. data/lib/wx/doc/treebook.rb +6 -1
  28. data/lib/wx/version.rb +1 -1
  29. data/rakelib/build.rb +1 -1
  30. data/rakelib/lib/core/include/funcall.inc +2 -1
  31. data/rakelib/lib/core/package.rb +22 -1
  32. data/rakelib/lib/core/spec.rb +10 -0
  33. data/rakelib/lib/core/spec_helper.rb +1 -1
  34. data/rakelib/lib/director/comboctrl.rb +104 -3
  35. data/rakelib/lib/director/config_base.rb +490 -19
  36. data/rakelib/lib/director/defs.rb +1 -3
  37. data/rakelib/lib/director/event_filter.rb +1 -1
  38. data/rakelib/lib/director/event_loop.rb +1 -1
  39. data/rakelib/lib/director/file_dialog_customize_hook.rb +2 -2
  40. data/rakelib/lib/director/gdicommon.rb +6 -0
  41. data/rakelib/lib/director/grid_cell_attr.rb +1 -1
  42. data/rakelib/lib/director/grid_cell_editor.rb +1 -1
  43. data/rakelib/lib/director/grid_cell_renderer.rb +1 -1
  44. data/rakelib/lib/director/header_ctrl.rb +3 -0
  45. data/rakelib/lib/director/html_listbox.rb +2 -1
  46. data/rakelib/lib/director/menu_item.rb +1 -1
  47. data/rakelib/lib/director/num_validator.rb +5 -7
  48. data/rakelib/lib/director/owner_drawn_combobox.rb +1 -0
  49. data/rakelib/lib/director/persistence_manager.rb +410 -0
  50. data/rakelib/lib/director/persistent_object.rb +70 -0
  51. data/rakelib/lib/director/persistent_window.rb +73 -0
  52. data/rakelib/lib/director/pgeditor.rb +1 -1
  53. data/rakelib/lib/director/pgproperties.rb +3 -3
  54. data/rakelib/lib/director/pgproperty.rb +5 -1
  55. data/rakelib/lib/director/richtext_style_listbox.rb +5 -0
  56. data/rakelib/lib/director/sizer.rb +1 -1
  57. data/rakelib/lib/director/static_bitmap.rb +4 -0
  58. data/rakelib/lib/director/text_entry.rb +1 -1
  59. data/rakelib/lib/director/window.rb +4 -0
  60. data/rakelib/lib/extractor/module.rb +15 -0
  61. data/rakelib/lib/generate/analyzer.rb +43 -43
  62. data/rakelib/lib/generate/doc/combo_ctrl.yaml +135 -0
  63. data/rakelib/lib/generate/doc/file_dialog_customize_hook.yaml +62 -0
  64. data/rakelib/lib/generate/doc/file_system.yaml +28 -0
  65. data/rakelib/lib/generate/doc.rb +1 -1
  66. data/rakelib/lib/generate/interface.rb +12 -4
  67. data/rakelib/lib/specs/interfaces.rb +3 -0
  68. data/rakelib/lib/swig_runner.rb +7 -4
  69. data/rakelib/lib/typemap/combo_popup.rb +42 -0
  70. data/rakelib/lib/typemap/config.rb +8 -0
  71. data/samples/widgets/widgets.rb +5 -9
  72. data/tests/test_combo_ctrl.rb +196 -0
  73. data/tests/test_config.rb +207 -42
  74. data/tests/test_persistence.rb +142 -0
  75. metadata +26 -2
@@ -17,9 +17,22 @@ module WXRuby3
17
17
  spec.items.clear
18
18
  spec.add_header_code <<~__HEREDOC
19
19
  #include "wxruby-Config.h"
20
+ #include <limits>
20
21
 
21
22
  static const char * __iv_ConfigBase_sc_config = "@config";
22
23
 
24
+ static WxRuby_ID s_use_hash_config_id("use_hash_config");
25
+
26
+ static void
27
+ _free_config_wx(void* cfg)
28
+ {
29
+ if (cfg)
30
+ {
31
+ wxConfigBase* config = (wxConfigBase*)cfg;
32
+ delete config;
33
+ }
34
+ }
35
+
23
36
  static VALUE config_base_get(int argc, VALUE *argv, VALUE self)
24
37
  {
25
38
  bool autoCreate = true;
@@ -30,34 +43,110 @@ module WXRuby3
30
43
  rb_raise(rb_eArgError, "Expected a single boolean argument");
31
44
  return Qnil;
32
45
  }
33
- autoCreate = !(argv[0] == Qfalse || argv[0] == Qnil);
46
+ autoCreate = !(argv[0] == Qfalse || argv[0] == Qnil); // test truthy-ness
34
47
  }
35
48
 
49
+ // get global ConfigBase instance from Ruby instance variable of ConfigBase singleton class
36
50
  VALUE cConfigBase_Singleton = rb_funcall(g_cConfigBase, rb_intern("singleton_class"), 0, 0);
37
51
  VALUE curConfig = rb_iv_get(cConfigBase_Singleton, __iv_ConfigBase_sc_config);
38
- // create new config instance if none exists and autoCreate is true
39
- if (NIL_P(curConfig) && autoCreate)
52
+
53
+ if (NIL_P(curConfig))
40
54
  {
41
- // create new ConfigBase instance
42
- curConfig = rb_class_new_instance(0, 0, g_cConfig);
43
- // set global wxConfigBase instance to a new Ruby Config wrapper
44
- wxConfigBase::Set(wxRuby_Ruby2ConfigBase(curConfig));
45
- // store global ConfigBase instance as Ruby instance variable of ConfigBase singleton class
46
- // (keeps it safe from GC)
47
- VALUE cConfigBase_Singleton = rb_funcall(g_cConfigBase, rb_intern("singleton_class"), 0, 0);
48
- rb_iv_set(cConfigBase_Singleton, __iv_ConfigBase_sc_config, curConfig);
49
- }
55
+ wxConfigBase* cfg = wxConfigBase::Get(autoCreate);
56
+ if (cfg)
57
+ {
58
+ // wrap the C++ config object
59
+ curConfig = Data_Wrap_Struct(g_cConfigWx, 0, 0, cfg);
60
+ // store global ConfigBase instance as Ruby instance variable of ConfigBase singleton class
61
+ rb_iv_set(cConfigBase_Singleton, __iv_ConfigBase_sc_config, curConfig);
62
+ }
63
+ }
50
64
  return curConfig;
51
65
  }
52
66
 
53
67
  static VALUE config_base_create(int argc, VALUE *argv, VALUE self)
54
68
  {
69
+ bool forced_create = false;
70
+ bool use_hash = false;
55
71
  if (argc>0)
56
72
  {
57
- rb_raise(rb_eArgError, "No arguments allowed.");
58
- return Qnil;
73
+ if (argc>2)
74
+ {
75
+ rb_raise(rb_eArgError, "Unexpected number of arguments.");
76
+ return Qnil;
77
+ }
78
+ if (argc>1 && TYPE(argv[1]) != T_HASH)
79
+ {
80
+ rb_raise(rb_eArgError, "Expected kwargs for 2.");
81
+ return Qnil;
82
+ }
83
+ if ((argc==1 && TYPE(argv[0]) != T_HASH) || argc>1)
84
+ {
85
+ VALUE rb_forced_create = argc==1 ? argv[0] : argv[1];
86
+ forced_create = !(rb_forced_create == Qfalse || rb_forced_create == Qnil); // test truthy-ness
87
+ }
88
+ if (TYPE(argv[argc-1]) == T_HASH)
89
+ {
90
+ VALUE rb_hash = argv[argc-1];
91
+ int hsz = RHASH_SIZE(rb_hash);
92
+ if (hsz>1 || (hsz==1 &&!rb_hash_includes(rb_hash, ID2SYM(s_use_hash_config_id()))))
93
+ {
94
+ rb_raise(rb_eArgError, "Unexpected keyword argument. Only :use_hash_config allowed.");
95
+ return Qnil;
96
+ }
97
+
98
+ VALUE rb_use_hash = rb_hash_aref(rb_hash, ID2SYM(s_use_hash_config_id()));
99
+ use_hash = !(rb_use_hash == Qfalse || rb_use_hash == Qnil); // test truthy-ness
100
+ }
101
+ }
102
+
103
+ VALUE curConfig = Qnil;
104
+
105
+ // get singleton class
106
+ VALUE cConfigBase_Singleton = rb_funcall(g_cConfigBase, rb_intern("singleton_class"), 0, 0);
107
+
108
+ // Any existing C++ global instance known? (do not auto-create if not)
109
+ wxConfigBase* config = wxConfigBase::Get(false);
110
+ if (config == nullptr || forced_create)
111
+ {
112
+ if (use_hash)
113
+ {
114
+ // create new Wx::Config instance
115
+ curConfig = rb_class_new_instance(0, 0, g_cConfig);
116
+ // set global wxConfigBase instance to a new Ruby Config wrapper
117
+ wxConfigBase::Set(wxRuby_Ruby2ConfigBase(curConfig));
118
+ }
119
+ else
120
+ {
121
+ if (config) wxConfigBase::Set(nullptr); // reset
122
+ wxConfigBase* new_cfg = wxConfigBase::Create(); // create new C++ instance
123
+ // wrap the C++ config object
124
+ curConfig = Data_Wrap_Struct(g_cConfigWx, 0, 0, new_cfg);
125
+ }
126
+ // store global ConfigBase instance as Ruby instance variable of ConfigBase singleton class
127
+ // (keeps it safe from GC)
128
+ rb_iv_set(cConfigBase_Singleton, __iv_ConfigBase_sc_config, curConfig);
129
+ if (config)
130
+ {
131
+ // clean up; destroy any previous config instance
132
+ delete config;
133
+ }
134
+ }
135
+ else
136
+ {
137
+ // check if this instance was already wrapped
138
+ curConfig = rb_iv_get(cConfigBase_Singleton, __iv_ConfigBase_sc_config);
139
+ if (NIL_P(curConfig))
140
+ {
141
+ // no global Ruby instance known so can't be wrapped yet (must be C++ instance than)
142
+ // wrap the C++ config object
143
+ curConfig = Data_Wrap_Struct(g_cConfigWx, 0, 0, config);
144
+ // store global ConfigBase instance as Ruby instance variable of ConfigBase singleton class
145
+ // (keeps it safe from GC)
146
+ rb_iv_set(cConfigBase_Singleton, __iv_ConfigBase_sc_config, curConfig);
147
+ }
59
148
  }
60
- return config_base_get(0, 0, self);
149
+ return curConfig;
61
150
  }
62
151
 
63
152
  static VALUE config_base_set(int argc, VALUE *argv, VALUE self)
@@ -82,15 +171,376 @@ module WXRuby3
82
171
  VALUE cConfigBase_Singleton = rb_funcall(g_cConfigBase, rb_intern("singleton_class"), 0, 0);
83
172
  VALUE curConfig = rb_iv_get(cConfigBase_Singleton, __iv_ConfigBase_sc_config);
84
173
  // set new config instance (could be nil)
85
- if (!NIL_P(newCfg))
174
+ // set global wxConfigBase instance to a (new) Ruby Hash wrapper (or nullptr)
175
+ wxConfigBase::Set(wxRuby_Ruby2ConfigBase(newCfg));
176
+ rb_iv_set(cConfigBase_Singleton, __iv_ConfigBase_sc_config, newCfg);
177
+
178
+ // check curConfig type
179
+ if (!NIL_P(curConfig) && rb_obj_is_kind_of(curConfig, g_cConfigWx) != Qtrue)
86
180
  {
87
- // set global wxConfigBase instance to a (new) Ruby Hash wrapper
88
- wxConfigBase::Set(wxRuby_Ruby2ConfigBase(newCfg));
181
+ // need to make config Ruby owned to it gets proper GC handling
182
+ // and the C++ allocated config instance gets destroyed
183
+ RDATA(curConfig)->dfree = _free_config_wx;
89
184
  }
90
- rb_iv_set(cConfigBase_Singleton, __iv_ConfigBase_sc_config, newCfg);
91
185
 
92
186
  return curConfig; // return old config (if any)
93
187
  }
188
+
189
+ static WxRuby_ID to_f_id("to_f");
190
+ static WxRuby_ID to_i_id("to_i");
191
+ static WxRuby_ID to_s_id("to_s");
192
+
193
+ #ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
194
+ #define PO_LONG wxLongLong_t
195
+ #define PO_NUM2LONG(n) NUM2LL(n)
196
+ #define PO_LONG2NUM(l) LL2NUM(l)
197
+ #else
198
+ #define PO_LONG long
199
+ #define PO_NUM2LONG(n) NUM2LONG(n)
200
+ #define PO_LONG2NUM(l) LONG2NUM(l)
201
+ #endif
202
+
203
+ static VALUE config_wx_read(int argc, VALUE *argv, VALUE self)
204
+ {
205
+ wxConfigBase *cfg;
206
+ Data_Get_Struct(self, wxConfigBase, cfg);
207
+
208
+ if (argc < 1 || argc > 1)
209
+ {
210
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)", argc);
211
+ }
212
+ wxString key = RSTR_TO_WXSTR(argv[0]);
213
+ wxConfigBase::EntryType vtype = cfg->GetEntryType(key);
214
+ switch(vtype)
215
+ {
216
+ case wxConfigBase::Type_Boolean:
217
+ {
218
+ bool v = false;
219
+ if (cfg->Read(key, &v))
220
+ {
221
+ return v ? Qtrue : Qfalse;
222
+ }
223
+ break;
224
+ }
225
+ case wxConfigBase::Type_Integer:
226
+ {
227
+ PO_LONG v = 0;
228
+ if (cfg->Read(key, &v))
229
+ {
230
+ return PO_LONG2NUM(v);
231
+ }
232
+ break;
233
+ }
234
+ case wxConfigBase::Type_Float:
235
+ {
236
+ double v = 0.0;
237
+ if (cfg->Read(key, &v))
238
+ {
239
+ return DBL2NUM(v);
240
+ }
241
+ break;
242
+ }
243
+ case wxConfigBase::Type_String:
244
+ {
245
+ wxString v;
246
+ if (cfg->Read(key, &v))
247
+ {
248
+ return WXSTR_TO_RSTR(v);
249
+ }
250
+ break;
251
+ }
252
+ default:
253
+ break;
254
+ }
255
+ return Qnil;
256
+ }
257
+
258
+ static VALUE config_wx_write(int argc, VALUE *argv, VALUE self)
259
+ {
260
+ wxConfigBase *cfg;
261
+ Data_Get_Struct(self, wxConfigBase, cfg);
262
+
263
+ if (argc < 2 || argc > 2)
264
+ {
265
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc);
266
+ }
267
+ wxString key = RSTR_TO_WXSTR(argv[0]);
268
+ VALUE value = argv[1];
269
+ bool rc = false;
270
+ switch(TYPE(value))
271
+ {
272
+ case T_TRUE:
273
+ case T_FALSE:
274
+ {
275
+ int32_t v = (value == Qtrue ? 1 : 0);
276
+ rc = cfg->Write(key, v);
277
+ break;
278
+ }
279
+
280
+ case T_FIXNUM:
281
+ {
282
+ PO_LONG v = PO_NUM2LONG(value);
283
+ if (v > std::numeric_limits<int32_t>::max())
284
+ { rc = cfg->Write(key, PO_NUM2LONG(value)); }
285
+ else
286
+ { rc = cfg->Write(key, static_cast<int32_t> (v)); }
287
+ break;
288
+ }
289
+
290
+ case T_BIGNUM:
291
+ {
292
+ VALUE sval = rb_funcall(value, to_s_id(), 0);
293
+ rc = cfg->Write(key, RSTR_TO_WXSTR(sval));
294
+ }
295
+ break;
296
+
297
+ case T_FLOAT:
298
+ rc = cfg->Write(key, NUM2DBL(value));
299
+ break;
300
+
301
+ case T_STRING:
302
+ rc = cfg->Write(key, RSTR_TO_WXSTR(value));
303
+ break;
304
+
305
+ default:
306
+ if (rb_respond_to(value, to_i_id()))
307
+ {
308
+ VALUE ival = rb_funcall(value, to_i_id(), 0);
309
+ rc = cfg->Write(key, PO_NUM2LONG(ival));
310
+ }
311
+ else if (rb_respond_to(value, to_f_id()))
312
+ {
313
+ VALUE fval = rb_funcall(value, to_f_id(), 0);
314
+ rc = cfg->Write(key, NUM2DBL(fval));
315
+ }
316
+ else
317
+ {
318
+ VALUE sval = rb_funcall(value, to_s_id(), 0);
319
+ rc = cfg->Write(key, RSTR_TO_WXSTR(sval));
320
+ }
321
+ break;
322
+ }
323
+ return rc ? Qtrue : Qfalse;
324
+ }
325
+
326
+ static VALUE config_wx_for_path(int argc, VALUE *argv, VALUE self)
327
+ {
328
+ wxConfigBase *cfg;
329
+ Data_Get_Struct(self, wxConfigBase, cfg);
330
+
331
+ if (argc < 1 || argc > 1)
332
+ {
333
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
334
+ }
335
+ wxString name = RSTR_TO_WXSTR(argv[0]);
336
+ wxConfigPathChanger path(cfg, name);
337
+ VALUE rc = Qnil;
338
+ if (rb_block_given_p ())
339
+ {
340
+ VALUE key = WXSTR_TO_RSTR(path.Name());
341
+ rc = rb_yield_values(2, self, key);
342
+ }
343
+ return rc;
344
+ }
345
+
346
+ static VALUE config_wx_delete(int argc, VALUE *argv, VALUE self)
347
+ {
348
+ wxConfigBase *cfg;
349
+ Data_Get_Struct(self, wxConfigBase, cfg);
350
+
351
+ if (argc < 1 || argc > 1)
352
+ {
353
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
354
+ }
355
+ wxString key = RSTR_TO_WXSTR(argv[0]);
356
+ VALUE rc = Qfalse;
357
+ if (cfg->HasGroup(key))
358
+ {
359
+ rc = cfg->DeleteGroup(key) ? Qtrue : Qfalse;
360
+ }
361
+ else if (cfg->HasEntry(key))
362
+ {
363
+ rc = cfg->DeleteEntry(key) ? Qtrue : Qfalse;
364
+ }
365
+ return rc;
366
+ }
367
+
368
+ static VALUE config_wx_rename(int argc, VALUE *argv, VALUE self)
369
+ {
370
+ wxConfigBase *cfg;
371
+ Data_Get_Struct(self, wxConfigBase, cfg);
372
+
373
+ if (argc < 2 || argc > 2)
374
+ {
375
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 2)", argc);
376
+ }
377
+ wxString key = RSTR_TO_WXSTR(argv[0]);
378
+ wxString newKey = RSTR_TO_WXSTR(argv[1]);
379
+ VALUE rc = Qfalse;
380
+ if (cfg->HasGroup(key))
381
+ {
382
+ rc = cfg->RenameGroup(key, newKey) ? Qtrue : Qfalse;
383
+ }
384
+ else
385
+ {
386
+ rc = cfg->RenameEntry(key, newKey) ? Qtrue : Qfalse;
387
+ }
388
+ return rc;
389
+ }
390
+
391
+ static VALUE config_wx_each_entry(int argc, VALUE *argv, VALUE self)
392
+ {
393
+ wxConfigBase *cfg;
394
+ Data_Get_Struct(self, wxConfigBase, cfg);
395
+
396
+ if (argc < 0 || argc > 0)
397
+ {
398
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 0)", argc);
399
+ }
400
+ wxString key;
401
+ long index = 0;
402
+ VALUE rc = Qnil;
403
+ if (rb_block_given_p())
404
+ {
405
+ if (cfg->GetFirstEntry(key, index))
406
+ {
407
+ do {
408
+ VALUE rb_key = WXSTR_TO_RSTR(key);
409
+ rc = rb_yield(rb_key);
410
+ } while (cfg->GetNextEntry(key, index));
411
+ }
412
+ }
413
+ return rc;
414
+ }
415
+
416
+ static VALUE config_wx_each_group(int argc, VALUE *argv, VALUE self)
417
+ {
418
+ wxConfigBase *cfg;
419
+ Data_Get_Struct(self, wxConfigBase, cfg);
420
+
421
+ if (argc < 0 || argc > 0)
422
+ {
423
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 0)", argc);
424
+ }
425
+ wxString key;
426
+ long index = 0;
427
+ VALUE rc = Qnil;
428
+ if (rb_block_given_p())
429
+ {
430
+ if (cfg->GetFirstGroup(key, index))
431
+ {
432
+ do {
433
+ VALUE rb_key = WXSTR_TO_RSTR(key);
434
+ rc = rb_yield(rb_key);
435
+ } while (cfg->GetNextGroup(key, index));
436
+ }
437
+ }
438
+ return rc;
439
+ }
440
+
441
+ static VALUE config_wx_number_of_entries(int argc, VALUE *argv, VALUE self)
442
+ {
443
+ wxConfigBase *cfg;
444
+ Data_Get_Struct(self, wxConfigBase, cfg);
445
+
446
+ if (argc < 0 || argc > 2)
447
+ {
448
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
449
+ }
450
+ bool recurse = argc>0 ? (argv[0] != Qfalse && argv[0] != Qnil) : false;
451
+ size_t n = cfg->GetNumberOfEntries(recurse);
452
+ return LONG2NUM(n);
453
+ }
454
+
455
+ static VALUE config_wx_number_of_groups(int argc, VALUE *argv, VALUE self)
456
+ {
457
+ wxConfigBase *cfg;
458
+ Data_Get_Struct(self, wxConfigBase, cfg);
459
+
460
+ if (argc < 0 || argc > 2)
461
+ {
462
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
463
+ }
464
+ bool recurse = argc>0 ? (argv[0] != Qfalse && argv[0] != Qnil) : false;
465
+ size_t n = cfg->GetNumberOfGroups(recurse);
466
+ return LONG2NUM(n);
467
+ }
468
+
469
+ static VALUE config_wx_has_entry(int argc, VALUE *argv, VALUE self)
470
+ {
471
+ wxConfigBase *cfg;
472
+ Data_Get_Struct(self, wxConfigBase, cfg);
473
+
474
+ if (argc < 1 || argc > 1)
475
+ {
476
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)", argc);
477
+ }
478
+ wxString path = RSTR_TO_WXSTR(argv[0]);
479
+ return cfg->HasEntry(path) ? Qtrue : Qfalse;
480
+ }
481
+
482
+ static VALUE config_wx_has_group(int argc, VALUE *argv, VALUE self)
483
+ {
484
+ wxConfigBase *cfg;
485
+ Data_Get_Struct(self, wxConfigBase, cfg);
486
+
487
+ if (argc < 1 || argc > 1)
488
+ {
489
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
490
+ }
491
+ wxString path = RSTR_TO_WXSTR(argv[0]);
492
+ return cfg->HasGroup(path) ? Qtrue : Qfalse;
493
+ }
494
+
495
+ static VALUE config_wx_path(int argc, VALUE *argv, VALUE self)
496
+ {
497
+ wxConfigBase *cfg;
498
+ Data_Get_Struct(self, wxConfigBase, cfg);
499
+
500
+ if (argc < 0 || argc > 2)
501
+ {
502
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
503
+ }
504
+ return WXSTR_TO_RSTR(cfg->GetPath());
505
+ }
506
+
507
+ static VALUE config_wx_clear(int argc, VALUE *argv, VALUE self)
508
+ {
509
+ wxConfigBase *cfg;
510
+ Data_Get_Struct(self, wxConfigBase, cfg);
511
+
512
+ if (argc < 0 || argc > 2)
513
+ {
514
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
515
+ }
516
+ return cfg->DeleteAll() ? Qtrue : Qfalse;
517
+ }
518
+
519
+ static VALUE config_wx_is_expanding_env_vars(int argc, VALUE *argv, VALUE self)
520
+ {
521
+ wxConfigBase *cfg;
522
+ Data_Get_Struct(self, wxConfigBase, cfg);
523
+
524
+ if (argc != 0)
525
+ {
526
+ rb_raise(rb_eArgError, "No arguments expected");
527
+ }
528
+ return cfg->IsExpandingEnvVars() ? Qtrue : Qfalse;
529
+ }
530
+
531
+ static VALUE config_wx_set_expand_env_vars(int argc, VALUE *argv, VALUE self)
532
+ {
533
+ wxConfigBase *cfg;
534
+ Data_Get_Struct(self, wxConfigBase, cfg);
535
+
536
+ if (argc < 1 || argc > 1)
537
+ {
538
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
539
+ }
540
+ bool expand = (argv[0] != Qfalse && argv[0] != Qnil);
541
+ cfg->SetExpandEnvVars(expand);
542
+ return Qnil;
543
+ }
94
544
  __HEREDOC
95
545
  spec.add_wrapper_code <<~__HEREDOC
96
546
  SWIGINTERN void
@@ -99,6 +549,7 @@ module WXRuby3
99
549
  if (cfg)
100
550
  {
101
551
  wxRbHashConfig* config = (wxRbHashConfig*)cfg;
552
+ config->ResetRubyConfig();
102
553
  delete config;
103
554
  }
104
555
  }
@@ -123,6 +574,26 @@ module WXRuby3
123
574
  rb_define_module_function(g_cConfigBase, "get", VALUEFUNC(config_base_get), -1);
124
575
  rb_define_module_function(g_cConfigBase, "set", VALUEFUNC(config_base_set), -1);
125
576
 
577
+ g_cConfigWx = rb_define_class_under(mWxCore, "ConfigWx", g_cConfigBase);
578
+ rb_undef_alloc_func(g_cConfigWx);
579
+ rb_define_protected_method(g_cConfigWx, "read_entry", VALUEFUNC(config_wx_read), -1);
580
+ rb_define_protected_method(g_cConfigWx, "write_entry", VALUEFUNC(config_wx_write), -1);
581
+ rb_define_method(g_cConfigWx, "for_path", VALUEFUNC(config_wx_for_path), -1);
582
+ rb_define_method(g_cConfigWx, "each_entry", VALUEFUNC(config_wx_each_entry), -1);
583
+ rb_define_method(g_cConfigWx, "each_group", VALUEFUNC(config_wx_each_group), -1);
584
+ rb_define_method(g_cConfigWx, "number_of_entries", VALUEFUNC(config_wx_number_of_entries), -1);
585
+ rb_define_method(g_cConfigWx, "number_of_groups", VALUEFUNC(config_wx_number_of_groups), -1);
586
+ rb_define_method(g_cConfigWx, "has_entry?", VALUEFUNC(config_wx_has_entry), -1);
587
+ rb_define_method(g_cConfigWx, "has_group?", VALUEFUNC(config_wx_has_group), -1);
588
+ rb_define_method(g_cConfigWx, "delete", VALUEFUNC(config_wx_delete), -1);
589
+ rb_define_method(g_cConfigWx, "rename", VALUEFUNC(config_wx_rename), -1);
590
+ rb_define_method(g_cConfigWx, "path", VALUEFUNC(config_wx_path), -1);
591
+ rb_define_method(g_cConfigWx, "clear", VALUEFUNC(config_wx_clear), -1);
592
+ rb_define_method(g_cConfigWx, "is_expanding_env_vars", VALUEFUNC(config_wx_is_expanding_env_vars), -1);
593
+ rb_define_alias(g_cConfigWx, "expanding_env_vars?", "is_expanding_env_vars");
594
+ rb_define_method(g_cConfigWx, "set_expand_env_vars", VALUEFUNC(config_wx_set_expand_env_vars), -1);
595
+ rb_define_alias(g_cConfigWx, "expand_env_vars=", "set_expand_env_vars");
596
+
126
597
  g_cConfig = rb_define_class_under(mWxCore, "Config", g_cConfigBase);
127
598
  rb_define_alloc_func(g_cConfig, config_allocate);
128
599
  __HEREDOC
@@ -32,9 +32,7 @@ module WXRuby3
32
32
  wxDELETEA
33
33
  wxSwap
34
34
  }
35
- if Config.instance.wx_version >= '3.3.0'
36
- spec.ignore 'wxOVERRIDE'
37
- end
35
+ spec.ignore 'wxOVERRIDE'
38
36
  super
39
37
  end
40
38
 
@@ -14,7 +14,7 @@ module WXRuby3
14
14
 
15
15
  def setup
16
16
  super
17
- spec.gc_as_untracked # no tracking
17
+ spec.gc_as_marked # not tracked but cached in Ruby
18
18
  end
19
19
  end # class EventFilter
20
20
 
@@ -15,7 +15,7 @@ module WXRuby3
15
15
  def setup
16
16
  super
17
17
  spec.items << 'wxEventLoopBase'
18
- spec.gc_as_untracked
18
+ spec.gc_as_marked # untracked but never disowned in Ruby
19
19
  spec.disable_proxies
20
20
  spec.make_concrete 'wxGUIEventLoop'
21
21
  spec.fold_bases 'wxGUIEventLoop' => 'wxEventLoopBase'
@@ -17,8 +17,8 @@ module WXRuby3
17
17
  def setup
18
18
  super
19
19
  spec.items << 'wxFileDialogCustomize'
20
- spec.gc_as_untracked 'wxFileDialogCustomizeHook'
21
- spec.gc_never 'wxFileDialogCustomize'
20
+ spec.gc_as_marked 'wxFileDialogCustomizeHook' # not tracked but cached in Ruby
21
+ spec.gc_as_untracked 'wxFileDialogCustomize'
22
22
  spec.make_abstract 'wxFileDialogCustomize'
23
23
  end
24
24
  end # class FileDialogCustomizeHook
@@ -49,6 +49,12 @@ module WXRuby3
49
49
  'wxRect::Intersect(const wxRect &)',
50
50
  'wxRect::Union(const wxRect &)'
51
51
  ]
52
+ if Config.instance.wx_version >= '3.3.0'
53
+ # ignore these as they are supposed to specify unary minus but confuse
54
+ # SWIG
55
+ spec.ignore 'wxPoint::operator-(const wxPoint&)',
56
+ 'wxRealPoint::operator-(const wxRealPoint&)'
57
+ end
52
58
  spec.regard 'wxRect::Offset', regard_doc: false
53
59
  # overrule common wxPoint mapping for wxRect ctor to fix ctor ambiguities here wrt wxSize
54
60
  spec.map 'const wxPoint& topLeft', 'const wxPoint& bottomRight', as: 'Wx::Point' do
@@ -17,7 +17,7 @@ module WXRuby3
17
17
  # exposing the mixin wxClientDataContainer/wxSharedClientDataContainer has no real upside
18
18
  # for wxRuby; far easier to just use member variables in derived classes
19
19
  spec.override_inheritance_chain('wxGridCellAttr', [])
20
- spec.gc_as_untracked('wxGridCellAttr')
20
+ spec.gc_as_marked('wxGridCellAttr') # tailored tracking
21
21
  # use custom free func to be able to account for more complex inheritance
22
22
  spec.add_header_code <<~__HEREDOC
23
23
  static void GC_free_GridCellAttr(void *ptr)
@@ -14,7 +14,7 @@ module WXRuby3
14
14
 
15
15
  def setup
16
16
  super
17
- spec.gc_as_untracked
17
+ spec.gc_as_marked # tailored tracking method
18
18
  # use custom free func to be able to account for more complex inheritance
19
19
  spec.add_header_code 'extern void GC_free_GridCellEditor(void *ptr);'
20
20
  spec.add_swig_code '%feature("freefunc") wxGridCellEditor "GC_free_GridCellEditor";'
@@ -14,7 +14,7 @@ module WXRuby3
14
14
 
15
15
  def setup
16
16
  super
17
- spec.gc_as_untracked
17
+ spec.gc_as_marked # tailored tracking
18
18
  # use custom free func to be able to account for more complex inheritance
19
19
  spec.add_header_code 'extern void GC_free_GridCellRenderer(void *ptr);'
20
20
  spec.add_swig_code '%feature("freefunc") wxGridCellRenderer "GC_free_GridCellRenderer";'
@@ -17,6 +17,7 @@ module WXRuby3
17
17
  def setup
18
18
  super
19
19
  spec.items << 'wxHeaderColumn' << 'wxHeaderCtrlSimple' << 'wxSettableHeaderColumn' << 'wxHeaderColumnSimple'
20
+ spec.gc_as_marked 'wxHeaderColumn', 'wxSettableHeaderColumn', 'wxHeaderColumnSimple'
20
21
  spec.regard 'wxHeaderCtrl::GetColumn',
21
22
  'wxHeaderCtrl::UpdateColumnVisibility',
22
23
  'wxHeaderCtrl::UpdateColumnsOrder',
@@ -25,6 +26,8 @@ module WXRuby3
25
26
  spec.regard 'wxHeaderCtrlSimple::GetBestFittingWidth'
26
27
  spec.extend_interface 'wxHeaderCtrlSimple',
27
28
  'virtual const wxHeaderColumn& GetColumn(unsigned int idx) const',
29
+ 'virtual void UpdateColumnVisibility(unsigned int idx, bool show)',
30
+ 'virtual void UpdateColumnsOrder(const wxArrayInt& order)',
28
31
  visibility: 'protected'
29
32
  # handled; can be suppressed
30
33
  spec.suppress_warning(473, 'wxHeaderCtrl::GetColumn', 'wxHeaderCtrlSimple::GetColumn')
@@ -95,7 +95,8 @@ module WXRuby3
95
95
  'wxItemContainer::SetClientData',
96
96
  'wxItemContainer::HasClientUntypedData',
97
97
  'wxItemContainer::Clear'])
98
- spec.ignore([ 'wxItemContainer::Append(const wxArrayString &, wxClientData **)',
98
+ spec.ignore([ 'wxItemContainer::DetachClientObject',
99
+ 'wxItemContainer::Append(const wxArrayString &, wxClientData **)',
99
100
  'wxItemContainer::Insert(const wxArrayString &, unsigned int, wxClientData **)',
100
101
  'wxItemContainer::Set(const wxArrayString &, wxClientData **)'], ignore_doc: false)
101
102
  # for doc only