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
@@ -1,294 +1,390 @@
1
1
  framework 'Foundation'
2
2
 
3
3
  require 'fileutils'
4
+ require 'rbconfig'
5
+ require 'yaml'
4
6
 
5
7
  module HotCocoa
6
-
8
+
7
9
  class ApplicationBuilder
8
-
10
+
11
+ ##
12
+ # @todo support CFBundleDocumentTypes
13
+ # @todo support CFBundleShortVersionString
14
+ # @todo support NSHumanReadableCopyright
15
+ # @todo support arbitrary info.plist key/value pairs
9
16
  class Configuration
10
-
11
- attr_reader :name, :version, :icon, :resources, :sources, :info_string, :load
12
-
13
- def initialize(file)
14
- require 'yaml'
15
- yml = YAML.load(File.read(file))
16
- @name = yml["name"]
17
- @load = yml["load"]
18
- @version = yml["version"] || "1.0"
19
- @icon = yml["icon"]
20
- @info_string = yml["info_string"]
21
- @sources = yml["sources"] || []
22
- @resources = yml["resources"] || []
23
- @overwrite = yml["overwrite"] == true ? true : false
24
- end
25
-
26
- def overwrite?
27
- @overwrite
28
- end
29
17
 
30
- def icon_exist?
31
- @icon ? File.exist?(@icon) : false
32
- end
18
+ ##
19
+ # Name of the app
20
+ #
21
+ # @return [String]
22
+ attr_reader :name
33
23
 
34
- end
35
-
36
- ApplicationBundlePackage = "APPL????"
37
-
38
- attr_accessor :name, :load_file, :sources, :overwrite, :icon, :version, :info_string, :resources, :deploy
39
-
40
- def self.build(config, options={:deploy => false})
41
- if !config.kind_of?(Configuration) || !$LOADED_FEATURES.detect {|f| f.include?("standard_rake_tasks")}
42
- require 'rbconfig'
43
- puts "Your Rakefile needs to be updated. Please copy the Rakefile from:"
44
- puts File.expand_path(File.join(Config::CONFIG['datadir'], "hotcocoa_template", "Rakefile"))
45
- exit
46
- end
47
- builder = new
48
- builder.deploy = options[:deploy] == true ? true : false
49
- builder.name = config.name
50
- builder.load_file = config.load
51
- builder.icon = config.icon if config.icon_exist?
52
- builder.version = config.version
53
- builder.info_string = config.info_string
54
- builder.overwrite = config.overwrite?
55
- config.sources.each do |source|
56
- builder.add_source_path source
24
+ ##
25
+ # Reverse URL unique identifier
26
+ #
27
+ # @example Identifier for Mail.app
28
+ #
29
+ # 'com.apple.mail'
30
+ #
31
+ # @return [String]
32
+ attr_reader :identifier
33
+
34
+ ##
35
+ # Version of the app
36
+ #
37
+ # @return [String]
38
+ attr_reader :version
39
+
40
+ ##
41
+ # Path to the icon file
42
+ #
43
+ # @return [String]
44
+ attr_reader :icon
45
+
46
+ ##
47
+ # Globbing patterns describing where to find resources that need
48
+ # to be copied into the app bundle
49
+ #
50
+ # @return [Array<String>]
51
+ attr_reader :resources
52
+
53
+ ##
54
+ # Globbing patterns describing where to find source code that
55
+ # needs to be copied into the app bundle
56
+ #
57
+ # @return [Array<String>]
58
+ attr_reader :sources
59
+
60
+ ##
61
+ # Whether the app is an daemon with UI or a regular app
62
+ #
63
+ # @return [Boolean]
64
+ attr_reader :agent
65
+
66
+ ##
67
+ # Whether to include the Ruby stdlib in the app
68
+ #
69
+ # @return [Boolean]
70
+ attr_reader :stdlib
71
+
72
+ ##
73
+ # Any `.xcdatamodel` directories to compile and add to the app
74
+ # bundle
75
+ #
76
+ # @return [Array<String>]
77
+ attr_reader :data_models
78
+
79
+ ##
80
+ # Four letter code identifying bundle type, the default value is 'APPL'
81
+ # to specify the bundle is an application
82
+ #
83
+ # @return [String]
84
+ attr_reader :type
85
+
86
+ ##
87
+ # Four letter code that is a signature of the bundle, defaults
88
+ # to '????' since most apps never set this value
89
+ #
90
+ # @example TextEdit
91
+ #
92
+ # 'ttxt'
93
+ #
94
+ # @example Mail
95
+ #
96
+ # 'emal'
97
+ #
98
+ # @return [String]
99
+ attr_reader :signature
100
+
101
+ ##
102
+ # An array of gem names to embed in the app bundle during
103
+ # deployment
104
+ #
105
+ # @return [Array<String>]
106
+ attr_reader :gems
107
+
108
+ ##
109
+ # Whether or not to embed BridgeSupport files embedding the
110
+ # MacRuby framework
111
+ #
112
+ # @return [Boolean]
113
+ attr_reader :embed_bs
114
+ alias_method :embed_bs?, :embed_bs
115
+
116
+ ##
117
+ # Always make a clean build of the app
118
+ #
119
+ # @return [Boolean]
120
+ attr_reader :overwrite
121
+ alias_method :overwrite?, :overwrite
122
+
123
+ # @todo validation (sources should not be an empty array)
124
+ def initialize file
125
+ yml = YAML.load(File.read(file))
126
+ @name = yml['name'] # mandatory
127
+ @icon = yml['icon']
128
+ @identifier = yml['identifier'] || "com.#{@name}"
129
+ @version = yml['version'] || '1.0'
130
+ @sources = yml['sources'] || [] # this should be mandatory?
131
+ @resources = yml['resources'] || []
132
+ @data_models = yml['data_models'] || []
133
+ @gems = yml['gems'] || []
134
+ @type = yml['type'] || 'APPL'
135
+ @signature = yml['signature'] || '????'
136
+ @overwrite = yml['overwrite'] == true ? true : false
137
+ @agent = yml['agent'] == true ? '1' : '0'
138
+ @stdlib = yml['stdlib'] == false ? false : true
139
+ @embed_bs = yml['embed_bs'] == false ? false : true
57
140
  end
