motion-prime 0.3.3 → 0.4.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 (47) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +4 -0
  3. data/Gemfile.lock +1 -1
  4. data/ROADMAP.md +3 -3
  5. data/doc/code/getting_started.rb +6 -5
  6. data/files/app/screens/sidebar_screen.rb +2 -2
  7. data/files/app/sections/sidebar/action.rb +1 -1
  8. data/motion-prime/api_client.rb +1 -1
  9. data/motion-prime/core_ext/kernel.rb +4 -0
  10. data/motion-prime/elements/_content_padding_mixin.rb +12 -4
  11. data/motion-prime/elements/_content_text_mixin.rb +10 -2
  12. data/motion-prime/elements/{base.rb → base_element.rb} +16 -7
  13. data/motion-prime/elements/button.rb +1 -1
  14. data/motion-prime/elements/draw/_draw_background_mixin.rb +20 -9
  15. data/motion-prime/elements/draw/image.rb +2 -2
  16. data/motion-prime/elements/draw/label.rb +7 -6
  17. data/motion-prime/elements/draw.rb +8 -3
  18. data/motion-prime/elements/label.rb +2 -2
  19. data/motion-prime/elements/table_view_cell.rb +7 -0
  20. data/motion-prime/helpers/has_search_bar.rb +1 -1
  21. data/motion-prime/helpers/has_styles.rb +7 -7
  22. data/motion-prime/models/model.rb +1 -1
  23. data/motion-prime/models/sync.rb +10 -10
  24. data/motion-prime/screens/_navigation_mixin.rb +1 -1
  25. data/motion-prime/sections/_draw_mixin.rb +74 -0
  26. data/motion-prime/sections/{base.rb → base_section.rb} +104 -55
  27. data/motion-prime/sections/form/base_field_section.rb +6 -6
  28. data/motion-prime/sections/form/base_header_section.rb +2 -3
  29. data/motion-prime/sections/form.rb +38 -17
  30. data/motion-prime/sections/tabbed.rb +3 -3
  31. data/motion-prime/sections/table.rb +172 -80
  32. data/motion-prime/services/table_data_indexes.rb +51 -0
  33. data/motion-prime/styles/_mixins.rb +8 -0
  34. data/motion-prime/support/dm_cell_with_section.rb +1 -1
  35. data/motion-prime/support/dm_text_field.rb +17 -12
  36. data/motion-prime/support/dm_text_view.rb +10 -23
  37. data/motion-prime/version.rb +1 -1
  38. data/motion-prime/views/layout.rb +4 -2
  39. data/motion-prime/views/styles.rb +2 -0
  40. data/motion-prime/views/view_builder.rb +8 -2
  41. data/motion-prime/views/view_styler.rb +6 -2
  42. metadata +8 -9
  43. data/motion-prime/helpers/cell_section.rb +0 -9
  44. data/motion-prime/sections/draw.rb +0 -93
  45. data/motion-prime/sections/form/text_with_button_field_section.rb +0 -23
  46. data/motion-prime/sections/table/base_cell_section.rb +0 -5
  47. data/motion-prime/sections/table/draw_cell_section.rb +0 -5
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YzZhZGNhZTIzZDliM2I2MzY3ZTE1NjdmODc2NmFmYjkyNjdjN2NhYw==
4
+ ZmRjMGMyMTFiMjJjYjBjYmY4OGMyMDM1YjJiZDRlYTNhMWI0NGJlMw==
5
5
  data.tar.gz: !binary |-
