Class: UIView

Inherits:
Object
  • Object
show all
Includes:
Teacup::Layout
Defined in:
lib/teacup/z_core_extensions/ui_view.rb,
lib/teacup/z_core_extensions/ui_view_getters.rb

Overview

Methods to retrieve a subview using the stylename as a key Kinda similar to jQuery-style $(el).find(‘stylename’)

Direct Known Subclasses

CustomView, DummyView

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Teacup::Layout

#layout, #subview

Instance Attribute Details

#debugObject

Enable debug messages for this object



17
18
19
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 17

def debug
  @debug
end

#stylenameObject

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



10
11
12
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 10

def stylename
  @stylename
end

#teacup_next_responderObject

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



14
15
16
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 14

def teacup_next_responder
  @teacup_next_responder
end

Instance Method Details

#_teacup_check_stylename(name_or_class) ⇒ Object



38
39
40
41
42
43
44
# File 'lib/teacup/z_core_extensions/ui_view_getters.rb', line 38

def _teacup_check_stylename(name_or_class)
  if name_or_class.is_a? Class
    self.is_a? name_or_class
  else
    self.stylename == name_or_class
  end
end

#add_uniq_constraints(constraint) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 241

def add_uniq_constraints(constraint)
  @teacup_constraints ||= {}

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

#animate_to_style(style) ⇒ Object

Animate a change to new styles

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

Parameters:

  • Hash

    the new styles and options for the animation



204
205
206
207
208
209
210
211
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 204

def animate_to_style(style)
  UIView.beginAnimations(nil, context: nil)
  UIView.setAnimationDuration(style[:duration]) if style[:duration]
  UIView.setAnimationCurve(style[:curve]) if style[:curve]
  UIView.setAnimationDelay(style[:delay]) if style[:delay]
  style(style)
  UIView.commitAnimations
end

#animate_to_stylename(stylename, options = {}) ⇒ Object

Animate a change to a new stylename.

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

Parameters:

  • Symbol

    the new stylename

  • Options

    the options for the animation (may include the duration and the curve)



185
186
187
188
189
190
191
192
193
194
195
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 185

def animate_to_stylename(stylename, options={})
  return if self.stylename == stylename

  UIView.beginAnimations(nil, context: nil)
  # TODO: This should be in a style-sheet!
  UIView.setAnimationDuration(options[:duration]) if options[:duration]
  UIView.setAnimationCurve(options[:curve]) if options[:curve]
  UIView.setAnimationDelay(options[:delay]) if options[:delay]
  self.stylename = stylename
  UIView.commitAnimations
end

#apply_constraintsObject



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 158

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

#get_ns_constraintsObject



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 80

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.tap{ |my_constraints|
    unless my_constraints.empty?
      self.setTranslatesAutoresizingMaskIntoConstraints(false)
    end
  }.map do |original_constraint|
    constraint = original_constraint.copy

    case original_constraint.target
    when UIView
      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 UIView
      constraint.relative_to = original_constraint.relative_to
    when :self
      constraint.relative_to = self
    when :superview
      constraint.relative_to = self.superview
    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
      puts "Could not find #{original_constraint.relative_to.inspect}"
      container = self
      tab = '  '
      while container && constraint.relative_to.nil?
        tab << '->'
        puts "#{tab} #{container.stylename.inspect}"
        container = container.superview
      end
    end

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

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

  my_constraints
end

#restyle!(orientation = nil) ⇒ Object



71
72
73
74
75
76
77
78
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 71

def restyle!(orientation=nil)
  if Teacup.should_restyle?
    if stylesheet && stylesheet.is_a?(Teacup::Stylesheet)
      style(stylesheet.query(stylename, self, orientation))
    end
    subviews.each{ |subview| subview.restyle!(orientation) }
  end
end

#style(properties) ⇒ Object

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.

Parameters:

  • Hash

    the properties to set.



226
227
228
229
230
231
232
233
234
235
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 226

def style(properties)
  if properties.key?(:constraints)
    add_uniq_constraints(properties.delete(:constraints))
  end

  Teacup.apply_hash self, properties

  self.setNeedsDisplay
  self.setNeedsLayout
end

#stylesheetObject



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 50

def stylesheet
  super
  # is a stylesheet assigned explicitly?
  retval = @stylesheet

  # 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
    retval = nextResponder.stylesheet
  end

  return retval
end

#stylesheet=(new_stylesheet) ⇒ Object

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.

Parameters:

  • Teacup::Stylesheet

    stylesheet.



39
40
41
42
43
44
45
46
47
48
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 39

def stylesheet=(new_stylesheet)
  should_restyle = Teacup.should_restyle_and_block

  @stylesheet = new_stylesheet

  if should_restyle
    Teacup.should_restyle!
    restyle!
  end
end

#top_level_viewObject



237
238
239
# File 'lib/teacup/z_core_extensions/ui_view.rb', line 237

def top_level_view
  return self
end

#viewsWithStylename(name_or_class) ⇒ Object

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



27
28
29
30
31
32
33
34
35
36
# File 'lib/teacup/z_core_extensions/ui_view_getters.rb', line 27

def viewsWithStylename name_or_class
  r = []
  r << self if self._teacup_check_stylename(name_or_class)

  subviews.each do |view|
    r << view if view._teacup_check_stylename(name_or_class)
    r.concat view.viewsWithStylename name_or_class
  end
  r
end

#viewWithStylename(name_or_class) ⇒ Object

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



9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/teacup/z_core_extensions/ui_view_getters.rb', line 9

def viewWithStylename name_or_class
  return self if self._teacup_check_stylename(name_or_class)

  view = 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 = subviews.find { |subview| found_subview = subview.viewWithStylename(name_or_class) }
  return found_subview if view

  nil  # couldn't find it
end