Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #211

Merged
merged 14 commits into from
Nov 2, 2023
19 changes: 19 additions & 0 deletions lib/wx/core/task_bar_button.rb
Original file line number Diff line number Diff line change
@@ -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
47 changes: 47 additions & 0 deletions rakelib/lib/director/accessible.rb
Original file line number Diff line number Diff line change
@@ -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<int>(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

6 changes: 6 additions & 0 deletions rakelib/lib/director/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
10 changes: 9 additions & 1 deletion rakelib/lib/director/frame.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions rakelib/lib/director/icon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
54 changes: 54 additions & 0 deletions rakelib/lib/director/media_ctrl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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<wxFileOffset> (NUM2LL(num));
#else
return static_cast<wxFileOffset> (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
Expand Down
2 changes: 2 additions & 0 deletions rakelib/lib/director/menu.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 6 additions & 2 deletions rakelib/lib/director/window.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ def setup
spec.ignore [
'wxWindow::TransferDataFromWindow',
'wxWindow::TransferDataToWindow',
'wxWindow::GetAccessible',
'wxWindow::PopEventHandler',
'wxWindow::SetConstraints',
'wxWindow::GetHandle',
Expand Down Expand Up @@ -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{
Expand Down
29 changes: 29 additions & 0 deletions rakelib/lib/typemap/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,35 @@ module Common
# do not seem to be virtual methods returning that
end

# const wxVector<int>&

map 'const wxVector<int>&' => 'Array<Integer>' do
map_in temp: 'wxVector<int> 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
Expand Down
2 changes: 1 addition & 1 deletion tests/test_list_ctrl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

require_relative './lib/wxframe_runner'

class ButtonTests < WxRuby::Test::GUITests
class ListCtrlTests < WxRuby::Test::GUITests

def setup
super
Expand Down
36 changes: 36 additions & 0 deletions tests/test_media_ctrl.rb
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions tools/check_swig_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand Down