6
- MDQ2ZmI4ZDMzNjI2MDVjOWQ5NDY2ZmFlZGQwM2RmNWYyNDc4N2IyZg==
6
+ MGEzNDAwZDRmZTI1OGJmNGZiM2Y2ODhiMzJlYjAzNjBjYzljYmZmYw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NjA4ZTk1ZmZmYmM4NmU4YWRkN2UwYWEzMWI3ZDJkY2ZlZDdkNjc0MDA2OGE0
10
- ZGQ0ZTM3NGFlNDBiMjRmYzNkMmQyZWQ1MDkzMjRlMzcxYTc3NWJmMGJjODM0
11
- MWVlNzYwMzViNjMxMzU2NjIyNWQxZTJjZTUxMGE0MDNkMmFmOTY=
9
+ OGFkMjM1MGQ3ZjhhOWU2NTY4ZGU4MWI5YjRhYzhkMDZjYmExODYyNjQxMmY4
10
+ MTE2NDM1NzhjNDAzNTRiZGFmZWQyNDE1YWNhYjQwODZiMGRmZmUyZDUwZmJk
11
+ Y2VhODNiYWJjMjRlZGI2Y2Y5NDI5NjdmOThjYjNhNmRiYWUyZWI=
12
12
  data.tar.gz: !binary |-
13
- YTE2MTY4ZTE5YjVkZjgwYWZhYzhkMDQzZmUzYzA3ZWYxZGFjYTAyOGQ1M2U5
14
- MWZlMThkYmIxYTJlN2VhZTE5NWM5OWY0MzlkYmU4NjgwMGRkZjZiNzdlM2Jk
15
- ZTQwMjlkNzA4MmExMjFhNTg3OTc1M2Q4MzQ4MzliMGY4NmYzMmQ=
13
+ OWRhNzY3MjQ1NzY1M2I5MWEwOGYwOTdiZjI4YzdhOTU0Zjc2YzkyYjdlNzc3
14
+ MmFkNzFlZDFjMDg1ODYwMjUyYWMwM2E3ZGVlMzQ1ZDAxOGZiZDFjOWRhZWNh
15
+ ZjIxMTJjOGJlNjQ2NTk3ZGY3MDEzNWE0YWM4MmRkMDdhNWZjMDk=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.4.0
2
+ * Big refactoring and speed improvements.
3
+ * Use BaseSection both for draw and base elements.
4
+
1
5
  === 0.3.3
2
6
  * Screen tab bar support
3
7
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- motion-prime (0.3.3)
4
+ motion-prime (0.4.0)
5
5
  bubble-wrap
6
6
  cocoapods
7
7
  methadone
data/ROADMAP.md CHANGED
@@ -1,12 +1,12 @@
1
- === 0.4.0
1
+ === 0.5.0
2
2
  * rename support/dm_* to support/mp_*
3
3
  * "id" attribute should always be added to model by default
4
4
  * add DSL for ViewStyles#setValue conditions
5
5
  * add auto-symbol-value for Prime::Config.color items
6
6
 
7
- === 0.5.0
7
+ === 0.6.0
8
8
  * add testing framework
9
9
  * add auth backends to ApiClient: password auth and facebook auth
10
10
 
11
- === 0.6.0
11
+ === 0.7.0
12
12
  * add sections/screens/models generator
@@ -21,13 +21,14 @@ end
21
21
  # **3. Create the main screen.**
22
22
  #
23
23
  # You should rewrite the `render` method, which will be runned after opening screen.
24
+ # Note: you must always pass `screen` option, which points to screen to render
24
25
 
25
26
  class MainScreen < Prime::BaseScreen
26
27
  title 'Main screen'
27
28
 
28
29
  def render
29
- @main_section = MyProfileSection.new(model: User.first)
30
- @main_section.render(to: self)
30
+ @main_section = MyProfileSection.new(screen: self, model: User.first)
31
+ @main_section.render
31
32
  end
32
33
  end
33
34
 
@@ -35,7 +36,7 @@ end
35
36
  #
36
37
  # "Section" is something like helper, which contains "Elements".
37
38
  #
38
- # Each element will be added to the parent screen when you run `section.render(to: screen)`
39
+ # Each element will be added to the parent screen when you run `section.render`
39
40
 
40
41
  class MyProfileSection < Prime::BaseSection
41
42
  element :title, text: "Hello World"
