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,448 +1,463 @@
1
1
  module HotCocoa
2
-
3
- module LayoutManaged
4
-
5
- def layout=(options)
6
- @layout = LayoutOptions.new(self, options)
7
- @layout.update_layout_views!
8
- end
9
-
10
- def layout
11
- @layout
12
- end
13
-
14
- end
2
+ class LayoutOptions
3
+ VALID_EXPANSIONS = [nil, :height, :width, [:height, :width], [:width, :height]]
4
+
5
+ attr_accessor :defaults_view
6
+
7
+ # @return [NSView]
8
+ attr_reader :view
9
+
10
+ # @param [NSView] view
11
+ # @param [Hash] options
12
+ #
13
+ # @option options [Boolean] :start (true) Whether the view is packed
14
+ # at the start or the end of the packing view
15
+ #
16
+ # @option options [Symbol] :expand (nil) Whether the view's first
17
+ # dimension (width for horizontal and height for vertical) should
18
+ # be expanded to the maximum possible size, and should be variable
19
+ # according to the packing view frame. Values can be `:height`,
20
+ # `:width`, or `[:height, :width]`
21
+ #
22
+ # @option options [Float] :padding (0.0) Controls the padding area
23
+ # around the view. `:padding` controls all the areas, while options
24
+ # like `:left_padding` only control the left side--if `:padding`
25
+ # is set, other padding flags are ignored
26
+ # @option options [Fload] :left_padding (0.0)
27
+ # @option options [Float] :right_padding (0.0)
28
+ # @option options [Float] :top_padding (0.0)
29
+ # @option options [Float] :bottom_padding (0.0)
30
+ #
31
+ # @option options [Symbol] :align Controls the view's alignment if
32
+ # its not expanded in the other dimension; modes can be:
33
+ #
34
+ # * `:left`
35
+ # For horizontal layouts, align left
36
+ #
37
+ # * `:center`
38
+ # Align center for horizontal or vertical layouts
39
+ #
40
+ # * `:right`
41
+ # For horizontal layouts, align right
42
+ #
43
+ # * `:top`
44
+ # For vertical layouts, align top
45
+ #
46
+ # * `:bottom`
47
+ # For vertical layouts, align bottom
48
+ #
49
+ # @option options [NSView] :defaults_view not sure yet...
50
+ def initialize view, options = {}
51
+ @view = view
52
+ @start = options[:start]
53
+ @expand = options[:expand]
54
+ @padding = options[:padding]
55
+ @left_padding = @padding || options[:left_padding]
56
+ @right_padding = @padding || options[:right_padding]
57
+ @top_padding = @padding || options[:top_padding]
58
+ @bottom_padding = @padding || options[:bottom_padding]
59
+ @align = options[:align]
60
+ @defaults_view = options[:defaults_view]
61
+ end
15
62
 
16
- class LayoutOptions
17
-
18
- VALID_EXPANSIONS = [nil, :height, :width, [:height, :width], [:width, :height]]
19
-
20
- attr_accessor :defaults_view
21
- attr_reader :view
22
-
23
- # options can be
24
- #
25
- # :start -> bool
26
- # Whether the view is packed at the start or the end of the packing view.
27
- # Default value is true.
28
- #
29
- # :expand -> :height, :width, [:height, :width]
30
- # Whether the view's first dimension (width for horizontal and height for vertical)
31
- # should be expanded to the maximum possible size, and should be variable according
32
- # to the packing view frame.
33
- # Default value is nil.
34
- #
35
- # :padding -> float
36
- # :left_padding -> float
37
- # :right_padding -> float
38
- # :top_padding -> float
39
- # :bottom_padding -> float
40
- # Controls the padding area around the view. :padding controls all areas, while
41
- # :left_padding for example only controls the left side. If :padding is set, other
42
- # padding flags are ignored.
43
- # Default value is 0.0 for all flags.
44
- #
45
- # :align -> mode
46
- # Controls the view's alignment if its not expanded in the other dimension
47
- # Modes can be:
48
- # :left
49
- # For horizontal layouts, align left
50
- # :center
51
- # Align center for horizontal or vertical layouts
52
- # :right
53
- # For horizontal layouts, align right
54
- # :top
55
- # For vertical layouts, align top
56
- # :bottom
57
- # For vertical layouts, align bottom
58
- def initialize(view, options={})
59
- @view = view
60
- @start = options[:start]
61
- @expand = options[:expand]
62
- @padding = options[:padding]
63
- @left_padding = @padding || options[:left_padding]
64
- @right_padding = @padding || options[:right_padding]
65
- @top_padding = @padding || options[:top_padding]
66
- @bottom_padding = @padding || options[:bottom_padding]
67
- @align = options[:align]
68
- @defaults_view = options[:defaults_view]
69
- end
70
-
71
- def start=(value)
72
- return if value == @start
73
- @start = value
74
- update_layout_views!
75
- end
76
-
77
- def start?
78
- return @start unless @start.nil?
79
- if in_layout_view?
80
- @view.superview.default_layout.start?
81
- else
82
- true
63
+ def start= value
64
+ return if value == @start
65
+ @start = value
66
+ update_layout_views!
83
67
  end
