hotcocoa 0.5

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.
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