hotcocoa 0.5.1 → 0.6.0pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. data/.yardopts +14 -0
  2. data/History.txt +21 -0
  3. data/README.markdown +84 -0
  4. data/Rakefile +47 -0
  5. data/bin/hotcocoa +20 -10
  6. data/docs/Contributors.markdown +25 -0
  7. data/docs/Mappings.markdown +352 -0
  8. data/docs/MappingsExplained.markdown +22 -0
  9. data/docs/Overview.markdown +58 -0
  10. data/docs/Resources.markdown +25 -0
  11. data/docs/Tutorial.markdown +3 -0
  12. data/lib/hotcocoa/application/builder.rb +237 -0
  13. data/lib/hotcocoa/application/specification.rb +373 -0
  14. data/lib/hotcocoa/application_builder.rb +338 -242
  15. data/lib/hotcocoa/attributed_string_helpers.rb +128 -0
  16. data/lib/hotcocoa/behaviors.rb +39 -6
  17. data/lib/hotcocoa/core_extensions/kernel.rb +67 -0
  18. data/lib/hotcocoa/core_extensions/nsarray.rb +15 -0
  19. data/lib/hotcocoa/core_extensions/nsmutable_attributed_string.rb +74 -0
  20. data/lib/hotcocoa/core_extensions/nsstring.rb +36 -0
  21. data/lib/hotcocoa/core_extensions/nsurl.rb +6 -0
  22. data/lib/hotcocoa/core_extensions/numeric.rb +9 -0
  23. data/lib/hotcocoa/core_extensions/object.rb +36 -0
  24. data/lib/hotcocoa/core_extensions/range.rb +30 -0
  25. data/lib/hotcocoa/core_extensions.rb +8 -0
  26. data/lib/hotcocoa/data_sources/combo_box_data_source.rb +38 -38
  27. data/lib/hotcocoa/data_sources/outline_view_data_source.rb +33 -0
  28. data/lib/hotcocoa/data_sources/table_data_source.rb +12 -13
  29. data/lib/hotcocoa/data_sources.rb +3 -0
  30. data/lib/hotcocoa/delegate_builder.rb +114 -79
  31. data/lib/hotcocoa/graphics/canvas.rb +211 -214
  32. data/lib/hotcocoa/graphics/color.rb +89 -91
  33. data/lib/hotcocoa/graphics/elements/particle.rb +16 -19
  34. data/lib/hotcocoa/graphics/elements/rope.rb +12 -14
  35. data/lib/hotcocoa/graphics/elements/sandpainter.rb +11 -13
  36. data/lib/hotcocoa/graphics/gradient.rb +13 -14
  37. data/lib/hotcocoa/graphics/image.rb +110 -83
  38. data/lib/hotcocoa/graphics/path.rb +44 -50
  39. data/lib/hotcocoa/graphics/pdf.rb +17 -19
  40. data/lib/hotcocoa/graphics.rb +21 -20
  41. data/lib/hotcocoa/kvo_accessors.rb +10 -11
  42. data/lib/hotcocoa/layout_view.rb +394 -379
  43. data/lib/hotcocoa/mapper.rb +346 -207
  44. data/lib/hotcocoa/mapping_methods.rb +107 -37
  45. data/lib/hotcocoa/mappings/appkit/alert.rb +25 -0
  46. data/lib/hotcocoa/mappings/appkit/application.rb +112 -0
  47. data/lib/hotcocoa/mappings/{array_controller.rb → appkit/array_controller.rb} +33 -35
  48. data/lib/hotcocoa/mappings/appkit/box.rb +37 -0
  49. data/lib/hotcocoa/mappings/appkit/button.rb +88 -0
  50. data/lib/hotcocoa/mappings/appkit/collection_view.rb +42 -0
  51. data/lib/hotcocoa/mappings/appkit/color.rb +40 -0
  52. data/lib/hotcocoa/mappings/appkit/column.rb +19 -0
  53. data/lib/hotcocoa/mappings/appkit/combo_box.rb +22 -0
  54. data/lib/hotcocoa/mappings/appkit/control.rb +31 -0
  55. data/lib/hotcocoa/mappings/appkit/font.rb +58 -0
  56. data/lib/hotcocoa/mappings/appkit/gradient.rb +19 -0
  57. data/lib/hotcocoa/mappings/appkit/image.rb +15 -0
  58. data/lib/hotcocoa/mappings/appkit/image_view.rb +41 -0
  59. data/lib/hotcocoa/mappings/appkit/label.rb +23 -0
  60. data/lib/hotcocoa/mappings/appkit/layout_view.rb +9 -0
  61. data/lib/hotcocoa/mappings/appkit/line.rb +16 -0
  62. data/lib/hotcocoa/mappings/appkit/menu.rb +78 -0
  63. data/lib/hotcocoa/mappings/appkit/menu_item.rb +47 -0
  64. data/lib/hotcocoa/mappings/appkit/outline_view.rb +62 -0
  65. data/lib/hotcocoa/mappings/appkit/popup.rb +106 -0
  66. data/lib/hotcocoa/mappings/appkit/progress_indicator.rb +61 -0
  67. data/lib/hotcocoa/mappings/appkit/scroll_view.rb +28 -0
  68. data/lib/hotcocoa/mappings/appkit/search_field.rb +9 -0
  69. data/lib/hotcocoa/mappings/appkit/secure_text_field.rb +15 -0
  70. data/lib/hotcocoa/mappings/appkit/segmented_control.rb +103 -0
  71. data/lib/hotcocoa/mappings/appkit/slider.rb +23 -0
  72. data/lib/hotcocoa/mappings/appkit/sound.rb +9 -0
  73. data/lib/hotcocoa/mappings/appkit/speech_synthesizer.rb +22 -0
  74. data/lib/hotcocoa/mappings/appkit/split_view.rb +19 -0
  75. data/lib/hotcocoa/mappings/appkit/status_bar.rb +7 -0
  76. data/lib/hotcocoa/mappings/appkit/status_item.rb +9 -0
  77. data/lib/hotcocoa/mappings/appkit/table_view.rb +108 -0
  78. data/lib/hotcocoa/mappings/appkit/text_field.rb +36 -0
  79. data/lib/hotcocoa/mappings/appkit/text_view.rb +13 -0
  80. data/lib/hotcocoa/mappings/appkit/toolbar.rb +99 -0
  81. data/lib/hotcocoa/mappings/appkit/toolbar_item.rb +36 -0
  82. data/lib/hotcocoa/mappings/appkit/tracking_area.rb +24 -0
  83. data/lib/hotcocoa/mappings/appkit/view.rb +65 -0
  84. data/lib/hotcocoa/mappings/appkit/window.rb +124 -0
  85. data/lib/hotcocoa/mappings/foundation/net_service.rb +65 -0
  86. data/lib/hotcocoa/mappings/foundation/net_service_browser.rb +27 -0
  87. data/lib/hotcocoa/mappings/foundation/notification.rb +24 -0
  88. data/lib/hotcocoa/mappings/foundation/sort_descriptor.rb +17 -0
  89. data/lib/hotcocoa/mappings/foundation/timer.rb +38 -0
  90. data/lib/hotcocoa/mappings/foundation/user_defaults.rb +43 -0
  91. data/lib/hotcocoa/mappings/foundation/xml_parser.rb +44 -0
  92. data/lib/hotcocoa/mappings/qtkit/movie.rb +15 -0
  93. data/lib/hotcocoa/mappings/qtkit/movie_view.rb +28 -0
  94. data/lib/hotcocoa/mappings/webkit/web_view.rb +20 -0
  95. data/lib/hotcocoa/mappings.rb +57 -111
  96. data/lib/hotcocoa/mvc.rb +90 -81
  97. data/lib/hotcocoa/notification_listener.rb +135 -58
  98. data/lib/hotcocoa/standard_rake_tasks.rb +17 -9
  99. data/lib/hotcocoa/target_action_convenience.rb +39 -0
  100. data/lib/hotcocoa/template.rb +90 -21
  101. data/lib/hotcocoa/version.rb +3 -0
  102. data/lib/hotcocoa.rb +12 -14
  103. data/template/Rakefile +31 -3
  104. data/template/__APPLICATION_NAME__.appspec +8 -0
  105. data/template/lib/application.rb +14 -17
  106. data/template/lib/menu.rb +11 -11
  107. data/test/application/test_builder.rb +28 -0
  108. data/test/application/test_specification.rb +280 -0
  109. data/test/core_extensions/test_kernel.rb +66 -0
  110. data/test/core_extensions/test_nsarray.rb +9 -0
  111. data/test/core_extensions/test_nsmutable_attributed_string.rb +86 -0
  112. data/test/core_extensions/test_nsstring.rb +20 -0
  113. data/test/core_extensions/test_nsurl.rb +9 -0
  114. data/test/core_extensions/test_numeric.rb +10 -0
  115. data/test/core_extensions/test_object.rb +37 -0
  116. data/test/core_extensions/test_range.rb +28 -0
  117. data/test/helper.rb +30 -0
  118. data/test/mappings/test_bonjour.rb +79 -0
  119. data/test/mappings/test_color.rb +16 -0
  120. data/test/mappings/test_font.rb +21 -0
  121. data/test/mappings/test_tracking_area.rb +18 -0
  122. data/test/test_application_builder.rb +95 -0
  123. data/test/test_attributed_string_helpers.rb +63 -0
  124. data/test/test_behaviours.rb +26 -0
  125. data/test/test_bin.rb +75 -0
  126. data/test/test_mapper.rb +100 -0
  127. data/test/test_mapping_methods.rb +67 -0
  128. data/test/test_mappings.rb +68 -0
  129. data/test/test_notification_listener.rb +19 -0
  130. data/test/test_template.rb +65 -0
  131. metadata +217 -90
  132. data/lib/hotcocoa/attributed_string.rb +0 -143
  133. data/lib/hotcocoa/kernel_ext.rb +0 -14
  134. data/lib/hotcocoa/mappings/alert.rb +0 -25
  135. data/lib/hotcocoa/mappings/application.rb +0 -112
  136. data/lib/hotcocoa/mappings/box.rb +0 -39
  137. data/lib/hotcocoa/mappings/button.rb +0 -92
  138. data/lib/hotcocoa/mappings/collection_view.rb +0 -44
  139. data/lib/hotcocoa/mappings/color.rb +0 -28
  140. data/lib/hotcocoa/mappings/column.rb +0 -21
  141. data/lib/hotcocoa/mappings/combo_box.rb +0 -24
  142. data/lib/hotcocoa/mappings/control.rb +0 -33
  143. data/lib/hotcocoa/mappings/font.rb +0 -44
  144. data/lib/hotcocoa/mappings/gradient.rb +0 -15
  145. data/lib/hotcocoa/mappings/image.rb +0 -15
  146. data/lib/hotcocoa/mappings/image_view.rb +0 -43
  147. data/lib/hotcocoa/mappings/label.rb +0 -25
  148. data/lib/hotcocoa/mappings/layout_view.rb +0 -9
  149. data/lib/hotcocoa/mappings/menu.rb +0 -71
  150. data/lib/hotcocoa/mappings/menu_item.rb +0 -47
  151. data/lib/hotcocoa/mappings/movie.rb +0 -13
  152. data/lib/hotcocoa/mappings/movie_view.rb +0 -27
  153. data/lib/hotcocoa/mappings/notification.rb +0 -17
  154. data/lib/hotcocoa/mappings/popup.rb +0 -110
  155. data/lib/hotcocoa/mappings/progress_indicator.rb +0 -68
  156. data/lib/hotcocoa/mappings/scroll_view.rb +0 -29
  157. data/lib/hotcocoa/mappings/search_field.rb +0 -9
  158. data/lib/hotcocoa/mappings/secure_text_field.rb +0 -17
  159. data/lib/hotcocoa/mappings/segmented_control.rb +0 -97
  160. data/lib/hotcocoa/mappings/slider.rb +0 -25
  161. data/lib/hotcocoa/mappings/sort_descriptor.rb +0 -13
  162. data/lib/hotcocoa/mappings/sound.rb +0 -9
  163. data/lib/hotcocoa/mappings/speech_synthesizer.rb +0 -25
  164. data/lib/hotcocoa/mappings/split_view.rb +0 -21
  165. data/lib/hotcocoa/mappings/status_bar.rb +0 -7
  166. data/lib/hotcocoa/mappings/status_item.rb +0 -9
  167. data/lib/hotcocoa/mappings/table_view.rb +0 -110
  168. data/lib/hotcocoa/mappings/text_field.rb +0 -41
  169. data/lib/hotcocoa/mappings/text_view.rb +0 -13
  170. data/lib/hotcocoa/mappings/timer.rb +0 -25
  171. data/lib/hotcocoa/mappings/toolbar.rb +0 -100
  172. data/lib/hotcocoa/mappings/toolbar_item.rb +0 -36
  173. data/lib/hotcocoa/mappings/view.rb +0 -67
  174. data/lib/hotcocoa/mappings/web_view.rb +0 -22
  175. data/lib/hotcocoa/mappings/window.rb +0 -118
  176. data/lib/hotcocoa/mappings/xml_parser.rb +0 -41
  177. data/lib/hotcocoa/object_ext.rb +0 -22
  178. data/lib/hotcocoa/plist.rb +0 -45
  179. data/template/config/build.yml +0 -8
  180. data/test/test_helper.rb +0 -3
  181. data/test/test_hotcocoa.rb +0 -11
