Class: MotionPrime::AbstractCollectionSection

Inherits:
Section
  • Object
show all
Includes:
HasStyleChainBuilder
Defined in:
motion-prime/sections/abstract_collection.rb

Direct Known Subclasses

GridSection, PageViewSection, TableSection

Constant Summary

Constants inherited from Section

Section::DEFAULT_CONTENT_HEIGHT, Section::KEYBOARD_HEIGHT_LANDSCAPE, Section::KEYBOARD_HEIGHT_PORTRAIT

Instance Attribute Summary collapse

Attributes inherited from Section

#elements, #model, #name, #options, #screen, #section_styles

Attributes included from DrawSectionMixin

#cached_draw_image, #container_element, #container_gesture_recognizers

Instance Method Summary collapse

Methods included from HasStyleChainBuilder

#build_styles_chain

Methods inherited from Section

#add_element, #after_element_render, after_element_render, after_initialize, after_render, before_initialize, before_render, bind_keyboard_close, #bind_keyboard_events, #bring_to_front, container, #container_bounds, #container_height, #container_options, #create_elements, #current_input_view_height, #default_name, #element, element, #elements_options, #elements_to_draw, #elements_to_render, #hard_reload_section, #has_container_bounds?, #hide_keyboard, inherited, #initialize, #keyboard_will_hide, #keyboard_will_show, #on_keyboard_hide, #on_keyboard_show, #render, #render!, #render_container, #render_element?, #screen?, #strong_references, #view

Methods included from DelegateMixin

#clear_delegated, #delegated_by

Methods included from DrawSectionMixin

#after_element_render, #before_element_render, #bind_gesture_on_container_for, #clear_gesture_for_receiver, #draw_in, #prerender_elements_for_state, #prerender_enabled?

Methods included from SectionWithContainerMixin

#container_view, #init_container_element, #load_container_with_elements

Methods included from FrameCalculatorMixin

#calculate_frame_for

Methods included from HasStyles

#prepare_gradient

Methods included from HasClassFactory

#camelize_factory, #class_factory, #low_camelize_factory, #underscore_factory

Methods included from HasNormalizer

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

Methods included from HasAuthorization

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

Constructor Details

This class inherits a constructor from MotionPrime::Section

Instance Attribute Details

#collection_elementObject

Returns the value of attribute collection_element.



6
7
8
# File 'motion-prime/sections/abstract_collection.rb', line 6

def collection_element
  @collection_element
end

#deceleratingObject (readonly)

Returns the value of attribute decelerating.



7
8
9
# File 'motion-prime/sections/abstract_collection.rb', line 7

def decelerating
  @decelerating
end

#did_appearObject

Returns the value of attribute did_appear.



6
7
8
# File 'motion-prime/sections/abstract_collection.rb', line 6

def did_appear
  @did_appear
end

Instance Method Details

#cell_for_index(index) ⇒ Object



206
207
208
209
210
211
212
213
# File 'motion-prime/sections/abstract_collection.rb', line 206

def cell_for_index(index)
  cell = cached_cell(index) || render_cell(index)
  # run table view is appeared callback if needed
  if !@did_appear && index.row == cell_sections_for_group(index.section).size - 1
    on_appear
  end
  cell.is_a?(UIView) ? cell : cell.view
end

#cell_name(index) ⇒ Object



193
194
195
196
# File 'motion-prime/sections/abstract_collection.rb', line 193

def cell_name(index)
  record = cell_section_by_index(index)
  "cell_#{record.object_id}_#{@data_stamp[record.object_id]}"
end

#cell_section_by_index(index) ⇒ Object



202
203
204
# File 'motion-prime/sections/abstract_collection.rb', line 202

def cell_section_by_index(index)
  cell_sections_for_group(index.section)[index.row]
end

#cell_section_styles(section) ⇒ Object



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
157
158
# File 'motion-prime/sections/abstract_collection.rb', line 118

