module Teacup::View

Attributes

debug[RW]

Enable debug messages for this object

style_classes[R]

A list of style classes that will be merged in (lower priority than stylename)

stylename[R]

The current stylename that is used to look up properties in the stylesheet.

teacup_next_responder[RW]

Any class that includes Teacup::Layout gets a `layout` method, which assigns itself as the 'teacup_next_responder'.

Public Instance Methods

_teacup_check_stylename(name_or_class) click to toggle source
# File lib/teacup/core_extensions/view_getters.rb, line 48
def _teacup_check_stylename(name_or_class)
  if name_or_class.is_a? Class
    return self.is_a?(name_or_class)
  elsif stylename == name_or_class
    return true
  elsif stylesheet.is_a?(Teacup::Stylesheet)
    return stylesheet.extends_style?(self.stylename, name_or_class)
  end
  return false
end
add_style_class(stylename) click to toggle source
# File lib/teacup/teacup_view.rb, line 75
def add_style_class(stylename)
  unless style_classes.include? stylename
    style_classes << stylename
    restyle!
  end
end
add_uniq_constraints(constraint) click to toggle source
# File lib/teacup/teacup_view.rb, line 358
def add_uniq_constraints(constraint)
  @teacup_constraints ||= {}

  if constraint.is_a? Array
    constraint.each do |constraint|
      add_uniq_constraints(constraint)
    end
  elsif constraint.is_a? Hash
    constraint.each do |sym, relative_to|
      @teacup_constraints[sym] = relative_to
    end
  elsif constraint.is_a?(Teacup::Constraint) || constraint.is_a?(Symbol)
    @teacup_constraints[constraint] = true
  else
    raise "Unsupported constraint: #{constraint.inspect}"
  end
end
animate_to_style(style) click to toggle source

Animate a change to new styles

This is equivalent to wrapping a call to .style() inside UIView.beginAnimations.

@param Hash the new styles and options for the animation

# File lib/teacup/teacup_view.rb, line 324
def animate_to_style(style)
  teacup_animation(options) do
    self.style(style)
  end
end
animate_to_stylename(stylename, options={}) click to toggle source

Animate a change to a new stylename.

This is equivalent to wrapping a call to .stylename= inside UIView.beginAnimations.

@param Symbol the new stylename @param Options the options for the animation (may include the

duration and the curve)
# File lib/teacup/teacup_view.rb, line 292
def animate_to_stylename(stylename, options={})
  return if self.stylename == stylename

  teacup_animation(options) do
    self.stylename = stylename
  end
end
animate_to_styles(style_classes, options={}) click to toggle source

Animate a change to a new list of style_classes.

This is equivalent to wrapping a call to .style_classes= inside UIView.beginAnimations.

@param Symbol the new stylename @param Options the options for the animation (may include the

duration and the curve)
# File lib/teacup/teacup_view.rb, line 309
def animate_to_styles(style_classes, options={})
  return if self.style_classes == style_classes

  teacup_animation(options) do
    self.style_classes = style_classes
  end
end
apply_constraints() click to toggle source
# File lib/teacup/teacup_view.rb, line 255
def apply_constraints
  if @teacup_added_constraints
    @teacup_added_constraints.each do |constraint|
      self.removeConstraint(constraint)
    end
  end
  @teacup_added_constraints = nil
  all_constraints = get_ns_constraints

  return if all_constraints.empty?

  @teacup_added_constraints = []
  all_constraints.each do |ns_constraint|
    @teacup_added_constraints << ns_constraint
    self.addConstraint(ns_constraint)
  end
end
apply_style_properties(properties) click to toggle source
# File lib/teacup/teacup_view.rb, line 347
def apply_style_properties(properties)
  Teacup.apply_hash self, properties
end
apply_stylename(stylename) click to toggle source

Applies styles pulled from a stylesheet, but does not assign those styles to any property. This is a one-shot use method, meant to be used as initialization or to apply styles that should not be reapplied during a rotation.

# File lib/teacup/teacup_view.rb, line 277
def apply_stylename(stylename)
  if stylesheet && stylesheet.is_a?(Teacup::Stylesheet)
    style(stylesheet.query(stylename, self))
  end
