wxruby3 0.9.0.pre.beta.9 → 0.9.0.pre.beta.11

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/ext/wxruby3/include/wxruby-ScaledDC.h +549 -0
  3. data/ext/wxruby3/swig/mark_free_impl.i +0 -34
  4. data/ext/wxruby3/swig/wx.i +1 -1
  5. data/lib/wx/core/bitmap.rb +7 -0
  6. data/lib/wx/core/choice.rb +3 -0
  7. data/lib/wx/core/combobox.rb +3 -0
  8. data/lib/wx/core/controlwithitems.rb +98 -2
  9. data/lib/wx/core/data_object.rb +74 -6
  10. data/lib/wx/core/icon.rb +7 -1
  11. data/lib/wx/core/imagelist.rb +11 -0
  12. data/lib/wx/core/listbox.rb +3 -0
  13. data/lib/wx/core/point.rb +21 -10
  14. data/lib/wx/core/real_point.rb +21 -10
  15. data/lib/wx/core/rect.rb +2 -2
  16. data/lib/wx/core/size.rb +12 -5
  17. data/lib/wx/doc/data_object.rb +104 -0
  18. data/lib/wx/doc/gdi_common.rb +33 -5
  19. data/lib/wx/doc/progress_dialog.rb +37 -0
  20. data/lib/wx/doc/scaled_dc.rb +16 -0
  21. data/lib/wx/global_const.rb +4 -3
  22. data/lib/wx/version.rb +1 -1
  23. data/rakelib/lib/config/mingw.rb +3 -0
  24. data/rakelib/lib/core/include/init.inc +2 -2
  25. data/rakelib/lib/core/package.rb +3 -3
  26. data/rakelib/lib/core/spec.rb +2 -0
  27. data/rakelib/lib/director/ctrl_with_items.rb +29 -17
  28. data/rakelib/lib/director/data_object.rb +94 -0
  29. data/rakelib/lib/director/data_object_simple_base.rb +123 -0
  30. data/rakelib/lib/director/derived_dc.rb +38 -0
  31. data/rakelib/lib/director/dialog.rb +29 -54
  32. data/rakelib/lib/director/image_list.rb +3 -1
  33. data/rakelib/lib/director/preview_frame.rb +41 -0
  34. data/rakelib/lib/director/print_data.rb +5 -7
  35. data/rakelib/lib/specs/interfaces.rb +2 -0
  36. data/rakelib/lib/typemap/data_object_data.rb +13 -4
  37. data/samples/dialogs/dialogs.rb +70 -50
  38. data/samples/drawing/maths_images.rb +1 -1
  39. data/samples/sampler/ext.rb +3 -3
  40. data/samples/sampler/stc_editor.rb +19 -19
  41. data/samples/sampler/txt_editor.rb +2 -2
  42. data/samples/treectrl/treectrl.rb +32 -30
  43. data/tests/lib/wxapp_runner.rb +64 -0
  44. data/tests/test_basic.rb +0 -5
  45. data/tests/test_clipboard.rb +114 -17
  46. data/tests/test_dialog.rb +2 -13
  47. data/tests/test_event_handling.rb +2 -13
  48. data/tests/test_events.rb +2 -6
  49. data/tests/test_geometry.rb +54 -17
  50. data/tests/test_intl.rb +2 -15
  51. data/tests/test_item_data.rb +69 -15
  52. data/tests/test_variant.rb +1 -15
  53. data/tests/testapp.rb +0 -5
  54. data/tests/testapp_noframe.rb +0 -5
  55. metadata +8 -2
@@ -122,6 +122,9 @@ module WXRuby3
122
122
  @rescomp << ' --define __WXMSW__ --define wxUSE_DPI_AWARE_MANIFEST=2 --define wxUSE_RC_MANIFEST=1 --define ISOLATION_AWARE_ENABLED'
123
123
  @rescomp << ' --define WXUSINGDLL'
124
124
  @extra_cflags << '-DISOLATION_AWARE_ENABLED'
125
+ if @wx_version >= '3.3.0'
126
+ @extra_cflags << '-D_UNICODE' << '-DUNICODE'
127
+ end
125
128
  end
126
129
  end
127
130
  private :init_platform
@@ -70,7 +70,7 @@ static void wxRuby_SetActivationContext()
70
70
  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
71
71
  (LPTSTR) &lpMsgBuf,
72
72
  0, NULL );
73
- ::fprintf(stderr, "Error in CreateActCtx : %s\n", lpMsgBuf);
73
+ std::wcerr << "Error in CreateActCtx : " << lpMsgBuf << std::endl;
74
74
  return;
