hotcocoa 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/History.txt +4 -0
  2. data/bin/hotcocoa +31 -0
  3. data/lib/hotcocoa/application_builder.rb +320 -0
  4. data/lib/hotcocoa/attributed_string.rb +143 -0
  5. data/lib/hotcocoa/behaviors.rb +7 -0
  6. data/lib/hotcocoa/data_sources/combo_box_data_source.rb +44 -0
  7. data/lib/hotcocoa/data_sources/table_data_source.rb +18 -0
  8. data/lib/hotcocoa/delegate_builder.rb +85 -0
  9. data/lib/hotcocoa/graphics/canvas.rb +836 -0
  10. data/lib/hotcocoa/graphics/color.rb +781 -0
  11. data/lib/hotcocoa/graphics/elements/particle.rb +75 -0
  12. data/lib/hotcocoa/graphics/elements/rope.rb +99 -0
  13. data/lib/hotcocoa/graphics/elements/sandpainter.rb +71 -0
  14. data/lib/hotcocoa/graphics/gradient.rb +63 -0
  15. data/lib/hotcocoa/graphics/image.rb +488 -0
  16. data/lib/hotcocoa/graphics/path.rb +325 -0
  17. data/lib/hotcocoa/graphics/pdf.rb +71 -0
  18. data/lib/hotcocoa/graphics.rb +161 -0
  19. data/lib/hotcocoa/kernel_ext.rb +14 -0
  20. data/lib/hotcocoa/kvo_accessors.rb +48 -0
  21. data/lib/hotcocoa/layout_view.rb +448 -0
  22. data/lib/hotcocoa/mapper.rb +227 -0
  23. data/lib/hotcocoa/mapping_methods.rb +40 -0
  24. data/lib/hotcocoa/mappings/alert.rb +25 -0
  25. data/lib/hotcocoa/mappings/application.rb +112 -0
  26. data/lib/hotcocoa/mappings/array_controller.rb +87 -0
  27. data/lib/hotcocoa/mappings/box.rb +39 -0
  28. data/lib/hotcocoa/mappings/button.rb +92 -0
  29. data/lib/hotcocoa/mappings/collection_view.rb +44 -0
  30. data/lib/hotcocoa/mappings/color.rb +28 -0
  31. data/lib/hotcocoa/mappings/column.rb +21 -0
  32. data/lib/hotcocoa/mappings/combo_box.rb +24 -0
  33. data/lib/hotcocoa/mappings/control.rb +33 -0
  34. data/lib/hotcocoa/mappings/font.rb +44 -0
  35. data/lib/hotcocoa/mappings/gradient.rb +15 -0
  36. data/lib/hotcocoa/mappings/image.rb +15 -0
  37. data/lib/hotcocoa/mappings/image_view.rb +43 -0
  38. data/lib/hotcocoa/mappings/label.rb +25 -0
  39. data/lib/hotcocoa/mappings/layout_view.rb +9 -0
  40. data/lib/hotcocoa/mappings/menu.rb +71 -0
  41. data/lib/hotcocoa/mappings/menu_item.rb +47 -0
  42. data/lib/hotcocoa/mappings/movie.rb +13 -0
  43. data/lib/hotcocoa/mappings/movie_view.rb +27 -0
  44. data/lib/hotcocoa/mappings/notification.rb +17 -0
  45. data/lib/hotcocoa/mappings/popup.rb +110 -0
  46. data/lib/hotcocoa/mappings/progress_indicator.rb +68 -0
  47. data/lib/hotcocoa/mappings/scroll_view.rb +29 -0
  48. data/lib/hotcocoa/mappings/search_field.rb +9 -0
  49. data/lib/hotcocoa/mappings/secure_text_field.rb +17 -0
  50. data/lib/hotcocoa/mappings/segmented_control.rb +97 -0
  51. data/lib/hotcocoa/mappings/slider.rb +25 -0
  52. data/lib/hotcocoa/mappings/sort_descriptor.rb +13 -0
  53. data/lib/hotcocoa/mappings/sound.rb +9 -0
  54. data/lib/hotcocoa/mappings/speech_synthesizer.rb +25 -0
  55. data/lib/hotcocoa/mappings/split_view.rb +21 -0
  56. data/lib/hotcocoa/mappings/status_bar.rb +7 -0
  57. data/lib/hotcocoa/mappings/status_item.rb +9 -0
  58. data/lib/hotcocoa/mappings/table_view.rb +110 -0
  59. data/lib/hotcocoa/mappings/text_field.rb +41 -0
  60. data/lib/hotcocoa/mappings/text_view.rb +13 -0
  61. data/lib/hotcocoa/mappings/timer.rb +25 -0
  62. data/lib/hotcocoa/mappings/toolbar.rb +97 -0
  63. data/lib/hotcocoa/mappings/toolbar_item.rb +36 -0
  64. data/lib/hotcocoa/mappings/view.rb +67 -0
  65. data/lib/hotcocoa/mappings/web_view.rb +22 -0
  66. data/lib/hotcocoa/mappings/window.rb +118 -0
  67. data/lib/hotcocoa/mappings/xml_parser.rb +41 -0
  68. data/lib/hotcocoa/mappings.rb +109 -0
  69. data/lib/hotcocoa/mvc.rb +175 -0
  70. data/lib/hotcocoa/notification_listener.rb +62 -0
  71. data/lib/hotcocoa/object_ext.rb +22 -0
  72. data/lib/hotcocoa/plist.rb +45 -0
  73. data/lib/hotcocoa/standard_rake_tasks.rb +17 -0
  74. data/lib/hotcocoa/template.rb +27 -0
  75. data/lib/hotcocoa/virtual_file_system.rb +172 -0
  76. data/lib/hotcocoa.rb +26 -0
  77. data/template/Rakefile +5 -0
  78. data/template/config/build.yml +8 -0
  79. data/template/lib/application.rb +45 -0
  80. data/template/lib/menu.rb +32 -0
  81. data/template/resources/HotCocoa.icns +0 -0
  82. data/test/test_helper.rb +3 -0
  83. data/test/test_hotcocoa.rb +11 -0
  84. metadata +137 -0
