Class: MotionPrime::Section

Inherits:
Object
  • Object
show all
Includes:
DrawSectionMixin, HasAuthorization, HasClassFactory, HasNormalizer, MotionSupport::Callbacks
Defined in:
motion-prime/sections/base_section.rb

Constant Summary collapse

KEYBOARD_HEIGHT_PORTRAIT =

Basic Sample

class MySection < MotionPrime::Section

element :title, text: "Hello World"
element :avatar, type: :image, image: 'defaults/avatar.jpg'

end

216
KEYBOARD_HEIGHT_LANDSCAPE =
162
DEFAULT_CONTENT_HEIGHT =
65

Instance Attribute Summary collapse

Attributes included from DrawSectionMixin

#cached_draw_image, #container_element, #container_gesture_recognizers

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DrawSectionMixin

#bind_gesture_on_container_for, #container_view, #draw_in, #init_container_element, #load_container_element, #prerender_elements_for_state, #prerender_enabled?, #strong_references

Methods included from FrameCalculatorMixin

#calculate_frome_for

Methods included from HasStyles

#prepare_gradient

Methods included from HasClassFactory

#camelize_factory, #class_factory, #low_camelize_factory

Methods included from HasNormalizer

#normalize_object, #normalize_options

Methods included from HasAuthorization

#api_client, #current_user, #reset_current_user, #user_signed_in?

Constructor Details

#initialize(options = {}) ⇒ Section

Returns a new instance of Section.



27
28
29
30
31
32
33
34
35
36
37
# File 'motion-prime/sections/base_section.rb', line 27

def initialize(options = {})
  @options = options

  run_callbacks :initialize do
    @options[:screen] = @options[:screen].try(:weak_ref)
    self.screen = options[:screen]
    @model = options[:model]
    @name = options[:name] ||= default_name
    @options_block = options[:block]
  end
end

Instance Attribute Details

#elementsObject

Returns the value of attribute elements.



23
24
25
# File 'motion-prime/sections/base_section.rb', line 23

def elements
  @elements
end

#modelObject

Returns the value of attribute model.



23
24
25
# File 'motion-prime/sections/base_section.rb', line 23

def model
  @model
end

#nameObject

Returns the value of attribute name.



23
24
25
# File 'motion-prime/sections/base_section.rb', line 23

def name
  @name
end

#optionsObject

Returns the value of attribute options.



23
24
25
# File 'motion-prime/sections/base_section.rb', line 23

def options
  @options
end

#screenObject

Returns the value of attribute screen.



23
24
25
# File 'motion-prime/sections/base_section.rb', line 23

def screen
  @screen
end

#section_stylesObject

Returns the value of attribute section_styles.



23
24
25
# File 'motion-prime/sections/base_section.rb', line 23

def section_styles
  @section_styles
end

Class Method Details

.after_initialize(method_name) ⇒ Object



357
358
359
# File 'motion-prime/sections/base_section.rb', line 357

def after_initialize(method_name)
  set_callback :initialize, :after, method_name
end

.after_render(method_name) ⇒ Object



351
352
353
# File 'motion-prime/sections/base_section.rb', line 351

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

.before_initialize(method_name) ⇒ Object



354
355
356
# File 'motion-prime/sections/base_section.rb', line 354

def before_initialize(method_name)
  set_callback :initialize, :before, method_name
end

.before_render(method_name) ⇒ Object



348
349
350
# File 'motion-prime/sections/base_section.rb', line 348

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

.bind_keyboard_close(options) ⇒ Object



360
361
362
# File 'motion-prime/sections/base_section.rb', line 360

def bind_keyboard_close(options)
  self.keyboard_close_bindings = options
end

.container(options) ⇒ Object



345
346
347
# File 'motion-prime/sections/base_section.rb', line 345

def container(options)
  self.container_options = options
end

.element(name, options = {}, &block) ⇒ Object



337
338
339
340
341
342
343
344
# File 'motion-prime/sections/base_section.rb', line 337

def element(name, options = {}, &block)
  options[:name] ||= name
  options[:type] ||= :label
  options[:block] = block
  self.elements_options ||= {}
  self.elements_options[name] = options
  self.elements_options[name]
end

Instance Method Details

#add_element(key, options = {}) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'motion-prime/sections/base_section.rb', line 155