@@ -44,10 +45,10 @@ end
44
45
 
45
46
  # **5. Create your first stylesheet file.**
46
47
  #
47
- # Styles will be applied to each element in section.
48
+ # Styles will be applied to each element in section.
48
49
  # The simplest rule by default is: `:section-name_:element-name`.
49
50
  #
50
- # E.g. if you have 'MyProfileSection' (the name for section by default will be - `my_profile`)
51
+ # E.g. if you have 'MyProfileSection' (the name for section by default will be - `my_profile`)
51
52
  # and 'title' element, then you should use `my_profile_title` style name.
52
53
 
53
54
  Prime::Styles.define do
@@ -1,7 +1,7 @@
1
1
  class SidebarScreen < Prime::BaseScreen
2
2
  def render
3
- @main_section = SidebarTableSection.new()
4
- @main_section.render(to: self)
3
+ @main_section = SidebarTableSection.new(screen: self)
4
+ @main_section.render
5
5
  end
6
6
 
7
7
  def open_home
@@ -1,4 +1,4 @@
1
- class SidebarActionSection < Prime::BaseCellSection
1
+ class SidebarActionSection < Prime::BaseSection
2
2
  container height: 43
3
3
  element :title, text: proc { model[:title] }
4
4
  element :arrow, type: :image
@@ -8,7 +8,7 @@ class ApiClient
8
8
  def parse_json(text)
9
9
  BW::JSON.parse(text)
10
10
  rescue
11
- puts "Can't parse json: #{text}"
11
+ NSLog("Can't parse json: #{text}")
12
12
  false
13
13
  end
14
14
 
@@ -1,4 +1,8 @@
1
1
  class Kernel
2
+ def pp(*attrs)
3
+ NSLog([*attrs].map(&:inspect).join(' ') + ' ' + self.class.to_s)
4
+ end
5
+
2
6
  def class_name_without_kvo
3
7
  self.class.name.gsub(/^NSKVONotifying_/, '')
4
8
  end
@@ -32,16 +32,24 @@ module MotionPrime
32
32
  content_padding_left + content_padding_right
33
33
  end
34
34
 
35
- def content_outer_height
36
- height = content_padding_height + content_height
35
+ def content_outer_height(cached = false)
36
+ height = content_padding_height + (cached ? cached_content_height : content_height)
37
37
  [[height, computed_options[:min_outer_height]].compact.max, computed_options[:max_outer_height]].compact.min
38
38
  end
39
39
 
40
- def content_outer_width
41
- width = content_padding_width + content_width
40
+ def cached_content_outer_height
41
+ content_outer_height(true)
42
+ end
43
+
44
+ def content_outer_width(cached = false)
45
+ width = content_padding_width + (cached ? cached_content_width : content_width)
42
46
  [[width, computed_options[:min_outer_width]].compact.max, computed_options[:max_outer_width]].compact.min
43
47
  end
44
48
 
49
+ def cached_content_outer_width
50
+ content_outer_width(true)
51
+ end
52
+
45
53
  def default_padding_for(side)
46
54
  view_class.constantize.send(:"default_padding_#{side}")
47
55
  end
@@ -13,14 +13,22 @@ module MotionPrime
13
13
  return min if content_text.blank?
14
14
 
15
15
  rect = get_content_rect(Float::MAX)
16
- [[rect.size.width.ceil, max].compact.min, min].max.ceil
16
+ @content_width = [[rect.size.width.ceil, max].compact.min, min].max.ceil
17
+ end
18
+
19
+ def cached_content_width
20
+ @content_width ||= content_width
17
21
  end
18
22
 
19
23
  def content_height
20
24
  min, max = computed_options[:min_height].to_f, computed_options[:max_height]
21
25
  return min if content_text.blank?
22
26
  rect = get_content_rect(computed_options[:width])
