motion-prime 0.4.5 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +14 -6
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +14 -0
  4. data/Gemfile.lock +1 -1
  5. data/README.md +10 -8
  6. data/ROADMAP.md +9 -10
  7. data/Rakefile +1 -1
  8. data/doc/code/getting_started.rb +3 -3
  9. data/doc/code/screens.rb +25 -10
  10. data/doc/code/sections.rb +41 -0
  11. data/doc/docs/getting_started.html +8 -3
  12. data/doc/docs/screens.html +58 -19
  13. data/doc/docs/sections.html +134 -0
  14. data/files/Gemfile +7 -1
  15. data/files/Gemfile.lock +18 -9
  16. data/files/Rakefile +2 -11
  17. data/files/app/app_delegate.rb +2 -2
  18. data/files/app/config/base.rb +0 -4
  19. data/files/app/screens/application_screen.rb +2 -2
  20. data/files/app/screens/home_screen.rb +2 -0
  21. data/files/app/screens/sidebar_screen.rb +3 -3
  22. data/files/app/sections/home/section.rb +3 -0
  23. data/files/app/sections/sidebar/action.rb +1 -1
  24. data/files/app/styles/home.rb +9 -0
  25. data/files/app/styles/sidebar.rb +3 -3
  26. data/lib/motion-prime.rb +9 -0
  27. data/motion-prime/api_client.rb +5 -1
  28. data/motion-prime/app_delegate.rb +40 -45
  29. data/motion-prime/core_ext/kernel.rb +8 -0
  30. data/motion-prime/elements/_content_text_mixin.rb +3 -1
  31. data/motion-prime/elements/_text_mixin.rb +1 -1
  32. data/motion-prime/elements/base_element.rb +6 -5
  33. data/motion-prime/elements/draw/image.rb +6 -1
  34. data/motion-prime/elements/view_with_section.rb +7 -0
  35. data/motion-prime/helpers/has_style_chain_builder.rb +4 -1
  36. data/motion-prime/models/_association_mixin.rb +139 -0
  37. data/motion-prime/models/_base_mixin.rb +184 -0
  38. data/motion-prime/models/_dirty_mixin.rb +31 -0
  39. data/motion-prime/models/_finder_mixin.rb +208 -0
  40. data/motion-prime/models/{bag.rb → _nano_bag_mixin.rb} +4 -4
  41. data/motion-prime/models/{sync.rb → _sync_mixin.rb} +75 -76
  42. data/motion-prime/models/json.rb +6 -9
  43. data/motion-prime/models/model.rb +24 -172
  44. data/motion-prime/{mp.rb → prime.rb} +0 -1
  45. data/motion-prime/screens/_base_mixin.rb +9 -10
  46. data/motion-prime/screens/_navigation_mixin.rb +12 -17
  47. data/motion-prime/screens/extensions/_indicators_mixin.rb +1 -1
  48. data/motion-prime/screens/extensions/_navigation_bar_mixin.rb +3 -3
  49. data/motion-prime/screens/{base_screen.rb → screen.rb} +11 -5
  50. data/motion-prime/sections/_cell_section_mixin.rb +13 -0
  51. data/motion-prime/sections/_draw_section_mixin.rb +17 -0
  52. data/motion-prime/sections/base_section.rb +51 -16
  53. data/motion-prime/sections/form/base_field_section.rb +27 -16
  54. data/motion-prime/sections/form/base_header_section.rb +4 -3
  55. data/motion-prime/sections/form/password_field_section.rb +4 -0
  56. data/motion-prime/sections/form/select_field_section.rb +4 -0
  57. data/motion-prime/sections/form/string_field_section.rb +4 -0
  58. data/motion-prime/sections/form/submit_field_section.rb +4 -0
  59. data/motion-prime/sections/form/text_field_section.rb +4 -0
  60. data/motion-prime/sections/form.rb +7 -1
  61. data/motion-prime/sections/tabbed.rb +1 -1
  62. data/motion-prime/sections/table/table_delegate.rb +5 -0
  63. data/motion-prime/sections/table.rb +71 -51
  64. data/motion-prime/services/logger.rb +37 -0
  65. data/motion-prime/support/mp_cell_with_section.rb +9 -4
  66. data/motion-prime/support/tab_bar_controller.rb +2 -1
  67. data/motion-prime/version.rb +1 -1
  68. data/motion-prime/views/layout.rb +1 -1
  69. data/motion-prime/views/view_builder.rb +7 -0
  70. data/motion-prime.gemspec +1 -1
  71. data/spec/delegate/{base_delegate_spec.rb → delegate_spec.rb} +1 -1
  72. data/spec/helpers/{base_delegate.rb → delegates.rb} +0 -0
  73. data/spec/helpers/models.rb +11 -18
  74. data/spec/helpers/{base_screen.rb → screens.rb} +1 -1
  75. data/spec/models/{association_spec.rb → associations_spec.rb} +1 -1
  76. data/spec/models/bag_spec.rb +1 -1
  77. data/spec/models/errors_spec.rb +1 -1
  78. data/spec/models/finder_spec.rb +1 -1
  79. data/spec/models/json.rb +87 -0
  80. data/spec/models/model_spec.rb +23 -3
  81. data/spec/models/store_extension_spec.rb +1 -1
  82. data/spec/models/store_spec.rb +1 -1
  83. data/spec/screens/{base_screen_spec.rb → screen_spec.rb} +5 -1
  84. metadata +52 -43
  85. data/motion-prime/models/association.rb +0 -134
  86. data/motion-prime/models/base.rb +0 -27
  87. data/motion-prime/models/finder.rb +0 -202
  88. data/motion-prime/screens/sidebar_container_screen.rb +0 -80