def cell_section_styles(section)
  # type = [`cell`, `header`, `field`]

  # UserFormSection example: field :email, type: :string
  # form_name = `user`
  # type = `field`
  # field_name = `email`
  # field_type = `string_field`

  # CategoriesTableSection example: table is a `CategoryTableSection`, cell is a `CategoryTitleSection`, element :icon, type: :image
  # table_name = `categories`
  # type = `cell` (always true)
  # table_cell_section_name = `title`
  type = section.respond_to?(:cell_type) ? section.cell_type : 'cell'
  suffixes = [type]
  if section.is_a?(BaseFieldSection)
    suffixes << section.default_name
  end

  styles = {}
  # table: base_table_<type>
  # form: base_form_<type>, base_form_<field_type>
  styles[:common] = build_styles_chain(collection_styles[:common], suffixes)
  if section.is_a?(BaseFieldSection)
    # form cell: _<type>_<field_name> = `_field_email`
    suffixes << :"#{type}_#{section.name}" if section.name
  elsif section.respond_to?(:cell_section_name) # cell section came from table
    # table cell: _<table_cell_section_name> = `_title`
    suffixes << section.cell_section_name
  end
  # table: <table_name>_table_<type>, <table_name>_table_<table_cell_section_name> = `categories_table_cell`, `categories_table_title`
  # form: <form_name>_form_<type>, <form_name>_form_<field_type>, user_form_<type>_email = `user_form_field`, `user_form_string_field`, `user_form_field_email`
  styles[:specific] = build_styles_chain(collection_styles[:specific], suffixes)

  container_options_styles = section.container_options[:styles]
  if container_options_styles.present?
    styles[:specific] += Array.wrap(container_options_styles)
  end

  styles
end

#cell_sections_for_group(section) ⇒ Object



198
199
200
# File 'motion-prime/sections/abstract_collection.rb', line 198

def cell_sections_for_group(section)
  raise "Implement #cell_sections_for_group"
end

#collection_dataArray<Prime::Section>

Return sections which will be used to render as collection cells.

This method should be redefined in your collection section and must return array.

Returns:

  • (Array<Prime::Section>)

    array of sections



35
36
37
# File 'motion-prime/sections/abstract_collection.rb', line 35

def collection_data
  @model || []
end

#collection_element_optionsObject



160
161
162
163
164
165
166
167
# File 'motion-prime/sections/abstract_collection.rb', line 160

def collection_element_options
  container_options.except(:styles, :height, :hidden).merge({
    section: self.weak_ref,
    styles: collection_styles.values.flatten,
    delegate: collection_delegate,
    data_source: collection_delegate
  })
end

#collection_stylesObject



109
110
111
112
113
114
115
116
# File 'motion-prime/sections/abstract_collection.rb', line 109

def collection_styles
  type = collection_styles_base

  base_styles = Array.wrap(type)
  item_styles = [name.to_sym]
  item_styles += Array.wrap(@styles) if @styles.present?
  {common: base_styles, specific: item_styles}
end

#collection_styles_baseObject



105
106
107
# File 'motion-prime/sections/abstract_collection.rb', line 105

def collection_styles_base
  raise "Implement #collection_styles_base"
end

#collection_viewObject



173
174
175
# File 'motion-prime/sections/abstract_collection.rb', line 173

def collection_view
  collection_element.try(:view)
end

#dataArray<Prime::Section>

Returns cached version of collection data

Returns:

  • (Array<Prime::Section>)

    cached array of sections



42
43
44
# File 'motion-prime/sections/abstract_collection.rb', line 42

def data
  @data || set_collection_data
end

#deallocObject



53
54
55
56
57
58
# File 'motion-prime/sections/abstract_collection.rb', line 53

def dealloc
  Prime.logger.dealloc_message :collection, self, @collection_element.try(:view).to_s
  @collection_delegate.try(:clear_delegated)
  @collection_element.try(:view).try(:setDataSource, nil)
  super
end

#fixed_collection_dataObject

IMPORTANT: when you use #map in collection_data, then #dealloc of Prime::Section will not be called to section created on that #map. We did not find yet why this happening, for now just using hack.



49
50
51
# File 'motion-prime/sections/abstract_collection.rb', line 49

def fixed_collection_data
  collection_data.to_enum.to_a
end

#height_for_index(index) ⇒ Object



215
216
217
218
219
# File 'motion-prime/sections/abstract_collection.rb', line 215

def height_for_index(index)
  section = cell_section_by_index(index)
  section.create_elements
  section.container_height
end

#hideObject