84
- end
85
-
86
- def expand=(value)
87
- return if value == @expand
88
- unless VALID_EXPANSIONS.include?(value)
89
- raise ArgumentError, "Expand must be nil, :height, :width or [:width, :height] not #{value.inspect}"
90
- end
91
- @expand = value
92
- update_layout_views!
93
- end
94
-
95
- def expand
96
- return @expand unless @expand.nil?
97
- if in_layout_view?
98
- @view.superview.default_layout.expand
99
- else
100
- false
68
+
69
+ def start?
70
+ return @start unless @start.nil?
71
+ if in_layout_view?
72
+ @view.superview.default_layout.start?
73
+ else
74
+ true
75
+ end
101
76
  end
102
- end
103
77
 
104
- def expand_width?
105
- e = self.expand
106
- e == :width || (e.respond_to?(:include?) && e.include?(:width))
107
- end
78
+ def expand= value
79
+ return if value == @expand
80
+ unless VALID_EXPANSIONS.include?(value)
81
+ raise ArgumentError, "Expand must be nil, :height, :width or [:width, :height] not #{value.inspect}"
82
+ end
83
+ @expand = value
84
+ update_layout_views!
85
+ end
108
86
 
109
- def expand_height?
110
- e = self.expand
111
- e == :height || (e.respond_to?(:include?) && e.include?(:height))
112
- end
113
-
114
- def left_padding=(value)
115
- return if value == @left_padding
116
- @left_padding = value
117
- @padding = nil
118
- update_layout_views!
119
- end
120
-
121
- def left_padding
122
- return @left_padding unless @left_padding.nil?
123
- if in_layout_view?
124
- @view.superview.default_layout.left_padding
125
- else
126
- @padding || 0.0
87
+ def expand
88
+ return @expand unless @expand.nil?
89
+ if in_layout_view?
90
+ @view.superview.default_layout.expand
91
+ else
92
+ false
93
+ end
127
94
  end
128
- end
129
95
 
130
- def right_padding=(value)
131
- return if value == @right_padding
132
- @right_padding = value
133
- @padding = nil
134
- update_layout_views!
135
- end
136
-
137
- def right_padding
138
- return @right_padding unless @right_padding.nil?
139
- if in_layout_view?
140
- @view.superview.default_layout.right_padding
141
- else
142
- @padding || 0.0
96
+ def expand_width?
97
+ e = self.expand
98
+ e == :width || (e.respond_to?(:include?) && e.include?(:width))
143
99
  end
144
- end
145
100
 
146
- def top_padding=(value)
147
- return if value == @top_padding
148
- @top_padding = value
149
- @padding = nil
150
- update_layout_views!
151
- end
101
+ def expand_height?
102
+ e = self.expand
103
+ e == :height || (e.respond_to?(:include?) && e.include?(:height))
104
+ end
152
105
 
153
- def top_padding
154
- return @top_padding unless @top_padding.nil?
155
- if in_layout_view?
156
- @view.superview.default_layout.top_padding
157
- else
158
- @padding || 0.0
106
+ def left_padding= value
107
+ return if value == @left_padding
108
+ @left_padding = value
109
+ @padding = nil
110
+ update_layout_views!
159
111
  end
160
- end
161
112
 