58
- config.resources.each do |resource|
59
- builder.add_resource_path resource
141
+
142
+ def icon_exists?
143
+ @icon ? File.exist?(@icon) : false
60
144
  end
61
- builder.build
62
145
  end
63
146
 
64
- # Used by the "Embed MacRuby" Xcode target.
65
- def self.deploy(path)
66
- raise "Given path `#{path}' does not exist" unless File.exist?(path)
67
- raise "Given path `#{path}' does not look like an application bundle" unless File.extname(path) == '.app'
68
- deployer = new
69
- Dir.chdir(File.dirname(path)) do
70
- deployer.name = File.basename(path, '.app')
71
- deployer.deploy
147
+ ##
148
+ # The cached app configuration options
149
+ #
150
+ # @return [HotCocoa::ApplicationBuilder::Configuration]
151
+ attr_accessor :config
152
+
153
+ ##
154
+ # Whether or not to build the app bundle for deployment by calling
155
+ # `macruby_deploy` on the generated app bundle
156
+ #
157
+ # @return [Boolean]
158
+ attr_accessor :deploy
159
+ alias_method :deploy?, :deploy
160
+
161
+ # @return [Array<String>]
162
+ attr_accessor :sources
163
+
164
+ # @return [Array<String>]
165
+ attr_accessor :resources
166
+
167
+ # @return [Array<String>]
168
+ attr_accessor :data_models
169
+
170
+ def self.build config, opts = {}
171
+ options = { deploy: false }.merge opts
172
+
173
+ builder = new
174
+ builder.config = config
175
+ builder.deploy = options[:deploy]
176
+
177
+ config.sources.each { |source| builder.add_source_path(source) }
178
+ config.resources.each { |resource| builder.add_resource_path(resource) }
179
+ config.data_models.each do |data|
180
+ builder.add_data_model(data) if File.extname(data) == '.xcdatamodel'
72
181
  end
182
+
183
+ builder.build
73
184
  end
74
185
 
75
186
  def initialize
76
- @sources = []
77
- @resources = []
187
+ @sources = []
188
+ @resources = []
189
+ @data_models = []
78
190
  end
79
-
191
+
80
192
  def build
81
193
  check_for_bundle_root
82
194
  build_bundle_structure
83
195
  write_bundle_files
84
196
  copy_sources
85
197
  copy_resources
86
- deploy if deploy?
87
- copy_icon_file if icon
88
- end
89
-
90
- def deploy
91
- copy_framework
198
+ compile_data_models
199
+ embed_framework if deploy?
200
+ copy_icon_file if config.icon_exists?
92
201
  end
93
202
 
94
- def deploy?
95
- @deploy
96
- end
97
-
98
- def overwrite?
99
- @overwrite
100
- end
101
-
102
- def add_source_path(source_file_pattern)
203
+ def add_source_path source_file_pattern
103
204
  Dir.glob(source_file_pattern).each do |source_file|
104
205
  sources << source_file
105
206
  end
106
207
  end
107
208
 