177
178
179
# File 'motion-prime/sections/abstract_collection.rb', line 177

def hide
  collection_view.try(:hide)
end

#on_appearObject



190
# File 'motion-prime/sections/abstract_collection.rb', line 190

def on_appear; end

#on_cell_render(cell, index) ⇒ Object



189
# File 'motion-prime/sections/abstract_collection.rb', line 189

def on_cell_render(cell, index); end

#on_click(index) ⇒ Object



191
# File 'motion-prime/sections/abstract_collection.rb', line 191

def on_click(index); end

#refresh_if_neededBoolean

Reload collection view if data was empty before.

Returns:

  • (Boolean)

    true if reload was happened



86
87
88
# File 'motion-prime/sections/abstract_collection.rb', line 86

def refresh_if_needed
  @data.nil? ? reload_collection_data : false
end

#reloadBoolean

Alias for reload_data

Returns:

  • (Boolean)

    true



71
72
73
# File 'motion-prime/sections/abstract_collection.rb', line 71

def reload
  reload_data
end

#reload_collection_dataBoolean

Reload collection view data

Returns:

  • (Boolean)

    true



78
79
80
81
# File 'motion-prime/sections/abstract_collection.rb', line 78

def reload_collection_data
  collection_view.reloadData
  true
end

#reload_dataBoolean

Reset all collection data and reload collection view

Returns:

  • (Boolean)

    true



63
64
65
66
# File 'motion-prime/sections/abstract_collection.rb', line 63

def reload_data
  reset_collection_data
  reload_collection_data
end

#render_cell(index) ⇒ Object



185
186
187
# File 'motion-prime/sections/abstract_collection.rb', line 185

def render_cell(index)
  raise "Implement #render_cell"
end

#render_collectionObject



169
170
171
# File 'motion-prime/sections/abstract_collection.rb', line 169

def render_collection
  raise "Implement #render_collection"
end

#reset_collection_dataBoolean

Reset all collection data.

Returns:

  • (Boolean)

    true



93
94
95
96
97
98
99
100
101
102
103
# File 'motion-prime/sections/abstract_collection.rb', line 93

def reset_collection_data
  @did_appear = false
  Array.wrap(@data).flatten.each do |section|
    next unless element = section.container_element
    element.update_options(reuse_identifier: nil)
    element.view.try(:removeFromSuperview)
  end
  @data = nil
  @data_stamp = nil
  true
end

#scroll_view_did_end_decelerating(scroll) ⇒ Object



225
226
227
228
# File 'motion-prime/sections/abstract_collection.rb', line 225

def scroll_view_did_end_decelerating(scroll)
  @decelerating = false
  display_pending_cells
end

#scroll_view_did_end_dragging(scroll, willDecelerate: will_decelerate) ⇒ Object



244
245
246
# File 'motion-prime/sections/abstract_collection.rb', line 244

def scroll_view_did_end_dragging(scroll, willDecelerate: will_decelerate)
  display_pending_cells unless @decelerating = will_decelerate
end

#scroll_view_did_scroll(scroll) ⇒ Object



230
# File 'motion-prime/sections/abstract_collection.rb', line 230

def scroll_view_did_scroll(scroll); end

#scroll_view_will_begin_dragging(scroll) ⇒ Object



221
222
223
# File 'motion-prime/sections/abstract_collection.rb', line 221

def scroll_view_will_begin_dragging(scroll)
  @decelerating = true
end

#showObject



181
182
183
# File 'motion-prime/sections/abstract_collection.rb', line 181

def show
  collection_view.try(:show)
end

#update_pull_to_refresh_after_scroll(scroll) ⇒ Object



232
233
234
235
236
237
238
239
240
241
242
# File 'motion-prime/sections/abstract_collection.rb', line 232

def update_pull_to_refresh_after_scroll(scroll)
  return unless refresh_view = collection_view.try(:pullToRefreshView)
  return refresh_view.alpha = 1 if refresh_view.state == SVPullToRefreshStateLoading

  current_offset = scroll.contentOffset.y
  table_inset = collection_view.contentInset.top
  refresh_offset = refresh_view.yOrigin
  alpha = [[-(current_offset + table_inset)/refresh_view.size.height, 0].max, 1].min

  refresh_view.alpha = alpha
end