lib/geomotion/cg_rect.rb in geomotion-0.13.1 vs lib/geomotion/cg_rect.rb in geomotion-0.13.2

- old
+ new

@@ -1,78 +1,81 @@ class CGRect - # CGRect.make # default rect: {origin: {x: 0, y: 0}, size: {width:0, height:0}} - # # aka CGRectZero - # CGRect.make(x: 10, y: 30) # default size: [0, 0] - # CGRect.make(x: 10, y: 30, width:100, height: 20) - # - # point = CGPoint.make(x: 10, y: 30) - # size = CGSize.make(width: 100, height: 20) - # CGRect.make(origin: point, size: size) - def self.make(options = {}) - if options[:origin] - x = options[:origin][0] - y = options[:origin][1] - else - x = options[:x] || 0 - y = options[:y] || 0 + class << self + # CGRect.make # default rect: {origin: {x: 0, y: 0}, size: {width:0, height:0}} + # # aka CGRectZero + # CGRect.make(x: 10, y: 30) # default size: [0, 0] + # CGRect.make(x: 10, y: 30, width:100, height: 20) + # + # point = CGPoint.make(x: 10, y: 30) + # size = CGSize.make(width: 100, height: 20) + # CGRect.make(origin: point, size: size) + def make(options = {}) + if options[:origin] + x = options[:origin][0] + y = options[:origin][1] + else + x = options[:x] || 0 + y = options[:y] || 0 + end + if options[:size] + w = options[:size][0] + h = options[:size][1] + else + w = options[:width] || 0 + h = options[:height] || 0 + end + self.new([x, y], [w, h]) end - if options[:size] - w = options[:size][0] - h = options[:size][1] - else - w = options[:width] || 0 - h = options[:height] || 0 + + def zero + CGRect.new([0, 0], [0, 0]) end - self.new([x, y], [w, h]) - end + alias empty zero - def self.empty - # Don't just return CGRectZero; can be mutated - CGRectZero.dup - end + def null + # Don't just return CGRectNull; can be mutated + CGRect.new([Float::INFINITY, Float::INFINITY], [0, 0]) + end - def self.null - # Don't just return CGRectNull; can be mutated - CGRectNull.dup - end + def infinite + # This actually returns the not-very-infinite value of: + # [[-1.7014114289565e+38, -1.7014114289565e+38], [3.402822857913e+38, 3.402822857913e+38]] + # originally this method returned [[-Infinity, -Infinity], [Infinity, Infinity]], + # but that rect ended up returning `false` for any point in the method + # CGRect.infinite.contains?(point). CGRectInfinite returns `true` for any + # (sensible) point, so we'll go with that instead + CGRectInfinite.dup + end - def self.infinite - # This actually returns the not-very-infinite value of: - # [[-1.7014114289565e+38, -1.7014114289565e+38], [3.402822857913e+38, 3.402822857913e+38]] - # originally this method returned [[-Infinity, -Infinity], [Infinity, Infinity]], - # but that rect ended up returning `false` for any point in the method - # CGRect.infinite.contains?(point). CGRectInfinite returns `true` for any - # (sensible) point, so we'll go with that instead - CGRectInfinite.dup - end + # OPTIONS: [:above, :below, :left_of, :right_of, :margins] + # :margins is array of [top, right, bottom, left] + # EX CGRect.layout(rect1, above: rect2, left_of: rect3, margins: [0, 10, 20, 0]) + def layout(rect1, options) + if options.empty? + p "No options provided in #{self.class}.layout" + return rect1 + end - # OPTIONS: [:above, :below, :left_of, :right_of, :margins] - # :margins is array of [top, right, bottom, left] - # EX CGRect.layout(rect1, above: rect2, left_of: rect3, margins: [0, 10, 20, 0]) - def self.layout(rect1, options) - if options.empty? - p "No options provided in #{self.class}.layout" - return rect1 - end + rect = self.new + rect.size = rect1.size - rect = self.new - rect.size = rect1.size + options[:margins] ||= [] + margins = {} + [:top, :right, :bottom, :left].each_with_index do |margin, index| + margins[margin] = options[:margins][index] || 0 + end - options[:margins] ||= [] - margins = {} - [:top, :right, :bottom, :left].each_with_index do |margin, index| - margins[margin] = options[:margins][index] || 0 - end + rect.y = options[:above].up(rect.height + margins[:bottom]).y if options[:above] + rect.y = options[:below].below(margins[:top]).y if options[:below] - rect.y = options[:above].up(rect.height + margins[:bottom]).y if options[:above] - rect.y = options[:below].below(margins[:top]).y if options[:below] + rect.x = options[:left_of].left(rect.width + margins[:right]).x if options[:left_of] + rect.x = options[:right_of].beside(margins[:left]).x if options[:right_of] - rect.x = options[:left_of].left(rect.width + margins[:right]).x if options[:left_of] - rect.x = options[:right_of].beside(margins[:left]).x if options[:right_of] + rect + end - rect end # bounds def min_x CGRectGetMinX(self) @@ -97,48 +100,64 @@ def max_y CGRectGetMaxY(self) end # getters/setters - def x(setter = nil) + def x(setter=nil, options=nil) if setter - return CGRect.new([setter, self.origin.y], self.size) + rect = CGRect.new([setter, self.origin.y], self.size) + if options + return rect.apply(options) + end + return rect end - min_x + return min_x end def x=(_x) self.origin.x = _x end - def y(setter = nil) + def y(setter=nil, options=nil) if setter - return CGRect.new([self.origin.x, setter], self.size) + rect = CGRect.new([self.origin.x, setter], self.size) + if options + return rect.apply(options) + end + return rect end - min_y + return min_y end def y=(_y) self.origin.y = _y end - def width(setter = nil) + def width(setter=nil, options=nil) if setter - return CGRect.new(self.origin, [setter, self.size.height]) + rect = CGRect.new(self.origin, [setter, self.size.height]) + if options + return rect.apply(options) + end + return rect end - CGRectGetWidth(self) + return CGRectGetWidth(self) end def width=(_width) self.size.width = _width end - def height(setter = nil) + def height(setter=nil, options=nil) if setter - return CGRect.new(self.origin, [self.size.width, setter]) + rect = CGRect.new(self.origin, [self.size.width, setter]) + if options + return rect.apply(options) + end + return rect end - CGRectGetHeight(self) + return CGRectGetHeight(self) end def height=(_height) self.size.height = _height end @@ -215,106 +234,180 @@ NSLog("Using the default value of `0` in `CGRect#left` is deprecated.") dist = 0 end raise "You must specify an amount in `CGRect#left`" unless dist.is_a?(Numeric) - options[:left] = dist - self.apply(options) + self.apply({ + left: dist + }.merge(options)) end def right(dist=nil, options={}) if dist.nil? NSLog("Using the default value of `0` in `CGRect#right` is deprecated.") dist = 0 end raise "You must specify an amount in `CGRect#right`" unless dist.is_a?(Numeric) - options[:right] = dist - self.apply(options) + self.apply({ + right: dist + }.merge(options)) end def up(dist=nil, options={}) if dist.nil? NSLog("Using the default value of `0` in `CGRect#up` is deprecated.") dist = 0 end raise "You must specify an amount in `CGRect#up`" unless dist.is_a?(Numeric) - options[:up] = dist - self.apply(options) + self.apply({ + up: dist + }.merge(options)) end def down(dist=nil, options={}) if dist.nil? NSLog("Using the default value of `0` in `CGRect#down` is deprecated.") dist = 0 end raise "You must specify an amount in `CGRect#down`" unless dist.is_a?(Numeric) - options[:down] = dist - self.apply(options) + self.apply({ + down: dist + }.merge(options)) end def wider(dist, options={}) raise "You must specify an amount in `CGRect#wider`" unless dist.is_a?(Numeric) - options[:wider] = dist - self.apply(options) + self.apply({ + wider: dist + }.merge(options)) end def thinner(dist, options={}) raise "You must specify an amount in `CGRect#thinner`" unless dist.is_a?(Numeric) - options[:thinner] = dist - self.apply(options) + self.apply({ + thinner: dist + }.merge(options)) end def taller(dist, options={}) raise "You must specify an amount in `CGRect#taller`" unless dist.is_a?(Numeric) - options[:taller] = dist - self.apply(options) + self.apply({ + taller: dist + }.merge(options)) end def shorter(dist, options={}) raise "You must specify an amount in `CGRect#shorter`" unless dist.is_a?(Numeric) - options[:shorter] = dist - self.apply(options) + self.apply({ + shorter: dist + }.merge(options)) end # adjacent rects def above(margin = 0, options={}) margin, options = 0, margin if margin.is_a?(NSDictionary) height = options[:height] || self.size.height - options[:up] = height + margin - self.apply(options) + self.apply({ + up: height + margin + }.merge(options)) end def below(margin = 0, options={}) margin, options = 0, margin if margin.is_a?(NSDictionary) - options[:down] = self.size.height + margin - self.apply(options) + self.apply({ + down: self.size.height + margin + }.merge(options)) end def before(margin = 0, options={}) margin, options = 0, margin if margin.is_a?(NSDictionary) width = options[:width] || self.size.width - options[:left] = width + margin - self.apply(options) + self.apply({ + left: width + margin + }.merge(options)) end def beside(margin = 0, options={}) margin, options = 0, margin if margin.is_a?(NSDictionary) - options[:right] = self.size.width + margin - self.apply(options) + self.apply({ + right: self.size.width + margin + }.merge(options)) end + # these methods create a rect INSIDE the receiver + + # Create a rect inside the receiver, on the left side. If `margin` is + # supplied, the rect will be moved that number of points to the right. + def from_left(options={}) + width = options[:width] + margin = options.delete(:margin) || 0 + raise "You must specify a width in `CGRect#from_left`" unless width + offset = cgrect_offset(options.delete(:absolute)) + self.apply({ + x: offset.x + margin, + y: offset.y, + height: self.size.height, + width: width + }.merge(options)) + end + + # Create a rect inside the receiver, on the right side. If `margin` is + # supplied, the rect will be moved that number of points to the left. + def from_right(options={}) + width = options[:width] + margin = options.delete(:margin) || 0 + raise "You must specify a width in `CGRect#from_right`" unless width + offset = cgrect_offset(options.delete(:absolute)) + self.apply({ + x: offset.x + self.size.width - width - margin, + y: offset.y, + height: self.size.height, + width: width + }.merge(options)) + end + + # Create a rect inside the receiver, on the top side. If `margin` is + # supplied, the rect will be moved that number of points down. + def from_top(options={}) + height = options[:height] + margin = options.delete(:margin) || 0 + raise "You must specify a height in `CGRect#from_top`" unless height + offset = cgrect_offset(options.delete(:absolute)) + self.apply({ + x: offset.x, + y: offset.y + margin, + width: self.size.width, + height: height + }.merge(options)) + end + + # Create a rect inside the receiver, on the bottom side. If `margin` is + # supplied, the rect will be moved that number of points up. + def from_bottom(options={}) + height = options[:height] + margin = options.delete(:margin) || 0 + raise "You must specify a height in `CGRect#from_bottom`" unless height + offset = cgrect_offset(options.delete(:absolute)) + self.apply({ + x: offset.x, + y: offset.y + self.size.height - height - margin, + width: self.size.width, + height: height + }.merge(options)) + end + # positions private def cgrect_offset(absolute) if absolute CGPoint.new(self.min_x, self.min_y) @@ -434,30 +527,32 @@ end return rect end alias grow_right wider - def grow_left(amount, options=nil) + def grow_left(amount, options={}) raise "You must specify an amount in `CGRect#grow_left`" unless amount.is_a?(Numeric) - options[:grow_left] = amount - self.apply(options) + self.apply({ + grow_left: amount + }.merge(options)) end alias grow_down taller - def grow_up(amount, options=nil) + def grow_up(amount, options={}) raise "You must specify an amount in `CGRect#grow_up`" unless amount.is_a?(Numeric) - options[:grow_up] = amount - self.apply(options) + self.apply({ + grow_up: amount + }.merge(options)) end - def grow_width(amount, options=nil) + def grow_width(amount, options={}) return self.grow([amount, 0], options) end - def grow_height(amount, options=nil) + def grow_height(amount, options={}) return self.grow([0, amount], options) end def shrink(size, options=nil) if size.is_a? Numeric @@ -472,19 +567,21 @@ alias shrink_left thinner def shrink_right(amount, options={}) raise "You must specify an amount in `CGRect#shrink_right`" unless amount.is_a?(Numeric) - options[:shrink_right] = amount - self.apply(options) + self.apply({ + shrink_right: amount + }.merge(options)) end alias shrink_up shorter def shrink_down(amount, options={}) raise "You must specify an amount in `CGRect#shrink_down`" unless amount.is_a?(Numeric) - options[:shrink_down] = amount - self.apply(options) + self.apply({ + shrink_down: amount + }.merge(options)) end def shrink_width(amount, options={}) return self.shrink([amount, 0], options) end