Class: MotionPrime::BaseElement

Inherits:
Object
  • Object
show all
Extended by:
HasClassFactory
Includes:
HasClassFactory, HasNormalizer, HasStyleChainBuilder, HasStyleOptions, MotionSupport::Callbacks
Defined in:
motion-prime/elements/base_element.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HasClassFactory

camelize_factory, class_factory, low_camelize_factory, underscore_factory

Methods included from HasStyleOptions

#extract_font_from

Methods included from HasStyleChainBuilder

#build_styles_chain

Methods included from HasNormalizer

#debug_info, #element?, #normalize_object, #normalize_options, #normalize_value

Constructor Details

#initialize(options = {}) ⇒ BaseElement

Returns a new instance of BaseElement.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'motion-prime/elements/base_element.rb', line 22

def initialize(options = {})
  options[:screen] = options[:screen].try(:weak_ref)
  @options = options
  @screen = options[:screen]
  @section = options[:section]
  @_has_section = @section.present?

  @view_class = options[:view_class] || 'UIView'
  @name = options[:name]
  @block = options[:block]
  @view_name = underscore_factory(self.class_name_without_kvo.demodulize).gsub(/(_draw)?_element/, '')

  if Prime.env.development?
    info = []
    info << @name
    info << view_name
    info << section.try(:name)
    info << screen.class
    @_element_info = info.join(' ')
    @@_allocated_elements ||= []
    @@_allocated_elements << @_element_info
  end
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



17
18
19
# File 'motion-prime/elements/base_element.rb', line 17

def name
  @name
end

#optionsObject

Returns the value of attribute options.



17
18
19
# File 'motion-prime/elements/base_element.rb', line 17

def options
  @options
end

#screenObject

Returns the value of attribute screen.



17
18
19
# File 'motion-prime/elements/base_element.rb', line 17

def screen
  @screen
end

#sectionObject

Returns the value of attribute section.



17
18
19
# File 'motion-prime/elements/base_element.rb', line 17

def section
  @section
end

#stylesObject

Returns the value of attribute styles.



17
18
19
# File 'motion-prime/elements/base_element.rb', line 17

def styles
  @styles
end

#viewObject

Returns the value of attribute view.



17
18
19
# File 'motion-prime/elements/base_element.rb', line 17

def view
  @view
end

#view_classObject

Returns the value of attribute view_class.



17
18
19
# File 'motion-prime/elements/base_element.rb', line 17

def view_class
  @view_class
end

#view_nameObject

Returns the value of attribute view_name.



17
18
19
# File 'motion-prime/elements/base_element.rb', line 17

def view_name
  @view_name
end

Class Method Details

.after_render(method_name) ⇒ Object



285
286
287
# File 'motion-prime/elements/base_element.rb', line 285

def after_render(method_name)
  set_callback :render, :after, method_name
end

.before_render(method_name) ⇒ Object



282
283
284
# File 'motion-prime/elements/base_element.rb', line 282

def before_render(method_name)
  set_callback :render, :before, method_name
end

.factory(type, options = {}) ⇒ Object



275
276
277
278
279
280
281
# File 'motion-prime/elements/base_element.rb', line 275

def factory(type, options = {})
  element_class = class_factory("#{type}_element", true) || self
  view_class_name = camelize_factory("ui_#{type}")

  options.merge!(view_class: view_class_name)
  element_class.new(options)
end

Instance Method Details

#add_target(target = nil, action = 'on_click:', event = :touch) ⇒ Object



57
58
59
60
# File 'motion-prime/elements/base_element.rb', line 57

def add_target(target = nil, action = 'on_click:', event = :touch)
  return false unless self.view
  self.view.addTarget(target || section, action: action, forControlEvents: event.uicontrolevent)
end

#bind_gesture(action, receiver = nil) ⇒ Object



158
159
160
161
162
163
# File 'motion-prime/elements/base_element.rb', line 158

def bind_gesture(action, receiver = nil)
  receiver ||= self
  single_tap = UITapGestureRecognizer.alloc.initWithTarget(receiver, action: action)
  view.addGestureRecognizer single_tap
  view.setUserInteractionEnabled true
end

#cell_element?Boolean

Returns:

  • (Boolean)


169
170
171
# File 'motion-prime/elements/base_element.rb', line 169

def cell_element?
  @view_class == 'UICollectionViewCell' || @view_class == 'UITableViewCell'
end

#cell_section?Boolean

Returns:

  • (Boolean)


165
166
167
# File 'motion-prime/elements/base_element.rb', line 165