@@ -0,0 +1,325 @@
1
+ # Ruby Cocoa Graphics is a graphics library providing a simple object-oriented
2
+ # interface into the power of Mac OS X's Core Graphics and Core Image drawing libraries.
3
+ # With a few lines of easy-to-read code, you can write scripts to draw simple or complex
4
+ # shapes, lines, and patterns, process and filter images, create abstract art or visualize
5
+ # scientific data, and much more.
6
+ #
7
+ # Inspiration for this project was derived from Processing and NodeBox. These excellent
8
+ # graphics programming environments are more full-featured than RCG, but they are implemented
9
+ # in Java and Python, respectively. RCG was created to offer similar functionality using
10
+ # the Ruby programming language.
11
+ #
12
+ # Author:: James Reynolds (mailto:drtoast@drtoast.com)
13
+ # Copyright:: Copyright (c) 2008 James Reynolds
14
+ # License:: Distributes under the same terms as Ruby
15
+
16
+ module HotCocoa::Graphics
17
+
18
+ # Make a reusable path. Draw it using canvas.draw(path)
19
+ class Path
20
+
21
+ attr_accessor :path, :rand, :inc, :fill, :stroke, :scale, :strokewidth, :x, :y, :image
22
+
23
+ # create a new path, starting at optional x,y
24
+ def initialize(x=0, y=0, &block)
25
+ @path = CGPathCreateMutable()
26
+ @transform = CGAffineTransformMakeTranslation(0,0)
27
+ moveto(x, y)
28
+
29
+ # set randomized rendering parameters
30
+ @rand = {}
31
+ randomize(:x, 0.0)
32
+ randomize(:y, 0.0)
33
+ randomize(:scale, 1.0)
34
+ randomize(:scalex, 1.0)
35
+ randomize(:scaley, 1.0)
36
+ randomize(:rotation, 0.0)
37
+ randomize(:strokewidth, 1.0)
38
+
39
+ # set incremental rendering parameters
40
+ @inc = {}
41
+ increment(:rotation, 0.0)
42
+ increment(:x, 0.0)
43
+ increment(:y, 0.0)
44
+ increment(:scale, 1.0)
45
+ increment(:scalex, 1.0)
46
+ increment(:scaley, 1.0)
47
+
48
+ @strokewidth = 1.0
49
+ @x = 0.0
50
+ @y = 0.0
51
+
52
+ if block
53
+ case block.arity
54
+ when 0
55
+ self.send(:instance_eval, &block)
56
+ else
57
+ block.call(self)
58
+ end
59
+ end
60
+ self
61
+ end
62
+
63
+ def fill(colors=nil)
64
+ if colors
65
+ rand[:fill] = colors
66
+ else
67
+ @fill
68
+ end
69
+ end
70
+
71
+ # randomize the specified parameter within the specified range
72
+ def randomize(parameter, value)
73
+ rand[parameter] = value
74
+ end
75
+
76
+ # increment the specified parameter within the specified range
77
+ def increment(parameter, value)
78
+ inc[parameter] = value
79
+ end
80
+
81
+ # return a mutable clone of this path
82
+ def clone
83
+ newpath = self.dup
84
+ newpath.path = CGPathCreateMutableCopy(@path)
85
+ newpath
86
+ end
87
+
88
+
89
+ # SET PARAMETERS
90
+
91
+ # set registration mode to :center or :corner
92
+ def registration(mode=:center)
93
+ @registration = mode
94
+ end
95
+
96
+ # print drawing operations if verbose is true
97
+ def verbose(tf=true)
98
+ @verbose = tf
99
+ end
100
+
101
+ # draw without stroke
102
+ def nostroke
103
+ @stroke = nil
104
+ end
105
+
106
+ # GET PATH INFO
107
+
108
+ # print origin and dimensions
109
+ def to_s
110
+ "path.to_s: bounding box at [#{originx},#{originy}] with #{width}x#{height}, current point [#{currentpoint[0]},#{currentpoint[1]}]"
111
+ end
112
+
113
+ # return the x coordinate of the path's origin
114
+ def originx
115
+ CGPathGetBoundingBox(@path).origin.x
116
+ end
117
+
118
+ # return the y coordinate of the path's origin
119
+ def originy
120
+ CGPathGetBoundingBox(@path).origin.y
121
+ end
122
+
123
+ # return the width of the path's bounding box
124
+ def width
125
+ CGPathGetBoundingBox(@path).size.width
126
+ end
127
+
128
+ # return the height of the path's bounding box
129
+ def height
130
+ CGPathGetBoundingBox(@path).size.height
131
+ end
132
+
133
+ # return the current point
134
+ def currentpoint
135
+ CGPathGetCurrentPoint(@path)
136
+ end
137
+
138
+ # true if the path contains the current point # doesn't work?
139
+ def contains(x,y)
140
+ eorule = true
141
+ CGPathContainsPoint(@path, @transform, CGPointMake(x, y), eorule)
142
+ end
143
+
144
+
145
+ # ADD SHAPES TO PATH
146
+
147
+ # add another path to this path
148
+ def addpath(p)
149
+ CGPathAddPath(@path, @transform, p.path)
150
+ end
151
+
152
+ # add a rectangle starting at [x,y] with dimensions w x h
153
+ def rect(x=0, y=0, w=20, h=20, reg=@registration)
154
+ if reg == :center
155
+ x = x - w / 2
156
+ y = y - h / 2
157
+ end
158
+ puts "path.rect at [#{x},#{y}] with #{w}x#{h}" if @verbose
159
+ CGPathAddRect(@path, @transform, CGRectMake(x,y,w,h))
160
+ self
161
+ end
162
+
163
+ # draw a rounded rectangle using quadratic curved corners (FIXME)
164
+ def roundrect(x=0, y=0, width=20, height=20, roundness=0, reg=@registration)
165
+ if roundness == 0
166
+ p.rect(x, y, width, height, reg)
167
+ else
168
+ if reg == :center
169
+ x = x - self.width / 2
170
+ y = y - self.height / 2
171
+ end
172
+ curve = min(width * roundness, height * roundness)
173
+ p = Path.new
174
+ p.moveto(x, y+curve)
175
+ p.curveto(x, y, x, y, x+curve, y)
176
+ p.lineto(x+width-curve, y)
177
+ p.curveto(x+width, y, x+width, y, x+width, y+curve)
178
+ p.lineto(x+width, y+height-curve)
179
+ p.curveto(x+width, y+height, x+width, y+height, x+width-curve, y+height)
180
+ p.lineto(x+curve, y+height)
181
+ p.curveto(x, y+height, x, y+height, x, y+height-curve)
182
+ p.endpath
183
+ end
184
+ addpath(p)
185
+ self
186
+ end
187
+
188
+ # create an oval starting at x,y with dimensions w x h, optionally registered at :center
189
+ def oval(x=0, y=0, w=20, h=20, reg=@registration)
190
+ if (reg == :center)
191
+ x = x - w / 2
192
+ y = y - h / 2
193
+ end
194
+ puts "path.oval at [#{x},#{y}] with #{w}x#{h}" if @verbose
195
+ CGPathAddEllipseInRect(@path, @transform, CGRectMake(x, y, w, h))
196
+ self
197
+ end
198
+
199
+ # draw a circle with center at x,y with width and (optional) height
200
+ # def circle(x,y,w,h=w)
201
+ # oval(x - w/2, y - h/2, w, h)
202
+ # end
203
+
204
+ # ADD LINES TO PATH
205
+
206
+ # draw a line from x1,x2 to x2,y2
207
+ def line(x1, y1, x2, y2)
208
+ CGPathAddLines(@path, @transform, [NSMakePoint(x1, y1), NSMakePoint(x2, y2)])
209
+ self
210
+ end
211
+
212
+ # draw the arc of a circle with center point x,y, radius, start angle (0 deg = 12 o'clock) and end angle
213
+ def arc(x, y, radius, start_angle, end_angle)
214
+ start_angle = radians(90 - start_angle)
215
+ end_angle = radians(90 - end_angle)
216
+ clockwise = 1 # 1 = clockwise, 0 = counterclockwise
217
+ CGPathAddArc(@path, @transform, x, y, radius, start_angle, end_angle, clockwise)
218
+ self
219
+ end
220
+
221
+ # draw lines connecting the array of points
222
+ def lines(points)
223
+ CGPathAddLines(@path, @transform, points)
224
+ self
225
+ end
226
+
227
+
228
+ # CONSTRUCT PATHS IN PATH OBJECT
229
+
230
+ # move the "pen" to x,y
231
+ def moveto(x, y)
232
+ CGPathMoveToPoint(@path, @transform,x,y)
233
+ self
234
+ end
235
+
236
+ # draw a line from the current point to x,y
237
+ def lineto(x,y)
238
+ CGPathAddLineToPoint(@path, @transform, x, y)
239
+ self
240
+ end
241
+
242
+ # draw a bezier curve from the current point, given the coordinates of two handle control points and an end point
243
+ def curveto(cp1x, cp1y, cp2x, cp2y, x, y)
244
+ CGPathAddCurveToPoint(@path, @transform, cp1x, cp1y, cp2x, cp2y, x, y)
245
+ self
246
+ end
247
+
248
+ # draw a quadratic curve given a single control point and an end point
249
+ def qcurveto(cpx, cpy, x, y)
250
+ CGPathAddQuadCurveToPoint(@path, @transform, cpx, cpy, x, y)
251
+ self
252
+ end
253
+
254
+ # draw an arc given the endpoints of two tangent lines and a radius
255
+ def arcto(x1, y1, x2, y2, radius)
256
+ CGPathAddArcToPoint(@path, @transform, x1, y1, x2, y2, radius)
257
+ self
258
+ end
259
+
260
+ # end the current path
261
+ def endpath
262
+ CGPathCloseSubpath(@path)
263
+ end
264
+
265
+
266
+ # TRANSFORMATIONS
267
+
268
+ # specify rotation for subsequent operations
269
+ def rotate(deg)
270
+ puts "path.rotate #{deg}" if @verbose
271
+ @transform = CGAffineTransformRotate(@transform, radians(deg))
272
+ end
273
+
274
+ # scale by horizontal/vertical scaling factors sx,sy for subsequent drawing operations
275
+ def scale(sx=nil, sy=nil)
276
+ if sx == nil && sy == nil
277
+ @scale
278
+ else
279
+ sy = sx unless sy
280
+ puts "path.scale #{sx}x#{sy}" if @verbose
281
+ @transform = CGAffineTransformScale(@transform, sx, sy)
282
+ end
283
+ end
284
+
285
+ # specify translation by x,y for subsequent drawing operations
286
+ def translate(x,y)
287
+ puts "path.translate #{x}x#{y}" if @verbose
288
+ @transform = CGAffineTransformTranslate(@transform, x, y)
289
+ end
290
+
291
+
292
+ # BUILD PRIMITIVES
293
+
294
+ # draw a petal starting at x,y with w x h and center bulge height using quadratic curves
295
+ def petal(x=0, y=0, w=10, h=50, bulge=h/2)
296
+ moveto(x,y)
297
+ qcurveto(x - w, y + bulge, x, y + h)
298
+ qcurveto(x + w, y + bulge, x, y)
299
+ endpath
300
+ self
301
+ end
302
+
303
+ # duplicate and rotate the Path object the specified number of times
304
+ def kaleidoscope(path,qty)
305
+ deg = 360 / qty
306
+ qty.times do
307
+ addpath(path)
308
+ rotate(deg)
309
+ end
310
+ end
311
+
312
+ # duplicate and rotate the Path object the specified number of times
313
+ #path, rotation, scale, translation, iterations
314
+ def spiral(path=nil, rotation=20, scalex=0.95, scaley=0.95, tx=10, ty=10, iterations=30)
315
+ iterations.times do
316
+ addpath(path)
317
+ rotate(rotation)
318
+ scale(scalex, scaley)
319
+ translate(tx, ty)
320
+ end
321
+ end
322
+
323
+
324
+ end
325
+ end
@@ -0,0 +1,71 @@
1
+ # Ruby Cocoa Graphics is a graphics library providing a simple object-oriented
2
+ # interface into the power of Mac OS X's Core Graphics and Core Image drawing libraries.
3
+ # With a few lines of easy-to-read code, you can write scripts to draw simple or complex
4
+ # shapes, lines, and patterns, process and filter images, create abstract art or visualize
5
+ # scientific data, and much more.
6
+ #
7
+ # Inspiration for this project was derived from Processing and NodeBox. These excellent
8
+ # graphics programming environments are more full-featured than RCG, but they are implemented
9
+ # in Java and Python, respectively. RCG was created to offer similar functionality using
10
+ # the Ruby programming language.
11
+ #
12
+ # Author:: James Reynolds (mailto:drtoast@drtoast.com)
13
+ # Copyright:: Copyright (c) 2008 James Reynolds
14
+ # License:: Distributes under the same terms as Ruby
15
+
16
+ module HotCocoa::Graphics
17
+
18
+ # parse a PDF file to determine pages, width, height
19
+ class Pdf
20
+
21
+ attr_reader :pages, :pdf
22
+
23
+ # create a new Pdf object given the original pathname, and password if needed
24
+ def initialize(original, password = nil)
25
+ # http://developer.apple.com/documentation/GraphicsImaging/Reference/CGPDFDocument/Reference/reference.html
26
+ # http://developer.apple.com/documentation/GraphicsImaging/Reference/CGPDFPage/Reference/reference.html
27
+ @pdf = CGPDFDocumentCreateWithURL(NSURL.fileURLWithPath(original)) # => CGPDFDocumentRef
28
+ result = CGPDFDocumentUnlockWithPassword(@pdf, password) if password # unlock if necessary
29
+ @pages = CGPDFDocumentGetNumberOfPages(@pdf) # => 4
30
+ puts "pdf.new #{original} (#{@pages} pages)" if @verbose
31
+ self
32
+ end
33
+
34
+ # print drawing functions to console if verbose is true
35
+ def verbose(tf)
36
+ @verbose = tf
37
+ end
38
+
39
+ # get the width of the specified pagenum
40
+ def width(pagenum=1)
41
+ cgpdfpage = page(pagenum)
42
+ mediabox = CGPDFPageGetBoxRect(cgpdfpage, KCGPDFMediaBox) # => CGRect
43
+ width = mediabox.size.width # CGRectGetWidth(mediabox)
44
+ width
45
+ end
46
+
47
+ # get the height of the specified pagenum
48
+ def height(pagenum=1)
49
+ cgpdfpage = page(pagenum)
50
+ mediabox = CGPDFPageGetBoxRect(cgpdfpage, KCGPDFMediaBox) # => CGRect
51
+ height = mediabox.size.height # CGRectGetHeight(mediabox)
52
+ height
53
+ end
54
+
55
+ # draw pagenum of the pdf document into a rectangle at x,y with dimensions w,h of drawing context ctx
56
+ def draw(ctx, x=0, y=0, w=width(pagenum), h=height(pagenum), pagenum=1)
57
+ rect = CGRectMake(x,y,w,h)
58
+ puts "pdf.draw page #{pagenum} at [#{x},#{y}] with #{w}x#{h}" if @verbose
59
+ CGContextDrawPDFDocument(ctx, rect, @pdf, pagenum)
60
+ true
61
+ end
62
+
63
+ private
64
+
65
+ # return a CGPDFPageRef for this pagenum
66
+ def page(pagenum)
67
+ CGPDFDocumentGetPage(@pdf, pagenum) # => CGPDFPageRef
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,161 @@
1
+ # Ruby Cocoa Graphics is a graphics library providing a simple object-oriented
2
+ # interface into the power of Mac OS X's Core Graphics and Core Image drawing libraries.
3
+ # With a few lines of easy-to-read code, you can write scripts to draw simple or complex
4
+ # shapes, lines, and patterns, process and filter images, create abstract art or visualize
5
+ # scientific data, and much more.
6
+ #
7
+ # Inspiration for this project was derived from Processing and NodeBox. These excellent
8
+ # graphics programming environments are more full-featured than RCG, but they are implemented
9
+ # in Java and Python, respectively. RCG was created to offer similar functionality using
10
+ # the Ruby programming language.
11
+ #
12
+ # Author:: James Reynolds (mailto:drtoast@drtoast.com)
13
+ # Copyright:: Copyright (c) 2008 James Reynolds
14
+ # License:: Distributes under the same terms as Ruby
15
+
16
+ # More information about Quartz 2D is available on the Apple's website:
17
+ # http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_overview/dq_overview.html#//apple_ref/doc/uid/TP30001066-CH202-TPXREF101
18
+
19
+
20
+
21
+ module HotCocoa;end # needed in case this is required without hotcocoa
22
+
23
+ framework 'Cocoa'
24
+
25
+ module HotCocoa::Graphics
26
+
27
+ # UTILITY FUNCTIONS (math/geometry)
28
+ TEST = 'OK'
29
+
30
+ # convert degrees to radians
31
+ def radians(deg)
32
+ deg * (Math::PI / 180.0)
33
+ end
34
+
35
+ # convert radians to degrees
36
+ def degrees(rad)
37
+ rad * (180 / Math::PI)
38
+ end
39
+
40
+ # return the angle of the line joining the two points
41
+ def angle(x0, y0, x1, y1)
42
+ degrees(Math.atan2(y1-y0, x1-x0))
43
+ end
44
+
45
+ # return the distance between two points
46
+ def distance(x0, y0, x1, y1)
47
+ Math.sqrt((x1-x0)**2 + (y1-y0)**2)
48
+ end
49
+
50
+ # return the coordinates of a new point at the given distance and angle from a starting point
51
+ def coordinates(x0, y0, distance, angle)
52
+ x1 = x0 + Math.cos(radians(angle)) * distance
53
+ y1 = y0 + Math.sin(radians(angle)) * distance
54
+ [x1,y1]
55
+ end
56
+
57
+ # return the lesser of a,b
58
+ def min(a, b)
59
+ a < b ? a : b
60
+ end
61
+
62
+ # return the greater of a,b
63
+ def max(a, b)
64
+ a > b ? a : b
65
+ end
66
+
67
+ # restrict the value to stay within the range
68
+ def inrange(value, min, max)
69
+ if value < min
70
+ min
71
+ elsif value > max
72
+ max
73
+ else
74
+ value
75
+ end
76
+ end
77
+
78
+ # return a random number within the range, or a float from 0 to the number
79
+ def random(left=nil, right=nil)
80
+ if right
81
+ rand * (right - left) + left
82
+ elsif left
83
+ rand * left
84
+ else
85
+ rand
86
+ end
87
+ end
88
+
89
+ def reflect(x0, y0, x1, y1, d=1.0, a=180)
90
+ d *= distance(x0, y0, x1, y1)
91
+ a += angle(x0, y0, x1, y1)
92
+ x, y = coordinates(x0, y0, d, a)
93
+ [x,y]
94
+ end
95
+
96
+ def choose(object)
97
+ case object
98
+ when Range
99
+ case object.first
100
+ when Float
101
+ rand * (object.last - object.first) + object.first
102
+ when Integer
103
+ rand(object.last - object.first + 1) + object.first
104
+ end
105
+ when Array
106
+ object.sample
107
+ else
108
+ object
109
+ end
110
+ end
111
+
112
+ # given an object's x,y coordinates and dimensions, return the distance
113
+ # needed to move in order to orient the object at the given location (:center, :bottomleft, etc)
114
+ def reorient(x, y, w, h, location)
115
+ case location
116
+ when :bottomleft
117
+ movex = -x
118
+ movey = -y
119
+ when :centerleft
120
+ movex = -x
121
+ movey = -y - h / 2
122
+ when :topleft
123
+ movex = -x
124
+ movey = -x - h
125
+ when :bottomright
126
+ movex = -x - w
127
+ movey = -y
128
+ when :centerright
129
+ movex = -x - w
130
+ movey = -y - h / 2
131
+ when :topright
132
+ movex = -x - w
133
+ movey = -y - h
134
+ when :bottomcenter
135
+ movex = -x - w / 2
136
+ movey = -y
137
+ when :center
138
+ movex = -x - w / 2
139
+ movey = -y - h / 2
140
+ when :topcenter
141
+ movex = -x - w / 2
142
+ movey = -y - h
143
+ else
144
+ raise "ERROR: image origin locator not recognized: #{location}"
145
+ end
146
+ #newx = oldx + movex
147
+ #newy = oldy + movey
148
+ [movex,movey]
149
+ end
150
+
151
+ end
152
+
153
+ require 'hotcocoa/graphics/canvas'
154
+ require 'hotcocoa/graphics/color'
155
+ require 'hotcocoa/graphics/gradient'
156
+ require 'hotcocoa/graphics/image'
157
+ require 'hotcocoa/graphics/path'
158
+ require 'hotcocoa/graphics/pdf'
159
+ require 'hotcocoa/graphics/elements/particle'
160
+ require 'hotcocoa/graphics/elements/rope'
161
+ require 'hotcocoa/graphics/elements/sandpainter'
@@ -0,0 +1,14 @@
1
+ module Kernel
2
+
3
+ alias_method :default_framework, :framework
4
+
5
+ def framework(name)
6
+ if default_framework(name)
7
+ HotCocoa::Mappings.framework_loaded
8
+ true
9
+ else
10
+ false
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,48 @@
1
+ class Object
2
+
3
+ def self.kvo_array(key, &b)
4
+ key = key.to_s
5
+ capitalized_key = key[0].capitalize + key[1..-1]
6
+ signatures = { :size => { selector: :"countOf#{capitalized_key}", type_signature: "i@:", flip: false },
7
+ :[] => { selector: :"objectIn#{capitalized_key}AtIndex:", type_signature: "@@:i", flip: false },
8
+ :insert => { selector: :"insertObject:in#{capitalized_key}AtIndex:", type_signature: "v@:@i", flip: true },
9
+ :delete_at => { selector: :"removeObjectFrom#{capitalized_key}AtIndex:", type_signature: "v@:i", flip: false }
10
+ }
11
+ define_methods_with_signatures(signatures, &b)
12
+ end
13
+
14
+ def self.kvo_set(key, &b)
15
+ key = key.to_s
16
+ capitalized_key = key[0].capitalize + key[1..-1]
17
+ signatures = { :add => { selector: :"add#{capitalized_key}Object:", type_signature: "v@:@", flip: false },
18
+ :delete => { selector: :"remove#{capitalized_key}Object:", type_signature: "v@:@", flip: false},
19
+ :merge => { selector: :"add#{capitalized_key}:", type_signature: "v@:@", flip: false },
20
+ :subtract => { selector: :"remove#{capitalized_key}:", type_signature: "v@:@", flip: false },
21
+ :set => { selector: :"#{key}", type_signature: "@@:", flip: false }
22
+ }
23
+ define_methods_with_signatures(signatures, &b)
24
+ end
25
+
26
+ private
27
+
28
+ def self.define_methods_with_signatures(signatures, &b)
29
+ c = Module.new
30
+ c.module_eval &b
31
+ c.instance_methods.each do |m|
32
+ signature = signatures[m]
33
+ if signature
34
+ method = c.instance_method(m)
35
+ if signature[:flip]
36
+ method = Proc.new { |a, b| method.bind(self).call(b, a)}
37
+ end
38
+ c.send(:define_method, signature[:selector], method)
39
+ c.send(:remove_method, m)
40
+ c.send(:method_signature, signature[:selector], signature[:type_signature])
41
+ elsif not Module.instance_methods.include?(m)
42
+ raise ArgumentError, "Method `#{m}' isn't a KVO accessor"
43
+ end
44
+ end
45
+ include c
46
+ end
47
+
48
+ end