23
- [[rect.size.height.ceil, max].compact.min, min].max.ceil
27
+ @content_height = [[rect.size.height.ceil, max].compact.min, min].max.ceil
28
+ end
29
+
30
+ def cached_content_height
31
+ @content_height ||= content_height
24
32
  end
25
33
 
26
34
  private
@@ -16,23 +16,25 @@ module MotionPrime
16
16
 
17
17
  def initialize(options = {})
18
18
  @options = options
19
+ @screen = options[:screen]
19
20
  @section = options[:section]
20
21
  @name = options[:name]
21
22
  @block = options[:block]
22
23
  @view_class = options[:view_class] || "UIView"
23
- @view_name = self.class_name_without_kvo.demodulize.underscore.gsub('_element', '')
24
+ @view_name = self.class_name_without_kvo.demodulize.underscore.gsub(/(_draw)?_element/, '')
24
25
  end
25
26
 
26
27
  def render(options = {}, &block)
27
- @screen = options[:to]
28
28
  run_callbacks :render do
29
29
  render!(&block)
30
30
  end
31
31
  end
32
32
 
33
33
  def render!(&block)
34
- @view = screen.add_view view_class.constantize, computed_options, &block
35
- @view
34
+ screen.add_view view_class.constantize, computed_options do |view|
35
+ @view = view
36
+ block.try(:call, view, self)
37
+ end
36
38
  end
37
39
 
38
40
  # Lazy-computing options
@@ -45,7 +47,7 @@ module MotionPrime
45
47
  @computed_options ||= {}
46
48
  block_options = compute_block_options || {}
47
49
  compute_style_options(options, block_options)
48
- @computed_options.merge!(options.except(:section, :name, :block, :view_class))
50
+ @computed_options.merge!(options.except(:screen, :name, :block, :view_class))
49
51
  @computed_options.merge!(block_options)
50
52
  normalize_options(@computed_options, section, %w[text placeholder font title_label padding padding_left padding_right min_width min_outer_width max_width max_outer_width width left right])
51
53
  end
@@ -60,7 +62,7 @@ module MotionPrime
60
62
 
61
63
  def compute_style_options(*style_sources)
62
64
  has_errors = section.respond_to?(:observing_errors?) && observing_errors? && has_errors?
63
- is_cell_section = section.is_a?(BaseCellSection) || section.is_a?(DrawCellSection)
65
+ is_cell_section = section.respond_to?(:cell_name)
64
66
 
65
67
  @styles = []
66
68
  if is_cell_section
@@ -132,7 +134,7 @@ module MotionPrime
132
134
  compute_options!
133
135
  view.try(:removeFromSuperview)
134
136
  @view = nil
135
- render(to: screen)
137
+ render
136
138
  end
137
139
 
138
140
  def hide
@@ -143,6 +145,13 @@ module MotionPrime
143
145
  view.hidden = false
144
146
  end
145
147
 
148
+ def bind_gesture(action, receiver = nil)
149
+ receiver ||= self
150
+ single_tap = UITapGestureRecognizer.alloc.initWithTarget(receiver, action: action)
151
+ view.addGestureRecognizer single_tap
152
+ view.setUserInteractionEnabled true
153
+ end
154
+
146
155
  class << self
147
156
  def factory(type, options = {})
148
157
  class_name = "#{type.classify}Element"
@@ -8,7 +8,7 @@ module MotionPrime
8
8
  def size_to_fit
9
9
  if computed_options[:size_to_fit] || style_options[:size_to_fit]
10
10
  if computed_options[:width]
11
- view.setHeight content_outer_height
11
+ view.setHeight cached_content_outer_height
12
12
  end
13
13
  end
14
14
  end
@@ -1,23 +1,34 @@
1
1
  module MotionPrime
2
2
  module DrawBackgroundMixin
3
- def draw_background_in(rect, options)
3
+ def draw_background_in(draw_rect, options)
4
+
4
5
  bg_color = options[:background_color]
5
6
  border_radius = options[:layer].try(:[], :corner_radius)
6
7
  border_width = options[:layer].try(:[], :border_width).to_f