162
- def bottom_padding=(value)
163
- return if value == @bottom_padding
164
- @bottom_padding = value
165
- @padding = nil
166
- update_layout_views!
167
- end
113
+ def left_padding
114
+ return @left_padding unless @left_padding.nil?
115
+ if in_layout_view?
116
+ @view.superview.default_layout.left_padding
117
+ else
118
+ padding
119
+ end
120
+ end
121
+
122
+ def right_padding= value
123
+ return if value == @right_padding
124
+ @right_padding = value
125
+ @padding = nil
126
+ update_layout_views!
127
+ end
128
+
129
+ def right_padding
130
+ return @right_padding unless @right_padding.nil?
131
+ if in_layout_view?
132
+ @view.superview.default_layout.right_padding
133
+ else
134
+ padding
135
+ end
136
+ end
137
+
138
+ def top_padding= value
139
+ return if value == @top_padding
140
+ @top_padding = value
141
+ @padding = nil
142
+ update_layout_views!
143
+ end
144
+
145
+ def top_padding
146
+ return @top_padding unless @top_padding.nil?
147
+ if in_layout_view?
148
+ @view.superview.default_layout.top_padding
149
+ else
150
+ padding
151
+ end
152
+ end
153
+
154
+ def bottom_padding= value
155
+ return if value == @bottom_padding
156
+ @bottom_padding = value
157
+ @padding = nil
158
+ update_layout_views!
159
+ end
160
+
161
+ def bottom_padding
162
+ return @bottom_padding unless @bottom_padding.nil?
163
+ if in_layout_view?
164
+ @view.superview.default_layout.bottom_padding
165
+ else
166
+ padding
167
+ end
168
+ end
169
+
170
+ def align
171
+ return @align unless @align.nil?
172
+ if in_layout_view?
173
+ @view.superview.default_layout.align
174
+ else
175
+ :left
176
+ end
177
+ end
168
178
 
169
- def bottom_padding
170
- return @bottom_padding unless @bottom_padding.nil?
171
- if in_layout_view?
172
- @view.superview.default_layout.bottom_padding
173
- else
179
+ def align= value
180
+ return if value == @align
181
+ @align = value
182
+ update_layout_views!
183
+ end
184
+
185
+ def padding= value
186
+ return if value == @padding
187
+ @right_padding = @left_padding = @top_padding = @bottom_padding = value
188
+ @padding = value
189
+ update_layout_views!
190
+ end
191
+
192
+ def padding
174
193
  @padding || 0.0
175
194
  end
176
- end
177
-
178
- def align
179
- return @align unless @align.nil?
180
- if in_layout_view?
181
- @view.superview.default_layout.align
182
- else
183
- :left
195
+
196
+ def inspect
197
+ "#<#{self.class} " +
198
+ "start=#{start?}, " +
199
+ "expand=#{expand.inspect}, " +
200
+ "padding=[l:#{left_padding}, r:#{right_padding}, t:#{top_padding}, b:#{bottom_padding}], " +
201
+ "align=#{align.inspect}, " +
202
+ "view=#{view.inspect}>"
184
203
  end
185
- end
186
204
 
187
- def align=(value)
188
- return if value == @align
189
- @align = value
190
- update_layout_views!
191
- end
192
-
193
- def padding=(value)
194
- return if value == @padding
195
- @right_padding = @left_padding = @top_padding = @bottom_padding = value
196
- @padding = value
197
- update_layout_views!
198
- end
199
-
200
- def padding
201
- @padding
202
- end
203
-
204
- def inspect
205
- "#<#{self.class} start=#{start?}, expand=#{expand.inspect}, left_padding=#{left_padding}, right_padding=#{right_padding}, top_padding=#{top_padding}, bottom_padding=#{bottom_padding}, align=#{align.inspect}, view=#{view.inspect}>"
206
- end
205
+ def update_layout_views!
206
+ @view.superview.views_updated! if in_layout_view?
207
+ @defaults_view.views_updated! if @defaults_view
208
+ end
209
+
210
+ private
207
211
 
208
- def update_layout_views!
209
- @view.superview.views_updated! if in_layout_view?
210
- @defaults_view.views_updated! if @defaults_view
211
- end
212
-
213
- private
214
-
215
212
  def in_layout_view?
216
213
  @view && @view.superview.kind_of?(LayoutView)
217
214
  end
215
+ end
218
216
 
219
-
220
- end
217
+ class LayoutView < NSView
218
+ attr_accessor :frame_color
221
219
 
222
- class LayoutView < NSView
223
-
224
- attr_accessor :frame_color
225
-
226
- def initWithFrame(frame)
227
- super
228
- @mode = :vertical
229
- @spacing = 10.0
230
- @margin = 10.0
231
- self
232
- end
220
+ def initWithFrame frame
221
+ super
222
+ @mode = :vertical
223
+ @spacing = 10.0
224
+ @margin = 10.0
225
+ self
226
+ end
233
227
 
