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