7
8
  border_color = options[:layer].try(:[], :border_color) || bg_color || :black
8
9
 
9
- if bg_color || border_width > 0
10
- context = UIGraphicsGetCurrentContext()
11
- CGContextSetFillColorWithColor(context, bg_color.uicolor.cgcolor) if bg_color
12
- CGContextSetLineWidth(context, border_width) if border_width > 0
13
- CGContextSetStrokeColorWithColor(context, border_color.uicolor.cgcolor) if border_color
10
+ rect = CGRectInset(draw_rect, -(border_width - 1)*0.5, -(border_width - 1)*0.5)
14
11
 
12
+ if bg_color || border_width > 0
15
13
  if border_radius
16
14
  bezierPath = UIBezierPath.bezierPathWithRoundedRect rect, cornerRadius: border_radius
17
- bezierPath.stroke if border_width > 0
18
- bezierPath.fill if bg_color
15
+ if border_width > 0
16
+ bezierPath.lineWidth = border_width
17
+ border_color.uicolor.setStroke
18
+ bezierPath.stroke
19
+ end
20
+ if bg_color
21
+ bg_color.uicolor.setFill
22
+ bezierPath.fill
23
+ end
19
24
  else
20
- CGContextStrokeRect(context, rect) if border_width > 0
25
+ context = UIGraphicsGetCurrentContext()
26
+ if border_width > 0 && border_color
27
+ CGContextSetLineWidth(context, border_width)
28
+ CGContextSetStrokeColorWithColor(context, border_color.uicolor.cgcolor)
29
+ CGContextStrokeRect(context, rect)
30
+ end
31
+ CGContextSetFillColorWithColor(context, bg_color.uicolor.cgcolor) if bg_color
21
32
  CGContextFillRect(context, rect) if bg_color
22
33
  end
23
34
  end
@@ -16,8 +16,8 @@ module MotionPrime
16
16
 
17
17
  image_rect = CGRectInset(image_rect, -0.5, -0.5)
18
18
  border_width = options[:layer].try(:[], :border_width).to_f
19
- background_rect = CGRectInset(image_rect, -(border_width - 1)*0.5, -(border_width - 1)*0.5)
20
- draw_background_in(background_rect, options)
19
+
20
+ draw_background_in(image_rect, options)
21
21
 
22
22
  # draw already initialized image
23
23
  if image_data
@@ -10,10 +10,11 @@ module MotionPrime
10
10
  end
11
11
 
12
12
  def draw_in(rect)
13
- return if computed_options[:hidden]
14
13
  size_to_fit_if_needed or set_text_position
15
14
  options = computed_options
16
15
 
16
+ return if computed_options[:hidden]
17
+
17
18
  # render background and border
18
19
  background_rect = CGRectMake(computed_left, computed_top, computed_outer_width, computed_outer_height)
19
20
  draw_background_in(background_rect, options)
@@ -22,8 +23,8 @@ module MotionPrime
22
23
  color = (options[:text_color] || :black).uicolor
23
24
  font = (options[:font] || :system).uifont
24
25
  alignment = (options.has_key?(:text_alignment) ? options[:text_alignment] : :left).uitextalignment
25
- line_break_mode = (options.has_key?(:line_break_mode) ? options[:line_break_mode] : :wordwrap).uilinebreakmode
26
- label_text = options[:text].to_s
26
+ line_break_mode = (options.has_key?(:line_break_mode) ? options[:line_break_mode] : :tailtruncation).uilinebreakmode
27
+ label_text = options[:text].to_s.gsub(/^[\n\r]+/, '')
27
28
 
28
29
  top_left_corner = CGPointMake(computed_inner_left, computed_inner_top)
29
30
  if options[:number_of_lines].to_i.zero?
@@ -66,9 +67,9 @@ module MotionPrime
66
67
 
67
68
  def size_to_fit_if_needed
68
69
  if computed_options[:size_to_fit]