75
75
  }
76
76
 
@@ -88,7 +88,7 @@ static void wxRuby_SetActivationContext()
88
88
  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
89
89
  (LPTSTR) &lpMsgBuf,
90
90
  0, NULL );
91
- ::fprintf(stderr, "Error in ActivateActCtx : %s\n", lpMsgBuf);
91
+ std::wcerr << "Error in ActivateActCtx : " << lpMsgBuf << std::endl;
92
92
  }
93
93
  }
94
94
 
@@ -208,7 +208,7 @@ module WXRuby3
208
208
  # next initialize all modules without classes (keeping only those with classes)
209
209
  inc_dirs.select! do |dir|
210
210
  modreg = Spec.module_registry[dir.spec.module_name]
211
- if modreg.nil? || modreg.empty?
211
+ if !dir.spec.initialize_at_end && (modreg.nil? || modreg.empty?)
212
212
  init = "Init_#{dir.spec.module_name}()"
213
213
  decls << "extern \"C\" void #{init};"
214
214
  init_fn << " #{init};"
@@ -222,7 +222,7 @@ module WXRuby3
222
222
  cls_set = ::Set.new
223
223
  inc_dirs.select! do |dir|
224
224
  modreg = Spec.module_registry[dir.spec.module_name]
225
- if modreg && !modreg.empty? && modreg.values.all? {|base| base.nil? || modreg.has_key?(base) }
225
+ if !dir.spec.initialize_at_end && modreg && !modreg.empty? && modreg.values.all? {|base| base.nil? || modreg.has_key?(base) }
226
226
  cls_set.merge modreg.keys # remember classes
227
227
  init = "Init_#{dir.spec.module_name}()"
228
228
  decls << "extern \"C\" void #{init};"
@@ -235,7 +235,7 @@ module WXRuby3
235
235
 
236
236
  # next initialize all modules with classes depending (bases AND mixins) on classes in any modules already
237
237
  # selected until there are no more modules left or none that are left depend on any selected ones
238
- while dir_inx = inc_dirs.find_index { |dir| is_dir_with_fulfilled_deps?(dir, cls_set) }
238
+ while dir_inx = inc_dirs.find_index { |dir| !dir.spec.initialize_at_end && is_dir_with_fulfilled_deps?(dir, cls_set) }
239
239
  dir = inc_dirs[dir_inx]
240
240
  modreg = Spec.module_registry[dir.spec.module_name]
241
241
  cls_set.merge modreg.keys # remember classes
@@ -77,6 +77,7 @@ module WXRuby3
77
77
  @post_processors = processors || [:rename, :fixmodule, :fix_protected_access]
78
78
  @requirements = [requirements].flatten
79
79
  @type_maps = Typemap::Collection.new
80
+ @initialize_at_end = false
80
81
  end
81
82
 
82
83
  attr_reader :director, :package, :module_name, :name, :items, :folded_bases, :ignores, :regards, :readonly, :contracts, :event_overrides,
@@ -85,6 +86,7 @@ module WXRuby3
85
86
  :runtime_code, :header_code, :wrapper_code, :extend_code, :init_code, :interface_code,
86
87
  :nogen_sections, :post_processors, :requirements, :type_maps
87
88
  attr_writer :interface_file
89
+ attr_accessor :initialize_at_end
88
90
 
89
91
  def interface_file
90
92
  @interface_file || File.join(Config.instance.classes_path, @name + '.i')
@@ -22,23 +22,40 @@ module WXRuby3
22
22
  wxEvtHandler
23
23
  wxObject])
24
24
  spec.ignore([
25
+ 'wxItemContainer::Append(const wxString &, wxClientData *)',
26
+ 'wxItemContainer::Append(const std::vector< wxString > &)',
27
+ 'wxItemContainer::Append(const wxArrayString &, wxClientData **)',
28
+ 'wxItemContainer::Append(unsigned int, const wxString *)',
29
+ 'wxItemContainer::Append(unsigned int, const wxString *, void **)',
30
+ 'wxItemContainer::Append(unsigned int, const wxString *, wxClientData **)',
31
+ 'wxItemContainer::Insert(const wxString &, unsigned int, wxClientData *)',
25
32
  'wxItemContainer::Insert(const std::vector< wxString > &)',
33
+ 'wxItemContainer::Insert(const wxArrayString &, unsigned int, wxClientData **)',
34
+ 'wxItemContainer::Insert(unsigned int, const wxString *, unsigned int)',
35
+ 'wxItemContainer::Insert(unsigned int, const wxString *, unsigned int, void **)',
36
+ 'wxItemContainer::Insert(unsigned int, const wxString *, unsigned int, wxClientData **)',
37
+ 'wxItemContainer::Set(const std::vector< wxString > &)',
38
+ 'wxItemContainer::Set(const wxArrayString &, wxClientData **)',
39
+ 'wxItemContainer::Set(unsigned int, const wxString *)',
40
+ 'wxItemContainer::Set(unsigned int, const wxString *, void **)',
41
+ 'wxItemContainer::Set(unsigned int, const wxString *, wxClientData **)',
42
+ 'wxItemContainer::DetachClientObject',
43
+ 'wxItemContainer::HasClientObjectData',
26
44
  'wxItemContainer::GetClientObject',
27
45
  'wxItemContainer::SetClientObject'])