end
get_ns_constraints() click to toggle source
# File lib/teacup/teacup_view.rb, line 145
def get_ns_constraints
  # gets the array of Teacup::Constraint objects
  my_constraints = (@teacup_constraints || []).map { |constraint, relative_to|
    if constraint.is_a?(Teacup::Constraint)
      constraint
    else
      if relative_to == true
        Teacup::Constraint.from_sym(constraint)
      else
        Teacup::Constraint.from_sym(constraint, relative_to)
      end
    end
  }.flatten.map do |original_constraint|
    constraint = original_constraint.copy

    view_class = self.class

    controller = nil
    target = self
    while target && controller.nil?
      if target.nextResponder.is_a?(UIViewController)
        controller = target.nextResponder
        target = nil
      else
        target = target.nextResponder
      end
    end

    case original_constraint.target
    when view_class
      constraint.target = original_constraint.target
    when :self
      constraint.target = self
    when :superview
      constraint.target = self.superview
    when Symbol, String
      container = self
      constraint.target = nil
      while container && constraint.target.nil?
        constraint.target = container.viewWithStylename(original_constraint.target)
        container = container.superview
      end
    end

    case original_constraint.relative_to
    when nil
      constraint.relative_to = nil
    when view_class
      constraint.relative_to = original_constraint.relative_to
    when :self
      constraint.relative_to = self
    when :superview
      constraint.relative_to = self.superview
    when :top_layout_guide
      if controller.respondsToSelector(:topLayoutGuide)
        constraint.relative_to = controller.topLayoutGuide
      else
        if controller
          NSLog("topLayoutGuide is only supported in >= iOS 7. Reverting to nil bound")
        end
        constraint.relative_to = nil
      end
    when :bottom_layout_guide
      if controller.respondsToSelector(:bottomLayoutGuide)
        constraint.relative_to = controller.bottomLayoutGuide
      else
        if controller
          NSLog("bottomLayoutGuide is only supported in >= iOS 7. Reverting to nil bound")
        end
        constraint.relative_to = nil
      end
    when Symbol, String
      # TODO: this re-checks lots of views - everytime it goes up to the
      # superview, it checks all the leaves again.
      container = self
      constraint.relative_to = nil
      while container && constraint.relative_to.nil?
        constraint.relative_to = container.viewWithStylename(original_constraint.relative_to)
        container = container.superview
      end
    end

    if original_constraint.relative_to && ! constraint.relative_to
      container = self
      puts "Searching for #{original_constraint.relative_to.inspect} in the tree:"
      tab = ''
      while container
        tab << '->'
        puts "#{tab} #{container.stylename.inspect}"
        container = container.superview
      end
      raise "Could not find #{original_constraint.relative_to.inspect}"
    end

    # the return value, for the map
    constraint.nslayoutconstraint
  end

  unless my_constraints.empty?
    self.setTranslatesAutoresizingMaskIntoConstraints(false)
  end

  # now add all che child constraints
  teacup_subviews.each do |subview|
    my_constraints.concat(subview.get_ns_constraints)
  end

  my_constraints
end
remove_style_class(stylename) click to toggle source
# File lib/teacup/teacup_view.rb, line 82
def remove_style_class(stylename)
  if style_classes.delete(stylename)
    restyle!
  end
end
reset_constraints() click to toggle source
# File lib/teacup/teacup_view.rb, line 351
def reset_constraints
  @teacup_constraints = nil
  self.teacup_subviews.each do |subview|
    subview.reset_constraints
  end
end
restyle!(orientation=nil) click to toggle source
# File lib/teacup/teacup_view.rb, line 133
def restyle!(orientation=nil)
  if Teacup.should_restyle?
    if stylesheet && stylesheet.is_a?(Teacup::Stylesheet)
      style_classes.each do |stylename|
        style(stylesheet.query(stylename, self, orientation))
      end
      style(stylesheet.query(self.stylename, self, orientation))
    end
    teacup_subviews.each { |subview| subview.restyle!(orientation) }
  end
end
style(properties) click to toggle source

Apply style properties to this element.

