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

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