hotcocoa 0.5.1 → 0.6.0pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +14 -0
- data/History.txt +21 -0
- data/README.markdown +84 -0
- data/Rakefile +47 -0
- data/bin/hotcocoa +20 -10
- data/docs/Contributors.markdown +25 -0
- data/docs/Mappings.markdown +352 -0
- data/docs/MappingsExplained.markdown +22 -0
- data/docs/Overview.markdown +58 -0
- data/docs/Resources.markdown +25 -0
- data/docs/Tutorial.markdown +3 -0
- data/lib/hotcocoa/application/builder.rb +237 -0
- data/lib/hotcocoa/application/specification.rb +373 -0
- data/lib/hotcocoa/application_builder.rb +338 -242
- data/lib/hotcocoa/attributed_string_helpers.rb +128 -0
- data/lib/hotcocoa/behaviors.rb +39 -6
- data/lib/hotcocoa/core_extensions/kernel.rb +67 -0
- data/lib/hotcocoa/core_extensions/nsarray.rb +15 -0
- data/lib/hotcocoa/core_extensions/nsmutable_attributed_string.rb +74 -0
- data/lib/hotcocoa/core_extensions/nsstring.rb +36 -0
- data/lib/hotcocoa/core_extensions/nsurl.rb +6 -0
- data/lib/hotcocoa/core_extensions/numeric.rb +9 -0
- data/lib/hotcocoa/core_extensions/object.rb +36 -0
- data/lib/hotcocoa/core_extensions/range.rb +30 -0
- data/lib/hotcocoa/core_extensions.rb +8 -0
- data/lib/hotcocoa/data_sources/combo_box_data_source.rb +38 -38
- data/lib/hotcocoa/data_sources/outline_view_data_source.rb +33 -0
- data/lib/hotcocoa/data_sources/table_data_source.rb +12 -13
- data/lib/hotcocoa/data_sources.rb +3 -0
- data/lib/hotcocoa/delegate_builder.rb +114 -79
- data/lib/hotcocoa/graphics/canvas.rb +211 -214
- data/lib/hotcocoa/graphics/color.rb +89 -91
- data/lib/hotcocoa/graphics/elements/particle.rb +16 -19
- data/lib/hotcocoa/graphics/elements/rope.rb +12 -14
- data/lib/hotcocoa/graphics/elements/sandpainter.rb +11 -13
- data/lib/hotcocoa/graphics/gradient.rb +13 -14
- data/lib/hotcocoa/graphics/image.rb +110 -83
- data/lib/hotcocoa/graphics/path.rb +44 -50
- data/lib/hotcocoa/graphics/pdf.rb +17 -19
- data/lib/hotcocoa/graphics.rb +21 -20
- data/lib/hotcocoa/kvo_accessors.rb +10 -11
- data/lib/hotcocoa/layout_view.rb +394 -379
- data/lib/hotcocoa/mapper.rb +346 -207
- data/lib/hotcocoa/mapping_methods.rb +107 -37
- data/lib/hotcocoa/mappings/appkit/alert.rb +25 -0
- data/lib/hotcocoa/mappings/appkit/application.rb +112 -0
- data/lib/hotcocoa/mappings/{array_controller.rb → appkit/array_controller.rb} +33 -35
- data/lib/hotcocoa/mappings/appkit/box.rb +37 -0
- data/lib/hotcocoa/mappings/appkit/button.rb +88 -0
- data/lib/hotcocoa/mappings/appkit/collection_view.rb +42 -0
- data/lib/hotcocoa/mappings/appkit/color.rb +40 -0
- data/lib/hotcocoa/mappings/appkit/column.rb +19 -0
- data/lib/hotcocoa/mappings/appkit/combo_box.rb +22 -0
- data/lib/hotcocoa/mappings/appkit/control.rb +31 -0
- data/lib/hotcocoa/mappings/appkit/font.rb +58 -0
- data/lib/hotcocoa/mappings/appkit/gradient.rb +19 -0
- data/lib/hotcocoa/mappings/appkit/image.rb +15 -0
- data/lib/hotcocoa/mappings/appkit/image_view.rb +41 -0
- data/lib/hotcocoa/mappings/appkit/label.rb +23 -0
- data/lib/hotcocoa/mappings/appkit/layout_view.rb +9 -0
- data/lib/hotcocoa/mappings/appkit/line.rb +16 -0
- data/lib/hotcocoa/mappings/appkit/menu.rb +78 -0
- data/lib/hotcocoa/mappings/appkit/menu_item.rb +47 -0
- data/lib/hotcocoa/mappings/appkit/outline_view.rb +62 -0
- data/lib/hotcocoa/mappings/appkit/popup.rb +106 -0
- data/lib/hotcocoa/mappings/appkit/progress_indicator.rb +61 -0
- data/lib/hotcocoa/mappings/appkit/scroll_view.rb +28 -0
- data/lib/hotcocoa/mappings/appkit/search_field.rb +9 -0
- data/lib/hotcocoa/mappings/appkit/secure_text_field.rb +15 -0
- data/lib/hotcocoa/mappings/appkit/segmented_control.rb +103 -0
- data/lib/hotcocoa/mappings/appkit/slider.rb +23 -0
- data/lib/hotcocoa/mappings/appkit/sound.rb +9 -0
- data/lib/hotcocoa/mappings/appkit/speech_synthesizer.rb +22 -0
- data/lib/hotcocoa/mappings/appkit/split_view.rb +19 -0
- data/lib/hotcocoa/mappings/appkit/status_bar.rb +7 -0
- data/lib/hotcocoa/mappings/appkit/status_item.rb +9 -0
- data/lib/hotcocoa/mappings/appkit/table_view.rb +108 -0
- data/lib/hotcocoa/mappings/appkit/text_field.rb +36 -0
- data/lib/hotcocoa/mappings/appkit/text_view.rb +13 -0
- data/lib/hotcocoa/mappings/appkit/toolbar.rb +99 -0
- data/lib/hotcocoa/mappings/appkit/toolbar_item.rb +36 -0
- data/lib/hotcocoa/mappings/appkit/tracking_area.rb +24 -0
- data/lib/hotcocoa/mappings/appkit/view.rb +65 -0
- data/lib/hotcocoa/mappings/appkit/window.rb +124 -0
- data/lib/hotcocoa/mappings/foundation/net_service.rb +65 -0
- data/lib/hotcocoa/mappings/foundation/net_service_browser.rb +27 -0
- data/lib/hotcocoa/mappings/foundation/notification.rb +24 -0
- data/lib/hotcocoa/mappings/foundation/sort_descriptor.rb +17 -0
- data/lib/hotcocoa/mappings/foundation/timer.rb +38 -0
- data/lib/hotcocoa/mappings/foundation/user_defaults.rb +43 -0
- data/lib/hotcocoa/mappings/foundation/xml_parser.rb +44 -0
- data/lib/hotcocoa/mappings/qtkit/movie.rb +15 -0
- data/lib/hotcocoa/mappings/qtkit/movie_view.rb +28 -0
- data/lib/hotcocoa/mappings/webkit/web_view.rb +20 -0
- data/lib/hotcocoa/mappings.rb +57 -111
- data/lib/hotcocoa/mvc.rb +90 -81
- data/lib/hotcocoa/notification_listener.rb +135 -58
- data/lib/hotcocoa/standard_rake_tasks.rb +17 -9
- data/lib/hotcocoa/target_action_convenience.rb +39 -0
- data/lib/hotcocoa/template.rb +90 -21
- data/lib/hotcocoa/version.rb +3 -0
- data/lib/hotcocoa.rb +12 -14
- data/template/Rakefile +31 -3
- data/template/__APPLICATION_NAME__.appspec +8 -0
- data/template/lib/application.rb +14 -17
- data/template/lib/menu.rb +11 -11
- data/test/application/test_builder.rb +28 -0
- data/test/application/test_specification.rb +280 -0
- data/test/core_extensions/test_kernel.rb +66 -0
- data/test/core_extensions/test_nsarray.rb +9 -0
- data/test/core_extensions/test_nsmutable_attributed_string.rb +86 -0
- data/test/core_extensions/test_nsstring.rb +20 -0
- data/test/core_extensions/test_nsurl.rb +9 -0
- data/test/core_extensions/test_numeric.rb +10 -0
- data/test/core_extensions/test_object.rb +37 -0
- data/test/core_extensions/test_range.rb +28 -0
- data/test/helper.rb +30 -0
- data/test/mappings/test_bonjour.rb +79 -0
- data/test/mappings/test_color.rb +16 -0
- data/test/mappings/test_font.rb +21 -0
- data/test/mappings/test_tracking_area.rb +18 -0
- data/test/test_application_builder.rb +95 -0
- data/test/test_attributed_string_helpers.rb +63 -0
- data/test/test_behaviours.rb +26 -0
- data/test/test_bin.rb +75 -0
- data/test/test_mapper.rb +100 -0
- data/test/test_mapping_methods.rb +67 -0
- data/test/test_mappings.rb +68 -0
- data/test/test_notification_listener.rb +19 -0
- data/test/test_template.rb +65 -0
- metadata +217 -90
- data/lib/hotcocoa/attributed_string.rb +0 -143
- data/lib/hotcocoa/kernel_ext.rb +0 -14
- data/lib/hotcocoa/mappings/alert.rb +0 -25
- data/lib/hotcocoa/mappings/application.rb +0 -112
- data/lib/hotcocoa/mappings/box.rb +0 -39
- data/lib/hotcocoa/mappings/button.rb +0 -92
- data/lib/hotcocoa/mappings/collection_view.rb +0 -44
- data/lib/hotcocoa/mappings/color.rb +0 -28
- data/lib/hotcocoa/mappings/column.rb +0 -21
- data/lib/hotcocoa/mappings/combo_box.rb +0 -24
- data/lib/hotcocoa/mappings/control.rb +0 -33
- data/lib/hotcocoa/mappings/font.rb +0 -44
- data/lib/hotcocoa/mappings/gradient.rb +0 -15
- data/lib/hotcocoa/mappings/image.rb +0 -15
- data/lib/hotcocoa/mappings/image_view.rb +0 -43
- data/lib/hotcocoa/mappings/label.rb +0 -25
- data/lib/hotcocoa/mappings/layout_view.rb +0 -9
- data/lib/hotcocoa/mappings/menu.rb +0 -71
- data/lib/hotcocoa/mappings/menu_item.rb +0 -47
- data/lib/hotcocoa/mappings/movie.rb +0 -13
- data/lib/hotcocoa/mappings/movie_view.rb +0 -27
- data/lib/hotcocoa/mappings/notification.rb +0 -17
- data/lib/hotcocoa/mappings/popup.rb +0 -110
- data/lib/hotcocoa/mappings/progress_indicator.rb +0 -68
- data/lib/hotcocoa/mappings/scroll_view.rb +0 -29
- data/lib/hotcocoa/mappings/search_field.rb +0 -9
- data/lib/hotcocoa/mappings/secure_text_field.rb +0 -17
- data/lib/hotcocoa/mappings/segmented_control.rb +0 -97
- data/lib/hotcocoa/mappings/slider.rb +0 -25
- data/lib/hotcocoa/mappings/sort_descriptor.rb +0 -13
- data/lib/hotcocoa/mappings/sound.rb +0 -9
- data/lib/hotcocoa/mappings/speech_synthesizer.rb +0 -25
- data/lib/hotcocoa/mappings/split_view.rb +0 -21
- data/lib/hotcocoa/mappings/status_bar.rb +0 -7
- data/lib/hotcocoa/mappings/status_item.rb +0 -9
- data/lib/hotcocoa/mappings/table_view.rb +0 -110
- data/lib/hotcocoa/mappings/text_field.rb +0 -41
- data/lib/hotcocoa/mappings/text_view.rb +0 -13
- data/lib/hotcocoa/mappings/timer.rb +0 -25
- data/lib/hotcocoa/mappings/toolbar.rb +0 -100
- data/lib/hotcocoa/mappings/toolbar_item.rb +0 -36
- data/lib/hotcocoa/mappings/view.rb +0 -67
- data/lib/hotcocoa/mappings/web_view.rb +0 -22
- data/lib/hotcocoa/mappings/window.rb +0 -118
- data/lib/hotcocoa/mappings/xml_parser.rb +0 -41
- data/lib/hotcocoa/object_ext.rb +0 -22
- data/lib/hotcocoa/plist.rb +0 -45
- data/template/config/build.yml +0 -8
- data/test/test_helper.rb +0 -3
- 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 ==
|
6
|
-
puts
|
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) ==
|
20
|
+
if File.extname(project_name) == '.rb'
|
12
21
|
file_to_copy = project_name
|
13
|
-
project_name = project_name
|
22
|
+
project_name = project_name.chomp '.rb'
|
14
23
|
else
|
15
|
-
puts
|
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
|
-
|
23
|
-
|
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
|
27
|
-
File.open(File.join(lib_dir,
|
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.
|