def add_element(key, options = {})
  return unless render_element?(key)
  opts = options.clone
  index = opts.delete(:at)
  options = build_options_for_element(opts)
  options[:name] ||= key
  element = build_element(options)
  if index
    new_elements_array = elements.to_a.insert(index, [key, element])
    self.elements = Hash[new_elements_array]
  else
    self.elements[key] = element
  end
end

#bind_keyboard_eventsObject



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'motion-prime/sections/base_section.rb', line 247

def bind_keyboard_events
  NSNotificationCenter.defaultCenter.addObserver self,
                                     selector: :on_keyboard_show,
                                         name: UIKeyboardDidShowNotification,
                                       object: nil
  NSNotificationCenter.defaultCenter.addObserver self,
                                     selector: :on_keyboard_hide,
                                         name: UIKeyboardDidHideNotification,
                                       object: nil
  NSNotificationCenter.defaultCenter.addObserver self,
                                     selector: :keyboard_will_show,
                                         name: UIKeyboardWillShowNotification,
                                       object: nil
  NSNotificationCenter.defaultCenter.addObserver self,
                                     selector: :keyboard_will_hide,
                                         name: UIKeyboardWillHideNotification,
                                       object: nil
end

#build_element(options = {}) ⇒ Object



170
171
172
173
174
175
176
177
178
# File 'motion-prime/sections/base_section.rb', line 170

def build_element(options = {})
  type = options.delete(:type)
  render_as = options.delete(:as).to_s
  if self.is_a?(BaseFieldSection) || self.is_a?(BaseHeaderSection) || render_as == 'view'
    BaseElement.factory(type, options)
  else
    DrawElement.factory(type, options) || BaseElement.factory(type, options)
  end
end

#cellObject



184
185
186
187
188
189
# File 'motion-prime/sections/base_section.rb', line 184

def cell
  container_view || begin
    first_element = elements.values.first
    first_element.view.superview.superview
  end
end

#container_boundsObject



45
46
47
# File 'motion-prime/sections/base_section.rb', line 45

def container_bounds
  options[:container_bounds] or raise "You must pass `container bounds` option to prerender base section"
end

#container_heightObject

Get computed container height

Examples:

class MySection < Prime::Section
  container height: proc { element(:title).content_outer_height }
  element :title, text: 'Hello world'
end
section = MySection.new
section.container_height # => 46


68
69
70
# File 'motion-prime/sections/base_section.rb', line 68

def container_height
  container_options[:height] || DEFAULT_CONTENT_HEIGHT
end

#container_optionsObject

Get computed container options



52
53
54
55
# File 'motion-prime/sections/base_section.rb', line 52

def container_options
  compute_container_options! unless @container_options
  @container_options
end

#create_elementsObject



140
141
142
143
144
145
146
# File 'motion-prime/sections/base_section.rb', line 140

def create_elements
  self.elements = {}
  elements_options.each do |key, opts|
    add_element(key, opts)
  end
  self.instance_eval(&@options_block) if @options_block.is_a?(Proc)
end

#deallocObject



39
40
41
42
43
# File 'motion-prime/sections/base_section.rb', line 39

def dealloc
  Prime.logger.dealloc_message :section, self, self.name
  NSNotificationCenter.defaultCenter.removeObserver self # unbinding events created in bind_keyboard_events
  super
end

#default_nameObject

Get section default name, based on class name

Examples:

class ProfileSection < Prime::Section
end

section = ProfileSection.new
section.default_name # => 'profile'
section.name         # => 'profile'

another_section = ProfileSection.new(name: 'another')
another_section.default_name # => 'profile'
another_section.name         # => 'another'


87
88
89
# File 'motion-prime/sections/base_section.rb', line 87

def default_name
  self.class_name_without_kvo.demodulize.underscore.gsub(/\_section$/, '')
end

#element(name) ⇒ Object



218
219
220
# File 'motion-prime/sections/base_section.rb', line 218

def element(name)
  elements[name.to_sym]
end

#elements_optionsObject

Get section elements options, where the key is element name.



94
95
96
# File 'motion-prime/sections/base_section.rb', line 94

def elements_options
  self.class.elements_options || {}
end

#elements_to_drawObject



276
277
278
# File 'motion-prime/sections/base_section.rb', line 276

