motion-prime/views/view_styler.rb in motion-prime-0.3.2 vs motion-prime/views/view_styler.rb in motion-prime-0.3.3
- old
+ new
@@ -1,119 +1,58 @@
module MotionPrime
class ViewStyler
+ include FrameCalculatorMixin
+ include HasStyles
+
attr_reader :view, :options
def initialize(view, bounds = CGRectZero, options = {})
@options = Styles.extend_and_normalize_options options
@view = view
- calculate_frame_for(bounds) if @options.delete(:calculate_frame)
+ prepare_frame_for(bounds) if @options.delete(:calculate_frame)
end
def apply
- convert_primitives_to_objects(options)
- setValuesForKeysWithDictionary(options)
+ converted_options = convert_primitives_to_objects(options)
+ setValuesForKeysWithDictionary(converted_options)
end
def convert_primitives_to_objects(options)
- options.each do |k,v|
- options[k] = STRUCTS_MAP[v.class].call(v) if STRUCTS_MAP.has_key?(v.class)
+ options.inject({}) do |result, (k, v)|
+ v = STRUCTS_MAP[v.class].call(v) if STRUCTS_MAP.has_key?(v.class)
+ result[k] = v
+ result
end
end
- def calculate_frame_for(bounds)
- width = options.delete(:width)
- height = options.delete(:height)
- top = options.delete(:top)
- right = options.delete(:right)
- bottom = options.delete(:bottom)
- left = options.delete(:left)
- value_type = options.delete(:value_type).to_s # absolute/relative
+ def prepare_frame_for(bounds)
+ options[:frame] = calculate_frome_for(bounds, options)
- if options[:height_to_fit].present? && height.nil? && (top.nil? || bottom.nil?)
- height = options[:height_to_fit]
- end
-
- if width.nil? && height.nil? && right.nil? && bottom.nil?
- options[:frame] = bounds
- else
- frame = CGRectZero
-
- max_width = bounds.size.width
- max_height = bounds.size.height
- width = 0.0 if width.nil?
- height = 0.0 if height.nil?
-
- # calculate left and right if width is relative, e.g 0.7
- if width && width > 0 && width <= 1 && value_type != 'absolute'
- if right.nil?
- left ||= 0
- right = max_width - max_width * width
- else
- left = max_width - max_width * width
- end
- end
-
- # calculate top and bottom if height is relative, e.g 0.7
- if height && height > 0 && height <= 1 && value_type != 'absolute'
- if bottom.nil?
- top ||= 0
- bottom = max_height - max_height * height
- else
- top = max_height - max_height * height
- end
- end
-
+ if options.slice(:width, :height, :right, :bottom, :height_to_fit).values.any?
mask = UIViewAutoresizingNone
- mask |= UIViewAutoresizingFlexibleTopMargin if top.nil?
- mask |= UIViewAutoresizingFlexibleLeftMargin if left.nil?
- mask |= UIViewAutoresizingFlexibleBottomMargin if bottom.nil?
- mask |= UIViewAutoresizingFlexibleRightMargin if right.nil?
- mask |= UIViewAutoresizingFlexibleWidth if !left.nil? && !right.nil?
- mask |= UIViewAutoresizingFlexibleHeight if !top.nil? && !bottom.nil?
-
- if !left.nil? && !right.nil?
- frame.origin.x = left
- frame.size.width = max_width - left - right
- elsif !right.nil?
- frame.origin.x = max_width - width - right
- frame.size.width = width
- elsif !left.nil?
- frame.origin.x = left
- frame.size.width = width
- else
- frame.origin.x = max_width / 2 - width / 2
- frame.size.width = width
- end
-
- if !top.nil? && !bottom.nil?
- frame.origin.y = top
- frame.size.height = max_height - top - bottom
- elsif !bottom.nil?
- frame.origin.y = max_height - height - bottom
- frame.size.height = height
- elsif !top.nil?
- frame.origin.y = top
- frame.size.height = height
- else
- frame.origin.y = max_height / 2 - height / 2
- frame.size.height = height
- end
-
- options[:frame] = frame
+ mask |= UIViewAutoresizingFlexibleTopMargin if options[:top].nil?
+ mask |= UIViewAutoresizingFlexibleLeftMargin if options[:left].nil?
+ mask |= UIViewAutoresizingFlexibleBottomMargin if options[:bottom].nil?
+ mask |= UIViewAutoresizingFlexibleRightMargin if options[:right].nil?
+ mask |= UIViewAutoresizingFlexibleWidth if !options[:left].nil? && !options[:right].nil?
+ mask |= UIViewAutoresizingFlexibleHeight if !options[:top].nil? && !options[:bottom].nil?
options[:autoresizingMask] = mask
end
end
def setValue(value, forUndefinedKey: key)
# return if value.nil?
# ignore options
+ return if options[:section].is_a?(DrawSection) && %w[gradient].include?(key.to_s)
return if key == 'size_to_fit' && view.is_a?(UILabel)
return if (key == 'url' || key == 'default') && view.is_a?(UIImageView)
return if %w[
+ styles
+ width height top right bottom left value_type
max_width max_outer_width min_width min_outer_width
max_height max_outer_height min_height min_outer_width
- height_to_fit container].include? key.to_s
+ height_to_fit container parent_frame].include? key.to_s
# apply options
if key.end_with?('title_color')
view.setTitleColor value.uicolor, forState: UIControlStateNormal
elsif key.end_with?('alignment') && value.is_a?(Symbol)
@@ -150,23 +89,29 @@
view.contentInset = current_inset
elsif key == 'autocapitalization'
view.autocapitalizationType = UITextAutocapitalizationTypeNone if value === false
elsif key == 'keyboard_type'
view.setKeyboardType value.uikeyboardtype
+ elsif key == 'rounded_corners'
+ radius = value[:radius].to_f
+ corner_consts = {top_left: UIRectCornerTopLeft, bottom_left: UIRectCornerBottomLeft, bottom_right: UIRectCornerBottomRight, top_right: UIRectCornerTopRight}
+ corners = value[:corners].inject(0) { |result, corner| result|corner_consts[corner] }
+ size = options[:parent_frame].size
+ bounds = CGRectMake(0, 0, size.width, size.height)
+ mask_path = UIBezierPath.bezierPathWithRoundedRect(bounds, byRoundingCorners: corners, cornerRadii: CGSizeMake(radius, radius))
+ mask_layer = CAShapeLayer.layer
+ mask_layer.frame = bounds
+ mask_layer.path = mask_path.CGPath
+ view.mask = mask_layer
elsif key == 'mask'
radius = value[:radius]
bounds = CGRectMake(0, 0, value[:width], value[:height])
mask_path = UIBezierPath.bezierPathWithRoundedRect(bounds, byRoundingCorners: UIRectCornerAllCorners, cornerRadii: CGSizeMake(radius, radius))
mask_layer = CAShapeLayer.layer
mask_layer.frame = bounds
mask_layer.path = mask_path.CGPath
view.layer.mask = mask_layer
- # TODO: apply for corner_radius_top/bottom
- # CAShapeLayer *shape = [[CAShapeLayer alloc] init];
- # shape.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height) byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:CGSizeMake(10, 10)].CGPath;
- # self.layer.mask = shape;
- # self.layer.masksToBounds = YES;
elsif key == 'attributed_text_options'
attributes = {}
if line_spacing = value[:line_spacing]
paragrahStyle = NSMutableParagraphStyle.alloc.init
paragrahStyle.setLineSpacing(line_spacing)
@@ -182,16 +127,13 @@
view.setAttributedTitle attributedString, forState: UIControlStateNormal
else
view.attributedText = attributedString
end
elsif key == 'gradient'
- gradient = CAGradientLayer.layer
- gradient.frame = CGRectMake(value[:frame_x].to_f, value[:frame_y].to_f, value[:frame_width].to_f, value[:frame_height].to_f)
- gradient.colors = value[:colors].map(&:uicolor).map(&:cgcolor)
- gradient.locations = value[:locations] if value[:locations]
+ gradient = prepare_gradient(value)
view.layer.insertSublayer(gradient, atIndex: 0)
elsif value.is_a?(Hash)
- self.class.new(view.send(key.camelize(:lower).to_sym), nil, value).apply
+ self.class.new(view.send(key.camelize(:lower).to_sym), nil, value.merge(parent_frame: options[:frame] || options[:parent_frame])).apply
else
view.setValue value, forKey: key.camelize(:lower)
end
end
\ No newline at end of file