wxruby3 0.9.3 → 0.9.4

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/ext/wxruby3/include/wxruby-Config.h +23 -5
  3. data/ext/wxruby3/include/wxruby-Persistence.h +79 -0
  4. data/ext/wxruby3/swig/memory_management.i +6 -0
  5. data/lib/wx/core/book_ctrl_base.rb +16 -0
  6. data/lib/wx/core/config.rb +454 -83
  7. data/lib/wx/core/notebook.rb +10 -8
  8. data/lib/wx/core/peristent_object.rb +15 -0
  9. data/lib/wx/core/persistence_manager.rb +39 -0
  10. data/lib/wx/core/persistent_window.rb +16 -0
  11. data/lib/wx/core/top_level_window.rb +16 -0
  12. data/lib/wx/core/treebook.rb +18 -0
  13. data/lib/wx/core.rb +4 -0
  14. data/lib/wx/doc/book_ctrl_base.rb +19 -0
  15. data/lib/wx/doc/config.rb +101 -41
  16. data/lib/wx/doc/extra/14_config.md +101 -0
  17. data/lib/wx/doc/extra/15_persistence.md +148 -0
  18. data/lib/wx/doc/persistence_manager.rb +36 -0
  19. data/lib/wx/doc/persistent_object.rb +27 -0
  20. data/lib/wx/doc/top_level_window.rb +19 -0
  21. data/lib/wx/doc/treebook.rb +6 -1
  22. data/lib/wx/version.rb +1 -1
  23. data/rakelib/build.rb +1 -1
  24. data/rakelib/lib/core/package.rb +22 -1
  25. data/rakelib/lib/core/spec.rb +10 -0
  26. data/rakelib/lib/core/spec_helper.rb +1 -1
  27. data/rakelib/lib/director/config_base.rb +490 -19
  28. data/rakelib/lib/director/event_filter.rb +1 -1
  29. data/rakelib/lib/director/event_loop.rb +1 -1
  30. data/rakelib/lib/director/file_dialog_customize_hook.rb +2 -2
  31. data/rakelib/lib/director/grid_cell_attr.rb +1 -1
  32. data/rakelib/lib/director/grid_cell_editor.rb +1 -1
  33. data/rakelib/lib/director/grid_cell_renderer.rb +1 -1
  34. data/rakelib/lib/director/header_ctrl.rb +3 -0
  35. data/rakelib/lib/director/html_listbox.rb +2 -1
  36. data/rakelib/lib/director/persistence_manager.rb +410 -0
  37. data/rakelib/lib/director/persistent_object.rb +70 -0
  38. data/rakelib/lib/director/persistent_window.rb +73 -0
  39. data/rakelib/lib/director/static_bitmap.rb +4 -0
  40. data/rakelib/lib/director/text_entry.rb +1 -1
  41. data/rakelib/lib/generate/analyzer.rb +43 -43
  42. data/rakelib/lib/generate/doc.rb +1 -1
  43. data/rakelib/lib/specs/interfaces.rb +3 -0
  44. data/rakelib/lib/typemap/config.rb +8 -0
  45. data/samples/widgets/widgets.rb +5 -9
  46. data/tests/test_config.rb +207 -42
  47. data/tests/test_persistence.rb +142 -0
  48. metadata +19 -2