def elements_to_draw
  self.elements.select { |key, element| element.is_a?(DrawElement) }
end

#elements_to_renderObject



280
281
282
# File 'motion-prime/sections/base_section.rb', line 280

def elements_to_render
  self.elements.select { |key, element| element.is_a?(BaseElement) }
end

#hideObject



226
227
228
229
230
231
232
# File 'motion-prime/sections/base_section.rb', line 226

def hide
  if container_view
    container_view.hidden = true
  else
    elements.values.each(&:hide)
  end
end

#hide_keyboardObject



266
267
268
269
270
271
272
273
274
# File 'motion-prime/sections/base_section.rb', line 266

def hide_keyboard
  elements = Array.wrap(keyboard_close_bindings_options[:elements])
  views = Array.wrap(keyboard_close_bindings_options[:views])

  elements.each do |el|
    views << el.view if %w[text_field text_view].include?(el.view_name) && el.view
  end
  views.compact.each(&:resignFirstResponder)
end

#keyboard_will_hideObject



245
# File 'motion-prime/sections/base_section.rb', line 245

def keyboard_will_hide; end

#keyboard_will_showObject



244
# File 'motion-prime/sections/base_section.rb', line 244

def keyboard_will_show; end

#load_elementsObject



148
149
150
151
152
153
# File 'motion-prime/sections/base_section.rb', line 148

def load_elements
  self.elements.values.each do |element|
    element.size_to_fit_if_needed if element.is_a?(LabelDrawElement)
    element.compute_options! if element.respond_to?(:computed_options) && !element.computed_options
  end
end

#load_sectionObject

Create elements if they are not created yet. This will not cause rendering elements, they will be rendered immediately after that or rendered async later, based on type of section.



103
104
105
106
107
108
109
110
111
112
113
# File 'motion-prime/sections/base_section.rb', line 103

def load_section
  return if @section_loaded
  if @section_loading
    sleep 0.1
    return @section_loaded ? false : load_section
  end
  @section_loading = true
  create_elements
  @section_loading = false
  return @section_loaded = true
end

#load_section!Object

Force load section



118
119
120
121
# File 'motion-prime/sections/base_section.rb', line 118

def load_section!
  @section_loaded = false
  load_section
end

#on_keyboard_hideObject



243
# File 'motion-prime/sections/base_section.rb', line 243

def on_keyboard_hide; end

#on_keyboard_showObject



242
# File 'motion-prime/sections/base_section.rb', line 242

def on_keyboard_show; end

#reload_sectionObject

Force reload section, will also re-render elements. For table view cells will also reload it’s table data.



125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'motion-prime/sections/base_section.rb', line 125

def reload_section
  self.elements_to_render.values.map(&:view).flatten.each do |view|
    view.removeFromSuperview if view
  end
  load_section!
  run_callbacks :render do
    render!
  end

  if @table && !self.is_a?(BaseFieldSection)
    cell.setNeedsDisplay
    @table.reload_table_data
  end
end

#render(container_options = {}) ⇒ Object



191
192
193
194
195
196
197
# File 'motion-prime/sections/base_section.rb', line 191

def render(container_options = {})
  load_section
  self.container_options.merge!(container_options)
  run_callbacks :render do
    render!
  end
end

#render!Object



210
211
212
213
214
215
216
# File 'motion-prime/sections/base_section.rb', line 210

def render!
  render_container(container_options) do
    elements_to_render.each do |key, element|
      element.render
    end
  end
end

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



199
200
201
202
203
204
205
206
207
208
# File 'motion-prime/sections/base_section.rb', line 199

def render_container(options = {}, &block)
  if should_render_container?
    element = self.container_element || self.init_container_element(options)
    element.render do
      block.call
    end
  else
    block.call
  end
end

#render_element?(element_name) ⇒ Boolean

Returns:

  • (Boolean)


180
181
182
# File 'motion-prime/sections/base_section.rb', line 180

def render_element?(element_name)
  true
end

#showObject



234
235
236
237
238
239
240
# File 'motion-prime/sections/base_section.rb', line 234

def show
  if container_view
    container_view.hidden = false
  else
    elements.values.each(&:show)
  end
end

#view(name) ⇒ Object



222
223
224
# File 'motion-prime/sections/base_section.rb', line 222

def view(name)
  element(name).view
end