234
- def vertical?
235
- @mode == :vertical
236
- end
228
+ def vertical?
229
+ @mode == :vertical
230
+ end
237
231
 
238
- def horizontal?
239
- @mode == :horizonal
240
- end
232
+ def horizontal?
233
+ @mode == :horizonal
234
+ end
235
+
236
+ def mode= mode
237
+ unless [:horizontal, :vertical].include?(mode)
238
+ raise ArgumentError, "invalid mode value #{mode}"
239
+ end
241
240
 
242
- def mode=(mode)
243
- if mode != :horizontal and mode != :vertical
244
- raise ArgumentError, "invalid mode value #{mode}"
241
+ if mode != @mode
242
+ @mode = mode
243
+ relayout!
244
+ end
245
245
  end
246
- if mode != @mode
247
- @mode = mode
246
+
247
+ def default_layout= options
248
+ options[:defaults_view] = self
249
+ @default_layout = LayoutOptions.new(nil, options)
248
250
  relayout!
249
251
  end
250
- end
251
-
252
- def default_layout=(options)
253
- options[:defaults_view] = self
254
- @default_layout = LayoutOptions.new(nil, options)
255
- relayout!
256
- end
257
-
258
- def default_layout
259
- @default_layout ||= LayoutOptions.new(nil, :defaults_view => self)
260
- end
261
252
 
262
- def spacing
263
- @spacing
264
- end
253
+ def default_layout
254
+ @default_layout ||= LayoutOptions.new(nil, :defaults_view => self)
255
+ end
265
256
 
266
- def spacing=(spacing)
267
- if spacing != @spacing
268
- @spacing = spacing.to_i
269
- relayout!
257
+ def spacing
258
+ @spacing
270
259
  end
271
- end
272
-
273
- def frame=(frame)
274
- setFrame(frame)
275
- end
276
-
277
- def size=(size)
278
- setFrameSize(size)
279
- end
280
-
281
- def margin
282
- @margin
283
- end
284
260
 
285
- def margin=(margin)
286
- if margin != @margin
287
- @margin = margin.to_i
288
- relayout!
261
+ def spacing= spacing
262
+ if spacing != @spacing
263
+ @spacing = spacing.to_i
264
+ relayout!
265
+ end
289
266
  end
290
- end
291
-
292
- def <<(view)
293
- addSubview(view)
294
- end
295
267
 
296
- def remove(subview, options = {})
297
- raise ArgumentError, "#{subview} is not a subview of #{self} and cannot be removed." unless subview.superview == self
298
- options[:needs_display] == false ? subview.removeFromSuperviewWithoutNeedingDisplay : subview.removeFromSuperview
299
- end
300
-
301
- def addSubview(view)
302
- super
303
- if view.respond_to?(:layout)
304
- relayout!
305
- else
306
- raise ArgumentError, "view #{view} does not support the #layout method"
268
+ def frame= frame
269
+ setFrame(frame)
307
270
  end
308
- end
309
-
310
- def views_updated!
311
- relayout!
312
- end
313
271
 
314
- def remove_view(view)
315
- unless subviews.include?(view)
316
- raise ArgumentError, "view #{view} not a subview of this LayoutView"
272
+ def size= size
273
+ setFrameSize(size)
317
274
  end
318
- view.removeFromSuperview
319
- relayout!
320
- end
321
275
 
322
- def remove_all_views
323
- subviews.each { |view| view.removeFromSuperview }
324
- relayout!
325
- end
276
+ def margin
277
+ @margin
278
+ end
326
279
 
327
- def drawRect(frame)
328
- if @frame_color
329
- @frame_color.set
330
- NSFrameRect(frame)
280
+ def margin= margin
281
+ if margin != @margin
282
+ @margin = margin.to_i
283
+ relayout!
284
+ end
331
285
  end
332
- end
333
286
 
334
- def setFrame(frame)
335
- super
336
- relayout!
337
- end
287
+ def << view
288
+ addSubview(view)
289
+ end
338
290
 
339
- def setFrameSize(size)
340
- super
341
- relayout!
342
- end
291
+ def remove subview, options = {}
292
+ raise ArgumentError, "#{subview} is not a subview of #{self} and cannot be removed." unless subview.superview == self
293
+ options[:needs_display] == false ? subview.removeFromSuperviewWithoutNeedingDisplay : subview.removeFromSuperview
294
+ end
343
295
 