@@ -0,0 +1,410 @@
1
+ # Copyright (c) 2023 M.J.N. Corino, The Netherlands
2
+ #
3
+ # This software is released under the MIT license.
4
+
5
+ ###
6
+ # wxRuby3 wxWidgets interface director
7
+ ###
8
+
9
+ module WXRuby3
10
+
11
+ class Director
12
+
13
+ class PersistenceManager < Director
14
+
15
+ include Typemap::ConfigBase
16
+
17
+ def setup
18
+ super
19
+ spec.gc_as_marked
20
+ spec.use_class_implementation 'wxPersistenceManager', 'WxRubyPersistenceManager'
21
+ spec.ignore 'wxPersistenceManager::Register',
22
+ 'wxPersistenceManager::Find',
23
+ 'wxPersistenceManager::Unregister',
24
+ 'wxPersistenceManager::Save',
25
+ 'wxPersistenceManager::Restore',
26
+ 'wxPersistenceManager::SaveAndUnregister',
27
+ 'wxPersistenceManager::RegisterAndRestore',
28
+ ignore_doc: false
29
+ # doc gen only
30
+ spec.map 'void *obj' => 'Object', swig: false do
31
+ map_in code: ''
32
+ end
33
+ spec.map 'T *obj' => 'Object', swig: false do
34
+ map_in code: ''
35
+ end
36
+ spec.regard 'wxPersistenceManager::wxPersistenceManager',
37
+ 'wxPersistenceManager::GetConfig',
38
+ 'wxPersistenceManager::GetKey'
39
+ spec.suppress_warning 473, 'wxPersistenceManager::GetConfig'
40
+ spec.ignore %w[wxCreatePersistentObject wxPersistentRegisterAndRestore]
41
+ spec.add_header_code <<~__HEREDOC
42
+ #include "wxruby-Persistence.h"
43
+
44
+ // default global wxRuby persistence manager
45
+ static WxRubyPersistenceManager s_wxruby_persistence_manager {};
46
+
47
+ static WxRuby_ID to_f_id("to_f");
48
+ static WxRuby_ID to_i_id("to_i");
49
+ static WxRuby_ID to_s_id("to_s");
50
+ static WxRuby_ID save_value_id("save_value");
51
+ static WxRuby_ID restore_value_id("save_value");
52
+ static WxRuby_ID create_po_id("create_persistent_object");
53
+
54
+ #ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
55
+ #define PO_LONG wxLongLong_t
56
+ #define PO_NUM2LONG(n) NUM2LL(n)
57
+ #define PO_LONG2NUM(l) LL2NUM(l)
58
+ #else
59
+ #define PO_LONG long
60
+ #define PO_NUM2LONG(n) NUM2LONG(n)
61
+ #define PO_LONG2NUM(l) LONG2NUM(l)
62
+ #endif
63
+
64
+ bool WxRubyPersistenceManager::SaveRubyValue(const wxPersistentObject& who, const wxString& name, VALUE value)
65
+ {
66
+ Swig::Director* dir = dynamic_cast<Swig::Director*> (this);
67
+ // is this a user defined Ruby persistence manager with overridden #save_value?
68
+ if (dir && !wxRuby_IsNativeMethod(dir->swig_get_self(), save_value_id()))
69
+ {
70
+ VALUE rb_who = SWIG_NewPointerObj(SWIG_as_voidptr(&who), SWIGTYPE_p_wxPersistentObject, 0 );
71
+ return wxRuby_Funcall(dir->swig_get_self(), save_value_id(), 3, rb_who, WXSTR_TO_RSTR(name), value);
72
+ }
73
+ else
74
+ {
75
+ // just call C++ base implementation
76
+ return DoSaveRubyValue(who, name, value);
77
+ }
78
+ }
79
+
80
+ VALUE WxRubyPersistenceManager::RestoreRubyValue(const wxPersistentObject& who, const wxString& name)
81
+ {
82
+ Swig::Director* dir = dynamic_cast<Swig::Director*> (this);
83
+ // is this a user defined Ruby persistence manager with overridden #restore_value?
84
+ if (dir && !wxRuby_IsNativeMethod(dir->swig_get_self(), restore_value_id()))
85
+ {
86
+ VALUE rb_who = SWIG_NewPointerObj(SWIG_as_voidptr(&who), SWIGTYPE_p_wxPersistentObject, 0 );
87
+ return wxRuby_Funcall(dir->swig_get_self(), restore_value_id(), 3, rb_who, WXSTR_TO_RSTR(name));
88
+ }
89
+ else
90
+ {
91
+ // just call C++ base implementation
92
+ return DoRestoreRubyValue(who, name);
93
+ }
94
+ }
95
+
96
+ bool WxRubyPersistenceManager::DoSaveRubyValue(const wxPersistentObject& who, const wxString& name, VALUE value)
97
+ {
98
+ wxConfigBase* cfg = this->GetConfig();
99
+ if (!cfg)
100
+ return false;
101
+ wxString key = this->GetKey(who, name);
102
+ switch(TYPE(value))
103
+ {
104
+ case T_TRUE:
105
+ case T_FALSE:
106
+ return cfg->Write(key, value == Qtrue);
107
+
108
+ case T_FIXNUM:
109
+ case T_BIGNUM:
110
+ return cfg->Write(key, PO_NUM2LONG(value));
111
+
112
+ case T_FLOAT:
113
+ return cfg->Write(key, NUM2DBL(value));
114
+
115
+ case T_STRING:
116
+ return cfg->Write(key, RSTR_TO_WXSTR(value));
117
+
118
+ default:
119
+ if (rb_respond_to(value, to_i_id()))
120
+ {
121
+ VALUE ival = rb_funcall(value, to_i_id(), 0);
122
+ return cfg->Write(key, PO_NUM2LONG(ival));
123
+ }
124
+ else if (rb_respond_to(value, to_f_id()))
125
+ {
126
+ VALUE fval = rb_funcall(value, to_f_id(), 0);
127
+ return cfg->Write(key, NUM2DBL(fval));
128
+ }
129
+ break;
130
+ }
131
+ VALUE sval = rb_funcall(value, to_s_id(), 0);
132
+ return cfg->Write(key, RSTR_TO_WXSTR(sval));
133
+ }
134
+
135
+ VALUE WxRubyPersistenceManager::DoRestoreRubyValue(const wxPersistentObject& who, const wxString& name)
136
+ {
137
+ wxConfigBase* cfg = this->GetConfig();
138
+ if (!cfg)
139
+ return Qnil;
140
+ wxString key = this->GetKey(who, name);
141
+ wxConfigBase::EntryType vtype = cfg->GetEntryType(key);
142
+ switch(vtype)
143
+ {
144
+ case wxConfigBase::Type_Boolean:
145
+ {
146
+ bool v;
147
+ if (cfg->Read(key, &v))
148
+ {
149
+ return v ? Qtrue : Qfalse;
150
+ }
151
+ break;
152
+ }
153
+ case wxConfigBase::Type_Integer:
154
+ {
155
+ PO_LONG v;
156
+ if (cfg->Read(key, &v))
157
+ {
158
+ return PO_LONG2NUM(v);
159
+ }
160
+ break;
161
+ }
162
+ case wxConfigBase::Type_Float:
163
+ {
164
+ double v;
165
+ if (cfg->Read(key, &v))
166
+ {
167
+ return DBL2NUM(v);
168
+ }
169
+ break;
170
+ }
171
+ case wxConfigBase::Type_String:
172
+ {
173
+ wxString v;
174
+ if (cfg->Read(key, &v))
175
+ {
176
+ return WXSTR_TO_RSTR(v);
177
+ }
178
+ break;
179
+ }
180
+ default:
181
+ break;
182
+ }
183
+ return Qnil;
184
+ }
185
+
186
+ void WxRubyPersistenceManager::UnregisterPersistentObject(VALUE rb_obj)
187
+ {
188
+ WxRubyPersistenceManager* wxrb_pm =
189
+ dynamic_cast<WxRubyPersistenceManager*> (&wxPersistenceManager::Get());
190
+ if (wxrb_pm) wxrb_pm->UnregisterRbPO(rb_obj);
191
+ }
192
+
193
+ void WxRubyPersistenceManager::GC_markPO()
194
+ {
195
+ rb_object_to_rb_po_map_t::iterator it;
196
+ for( it = rb_object_po_map_.begin(); it != rb_object_po_map_.end(); ++it )
197
+ {
198
+ rb_gc_mark(it->first);
199
+ rb_gc_mark(it->second);
200
+ }
201
+ }
202
+
203
+ static void wxRuby_markPersistentObjects()
204
+ {
205
+ WxRubyPersistenceManager* wxrb_pm =
206
+ dynamic_cast<WxRubyPersistenceManager*> (&wxPersistenceManager::Get());
207
+ if (wxrb_pm) wxrb_pm->GC_markPO();
208
+ }
209
+ __HEREDOC
210
+ spec.add_extend_code 'wxPersistenceManager', <<~__HEREDOC
211
+ VALUE Register(VALUE obj)
212
+ {
213
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
214
+ VALUE rb_po = rb_funcall(obj, create_po_id(), 0);
215
+ if (!NIL_P(rb_po) && wxrb_pm)
216
+ {
217
+ void* ptr;
218
+ int res = SWIG_ConvertPtr(rb_po, &ptr, SWIGTYPE_p_wxPersistentObject, SWIG_POINTER_DISOWN);
219
+ if (!SWIG_IsOK(res))
220
+ {
221
+ rb_raise(rb_eRuntimeError, "Unable to create Wx::PersistentObject for object");
222
+ }
223
+ wxPersistentObject* po = reinterpret_cast< wxPersistentObject * >(ptr);
224
+ if ($self->Register(po->GetObject(), po))
225
+ {
226
+ wxrb_pm->RegisterRbPO(obj, rb_po);
227
+ return rb_po;
228
+ }
229
+ }
230
+ return Qnil;
231
+ }
232
+
233
+ VALUE Register(VALUE obj, VALUE rb_po)
234
+ {
235
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
236
+ if (!NIL_P(rb_po) && wxrb_pm)
237
+ {
238
+ void* ptr;
239
+ int res = SWIG_ConvertPtr(rb_po, &ptr, SWIGTYPE_p_wxPersistentObject, SWIG_POINTER_DISOWN);
240
+ if (!SWIG_IsOK(res))
241
+ {
242
+ rb_raise(rb_eRuntimeError, "Unable to create Wx::PersistentObject for object");
243
+ }
244
+ wxPersistentObject* po = reinterpret_cast< wxPersistentObject * >(ptr);
245
+ if ($self->Register(po->GetObject(), po))
246
+ {
247
+ wxrb_pm->RegisterRbPO(obj, rb_po);
248
+ return rb_po;
249
+ }
250
+ }
251
+ return Qnil;
252
+ }
253
+
254
+ VALUE Find(VALUE obj)
255
+ {
256
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
257
+ VALUE rb_po = wxrb_pm ? wxrb_pm->FindRbPO(obj) : Qnil;
258
+ if (!NIL_P(rb_po) && wxrb_pm)
259
+ {
260
+ void* ptr;
261
+ int res = SWIG_ConvertPtr(rb_po, &ptr, SWIGTYPE_p_wxPersistentObject, 0);
262
+ if (!SWIG_IsOK(res))
263
+ {
264
+ rb_raise(rb_eRuntimeError, "Invalid Wx::PersistentObject for object");
265
+ }
266
+ wxPersistentObject* po = reinterpret_cast< wxPersistentObject * >(ptr);
267
+ if ($self->Find(po->GetObject()))
268
+ return rb_po;
269
+ }
270
+ return Qnil;
271
+ }
272
+
273
+ void Unregister(VALUE obj)
274
+ {
275
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
276
+ VALUE rb_po = wxrb_pm ? wxrb_pm->FindRbPO(obj) : Qnil;
277
+ if (!NIL_P(rb_po) && wxrb_pm)
278
+ {
279
+ void* ptr;
280
+ int res = SWIG_ConvertPtr(rb_po, &ptr, SWIGTYPE_p_wxPersistentObject, 0);
281
+ if (!SWIG_IsOK(res))
282
+ {
283
+ rb_raise(rb_eRuntimeError, "Invalid Wx::PersistentObject for object");
284
+ }
285
+ wxPersistentObject* po = reinterpret_cast< wxPersistentObject * >(ptr);
286
+ $self->Unregister(po->GetObject());
287
+ }
288
+ }
289
+
290
+ void Save(VALUE obj)
291
+ {
292
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
293
+ VALUE rb_po = wxrb_pm ? wxrb_pm->FindRbPO(obj) : Qnil;
294
+ if (!NIL_P(rb_po) && wxrb_pm)
295
+ {
296
+ void* ptr;
297
+ int res = SWIG_ConvertPtr(rb_po, &ptr, SWIGTYPE_p_wxPersistentObject, 0);
298
+ if (!SWIG_IsOK(res))
299
+ {
300
+ rb_raise(rb_eRuntimeError, "Invalid Wx::PersistentObject for object");
301
+ }
302
+ wxPersistentObject* po = reinterpret_cast< wxPersistentObject * >(ptr);
303
+ $self->Save(po->GetObject());
304
+ }
305
+ }
306
+
307
+ bool Restore(VALUE obj)
308
+ {
309
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
310
+ VALUE rb_po = wxrb_pm ? wxrb_pm->FindRbPO(obj) : Qnil;
311
+ if (!NIL_P(rb_po) && wxrb_pm)
312
+ {
313
+ void* ptr;
314
+ int res = SWIG_ConvertPtr(rb_po, &ptr, SWIGTYPE_p_wxPersistentObject, 0);
315
+ if (!SWIG_IsOK(res))
316
+ {
317
+ rb_raise(rb_eRuntimeError, "Invalid Wx::PersistentObject for object");
318
+ }
319
+ wxPersistentObject* po = reinterpret_cast< wxPersistentObject * >(ptr);
320
+ return $self->Restore(po->GetObject());
321
+ }
322
+ return false;
323
+ }
324
+
325
+ void SaveAndUnregister(VALUE obj)
326
+ {
327
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
328
+ VALUE rb_po = wxrb_pm ? wxrb_pm->FindRbPO(obj) : Qnil;
329
+ if (!NIL_P(rb_po) && wxrb_pm)
330
+ {
331
+ void* ptr;
332
+ int res = SWIG_ConvertPtr(rb_po, &ptr, SWIGTYPE_p_wxPersistentObject, 0);
333
+ if (!SWIG_IsOK(res))
334
+ {
335
+ rb_raise(rb_eRuntimeError, "Invalid Wx::PersistentObject for object");
336
+ }
337
+ wxPersistentObject* po = reinterpret_cast< wxPersistentObject * >(ptr);
338
+ $self->Save(po->GetObject());
339
+ $self->Unregister(po->GetObject());
340
+ }
341
+ }
342
+
343
+ bool RegisterAndRestore(VALUE obj)
344
+ {
345
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
346
+ VALUE rb_po = rb_funcall(obj, create_po_id(), 0);
347
+ if (!NIL_P(rb_po) && wxrb_pm)
348
+ {
349
+ void* ptr;
350
+ int res = SWIG_ConvertPtr(rb_po, &ptr, SWIGTYPE_p_wxPersistentObject, SWIG_POINTER_DISOWN);
351
+ if (!SWIG_IsOK(res))
352
+ {
353
+ rb_raise(rb_eRuntimeError, "Unable to create Wx::PersistentObject for object");
354
+ }
355
+ wxPersistentObject* po = reinterpret_cast< wxPersistentObject * >(ptr);
356
+ if ($self->Register(po->GetObject(), po))
357
+ {
358
+ wxrb_pm->RegisterRbPO(obj, rb_po);
359
+ return $self->Restore(po->GetObject());
360
+ }
361
+ }
362
+ return false;
363
+ }
364
+
365
+ bool RegisterAndRestore(VALUE obj, VALUE rb_po)
366
+ {
367
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
368
+ if (!NIL_P(rb_po) && wxrb_pm)
369
+ {
370
+ void* ptr;
371
+ int res = SWIG_ConvertPtr(rb_po, &ptr, SWIGTYPE_p_wxPersistentObject, SWIG_POINTER_DISOWN);
372
+ if (!SWIG_IsOK(res))
373
+ {
374
+ rb_raise(rb_eRuntimeError, "Unable to create Wx::PersistentObject for object");
375
+ }
376
+ wxPersistentObject* po = reinterpret_cast< wxPersistentObject * >(ptr);
377
+ if ($self->Register(po->GetObject(), po))
378
+ {
379
+ wxrb_pm->RegisterRbPO(obj, rb_po);
380
+ return $self->Restore(po->GetObject());
381
+ }
382
+ }
383
+ return false;
384
+ }
385
+
386
+ bool SaveValue(const wxPersistentObject& who, const wxString& name, VALUE value)
387
+ {
388
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
389
+ return wxrb_pm ? wxrb_pm->DoSaveRubyValue(who, name, value) : false;
390
+ }
391
+
392
+ VALUE RestoreValue(const wxPersistentObject& who, const wxString& name)
393
+ {
394
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> ($self);
395
+ return wxrb_pm ? wxrb_pm->DoRestoreRubyValue(who, name) : Qnil;
396
+ }
397
+ __HEREDOC
398
+ spec.add_init_code <<~__HEREDOC
399
+ // install the default global wxRuby persistence manager
400
+ wxPersistenceManager::Set(s_wxruby_persistence_manager);
401
+ // and the persistent object marker
402
+ wxRuby_AppendMarker(wxRuby_markPersistentObjects);
403
+ __HEREDOC
404
+ end
405
+
406
+ end # class PersistenceManager
407
+
408
+ end # class Director
409
+
410
+ end # module WXRuby3
@@ -0,0 +1,70 @@
1
+ # Copyright (c) 2023 M.J.N. Corino, The Netherlands
2
+ #
3
+ # This software is released under the MIT license.
4
+
5
+ ###
6
+ # wxRuby3 wxWidgets interface director
7
+ ###
8
+
9
+ module WXRuby3
10
+
11
+ class Director
12
+
13
+ class PersistentObject < Director
14
+
15
+ def setup
16
+ super
17
+ spec.gc_as_marked
18
+ spec.add_header_code <<~__HEREDOC
19
+ #include "wxruby-Persistence.h"
20
+
21
+ WxRubyPersistentObject::WxRubyPersistentObject(VALUE rb_obj)
22
+ : wxPersistentObject((void*)rb_obj)
23
+ {}
24
+
25
+ WxRubyPersistentObject::~WxRubyPersistentObject()
26
+ {
27
+ if (this->GetObject())
28
+ WxRubyPersistenceManager::UnregisterPersistentObject(
29
+ reinterpret_cast<VALUE> (this->GetObject()));
30
+ }
31
+ __HEREDOC
32
+ spec.use_class_implementation 'wxPersistentObject', 'WxRubyPersistentObject'
33
+ spec.ignore %w[wxPersistentObject::GetObject wxPersistentObject::wxPersistentObject]
34
+ spec.ignore %w[wxCreatePersistentObject wxPersistentRegisterAndRestore]
35
+ spec.extend_interface 'wxPersistentObject',
36
+ 'wxPersistentObject(VALUE rb_obj)',
37
+ visibility: 'protected'
38
+ spec.add_extend_code 'wxPersistentObject', <<~__HEREDOC
39
+ bool SaveValue(const wxString& name, VALUE value)
40
+ {
41
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> (&wxPersistenceManager::Get());
42
+ return wxrb_pm ? wxrb_pm->SaveRubyValue(*$self, name, value) : false;
43
+ }
44
+ VALUE RestoreValue(const wxString& name)
45
+ {
46
+ WxRubyPersistenceManager* wxrb_pm = dynamic_cast<WxRubyPersistenceManager*> (&wxPersistenceManager::Get());
47
+ return wxrb_pm ? wxrb_pm->RestoreRubyValue(*$self, name) : Qnil;
48
+ }
49
+ __HEREDOC
50
+ spec.add_extend_code 'wxPersistentObject', <<~__HEREDOC
51
+ VALUE GetObject()
52
+ {
53
+ WxRubyPersistentObject* rpo = dynamic_cast<WxRubyPersistentObject*> ($self);
54
+ if (rpo)
55
+ {
56
+ return reinterpret_cast<VALUE> (rpo->GetObject());
57
+ }
58
+ else
59
+ {
60
+ return Qnil;
61
+ }
62
+ }
63
+ __HEREDOC
64
+ super
65
+ end
66
+ end # class PersistentObject
67
+
68
+ end # class Director
69
+
70
+ end # module WXRuby3
@@ -0,0 +1,73 @@
1
+ # Copyright (c) 2023 M.J.N. Corino, The Netherlands
2
+ #
3
+ # This software is released under the MIT license.
4
+
5
+ ###
6
+ # wxRuby3 wxWidgets interface director
7
+ ###
8
+
9
+ module WXRuby3
10
+
11
+ class Director
12
+
13
+ class PersistentWindow < Director
14
+
15
+ def setup
16
+ spec.items << 'wxPersistentTLW' << 'wxPersistentBookCtrl' << 'wxPersistentTreeBookCtrl'
17
+ if Config.instance.wx_version >= '3.3.0'
18
+ # before 3.3.0 this was not properly available
19
+ spec.items << 'wxPersistentComboBox'
20
+ end
21
+ super
22
+ spec.gc_as_marked
23
+ spec.use_template_as_class('wxPersistentWindow', 'wxPersistentWindowBase')
24
+ spec.override_inheritance_chain('wxPersistentWindow', %w[wxPersistentObject])
25
+ spec.ignore 'wxPersistentWindow::wxPersistentWindow',
26
+ 'wxPersistentWindow::Get',
27
+ ignore_doc: false
28
+ # make ctor protected because of pure virt methods
29
+ spec.extend_interface 'wxPersistentWindow',
30
+ 'wxPersistentWindowBase(wxWindow *win)',
31
+ visibility: 'protected'
32
+ spec.add_header_code 'typedef wxWindow WindowType;'
33
+ spec.add_swig_code 'typedef wxWindow WindowType;'
34
+ spec.map 'WindowType *' => 'Wx::Window', swig: false do
35
+ map_in code: ''
36
+ map_out code: ''
37
+ end
38
+ spec.add_extend_code 'wxPersistentWindowBase', <<~__HEREDOC
39
+ wxWindow * GetObject()
40
+ {
41
+ return reinterpret_cast<wxWindow*> ($self->GetObject());
42
+ }
43
+ __HEREDOC
44
+ # wxPersistentTLW
45
+ spec.override_inheritance_chain('wxPersistentTLW', [{ 'wxPersistentWindowBase' => 'wxPersistentWindow' }, 'wxPersistentObject'])
46
+ # add method override missing from docs
47
+ spec.extend_interface 'wxPersistentTLW',
48
+ 'virtual wxString GetKind() const override'
49
+ # wxPersistentBookCtrl
50
+ spec.override_inheritance_chain('wxPersistentBookCtrl', [{ 'wxPersistentWindowBase' => 'wxPersistentWindow' }, 'wxPersistentObject'])
51
+ # add method override missing from docs
52
+ spec.extend_interface 'wxPersistentBookCtrl',
53
+ 'virtual wxString GetKind() const override'
54
+ # wxPersistentTreeBookCtrl
55
+ spec.override_inheritance_chain('wxPersistentTreeBookCtrl', ['wxPersistentBookCtrl', { 'wxPersistentWindowBase' => 'wxPersistentWindow' }, 'wxPersistentObject'])
56
+ # add method override missing from docs
57
+ spec.extend_interface 'wxPersistentTreeBookCtrl',
58
+ 'virtual wxString GetKind() const override'
59
+ spec.do_not_generate :functions, :defines, :typedefs, :variables, :enums
60
+ if Config.instance.wx_version >= '3.0.0'
61
+ # wxPersistentComboBox
62
+ spec.override_inheritance_chain('wxPersistentComboBox', [{ 'wxPersistentWindowBase' => 'wxPersistentWindow' }, 'wxPersistentObject'])
63
+ # add method override missing from docs
64
+ spec.extend_interface 'wxPersistentComboBox',
65
+ 'virtual wxString GetKind() const override'
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -45,6 +45,10 @@ module WXRuby3
45
45
  spec.add_swig_code %Q{typedef wxStaticBitmap::ScaleMode ScaleMode; }
