diff --git a/lib/wx/core/task_bar_button.rb b/lib/wx/core/task_bar_button.rb new file mode 100644 index 00000000..2ac418a8 --- /dev/null +++ b/lib/wx/core/task_bar_button.rb @@ -0,0 +1,19 @@ +# Copyright (c) 2023 M.J.N. Corino, The Netherlands +# +# This software is released under the MIT license. + + +module Wx + + if Wx::PLATFORM == 'WXMSW' + class TaskBarButton + + wx_remove_thumb_bar_button = instance_method :remove_thumb_bar_button + define_method :remove_thumb_bar_button do |button| + button = button.get_id if button.is_a?(Wx::ThumbBarButton) + wx_remove_thumb_bar_button.bind(self).call(button) + end + + end + end +end diff --git a/rakelib/lib/director/accessible.rb b/rakelib/lib/director/accessible.rb new file mode 100644 index 00000000..6402751e --- /dev/null +++ b/rakelib/lib/director/accessible.rb @@ -0,0 +1,47 @@ +# Copyright (c) 2023 M.J.N. Corino, The Netherlands +# +# This software is released under the MIT license. + +### +# wxRuby3 wxWidgets interface director +### + +module WXRuby3 + + class Director + + class Accessible < Director + + def setup + super + spec.make_abstract 'wxAccessible' + spec.map 'wxAccessible**' => 'Wx::Accessible' do + map_in ignore: true, temp: 'wxAccessible* tmp', code: '$1 = &tmp;' + map_argout code: <<~__HEREDOC + if (tmp$argnum) + { + $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr(tmp$argnum), SWIGTYPE_p_wxAccessible, 0)); + } + __HEREDOC + + end + spec.map 'wxString *' => 'String' do + map_in ignore: true, temp: 'wxString tmp', code: '$1 = &tmp;' + map_argout code: '$result = SWIG_Ruby_AppendOutput($result, WXSTR_TO_RSTR(tmp$argnum));' + end + spec.map 'wxAccRole *' => 'Wx::AccRole' do + map_in ignore: true, temp: 'wxAccRole tmp', code: '$1 = &tmp;' + map_argout code: <<~__HEREDOC + $result = SWIG_Ruby_AppendOutput($result, wxRuby_GetEnumValueObject("AccRole", static_cast(tmp$argnum))); + __HEREDOC + end + spec.map_apply 'int * OUTPUT' => ['int * childCount', 'int * childId', 'int * toId'] + spec.map_apply 'long * OUTPUT' => 'long * state' + end + + end + + end + +end + diff --git a/rakelib/lib/director/app.rb b/rakelib/lib/director/app.rb index 44133e1c..914d346a 100644 --- a/rakelib/lib/director/app.rb +++ b/rakelib/lib/director/app.rb @@ -16,6 +16,12 @@ class App < EvtHandler def setup spec.items << 'wxAppConsole' << 'wxEventFilter' + if Config.platform == :mingw && Config.instance.wx_version >= '3.3.0' + spec.items << 'wxDarkModeSettings' + spec.disown 'wxDarkModeSettings *settings' + # wxDarkModeSettings does has have virt dtor; it's just not documented + spec.suppress_warning(514, 'wxDarkModeSettings') + end spec.fold_bases('wxApp' => 'wxAppConsole', 'wxAppConsole' => 'wxEventFilter') spec.override_inheritance_chain('wxApp', %w[wxEvtHandler wxObject]) spec.ignore %w{ diff --git a/rakelib/lib/director/frame.rb b/rakelib/lib/director/frame.rb index 10c52af7..245ab225 100644 --- a/rakelib/lib/director/frame.rb +++ b/rakelib/lib/director/frame.rb @@ -21,7 +21,15 @@ def setup when 'wxFrame' spec.ignore %w[ wxFrame::OnCreateStatusBar wxFrame::OnCreateToolBar] - unless Config.instance.features_set?(*%w[__WXMSW__ wxUSE_TASKBARBUTTON]) + if Config.instance.features_set?(*%w[__WXMSW__ wxUSE_TASKBARBUTTON]) + spec.items << 'wxTaskBarButton' << 'wxThumbBarButton' + spec.no_proxy 'wxTaskBarButton' + spec.gc_as_untracked 'wxTaskBarButton', 'wxThumbBarButton' + spec.disown 'wxThumbBarButton *button' + # superfluous and causing trouble for disown policy (re-implemented in pure Ruby) + spec.ignore 'wxTaskBarButton::RemoveThumbBarButton(wxThumbBarButton*)', ignore_doc: false + spec.new_object 'wxTaskBarButton::RemoveThumbBarButton(int)' + else spec.ignore('wxFrame::MSWGetTaskBarButton') end # this reimplemented window base method need to be properly wrapped but diff --git a/rakelib/lib/director/icon.rb b/rakelib/lib/director/icon.rb index 189d73aa..033f5c8f 100644 --- a/rakelib/lib/director/icon.rb +++ b/rakelib/lib/director/icon.rb @@ -25,9 +25,12 @@ def setup spec.ignore('wxIcon::wxIcon(const char *const *)', 'wxIcon::wxIcon(const char[],int,int)') # xml specs incorrectly list this method for MWS while it does not exist anymore spec.ignore('wxIcon::ConvertToDisabled') - unless Config.platform == :mingw + if Config.platform == :mingw + spec.ignore 'wxIconBundle::wxIconBundle(const wxString &, WXHINSTANCE)', + 'wxIconBundle::AddIcon(const wxString&,WXHINSTANCE)', + 'wxIcon::CreateFromHICON' + else spec.override_inheritance_chain('wxIcon', %w[wxBitmap wxGDIObject wxObject]) - spec.ignore 'wxIconBundle::wxIconBundle(const wxString &, WXHINSTANCE)' end super end diff --git a/rakelib/lib/director/media_ctrl.rb b/rakelib/lib/director/media_ctrl.rb index 9a85f5bd..eec0b490 100644 --- a/rakelib/lib/director/media_ctrl.rb +++ b/rakelib/lib/director/media_ctrl.rb @@ -16,6 +16,60 @@ class MediaCtrl < Window def setup super + spec.map 'const wxURI&' => 'URI' do + add_header <<~__CODE + static VALUE wxRuby_GetRubyURIClass() + { + static VALUE rb_cURI = Qnil; + if (NIL_P(rb_cURI)) + { + rb_require("uri"); + rb_cURI = rb_const_get(rb_cObject, rb_intern("URI")); + } + return rb_cURI; + } + static WxRuby_ID to_s_id("to_s"); + __CODE + map_in temp: 'wxURI tmp', code: <<~__CODE + if (rb_obj_is_kind_of($input, wxRuby_GetRubyURIClass())) + { + VALUE s = rb_funcall($input, to_s_id(), 0); + tmp = wxURI(RSTR_TO_WXSTR(s)); + $1 = &tmp; + } + else + { + rb_raise(rb_eArgError, "expected URI for %d", $argnum-1); + } + __CODE + map_typecheck precedence: 'POINTER', code: '$1 = rb_obj_is_kind_of($input, wxRuby_GetRubyURIClass());' + end + spec.map 'wxFileOffset' => 'Integer' do + # we need these inline methods here as we do not want SWIG to preprocess the code + # as it will do in the type mapping code sections + add_header_code <<~__CODE + inline wxFileOffset __ruby2wxFileOffset(VALUE num) + { + #ifdef wxHAS_HUGE_FILES + return static_cast (NUM2LL(num)); + #else + return static_cast (NUM2LONG(num)); + #endif + } + inline VALUE __wxFileOffset2ruby(wxFileOffset offs) + { + #ifdef wxHAS_HUGE_FILES + return LL2NUM(offs); + #else + return LONG2NUM(offs); + #endif + } + __CODE + + map_in code: '$1 = __ruby2wxFileOffset($input);' + map_out code: '$result = __wxFileOffset2ruby($1);' + map_typecheck code: '$1 = TYPE($input) == T_FIXNUM;' + end spec.do_not_generate :variables, :enums, :defines, :functions end end # class MediaCtrl diff --git a/rakelib/lib/director/menu.rb b/rakelib/lib/director/menu.rb index 247ce109..2f2a90cf 100644 --- a/rakelib/lib/director/menu.rb +++ b/rakelib/lib/director/menu.rb @@ -85,6 +85,8 @@ class wxRubyMenu : public wxMenu spec.add_swig_code <<~__HEREDOC %markfunc wxMenu "mark_wxMenu"; __HEREDOC + # ignore MSW specific method + spec.ignore 'wxMenu::MSWCommand' # fix SWIG's problems with const& return value spec.ignore('wxMenu::GetTitle', ignore_doc: false) # keep doc spec.add_extend_code 'wxMenu', <<~__HEREDOC diff --git a/rakelib/lib/director/window.rb b/rakelib/lib/director/window.rb index eeb18b48..7b9fdcba 100644 --- a/rakelib/lib/director/window.rb +++ b/rakelib/lib/director/window.rb @@ -68,7 +68,6 @@ def setup spec.ignore [ 'wxWindow::TransferDataFromWindow', 'wxWindow::TransferDataToWindow', - 'wxWindow::GetAccessible', 'wxWindow::PopEventHandler', 'wxWindow::SetConstraints', 'wxWindow::GetHandle', @@ -112,7 +111,12 @@ def setup if Config.instance.wx_version >= '3.3.0' spec.ignore('wxWindow::MSWDisableComposited') unless Config.instance.features_set?('__WXMSW__') end - spec.ignore('wxWindow::SetAccessible') unless Config.instance.features_set?('wxUSE_ACCESSIBILITY') + if Config.instance.features_set?('wxUSE_ACCESSIBILITY') + spec.disown 'wxAccessible *accessible' + else + spec.ignore('wxWindow::SetAccessible', + 'wxWindow::GetAccessible') + end spec.ignore(%w[wxWindow::RegisterHotKey wxWindow::UnregisterHotKey]) unless Config.instance.features_set?('wxUSE_HOTKEY') spec.ignore('wxWindow::SetSize(int, int)') # not useful as the wxSize variant will also accept an array spec.swig_import %w{ diff --git a/rakelib/lib/typemap/common.rb b/rakelib/lib/typemap/common.rb index 8a4638c0..440715a5 100644 --- a/rakelib/lib/typemap/common.rb +++ b/rakelib/lib/typemap/common.rb @@ -436,6 +436,35 @@ module Common # do not seem to be virtual methods returning that end + # const wxVector& + + map 'const wxVector&' => 'Array' do + map_in temp: 'wxVector tmp', code: <<~__CODE + if (($input == Qnil) || (TYPE($input) != T_ARRAY)) + { + VALUE dump = rb_inspect($input); + rb_raise(rb_eArgError, "expected Array of Integer for %d but got %s", + $argnum-1, StringValuePtr(dump)); + } + else + { + for (int i = 0; i < RARRAY_LEN($input); i++) + { + tmp.push_back(NUM2INT(rb_ary_entry($input,i))); + } + $1 = &tmp; + } + __CODE + map_directorin code: <<~__CODE + $input = rb_ary_new(); + for (size_t i = 0; i < $1.size(); i++) + { + rb_ary_push($input,INT2NUM( $1[i] ) ); + } + __CODE + map_typecheck precedence: 'INT32_ARRAY', code: '$1 = (TYPE($input) == T_ARRAY);' + end + # various enumerator type mappings map *%w[wxEdge wxRelationship wxKeyCode], as: 'Integer' do diff --git a/tests/test_list_ctrl.rb b/tests/test_list_ctrl.rb index 112bdc1e..851d542c 100644 --- a/tests/test_list_ctrl.rb +++ b/tests/test_list_ctrl.rb @@ -4,7 +4,7 @@ require_relative './lib/wxframe_runner' -class ButtonTests < WxRuby::Test::GUITests +class ListCtrlTests < WxRuby::Test::GUITests def setup super diff --git a/tests/test_media_ctrl.rb b/tests/test_media_ctrl.rb new file mode 100644 index 00000000..aea44ebc --- /dev/null +++ b/tests/test_media_ctrl.rb @@ -0,0 +1,36 @@ +# Copyright (c) 2023 M.J.N. Corino, The Netherlands +# +# This software is released under the MIT license. + +require_relative './lib/wxframe_runner' + +# test seems to deadlock for WXGTK +if Wx.has_feature?(:USE_MEDIACTRL) && Wx::PLATFORM != 'WXGTK' + +require 'uri' + +class MediaCtrlTests < WxRuby::Test::GUITests + + def setup + super + @media = Wx::MediaCtrl.new(frame_win) + end + + def cleanup + @media.destroy + super + end + + attr_reader :media + + def test_uri + # just checking if Ruby URI is properly mapped + uri = URI('/path/to/somewhere/media.type') + # can't check for true/false since the return value doesn't seem particularly + # reliable for non-existing media resources + assert_boolean(media.load(uri)) + end + +end + +end diff --git a/tools/check_swig_types.rb b/tools/check_swig_types.rb index 945fbd06..3cff0425 100644 --- a/tools/check_swig_types.rb +++ b/tools/check_swig_types.rb @@ -35,6 +35,12 @@ def scan_sources SWIG_TYPES_USED << type_str (SWIG_TYPES_USED_FILES[type_str] ||= ::Set.new) << File.basename(p) end + when /VALUE\s+vresult\s+=\s+SWIG_NewClassInstance\(self,\s*(SWIGTYPE_p_\w+)\);/ + SWIG_TYPES_USED << $1 + (SWIG_TYPES_USED_FILES[$1] ||= ::Set.new) << File.basename(p) + when /SwigClassWxBitmap.klass\s+=\s+rb_define_class_under\(.*\(\(swig_class\s+\*\)\s*(SWIGTYPE_p_\w+)->clientdata\)->klass\);/ + SWIG_TYPES_USED << $1 + (SWIG_TYPES_USED_FILES[$1] ||= ::Set.new) << File.basename(p) when /\A\s+SWIG_TypeClientData\((SWIGTYPE_p_\w+),/ if SWIG_TYPES_WRAPPED.include?($1) STDERR.puts "*** ERROR: SWIG type #{$1} defined multiple times."