69
- @computed_options[:width] ||= content_outer_width
70
+ computed_options[:width] ||= cached_content_outer_width
70
71
  if computed_options[:width]
71
- @computed_options[:height] = content_outer_height
72
+ computed_options[:height] ||= cached_content_outer_height
72
73
  end
73
74
  reset_computed_values
74
75
  true
@@ -78,7 +79,7 @@ module MotionPrime
78
79
  def set_text_position
79
80
  if computed_options.slice(:padding_top, :padding_bottom, :padding).none?
80
81
  computed_options[:width] ||= computed_width
81
- @padding_top = (computed_outer_height - content_height)/2
82
+ @padding_top = (computed_outer_height - cached_content_height)/2
82
83
  # @padding_top += 1 unless @padding_top.zero?
83
84
  end
84
85
  end
@@ -47,13 +47,18 @@ module MotionPrime
47
47
  def computed_right; computed_left + computed_width end
48
48
  def computed_inner_right; computed_right - content_padding_right end
49
49
 
50
-
51
- def reset_computed_values
52
- @computed_frame = nil
50
+ def bind_gesture(action, receiver = nil)
51
+ section.bind_gesture_on_container_for(self, action, receiver)
53
52
  end
54
53
 
54
+ private
55
+ def reset_computed_values
56
+ @computed_frame = nil
57
+ end
58
+
55
59
  class << self
56
60
  def factory(type, options = {})
61
+ return unless %w[View Label Image].include?(type.classify)
57
62
  class_name = "#{type.classify}DrawElement"
58
63
  "MotionPrime::#{class_name}".constantize.new(options)
59
64
  end
@@ -13,7 +13,7 @@ module MotionPrime
13
13
  def size_to_fit
14
14
  if computed_options[:size_to_fit] || style_options[:size_to_fit]
15
15
  if computed_options[:width]
16
- view.setHeight([content_outer_height, computed_options[:height]].compact.min)
16
+ view.setHeight([cached_content_outer_height, computed_options[:height]].compact.min)
17
17
  else
18
18
  view.sizeToFit
19
19
  # we should re-set values, because sizeToFit do not use padding
@@ -25,7 +25,7 @@ module MotionPrime
25
25
 
26
26
  def size_to_fit_if_needed
27
27
  if computed_options[:size_to_fit] && computed_options[:width]
28
- @computed_options[:height_to_fit] = content_outer_height
28
+ @computed_options[:height_to_fit] = cached_content_outer_height
29
29
  end
30
30
  end
31
31
  end
@@ -0,0 +1,7 @@
1
+ module MotionPrime
2
+ class TableViewCellElement < BaseElement
3
+ def view_class
4
+ "DMCellWithSection"
5
+ end
6
+ end
7
+ end
@@ -16,7 +16,7 @@ module MotionPrime
16
16
  @search_callback = block
17
17
  search_bar
18
18
  rescue
19
- puts "can't add search bar to #{self.class_name_without_kvo}"
19
+ NSLog("can't add search bar to #{self.class_name_without_kvo}")
20
20
  end
21
21
 
22
22
  def create_search_bar(options = {})
@@ -4,13 +4,7 @@ module MotionPrime
4
4
  colors = options[:colors].map(&:uicolor).map(&:cgcolor)
5
5
  locations = options[:locations] if options[:locations]
6
6
 
7
- if self.is_a?(DrawSection)
8
- color_space = CGColorSpaceCreateDeviceRGB()
9
- locations_pointer = Pointer.new(:float, 2)
10
- locations.each_with_index { |loc, id| locations_pointer[id] = loc }
11
- gradient = CGGradientCreateWithColors(color_space, colors, locations_pointer)
12
- # CGColorSpaceRelease(color_space)
13
- else
7
+ if self.is_a?(ViewStyler)
14
8
  gradient = CAGradientLayer.layer
15
9
 
16
10
  gradient.frame = if options[:frame_width]