108
- def add_resource_path(resource_file_pattern)
209
+ def add_resource_path resource_file_pattern
109
210
  Dir.glob(resource_file_pattern).each do |resource_file|
110
211
  resources << resource_file
111
212
  end
112
213
  end
113
-
114
- private
115
-
116
- def check_for_bundle_root
117
- if File.exist?(bundle_root) && overwrite?
118
- `rm -rf #{bundle_root}`
119
- end
120
- end
121
-
122
- def build_bundle_structure
123
- Dir.mkdir(bundle_root) unless File.exist?(bundle_root)
124
- Dir.mkdir(contents_root) unless File.exist?(contents_root)
125
- Dir.mkdir(frameworks_root) unless File.exist?(frameworks_root)
126
- Dir.mkdir(macos_root) unless File.exist?(macos_root)
127
- Dir.mkdir(resources_root) unless File.exist?(resources_root)
128
- end
129
-
130
- def write_bundle_files
131
- write_pkg_info_file
132
- write_info_plist_file
133
- build_executable unless File.exist?(File.join(macos_root, objective_c_executable_file))
134
- write_ruby_main
214
+
215
+ def add_data_model model
216
+ Dir.glob(model).each do |data|
217
+ data_models << data
135
218
  end
136
-
137
- def copy_framework
138
- unless File.exist?(File.join(frameworks_root, 'MacRuby.framework'))
139
- FileUtils.mkdir_p frameworks_root
140
- FileUtils.cp_r macruby_framework_path, frameworks_root
141
- end
142
- `install_name_tool -change #{current_macruby_path}/usr/lib/libmacruby.dylib @executable_path/../Frameworks/MacRuby.framework/Versions/#{current_macruby_version}/usr/lib/libmacruby.dylib '#{macos_root}/#{objective_c_executable_file}'`
219
+ end
220
+
221
+
222
+ private
223
+
224
+ def check_for_bundle_root
225
+ FileUtils.rm_rf bundle_root if File.exist?(bundle_root) && config.overwrite?
226
+ end
227
+
228
+ def build_bundle_structure
229
+ [bundle_root, contents_root, frameworks_root,
230
+ macos_root, resources_root].each do |dir|
231
+ Dir.mkdir(dir) unless File.exist?(dir)
143
232
  end
144
-
145
- def copy_sources
146
- FileUtils.cp_r load_file, resources_root unless sources.include?(load_file)
147
- sources.each do |source|
148
- destination = File.join(resources_root, source)
149
- FileUtils.mkdir_p(File.dirname(destination)) unless File.exist?(File.dirname(destination))
150
- FileUtils.cp_r source, destination
151
- end
233
+ end
234
+
235
+ def write_bundle_files
236
+ write_pkg_info_file
237
+ write_info_plist_file
238
+ build_executable unless File.exist?(File.join(macos_root, objective_c_executable_file))
239
+ write_ruby_main
240
+ end
241
+
242
+ def copy_sources
243
+ sources.each do |source|
244
+ destination = File.join(resources_root, source)
245
+ FileUtils.mkdir_p(File.dirname(destination)) unless File.exist?(File.dirname(destination))
246
+ FileUtils.cp_r source, destination
152
247
  end
153
-
154
- def copy_resources
155
- resources.each do |resource|
156
- destination = File.join(resources_root, resource.split("/")[1..-1].join("/"))
157
- FileUtils.mkdir_p(File.dirname(destination)) unless File.exist?(File.dirname(destination))
248
+ end
249
+
250
+ def copy_resources
251
+ resources.each do |resource|
252
+ destination = File.join(resources_root, resource.split("/")[1..-1].join("/"))
253
+ FileUtils.mkdir_p(File.dirname(destination)) unless File.exist?(File.dirname(destination))
254
+
255
+ if resource =~ /\.xib$/
256
+ destination.gsub!(/.xib/, '.nib')
257
+ puts `ibtool --compile #{destination} #{resource}`
258
+ else
158
259
  FileUtils.cp_r resource, destination
159
260
  end
160
261
  end
161
-
162
- def copy_icon_file
163
- FileUtils.cp(icon, icon_file) unless File.exist?(icon_file)
164
- end
165
-
166
- def write_pkg_info_file
167
- File.open(pkg_info_file, "wb") {|f| f.write ApplicationBundlePackage}
168
- end
262
+ end
169
263
 