data/.yardopts ADDED
@@ -0,0 +1,14 @@
1
+ --no-cache
2
+ --no-output
3
+ --verbose
4
+ --markup markdown
5
+ --markup-provider redcarpet
6
+ --readme README.markdown
7
+ lib/**/*.rb
8
+ -
9
+ History.txt
10
+ docs/Contributors.markdown
11
+ docs/Overview.markdown
12
+ docs/Resources.markdown
13
+ docs/Tutorial.markdown
14
+ docs/Mappings.markdown
data/History.txt CHANGED
@@ -1,3 +1,24 @@
1
+ === 0.6.0 2011-10-xx
2
+
3
+ * 8 enhancements:
4
+ * New application builder to work with MacRuby 0.11
5
+ * Application templates now use an appspec, similar to a gemspec
6
+ * Truer lazy loading for mappings (may break custom mappings!)
7
+ * API documention (67% coverage so far)
8
+ * Regression tests (< 67% coverage so far)
9
+ * Updating and porting of the tutorial documentation (~40% complete)
10
+ * HotCocoa now works when compiled
11
+ * HotCocoa is now leaner and meaner
12
+
13
+ * 3 new mappings:
14
+ * NSNetService => bonjour_service
15
+ * NSNetServiceBrowser => bonjour_browser
16
+ * NSBezierPath => line
17
+
18
+ * 2 graphics improvements:
19
+ * Image class works with more image types
20
+ * Image class can save images
21
+
1
22
  === 0.0.1 2009-11-07