@@ -13,6 +13,23 @@ module MotionPrime
13
13
  container_element.try(:view)
14
14
  end
15
15
 
16
+ def init_container_element(options = {})
17
+ @container_element ||= begin
18
+ options.merge!({
19
+ screen: screen,
20
+ section: self.weak_ref,
21
+ has_drawn_content: true
22
+ })
23
+ options[:styles] ||= []
24
+ MotionPrime::BaseElement.factory(:view_with_section, options)
25
+ end
26
+ end
27
+
28
+ def load_container_element(options = {})
29
+ init_container_element(options)
30
+ @container_element.compute_options! unless @container_element.computed_options
31
+ end
32
+
16
33
  def draw_in(rect, state = :normal)
17
34
  if cached_draw_image[state]
18
35
  context = UIGraphicsGetCurrentContext()
@@ -1,12 +1,12 @@
1
1
  motion_require '../helpers/has_authorization'
2
2
  module MotionPrime
3
- class BaseSection
4
- # MotionPrime::BaseSection is container for Elements.
3
+ class Section
4
+ # MotionPrime::Section is container for Elements.
5
5
  # Sections are located inside Screen and can contain multiple Elements.
6
6
  # On render, each element will be added to parent screen.
7
7
 
8
8
  # == Basic Sample
9
- # class MySection < MotionPrime::BaseSection
9
+ # class MySection < MotionPrime::Section
10
10
  # element :title, text: "Hello World"
11
11
  # element :avatar, type: :image, image: 'defaults/avatar.jpg'
12
12
  # end
@@ -22,22 +22,23 @@ module MotionPrime
22
22
 
23
23
  attr_accessor :screen, :model, :name, :options, :elements, :section_styles
24
24
  class_attribute :elements_options, :container_options, :keyboard_close_bindings
25
- define_callbacks :render
25
+ define_callbacks :render, :initialize
26
26
 
27
27
  def initialize(options = {})
28
- options[:screen] = options[:screen].try(:weak_ref)
29
28
  @options = options
30
- self.screen = options[:screen]
31
- @model = options[:model]
32
- @name = options[:name] ||= default_name
33
- @options_block = options[:block]
29
+
30
+ run_callbacks :initialize do
31
+ @options[:screen] = @options[:screen].try(:weak_ref)
32
+ self.screen = options[:screen]
33
+ @model = options[:model]
34
+ @name = options[:name] ||= default_name
35
+ @options_block = options[:block]
36
+ end
34
37
  end
35
38
 
36
39
  def dealloc
37
- # pp 'deallocating section. elements count: ', self.elements.try(:count), self.to_s
38
-
39
- NSNotificationCenter.defaultCenter.removeObserver self
40
- self.delegate = nil if self.respond_to?(:delegate)
40
+ # pp 'deallocating section', self.name, self.elements.try(:count), self.to_s, self.object_id
41
+ NSNotificationCenter.defaultCenter.removeObserver self # unbinding events created in bind_keyboard_events
41
42
  super
