cocoa 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,3 +2,23 @@ cocoa
2
2
  =====
3
3
 
4
4
  Ruby FFI bindings for the OSX Cocoa API
5
+
6
+ ### Installation
7
+
8
+ ```
9
+ gem install cocoa
10
+ ```
11
+
12
+ ### Usage
13
+
14
+ ```ruby
15
+ require 'cocoa'
16
+ array = Cocoa::NSMutableArray.array
17
+ array.addObject "head"
18
+ array.addObject "tail"
19
+ array.description
20
+ => (
21
+ head,
22
+ tail
23
+ )
24
+ ```
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- PROJECT_SPECS = FileList['spec/**/*.rb']
3
+ PROJECT_SPECS = FileList['spec/**/*_spec.rb']
4
4
 
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "cocoa"
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Patrick Hanevold"]
12
- s.date = "2014-03-25"
12
+ s.date = "2014-03-26"
13
13
  s.description = "Ruby FFI bindings for the OSX Cocoa API"
14
14
  s.email = "patrick.hanevold@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -411,9 +411,14 @@ Gem::Specification.new do |s|
411
411
  "lib/cocoa/bindings/NSXPCConnection.rb",
412
412
  "lib/cocoa/bindings/NSXPCInterface.rb",
413
413
  "lib/cocoa/bindings/NSXPCListener.rb",
414
+ "lib/cocoa/extensions.rb",
414
415
  "lib/cocoa/helpers.rb",
416
+ "lib/cocoa/objc.rb",
417
+ "lib/cocoa/structs/NSPoint.rb",
418
+ "lib/cocoa/structs/NSRect.rb",
419
+ "lib/cocoa/structs/NSSize.rb",
415
420
  "spec/cocoa/cocoa_spec.rb",
416
- "spec/cocoa/spec_helper.rb",
421
+ "spec/spec_helper.rb",
417
422
  "tasks/bacon.rake",
418
423
  "tasks/generate.rake",
419
424
  "tasks/setup.rake"
@@ -2,21 +2,7 @@
2
2
  require 'active_support'
3
3
 
4
4
  require 'cocoa/helpers'
5
- Dir[File.dirname(__FILE__) + '/cocoa/bindings/*'].each do |name|
6
- require "cocoa/bindings/#{name.split('/').last}"
7
- end
8
-
9
- class String
10
- def method_missing meth,*args
11
- if Cocoa::NSString.method_defined?(meth)
12
- str = Cocoa::NSString.new(true)
13
- str.object = Cocoa::String_to_NSString(self)
14
- str.send(meth,*args)
15
- else
16
- super
17
- end
18
- end
19
- end
5
+ require "cocoa/bindings/NSString"
20
6
 
21
7
  module Cocoa
22
8
  extend FFI::Library
@@ -28,6 +14,15 @@ module Cocoa
28
14
  attach_function :NSApplicationLoad, [], :bool
29
15
  NSApplicationLoad()
30
16
 
17
+ def const_missing name
18
+ if File.exists?(File.dirname(__FILE__) + "/cocoa/bindings/#{name}.rb")
19
+ require "cocoa/bindings/#{name}"
20
+ "Cocoa::#{name}".constantize
21
+ else
22
+ super
23
+ end
24
+ end
25
+
31
26
  CA_WARN_DEPRECATED = 1
32
27
  CFByteOrderBigEndian = 2
33
28
  CFByteOrderLittleEndian = 1
@@ -6720,3 +6715,4 @@ module Cocoa
6720
6715
  attach_method :NSZoneRealloc, :args=>3, :names=>[], :types=>["^{_NSZone=}", "^v", "Q"], :retval=>"^v"
6721
6716
  attach_method :NXReadNSObjectFromCoder, :args=>1, :names=>[], :types=>["@"], :retval=>"@"
6722
6717
  end
6718
+ require "cocoa/extensions"
@@ -0,0 +1,23 @@
1
+ class Cocoa::NSObject
2
+ def self.const_missing name
3
+ Cocoa.const_get name
4
+ end
5
+ end
6
+
7
+ class Cocoa::NSString < Cocoa::NSObject
8
+ def to_s
9
+ Cocoa::NSString_to_String(object)
10
+ end
11
+ end
12
+
13
+ class String
14
+ def method_missing meth,*args
15
+ if Cocoa::NSString.method_defined?(meth)
16
+ str = Cocoa::NSString.new(true)
17
+ str.object = Cocoa::String_to_NSString(self)
18
+ str.send(meth,*args)
19
+ else
20
+ super
21
+ end
22
+ end
23
+ end
@@ -1,94 +1,13 @@
1
1
  require 'active_support/inflector'