def cell_section?
  section.respond_to?(:cell_section_name)
end

#compute_options!Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'motion-prime/elements/base_element.rb', line 94

def compute_options!
  block_options = compute_block_options || {}
  raw_options = self.options.except(:screen, :name, :block, :view_class).merge(block_options)
  compute_style_options(raw_options)
  raw_options = Styles.for(styles).deep_merge(raw_options)
  @computed_options = raw_options
  return unless @_has_section
  NSLog('ERRROR') unless section
  normalize_options(@computed_options, section.send(:elements_eval_object), %w[
    font font_name font_size text placeholder title_label
    padding padding_left padding_right padding_top padding_bottom
    left right min_width min_outer_width max_width max_outer_width width
    top bottom min_height min_outer_height max_height max_outer_height height])
end

#computed_optionsObject

Lazy-computing options



89
90
91
92
# File 'motion-prime/elements/base_element.rb', line 89

def computed_options
  compute_options! unless @computed_options
  @computed_options
end

#deallocObject



46
47
48
49
50
51
52
53
54
55
# File 'motion-prime/elements/base_element.rb', line 46

def dealloc
  if Prime.env.development?
    index = @@_allocated_elements.index(@_element_info)
    @@_allocated_elements.delete_at(index) if index
  end
  Prime.logger.dealloc_message :element, self, self.name
  super
rescue # "undefined `super` method" bug fix
  Prime.logger.debug "Undefined `super` in `base_element`"
end

#hideObject



150
151
152
# File 'motion-prime/elements/base_element.rb', line 150

def hide
  view.hidden = true if view # TODO: should we update computed options in opposite case?
end

#notify_section_after_renderObject



66
67
68
# File 'motion-prime/elements/base_element.rb', line 66

def notify_section_after_render
  section.try(:after_element_render, self)
end

#notify_section_before_renderObject



62
63
64
# File 'motion-prime/elements/base_element.rb', line 62

def notify_section_before_render
  section.try(:before_element_render, self)
end

#reload!Object



109
110
111
112
# File 'motion-prime/elements/base_element.rb', line 109

def reload!
  reset_computed_values
  compute_options!
end

#render(options = {}, &block) ⇒ Object



70
71
72
73
74
# File 'motion-prime/elements/base_element.rb', line 70

def render(options = {}, &block)
  run_callbacks :render do
    render!(options, &block)
  end
end

#render!(options = {}, &block) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
# File 'motion-prime/elements/base_element.rb', line 76

def render!(options = {}, &block)
  view = screen.add_view class_factory(view_class), computed_options.merge(options) do |view|
    @view = view
    block.try(:call, view, self)
  end

  if computed_options.has_key?(:delegate) && computed_options[:delegate].respond_to?(:delegated_by) && view.respond_to?(:setDelegate)
    computed_options[:delegate].delegated_by(view)
  end
  view
end

#rerender!(changed_options = []) ⇒ Object



114
115
116
117
118
119
120
121
122
# File 'motion-prime/elements/base_element.rb', line 114

def rerender!(changed_options = [])
  render_target = view.try(:superview)
  view.try(:removeFromSuperview)
  render(render_target: render_target)

  if (changed_options & [:text, :size_to_fit]).any? && respond_to?(:size_to_fit)
    size_to_fit
  end
end

#showObject



154
155
156
# File 'motion-prime/elements/base_element.rb', line 154

def show
  view.hidden = false if view
end

#updateObject



146
147
148
# File 'motion-prime/elements/base_element.rb', line 146

def update
  update_with_options({})
end

#update_options(new_options) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'motion-prime/elements/base_element.rb', line 131

def update_options(new_options)
  options.deep_merge!(new_options)
  return unless view

  required_options = if new_options.slice(:width, :height, :top, :left, :right, :bottom).any?
    new_options[:calculate_frame] = true
    [:width, :height, :top, :left, :right, :bottom]
  elsif new_options.slice(:text, :title).any?
    [:line_spacing, :line_height, :underline, :fragment_color, :text_alignment, :font, :font_name, :font_size, :line_break_mode, :number_of_lines]
  end
  new_options = computed_options.slice(*Array.wrap(required_options)).merge(new_options)

  ViewStyler.new(view, view.superview.try(:bounds), new_options).apply
end

#update_with_options(new_options = {}) ⇒ Object



124
125
126
127
128
129
# File 'motion-prime/elements/base_element.rb', line 124

def update_with_options(new_options = {})
  options.deep_merge!(new_options)
  reload!
  computed_options.deep_merge!(new_options)
  rerender!(new_options.keys)
end