42
43
  end
43
44
 
@@ -81,7 +82,9 @@ module MotionPrime
81
82
  end
82
83
 
83
84
  def reload_section
84
- self.elements_to_render.values.map(&:view).flatten.compact.each { |view| view.removeFromSuperview }
85
+ self.elements_to_render.values.map(&:view).flatten.each do |view|
86
+ view.removeFromSuperview if view
87
+ end
85
88
  load_section!
86
89
  run_callbacks :render do
87
90
  render!
@@ -148,9 +151,22 @@ module MotionPrime
148
151
  end
149
152
  end
150
153
 
154
+ def render_container(options = {}, &block)
155
+ if should_render_container?
156
+ element = self.container_element || self.init_container_element(options)
157
+ element.render do
158
+ block.call
159
+ end
160
+ else
161
+ block.call
162
+ end
163
+ end
164
+
151
165
  def render!
152
- elements_to_render.each do |key, element|
153
- element.render
166
+ render_container(container_options) do
167
+ elements_to_render.each do |key, element|
168
+ element.render
169
+ end
154
170
  end
155
171
  end
156
172
 
@@ -218,6 +234,9 @@ module MotionPrime
218
234
  self.elements.select { |key, element| element.is_a?(BaseElement) }
219
235
  end
220
236
 
237
+ def events_off
238
+ end
239
+
221
240
  protected
222
241
  def bind_keyboard_close
223
242
  return unless self.class.keyboard_close_bindings.present?
@@ -241,6 +260,16 @@ module MotionPrime
241
260
  end
242
261
 
243
262
  private
263
+ def should_render_container?
264
+ has_drawn_content?
265
+ end
266
+
267
+ def has_drawn_content?
268
+ self.elements.values.any? do |element|
269
+ element.is_a?(DrawElement)
270
+ end
271
+ end
272
+
244
273
  def compute_container_options!
245
274
  raw_options = {}
246
275
  raw_options.merge!(self.class.container_options.try(:clone) || {})
@@ -274,6 +303,12 @@ module MotionPrime
274
303
  def after_render(method_name)
275
304
  set_callback :render, :after, method_name
276
305
  end
306
+ def before_initialize(method_name)
307
+ set_callback :initialize, :before, method_name
308
+ end
309
+ def after_initialize(method_name)
310
+ set_callback :initialize, :after, method_name
311
+ end
277
312
  def bind_keyboard_close(options)
278
313
  self.keyboard_close_bindings = options
279
314
  end
@@ -1,16 +1,17 @@
1
1
  module MotionPrime
2
- class BaseFieldSection < BaseSection
2
+ class BaseFieldSection < Section
3
3
  include CellSectionMixin
4
4
  include BW::KVO
5
5
 
6
6
  attr_reader :form
7
7
  after_render :on_section_render
8
8
 
9
- def initialize(options = {})
10
- @form = options[:table].try(:weak_ref)
9
+ before_initialize :prepare_table_data
10
+ after_initialize :observe_model_errors
11
+
12
+ def prepare_table_data
13
+ @form = @options[:table]
11
14
  @errors_observer_options = normalize_options(options.delete(:observe_errors).clone, self) if options[:observe_errors]
12
- super
13
- observe_model_errors
14
15
  end
15
16
 
16
17
  def render_element?(element_name)
@@ -30,19 +31,26 @@ module MotionPrime
30
31
 
31
32
  def observe_model_errors
32
33
  return unless observing_errors?
33
- errors_observer_fields.each do |field|
34
- observe observing_errors_for.errors, observing_errors_for.errors.unique_key(field) do |old_value, new_value|
35
- next if old_value == new_value
36
- if @status_for_updated == :rendered
37
- reload_section
38
- else
39
- load_section!
40
- form.reload_table_data
41
- end
34
+ on_error_change = proc { |old_value, new_value|
35
+ next if old_value == new_value
36
+ if @status_for_updated == :rendered
37
+ reload_section
38
+ else
39
+ load_section!
40
+ form.reload_table_data
42
41
  end
42
+ }.weak!
43
+
44
+ errors_observer_fields.each do |field|
45
+ observe observing_errors_for.errors, observing_errors_for.errors.unique_key(field), &on_error_change
43
46
  end
44
47
  end
45
48
 