2
2
  require 'ffi'
3
-
4
- module ObjC
5
- extend FFI::Library
6
-
7
- # Load the 'libobjc' library.
8
- ffi_lib 'objc'
9
-
10
- # Bind the 'sel_registerName' function, which accepts a String and
11
- # returns an equivalent Objective-C selector (i.e. message name).
12
- attach_function :sel_registerName, [:string], :pointer
13
-
14
- # Bind the 'objc_msgSend' function, which sends a message to an
15
- # Objective-C object. It accepts a pointer to the object being sent
16
- # the message, a pointer to a selector, and a varargs array of
17
- # arguments to be sent with the message. It returns a pointer to the
18
- # result of sending the message.
19
- attach_function :objc_msgSend, [:pointer, :pointer, :varargs], :pointer
20
- #attach_function :objc_msgSend_stret, [:pointer, :pointer, :varargs], CGRect.by_value
21
-
22
- # A convenience method using objc_msgSend and sel_registerName to easily
23
- # send Objective-C messages from Ruby.
24
- def self.msgSend( id, selector, *args )
25
- selector = sel_registerName(selector) if selector.is_a? String
26
- objc_msgSend( id, selector, *args )
27
- end
28
-
29
- def self.msgSend_stret( return_type, id, selector, *args )
30
- selector = sel_registerName(selector) if selector.is_a? String
31
- method = "objc_msgSend_stret_for_#{return_type.name.underscore}".to_sym
32
- unless respond_to? method
33
- attach_function method, :objc_msgSend_stret, [:pointer, :pointer, :varargs], return_type.by_value
34
- end
35
- send(method, id, selector, *args )
36
- end
37
-
38
- # Bind the 'objc_getClass' function, which accepts the name of an
39
- # Objective-C class, and returns a pointer to that class.
40
- attach_function :objc_getClass, [:string], :pointer
41
-
42
- attach_function :objc_allocateClassPair, [:pointer, :string, :int], :pointer
43
- attach_function :objc_registerClassPair, [:pointer], :void
44
- end
45
-
46
- class CGPoint < FFI::Struct
47
- def initialize *args
48
- options = args.first
49
- if options.is_a? Hash
50
- self[:x] = options[:x]
51
- self[:y] = options[:y]
52
- else
53
- super *args
54
- end
55
- end
56
- layout :x, :double,
57
- :y, :double
58
- end
59
-
60
- class CGSize < FFI::Struct
61
- def initialize *args
62
- options = args.first
63
- if options.is_a? Hash
64
- self[:width] = options[:width]
65
- self[:height] = options[:height]
66
- else
67
- super *args
68
- end
69
- end
70
- layout :width, :double,
71
- :height, :double
72
- end
73
-
74
- class CGRect < FFI::Struct
75
- def initialize *args
76
- options = args.first
77
- if options.is_a? Hash
78
- self[:origin][:x] = options[:x]
79
- self[:origin][:y] = options[:y]
80
- self[:size][:width] = options[:width]
81
- self[:size][:height] = options[:height]
82
- else
83
- super *args
84
- end
85
- end
86
- layout :origin, CGPoint,
87
- :size, CGSize
88
- end
3
+ require 'cocoa/objc'
89
4
 
90
5
  module Cocoa; end
91
6
 
7
+ require 'cocoa/structs/NSPoint'
8
+ require 'cocoa/structs/NSSize'
9
+ require 'cocoa/structs/NSRect'
10
+
92
11
  class Cocoa::CFRange < FFI::Struct
93
12
  def initialize *args
94
13
  options = args.first
@@ -105,10 +24,6 @@ class Cocoa::CFRange < FFI::Struct
105
24
  layout :location, :long_long, :length, :long_long
106
25
  end
107
26
 
108
- NSRect = CGRect
109
- NSSize = CGSize
110
- NSPoint = CGPoint
111
-
112
27
  module Cocoa
113
28
 