46
46
  spec.add_header_code %Q{typedef wxStaticBitmap::ScaleMode ScaleMode; }
47
47
  defmod.items << def_genstatbmp
48
+ # as we already called super before adding wxGenericStaticBitmap the no_proxy settings from the
49
+ # base Window director are missing; just copy all those set for wxStaticBitmap
50
+ list = spec.no_proxies.select { |name| name.start_with?('wxStaticBitmap::') }
51
+ spec.no_proxy(*list.collect { |name| name.sub(/\AwxStaticBitmap::/, 'wxGenericStaticBitmap::')})
48
52
  defmod
49
53
  end
50
54
 
@@ -15,7 +15,7 @@ module WXRuby3
15
15
  def setup
16
16
  super
17
17
  spec.items << 'wxTextCompleter' << 'wxTextCompleterSimple'
18
- spec.gc_as_untracked 'wxTextCompleter', 'wxTextCompleterSimple'
18
+ spec.gc_as_marked 'wxTextCompleter', 'wxTextCompleterSimple' # untracked but cached in Ruby
19
19
  spec.gc_as_untracked 'wxTextEntry' # actually no GC control necessary as this is a mixin only
20
20
  # turn wxTextEntry into a mixin module
21
21
  spec.make_mixin 'wxTextEntry'