49
+ def dealloc
50
+ clear_observers
51
+ super
52
+ end
53
+
46
54
  def form_name
47
55
  form.name
48
56
  end
@@ -120,9 +128,12 @@ module MotionPrime
120
128
  end
121
129
 
122
130
  def clear_observers
123
- errors_observer_fields.each do |field|
131
+ return unless observing_errors?
132
+ # unobserve_all cause double dealloc, following code is a replacement
133
+ block = proc { |field|
124
134
  unobserve observing_errors_for.errors, observing_errors_for.errors.unique_key(field)
125
- end if observing_errors?
135
+ }.weak!
136
+ errors_observer_fields.each(&block)
126
137
  end
127
138
 
128
139
  def container_height
@@ -1,14 +1,15 @@
1
1
  module MotionPrime
2
- class BaseHeaderSection < BaseSection
2
+ class BaseHeaderSection < Section
3
3
  include CellSectionMixin
4
4
  DEFAULT_HEADER_HEIGHT = 20
5
5
 
6
6
  element :title, text: proc { @options[:title] }
7
7
  element :hint, text: proc { @options[:hint] }
8
8
 
9
- def initialize(options = {})
9
+ before_initialize :prepare_header_options
10
+
11
+ def prepare_header_options
10
12
  @cell_type = :header
11
- super
12
13
  end
13
14
 
14
15
  def render_element?(name)
@@ -8,5 +8,9 @@ module MotionPrime
8
8
  end
9
9
  element :error_message, type: :error_message, text: proc { all_errors.join("\n") if observing_errors? }
10
10
  after_render :bind_text_input
11
+
12
+ def events_off
13
+ view(:input).off :change
14
+ end
11
15
  end
12
16
  end
@@ -18,5 +18,9 @@ module MotionPrime
18
18
  form.send(options[:action]) if options[:action]
19
19
  end
20
20
  end
21
+
22
+ def events_off
23
+ view(:button).off :touch_down
24
+ end
21
25
  end
22
26
  end
@@ -10,5 +10,9 @@ module MotionPrime
10
10
 
11
11
  element :error_message, type: :error_message, text: proc { all_errors.join("\n") if observing_errors? }
12
12
  after_render :bind_text_input
13
+
14
+ def events_off
15
+ view(:input).off :change
16
+ end
13
17
  end
14
18
  end
@@ -10,5 +10,9 @@ module MotionPrime
10
10
  form.send(options[:action]) if options[:action]
11
11
  end
12
12
  end
13
+
14
+ def events_off
15
+ view(:submit).off :touch
16
+ end
13
17
  end
14
18
  end
@@ -9,5 +9,9 @@ module MotionPrime
9
9
 
10
10
  element :error_message, type: :error_message, text: proc { observing_errors? and all_errors.join("\n") }
11
11
  after_render :bind_text_input
12
+
13
+ def events_off
14
+ view(:input).off :change
15
+ end
12
16
  end
13
17
  end
@@ -155,7 +155,7 @@ module MotionPrime
155
155
 
156
156
  def load_field(field)
157
157
  field_class = class_factory("#{field[:type]}_field_section", true)
158
- field_class.new(field.merge(screen: screen, table: self))
158
+ field_class.new(field.merge(screen: screen, table: self.weak_ref))
159
159
  end
160
160
 
161
161
  def render_field?(name, options)
@@ -209,6 +209,12 @@ module MotionPrime
209
209
  section.container_height
210
210
  end
211
211
 
212
+ def events_off
213
+ fields.values.each do |section|
214
+ section.events_off
215
+ end
216
+ end
217
+
212
218
  class << self
213
219
  def field(name, options = {}, &block)
214
220
  options[:name] = name
@@ -1,5 +1,5 @@
1
1
  module MotionPrime
2
- class TabbedSection < BaseSection
2
+ class TabbedSection < Section
3
3
  # MotionPrime::TabbedSection is base class for building tabbed views.
4
4
 
5
5
  # == Basic Sample
@@ -5,6 +5,11 @@ module MotionPrime
5
5
  self.table_section = options[:section].try(:weak_ref)
6
6
  end
7
7
 
8
+ # def dealloc
9
+ # pp '@@ dealloc table_delegate'
10
+ # super
11
+ # end
12
+
8
13
  def init_pull_to_refresh