@@ -21,6 +15,12 @@ module MotionPrime
21
15
 
22
16
  gradient.colors = colors
23
17
  gradient.locations = locations
18
+ else
19
+ color_space = CGColorSpaceCreateDeviceRGB()
20
+ locations_pointer = Pointer.new(:float, 2)
21
+ locations.each_with_index { |loc, id| locations_pointer[id] = loc }
22
+ gradient = CGGradientCreateWithColors(color_space, colors, locations_pointer)
23
+ # CGColorSpaceRelease(color_space)
24
24
  end
25
25
  gradient
26
26
  end
@@ -31,7 +31,7 @@ module MotionPrime
31
31
  if has_attribute?(k)
32
32
  assign_attribute(k, v) unless options[:skip_nil_values] && v.nil?
33
33
  elsif options[:check_attribute_presence]
34
- puts "unknown attribute: #{k}"
34
+ NSLog("unknown attribute: #{k}")
35
35
  else
36
36
  raise(NoMethodError, "unknown attribute: #{k}")
37
37
  end
@@ -56,18 +56,18 @@ module MotionPrime
56
56
 
57
57
  fetch_with_url url do |data, status_code|
58
58
  save if sync_options[:save]
59
- block.call(data, status_code) if use_callback
59
+ block.call(data, status_code, data) if use_callback
60
60
  end if should_fetch
61
61
 
62
62
  update_with_url url, sync_options do |data, status_code|
63
63
  save if sync_options[:save] && status_code.to_s =~ /20\d/
64
64
  # run callback only if it wasn't run on fetch
65
- block.call(data, status_code) if use_callback && !should_fetch
65
+ block.call(data, status_code, data) if use_callback && !should_fetch
66
66
  end if should_update
67
67
 
68
68
  fetch_associations(sync_options) do |data, status_code|
69
69
  # run callback only if it wasn't run on fetch or update
70
- block.call(data, status_code) if use_callback && !should_fetch && !should_update
70
+ block.call(data, status_code, data) if use_callback && !should_fetch && !should_update
71
71
  end if should_fetch_associations
72
72
  end
73
73
 
@@ -76,7 +76,7 @@ module MotionPrime
76
76
  use_callback = block_given?
77
77
  api_client.get(url) do |data, status_code|
78
78
  fetch_with_attributes(data, &block) if data.present?
79
- block.call(data, status_code) if use_callback
79
+ block.call(data, status_code, data) if use_callback
80
80
  end
81
81
  end
82
82
 
@@ -98,7 +98,7 @@ module MotionPrime
98
98
  if update_from_response && status_code.to_s =~ /20\d/ && data.is_a?(Hash)
99
99
  set_attributes_from_response(data)
100
100
  end
101
- block.call(data, status_code) if use_callback
101
+ block.call(data, status_code, data) if use_callback
102
102
  end
103
103
  end
104
104
 
@@ -153,7 +153,7 @@ module MotionPrime
153
153
  old_collection = self.send(key)
154
154
 
155
155
  use_callback = block_given?
156
- puts "SYNC: started sync for #{key} in #{self.class_name_without_kvo}"
156
+ NSLog("SYNC: started sync for #{key} in #{self.class_name_without_kvo}")
157
157
  api_client.get normalize_sync_url(options[:sync_url]) do |response, status_code|
158
158
  data = options[:sync_key] && response ? response[options[:sync_key]] : response
159
159
  if data
@@ -174,10 +174,10 @@ module MotionPrime
174
174
  end
175
175
  end
176
176
  save if sync_options[:save]
177
- puts "SYNC: finished sync for #{key} in #{self.class_name_without_kvo}"
177
+ NSLog("SYNC: finished sync for #{key} in #{self.class_name_without_kvo}")
178
178
  block.call(data, status_code, response) if use_callback
179
179
  else
180
- puts "SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}"
180
+ NSLog("SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}")
181
181
  block.call(data, status_code, response) if use_callback
182
182
  end