114
29
  def instances
@@ -138,16 +53,12 @@ module Cocoa
138
53
  CFRange.new(location: loc, length: len)
139
54
  end
140
55
 
141
- # Accepts a Ruby String and creates an equivalent NSString instance
142
- # and returns a pointer to it.
143
56
  def self.String_to_NSString( string )
144
57
  nsstring_class = ObjC.objc_getClass("NSString")
145
58
  ObjC.msgSend( nsstring_class, "stringWithUTF8String:",
146
59
  :string, string )
147
60
  end
148
61
 
149
- # Accepts a pointer to an NSString object, and returns the string
150
- # contents as a Ruby String.
151
62
  def self.NSString_to_String( nsstring_pointer )
152
63
  c_string_pointer = ObjC.msgSend( nsstring_pointer, "UTF8String" )
153
64
  if c_string_pointer.null?
@@ -196,7 +107,7 @@ module Cocoa
196
107
 
197
108
  def self.attach_singular_method method,*params
198
109
  params = params.extract_options!
199
- params.freeze
110
+ params.freeze
200
111
  if params[:args] == 0
201
112
  define_singleton_method method do
202
113
  instance = new(true)
@@ -300,7 +211,13 @@ params.freeze
300
211
  instance = begin
301
212
  ("Cocoa::"+klass_name).constantize.new(true)
302
213
  rescue
303
- klass_name = "FIX_#{klass_name}" if klass_name[0]=='_'
214
+ klass_name = if klass_name =~ /^__NSCF/
215
+ "NS#{klass_name[6..-1]}"
216
+ elsif klass_name[0]=='_'
217
+ "FIX_#{klass_name}"
218
+ else
219
+ klass_name
220
+ end
304
221
  klass = begin
305
222
  Cocoa.const_get(klass_name)
306
223
  rescue => e
@@ -354,7 +271,7 @@ params.freeze
354
271
  end
355
272
 
356
273
  params = params.extract_options!
357
- params.freeze
274
+ params.freeze
358
275
  if params[:args] == 0
359
276
  begin
360
277
  attach_function "call_#{method}".to_sym, method, [], apple_type_to_ffi(params[:retval])
@@ -451,7 +368,6 @@ params.freeze
451
368
 
452
369
  def self.inherited(parent)
453
370
  if parent.name
454
- puts "INHERITED #{parent.name}" if parent.name =~ /Timer/
455
371
  klass = ObjC.objc_allocateClassPair(ObjC.objc_getClass(name.split('::').last),parent.name,0)
456
372
  ObjC.objc_registerClassPair(klass)
457
373
  end
@@ -553,7 +469,7 @@ puts "INHERITED #{parent.name}" if parent.name =~ /Timer/
553
469
  end
554
470
 
555
471
  def self.attach_singular_method method,*__params
556
- __params.freeze
472
+ __params.freeze
557
473
  return if method==:class
558
474
  return if method==:new
559
475
  if __params.first.is_a?(Hash) && __params.first[:args] == 0
@@ -564,11 +480,8 @@ __params.freeze
564
480
  end
565
481
  else
566
482
  _params = [__params.dup].flatten
567
- _params.freeze
483
+ _params.freeze
568
484
  define_singleton_method method do |*args|
569
- # puts method
570
- # puts args.inspect
571
- # puts _params.inspect
572
485
  par = if _params.size == 1 && _params.first[:variadic]
573
486
  _params
574
487
  else
@@ -613,7 +526,7 @@ _params.freeze
613
526
  @@method_specs ||= {}
614
527
  if _params.first.is_a? Array
615
528
  _params = [_params].flatten
616
- _params.freeze
529
+ _params.freeze
617
530
  define_method method do |*args|
618
531
  if args.last.is_a? Hash
619
532
  params = _params.select{ |par| par[:args] == args.last.size+1 && par[:names].map(&:to_sym).sort == args.last.keys.sort }
@@ -641,7 +554,7 @@ _params.freeze
641
554
  params = _params.extract_options!
642
555
  @@method_specs[method] = params
643
556
  if params[:args] == 0
644
- params.freeze
557
+ params.freeze
645
558
  define_method method do
646
559
  case params[:retval]
647
560
  when '@'
@@ -669,7 +582,6 @@ params.freeze
669
582
  ("Cocoa::"+klass_name).constantize.new(true)