9
14
  return unless block = table_section.class.pull_to_refresh_block
10
15
  table_section.add_pull_to_refresh do
@@ -2,7 +2,7 @@ motion_require './table/refresh_mixin'
2
2
  motion_require './table/table_delegate'
3
3
 
4
4
  module MotionPrime
5
- class TableSection < BaseSection
5
+ class TableSection < Section
6
6
  include TableSectionRefreshMixin
7
7
  include HasStyleChainBuilder
8
8
  include HasSearchBar
@@ -15,10 +15,11 @@ module MotionPrime
15
15
  after_render :init_pull_to_refresh
16
16
  delegate :init_pull_to_refresh, to: :table_delegate
17
17
 
18
- # def dealloc
19
- # pp 'deallocating table. sections count:', @data.try(:count)
20
- # super
21
- # end
18
+ def dealloc
19
+ cancel_block = proc { :cancelled }.weak!
20
+ @preloader_queue.map!(&cancel_block) if @preloader_queue.present?
21
+ super
22
+ end
22
23
 
23
24
  def table_data
24
25
  []
@@ -50,10 +51,18 @@ module MotionPrime
50
51
  @did_appear = false
51
52
  @data = nil
52
53
  @async_loaded_data = nil
53
- @next_portion_starts_from = nil
54
+ @preloader_next_starts_from = nil
54
55
  @preloader_cancelled = false
55
56
  @data_stamp = nil
56
- @queue_states[-1] = :cancelled if @queue_states.present?
57
+ @preloader_queue[-1] = :cancelled if @preloader_queue.present?
58
+ # @ids.each do |id|
59
+ # table_view.dequeueReusableCellWithIdentifier(id)
60
+ # end if @ids
61
+ # table_view.valueForKey('_reusableTableCells').removeAllObjects
62
+
63
+ # releasing table_delegate
64
+ # @table_delegate = nil
65
+ # table_view.delegate = table_delegate
57
66
  end
58
67
 
59
68
  def table_styles
@@ -142,20 +151,16 @@ module MotionPrime
142
151
  element = section.container_element || section.init_container_element(container_element_options_for(index))
143
152
 
144
153
  view = element.render do
145
- rows_for_section(index.section)[index.row].render
154
+ section.render
146
155
  end
147
-
148
- @rendered_cells[index.section][index.row] = view
149
156
  on_row_render(view, index)
150
-
151
- preload_sections_for(index)
152
-
157
+ preload_sections_after(index)
153
158
  view
154
159
  end
155
160
 
156
161
  def render_header(section)
157
162
  return unless options = self.section_header_options.try(:[], section)
158
- self.section_headers[section] ||= BaseHeaderSection.new(options.merge(screen: screen, table: self))
163
+ self.section_headers[section] ||= BaseHeaderSection.new(options.merge(screen: screen, table: self.weak_ref))
159
164
  end
160
165
 
161
166
  def header_for_section(section)
@@ -204,9 +209,6 @@ module MotionPrime
204
209
  end
205
210
 
206
211
  def cell_for_index(table, index)
207
- @rendered_cells ||= []
208
- @rendered_cells[index.section] ||= []
209
-
210
212
  cell = cached_cell(index, table) || render_cell(index, table)
211
213
 
212
214
  # run table view is appeared callback if needed
@@ -255,7 +257,9 @@ module MotionPrime
255
257
 
256
258
  private
257
259
  def display_pending_cells
258
- table_view.visibleCells.each { |cell_view| cell_view.section.display if cell_view.section.pending_display }
260
+ table_view.visibleCells.each do |cell_view|
261
+ cell_view.section.display if cell_view.section.pending_display
262
+ end
259
263
  end
260
264
 
261
265
  def set_table_data
@@ -328,8 +332,8 @@ module MotionPrime
328
332
  rows = [id]
329
333
  end
330
334
  rows.map { |row| "#{section}_#{row}" }
331
- end.flatten
332
- set_data_stamp(keys)
335
+ end
336
+ set_data_stamp(keys.flatten)
333
337
  end
334
338
 
335
339
  def load_sections
@@ -341,45 +345,61 @@ module MotionPrime
341
345
  end
342
346
  end
343
347
 