170
- def write_info_plist_file
171
- File.open(info_plist_file, "w") do |f|
172
- f.puts %{<?xml version="1.0" encoding="UTF-8"?>}
173
- f.puts %{<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">}
174
- f.puts %{<plist version="1.0">}
175
- f.puts %{<dict>}
176
- f.puts %{ <key>CFBundleDevelopmentRegion</key>}
177
- f.puts %{ <string>English</string>}
178
- f.puts %{ <key>CFBundleIconFile</key>} if icon
179
- f.puts %{ <string>#{name}.icns</string>} if icon
180
- f.puts %{ <key>CFBundleGetInfoString</key>} if info_string
181
- f.puts %{ <string>#{info_string}</string>} if info_string
182
- f.puts %{ <key>CFBundleExecutable</key>}
183
- f.puts %{ <string>#{name.gsub(/ /, '')}</string>}
184
- f.puts %{ <key>CFBundleIdentifier</key>}
185
- f.puts %{ <string>com.yourcompany.#{name}</string>}
186
- f.puts %{ <key>CFBundleInfoDictionaryVersion</key>}
187
- f.puts %{ <string>6.0</string>}
188
- f.puts %{ <key>CFBundleName</key>}
189
- f.puts %{ <string>#{name}</string>}
190
- f.puts %{ <key>CFBundlePackageType</key>}
191
- f.puts %{ <string>APPL</string>}
192
- f.puts %{ <key>CFBundleSignature</key>}
193
- f.puts %{ <string>????</string>}
194
- f.puts %{ <key>CFBundleVersion</key>}
195
- f.puts %{ <string>#{version}</string>}
196
- f.puts %{ <key>NSPrincipalClass</key>}
197
- f.puts %{ <string>NSApplication</string>}
198
- f.puts %{</dict>}
199
- f.puts %{</plist>}
200
- end
264
+ def compile_data_models
265
+ data_models.each do |data|
266
+ `/Developer/usr/bin/momc #{data} #{resources_root}/#{File.basename(data, ".xcdatamodel")}.mom`
201
267
  end
202
-
203
- def build_executable
204
- File.open(objective_c_source_file, "wb") do |f|
205
- f.puts %{
206
-
207
- #import <MacRuby/MacRuby.h>
208
-
209
- int main(int argc, char *argv[])
210
- {
211
- return macruby_main("rb_main.rb", argc, argv);
212
- }
268
+ end
269
+
270
+ def copy_icon_file
271
+ FileUtils.cp config.icon, icon_file
272
+ end
273
+
274
+ def write_pkg_info_file
275
+ File.open(pkg_info_file, 'wb') { |f| f.write "#{config.type}#{config.signature}" }
276
+ end
277
+
278
+ def write_info_plist_file
279
+ # http://developer.apple.com/library/mac/#documentation/General/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html%23//apple_ref/doc/uid/TP40009254-SW1
280
+ info = {
281
+ CFBundleName: config.name,
282
+ CFBundleIdentifier: config.identifier,
283
+ CFBundleVersion: config.version,
284
+ CFBundlePackageType: config.type,
285
+ CFBundleSignature: config.signature,
286
+ CFBundleExecutable: objective_c_executable_file,
287
+ CFBundleDevelopmentRegion: 'English',
288
+ CFBundleInfoDictionaryVersion: '6.0',
289
+ NSPrincipalClass: 'NSApplication',
290
+ LSUIElement: config.agent,
291
+ LSMinimumSystemVersion: '10.6.7', # should match MacRuby
292
+ }
293
+ info[:CFBundleIconFile] = File.basename(config.icon) if config.icon_exists?
294
+
295
+ File.open(info_plist_file, 'w') { |f| f.write info.to_plist }
296
+ end
297
+
298
+ def embed_framework # and also gems
299
+ options = config.stdlib ? '' : '--no-stdlib '
300
+ config.gems.each { |gem| options << "--gem #{gem} " }
301
+ options << '--bs ' if config.embed_bs?
302
+ puts `macruby_deploy --embed --gem hotcocoa #{options} #{bundle_root}`
303
+ end
304
+
305
+ # @todo something better than puts `gcc`
306
+ def build_executable
307
+ File.open(objective_c_source_file, 'wb') do |f|
308
+ f.write %{
309
+ #import <MacRuby/MacRuby.h>
310
+
311
+ int main(int argc, char *argv[])
312
+ {
313
+ return macruby_main("rb_main.rb", argc, argv);
213
314
  }
214
- end
215
- archs = RUBY_ARCH.include?('ppc') ? '-arch ppc' : '-arch i386 -arch x86_64'
216
- puts `cd "#{macos_root}" && gcc main.m -o #{objective_c_executable_file} #{archs} -framework MacRuby -framework Foundation -fobjc-gc-only`
217
- File.unlink(objective_c_source_file)
218
- end
219
-
220
- def write_ruby_main
221
- File.open(main_ruby_source_file, "wb") do |f|
222
- f.puts "$:.map! { |x| x.sub(/^\\/Library\\/Frameworks/, NSBundle.mainBundle.privateFrameworksPath) }" if deploy?
223
- f.puts "$:.unshift NSBundle.mainBundle.resourcePath.fileSystemRepresentation"
224
- f.puts "load '#{load_file}'"
225
- end
226
- end
227
-
228
- def bundle_root
229
- "#{name}.app"
315
+ }
230
316
  end
231
-
232
- def contents_root
233
- File.join(bundle_root, "Contents")
317
+ Dir.chdir(macos_root) do
318
+ puts `gcc main.m -o #{objective_c_executable_file} -arch x86_64 -framework MacRuby -framework Foundation -fobjc-gc-only`
234
319
  end
320
+ File.unlink(objective_c_source_file)
321
+ end
235
322
 
236
- def frameworks_root
237
- File.join(contents_root, "Frameworks")
238
- end
239
-
240
- def macos_root
241
- File.join(contents_root, "MacOS")
242
- end
243
-
244
- def resources_root
245
- File.join(contents_root, "Resources")
246
- end
323
+ # Borrow rb_main from MacRuby Xcode templates
324
+ def write_ruby_main
325
+ File.open(main_ruby_source_file, 'wb') do |f|
326
+ f.write <<-EOF
327
+ # Borrowed from the MacRuby sources on April 18, 2011
328
+ framework 'Cocoa'
247
329
 
248
- def bridgesupport_root
249
- File.join(resources_root, "BridgeSupport")
250
- end
251
-
252
- def info_plist_file
253
- File.join(contents_root, "Info.plist")
254
- end
255
-
256
- def icon_file
257
- File.join(resources_root, "#{name}.icns")
258
- end
259
-
260
- def pkg_info_file
261
- File.join(contents_root, "PkgInfo")
262
- end
263
-
264
- def objective_c_executable_file
265
- name.gsub(/ /, '')
266
- end
267
-
268
- def objective_c_source_file
269
- File.join(macos_root, "main.m")
270
- end
271
-
272
- def main_ruby_source_file
273
- File.join(resources_root, "rb_main.rb")
274
- end
275
-
276
- def current_macruby_version
277
- NSFileManager.defaultManager.pathContentOfSymbolicLinkAtPath(File.join(macruby_versions_path, "Current"))
278
- end
279
-
280
- def current_macruby_path
281
- File.join(macruby_versions_path, current_macruby_version)
282
- end
283
-
284
- def macruby_versions_path
285
- File.join(macruby_framework_path, "Versions")
286
- end
287
-
288
- def macruby_framework_path
289
- "/Library/Frameworks/MacRuby.framework"
330
+ # Loading all the Ruby project files.
331
+ main = File.basename(__FILE__, File.extname(__FILE__))
332
+ dir_path = NSBundle.mainBundle.resourcePath.fileSystemRepresentation
333
+ dir_path += "/lib/"
334
+ Dir.glob(File.join(dir_path, '*.{rb,rbo}')).map { |x| File.basename(x, File.extname(x)) }.uniq.each do |path|
335
+ if path != main
336
+ require File.join(dir_path, path)
337
+ end
338
+ end
339
+
340
+ # Starting the Cocoa main loop.
341
+ NSApplicationMain(0, nil)
342
+ EOF
290
343
  end
344
+ end
291
345
 
346
+ def bundle_root
347
+ "#{config.name}.app"
348
+ end
349
+
350
+ def contents_root
351
+ File.join(bundle_root, "Contents")
352
+ end
353
+
354
+ def frameworks_root
355
+ File.join(contents_root, "Frameworks")
356
+ end
357
+
358
+ def macos_root
359
+ File.join(contents_root, "MacOS")
360
+ end
361
+
362
+ def resources_root
363
+ File.join(contents_root, "Resources")
364
+ end
365
+
366
+ def info_plist_file
367
+ File.join(contents_root, "Info.plist")
368
+ end
369
+
370
+ def icon_file
371
+ File.join(resources_root, "#{config.name}.icns")
372
+ end
373
+
374
+ def pkg_info_file
375
+ File.join(contents_root, "PkgInfo")
376
+ end
377
+
378
+ def objective_c_executable_file
379
+ config.name.gsub(/\s+/, '')
380
+ end
381
+
382
+ def objective_c_source_file
383
+ File.join(macos_root, "main.m")
384
+ end
385
+
386
+ def main_ruby_source_file
387
+ File.join(resources_root, "rb_main.rb")
388
+ end
292
389
  end
293
-
294
390
  end