Takes a hash of properties such as may have been read from a stylesheet or passed as parameters to {Teacup::Layout#layout}, and applies them to the element.

Does a little bit of magic (that may be split out as 'sugarcube') to make properties work as you'd expect.

If you try and assign something in properties that is not supported, a warning message will be emitted.

@param Hash the properties to set.

# File lib/teacup/teacup_view.rb, line 343
def style(properties)
  apply_style_properties(properties)
end
style_classes=(new_style_classes) click to toggle source

Why stop at just one stylename!? Assign a bunch of them using `style_classes`. These are distinct from `stylename`, and `stylename` styles are given priority of `style_classes`.

If you are using Pixate, it will also set the pixate `styleClass` property.

@param Array [Symbol] style_classes

# File lib/teacup/teacup_view.rb, line 63
def style_classes=(new_style_classes)
  @style_classes = new_style_classes
  if respond_to?(:setStyleClass)
    setStyleClass(new_style_classes.join(' '))
  end
  restyle!
end
stylename=(new_stylename) click to toggle source

Alter the stylename of this view.

This will cause new styles to be applied from the stylesheet.

If you are using Pixate, it will also set the pixate `styleId` property.

@param Symbol stylename

# File lib/teacup/teacup_view.rb, line 45
def stylename=(new_stylename)
  @stylename = new_stylename
  if respond_to?(:'setStyleId:')
    setStyleId(new_stylename)
  end
  if respond_to?(:'setNuiClass:')
    setNuiClass(new_stylename)
  end
  restyle!
end
stylesheet() click to toggle source
# File lib/teacup/teacup_view.rb, line 109
def stylesheet
  if @stylesheet.is_a? Symbol
    @stylesheet = Teacup::Stylesheet[@stylesheet]
  end
  # is a stylesheet assigned explicitly?
  retval = @stylesheet
  return retval if retval

  # the 'teacup_next_responder' is assigned in the `layout` method, and links
  # any views created there to the custom class (could be a controller, could
  # be any class that includes Teacup::Layout).  That responder is checked
  # next, but only if it wouldn't result in a circular loop.
  if ! retval && teacup_next_responder && teacup_next_responder != self
    retval = teacup_next_responder.stylesheet
  end

  # lastly, go up the chain; either a controller or superview
  if ! retval && nextResponder && nextResponder.respond_to?(:stylesheet)
    retval = nextResponder.stylesheet
  end

  return retval
end
stylesheet=(new_stylesheet) click to toggle source

Alter the stylesheet of this view.

This will cause new styles to be applied using the current stylename, and will recurse into subviews.

If you would prefer that a given UIView object does not inherit the stylesheet from its parents, override the 'stylesheet' method to return the correct value at all times.

@param Teacup::Stylesheet stylesheet.

# File lib/teacup/teacup_view.rb, line 98
def stylesheet=(new_stylesheet)
  should_restyle = Teacup.should_restyle_and_block

  @stylesheet = new_stylesheet

  if should_restyle
    Teacup.should_restyle!
    restyle!
  end
end
teacup_next_responder=(layout) click to toggle source
# File lib/teacup/teacup_view.rb, line 27
def teacup_next_responder=(layout)
  @_has_next_responder = true
  @teacup_next_responder = WeakRef.new(layout)
end
teacup_subviews() click to toggle source

Subviews or empty collection of views to cater for issue with iOS7 dp3

# File lib/teacup/teacup_view.rb, line 23
def teacup_subviews
  self.subviews || []
end
viewWithStylename(name_or_class) click to toggle source

get one subview by stylename or class. If the receiver matches, it will be returned my_view.viewWithStylename :button => #<UIButton..> my_view.viewWithStylename UIButton => #<UIButton..>

# File lib/teacup/core_extensions/view_getters.rb, line 10
def viewWithStylename name_or_class
  return self if self._teacup_check_stylename(name_or_class)

  view = self.teacup_subviews.find { |view| view._teacup_check_stylename(name_or_class) }
  return view if view

  # found_subview will get assigned to the view we want, but the subview is
  # what is returned.
  found_subview = nil
  view = self.teacup_subviews.find { |subview| found_subview = subview.viewWithStylename(name_or_class) }
  return found_subview if view

  return nil  # couldn't find it
end
viewsWithStylename(name_or_class) click to toggle source

get all subviews by stylename or class my_view.viewsWithStylename :button => [#<UIButton..>, #<UIButton…>] my_view.viewsWithStylename UIButton => [#<UIButton..>, #<UIButton…>]

# File lib/teacup/core_extensions/view_getters.rb, line 28
def viewsWithStylename name_or_class
  retval = []
  retval << self if self._teacup_check_stylename(name_or_class)

  search_views = [].concat(self.subviews)
  # ewww, a traditional for loop! the search_views array is modified in place,
  # and `each` and other methods don't like that.
  index = 0
  while index < search_views.length
    view = search_views[index]
    if view._teacup_check_stylename(name_or_class)
      retval << view
    end
    search_views.concat(view.subviews)
    index += 1
  end

  return retval
end