344
- private
345
-
346
- def relayout!
347
- vertical = @mode == :vertical
348
- view_size = frameSize
349
- dimension = @margin
350
- end_dimension = vertical ? view_size.height : view_size.width
351
- end_dimension -= (@margin * 2)
352
-
353
- expandable_size = end_dimension
354
- expandable_views = 0
355
- subviews.each do |view|
356
- next if !view.respond_to?(:layout) || view.layout.nil?
357
- if (vertical ? view.layout.expand_height? : view.layout.expand_width?)
358
- expandable_views += 1
296
+ def addSubview(view)
297
+ super
298
+ if view.respond_to?(:layout)
299
+ relayout!
359
300
  else
360
- expandable_size -= vertical ? view.frameSize.height : view.frameSize.width
361
- expandable_size -= @spacing
301
+ raise ArgumentError, "view #{view} does not support the #layout method"
362
302
  end
363
- expandable_size -=
364
- vertical ? view.layout.top_padding + view.layout.bottom_padding
365
- : view.layout.left_padding + view.layout.right_padding
366
303
  end
367
- expandable_size /= expandable_views
368
304
 
369
- subviews.each do |view|
370
- next if !view.respond_to?(:layout) || view.layout.nil?
371
- options = view.layout
372
- subview_size = view.frameSize
373
- view_frame = NSMakeRect(0, 0, *subview_size)
374
- subview_dimension = vertical ? subview_size.height : subview_size.width
305
+ def views_updated!
306
+ relayout!
307
+ end
375
308
 
376
- if vertical
377
- view_frame.origin.x = @margin
378
- if options.start?
379
- view_frame.origin.y = dimension
380
- else
381
- view_frame.origin.y = end_dimension - subview_dimension
382
- end
383
- else
384
- if options.start?
385
- view_frame.origin.x = dimension
386
- else
387
- view_frame.origin.x = end_dimension - subview_dimension
388
- end
389
- view_frame.origin.y = @margin
309
+ def remove_view view
310
+ unless subviews.include?(view)
311
+ raise ArgumentError, "view #{view} not a subview of this LayoutView"
390
312
  end
313
+ view.removeFromSuperview
314
+ relayout!
315
+ end
391
316
 
392
- if (vertical ? options.expand_height? : options.expand_width?)
393
- if vertical
394
- view_frame.size.height = expandable_size
317
+ def remove_all_views
318
+ subviews.each { |view| view.removeFromSuperview }
319
+ relayout!
320
+ end
321
+
322
+ def drawRect frame
323
+ if frame_color
324
+ frame_color.set
325
+ NSFrameRect(frame)
326
+ end
327
+ end
328
+
329
+ def setFrame frame
330
+ super(frame, &nil)
331
+ relayout!
332
+ end
333
+
334
+ def setFrameSize size
335
+ super(size, &nil)
336
+ relayout!
337
+ end
338
+
339
+ private
340
+
341
+ def calc_expandable_size end_dimension
342
+ expandable_size = end_dimension
343
+ expandable_views = 0
344
+
345
+ subviews.each do |view|
346
+ next unless can_layout?(view)
347
+
348
+ if vertical?
349
+ size = view.frameSize.height
350
+ expand = view.layout.expand_height?
351
+ padding = view.layout.top_padding + view.layout.bottom_padding
395
352
  else
396
- view_frame.size.width = expandable_size
353
+ size = view.frameSize.width
354
+ expand = view.layout.expand_width?
355
+ padding = view.layout.left_padding + view.layout.right_padding
397
356
  end
398
- subview_dimension = expandable_size
357
+
358
+ if expand
359
+ expandable_views += 1
360
+ else
361
+ expandable_size -= size
362
+ expandable_size -= @spacing
363
+ end
364
+
365
+ expandable_size -= padding
399
366
  end
400
-
401
- if (vertical ? options.expand_width? : options.expand_height?)
402
- if vertical
403
- view_frame.size.width = view_size.width - (2 * @margin) - options.right_padding - options.left_padding
367
+
368
+ expandable_size /= expandable_views
369
+ expandable_size
370
+ end
371
+
372
+ def relayout!
373
+ view_size = frameSize
374
+ end_dimension = vertical? ? view_size.height : view_size.width
375
+ end_dimension -= (@margin * 2)
376
+ dimension = @margin
377
+
378
+ expandable_size = calc_expandable_size(end_dimension)
379
+
380
+ subviews.each do |view|
381
+ next unless can_layout?(view)
382
+
383
+ options = view.layout
384
+ subview_size = view.frameSize
385
+ view_frame = NSMakeRect(0, 0, *subview_size)
386
+ subview_dimension = vertical? ? subview_size.height : subview_size.width
387
+
388
+ if vertical?
389
+ primary_dimension = 'height'
390
+ secondary_dimension = 'width'
391
+ primary_axis = 'x'
392
+ secondary_axis = 'y'
393
+ expand_primary = 'expand_height?'
394
+ expand_secondary = 'expand_width?'
395
+ padding_first = 'left_padding'
396
+ padding_second = 'right_padding'
397
+ padding_third = 'bottom_padding'
398
+ padding_fourth = 'top_padding'
404
399
  else