670
583
  rescue
671
584
  klass_name = "FIX_#{klass_name}" if klass_name[0]=='_'
672
- # puts "TRYING #{klass_name}"
673
585
  klass = begin
674
586
  Cocoa.const_get(klass_name)
675
587
  rescue => e
@@ -720,7 +632,7 @@ params.freeze
720
632
  when '@'
721
633
  :pointer
722
634
  when /^{([^=]*)=.*}$/
723
- $1.constantize.by_value
635
+ Cocoa::const_get($1).by_value
724
636
  else
725
637
  raise type
726
638
  end
@@ -763,8 +675,8 @@ params.freeze
763
675
  def self.method_added(name)
764
676
  return if caller.first.split('`').last[0..-2] == 'define_method' # MRI
765
677
  return if caller.first.split('`').last[0..-2] == 'attach_method' # Rubinius
766
- method_definition = "#{self.name.underscore}_#{name.to_s.underscore}".to_sym
767
- add_method = "add_#{self.name.underscore}_#{name.to_s.underscore}".to_sym
678
+ method_definition = "#{self.name.gsub('::','__')}_#{name}".to_sym
679
+ add_method = "add_#{method_definition}".to_sym
768
680
 
769
681
  @method_callers ||= {}
770
682
  raise "allready added" if @method_callers[method_definition]
@@ -0,0 +1,25 @@
1
+ module ObjC
2
+ extend FFI::Library
3
+
4
+ ffi_lib 'objc'
5
+
6
+ attach_function :sel_registerName, [:string], :pointer
7
+ attach_function :objc_msgSend, [:pointer, :pointer, :varargs], :pointer
8
+ attach_function :objc_getClass, [:string], :pointer
9
+ attach_function :objc_allocateClassPair, [:pointer, :string, :int], :pointer
10
+ attach_function :objc_registerClassPair, [:pointer], :void
11
+
12
+ def self.msgSend( id, selector, *args )
13
+ selector = sel_registerName(selector) if selector.is_a? String
14
+ objc_msgSend( id, selector, *args )
15
+ end
16
+
17
+ def self.msgSend_stret( return_type, id, selector, *args )
18
+ selector = sel_registerName(selector) if selector.is_a? String
19
+ method = "objc_msgSend_stret_for_#{return_type.name.underscore}".to_sym
20
+ unless respond_to? method
21
+ attach_function method, :objc_msgSend_stret, [:pointer, :pointer, :varargs], return_type.by_value
22
+ end
23
+ send(method, id, selector, *args )
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ module Cocoa
2
+ class CGPoint < FFI::Struct
3
+ def initialize *args
4
+ options = args.first
5
+ if options.is_a? Hash
6
+ self[:x] = options[:x]
7
+ self[:y] = options[:y]
8
+ else
9
+ super *args
10
+ end
11
+ end
12
+ layout :x, :double,
13
+ :y, :double
14
+ end
15
+
16
+ NSPoint = CGPoint
17
+ end
@@ -0,0 +1,19 @@
1
+ module Cocoa
2
+ class CGRect < FFI::Struct
3
+ def initialize *args
4
+ options = args.first
5
+ if options.is_a? Hash
6
+ self[:origin][:x] = options[:x]
7
+ self[:origin][:y] = options[:y]
8
+ self[:size][:width] = options[:width]
9
+ self[:size][:height] = options[:height]
10
+ else
11
+ super *args
12
+ end
13
+ end
14
+ layout :origin, CGPoint,
15
+ :size, CGSize
16
+ end
17
+
18
+ NSRect = Cocoa::CGRect
19
+ end
@@ -0,0 +1,17 @@
1
+ module Cocoa
2
+ class CGSize < FFI::Struct
3
+ def initialize *args
4
+ options = args.first
5
+ if options.is_a? Hash
6
+ self[:width] = options[:width]
7
+ self[:height] = options[:height]
8
+ else
9
+ super *args
10
+ end
11
+ end
12
+ layout :width, :double,
13
+ :height, :double
14
+ end
15
+
16
+ NSSize = CGSize
17
+ end
@@ -1,17 +1,32 @@
1
- require_relative 'spec_helper'
1
+ require_relative '../spec_helper'
2
2
  require 'cocoa'