183
183
  end
@@ -185,7 +185,7 @@ module MotionPrime
185
185
 
186
186
  def fetch_has_one(key, options = {}, &block)
187
187
  use_callback = block_given?
188
- puts "SYNC: started sync for #{key} in #{self.class_name_without_kvo}"
188
+ NSLog("SYNC: started sync for #{key} in #{self.class_name_without_kvo}")
189
189
  api_client.get normalize_sync_url(options[:sync_url]) do |response, status_code|
190
190
  data = options.has_key?(:sync_key) ? response[options[:sync_key]] : response
191
191
  if data.present?
@@ -198,7 +198,7 @@ module MotionPrime
198
198
  model.save if sync_options[:save]
199
199
  block.call(data, status_code, response) if use_callback
200
200
  else
201
- puts "SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}"
201
+ NSLog("SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}")
202
202
  block.call(data, status_code, response) if use_callback
203
203
  end
204
204
  end
@@ -25,7 +25,7 @@ module MotionPrime
25
25
  screen
26
26
  end
27
27
 
28
-
28
+
29
29
  def close_screen(args = {})
30
30
  args[:animated] = args.has_key?(:animated) ? args[:animated] : true
31
31
  # Pop current view, maybe with arguments, if in navigation controller
@@ -0,0 +1,74 @@
1
+ module MotionPrime
2
+ module DrawMixin
3
+ include HasStyles
4
+ attr_accessor :container_element, :container_gesture_recognizers
5
+
6
+ def container_view
7
+ container_element.try(:view)
8
+ end
9
+
10
+ def draw_in(rect)
11
+ draw_background(rect)
12
+ draw_elements(rect)
13
+ end
14
+
15
+ def bind_gesture_on_container_for(element, action, receiver = nil)
16
+ self.container_gesture_recognizers ||= begin
17
+ set_container_gesture_recognizer
18
+ []
19
+ end
20
+ self.container_gesture_recognizers << {element: element, action: action, receiver: receiver}
21
+ end
22
+
23
+ private
24
+ def set_container_gesture_recognizer
25
+ single_tap = UITapGestureRecognizer.alloc.initWithTarget(self, action: 'on_container_tap_gesture:')
26
+ single_tap.cancelsTouchesInView = false
27
+ container_view.addGestureRecognizer single_tap
28
+ container_view.setUserInteractionEnabled true
29
+ end
30
+
31
+ def on_container_tap_gesture(recognizer)
32
+ target = Array.wrap(container_gesture_recognizers).detect do |gesture_data|
33
+ CGRectContainsPoint(gesture_data[:element].computed_frame, recognizer.locationInView(container_view))
34
+ end
35
+ (target[:receiver] || self).send(target[:action], recognizer, target[:element]) if target
36
+ end
37
+
38
+ def draw_elements(rect)
39
+ elements_to_draw.each do |key, element|
40
+ element.draw_in(rect)
41
+ end
42
+ end
43
+
44
+ def view_style_options
45
+ @view_style_options ||= begin
46
+ options = Styles.for(container_options[:styles])
47
+ normalize_options(options)
48
+ options
49
+ end
50
+ end
51
+
52
+ def draw_background(rect)
53
+ options = container_element.computed_options
54
+
55
+ if gradient_options = options[:gradient]
56
+ start_point = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect))
57
+ end_point = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect))
58
+
59
+ context = UIGraphicsGetCurrentContext()
60
+ # CGContextSaveGState(context)
61
+ CGContextAddRect(context, rect)
62
+ CGContextClip(context)
63
+ gradient = prepare_gradient(gradient_options)
64
+ CGContextDrawLinearGradient(context, gradient, start_point, end_point, 0)
65
+ # CGContextRestoreGState(context)
66
+ elsif background_color = options[:background_color]
67
+ unless background_color.uicolor == :clear.uicolor
68
+ background_color.uicolor.setFill
69
+ UIRectFill(rect)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end