344
- def preload_sections_for(index)
345
- return if !async_data? || @next_portion_starts_from == false
346
- service = index_service
347
-
348
- load_limit = self.class.async_data_options.try(:[], :preload_rows_count)
349
- @next_portion_starts_from ||= index
350
- start_preload_when_index_loaded = service.sum_index(@next_portion_starts_from, load_limit ? -load_limit/2 : 0)
351
- if service.compare_indexes(index, start_preload_when_index_loaded) >= 0
352
- section = @next_portion_starts_from.section
353
- next_row = @next_portion_starts_from.row
354
- left_to_load = rows_for_section(section).count - next_row
355
-
356
- load_count = [left_to_load, load_limit].compact.min
357
348
 
358
- next_index = @next_portion_starts_from
359
- @preloader_cancelled = false
349
+ # Preloads sections after rendering cell in current sheduled index or given index.
350
+ # TODO: probably should be in separate class.
351
+ #
352
+ # @param index [NSIndexPath] Value of first index to load if current sheduled index not exists.
353
+ # @return [NSIndexPath, Boolean] Index of next sheduled index.
354
+ def preload_sections_after(index)
355
+ return if !async_data? || @preloader_next_starts_from == false
356
+ service = preloader_index_service
360
357
 
361
- @queue_states ||= []
362
-
363
- BW::Reactor.schedule(@queue_states.count) do |queue_id|
364
- @queue_states[queue_id] = :in_progress
365
-
366
- result = load_count.times do |offset|
367
- break if @queue_states[queue_id] == :cancelled
368
- load_cell_by_index(next_index, preload: true)
369
- next_index = service.sum_index(next_index, 1) unless offset == load_count - 1
370
- end
358
+ load_limit = self.class.async_data_options.try(:[], :preload_rows_count)
359
+ @preloader_next_starts_from ||= index
360
+ index_to_start_preloading = service.sum_index(@preloader_next_starts_from, load_limit ? -load_limit/2 : 0)
361
+ if service.compare_indexes(index, index_to_start_preloading) >= 0
362
+ load_count = preload_sections_schedule_next(@preloader_next_starts_from, load_limit)
363
+ @preloader_next_starts_from = service.sum_index(@preloader_next_starts_from, load_count, false)
364
+ else
365
+ false
366
+ end
367
+ end
371
368
 
372
- if result
373
- on_async_data_preloaded(next_index)
374
- @queue_states[queue_id] = :completed
369
+ # Schedules preloading sections starting with given index with given limit.
370
+ # TODO: probably should be in separate class.
371
+ #
372
+ # @param index [NSIndexPath] Value of first index to load.
373
+ # @param limit [Integer] Limit of sections to load.
374
+ # @return [Integer] Count of sections scheduled to load.
375
+ def preload_sections_schedule_next(index, limit)
376
+ service = preloader_index_service
377
+
378
+ left_to_load = rows_for_section(index.section).count - index.row
379
+ load_count = [left_to_load, limit].compact.min
380
+ @preloader_cancelled = false
381
+ @preloader_queue ||= []
382
+
383
+ # TODO: do not release parent_objcets unless finished
384
+ BW::Reactor.schedule(@preloader_queue.count) do |queue_id|
385
+ @preloader_queue[queue_id] = :in_progress
386
+
387
+ result = load_count.times do |offset|
388
+ break if @break_preload || @preloader_queue[queue_id] == :cancelled
389
+ load_cell_by_index(index, preload: true)
390
+ unless offset == load_count - 1
391
+ index = service.sum_index(index, 1)
375
392
  end
376
393
  end
377
-
378
- @next_portion_starts_from = service.sum_index(@next_portion_starts_from, load_count, false)
394
+ if result
395
+ on_async_data_preloaded(index)
396
+ @preloader_queue[queue_id] = :completed
397
+ end
379
398
  end
399
+ load_count
380
400
  end
381
401
 
382
- def index_service
402
+ def preloader_index_service
383
403
  TableDataIndexes.new(@data)
384
404
  end
385
405
 