405
- view_frame.size.height = view_size.height - (2 * @margin) - options.top_padding - options.bottom_padding
400
+ primary_dimension = 'width'
401
+ secondary_dimension = 'height'
402
+ primary_axis = 'y'
403
+ secondary_axis = 'x'
404
+ expand_primary = 'expand_width?'
405
+ expand_secondary = 'expand_height?'
406
+ padding_first = 'top_padding'
407
+ padding_second = 'bottom_padding'
408
+ padding_third = 'left_padding'
409
+ padding_fourth = 'right_padding'
406
410
  end
407
- else
408
- case options.align
409
- when :left, :bottom
410
- # Nothing to do
411
-
412
- when :center
413
- if vertical
414
- view_frame.origin.x = (view_size.width / 2.0) - (subview_size.width / 2.0)
415
- else
416
- view_frame.origin.y = (view_size.height / 2.0) - (subview_size.height / 2.0)
417
- end
418
411
 
419
- when :right, :top
420
- if vertical
421
- view_frame.origin.x = view_size.width - subview_size.width - @margin
422
- else
423
- view_frame.origin.y = view_size.height - subview_size.height - @margin
412
+ view_frame.origin.send("#{primary_axis}=", @margin)
413
+ view_frame.origin.send("#{secondary_axis}=", (options.start? ? dimension : (end_dimension - subview_dimension)))
414
+
415
+ if options.send(expand_primary)
416
+ view_frame.size.send("#{primary_dimension}=", expandable_size)
417
+ subview_dimension = expandable_size
418
+ end
419
+
420
+ if options.send(expand_secondary)
421
+ view_frame.size.send("#{secondary_dimension}=",
422
+ view_size.send("#{secondary_dimension}") - (2 * @margin) -
423
+ options.send(padding_first) - options.send(padding_second))
424
+ else
425
+
426
+ case options.align
427
+ when :left, :bottom
428
+ # Nothing to do
429
+
430
+ when :center
431
+ view_frame.origin.send("#{primary_axis}=", (view_size.send(secondary_dimension) / 2.0) - (subview_size.send(secondary_dimension) / 2.0))
432
+
433
+ when :right, :top
434
+ view_frame.origin.send("#{primary_axis}=", view_size.send(secondary_dimension) -
435
+ subview_size.send(secondary_dimension) - @margin)
424
436
  end
425
437
  end
426
- end
427
438
 
428
- puts "view #{view} options #{options} final frame #{view_frame}" if $DEBUG
439
+ if $DEBUG
440
+ puts "view #{view} options #{options.inspect} " +
441
+ "final frame [#{view_frame.origin.x}, #{view_frame.origin.y}, "+
442
+ "#{view_frame.size.width}x#{view_frame.size.height}]"
443
+ end
429
444
 
430
- view_frame.origin.x += options.left_padding
431
- view_frame.origin.y += options.bottom_padding
445
+ view_frame.origin.x += options.left_padding
446
+ view_frame.origin.y += options.bottom_padding
432
447
 
433
- if options.start?
434
- dimension += subview_dimension + @spacing
435
- if vertical
436
- dimension += options.bottom_padding + options.top_padding
448
+ if options.start?
449
+ dimension += subview_dimension + @spacing
450
+ dimension += options.send(padding_third) + options.send(padding_fourth)
437
451
  else
438
- dimension += options.left_padding + options.right_padding
452
+ end_dimension -= subview_dimension + @spacing
439
453
  end
440
- else
441
- end_dimension -= subview_dimension + @spacing
454
+
455
+ view.frame = view_frame
442
456
  end
457
+ end
443
458
 
444
- view.frame = view_frame
445
- end
459
+ def can_layout? view
460
+ view.respond_to?(:layout) && !view.layout.nil?
461
+ end
446
462
  end
447
463
  end
448
- end