2
23
 
3
24
  * 1 major enhancement:
data/README.markdown ADDED
@@ -0,0 +1,84 @@
1
+ # hotcocoa
2
+
3
+ * [http://github.com/ferrous26/hotcocoa](http://github.com/ferrous26/hotcocoa)
4
+ * [Documentation](http://rdoc.info/github/ferrous26/hotcocoa/master/frames) WIP
5
+
6
+ ## Description
7
+
8
+ HotCocoa is a thin, idiomatic Ruby layer that sits above Cocoa and
9
+ other frameworks. HotCocoa used to be included in MacRuby but is now
10
+ managed as a separate gem. This will allow HotCocoa to accept
11
+ contributions and evolve more quickly. To see more information on
12
+ HotCocoa (including tutorial) see
13
+ [http://macruby.org](http://macruby.org).
14
+
15
+ ## Note
16
+
17
+ This is a fork of HotCocoa that is being kept alive by myself and
18
+ other contributors; most of the work now is going in to documentation
19
+ and regression tests, but we are still adding new mappings, improving
20
+ existing mappings, and adding other features that we feel help meet
21
+ the goals of this project.
22
+
23
+ If you find issues with HotCocoa you can open issues and I (or
24
+ another contributor) will try to fix them.
25
+
26
+ There are a list of
27
+ [gotchas](https://github.com/ferrous26/hotcocoa/wiki/Gotchas) in the
28
+ wiki.
29
+
30
+ ## Install
31
+
32
+ * sudo macrake install
33
+
34
+ This fork is only available from source right now.
35
+
36
+ Note: If you are on Snow Leopard, you will also need the
37
+ [Bridge Support Preview](http://www.macruby.org/files/BridgeSupport%20Preview%203.zip)
38
+ in order to run this fork of HotCocoa. Read about it on the
39
+ [MacRuby Blog](http://www.macruby.org/blog/2010/10/08/bridgesupport-preview.html).
40
+
41
+ ## Documentation
42
+
43
+ Documentation is a work in progress; some of the documentation is
44
+ being ported from the MacRuby website where it is still available.
45
+
46
+ The documentation does not include the mappings right now due to the
47
+ way that mappings are implemented; a YARD plug-in is needed for that.
48
+
49
+ ## Contributing to HotCocoa
50
+
51
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
52
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
53
+ * Fork the project
54
+ * Start a feature/bugfix branch
55
+ * Commit and push until you are happy with your contribution
56
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
57
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
58
+ * No contribution is too small!
59
+
60
+ ## License
61
+
62
+ (The MIT License)
63
+
64
+ Copyright (c) 2009-2010 Richard Kilmer
65
+ Copyright (c) 2011 Mark Rada
66
+
67
+ Permission is hereby granted, free of charge, to any person obtaining
68
+ a copy of this software and associated documentation files (the
69
+ 'Software'), to deal in the Software without restriction, including
70
+ without limitation the rights to use, copy, modify, merge, publish,
71
+ distribute, sublicense, and/or sell copies of the Software, and to
72
+ permit persons to whom the Software is furnished to do so, subject to
73
+ the following conditions:
74
+
75
+ The above copyright notice and this permission notice shall be
76
+ included in all copies or substantial portions of the Software.
77
+
78
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
79
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
80
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
81
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
82
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
83
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
84
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ task :default => :build
2
+ task :build => :gem
3
+
4
+ if MACRUBY_REVISION.match(/^git commit/)
5
+ require 'rake/compiletask'
6
+ Rake::CompileTask.new
7
+ end
8
+
9
+ require 'rake/testtask'
10
+ Rake::TestTask.new do |t|
11
+ t.pattern = 'test/**/test_*.rb'
12
+ t.ruby_opts = ['-rtest/helper']
13
+ t.verbose = true
14
+ end
15
+
16
+ require 'rake/gempackagetask'
17
+ spec = Gem::Specification.load('hotcocoa.gemspec')
18
+ Rake::GemPackageTask.new(spec) { }
19
+
20
+ require 'rubygems/dependency_installer'
21
+ desc 'Install hotcocoa'
22
+ task :install => :gem do
23
+ Gem::Installer.new("pkg/#{spec.file_name}").install
24
+ end
25
+
26
+ # in reality this doesn't do the same dependency resolution that
27
+ # bundler is capable of, but this should be good 99% of the time
28
+ # and _way_ faster
29
+ desc 'Setup dependencies without* Bundler'
30
+ task :setup_dev do
31
+ (spec.runtime_dependencies + spec.development_dependencies).each do |dep|
32
+ Gem::DependencyInstaller.new.install(dep.name, dep.requirement)
33
+ end
34
+ end
35
+
36
+ desc 'Start up IRb with Hot Cocoa loaded'
37
+ task :console do
38
+ irb = ENV['RUBY_VERSION'] ? 'irb' : 'macirb'
39
+ sh "#{irb} -Ilib -rhotcocoa"
40
+ end
41
+
42
+ begin
43
+ require 'yard'
44
+ YARD::Rake::YardocTask.new
45
+ rescue LoadError
46
+ warn 'yard not available. Install it with: macgem install yard'
47
+ end
data/bin/hotcocoa CHANGED
@@ -2,30 +2,40 @@
2
2
 
3
3
  project_name = ARGV.shift
4
4
 
5
- if project_name.nil? or project_name == "--help" or project_name =="-h"
6
- puts "Usage: hotcocoa <project name>"
5
+ if project_name.nil? or project_name == '--help' or project_name == '-h'
6
+ puts 'Usage: hotcocoa <project name>'
7
+ exit
8
+ end
9
+
10
+ require 'rubygems'
11
+ require 'hotcocoa/version'
12
+ require 'hotcocoa/template'
13
+
14
+ if project_name == '-v' or project_name == '--version'
15
+ puts "HotCocoa #{HotCocoa::VERSION} (#{RUBY_DESCRIPTION})"
7
16
  exit
8
17
  end
9
18
 
10
19
  if File.exist?(project_name)
11
- if File.extname(project_name) == ".rb"
20
+ if File.extname(project_name) == '.rb'
12
21
  file_to_copy = project_name
13
- project_name = project_name[0..-4]
22
+ project_name = project_name.chomp '.rb'
14
23
  else
15
- puts %{Error: "#{project_name}" already exists in this directory.}
24
+ puts "Error: '#{project_name}' already exists in this directory."
16
25
  exit
17
26
  end
18
27
  else
19
28
  file_to_copy = nil
20
29
  end
21
30
 
22
- require 'hotcocoa/template'
23
- HotCocoa::Template.copy_to(project_name, project_name.split("_").collect(&:capitalize).join(" "))
31
+ pretty_project_name = project_name.split(/[^a-zA-Z0-9]/).collect do |name|
32
+ name.sub(/./) { |character| character.upcase }
33
+ end.join
34
+ HotCocoa::Template.new(project_name, pretty_project_name).copy!
24
35
 
25
36
  if file_to_copy
26
- lib_dir = File.join(project_name, "lib")
27
- File.open(File.join(lib_dir, "application.rb"), "w") do |file|
37
+ lib_dir = File.join(project_name, 'lib')
38
+ File.open(File.join(lib_dir, 'application.rb'), 'w') do |file|
28
39
  file.write File.read(file_to_copy)
29
40
  end
30
41
  end
31
-
@@ -0,0 +1,25 @@
1
+ # Contributors
2
+
3
+ Hot Cocoa was originally developed as part of the MacRuby standard
4
+ library; the project was led by Rich Kilmer and had contributions from
5
+ the MacRuby core team and a few others.
6
+
7
+ In late 2009, Hot Cocoa was pulled out of the MacRuby repository and
8
+ moved to Github.
9
+
10
+ ## Credits
11
+
12
+ * [Rich Kilmer](https://github.com/richkilmer)
13
+ * [Laurent Sansonetti](https://github.com/lrz)
14
+ * [Ben Stiglitz](https://github.com/benstiglitz)
15
+ * [Eloy Durán](https://github.com/alloy)
16
+ * [Vincent Isambart](https://github.com/vincentisambart)
17
+ * [Dan Sinclair](https://github.com/dj2)
18
+ * [Matt Aimonetti](https://github.com/mattetti)
19
+ * [Isaac Kearse](https://github.com/isaac)
20
+ * [reborg](https://github.com/reborg)
21
+ * [Patrick](https://github.com/hellopatrick)
22
+ * [Watson](https://github.com/watson1978)
23
+ * [Mark Rada](https://github.com/ferrous26)
24
+
25
+ If we forgot your name, let us know and we will add it.
@@ -0,0 +1,352 @@
1
+ ## Introduction
2
+
3
+ A HotCocoa mapping defines a structure that sits on top of a
4
+ particular Objective-C class and simplifies its usage in MacRuby.
5
+
6
+ This structure is defined in a simple, Ruby-based
7
+ [DSL](http://en.wikipedia.org/wiki/Domain-specific_language)
8
+ (domain-specific language). The HotCocoa DSL includes syntax to aid in
9
+ object instantiation, constant mapping, default options, customized
10
+ methods, and delegate-method mappings. The only required section is
11
+ object instantiation; the other four sections are only required if the
12
+ Objective-C class in question requires it. Once defined, a mapping is
13
+ registered with the {#HotCocoa::Mappings} module, using the names of
14
+ the mapping and the mapped Objective-C class.
15
+
16
+ The mappings that ship with HotCocoa are found in the
17
+ 'lib/hotcocoa/mappings' directory of the source. You can easily define
18
+ your own mappings for classes by following the examples below. Place
19
+ mappings in files of your own, loading them after you load the
20
+ `hotcocoa` library.
21
+
22
+ ## Basic Mapping Syntax
23
+
24
+ The basic syntax for defining a mapping is:
25
+
26
+ HotCocoa::Mappings.map name: CocoaClassName do
27
+ # mapping code...
28
+ end
29
+
30
+ To create a mapping, call the `map` method on `HotCocoa::Mappings`,
31
+ passing in a key-value pair to specify the constructor name and Cocoa
32
+ class to be mapped. Replace `name:` with the desired name of the method
33
+ you want to be generated and made available to users of HotCocoa. For
34
+ example, the mapping definition for an `NSButton` might be:
35
+
36
+ HotCocoa::Mappings.map button: NSButton do
37
+ # mapping code...
38
+ end
39
+
40
+ This creates a method on HotCocoa named `button`, which will return
41
+ an instance of an `NSButton` class. One caveat to note now is that
42
+ the class being mapped has to be available when you define the
43
+ mapping. `NSButton` is available because HotCocoa loads the `Cocoa`
44
+ framework; if you want to map a class from `AVFoundation` then you
45
+ will need to load `AVFoundation` before you define any mappings.
46
+
47
+ You can create more than one mapping per Objective-C class. A good
48
+ reason to do this would be to provide different sets of defaults. As
49
+ an example,
50
+ [Interface Builder](http://en.wikipedia.org/wiki/Interface_Builder)
51
+ provides several "different" types of buttons in its Object Library,
52
+ but they are all instances of `NSButton` that just have a different
53
+ default configuration.
54
+
55
+ ## Object Instantiation Method (required)
56
+
57
+ There are two methods, `#init_with_options` and `#alloc_with_options`,
58
+ that you can implement to support object instantiation. Define these
59
+ methods within the block that you pass to the `map` method.
60
+
61
+ HotCocoa::Mappings.map button: NSButton do
62
+ def init_with_options buttons, options
63
+ button.initWithFrame options.delete(:frame)
64
+ end
65
+ end
66
+
67
+ As you can see from the method definition above, the
68
+ `#init_with_options` method is provided with an instance of the class
69
+ that you declared in the mapping (`NSButton`) which is created with
70
+ `NSButton.alloc`. This implementation just calls the proper `#init`
71
+ method. This example calls `#initWithFrame` and passes the options
72
+ value for the `:frame`. The options hash is passed to this function
73
+ when you call the `#button` method:
74
+
75
+ button frame: [0,0,20,100]
76
+
77
+ Note that the method must delete any option that it consumes and must
78
+ return the mapped object. Every option used in the construction of the
79
+ object should be removed from the hash. Any options that are left in the hash
80
+ after begin processed by the instantiation methods will be dispatched
81
+ to the `NSButton` instance.
82
+
83
+ The second method you can implement is:
84
+
85
+ HotCocoa::Mappings.map button: NSButton do
86
+ def alloc_with_options options
87
+ NSButton.alloc.initWithFrame options.delete(:frame)
88
+ end
89
+ end
90
+
91
+ Here you are not provided with the `alloc`'d object as the first
92
+ parameter, but simply the options hash. This is helpful for classes
93
+ that use class methods for instantiation, such as:
94
+
95
+ NSImage.imageNamed 'my_image'
96
+
97
+ You should implement either `#init_with_options` or
98
+ `#alloc_with_options`, but not both. If `#alloc_with_options` exists,
99
+ it will be called and `#init_with_options` will be ignored.
100
+
101
+ If you want a constructor to handle a block with extra behavior then
102
+ you will also need to implement `#handle_block` for the mapping. Block
103
+ handling is done after the mapped instance has been initialized and
104
+ `#handle_block` will be given the instance as a parameter. For
105
+ instance, HotCocoa uses this construct to encapsulate normal
106
+ application setup:
107
+
108
+ HotCocoa::Mappings.map application: NSApplication do
109
+ def alloc_with_options opts
110
+ NSApplication.sharedApplication
111
+ end
112
+ def handle_block app
113
+ load_menus
114
+ yield application
115
+ application.run
116
+ end
117
+ end
118
+
119
+ HotCocoa.application do |app|
120
+ app.delegate = self
121
+ end
122
+
123
+ ## Default Options (optional)
124
+
125
+ You can provide a hash of default options in the definition of your
126
+ mapping. This is very useful for many Cocoa classes, because there are
127
+ so many configuration options. Defaults are appended to the options
128
+ hash that is passed into the constructor method if a value of the same
129
+ key does not exist.
130
+
131
+ Supplying your defaults is simple. In the example below, if you
132
+ provide a `:frame`, it will be used instead of `CGRectZero`:
133
+
134
+ HotCocoa::Mappings.map button: NSButton do
135
+ defaults bezel: :rounded,
136
+ frame: CGRectZero,
137
+ layout: {}
138
+ end
139
+
140
+ A few of the defaults shown above are pretty important to UI classes;
141
+ specifically, `:frame` and `:layout`. The `NSButton` example uses
142
+ `frame: CGRectZero`. The `CGRectZero` constant equals a rectangle of
143
+ `[0,0,0,0]`. The `layout: {}` part is important for using the
144
+ `layout_view` classes, which are included in HotCocoa, it describes
145
+ where to put the UI element.
146
+
147
+ This default value for the layout is an empty hash, but if it's not
148
+ passed, the default value for the layout is actually `nil`. If the
149
+ layout is `nil`, the component is not included when the `layout_view`
150
+ computes the layout for the components. All of the UI mappings that ship with
151
+ HotCocoa provide an empty hash as a default `:layout`.
152
+
153
+ ## Constant Mapping (optional, inherited)
154
+
155
+ Because constant names need to be globally unique in Objective-C, they
156
+ can get very long. What the constant mapping provides in HotCocoa is
157
+ the ability to use short symbol names and map them to the constant
158
+ names that are scoped to the wrapped class. This is an example of
159
+ mapping constants to represent button state:
160
+
161
+ HotCocoa::Mappings.map button: NSButton do
162
+ constant :state, {
163
+ on: NSOnState,
164
+ off: NSOffState,
165
+ mixed: NSMixedState
166
+ }
167
+ end
168
+
169
+ A constant map includes the key (`:state`), followed by a hash which
170
+ maps symbols to actual constants. When you provide options to the
171
+ constructor method that match a constant key, it looks up the
172
+ corresponding value in that hash and replaces the value in the option
173
+ hash with the constant's value.
174
+
175
+ So, when you call:
176
+
177
+ button :state => :on
178
+
179
+ It will be replaced with:
180
+
181
+ button :state => NSOnState
182
+
183
+ You can have as many constant maps in each class as you need. Constant
184
+ maps are also inherited by subclasses. A constant map on `NSView` is
185
+ also available on `NSControl` and `NSButton` (as they are subclasses).
186
+
187
+ If you provide a value for a constant key that is an array rather than
188
+ a single symbol, the constants in the array are __OR__'d with each
189
+ other. This is useful when the constants are masked. For `NSWindow`'s
190
+ mapping of style:
191
+
192
+ { style: [:titled, :closable, :miniaturizable, :resizable] }
193
+
194
+ is equivalent to:
195
+
196
+ style = NSTitledWindowMask |
197
+ NSClosableWindowMask |
198
+ NSMiniaturizableWindowMask |
199
+ NSResizableWindowMask
200
+
201
+ ## Custom Methods (optional, inherited)
202
+
203
+ Custom methods are simply modules that are included in the instance;
204
+ they provide idiomatic Ruby methods for the mapped Objective-C class
205
+ instance. Providing custom methods in your mapping is easy:
206
+
207
+ HotCocoa::Mappings.map button: NSButton do
208
+ custom_methods do
209
+ def bezel= value
210
+ setBezelStyle(value)
211
+ end
212
+ def on?
213
+ state == NSOnState
214
+ end
215
+ end
216
+ end
217
+
218
+ In the first method, `#bezel=`, we provide a better method name than
219
+ `setBezelStyle`. Although we could provide idiomatic Ruby methods for
220
+ every Objective-C method, the number of these methods is huge. The
221
+ general principle is to customize where this provides something
222
+ better, not just syntactically better. Custom methods, like constant
223
+ mappings, are inherited by subclasses.
224
+
225
+ ## Constant Mappings and Custom Methods
226
+
227
+ In the last example, the `#bezel=` method serves as a corresponding
228
+ method name to the constant map for bezel style:
229
+
230
+ constant :bezel, {
231
+ rounded: NSRoundedBezelStyle,
232
+ regular_square: NSRegularSquareBezelStyle,
233
+ thick_square: NSThickSquareBezelStyle,
234
+ thicker_square: NSThickerSquareBezelStyle,
235
+ disclosure: NSDisclosureBezelStyle,
236
+ shadowless_square: NSShadowlessSquareBezelStyle,
237
+ circular: NSCircularBezelStyle,
238
+ textured_square: NSTexturedSquareBezelStyle,
239
+ help_button: NSHelpButtonBezelStyle,
240
+ small_square: NSSmallSquareBezelStyle,
241
+ textured_rounded: NSTexturedRoundedBezelStyle,
242
+ round_rect: NSRoundRectBezelStyle,
243
+ recessed: NSRecessedBezelStyle,
244
+ rounded_disclosure: NSRoundedDisclosureBezelStyle
245
+ }
246
+
247
+ This way, you can easily create buttons of the provided bezel style:
248
+
249
+ button :bezel => :circular
250
+
251
+ If you recall from the default options section (above), you can also
252
+ include default values that are constant mapped values (e.g.
253
+ `:bezel => :rounded` is the default for a button). In this way,
254
+ constant mappings and custom methods work together to provide a vastly
255
+ better syntax for using constants in your code and simplifying the
256
+ code needed for an `#init_with_options` method.
257
+
258
+ ## Delegate Method Mapping (optional)
259
+
260
+ Delegate method mapping is a little more complex then the prior
261
+ sections. Delegate methods are used pervasively in Cocoa to facilitate
262
+ customization of controls. Normally, what you need to do is implement
263
+ the methods that the control is looking for in a class of your
264
+ own. You would then set an instance of that class as the delegate of
265
+ the control, using `setDelegate(instance)`.
266
+
267
+ In HotCocoa, we wanted to enable the use of Ruby blocks for delegate
268
+ method calls, so the Objective-C code:
269
+
270
+ class MyDelegate
271
+ def windowWillClose sender
272
+ # perform something
273
+ end
274
+ end
275
+
276
+ window.setDelegate(MyDelegate.new)
277
+
278
+ is simplified to the Ruby code:
279
+
280
+ window.will_close do
281
+ # perform something
282
+ end
283
+
284
+ Notice that we do not have to worry about the `sender` parameter
285
+ because the sender is `window`.
286
+
287
+ To enable HotCocoa style delegation, you map individual delegate
288
+ methods to a symbol name, then map parameters that are passed to that
289
+ delegate method to the block parameters. For `NSWindow` the definition
290
+ for delegating `windowWillClose`, which passes no parameters to the
291
+ block, would be:
292
+
293
+ HotCocoa::Mappings.map window: NSWindow do
294
+ delegating 'windowWillClose:', to: :will_close
295
+ end
296
+
297
+ This creates a `#will_close` method that accepts the block (as
298
+ above). For the sake of efficiency, it:
299
+
300
+ 1. creates an object
301
+ 2. adds the delegating method (`#windowWillClose`) as a method on that
302
+ object's singleton class
303
+ 3. stores the passed-in block inside that object
304
+
305
+ The generated `#windowWillClose` method calls that block when Cocoa
306
+ calls the `#windowWillClose` method. Each time a delegate method is
307
+ created, the object is set as the delegate (using `#setDelegate`).
308
+
309
+ When a delegate needs to forward parameters to the block, the
310
+ definition becomes a little more complex:
311
+
312
+ HotCocoa::Mappings.map window: NSWindow do
313
+ delegating 'window:willPositionSheet:usingRect:', to: :will_position_sheet, parameters: [:willPositionSheet, :usingRect]
314
+ end
315
+
316
+ The `parameters:` list contains the corresponding selector name from
317
+ the Objective-C selector. Even though the delegate method normally has
318
+ three parameters (`window`, `willPositionSheet`, and `usingRect`), the
319
+ block will only be passed the last two (because we already have the
320
+ first parameter). Using this method would look like:
321
+
322
+ window.will_position_sheet do |sheet, rect|
323
+ # ...
324
+ end
325
+
326
+ It's also possible to map a parameter, in cases where you have to
327
+ invoke a more complex calling on the parameter:
328
+
329
+ HotCocoa::Mappings.map window: NSWindow do
330
+ delegating 'windowDidExpose:', to: :did_expose, parameters: ["windowDidExpose.userInfo['NSExposedRect']"]
331
+ end
332
+
333
+ Here we want to walk the first parameter's `userInfo` dictionary, get
334
+ the `NSExposedRect` rectangle, and pass it as a parameter to the
335
+ `did_expose` block. Using this method would look like:
336
+
337
+ window.did_expose do | rect|
338
+ # ...
339
+ end
340
+
341
+ Each method for a delegate has to be mapped with an individual
342
+ delegating call.
343
+
344
+ ## When To Make A Mapping
345
+
346
+ The best candidates for a new HotCocoa mappings are classes that
347
+ require a lot of configuration. Though sometimes it is convenient to
348
+ make a mapping just to take advantage of a mapping feature that
349
+ HotCocoa provides, such as block-based delegation.
350
+
351
+ If you have mappings that you would like to share, feel free to open a
352
+ pull request on [Github](http://github.com/ferrous26/hotcocoa).
@@ -0,0 +1,22 @@
1
+ # Mappings
2
+
3
+ Hot Cocoa mappings are the centre piece of the library; they allow for
4
+ instantiation and configuration of Cocoa classes using much more
5
+ concise syntax than their native interface.
6
+
7
+ There are two ways to use a mapping---either by including the Hot
8
+ Cocoa behaviours or by extending them. This is a natural extension of
9
+ Ruby's ability to `#include` and `#extend`.
10
+
11
+ To include the behaviours, you would subclass an Objective-C class and
12
+ then `#include` {HotCocoa::Behaviors}.
13
+
14
+ To `#extend` and instance of an Objective-C class, you would just use
15
+ the HotCocoa constructors.
16
+
17
+ {file:docs/NewMappings.markdown New Mappings} can be added
18
+ for any Objective-C class, in fact, you can create a mapping for any
19
+ class, even your own.
20
+
21
+ Mappings are organized by the framework to which they belong. This is
22
+ so that they are not loaded until the framework they belong to is loaded.
@@ -0,0 +1,58 @@
1
+ # Overview
2
+
3
+ If you've done any amount of programming on Mac OS X, you know that
4
+ the API can be quite verbose. Even with MacRuby's wonderful keyword
5
+ arguments, it can be daunting to enter this...
6
+
7
+ win = NSWindow.alloc.initWithContentRect [10,20,300,300],
8
+ styleMask: (NSTitledWindowMask |
9
+ NSClosableWindowMask |
10
+ NSMiniaturizableWindowMask |
11
+ NSResizableWindowMask)
12
+
13
+ ...every time you want to create and configure a new `NSWindow` instance!
14
+
15
+ This is the reason most developers use [Interface Builder](http://en.wikipedia.org/wiki/Interface_Builder)
16
+ to configure interface components.
17
+ The purpose of HotCocoa is to allow you to use the flexible syntax of
18
+ Ruby and its dynamic nature to simplify programmatically constructing
19
+ user interfaces on Mac OS X without an Interface Builder.
20
+
21
+ With HotCocoa, creating the `NSWindow` instance above is as simple as:
22
+
23
+ win = window frame: [10,20,300,300]
24
+
25
+ HotCocoa achieves this feat by creating Mappings over the most common
26
+ Classes and Constants used on Mac OS X. Those mappings create
27
+ constructor methods on the HotCocoa module (like the "window" method
28
+ above). Each constructor method accepts an optional block which yields
29
+ the created instance (more on that in the
30
+ {file:docs/Tutorial.markdown HotCocoa Tutorial}). Mappings also
31
+ decorate the standard Objective-C API with nice Ruby APIs for
32
+ common operations. The important thing to realize is that the
33
+ constructor methods return real instances of these common classes, not
34
+ high-level abstractions. So, you can call any Objective-C method
35
+ available on those objects.
36
+
37
+ In HotCocoa, Mappings provide the following:
38
+
39
+ * Defaults: Smart default constructor parameters (like the styles in
40
+ window) to minimize the parameters you have to pass in.
41
+ * Constants: Mapping of constants to Ruby symbols to minimize the text
42
+ and maximize the readability of HotCocoa applications.
43
+ * Constructors: Building the instances of the mapped classes using the
44
+ correct class-specific APIs.
45
+ * Custom Methods: Ruby-friendly API for commonly used methods (like
46
+ `#<<` for `#addSubview` on `NSView` subclasses).
47
+ * Delegate Methods: Simplified Ruby-friendly methods for delegating
48
+ instances that use Ruby blocks
49
+
50
+ Now that you understand the basics of what HotCocoa is and why we are
51
+ building it, please look at
52
+ {file:docs/Resources.markdown HotCocoa Resources} (and eventually, the
53
+ {file:docs/Tutorial.markdown HotCocoa Tutorial}) for examples of how
54
+ to build Mac OS X applications with it. For a more detailed
55
+ understanding of how to read, create, edit, or contribute mapping
56
+ files, see {file:docs/Mappings.markdown HotCocoa Mappings}. For the
57
+ current status of the project, visit the
58
+ [code repository](http://github.com/ferrous26/hotcocoa) on Github.