3
3
 
4
4
  describe 'Cocoa' do
5
+ it 'should lazy load cocoa classes in cocoa derived classes' do
6
+ class Derived < Cocoa::NSObject
7
+ def get_lazy
8
+ NSMenu.new
9
+ end
10
+ end
11
+ Derived.new.get_lazy.class.name.should == 'Cocoa::NSMenu'
12
+ end
13
+ it 'should provide correct return types for class methods' do
14
+ Cocoa::NSMutableArray.array.class.name.should == 'Cocoa::NSMutableArray'
15
+ end
16
+ it 'should provide correct return types for instance methods' do
17
+ array = Cocoa::NSMutableArray.array
18
+ Cocoa::NSMutableArray.array.description.class.name.should == 'Cocoa::NSString'
19
+ end
5
20
  it 'should convert NSString to ruby strings' do
6
21
  array = Cocoa::NSMutableArray.array
7
22
  array.addObject "head"
8
23
  array.addObject "tail"
9
24
  Cocoa::NSString_to_String(array.description.object).should == "(\n head,\n tail\n)"
10
25
  end
11
- it 'should return strings' do
26
+ it 'should return stringifyable strings' do
12
27
  array = Cocoa::NSMutableArray.array
13
28
  array.addObject "head"
14
29
  array.addObject "tail"
15
- array.description.should == "(\n head,\n tail\n)"
30
+ array.description.to_s.should == "(\n head,\n tail\n)"
16
31
  end
17
32
  end
@@ -1,4 +1,4 @@
1
- $: << File.expand_path(File.join(File.dirname(__FILE__), '/../../lib'))
1
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '/../lib'))
2
2
 
3
3
  # require 'simplecov'
4
4
 
@@ -120,21 +120,7 @@ task :generate do
120
120
  require 'active_support'
121
121
 
122
122
  require 'cocoa/helpers'
123
- Dir['lib/cocoa/bindings/*'].each do |name|
124
- require "cocoa/bindings/\#{name.split('/').last}"
125
- end
126
-
127
- class String
128
- def method_missing meth,*args
129
- if Cocoa::NSString.method_defined?(meth)
130
- str = Cocoa::NSString.new(true)
131
- str.object = Cocoa::String_to_NSString(self)
132
- str.send(meth,*args)
133
- else
134
- super
135
- end
136
- end
137
- end
123
+ require "cocoa/bindings/NSString"
138
124
 
139
125
  module Cocoa
140
126
  extend FFI::Library
@@ -146,6 +132,15 @@ module Cocoa
146
132
  attach_function :NSApplicationLoad, [], :bool
147
133
  NSApplicationLoad()
148
134
 
135
+ def const_missing name
136
+ if File.exists?(File.dirname(__FILE__) + "/cocoa/bindings/\#{name}.rb")
137
+ require "cocoa/bindings/\#{name}"
138
+ "Cocoa::\#{name}".constantize
139
+ else
140
+ super
141
+ end
142
+ end
143
+
149
144
  }
150
145
  enums.each do |name,value|
151
146
  mod.puts " #{name} = #{value}"
@@ -184,5 +179,6 @@ module Cocoa
184
179
  end
185
180
  end
186
181
  mod.puts "end"
182
+ mod.puts 'require "cocoa/extensions"'
187
183
  mod.close
188
184
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-25 00:00:00.000000000 Z
12
+ date: 2014-03-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -525,9 +525,14 @@ files:
525
525
  - lib/cocoa/bindings/NSXPCConnection.rb
526
526
  - lib/cocoa/bindings/NSXPCInterface.rb
527
527
  - lib/cocoa/bindings/NSXPCListener.rb
528
+ - lib/cocoa/extensions.rb
528
529
  - lib/cocoa/helpers.rb
530
+ - lib/cocoa/objc.rb
531
+ - lib/cocoa/structs/NSPoint.rb
532
+ - lib/cocoa/structs/NSRect.rb
533
+ - lib/cocoa/structs/NSSize.rb
529
534
  - spec/cocoa/cocoa_spec.rb
530
- - spec/cocoa/spec_helper.rb
535
+ - spec/spec_helper.rb
531
536
  - tasks/bacon.rake
532
537
  - tasks/generate.rake
533
538
  - tasks/setup.rake