46
+ spec.ignore([
47
+ 'wxItemContainer::Append(const wxArrayString &, void **)',
48
+ 'wxItemContainer::Insert(const wxArrayString &, unsigned int, void **)',
49
+ 'wxItemContainer::Set(const wxArrayString &, void **)'], ignore_doc: false)
50
+ # for doc only
51
+ spec.map 'void** clientData' => 'Array', swig: false do
52
+ map_in code: ''
53
+ end
28
54
  spec.ignore(%w[wxItemContainer::GetClientData wxItemContainer::SetClientData], ignore_doc: false) # keep docs
29
- # Replace the old Wx definitions of these methods - which segfault
55
+ # Replace the old Wx definition of this method (which segfaults)
56
+ # Only need the setter as we cache data in Ruby and the getter
57
+ # therefor can be pure Ruby
30
58
  spec.add_extend_code('wxControlWithItems', <<~__HEREDOC
31
- VALUE get_client_data(int n) {
32
- // Avoid an assert failure if no data previously set
33
- if ( ! self->HasClientUntypedData() )
34
- return Qnil;
35
-
36
- VALUE returnVal = (VALUE) self->GetClientData(n);
37
- if ( ! returnVal )
38
- return Qnil;
39
- return returnVal;
40
- }
41
-
42
59
  VALUE set_client_data(int n, VALUE item_data) {
43
60
  self->SetClientData(n, (void *)item_data);
44
61
  return item_data;
@@ -51,13 +68,8 @@ module WXRuby3
51
68
  def setup_ctrl_with_items(clsnm)
52
69
  # used in GC phase so DO NOT trigger Ruby redirection
53
70
  spec.no_proxy "#{clsnm}::GetCount"
54
- spec.add_swig_code <<~__HEREDOC
55
- // adjust GC marker
56
- %markfunc #{clsnm} "GC_mark_wxControlWithItems";
57
- __HEREDOC
58
71
  spec.add_header_code <<~__HEREDOC
59
72
  extern swig_class cWxControlWithItems;
60
- WXRUBY_EXPORT void GC_mark_wxControlWithItems(void* ptr);
61
73
  __HEREDOC
62
74
  spec.no_proxy "#{clsnm}::GetStringSelection"
63
75
  end
@@ -56,9 +56,103 @@ module WXRuby3
56
56
  # Once a DataObject has been added, it belongs to the wxDataObjectComposite object,
57
57
  # and will be freed by it on destruction.
58
58
  spec.disown 'wxDataObjectSimple* dataObject'
59
+
60
+ # Add GC management for the DataObjectSimple instances added to a DataObjectComposite instance.
61
+ spec.add_header_code <<~__HEREDOC
62
+ #include <vector>
63
+ #include <map>
64
+
65
+ typedef std::vector<VALUE> data_object_list_t;
66
+ typedef std::map<wxDataObjectComposite*, data_object_list_t> composite_data_object_map_t;
67
+ static composite_data_object_map_t CompositeDataObject_Map;
68
+
69
+ static void wxRuby_markCompositeDataObjects()
70
+ {
71
+ composite_data_object_map_t::iterator it;
72
+ for( it = CompositeDataObject_Map.begin(); it != CompositeDataObject_Map.end(); ++it )
73
+ {
74
+ data_object_list_t &do_list = it->second;
75
+ for (VALUE data_obj : do_list)
76
+ {
77
+ #ifdef __WXRB_DEBUG__
78
+ if (wxRuby_TraceLevel()>1)
79
+ {
80
+ void *c_ptr = (TYPE(data_obj) == T_DATA ? DATA_PTR(data_obj) : 0);
81
+ std::wcout << "**** wxRuby_markCompositeDataObjects : " << it->first << "|" << (void*)c_ptr << std::endl;
82
+ }
83
+ #endif
84
+ rb_gc_mark(data_obj);
85
+ }
86
+ }
87
+ }
88
+
89
+ // custom implementation for wxRuby so we can handle de-registering composites
90
+ class WxRuby_DataObjectComposite : public wxDataObjectComposite
91
+ {
92
+ public:
93
+ WxRuby_DataObjectComposite() : wxDataObjectComposite() {}
94
+ virtual ~WxRuby_DataObjectComposite()
95
+ {
96
+ CompositeDataObject_Map.erase(this);
97
+ }
98
+ };
99
+ __HEREDOC
100
+ # install GC marker
101
+ spec.add_init_code 'wxRuby_AppendMarker(wxRuby_markCompositeDataObjects);'
102
+ # use custom implementation class
103
+ spec.use_class_implementation 'wxDataObjectComposite', 'WxRuby_DataObjectComposite'
104
+
105
+ # disable generating the default Add method (keep docs)
106
+ spec.ignore 'wxDataObjectComposite::Add', ignore_doc: false
107
+ # Add custom Add implementation
108
+ spec.add_extend_code 'wxDataObjectComposite', <<~__HEREDOC
109
+ void add(VALUE rb_dataObject, bool preferred=false)
110
+ {
111
+ // convert simple object
112
+ wxDataObjectSimple *simple_do;
113
+ int res = SWIG_ConvertPtr(rb_dataObject, SWIG_as_voidptrptr(&simple_do), SWIGTYPE_p_wxDataObjectSimple, SWIG_POINTER_DISOWN);
114
+ if (!SWIG_IsOK(res))
115
+ {
116
+ rb_raise(rb_eArgError, "Expected Wx::DataObjectSimple for 1");
117
+ }
118
+
119
+ // add new simple instance to registration for this composite
120
+ CompositeDataObject_Map[$self].push_back(rb_dataObject);
121
+
122
+ // add to composite
123
+ $self->Add(simple_do);
124
+ }
125
+ __HEREDOC
126
+
59
127
  end
60
128
  end # class DataObject
61
129
 
130
+ def doc_generator
131
+ DataObjectDocGenerator.new(self)
132
+ end
133
+
62
134
  end # class Director
63
135
 
136
+ class DataObjectDocGenerator < DocGenerator
137
+
138
+ def get_class_doc(clsdef)
139
+ if clsdef.name == 'wxDataObjectSimple'
140
+ []
141
+ else
142
+ super
143
+ end
144
+ end
145
+ protected :get_class_doc
146
+
147
+ def get_method_doc(mtd)
148
+ if Extractor::MethodDef === mtd && mtd.class_name == 'wxDataObject' && mtd.name == 'GetDataSize'
149
+ {}
150
+ else
151
+ super
152
+ end
153
+ end
154
+ protected :get_method_doc
155
+
156
+ end
157
+
64
158
  end # module WXRuby3
@@ -0,0 +1,123 @@
1
+ ###
2
+ # wxRuby3 wxWidgets interface director
3
+ # Copyright (c) M.J.N. Corino, The Netherlands
4
+ ###
5
+
6
+ module WXRuby3
7
+
8
+ class Director
9
+
10
+ class DataObjectSimpleBase < Director
11
+
12
+ include Typemap::DataFormat
13
+ include Typemap::DataObjectData
14
+
15
+ def setup
16
+ super
17
+ spec.items.clear
18
+ # insert literal code as #gc_as_xx does not work without parsed class items
19
+ spec.add_swig_code 'GC_MANAGE_AS_OBJECT(wxDataObjectSimpleBase);'
20
+ spec.initialize_at_end = true
21
+
22
+ spec.swig_import 'ext/wxruby3/swig/classes/include/wxDataObject.h'
23
+
24
+ spec.add_header_code <<~__HEREDOC
25
+ class wxDataObjectSimpleBase : public wxDataObjectSimple
26
+ {
27
+ public:
28
+ wxDataObjectSimpleBase(const wxDataFormat &format=wxFormatInvalid)
29
+ : wxDataObjectSimple(format) {}
30
+ virtual ~wxDataObjectSimpleBase() { }
31
+
32
+ virtual size_t GetDataSize() const { return _GetDataSize(); }
33
+ virtual size_t GetDataSize(const wxDataFormat &) const { return _GetDataSize(); }
34
+ virtual bool GetDataHere(const wxDataFormat &, void *buf) const { return _GetData(buf); }
35
+ virtual bool GetDataHere(void *data_buffer) const { return _GetData(data_buffer); }
36
+ virtual bool SetData(const wxDataFormat &, size_t len, const void *buf) { return _SetData(len, buf); }
37
+ virtual bool SetData(size_t len, const void *buf) { return _SetData(len, buf); }
38
+
39
+ protected:
40
+ virtual size_t _GetDataSize() const { return 0; }
41
+ virtual bool _GetData(void *data_buffer) const { return false; }
42
+ virtual bool _SetData(size_t len, const void *buf) { return false; }
43
+ };
44
+ __HEREDOC
45
+
46
+ spec.add_interface_code <<~__HEREDOC
47
+ class wxDataObjectSimpleBase : public wxDataObjectSimple
48
+ {
49
+ public:
50
+ wxDataObjectSimpleBase(const wxDataFormat &format=wxFormatInvalid);
51
+
52
+ virtual void GetAllFormats(wxDataFormat *formats, Direction dir=Get) const;
53
+ virtual size_t GetFormatCount(Direction dir=Get) const;
54
+ virtual wxDataFormat GetPreferredFormat(Direction dir=Get) const;
55
+
56
+ protected:
57
+ virtual size_t _GetDataSize() const;
58
+ %feature("numoutputs", "0") _GetData;
59
+ virtual VOID_BOOL _GetData(void *data_buffer) const;
60
+ virtual bool _SetData(size_t len, const void *buf);
61
+ };
62
+ __HEREDOC
63
+
64
+ # For wxDataObjectSimpleBase::GetDataHere/_GetData : the ruby method should
65
+ # return either a string containing the
66
+ # data, or nil if the data cannot be provided for some reason.
67
+ spec.map 'void *data_buffer' do
68
+
69
+ map_in ignore: true, code: ''
70
+
71
+ # "misuse" the 'check' typemap to initialize the ignored argument
72
+ # since this is inserted after any non-ignored arguments have been converted we can use these
73
+ # here
74
+ map_check temp: 'std::unique_ptr<char[]> data_buf, size_t data_size', code: <<~__CODE
75
+ data_size = arg1->GetDataSize();
76
+ data_buf = std::make_unique<char[]>(data_size);
77
+ $1 = data_buf.get ();
78
+ __CODE
79
+
80
+ # ignore C defined return value entirely (also affects directorout)
81
+ map_out ignore: 'bool'
82
+
83
+ map_argout as: {type: 'String', index: 1}, code: <<~__CODE
84
+ if (result)
85
+ {
86
+ $result = rb_utf8_str_new( (const char*)data_buf$argnum.get(), data_size$argnum);
87
+ }
88
+ else
89
+ $result = Qnil;
90
+ __CODE
91
+
92
+ # ignore the buffer pointer for now
93
+ map_directorin code: ''
94
+
95
+ map_directorargout code: <<~__CODE
96
+ if (RTEST(result))
97
+ {
98
+ if (TYPE(result) == T_STRING)
99
+ {
100
+ memcpy(data_buffer, StringValuePtr(result), RSTRING_LEN(result) );
101
+ c_result = true;
102
+ }
103
+ else
104
+ {
105
+ Swig::DirectorTypeMismatchException::raise(rb_eTypeError,
106
+ "get_data_here should return a string, or nil on failure");
107
+ }
108
+ }
109
+ else
110
+ c_result = false;
111
+ __CODE
112
+
113
+ end
114
+
115
+ # Once a DataObject has been added, it belongs to the wxDataObjectComposite object,
116
+ # and will be freed by it on destruction.
117
+ # spec.disown 'wxDataObjectSimple* dataObject'
118
+ end
119
+ end # class DataObject
120
+
121
+ end # class Director
122
+
123
+ end # module WXRuby3
@@ -52,6 +52,44 @@ module WXRuby3
52
52
  'wxSVGFileDC::EndPage'
53
53
  elsif spec.module_name == 'wxGCDC'
54
54
  spec.ignore 'wxGCDC::wxGCDC(const wxEnhMetaFileDC &)'
55
+ elsif spec.module_name == 'wxScaledDC'
56
+ spec.items.clear # wxRuby extension; no XML docs
57
+ spec.override_inheritance_chain('wxScaledDC', %w[wxDC wxObject])
58
+ # as there are no dependencies parsed from XML make sure we're initialized after Wx::DC
59
+ spec.initialize_at_end = true
60
+ spec.gc_as_temporary 'wxScaledDC'
61
+ spec.no_proxy 'wxScaledDC'
62
+ spec.include 'wxruby-ScaledDC.h'
63
+ # wxScaledDc should ever only be used in a restricted scope
64
+ # to be destructed directly after use therefor we make it abstract
65
+ # and provide a class factory method #draw_on with accepts a block.
66
+ # (as we there no classes defined in XML we cannot use add_extend_code
67
+ # so we use a workaround here)
68
+ spec.add_swig_code <<~__HEREDOC
69
+ %extend wxScaledDC {
70
+ static void draw_on(wxDC& target, double scale)
71
+ {
72
+ if (rb_block_given_p())
73
+ {
74
+ wxScaledDC scaled_dc(target, scale);
75
+ wxScaledDC* p_scaled_dc = &scaled_dc;
76
+ VALUE rb_scaled_dc = SWIG_NewPointerObj(SWIG_as_voidptr(p_scaled_dc), SWIGTYPE_p_wxScaledDC, 0);
77
+ rb_yield(rb_scaled_dc);
78
+ }
79
+ return ;
80
+ }
81
+ };
82
+ __HEREDOC
83
+ spec.swig_import %w[ext/wxruby3/swig/classes/include/wxObject.h
84
+ ext/wxruby3/swig/classes/include/wxDC.h]
85
+ spec.add_interface_code <<~__HEREDOC
86
+ class wxScaledDC : public wxDC
87
+ {
88
+ public:
89
+ wxScaledDC(wxDC& target, double scale);
90
+ virtual ~wxScaledDC() = 0;
91
+ };
92
+ __HEREDOC
55
93
  else
56
94
  # ctors of all other derived DC require a running App
57
95
  spec.require_app spec.module_name
@@ -107,72 +107,48 @@ module WXRuby3
107
107
  spec.do_not_generate(:functions, :enums, :defines)
108
108
  when 'wxDirDialog'
109
109
  when 'wxProgressDialog'
110
- # These two have problematic arguments; they accept a bool pointer
111
- # which will be set to true if "skip" was pressed since the last
112
- # update. Dealt with below.
113
110
  spec.make_concrete 'wxProgressDialog'
114
111
  spec.items << 'wxGenericProgressDialog'
115
112
  spec.fold_bases('wxProgressDialog' => 'wxGenericProgressDialog')
116
- spec.ignore(%w[wxGenericProgressDialog::Pulse wxGenericProgressDialog::Update], ignore_doc: false) # keep docs
117
- # TODO : add docs for Ruby specials
113
+ if Config.instance.windows?
114
+ # The native dialog implementation for WXMSW is not usable with wxRuby because
115
+ # of it's multi-threaded nature so we explicitly use the generic implementation here
116
+ # (on most or all other platforms that is implicitly so).
117
+ spec.use_class_implementation 'wxProgressDialog', 'wxGenericProgressDialog'
118
+ end
119
+ # These two have problematic arguments; they accept a bool pointer
120
+ # which will be set to true if "skip" was pressed since the last
121
+ # update. Dealt with below.
122
+ spec.ignore(%w[wxGenericProgressDialog::Pulse wxGenericProgressDialog::Update])
118
123
  spec.add_extend_code 'wxProgressDialog', <<~__HEREDOC
119
- // In wxRuby there are two versions of each of these methods, the
120
- // standard one which returns just true/false depending on whether it
121
- // has been aborted, and a special one which returns a pair of values,
122
- // true/false for "aborted" and then true/false for "skipped"
124
+ // In wxRuby we change the return value for these methods to be either:
125
+ // - false if canceled
126
+ // - true if not canceled nor skipped
127
+ // - :skipped if skipped
123
128
  VALUE pulse(VALUE rb_msg = Qnil)
124
129
  {
130
+ static WxRuby_ID skipped_id("skipped");
131
+
125
132
  wxString new_msg;
126
133
  if ( rb_msg == Qnil )
127
134
  new_msg = wxEmptyString;
128
135
  else
129
136
  new_msg = wxString( StringValuePtr(rb_msg), wxConvUTF8 );
130
137
 
131
- if ( $self->Pulse(new_msg) )
132
- return Qtrue;
133
- else
134
- return Qfalse;
135
- }
136
-
137
- VALUE pulse_and_check(VALUE rb_msg = Qnil)
138
- {
139
- VALUE ret = rb_ary_new();
140
-
141
- wxString new_msg;
142
- if ( rb_msg == Qnil )
143
- new_msg = wxEmptyString;
144
- else
145
- new_msg = wxString( StringValuePtr(rb_msg), wxConvUTF8 );
146
-
147
138
  bool skip = false;
148
139
  if ( $self->Pulse(new_msg, &skip) )
149
- rb_ary_push(ret, Qtrue);
150
- else
151
- rb_ary_push(ret, Qfalse);
152
-
153
- rb_ary_push(ret, ( skip ? Qtrue : Qfalse) );
154
-
155
- return ret;
156
- }
157
-
158
- VALUE update(int value, VALUE rb_msg = Qnil)
159
- {
160
- wxString new_msg;
161
- if ( rb_msg == Qnil )
162
- new_msg = wxEmptyString;
163
- else
164
- new_msg = wxString( StringValuePtr(rb_msg), wxConvUTF8 );
165
-
166
- if ( $self->Update(value, new_msg) )
167
- return Qtrue;
140
+ {
141
+ if (skip) return ID2SYM(skipped_id());
142
+ else return Qtrue;
143
+ }
168
144
  else
169
145
  return Qfalse;
170
146
  }
171
147
 
172
- VALUE update_and_check(int value, VALUE rb_msg = Qnil)
148
+ VALUE update(int value, VALUE rb_msg = Qnil)
173
149
  {
174
- VALUE ret = rb_ary_new();
175
-
150
+ static WxRuby_ID skipped_id("skipped");
151
+
176
152
  wxString new_msg;
177
153
  if ( rb_msg == Qnil )
178
154
  new_msg = wxEmptyString;
@@ -181,13 +157,12 @@ module WXRuby3
181
157
 
182
158
  bool skip = false;
183
159
  if ( $self->Update(value, new_msg, &skip) )
184
- rb_ary_push(ret, Qtrue);
185
- else
186
- rb_ary_push(ret, Qfalse);
187
-
188
- rb_ary_push(ret, ( skip ? Qtrue : Qfalse) );
189
-
190
- return ret;
160
+ {
161
+ if (skip) return ID2SYM(skipped_id());
162
+ else return Qtrue;
163
+ }
164
+ else
165
+ return Qfalse;
191
166
  }
192
167
  __HEREDOC
193
168
  when 'wxWizard'
@@ -11,7 +11,9 @@ module WXRuby3
11
11
 
12
12
  def setup
13
13
  spec.require_app 'wxImageList'
14
- spec.rename_for_ruby('AddIcon' => 'wxImageList::Add(const wxIcon &)')
14
+ if Config.instance.windows? || Config.instance.macosx?
15
+ spec.ignore('wxImageList::Add(const wxIcon &)', ignore_doc: false)
16
+ end
15
17
  super
16
18
  end
17
19
  end # class ImageList
@@ -13,6 +13,47 @@ module WXRuby3
13
13
 
14
14
  def setup
15
15
  super
16
+ # we need access to the wxPrintPreview maintained in the frame
17
+ # for GC marking so define a derived class for that.
18
+ spec.add_header_code <<~__HEREDOC
19
+ class WxRubyPreviewFrame : public wxPreviewFrame
20
+ {
21
+ public:
22
+ WxRubyPreviewFrame(wxPrintPreviewBase *preview,
23
+ wxWindow *parent,
24
+ const wxString& title = wxGetTranslation(wxASCII_STR("Print Preview")),
25
+ const wxPoint& pos = wxDefaultPosition,
26
+ const wxSize& size = wxDefaultSize,
27
+ long style = wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT,
28
+ const wxString& name = wxASCII_STR(wxFrameNameStr))
29
+ : wxPreviewFrame(preview, parent, title, pos, size, style, name)
30
+ {}
31
+ virtual ~WxRubyPreviewFrame() {}
32
+
33
+ const wxPrintPreview* get_print_preview() const
34
+ {
35
+ return dynamic_cast<const wxPrintPreview*> (this->m_printPreview);
36
+ }
37
+ };
38
+
39
+ static void GC_mark_wxPreviewFrame(void *ptr)
40
+ {
41
+ if ( GC_IsWindowDeleted(ptr) )
42
+ return;
43
+
44
+ // Do standard marking routines as for all wxWindows
45
+ GC_mark_wxWindow(ptr);
46
+
47
+ WxRubyPreviewFrame* preview_frame = dynamic_cast<WxRubyPreviewFrame*>((wxPreviewFrame*)ptr);
48
+ if (preview_frame)
49
+ {
50
+ const void* ptr = (const void*)preview_frame->get_print_preview();
51
+ rb_gc_mark(SWIG_RubyInstanceFor(const_cast<void*> (ptr)));
52
+ }
53
+ }
54
+ __HEREDOC
55
+ spec.use_class_implementation 'wxPreviewFrame', 'WxRubyPreviewFrame'
56
+ spec.add_swig_code '%markfunc wxPreviewFrame "GC_mark_wxPreviewFrame";'
16
57
  spec.rename_for_ruby('init' => 'wxPreviewFrame::Initialize')
17
58
  # We do not wrap the (undocumented) wxPrintPreviewBase so map this to wxPrintPreview what
18
59
  # in all cases will be the actual base being used.
@@ -15,15 +15,13 @@ module WXRuby3
15
15
  spec.disable_proxies # fixed and final data structures
16
16
  spec.items << 'wxPrintDialogData' << 'wxPageSetupDialogData'
17
17
  spec.ignore 'wxPrintDialogData::SetSetupDialog' # deprecated since 2.5.4
18
- # make wxPrintDialogData GC-safe
19
- spec.ignore 'wxPrintDialogData::GetPrintData'
20
- spec.add_extend_code 'wxPrintDialogData', <<~__HEREDOC
21
- wxPrintData* GetPrintData()
22
- { return new wxPrintData(self->GetPrintData()); }
23
- __HEREDOC
24
- spec.new_object 'wxPrintDialogData::GetPrintData'
18
+ # only keep the const version
25
19
  spec.ignore 'wxPageSetupDialogData::GetPrintData'
26
20
  spec.regard 'wxPageSetupDialogData::GetPrintData() const'
21
+ # for GetPrintData methods
22
+ spec.map 'wxPrintData&' => 'Wx::PrintData' do
23
+ map_out code: '$result = SWIG_NewPointerObj(SWIG_as_voidptr(new wxPrintData(*$1)), SWIGTYPE_p_wxPrintData, SWIG_POINTER_OWN);'
24
+ end
27
25
  spec.swig_import 'swig/classes/include/wxDefs.h'
28
26
  end
29
27
  end # class PrintData
@@ -29,6 +29,7 @@ module WXRuby3
29
29
  Director.Spec(pkg, 'wxScreenDC', director: Director::DerivedDC)
30
30
  Director.Spec(pkg, 'wxSVGFileDC', director: Director::DerivedDC, requirements: %w[wxUSE_SVG])
31
31
  Director.Spec(pkg, 'wxGCDC', director: Director::DerivedDC, requirements: %w[wxUSE_GRAPHICS_CONTEXT])
32
+ Director.Spec(pkg, 'wxScaledDC', director: Director::DerivedDC)
32
33
  Director.Spec(pkg, 'wxWindow')
33
34
  Director.Spec(pkg, 'wxNonOwnedWindow', director: Director::Window)
34
35
  Director.Spec(pkg, 'wxPopupWindow')
@@ -171,6 +172,7 @@ module WXRuby3
171
172
  Director.Spec(pkg, 'wxCheckListBox', requirements: %w[wxUSE_CHECKLISTBOX])
172
173
  Director.Spec(pkg, 'wxDataFormat', requirements: %w[wxUSE_CLIPBOARD])
173
174
  Director.Spec(pkg, 'wxDataObject', requirements: %w[wxUSE_CLIPBOARD])
175
+ Director.Spec(pkg, 'wxDataObjectSimpleBase', requirements: %w[wxUSE_CLIPBOARD])
174
176
  Director.Spec(pkg, 'wxClipboard', requirements: %w[wxUSE_CLIPBOARD])
175
177
  Director.Spec(pkg, 'wxDragDrop', requirements: %w[wxUSE_DRAG_AND_DROP])
176
178
  Director.Spec(pkg, 'wxContextHelpButton', director: Director::Button, requirements: %w[wxUSE_HELP])
@@ -47,7 +47,7 @@ module WXRuby3
47
47
  map_argout as: {type: 'String', index: 1}, code: <<~__CODE
48
48
  if (result)
49
49
  {
50
- $result = rb_str_new( (const char*)data_buf$argnum.get(), data_size$argnum);
50
+ $result = rb_utf8_str_new( (const char*)data_buf$argnum.get(), data_size$argnum);
51
51
  }
52
52
  else
53
53
  $result = Qnil;
@@ -83,11 +83,20 @@ module WXRuby3
83
83
  map 'size_t len, const void* buf' do
84
84
 
85
85
  map_in from: {type: 'String', index: 1}, code: <<~__CODE
86
- $1 = RSTRING_LEN($input);
87
- $2 = (void*)StringValuePtr($input);
86
+ if (RTEST($input) && TYPE($input) == T_STRING)
87
+ {
88
+ $1 = RSTRING_LEN($input);
89
+ $2 = (void*)StringValuePtr($input);
90
+ }
91
+ else
92
+ {
93
+ $1 = 0; $2 = NULL;
94
+ }
88
95
  __CODE
89
96
 
90
- map_directorin code: '$input = rb_external_str_new( (const char *)buf, len );'
97
+ map_directorin code: '$input = rb_utf8_str_new( (const char *)buf, len );'
98
+
99
+ map_typecheck precedence: 'pointer', code: '$1 = (TYPE($input) == T_STRING);'
91
100
  end
92
101
 
93
102
  end # define