wxruby3 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
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