hotcocoa 0.6.0pre → 0.6.0pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +30 -19
- data/lib/hotcocoa/application/builder.rb +100 -14
- data/lib/hotcocoa/application/specification.rb +3 -8
- data/lib/hotcocoa/application_builder.rb +1 -2
- data/lib/hotcocoa/mappings/appkit/tracking_area.rb +5 -1
- data/lib/hotcocoa/notification_listener.rb +15 -4
- data/lib/hotcocoa/rake_tasks.rb +30 -0
- data/lib/hotcocoa/standard_rake_tasks.rb +9 -5
- data/lib/hotcocoa/version.rb +1 -1
- data/template/Rakefile +5 -30
- data/template/__APPLICATION_NAME__.appspec +34 -0
- data/test/application/helper.rb +21 -0
- data/test/application/test_builder.rb +61 -18
- data/test/application/test_specification.rb +4 -17
- data/test/mappings/test_bonjour.rb +9 -0
- data/test/mappings/test_tracking_area.rb +1 -1
- data/test/test_application_builder.rb +30 -40
- data/test/test_notification_listener.rb +34 -5
- metadata +5 -2
data/README.markdown
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
# hotcocoa
|
2
2
|
|
3
3
|
* [http://github.com/ferrous26/hotcocoa](http://github.com/ferrous26/hotcocoa)
|
4
|
-
* [Documentation](http://rdoc.info/github/ferrous26/hotcocoa/master/frames)
|
4
|
+
* [Documentation](http://rdoc.info/github/ferrous26/hotcocoa/master/frames)
|
5
5
|
|
6
6
|
## Description
|
7
7
|
|
8
8
|
HotCocoa is a thin, idiomatic Ruby layer that sits above Cocoa and
|
9
|
-
other frameworks.
|
10
|
-
|
11
|
-
|
12
|
-
HotCocoa (including tutorial) see
|
9
|
+
other frameworks. The goal of the project is to simplify the process of creating
|
10
|
+
and configuring Cocoa objects used when building native Mac apps. To get more
|
11
|
+
information on HotCocoa (including tutorials) see
|
13
12
|
[http://macruby.org](http://macruby.org).
|
14
13
|
|
15
14
|
## Note
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
existing mappings, and adding other features that we feel help meet
|
21
|
-
the goals of this project.
|
16
|
+
HotCocoa has ambitious goals that are difficult to accomplish with the input of
|
17
|
+
only a few people. Feedback is the easiest way to contribute and goes a long way
|
18
|
+
to making sure HotCocoa is on the right path to accomplishing those goals.
|
22
19
|
|
23
|
-
|
24
|
-
|
20
|
+
There are still some APIs that need documentation, regression tests that need to
|
21
|
+
be written, and tutorials to be updated; but new features and improved performance
|
22
|
+
will also be coming in the not too distant future. If you find issues with
|
23
|
+
HotCocoa, don't hesitate to open tickets on Github (or try to fix it yourself and
|
24
|
+
send in the patch :)).
|
25
25
|
|
26
26
|
There are a list of
|
27
27
|
[gotchas](https://github.com/ferrous26/hotcocoa/wiki/Gotchas) in the
|
@@ -29,22 +29,33 @@ wiki.
|
|
29
29
|
|
30
30
|
## Install
|
31
31
|
|
32
|
-
|
32
|
+
From rubygems:
|
33
33
|
|
34
|
-
|
34
|
+
sudo macgem install hotcocoa --pre
|
35
35
|
|
36
|
-
|
36
|
+
You need to add the `--pre` flag since HotCocoa 0.6 is not officially released yet.
|
37
|
+
Or you can clone the repository on Github and install from there:
|
38
|
+
|
39
|
+
git clone git://github.com/ferrous26/hotcocoa
|
40
|
+
cd hotcocoa
|
41
|
+
sudo macrake install
|
42
|
+
|
43
|
+
__Note__: If you are on Snow Leopard, you will also need the
|
37
44
|
[Bridge Support Preview](http://www.macruby.org/files/BridgeSupport%20Preview%203.zip)
|
38
|
-
in order to run
|
45
|
+
in order to run HotCocoa. Read about it on the
|
39
46
|
[MacRuby Blog](http://www.macruby.org/blog/2010/10/08/bridgesupport-preview.html).
|
40
47
|
|
48
|
+
__Note 2__: You will also need the Mac OS X developer tools in order
|
49
|
+
to build apps. Xcode is not required, but the compiler toolchain is
|
50
|
+
needed.
|
51
|
+
|
41
52
|
## Documentation
|
42
53
|
|
43
54
|
Documentation is a work in progress; some of the documentation is
|
44
|
-
being ported from the MacRuby website
|
55
|
+
being ported from the MacRuby website and you can still view it there.
|
45
56
|
|
46
|
-
The documentation does not include the mappings right now due to the
|
47
|
-
way that mappings are implemented; a YARD plug-in
|
57
|
+
The documentation currently does not include the mappings right now due to the
|
58
|
+
way that mappings are implemented; a YARD plug-in will be needed for thatv
|
48
59
|
|
49
60
|
## Contributing to HotCocoa
|
50
61
|
|
@@ -9,6 +9,9 @@ module Application
|
|
9
9
|
# This class is responsible for building application bundles, but could
|
10
10
|
# theoretically be used to build other bundles, such as frameworks, with
|
11
11
|
# only a few changes.
|
12
|
+
#
|
13
|
+
# It is designed to work in conjunction with an {Application::Specification}
|
14
|
+
# object which would provide details on how to build the bundle.
|
12
15
|
class Builder
|
13
16
|
|
14
17
|
##
|
@@ -22,17 +25,20 @@ module Application
|
|
22
25
|
new(spec).build(opts)
|
23
26
|
end
|
24
27
|
|
28
|
+
##
|
29
|
+
# Cached spec.
|
30
|
+
#
|
25
31
|
# @return [Application::Specification]
|
26
32
|
attr_reader :spec
|
27
33
|
|
28
34
|
# @param [Application::Specification]
|
29
35
|
def initialize spec
|
30
36
|
@spec = case spec
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
37
|
+
when Specification
|
38
|
+
spec
|
39
|
+
when String
|
40
|
+
Specification.load spec
|
41
|
+
end
|
36
42
|
end
|
37
43
|
|
38
44
|
# @param [Hash]
|
@@ -50,10 +56,15 @@ module Application
|
|
50
56
|
deploy if opts[:deploy]
|
51
57
|
end
|
52
58
|
|
59
|
+
##
|
60
|
+
# Run the bundle's binary directly so `STDOUT` and `STDERR` appear in the
|
61
|
+
# terminal.
|
53
62
|
def run
|
54
63
|
`"./#{executable_file}"`
|
55
64
|
end
|
56
65
|
|
66
|
+
##
|
67
|
+
# Destroy the existing bundle, if it exists.
|
57
68
|
def remove_bundle_root
|
58
69
|
FileUtils.rm_rf bundle_root if File.exist?(bundle_root)
|
59
70
|
end
|
@@ -62,26 +73,37 @@ module Application
|
|
62
73
|
private
|
63
74
|
|
64
75
|
##
|
65
|
-
#
|
76
|
+
# Call `macruby_deploy` to lend a helping hand.
|
66
77
|
def deploy
|
67
78
|
puts `macruby_deploy --embed --gem hotcocoa #{deploy_options} #{bundle_root}`
|
68
79
|
end
|
69
80
|
|
81
|
+
##
|
82
|
+
# Build the options list to pass to `macruby_deploy`.
|
70
83
|
def deploy_options
|
71
84
|
options = []
|
72
85
|
spec.gems.each { |g| options << "--gem #{g}" }
|
73
86
|
options << '--bs' if spec.embed_bs?
|
74
87
|
options << '--compile' if spec.compile?
|
75
|
-
options << '--no-stdlib' unless spec.stdlib
|
88
|
+
options << '--no-stdlib' unless spec.stdlib
|
89
|
+
if spec.stdlib.respond_to? :each
|
90
|
+
spec.stdlib.each do |lib|
|
91
|
+
options << "--stdlib #{lib}"
|
92
|
+
end
|
93
|
+
end
|
76
94
|
options.join(' ')
|
77
95
|
end
|
78
96
|
|
97
|
+
##
|
98
|
+
# Setup the basic directory structure of a bundle.
|
79
99
|
def build_bundle_structure
|
80
100
|
[bundle_root, contents_root, frameworks_root, macos_root, resources_root].each do |dir|
|
81
101
|
Dir.mkdir(dir) unless File.exist?(dir)
|
82
102
|
end
|
83
103
|
end
|
84
104
|
|
105
|
+
##
|
106
|
+
# Setup the remaining standard files for the bundle.
|
85
107
|
def write_bundle_files
|
86
108
|
write_pkg_info_file
|
87
109
|
write_info_plist_file
|
@@ -89,6 +111,8 @@ module Application
|
|
89
111
|
write_ruby_main
|
90
112
|
end
|
91
113
|
|
114
|
+
##
|
115
|
+
# Copy the sources, usually just the ruby source code, into the bundle.
|
92
116
|
def copy_sources
|
93
117
|
spec.sources.each do |source|
|
94
118
|
destination = File.join(resources_root, source)
|
@@ -97,6 +121,12 @@ module Application
|
|
97
121
|
end
|
98
122
|
end
|
99
123
|
|
124
|
+
##
|
125
|
+
# @todo An example project that uses a `xib`.
|
126
|
+
#
|
127
|
+
# Copy the resources, such as images and data, into the bundle.
|
128
|
+
# Resources can also include interface builder files, which will
|
129
|
+
# be compiled for you.
|
100
130
|
def copy_resources
|
101
131
|
spec.resources.each do |resource|
|
102
132
|
destination = File.join(resources_root, resource.split('/')[1..-1].join('/'))
|
@@ -111,21 +141,36 @@ module Application
|
|
111
141
|
end
|
112
142
|
end
|
113
143
|
|
144
|
+
##
|
145
|
+
# Compile any CoreData model files and copy them to the bundle.
|
114
146
|
def compile_data_models
|
115
147
|
spec.data_models.each do |data|
|
116
148
|
`/Developer/usr/bin/momc #{data} #{resources_root}/#{File.basename(data, ".xcdatamodel")}.mom`
|
117
149
|
end
|
118
150
|
end
|
119
151
|
|
152
|
+
##
|
153
|
+
# Copy the icon file to the bundle.
|
120
154
|
def copy_icon_file
|
121
155
|
FileUtils.cp spec.icon, icon_file
|
122
156
|
end
|
123
157
|
|
158
|
+
##
|
159
|
+
# Generate the `PkgInfo` file for the bundle. Every bundle needs this
|
160
|
+
# in order identify its type of bundle and signature.
|
124
161
|
def write_pkg_info_file
|
125
|
-
File.open(pkg_info_file, 'wb')
|
162
|
+
File.open(pkg_info_file, 'wb') do |file|
|
163
|
+
file.write "#{spec.type}#{spec.signature}"
|
164
|
+
end
|
126
165
|
end
|
127
166
|
|
128
|
-
|
167
|
+
##
|
168
|
+
# @todo Development region needs to be configurable in the future. And
|
169
|
+
# so should the default class. They should still both have defaults.
|
170
|
+
#
|
171
|
+
# Generate and the `Info.plist` for the bundle using fields from the
|
172
|
+
# cached app spec.
|
173
|
+
def info_plist
|
129
174
|
# http://developer.apple.com/library/mac/#documentation/General/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html%23//apple_ref/doc/uid/TP40009254-SW1
|
130
175
|
info = {
|
131
176
|
CFBundleName: spec.name,
|
@@ -138,14 +183,28 @@ module Application
|
|
138
183
|
CFBundleInfoDictionaryVersion: '6.0',
|
139
184
|
NSPrincipalClass: 'NSApplication',
|
140
185
|
LSUIElement: spec.agent,
|
141
|
-
LSMinimumSystemVersion: '10.6.7', # should match MacRuby
|
186
|
+
LSMinimumSystemVersion: '10.6.7', # @todo should match MacRuby
|
142
187
|
}
|
143
188
|
info[:CFBundleIconFile] = File.basename(spec.icon) if spec.icon_exists?
|
189
|
+
info.merge! spec.plist # should always be done last
|
190
|
+
info.to_plist
|
191
|
+
end
|
144
192
|
|
145
|
-
|
193
|
+
##
|
194
|
+
# Wirte out the generated info plist for the bundle.
|
195
|
+
def write_info_plist_file
|
196
|
+
File.open(info_plist_file, 'w') do |file|
|
197
|
+
file.write info_plist
|
198
|
+
end
|
146
199
|
end
|
147
200
|
|
148
|
-
|
201
|
+
##
|
202
|
+
# @todo Need a better way of specifying the supported architectures,
|
203
|
+
# hard coding makes HotCocoa susceptible to the same problem
|
204
|
+
# as before.
|
205
|
+
#
|
206
|
+
# Create the standard bootstrap binary to launch a MacRuby app and place
|
207
|
+
# it in the bundle.
|
149
208
|
def build_executable
|
150
209
|
File.open(objective_c_source_file, 'wb') do |f|
|
151
210
|
f.write %{
|
@@ -158,12 +217,14 @@ module Application
|
|
158
217
|
}
|
159
218
|
end
|
160
219
|
Dir.chdir(macos_root) do
|
161
|
-
puts
|
220
|
+
puts `#{RbConfig::CONFIG['CC']} main.m -o #{executable_file_name} -arch x86_64 -framework MacRuby -framework Foundation -fobjc-gc-only`
|
162
221
|
end
|
163
222
|
File.unlink(objective_c_source_file)
|
164
223
|
end
|
165
224
|
|
166
|
-
|
225
|
+
##
|
226
|
+
# Borrow `rb_main` from MacRuby Xcode templates and use it to load all
|
227
|
+
# the sources in the bundle at boot time.
|
167
228
|
def write_ruby_main
|
168
229
|
File.open(main_ruby_source_file, 'wb') do |f|
|
169
230
|
f.write <<-EOF
|
@@ -186,50 +247,75 @@ module Application
|
|
186
247
|
end
|
187
248
|
end
|
188
249
|
|
250
|
+
##
|
251
|
+
# Path where to put the bundle.
|
189
252
|
def bundle_root
|
190
253
|
"#{spec.name}.app"
|
191
254
|
end
|
192
255
|
|
256
|
+
##
|
257
|
+
# Path where to put the `Contents' directory of the bundle.
|
193
258
|
def contents_root
|
194
259
|
File.join(bundle_root, 'Contents')
|
195
260
|
end
|
196
261
|
|
262
|
+
##
|
263
|
+
# Path where to put the `Frameworks' directory of the bundle.
|
197
264
|
def frameworks_root
|
198
265
|
File.join(contents_root, 'Frameworks')
|
199
266
|
end
|
200
267
|
|
268
|
+
##
|
269
|
+
# Path where to put the `MacOS' directory of the bundle.
|
201
270
|
def macos_root
|
202
271
|
File.join(contents_root, 'MacOS')
|
203
272
|
end
|
204
273
|
|
274
|
+
##
|
275
|
+
# Path where to put the `Resources' directory of the bundle.
|
205
276
|
def resources_root
|
206
277
|
File.join(contents_root, 'Resources')
|
207
278
|
end
|
208
279
|
|
280
|
+
##
|
281
|
+
# Path where to put the `Info.plist' directory of the bundle.
|
209
282
|
def info_plist_file
|
210
283
|
File.join(contents_root, 'Info.plist')
|
211
284
|
end
|
212
285
|
|
286
|
+
##
|
287
|
+
# Path where to put the icon for the bundle.
|
213
288
|
def icon_file
|
214
289
|
File.join(resources_root, "#{spec.name}.icns")
|
215
290
|
end
|
216
291
|
|
292
|
+
##
|
293
|
+
# Path where to put the `PkgInfo` file for the bundle.
|
217
294
|
def pkg_info_file
|
218
295
|
File.join(contents_root, 'PkgInfo')
|
219
296
|
end
|
220
297
|
|
298
|
+
##
|
299
|
+
# Generate the name of the binary. Done by removing whitespace from
|
300
|
+
# the `name` attribute of the cached app spec.
|
221
301
|
def executable_file_name
|
222
302
|
spec.name.gsub(/\s+/, '')
|
223
303
|
end
|
224
304
|
|
305
|
+
##
|
306
|
+
# Path where to put the binary file for the bundle.
|
225
307
|
def executable_file
|
226
308
|
File.join(macos_root, executable_file_name)
|
227
309
|
end
|
228
310
|
|
311
|
+
##
|
312
|
+
# Temporary path where the temporary source for bootstrap binary.
|
229
313
|
def objective_c_source_file
|
230
314
|
File.join(macos_root, 'main.m')
|
231
315
|
end
|
232
316
|
|
317
|
+
##
|
318
|
+
# Path where to put the `rb_main.rb` bootstrap file.
|
233
319
|
def main_ruby_source_file
|
234
320
|
File.join(resources_root, 'rb_main.rb')
|
235
321
|
end
|
@@ -127,7 +127,7 @@ module Application
|
|
127
127
|
# Empty by default.
|
128
128
|
#
|
129
129
|
# @return [Hash]
|
130
|
-
|
130
|
+
attr_accessor :plist
|
131
131
|
|
132
132
|
# @todo Support localization related plist keys natively
|
133
133
|
# @todo CFBundleDevelopmentRegion (Recommended)
|
@@ -154,7 +154,7 @@ module Application
|
|
154
154
|
# @return [Array<String>]
|
155
155
|
attr_accessor :data_models
|
156
156
|
|
157
|
-
# @group
|
157
|
+
# @group Deployment Options
|
158
158
|
|
159
159
|
##
|
160
160
|
# Whether to include the Ruby stdlib in the app when embedding
|
@@ -244,8 +244,6 @@ module Application
|
|
244
244
|
alias_method :embed_bs?, :embed_bs
|
245
245
|
|
246
246
|
##
|
247
|
-
# @todo Is this actually useful or can we get rid of it?
|
248
|
-
#
|
249
247
|
# Whether or not to always make a clean build of the app.
|
250
248
|
#
|
251
249
|
# Defaults to false.
|
@@ -257,7 +255,7 @@ module Application
|
|
257
255
|
# @endgroup
|
258
256
|
|
259
257
|
DEFAULT_ATTRIBUTES = {
|
260
|
-
|
258
|
+
plist: {},
|
261
259
|
sources: [],
|
262
260
|
resources: [],
|
263
261
|
data_models: [],
|
@@ -281,8 +279,6 @@ module Application
|
|
281
279
|
end
|
282
280
|
yield self
|
283
281
|
|
284
|
-
# @todo go through plist and overwrite specific keys?
|
285
|
-
|
286
282
|
# @todo should we verify at initialization or defer until building?
|
287
283
|
verify!
|
288
284
|
end
|
@@ -342,7 +338,6 @@ module Application
|
|
342
338
|
@copyright = @copyright.to_s if @copyright
|
343
339
|
end
|
344
340
|
|
345
|
-
# @todo Should a warning be given if not embedding the stdlib?
|
346
341
|
def verify_stdlib
|
347
342
|
# need to be careful here; the main components of hotcocoa do
|
348
343
|
# not depend on the stdlib right now, but if that changes then
|
@@ -302,7 +302,6 @@ module HotCocoa
|
|
302
302
|
puts `macruby_deploy --embed --gem hotcocoa #{options} #{bundle_root}`
|
303
303
|
end
|
304
304
|
|
305
|
-
# @todo something better than puts `gcc`
|
306
305
|
def build_executable
|
307
306
|
File.open(objective_c_source_file, 'wb') do |f|
|
308
307
|
f.write %{
|
@@ -315,7 +314,7 @@ module HotCocoa
|
|
315
314
|
}
|
316
315
|
end
|
317
316
|
Dir.chdir(macos_root) do
|
318
|
-
puts
|
317
|
+
puts `#{RbConfig::CONFIG['CC']} main.m -o #{objective_c_executable_file} -arch x86_64 -framework MacRuby -framework Foundation -fobjc-gc-only`
|
319
318
|
end
|
320
319
|
File.unlink(objective_c_source_file)
|
321
320
|
end
|
@@ -16,8 +16,12 @@ HotCocoa::Mappings.map tracking_area: NSTrackingArea do
|
|
16
16
|
|
17
17
|
def init_with_options tracking_area, options
|
18
18
|
rect = options.delete(:rect)
|
19
|
+
widget_options = options.delete(:options)
|
20
|
+
if widget_options.nil?
|
21
|
+
raise ArgumentError.new("Options must be set for NSTrackingArea, in particular the type of tracking area")
|
22
|
+
end
|
19
23
|
tracking_area.initWithRect rect,
|
20
|
-
options:
|
24
|
+
options: widget_options,
|
21
25
|
owner: options.delete(:owner),
|
22
26
|
userInfo: nil
|
23
27
|
end
|
@@ -39,7 +39,7 @@ class HotCocoa::NotificationListener
|
|
39
39
|
|
40
40
|
class << self
|
41
41
|
##
|
42
|
-
# List of all {HotCocoa::
|
42
|
+
# List of all {HotCocoa::NotificationListener}s.
|
43
43
|
#
|
44
44
|
# @return [HotCocoa::NotificationListener]
|
45
45
|
attr_reader :registered_listeners
|
@@ -66,22 +66,32 @@ class HotCocoa::NotificationListener
|
|
66
66
|
# notification
|
67
67
|
# @yieldparam [String] notification the name of the notification received
|
68
68
|
def initialize options = {}, &block
|
69
|
-
|
69
|
+
unless block_given?
|
70
|
+
raise ArgumentError, 'You must pass a block to act as the callback'
|
71
|
+
end
|
70
72
|
@callback = block
|
71
73
|
|
72
74
|
@name = options[:named]
|
73
75
|
@sender = options[:sent_by]
|
74
76
|
@suspension_behavior = DistributedBehaviors[options[:when_suspended] || :coalesce]
|
75
77
|
@distributed = (options[:distributed] == true)
|
76
|
-
|
78
|
+
self.class.registered_listeners << self
|
77
79
|
observe
|
78
80
|
end
|
79
81
|
|
82
|
+
##
|
83
|
+
# (see #stop_listening)
|
84
|
+
# @deprecated Use {#stop_listening} instead. This API is scheduled to
|
85
|
+
# be removed in HotCocoa 0.7.
|
86
|
+
def stop_notifications options = {}
|
87
|
+
stop_listening options
|
88
|
+
end
|
89
|
+
|
80
90
|
##
|
81
91
|
# Stop the listener from listening to any future notifications. The
|
82
92
|
# options available here are the same as the {#initialize} methods
|
83
93
|
# `:named` and `:sent_by` options.
|
84
|
-
def
|
94
|
+
def stop_listening options = {}
|
85
95
|
if options.has_key?(:named) || options.has_key?(:sent_by)
|
86
96
|
notification_center.removeObserver self,
|
87
97
|
name: options[:named],
|
@@ -89,6 +99,7 @@ class HotCocoa::NotificationListener
|
|
89
99
|
else
|
90
100
|
notification_center.removeObserver self
|
91
101
|
end
|
102
|
+
self.class.registered_listeners.delete self
|
92
103
|
end
|
93
104
|
|
94
105
|
##
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'hotcocoa/application/builder'
|
2
|
+
|
3
|
+
builder = Application::Builder.new APPSPEC
|
4
|
+
|
5
|
+
desc 'Build the application'
|
6
|
+
task :build do
|
7
|
+
builder.build
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'Build a deployable version of the application'
|
11
|
+
task :deploy do
|
12
|
+
builder.build deploy: true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Build and execute the application'
|
16
|
+
task :run => [:build] do
|
17
|
+
builder.run
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Cleanup build files'
|
21
|
+
task :clean do
|
22
|
+
builder.remove_bundle_root
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'Create the dmg archive from the application bundle'
|
26
|
+
task :dmg => :deploy do
|
27
|
+
app_name = builder.spec.name
|
28
|
+
rm_rf "#{app_name}.dmg"
|
29
|
+
sh "hdiutil create #{app_name}.dmg -quiet -srcdir #{app_name}.app -format UDZO -imagekey zlib-level=9"
|
30
|
+
end
|
@@ -1,12 +1,16 @@
|
|
1
1
|
$stderr.puts <<EOM
|
2
|
-
standard_rake_tasks.rb is deprecated in favour
|
3
|
-
|
2
|
+
The old build system, which uses standard_rake_tasks.rb is deprecated in favour
|
3
|
+
of a more easily configurable build system as of HotCocoa 0.6. The old build
|
4
|
+
system will be removed in HotCocoa 0.7.
|
5
|
+
|
6
|
+
You can update your existing project by looking at the new project template, which
|
7
|
+
can be found on Github:
|
8
|
+
|
9
|
+
https://github.com/ferrous26/hotcocoa/blob/master/template
|
4
10
|
|
5
|
-
You can update your Rakefile by copying the new tasks from Github at
|
6
|
-
https://github.com/ferrous26/hotcocoa/blob/master/template/Rakefile
|
7
11
|
EOM
|
8
12
|
|
9
|
-
AppConfig = HotCocoa::ApplicationBuilder::Configuration.new(
|
13
|
+
AppConfig = HotCocoa::ApplicationBuilder::Configuration.new('config/build.yml')
|
10
14
|
|
11
15
|
desc 'Build a deployable version of the application'
|
12
16
|
task :deploy do
|
data/lib/hotcocoa/version.rb
CHANGED
data/template/Rakefile
CHANGED
@@ -1,33 +1,8 @@
|
|
1
|
-
|
2
|
-
require 'hotcocoa/application/builder'
|
3
|
-
|
4
|
-
builder = Application::Builder.new '__APPLICATION_NAME__.appspec'
|
5
|
-
|
6
|
-
desc 'Build the application'
|
7
|
-
task :build do
|
8
|
-
builder.build
|
9
|
-
end
|
1
|
+
APPSPEC = '__APPLICATION_NAME__.appspec'
|
10
2
|
|
11
|
-
|
12
|
-
|
13
|
-
builder.build deploy: true
|
14
|
-
end
|
15
|
-
|
16
|
-
desc 'Build and execute the application'
|
17
|
-
task :run => [:build] do
|
18
|
-
builder.run
|
19
|
-
end
|
20
|
-
|
21
|
-
desc 'Cleanup build files'
|
22
|
-
task :clean do
|
23
|
-
builder.remove_bundle_root
|
24
|
-
end
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hotcocoa/rake_tasks'
|
25
5
|
|
26
|
-
|
27
|
-
task :dmg => :deploy do
|
28
|
-
app_name = builder.spec.name
|
29
|
-
rm_rf "#{app_name}.dmg"
|
30
|
-
sh "hdiutil create #{app_name}.dmg -quiet -srcdir #{app_name}.app -format UDZO -imagekey zlib-level=9"
|
31
|
-
end
|
6
|
+
task :default => :run
|
32
7
|
|
33
|
-
|
8
|
+
# Add your own tasks here
|
@@ -1,8 +1,42 @@
|
|
1
|
+
# for more information about the fields that can be set on the specification, check out the rdoc:
|
2
|
+
# http://rdoc.info/github/ferrous26/hotcocoa/master/Application/Specification
|
3
|
+
#
|
1
4
|
Application::Specification.new do |s|
|
2
5
|
s.name = '__APPLICATION_NAME__'
|
3
6
|
s.identifier = 'com.__COMPANY_NAME__.__APPLICATION_NAME__'
|
7
|
+
|
8
|
+
# The version of the app, usually including the build number.
|
4
9
|
s.version = '1.0'
|
10
|
+
|
5
11
|
s.icon = 'resources/HotCocoa.icns'
|
6
12
|
s.resources = Dir.glob('resources/**/*.*')
|
7
13
|
s.sources = Dir.glob('lib/**/*.rb')
|
14
|
+
|
15
|
+
# optional copyright
|
16
|
+
# s.copyright = "2011, Your Company"
|
17
|
+
|
18
|
+
# optional short version (in contrast to the full version, the short version should not contain the build number)
|
19
|
+
# s.short_version = "$MAJOR.$MINOR.$PATCHLEVEL"
|
20
|
+
|
21
|
+
# to avoid embedding the standard libs
|
22
|
+
# s.stdlib = false
|
23
|
+
# alternatively, specify the modules that you wish to include
|
24
|
+
# s.stdlib = ['base64', 'matrix', 'set']
|
25
|
+
|
26
|
+
# specify which gems you wish to be bundled with your application
|
27
|
+
# hotcocoa is automatically bundled and doesn't need to be specified here
|
28
|
+
# s.gems = ['rest-client']
|
29
|
+
|
30
|
+
# uncomment if you wish to embed the BridgeSupport files during deployment
|
31
|
+
# useful if you need to deploy the app to OS X 10.6.
|
32
|
+
# s.embed_bs = true
|
33
|
+
|
34
|
+
# uncomment to always make a clean build of the app
|
35
|
+
# s.overwrite = true
|
36
|
+
|
37
|
+
# toggle whether the app is an daemon with UI or a regular app
|
38
|
+
# You can use this flag to hide the dock icon for the app; the
|
39
|
+
# default value is false so that apps will have a dock icon
|
40
|
+
# s.agent = true
|
8
41
|
end
|
42
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'hotcocoa/application/builder'
|
2
|
+
|
3
|
+
class TestApplicationModule < MiniTest::Unit::TestCase
|
4
|
+
include Application
|
5
|
+
|
6
|
+
def hotconsole_spec
|
7
|
+
@@hotconsole_spec ||= Specification.load 'test/fixtures/hotconsole.appspec'
|
8
|
+
end
|
9
|
+
def stopwatch_spec
|
10
|
+
@@stopwatch_spec ||= Specification.load 'test/fixtures/stopwatch.appspec'
|
11
|
+
end
|
12
|
+
|
13
|
+
def minimal_spec
|
14
|
+
Specification.new do |s|
|
15
|
+
s.name = 'test'
|
16
|
+
s.identifier = 'com.test.test'
|
17
|
+
yield s if block_given?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -1,28 +1,71 @@
|
|
1
|
-
require '
|
1
|
+
require 'test/application/helper'
|
2
2
|
|
3
|
-
class TestApplicationBuilder <
|
4
|
-
include Application
|
3
|
+
class TestApplicationBuilder < TestApplicationModule
|
5
4
|
|
6
|
-
|
5
|
+
def hotconsole
|
6
|
+
@@hotconsole ||= Builder.new hotconsole_spec
|
7
|
+
end
|
8
|
+
def stopwatch
|
9
|
+
@@stopwatch ||= Builder.new stopwatch_spec
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_caches_spec
|
13
|
+
assert_equal stopwatch_spec, stopwatch.spec
|
14
|
+
end
|
7
15
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
16
|
+
# I don't think it is too important to test deployment as well
|
17
|
+
# as long as we make sure we are passing the correct options
|
18
|
+
# to `macruby_deploy`
|
11
19
|
|
12
|
-
def
|
13
|
-
|
20
|
+
def test_deploy_option_gems
|
21
|
+
assert_includes stopwatch.send(:deploy_options), '--gem rest-client'
|
22
|
+
refute_includes hotconsole.send(:deploy_options), '--gem'
|
23
|
+
end
|
14
24
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
25
|
+
def test_deploy_option_compile
|
26
|
+
assert_includes stopwatch.send(:deploy_options), '--compile'
|
27
|
+
refute_includes hotconsole.send(:deploy_options), '--compile'
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_deploy_option_embed_bs
|
31
|
+
refute_includes stopwatch.send(:deploy_options), '--bs'
|
32
|
+
assert_includes hotconsole.send(:deploy_options), '--bs'
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_deploy_option_stdlib
|
36
|
+
assert_includes stopwatch.send(:deploy_options), '--no-stdlib'
|
37
|
+
refute_includes hotconsole.send(:deploy_options), 'stdlib'
|
38
|
+
|
39
|
+
spec = minimal_spec do |s|
|
40
|
+
s.stdlib = ['matrix', 'base64']
|
41
|
+
end
|
42
|
+
options = Builder.new(spec).send :deploy_options
|
43
|
+
refute_includes options, '--no-stdlib'
|
44
|
+
assert_includes options, '--stdlib matrix'
|
45
|
+
assert_includes options, '--stdlib base64'
|
19
46
|
end
|
20
47
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
48
|
+
def test_plist_only_uses_icon_if_it_can
|
49
|
+
plist = load_plist(hotconsole.send(:info_plist))
|
50
|
+
refute_includes plist, :CFBundleIconFile
|
51
|
+
|
52
|
+
spec = hotconsole_spec.dup
|
53
|
+
spec.icon = '/Applications/Calculator.app/Contents/Resources/Calculator.icns'
|
54
|
+
plist = load_plist(Builder.new(spec).send(:info_plist))
|
55
|
+
assert_includes plist, :CFBundleIconFile
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_plist_hash_from_spec_overrides_all
|
59
|
+
spec = hotconsole_spec.dup
|
60
|
+
spec.plist[:MyKey] = true
|
61
|
+
spec.plist[:NSPrincipleClass] = 'Foo'
|
62
|
+
spec.plist[:CFBundleName] = 'Cake'
|
63
|
+
|
64
|
+
plist = load_plist(Builder.new(spec).send(:info_plist))
|
65
|
+
assert_equal true, plist[:MyKey ]
|
66
|
+
assert_equal 'Foo', plist[:NSPrincipleClass ]
|
67
|
+
assert_equal 'Cake', plist[:CFBundleName ]
|
68
|
+
assert_equal spec.identifier, plist[:CFBundleIdentifier]
|
26
69
|
end
|
27
70
|
|
28
71
|
end
|
@@ -1,11 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'test/application/helper'
|
2
2
|
|
3
|
-
class TestApplicationSpecification <
|
4
|
-
include Application
|
5
|
-
|
6
|
-
# Some HotCocoa appspec files, converted from build.yml files borrowed from projects on Github
|
7
|
-
HOTCONSOLE = 'test/fixtures/hotconsole.appspec'
|
8
|
-
STOPWATCH = 'test/fixtures/stopwatch.appspec'
|
3
|
+
class TestApplicationSpecification < TestApplicationModule
|
9
4
|
|
10
5
|
def rescue_spec_error_for &block
|
11
6
|
begin
|
@@ -15,14 +10,6 @@ class TestApplicationSpecification < MiniTest::Unit::TestCase
|
|
15
10
|
end
|
16
11
|
end
|
17
12
|
|
18
|
-
def minimal_spec
|
19
|
-
Specification.new do |s|
|
20
|
-
s.name = 'test'
|
21
|
-
s.identifier = 'com.test.test'
|
22
|
-
yield s if block_given?
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
13
|
def test_spec_requires_a_block
|
27
14
|
error = rescue_spec_error_for # no block given
|
28
15
|
assert_match /must pass a block/, error.message
|
@@ -259,7 +246,7 @@ class TestApplicationSpecification < MiniTest::Unit::TestCase
|
|
259
246
|
|
260
247
|
# doubles as an integration test
|
261
248
|
def test_load_evaluates_files_properly
|
262
|
-
spec =
|
249
|
+
spec = hotconsole_spec
|
263
250
|
assert_equal 'HotConsole', spec.name
|
264
251
|
assert_equal 'com.vincentisambart.HotConsole', spec.identifier
|
265
252
|
assert_equal '1.0', spec.version
|
@@ -267,7 +254,7 @@ class TestApplicationSpecification < MiniTest::Unit::TestCase
|
|
267
254
|
assert_equal [], spec.resources
|
268
255
|
assert_equal 'girb', spec.signature
|
269
256
|
|
270
|
-
spec =
|
257
|
+
spec = stopwatch_spec
|
271
258
|
assert_equal 'Stopwatch', spec.name
|
272
259
|
assert_equal 'nz.co.kearse.stopwatch', spec.identifier
|
273
260
|
assert_equal Dir.glob('{lib,hotcocoa}*/**/*.rb'), spec.sources
|
@@ -76,4 +76,13 @@ class TestBonjourMappings < MiniTest::Unit::TestCase
|
|
76
76
|
skip 'TODO'
|
77
77
|
end
|
78
78
|
|
79
|
+
def bench_delegate_building
|
80
|
+
browser = bonjour_browser
|
81
|
+
assert_performance_linear do |n|
|
82
|
+
n.times do
|
83
|
+
browser.did_find_service { |_,_| }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
79
88
|
end
|
@@ -12,7 +12,7 @@ class TestTrackingAreaMappings < MiniTest::Unit::TestCase
|
|
12
12
|
|
13
13
|
def bench_create_tracking_area
|
14
14
|
assert_performance_linear do |n|
|
15
|
-
n.times { HotCocoa.tracking_area }
|
15
|
+
n.times { HotCocoa.tracking_area(options: [:mouse_entered_and_exited, :active_first_responder]) }
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -6,90 +6,80 @@ require 'hotcocoa/application_builder'
|
|
6
6
|
class TestConfiguration < MiniTest::Unit::TestCase
|
7
7
|
|
8
8
|
Configuration = HotCocoa::ApplicationBuilder::Configuration
|
9
|
-
TEST_DIR = File.join(
|
9
|
+
TEST_DIR = File.join(ENV['TMPDIR'], 'test_app_builder')
|
10
10
|
|
11
11
|
# Some HotCocoa build.yml files, borrowed from projects on Github
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
def hotconsole_config
|
13
|
+
@@hotconsole_config ||= Configuration.new 'test/fixtures/hotconsole.yml'
|
14
|
+
end
|
15
|
+
def calculator_config
|
16
|
+
@@calculator_config ||= Configuration.new 'test/fixtures/calculator.yml'
|
17
|
+
end
|
18
|
+
def stopwatch_config
|
19
|
+
@@stopwatch_config ||= Configuration.new 'test/fixtures/stopwatch.yml'
|
20
|
+
end
|
21
|
+
def empty_config
|
22
|
+
@@empty_config ||= Configuration.new 'test/fixtures/empty.yml'
|
23
|
+
end
|
16
24
|
|
17
25
|
def setup; FileUtils.mkdir TEST_DIR; end
|
18
26
|
def teardown; FileUtils.rm_rf TEST_DIR; end
|
19
27
|
|
20
28
|
def test_reads_attributes
|
21
|
-
conf =
|
29
|
+
conf = hotconsole_config
|
22
30
|
assert_equal 'HotConsole', conf.name
|
23
31
|
assert_equal '1.0', conf.version
|
24
32
|
assert_equal 'resources/HotConsole.icns', conf.icon
|
25
33
|
assert_equal ['resources/**/*.*'], conf.resources
|
26
34
|
assert_equal ['lib/**/*.rb'], conf.sources
|
27
35
|
|
28
|
-
conf =
|
36
|
+
conf = calculator_config
|
29
37
|
assert_equal 'Calculator', conf.name
|
30
38
|
assert_equal '2.0', conf.version
|
31
39
|
end
|
32
40
|
|
33
41
|
def test_version_defaults_to_1_if_not_set
|
34
|
-
conf =
|
42
|
+
conf = stopwatch_config
|
35
43
|
refute_nil conf.version
|
36
44
|
assert_equal '1.0', conf.version
|
37
45
|
end
|
38
46
|
|
39
47
|
def test_sources_resources_and_data_models_are_initialized_to_an_empty_array_if_not_provided
|
40
|
-
conf =
|
48
|
+
conf = empty_config
|
41
49
|
assert_empty conf.sources
|
42
50
|
assert_empty conf.resources
|
43
51
|
assert_empty conf.data_models
|
44
52
|
end
|
45
53
|
|
46
54
|
def test_overwirte_attribute
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
conf = Configuration.new STOPWATCH
|
51
|
-
assert conf.overwrite?
|
55
|
+
refute empty_config.overwrite?
|
56
|
+
assert stopwatch_config.overwrite?
|
52
57
|
end
|
53
58
|
|
54
59
|
def test_agent_attribute
|
55
|
-
|
56
|
-
assert_equal '
|
57
|
-
|
58
|
-
conf = Configuration.new STOPWATCH
|
59
|
-
assert_equal '1', conf.agent
|
60
|
+
assert_equal '0', empty_config.agent
|
61
|
+
assert_equal '1', stopwatch_config.agent
|
60
62
|
end
|
61
63
|
|
62
64
|
def test_stdlib_attribute
|
63
|
-
|
64
|
-
assert_equal
|
65
|
-
|
66
|
-
conf = Configuration.new STOPWATCH
|
67
|
-
assert_equal false, conf.stdlib
|
65
|
+
assert_equal true, hotconsole_config.stdlib
|
66
|
+
assert_equal false, stopwatch_config.stdlib
|
68
67
|
end
|
69
68
|
|
70
69
|
def test_type_attribute
|
71
|
-
|
72
|
-
assert_equal '
|
73
|
-
|
74
|
-
conf = Configuration.new EMPTY_APP
|
75
|
-
assert_equal 'BNDL', conf.type
|
70
|
+
assert_equal 'APPL', hotconsole_config.type
|
71
|
+
assert_equal 'BNDL', empty_config.type
|
76
72
|
end
|
77
73
|
|
78
74
|
def test_signature_attribute
|
79
|
-
|
80
|
-
assert_equal '
|
81
|
-
|
82
|
-
conf = Configuration.new HOTCONSOLE
|
83
|
-
assert_equal 'girb', conf.signature
|
75
|
+
assert_equal '????', empty_config.signature
|
76
|
+
assert_equal 'girb', hotconsole_config.signature
|
84
77
|
end
|
85
78
|
|
86
79
|
def test_icon_exists?
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
# works because this project uses the icon from a system app
|
91
|
-
conf = Configuration.new CALCULATOR
|
92
|
-
assert conf.icon_exists?
|
80
|
+
refute hotconsole_config.icon_exists?
|
81
|
+
# works on all Macs because this project uses the icon from a system app
|
82
|
+
assert calculator_config.icon_exists?
|
93
83
|
end
|
94
84
|
|
95
85
|
end
|
@@ -1,19 +1,48 @@
|
|
1
1
|
# Integration tests
|
2
2
|
class TestNotificationListener < MiniTest::Unit::TestCase
|
3
|
+
include HotCocoa
|
3
4
|
|
4
|
-
def
|
5
|
+
def teardown
|
6
|
+
NotificationListener.registered_listeners.each &:stop_listening
|
5
7
|
end
|
6
8
|
|
7
|
-
def
|
9
|
+
def test_requires_a_block
|
10
|
+
assert_raises ArgumentError do
|
11
|
+
NotificationListener.new
|
12
|
+
end
|
8
13
|
end
|
9
14
|
|
10
|
-
def
|
15
|
+
def test_caches_listeners
|
16
|
+
listener = NotificationListener.new { |_| }
|
17
|
+
assert_includes NotificationListener.registered_listeners, listener
|
11
18
|
end
|
12
19
|
|
13
|
-
def
|
20
|
+
def test_executes_block_when_notif_is_received
|
21
|
+
got_callback = false
|
22
|
+
NotificationListener.new named: 'test' do |_|
|
23
|
+
got_callback = true
|
24
|
+
end
|
25
|
+
NSNotificationCenter.defaultCenter.postNotificationName 'test',
|
26
|
+
object: self
|
27
|
+
assert got_callback
|
14
28
|
end
|
15
29
|
|
16
|
-
def
|
30
|
+
def test_can_stop_listening
|
31
|
+
got_callback = false
|
32
|
+
listener = NotificationListener.new named: 'test2' do |_|
|
33
|
+
got_callback = true
|
34
|
+
end
|
35
|
+
listener.stop_listening
|
36
|
+
NSNotificationCenter.defaultCenter.postNotificationName 'test2',
|
37
|
+
object: self
|
38
|
+
|
39
|
+
refute_includes NotificationListener.registered_listeners, listener
|
40
|
+
refute got_callback
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_on_notification_is_alias
|
44
|
+
listener = ::HotCocoa.on_notification { |_| }
|
45
|
+
assert_kind_of NotificationListener, listener
|
17
46
|
end
|
18
47
|
|
19
48
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: hotcocoa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: 5
|
5
|
-
version: 0.6.
|
5
|
+
version: 0.6.0pre2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Richard Kilmer
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-10-
|
13
|
+
date: 2011-10-08 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -168,6 +168,7 @@ files:
|
|
168
168
|
- lib/hotcocoa/mappings.rb
|
169
169
|
- lib/hotcocoa/mvc.rb
|
170
170
|
- lib/hotcocoa/notification_listener.rb
|
171
|
+
- lib/hotcocoa/rake_tasks.rb
|
171
172
|
- lib/hotcocoa/standard_rake_tasks.rb
|
172
173
|
- lib/hotcocoa/target_action_convenience.rb
|
173
174
|
- lib/hotcocoa/template.rb
|
@@ -178,6 +179,7 @@ files:
|
|
178
179
|
- template/lib/menu.rb
|
179
180
|
- template/Rakefile
|
180
181
|
- template/resources/HotCocoa.icns
|
182
|
+
- test/application/helper.rb
|
181
183
|
- test/application/test_builder.rb
|
182
184
|
- test/application/test_specification.rb
|
183
185
|
- test/core_extensions/test_kernel.rb
|
@@ -237,6 +239,7 @@ signing_key:
|
|
237
239
|
specification_version: 3
|
238
240
|
summary: Cocoa mapping library for MacRuby
|
239
241
|
test_files:
|
242
|
+
- test/application/helper.rb
|
240
243
|
- test/application/test_builder.rb
|
241
244
|
- test/application/test_specification.rb
|
242
245
|
- test/core_extensions/test_kernel.rb
|