motion-prime 0.4.5 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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