@@ -0,0 +1,37 @@
1
+ module MotionPrime
2
+ class Logger
3
+ LOGGER_ERROR_LEVEL = 0
4
+ LOGGER_INFO_LEVEL = 1
5
+ LOGGER_DEBUG_LEVEL = 2
6
+
7
+ class_attribute :level
8
+
9
+ class << self
10
+ def error(*args)
11
+ pp(*args) if LOGGER_ERROR_LEVEL <= current_level
12
+ end
13
+
14
+ def info(*args)
15
+ pp(*args) if LOGGER_INFO_LEVEL <= current_level
16
+ end
17
+
18
+ def debug(*args)
19
+ pp(*args) if LOGGER_DEBUG_LEVEL <= current_level
20
+ end
21
+
22
+ def current_level
23
+ current_level = self.level || (Config.logger.level.nil? ? :info : Config.logger.level)
24
+ case current_level.to_s
25
+ when 'error'
26
+ LOGGER_ERROR_LEVEL
27
+ when 'info'
28
+ LOGGER_INFO_LEVEL
29
+ when 'debug'
30
+ LOGGER_DEBUG_LEVE
31
+ else
32
+ 2
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,9 +1,9 @@
1
1
  class MPCellWithSection < UITableViewCell
2
- attr_accessor :section
2
+ attr_reader :section
3
3
 
4
4
  def setSection(section)
5
5
  @section = section.try(:weak_ref)
6
- @section_name = section.name
6
+ @section_name = section.try(:name) # TODO: remove after debug
7
7
  end
8
8
 
9
9
  def drawRect(rect)
@@ -12,7 +12,12 @@ class MPCellWithSection < UITableViewCell
12
12
  end
13
13
 
14
14
  def draw_in(rect)
15
- return unless section
16
- section.draw_in(rect) if section.respond_to?(:draw_in)
15
+ # pp '++ drawing', @section_name, self.object_id
16
+ section.draw_in(rect) if section && section.respond_to?(:draw_in)
17
17
  end
18
+
19
+ # def dealloc
20
+ # pp '--- deallog cell with section', @section_name, self.object_id
21
+ # super
22
+ # end
18
23
  end
@@ -7,7 +7,8 @@ module MotionPrime
7
7
 
8
8
  screens.each_with_index do |screen, index|
9
9
  if screen.is_a?(Hash)
10
- screen, image, title = screen[:screen].try(:weak_ref), screen[:image], screen[:title]
10
+ screen, image, title = screen[:screen], screen[:image], screen[:title]
11
+ screen = Screen.create_with_options(screen).try(:weak_ref)
11
12
  title ||= screen.title
12
13
  image = image.uiimage if image
13
14
  screen.tabBarItem = UITabBarItem.alloc.initWithTitle title, image: image, tag: index
@@ -1,3 +1,3 @@
1
1
  module MotionPrime
2
- VERSION = "0.4.5"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -2,7 +2,7 @@
2
2
  motion_require '../support/mp_cell_with_section'
3
3
  module MotionPrime
4
4
  module Layout
5
- def add_view(klass, options = {}, &block)
5
+ def add_view(klass, options = {}, &block)
6
6
  bounds = if view_stack.empty?
7
7
  options.delete(:parent_view).try(:bounds) || CGRectZero
8
8
  else
@@ -110,6 +110,13 @@ module MotionPrime
110
110
 
111
111
  klass.alloc.initWithStyle style, reuseIdentifier: options.delete(:reuse_identifier)
112
112
  },
113
+ 'MPViewWithSection' => Proc.new{|klass, options|
114
+ if options[:has_drawn_content]
115
+ options[:background_color] = :clear
116
+ options.delete(:gradient)
117
+ end
118
+ klass.alloc.initWithFrame CGRectZero
119
+ },
113
120
  'UISearchBar' => Proc.new{|klass, options|
114
121
  klass = options[:search_field_background_image] ? MPSearchBarCustom : UISearchBar
115
122
  search_bar = klass.alloc.init
data/motion-prime.gemspec CHANGED
@@ -4,7 +4,7 @@ require File.expand_path('../motion-prime/version', __FILE__)
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "motion-prime"
6
6
  spec.version = MotionPrime::VERSION
7
- spec.authors = ["Iskander Haziev"]
7
+ spec.authors = ["Iskander Haziev", "Pavel Feklistov"]
8
8
  spec.email = ["gvalmon@gmail.com"]
9
9
  spec.description = %q{RubyMotion apps development framework}
10
10
  spec.summary = %q{RubyMotion apps development framework}
@@ -1,4 +1,4 @@
1
- describe "base delegate" do
1
+ describe MotionPrime::BaseAppDelegate do
2
2
 
3
3
  before { @subject = BaseDelegate.new }
4
4
 
File without changes