@@ -540,53 +540,53 @@ module WXRuby3
540
540
  # check the preprocessed definitions
541
541
  errors = []
542
542
  warnings = []
543
- def_items.each do |item|
544
- if Extractor::ClassDef === item && !item_ignored(item, doc_gen) &&
543
+ # select eligible ClassDef
544
+ cls_items = def_items.select do |item|
545
+ Extractor::ClassDef === item && !item_ignored(item, doc_gen) &&
545
546
  (!item.is_template? || template_as_class?(item.name)) &&
546
547
  !is_folded_base?(item.name)
547
- intf_class_name = if item.is_template? || template_as_class?(item.name)
548
- template_class_name(item.name)
549
- else
550
- item.name
551
- end
552
- # this should not happen
553
- raise "Missing preprocessed data for class #{intf_class_name}" unless has_class_interface(intf_class_name)
554
- # get the class's method registry
555
- cls_mtdreg = class_interface_methods(intf_class_name)
556
- # check all directly inherited generated methods
557
- mtdlist = ::Set.new # remember handled signatures
558
- base_list(item).each do |base_name|
559
- # get 'real' base name (i.e. take renames into account)
560
- base_name = ifspec.classdef_name(base_name)
561
- # make sure the base class has been preprocessed
562
- get_class_interface(package, base_name, doc_gen) unless has_class_interface(base_name)
563
- # generate any required enum typemaps for inherited virtuals
564
- gen_base_class_enum_typemaps(base_name, enum_maps)
565
- # iterate the base class's method registrations
566
- class_interface_methods(base_name).each_pair do |mtdsig, mtdreg|
567
- # only check on methods we have not handled yet
568
- if !mtdlist.include?(mtdsig)
569
- # did we inherit a virtual method that was not proxied in the base
570
- if mtdreg[:virtual] && !mtdreg[:proxy]
571
- # # if we did NOT generate a wrapper override and we do not have the proxy suppressed we're in trouble
572
- # if !cls_mtdreg.has_key?(mtdsig) && has_method_proxy?(item.name, mtdreg[:method])
573
- # warnings << "* WARNING: disabling proxy for virtual method #{mtdreg[:method].signature} without wrapper implementation in class #{item.name} since it is NOT proxied in base class #{base_name}!"
574
- # els
575
- if cls_mtdreg.has_key?(mtdsig) && !cls_mtdreg[mtdsig][:extension] && !has_method_proxy?(item.name, cls_mtdreg[mtdsig][:method])
576
- # if this is not a custom extension and we do have an override wrapper and no proxy this is unnecessary code bloat
577
- warnings << " * WARNING: Unnecessary override #{mtdreg[:method].signature} in class #{item.name} for non-proxied base in #{base_name}. Ignoring."
578
- cls_mtdreg[mtdsig][:ignore] = true
579
- end
580
- # or did we inherit a virtual method that was proxied in the base
581
- # for which we DO generate a wrapper override
582
- elsif mtdreg[:virtual] && mtdreg[:proxy] && cls_mtdreg.has_key?(mtdsig)
583
- # if we do not have a proxy as well we're in trouble
584
- if !has_method_proxy?(item, mtdreg[:method])
585
- errors << "* ERROR: method #{mtdreg[:method].signature} is NOT proxied with an overriden wrapper implementation in class #{item.name} but is also implemented and proxied in base class #{base_name}!"
586
- end
548
+ end
549
+ cls_items.each do |item|
550
+ intf_class_name = if item.is_template? || template_as_class?(item.name)
551
+ template_class_name(item.name)
552
+ else
553
+ item.name
554
+ end
555
+ # this should not happen
556
+ raise "Missing preprocessed data for class #{intf_class_name}" unless has_class_interface(intf_class_name)
557
+ # get the class's method registry
558
+ cls_mtdreg = class_interface_methods(intf_class_name)
559
+ # check all directly inherited generated methods
560
+ mtdlist = ::Set.new # remember handled signatures
561
+ base_list(item).each do |base_name|
562
+ # make sure the base class has been preprocessed
563
+ get_class_interface(package, base_name, doc_gen) unless has_class_interface(base_name)
564
+ # generate any required enum typemaps for inherited virtuals
565
+ gen_base_class_enum_typemaps(base_name, enum_maps)
566
+ # iterate the base class's method registrations
567
+ class_interface_methods(base_name).each_pair do |mtdsig, mtdreg|
568
+ # only check on methods we have not handled yet
569
+ if !mtdlist.include?(mtdsig)
570
+ # did we inherit a virtual method that was not proxied in the base
571
+ if mtdreg[:virtual] && !mtdreg[:proxy]
572
+ # # if we did NOT generate a wrapper override and we do not have the proxy suppressed we're in trouble
573
+ # if !cls_mtdreg.has_key?(mtdsig) && has_method_proxy?(item.name, mtdreg[:method])
574
+ # warnings << "* WARNING: disabling proxy for virtual method #{mtdreg[:method].signature} without wrapper implementation in class #{item.name} since it is NOT proxied in base class #{base_name}!"
575
+ # els
576
+ if cls_mtdreg.has_key?(mtdsig) && !cls_mtdreg[mtdsig][:extension] && !has_method_proxy?(item.name, cls_mtdreg[mtdsig][:method])
577
+ # if this is not a custom extension and we do have an override wrapper and no proxy this is unnecessary code bloat
578
+ warnings << " * WARNING: Unnecessary override #{mtdreg[:method].signature} in class #{item.name} for non-proxied base in #{base_name}. Ignoring."
579
+ cls_mtdreg[mtdsig][:ignore] = true
580
+ end
581
+ # or did we inherit a virtual method that was proxied in the base
582
+ # for which we DO generate a wrapper override
583
+ elsif mtdreg[:virtual] && mtdreg[:proxy] && cls_mtdreg.has_key?(mtdsig)
584
+ # if we do not have a proxy as well we're in trouble
585
+ if !has_method_proxy?(item, mtdreg[:method])
586
+ errors << "* ERROR: method #{mtdreg[:method].signature} is NOT proxied with an overriden wrapper implementation in class #{item.name} but is also implemented and proxied in base class #{base_name}!"
587
587
  end
588
- mtdlist << mtdsig
589
588
  end
589
+ mtdlist << mtdsig
590
590
  end
591
591
  end
592
592
  end