motion-prime 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -0
  3. data/Gemfile.lock +2 -2
  4. data/ROADMAP.md +1 -0
  5. data/files/Gemfile +1 -1
  6. data/motion-prime/api_client.rb +3 -3
  7. data/motion-prime/elements/_content_text_mixin.rb +1 -0
  8. data/motion-prime/elements/_text_mixin.rb +5 -0
  9. data/motion-prime/elements/draw.rb +21 -6
  10. data/motion-prime/elements/draw/_draw_background_mixin.rb +68 -4
  11. data/motion-prime/elements/draw/image.rb +4 -6
  12. data/motion-prime/elements/draw/label.rb +20 -12
  13. data/motion-prime/elements/draw/view.rb +1 -0
  14. data/motion-prime/models/_association_mixin.rb +4 -3
  15. data/motion-prime/models/_sync_mixin.rb +2 -1
  16. data/motion-prime/models/association_collection.rb +2 -5
  17. data/motion-prime/screens/_navigation_mixin.rb +1 -1
  18. data/motion-prime/screens/controllers/tab_bar_controller.rb +4 -4
  19. data/motion-prime/screens/extensions/_navigation_bar_mixin.rb +15 -5
  20. data/motion-prime/sections/_async_table_mixin.rb +8 -2
  21. data/motion-prime/sections/_draw_section_mixin.rb +1 -1
  22. data/motion-prime/sections/_section_with_container_mixin.rb +1 -0
  23. data/motion-prime/sections/abstract_collection.rb +7 -0
  24. data/motion-prime/sections/base_section.rb +1 -1
  25. data/motion-prime/sections/form.rb +0 -8
  26. data/motion-prime/sections/form/base_field_section.rb +1 -1
  27. data/motion-prime/sections/form/form_delegate.rb +0 -32
  28. data/motion-prime/sections/table.rb +1 -1
  29. data/motion-prime/sections/table/table_delegate.rb +31 -0
  30. data/motion-prime/support/consts.rb +8 -1
  31. data/motion-prime/version.rb +1 -1
  32. data/motion-prime/views/_frame_calculator_mixin.rb +0 -1
  33. data/motion-prime/views/view_builder.rb +7 -5
  34. data/motion-prime/views/view_styler.rb +8 -5
  35. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c05d314976c62a856091891705c135ec7efcec22
4
- data.tar.gz: c36d99bc5fbd5c2220d0eac3677d87dbc0acf4b8
3
+ metadata.gz: 45140a3e0294c388e06a65d8984b3178d3a61860
4
+ data.tar.gz: bbdb962a185668be9c8788616fd562697b4dc80f
5
5
  SHA512:
6
- metadata.gz: 89864fab09b0b64a7c1ad1610300141c5ae60296a4a858e7abb83ceecf1277ebd3ff027886a061e1e022e1df551e9270b24f435a12f33d34973e7d4940d72e35
7
- data.tar.gz: 6c83f9726a57b620a1d2f93fd0e8e8b2089d3e71de9f5bea27acd279f98ad9a9f536bd247d1b4fd42822cc31341510d3ce82316eba8b49314ca8a71ee7dc5829
6
+ metadata.gz: 29e217defff9f85b314495158591cd4bb0215d58f86e3bee2e7660fd4e70e36668c035917f9589345425527d3f10edfd02d57255bfd7608937279b09203682cc
7
+ data.tar.gz: a459b509909885a8b77d71f94a4cb02cb12e91f56b9c9f91c24b1e1c863d9ba073b105258908fc6648da2487d8225638a98bc34b3bc479ec55f30a7c3f29b78d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ === 1.0.5
2
+ * Bug fixes
3
+
1
4
  === 1.0.4
2
5
  * Multiple bug fixes
3
6
  * Model#save will be performed on main thread (now you can fetch models in thread)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- motion-prime (1.0.4)
4
+ motion-prime (1.0.5)
5
5
  activesupport
6
6
  afmotion (~> 2.1.0)
7
7
  bubble-wrap (~> 1.6.0)
@@ -51,7 +51,7 @@ GEM
51
51
  fuzzy_match (2.0.4)
52
52
  i18n (0.6.9)
53
53
  json_pure (1.8.1)
54
- methadone (1.4.0)
54
+ methadone (1.5.1)
55
55
  bundler
56
56
  motion-cocoapods (1.4.1)
57
57
  cocoapods (>= 0.32.1)
data/ROADMAP.md CHANGED
@@ -15,6 +15,7 @@
15
15
  * create "display_network_error" extension.
16
16
  * add different templates. some templates should be more like final app.
17
17
  * add size_to_fit support for images.
18
+ * simplify border radius for common case
18
19
 
19
20
  === 1.2.0
20
21
  * Move api_client and model sync mixin to prime_model_sync gem.
data/files/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
3
  gem 'motion-cocoapods', '~> 1.4.1'
4
- gem 'motion-prime', '1.0.4'
4
+ gem 'motion-prime', '1.0.5'
5
5
 
6
6
  # add reside menu for sidebar support
7
7
  # gem 'prime_reside_menu', '~> 0.1.4'
@@ -80,7 +80,7 @@ class ApiClient
80
80
  elsif progress
81
81
  # handle progress
82
82
  elsif !response.success? && allow_queue?(method, path, options)
83
- queue(method: method, path: path, params: params)
83
+ queue(method: method, path: path, params: data)
84
84
  elsif response.operation.response.nil?
85
85
  block.call if use_callback
86
86
  else
@@ -123,9 +123,9 @@ class ApiClient
123
123
  end
124
124
 
125
125
  def queue(item)
126
- queue_list = user_defaults['api_client_queue'].clone || []
126
+ queue_list = MotionPrime::JSON.parse(user_defaults['api_client_queue']) || []
127
127
  queue_list.push(item)
128
- user_defaults['api_client_queue'] = queue_list
128
+ user_defaults['api_client_queue'] = MotionPrime::JSON.generate(queue_list)
129
129
  end
130
130
 
131
131
  # TODO: temporary solution, add real caching system here
@@ -115,6 +115,7 @@ module MotionPrime
115
115
  normalize_object(font, section || self)
116
116
  end
117
117
 
118
+ # FIXME: does not work when #update_with_options is called
118
119
  def input_value_text
119
120
  view && !is_a?(DrawElement) ? view.text : (computed_options[:html] || computed_options[:text])
120
121
  end
@@ -33,6 +33,7 @@ module MotionPrime
33
33
  prepared_text = NSMutableAttributedString.alloc.initWithString(options[:text].to_s, attributes: attributes)
34
34
  underline_range = options[:underline]
35
35
  fragment_color = options[:fragment_color]
36
+ fragment_font = options[:fragment_font]
36
37
  if paragrah_style && (underline_range || fragment_color) && options.fetch(:number_of_lines, 1) == 1
37
38
  Prime.logger.debug "If attributed text has paragraph style and underline - you must set number of lines != 1"
38
39
  end
@@ -44,6 +45,10 @@ module MotionPrime
44
45
  if fragment_color
45
46
  prepared_text.addAttributes({NSForegroundColorAttributeName => fragment_color[:color].uicolor}, range: fragment_color[:range])
46
47
  end
48
+ if fragment_font
49
+ prepared_text.addAttributes({NSFontAttributeName => fragment_font[:font].uifont}, range: fragment_font[:range])
50
+ end
51
+
47
52
  prepared_text
48
53
  end
49
54
 
@@ -10,18 +10,32 @@ module MotionPrime
10
10
  def draw_options
11
11
  options = computed_options
12
12
  background_color = options[:background_color].try(:uicolor)
13
+ layer_options = options[:layer] || {}
14
+ corner_radius = layer_options[:corner_radius].to_f
15
+
16
+ layer_options.delete(:masks_to_bounds) if layer_options[:masks_to_bounds].nil?
17
+ options.delete(:clips_to_bounds) if options[:clips_to_bounds].nil?
18
+ masks_to_bounds = layer_options.fetch(:masks_to_bounds, options.fetch(:clips_to_bounds, corner_radius > 0))
13
19
  {
14
20
  rect: CGRectMake(frame_left, frame_top, frame_outer_width, frame_outer_height),
15
21
  background_color: background_color,
16
- masks_to_bounds: options[:layer].try(:[], :masks_to_bounds) || options[:clips_to_bounds],
17
- corner_radius: options[:layer].try(:[], :corner_radius).to_f,
18
- border_width: options[:layer].try(:[], :border_width).to_f,
19
- border_color: options[:layer].try(:[], :border_color).try(:uicolor) || background_color,
20
- border_sides: options[:layer].try(:[], :border_sides),
21
- dashes: options[:layer].try(:[], :dashes),
22
+ masks_to_bounds: masks_to_bounds,
23
+ corner_radius: corner_radius,
24
+ rounded_corners: layer_options[:rounded_corners],
25
+ border_width: layer_options[:border_width].to_f,
26
+ border_color: layer_options[:border_color].try(:uicolor) || background_color,
27
+ border_sides: layer_options[:border_sides],
28
+ dashes: layer_options[:dashes]
22
29
  }
23
30
  end
24
31
 
32
+ def draw_in(rect)
33
+ if @_prev_rect_size && @_prev_rect_size != rect.size
34
+ reset_computed_values
35
+ end
36
+ @_prev_rect_size = rect.size
37
+ end
38
+
25
39
  def render!; end
26
40
 
27
41
  def on_container_render
@@ -59,6 +73,7 @@ module MotionPrime
59
73
  end
60
74
 
61
75
  def rerender!(changed_options = [])
76
+ @_original_options = nil
62
77
  section.cached_draw_image = nil
63
78
  view.try(:setNeedsDisplay)
64
79
  end
@@ -3,7 +3,7 @@ module MotionPrime
3
3
  def draw_background_in_context(context = nil)
4
4
  context ||= UIGraphicsGetCurrentContext()
5
5
  options = draw_options
6
- rect, background_color, border_width, border_color, border_sides, corner_radius, dashes_array = options.slice(:rect, :background_color, :border_width, :border_color, :border_sides, :corner_radius, :dashes).values
6
+ rect, background_color, border_width, border_color, border_sides, corner_radius, dashes_array, rounded_corners = options.slice(:rect, :background_color, :border_width, :border_color, :border_sides, :corner_radius, :dashes, :rounded_corners).values
7
7
 
8
8
  return unless background_color || border_width > 0
9
9
 
@@ -15,7 +15,7 @@ module MotionPrime
15
15
  dashes_array.each_with_index { |length, i| dashes[i] = length }
16
16
  end
17
17
 
18
- if corner_radius > 0
18
+ if corner_radius > 0 && !rounded_corners
19
19
  bezier_path = UIBezierPath.bezierPathWithRoundedRect rect, cornerRadius: corner_radius
20
20
  UIGraphicsPushContext(context)
21
21
  bezier_path.setLineDash(dashes, count: dashes_array.count, phase: 0) if dashes
@@ -29,11 +29,24 @@ module MotionPrime
29
29
  bezier_path.fill
30
30
  end
31
31
  UIGraphicsPopContext()
32
+ elsif corner_radius > 0
33
+ CGContextSetLineDash(context, dashes_array.count, dashes, 0) if dashes
34
+ CGContextSetLineWidth(context, border_width) if border_width > 0
35
+ CGContextSetStrokeColorWithColor(context, border_color.uicolor.cgcolor) if border_color
36
+ draw_rect_in_context(context, rect: rect, radius: corner_radius, rounded_corners: rounded_corners)
37
+ CGContextSaveGState(context)
38
+ CGContextClip(context)
39
+ if background_color
40
+ CGContextSetFillColorWithColor(context, background_color.uicolor.cgcolor)
41
+ CGContextFillRect(context, rect)
42
+ end
43
+ CGContextRestoreGState(context)
32
44
  else
33
45
  if border_width > 0 && border_color
34
46
  CGContextSetLineDash(context, dashes_array.count, dashes, 0) if dashes
35
47
  CGContextSetLineWidth(context, border_width)
36
48
  CGContextSetStrokeColorWithColor(context, border_color.uicolor.cgcolor)
49
+
37
50
  if border_sides.present?
38
51
  points = [
39
52
  [rect.origin.x, rect.origin.y],
@@ -67,9 +80,60 @@ module MotionPrime
67
80
  CGContextStrokeRect(context, rect)
68
81
  end
69
82
  end
70
- CGContextSetFillColorWithColor(context, background_color.uicolor.cgcolor) if background_color
71
- CGContextFillRect(context, rect) if background_color
83
+
84
+ if background_color
85
+ CGContextSetFillColorWithColor(context, background_color.uicolor.cgcolor)
86
+ CGContextFillRect(context, rect)
87
+ end
72
88
  end
73
89
  end
90
+
91
+ def draw_rect_in_context(context, options)
92
+ rect = options.fetch(:rect)
93
+ radius = options.fetch(:radius, 0)
94
+ rounded_corners = options[:rounded_corners] || [:top_left, :top_right, :bottom_right, :bottom_left]
95
+
96
+ CGContextBeginPath(context)
97
+
98
+ x_left = rect.origin.x
99
+ x_left_center = x_left + radius
100
+ x_right_center = x_left + rect.size.width - radius
101
+ x_right = x_left + rect.size.width
102
+ y_top = rect.origin.y
103
+ y_top_center = y_top + radius
104
+ y_bottom_center = y_top + rect.size.height - radius
105
+ y_bottom = y_top + rect.size.height
106
+ CGContextMoveToPoint(context, x_left, y_top_center)
107
+
108
+ if rounded_corners.include?(:top_left)
109
+ CGContextAddArcToPoint(context, x_left, y_top, x_left_center, y_top, radius)
110
+ else
111
+ CGContextAddLineToPoint(context, x_left, y_top)
112
+ end
113
+ CGContextAddLineToPoint(context, x_right_center, y_top)
114
+
115
+ if rounded_corners.include?(:top_right)
116
+ CGContextAddArcToPoint(context, x_right, y_top, x_right, y_top_center, radius)
117
+ else
118
+ CGContextAddLineToPoint(context, x_right, y_top)
119
+ end
120
+ CGContextAddLineToPoint(context, x_right, y_bottom_center)
121
+
122
+ if rounded_corners.include?(:bottom_right)
123
+ CGContextAddArcToPoint(context, x_right, y_bottom, x_right_center, y_bottom, radius)
124
+ else
125
+ CGContextAddLineToPoint(context, x_right, y_bottom)
126
+ end
127
+ CGContextAddLineToPoint(context, x_left_center, y_bottom)
128
+
129
+ if rounded_corners.include?(:bottom_left)
130
+ CGContextAddArcToPoint(context, x_left, y_bottom, x_left, y_bottom_center, radius)
131
+ else
132
+ CGContextAddLineToPoint(context, x_left, y_bottom)
133
+ end
134
+ CGContextAddLineToPoint(context, x_left, y_top_center)
135
+
136
+ CGContextClosePath(context)
137
+ end
74
138
  end
75
139
  end
@@ -17,10 +17,11 @@ module MotionPrime
17
17
 
18
18
  def draw_in(rect)
19
19
  return if computed_options[:hidden]
20
- draw_background_in_context(UIGraphicsGetCurrentContext())
20
+ super
21
21
  if computed_options[:draw_in_rect]
22
22
  draw_in_context(UIGraphicsGetCurrentContext())
23
23
  else
24
+ draw_background_in_context(UIGraphicsGetCurrentContext())
24
25
  draw_with_layer
25
26
  end
26
27
  load_image
@@ -37,12 +38,9 @@ module MotionPrime
37
38
  inset = border_width > 0 ? (border_width - 1 ).abs*0.5 : 0
38
39
  rect = CGRectInset(options[:inner_rect], inset, inset)
39
40
  radius = options[:corner_radius].to_f if options[:corner_radius] && options[:masks_to_bounds]
40
-
41
41
  UIGraphicsPushContext(context)
42
42
  if radius
43
- CGContextBeginPath(context)
44
- CGContextAddArc(context, rect.origin.x + rect.size.width/2, rect.origin.y + rect.size.height/2, radius, 0, 2*Math::PI, 0) # FIXME
45
- CGContextClosePath(context)
43
+ draw_rect_in_context(context, rect: rect, radius: radius, rounded_corners: options[:rounded_corners])
46
44
  CGContextSaveGState(context)
47
45
  CGContextClip(context)
48
46
  image.drawInRect(rect)
@@ -58,6 +56,7 @@ module MotionPrime
58
56
  @layer.try(:removeFromSuperlayer)
59
57
  return unless image = options[:image]
60
58
  rect = options[:inner_rect]
59
+
61
60
  radius = options[:corner_radius].to_f if options[:corner_radius] && options[:masks_to_bounds]
62
61
 
63
62
  @layer = CALayer.layer
@@ -94,7 +93,6 @@ module MotionPrime
94
93
  end
95
94
 
96
95
  self.image_data = image
97
-
98
96
  section.cached_draw_image = nil
99
97
  if section.respond_to?(:cell_section_name)
100
98
  section.pending_display!
@@ -34,12 +34,15 @@ module MotionPrime
34
34
  line_spacing: options[:line_spacing],
35
35
  line_height: options[:line_height],
36
36
  underline: options[:underline],
37
+ fragment_color: options[:fragment_color],
38
+ fragment_font: options[:fragment_font],
37
39
  top_left_corner: top_left_corner,
38
40
  inner_rect: inner_rect
39
41
  })
40
42
  end
41
43
 
42
44
  def draw_in(rect)
45
+ super
43
46
  draw_in_context(UIGraphicsGetCurrentContext())
44
47
  end
45
48
 
@@ -54,8 +57,7 @@ module MotionPrime
54
57
 
55
58
  UIGraphicsPushContext(context)
56
59
  options = draw_options
57
- if options[:is_html] || options[:line_spacing] ||
58
- options[:line_height] || options[:underline] || options[:force_attributed]
60
+ if options.slice(:is_html, :line_spacing, :line_height, :underline, :force_attributed, :fragment_color, :fragment_font).any?
59
61
  prepared_text = options[:is_html] ? html_string(options) : attributed_string(options)
60
62
 
61
63
  CGContextSaveGState(context)
@@ -90,27 +92,33 @@ module MotionPrime
90
92
  end
91
93
 
92
94
  def size_to_fit_if_needed
93
- if computed_options[:size_to_fit]
94
- computed_options[:width] ||= cached_content_outer_width
95
- computed_options[:height] ||= cached_content_outer_height
95
+ if original_options[:size_to_fit]
96
+ computed_options[:width] = cached_content_outer_width unless original_options[:width]
97
+ computed_options[:height] = cached_content_outer_height unless original_options[:height]
96
98
  reset_computed_values
97
- elsif computed_options.slice(:width, :left, :right).values.none?
98
- computed_options[:width] ||= cached_content_outer_width
99
+ elsif !original_options[:width] && (!original_options[:left] || !original_options[:right])
100
+ computed_options[:width] = cached_content_outer_width unless original_options[:width]
99
101
  reset_computed_values
100
- elsif computed_options.slice(:height, :top, :bottom).values.none?
101
- computed_options[:height] ||= cached_content_outer_height
102
+ elsif original_options.slice(:height, :top, :bottom).values.none?
103
+ computed_options[:height] = cached_content_outer_height unless original_options[:height]
102
104
  reset_computed_values
103
105
  end
104
106
  end
105
107
 
106
108
  def set_text_position
107
- if computed_options.slice(:padding_top, :padding_bottom, :padding).values.none?
109
+ # FIXME: there is a bug when overriding this method for custom fonts (adjust @padding_top), you must set 'padding' to 0
110
+ if original_options.slice(:padding_top, :padding_bottom, :padding, :size_to_fit).values.none?
108
111
  computed_options[:width] ||= frame_width
112
+ frame_height = computed_options[:height] || frame_outer_height
109
113
  content_height = cached_content_height
110
- content_height = frame_outer_height if content_height > frame_outer_height
111
- @padding_top = (frame_outer_height - content_height)/2
114
+ content_height = frame_height if content_height > frame_height
115
+ @padding_top = (frame_height - content_height)/2
112
116
  # @padding_top += 1 unless @padding_top.zero?
113
117
  end
114
118
  end
119
+
120
+ def original_options
121
+ @_original_options ||= computed_options.clone
122
+ end
115
123
  end
116
124
  end
@@ -4,6 +4,7 @@ module MotionPrime
4
4
  include DrawBackgroundMixin
5
5
 
6
6
  def draw_in(rect)
7
+ super
7
8
  draw_in_context(UIGraphicsGetCurrentContext())
8
9
  end
9
10
 
@@ -89,7 +89,7 @@ module MotionPrime
89
89
  define_method("#{association_name}_attributes=") do |value|
90
90
  bags_attributes = self.send(association_name).try(:bags_attributes) || {}
91
91
  self.send(bag_name).clear
92
- association = association_name.classify.constantize.new
92
+ association = options.fetch(:class_name, association_name.classify).constantize.new
93
93
  association.info.merge!(bags_attributes)
94
94
  association.fetch_with_attributes(value)
95
95
  self.send(:"#{bag_name}") << association
@@ -120,7 +120,7 @@ module MotionPrime
120
120
 
121
121
  pending_save_counter = 0
122
122
  collection = value.inject({}) do |result, attrs|
123
- model = association_name.classify.constantize.new
123
+ model = options.fetch(:class_name, association_name.classify).constantize.new
124
124
  model.info.merge!(bags_attributes.fetch(attrs[:id], {}))
125
125
  model.fetch_with_attributes(attrs)
126
126
  unique_key = model.id || "pending_#{pending_save_counter+=1}"
@@ -138,6 +138,7 @@ module MotionPrime
138
138
  bag = self.send(:"#{bag_name}")
139
139
  collection_options = {
140
140
  association_name: association_name,
141
+ class_name: options.fetch(:class_name, association_name.classify),
141
142
  inverse_relation: {
142
143
  type: :has_one,
143
144
  name: self.class_name_without_kvo.demodulize.underscore,
@@ -152,7 +153,7 @@ module MotionPrime
152
153
  self._associations ||= {}
153
154
  self._associations[association_name] = {
154
155
  type: :belongs_to_one,
155
- class_name: association_name.classify
156
+ class_name: options.fetch(:class_name, association_name.classify)
156
157
  }.merge(options)
157
158
 
158
159
  self.send(:attr_accessor, association_name)
@@ -284,7 +284,8 @@ module MotionPrime
284
284
 
285
285
  track_changed_attributes do
286
286
  old_collection = self.send(key)
287
- model_class = key.classify.constantize
287
+ association_options = associations[key]
288
+ model_class = association_options.fetch(:class_name, key.classify).constantize
288
289
 
289
290
  data.each do |attributes|
290
291
  model = old_collection.detect{ |model| model.id == attributes[:id]}
@@ -2,12 +2,13 @@ module MotionPrime
2
2
  class AssociationCollection < ::Array
3
3
  include FilterMixin
4
4
 
5
- attr_reader :bag, :association_name
5
+ attr_reader :bag, :association_name, :model_class
6
6
  attr_reader :inverse_relation_name, :inverse_relation_key, :model_inverse_relation_name
7
7
 
8
8
  def initialize(bag, options, *args)
9
9
  @bag = bag
10
10
  @association_name = options[:association_name]
11
+ @model_class = options[:class_name].constantize
11
12
  bag.bare_class = model_class
12
13
 
13
14
  inverse_relation_options = options[:inverse_relation]
@@ -91,10 +92,6 @@ module MotionPrime
91
92
  data
92
93
  end
93
94
 
94
- def model_class
95
- @model_class ||= @association_name.classify.constantize
96
- end
97
-
98
95
  # Remove all association records.
99
96
  #
100
97
  # @example:
@@ -23,7 +23,7 @@ module MotionPrime
23
23
 
24
24
  # @return screen [Prime::Screen] screen appearing after close
25
25
  def close_screen(args = {})
26
- args[:animated] = args.has_key?(:animated) ? args[:animated] : true
26
+ args[:animated] = args.fetch(:animated, true)
27
27
  # Pop current view, maybe with arguments, if in navigation controller
28
28
  if modal?
29
29
  close_screen_modal(args)
@@ -53,11 +53,11 @@ module MotionPrime
53
53
  def self.extract_image_from_options(options, with_key: key)
54
54
  image = options.delete(key)
55
55
  return unless image
56
- image = image.uiimage
57
- if options[:translucent] === false
58
- image = image.imageWithRenderingMode UIImageRenderingModeAlwaysOriginal
56
+ ui_image = image.uiimage
57
+ if ui_image && options[:translucent] === false
58
+ ui_image = ui_image.imageWithRenderingMode UIImageRenderingModeAlwaysOriginal
59
59
  end
60
- image
60
+ ui_image
61
61
  end
62
62
  end
63
63
  end
@@ -16,6 +16,12 @@ module MotionPrime
16
16
  navigationItem.rightBarButtonItem = create_navigation_button(title, args, &block)
17
17
  end
18
18
 
19
+ def set_navigation_right_buttons(options)
20
+ navigationItem.rightBarButtonItems = options.map do |button_options|
21
+ create_navigation_button(button_options.delete(:title), button_options)
22
+ end
23
+ end
24
+
19
25
  def set_navigation_left_button(title, args = {}, &block)
20
26
  navigationItem.leftBarButtonItem = create_navigation_button(title, args, &block)
21
27
  end
@@ -65,9 +71,9 @@ module MotionPrime
65
71
  end
66
72
 
67
73
  def create_navigation_button_with_title(title, args)
68
- image = args[:icon].uiimage if args[:icon]
74
+ ui_image = args[:icon].uiimage if args[:icon]
69
75
  face = UIButton.buttonWithType UIButtonTypeCustom
70
- face.setImage(image, forState: UIControlStateNormal) if args[:icon]
76
+ face.setImage(ui_image, forState: UIControlStateNormal) if ui_image
71
77
  face.setTitle(title, forState: UIControlStateNormal)
72
78
  face.setTitleColor((args[:title_color] || :app_navigation_base).uicolor, forState: UIControlStateNormal)
73
79
  face.setContentHorizontalAlignment UIControlContentHorizontalAlignmentLeft
@@ -79,10 +85,14 @@ module MotionPrime
79
85
  end
80
86
 
81
87
  def create_navigation_button_with_image(title, args)
82
- image = args[:image].uiimage
83
88
  face = UIButton.buttonWithType UIButtonTypeCustom
84
- face.bounds = CGRectMake(0, 0, image.size.width, image.size.height)
85
- face.setImage image, forState: UIControlStateNormal
89
+ if ui_image = args[:image].uiimage
90
+ ui_image = ui_image.imageWithRenderingMode(2) if args[:tint_color].present?
91
+ face.bounds = CGRectMake(0, 0, ui_image.size.width, ui_image.size.height)
92
+ face.setImage ui_image, forState: UIControlStateNormal
93
+ end
94
+ face.setTintColor(args[:tint_color].uicolor) if args[:tint_color]
95
+ face.setImageEdgeInsets(UIEdgeInsetsMake(0, args[:offset_x], 0, -args[:offset_x])) if args[:offset_x]
86
96
  face.on :touch do
87
97
  args[:action].to_proc.call(args[:target] || self)
88
98
  end if args[:action]
@@ -55,10 +55,10 @@ module Prime
55
55
  #
56
56
  # @param from_index [NSIndexPath] Value of first index to load if current sheduled index not exists.
57
57
  # @return [NSIndexPath, Boolean] Index of next sheduled index.
58
- def preload_sections_after(from_index)
58
+ def preload_sections_after(from_index, load_limit = nil)
59
59
  return unless async_data?
60
60
  service = preloader_index_service
61
- load_limit = self.class.async_data_options.try(:[], :preload_cells_count)
61
+ load_limit ||= self.class.async_data_options.try(:[], :preload_cells_count)
62
62
 
63
63
  if @preloader_next_starts_from
64
64
  index_to_start_preloading = service.sum_index(@preloader_next_starts_from, load_limit ? -load_limit/2 : 0)
@@ -70,6 +70,7 @@ module Prime
70
70
  current_group = from_index.section
71
71
  left_to_load_in_group = cell_sections_for_group(current_group).count - from_index.row
72
72
  load_count = [left_to_load_in_group, load_limit].compact.min
73
+
73
74
  to_index = service.sum_index(from_index, load_count - 1)
74
75
  @preloader_next_starts_from = to_index
75
76
 
@@ -90,6 +91,11 @@ module Prime
90
91
 
91
92
  load_count = to_index.row - from_index.row + 1
92
93
  preload_sections_schedule_from(from_index, load_count) if load_count > 0
94
+
95
+ # quota_left = (load_limit || 0) - load_count
96
+ # if quota_left > 0 && cell_sections_for_group(current_group + 1).any?
97
+ # preload_sections_after(NSIndexPath.indexPathForRow(0, inSection: current_group + 1), quota_left)
98
+ # end
93
99
  end
94
100
 
95
101
  # Schedules preloading sections starting with given index with given limit.
@@ -86,7 +86,7 @@ module MotionPrime
86
86
 
87
87
  def on_container_tap_gesture(recognizer)
88
88
  target = Array.wrap(container_gesture_recognizers).detect do |gesture_data|
89
- point = recognizer.locationInView(container_view)
89
+ point = recognizer.locationInView(container_view.respond_to?(:content_view) ? container_view.content_view : container_view)
90
90
  element = gesture_data[:element]
91
91
  section = element.section
92
92
  if section.has_container_bounds?
@@ -26,6 +26,7 @@ module MotionPrime
26
26
 
27
27
  def load_container_with_elements(options = {})
28
28
  init_container_element(options[:container] || {})
29
+ # FIXME: does not work for grid sections
29
30
  @container_element.compute_options! unless @container_element.computed_options
30
31
  compute_element_options(options[:elements] || {})
31
32
 
@@ -245,6 +245,13 @@ module MotionPrime
245
245
  display_pending_cells unless @decelerating = will_decelerate
246
246
  end
247
247
 
248
+ def on_input_change(text_field); end
249
+ def on_input_edit_begin(text_field); end
250
+ def on_input_edit_end(text_field); end
251
+ def on_input_return(text_field)
252
+ text_field.resignFirstResponder
253
+ end
254
+
248
255
  private
249
256
  def cached_cell(index)
250
257
  end
@@ -54,7 +54,7 @@ module MotionPrime
54
54
  end
55
55
 
56
56
  def strong_references
57
- [screen, screen.main_controller]
57
+ [screen, screen.try(:main_controller)]
58
58
  end
59
59
 
60
60
  def container_bounds
@@ -140,14 +140,6 @@ module MotionPrime
140
140
  :base_form
141
141
  end
142
142
 
143
- # ALIASES
144
- def on_input_change(text_field); end
145
- def on_input_edit_begin(text_field); end
146
- def on_input_edit_end(text_field); end
147
- def on_input_return(text_field)
148
- text_field.resignFirstResponder
149
- end
150
-
151
143
  def allow_string_replacement?(target, limit, range, string)
152
144
  if string.length.zero? || (range.length + limit - target.text.length) >= string.length
153
145
  true
@@ -130,7 +130,7 @@ module MotionPrime
130
130
  end
131
131
 
132
132
  def observing_errors?
133
- @errors_observer_options.present?
133
+ @errors_observer_options.present? && observing_errors_for.present?
134
134
  end
135
135
 
136
136
  def has_errors?
@@ -1,19 +1,6 @@
1
1
  motion_require '../table/table_delegate'
2
2
  module MotionPrime
3
3
  class FormDelegate < TableDelegate
4
- def textFieldShouldReturn(text_field)
5
- table_section.on_input_return(text_field)
6
- end
7
- def textFieldShouldBeginEditing(text_field)
8
- text_field.respond_to?(:readonly) ? !text_field.readonly : true
9
- end
10
- def textFieldDidBeginEditing(text_field)
11
- table_section.on_input_edit_begin(text_field)
12
- end
13
- def textFieldDidEndEditing(text_field)
14
- table_section.on_input_edit_end(text_field)
15
- end
16
-
17
4
  def textField(text_field, shouldChangeCharactersInRange:range, replacementString:string)
18
5
  limit = (table_section.class.text_field_limits || {}).find do |field_name, limit|
19
6
  table_section.view("#{field_name}:input") == text_field
@@ -22,25 +9,6 @@ module MotionPrime
22
9
  table_section.allow_string_replacement?(text_field, limit, range, string)
23
10
  end
24
11
 
25
- def textViewDidBeginEditing(text_view)
26
- table_section.on_input_edit_begin(text_view)
27
- end
28
- def textViewDidEndEditing(text_view)
29
- table_section.on_input_edit_end(text_view)
30
- end
31
- def textViewDidChange(text_view) # bug in iOS 7 - cursor is out of textView bounds
32
- line = text_view.caretRectForPosition(text_view.selectedTextRange.start)
33
- overflow = line.origin.y + line.size.height -
34
- (text_view.contentOffset.y + text_view.bounds.size.height - text_view.contentInset.bottom - text_view.contentInset.top)
35
- if overflow > 0
36
- offset = text_view.contentOffset
37
- offset.y += overflow + text_view.textContainerInset.bottom
38
- UIView.animate(duration: 0.2) do
39
- text_view.setContentOffset(offset)
40
- end
41
- end
42
- end
43
-
44
12
  def textView(text_view, shouldChangeTextInRange:range, replacementText:string)
45
13
  textField(text_view, shouldChangeCharactersInRange:range, replacementString:string)
46
14
  end
@@ -57,7 +57,7 @@ module MotionPrime
57
57
  index = index_for_cell_section(section)
58
58
  next Prime.logger.debug("Reload section: `#{section.name}` is not in the list") unless index
59
59
  paths << index
60
- block.call(section, index, counter)
60
+ block.call(section, index, counter) if block_given?
61
61
  deque_cell(section, at: index) # deque cached
62
62
  section.reload
63
63
  end
@@ -75,5 +75,36 @@ module MotionPrime
75
75
  def scrollViewDidEndDragging(scroll, willDecelerate: will_decelerate)
76
76
  table_section.scroll_view_did_end_dragging(scroll, willDecelerate: will_decelerate)
77
77
  end
78
+
79
+ def textFieldShouldReturn(text_field)
80
+ table_section.on_input_return(text_field)
81
+ end
82
+ def textFieldShouldBeginEditing(text_field)
83
+ text_field.respond_to?(:readonly) ? !text_field.readonly : true
84
+ end
85
+ def textFieldDidBeginEditing(text_field)
86
+ table_section.on_input_edit_begin(text_field)
87
+ end
88
+ def textFieldDidEndEditing(text_field)
89
+ table_section.on_input_edit_end(text_field)
90
+ end
91
+ def textViewDidBeginEditing(text_view)
92
+ table_section.on_input_edit_begin(text_view)
93
+ end
94
+ def textViewDidEndEditing(text_view)
95
+ table_section.on_input_edit_end(text_view)
96
+ end
97
+ def textViewDidChange(text_view) # bug in iOS 7 - cursor is out of textView bounds
98
+ line = text_view.caretRectForPosition(text_view.selectedTextRange.start)
99
+ overflow = line.origin.y + line.size.height -
100
+ (text_view.contentOffset.y + text_view.bounds.size.height - text_view.contentInset.bottom - text_view.contentInset.top)
101
+ if overflow > 0
102
+ offset = text_view.contentOffset
103
+ offset.y += overflow + text_view.textContainerInset.bottom
104
+ UIView.animate(duration: 0.2) do
105
+ text_view.setContentOffset(offset)
106
+ end
107
+ end
108
+ end
78
109
  end
79
110
  end
@@ -11,6 +11,13 @@ UIControlContentVerticalAlignmentBottom
11
11
  UIControlContentVerticalAlignmentFill
12
12
 
13
13
  if defined?(ALAssetsLibrary)
14
+ ALAssetsLibrary
15
+ end
16
+
17
+ if defined?(ALAuthorizationStatusNotDetermined)
14
18
  ALAuthorizationStatusNotDetermined
19
+ end
20
+
21
+ if defined?(ALAssetsGroupAll)
15
22
  ALAssetsGroupAll
16
- end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module MotionPrime
2
- VERSION = "1.0.4"
2
+ VERSION = "1.0.5"
3
3
  end
@@ -7,7 +7,6 @@ module MotionPrime
7
7
  right = options[:right]
8
8
  bottom = options[:bottom]
9
9
  left = options[:left]
10
-
11
10
  value_type = options[:value_type].to_s # absolute/relative
12
11
 
13
12
  if options[:height_to_fit].present? && height.nil? && (top.nil? || bottom.nil?)
@@ -67,12 +67,12 @@ module MotionPrime
67
67
  if image.nil?
68
68
  klass.alloc.initWithFrame CGRectZero
69
69
  else
70
- image = image.uiimage
71
- image = image.imageWithRenderingMode(2) if options[:tint_color].present?
70
+ ui_image = image.uiimage
71
+ ui_image = ui_image.imageWithRenderingMode(2) if options[:tint_color].present?
72
72
  if highlighted_image.nil?
73
- klass.alloc.initWithImage image.uiimage
73
+ klass.alloc.initWithImage ui_image
74
74
  else
75
- klass.alloc.initWithImage image.uiimage, highlightedImage: highlighted_image.uiimage
75
+ klass.alloc.initWithImage ui_image, highlightedImage: highlighted_image.uiimage
76
76
  end
77
77
  end
78
78
  },
@@ -109,7 +109,9 @@ module MotionPrime
109
109
  'UICollectionView' => Proc.new{|klass, options|
110
110
  unless layout = options.delete(:layout)
111
111
  layout = UICollectionViewFlowLayout.alloc.init
112
- total_width = options[:parent_bounds].size.width / (options.delete(:grid_size) || 3)
112
+
113
+ width = options[:width] || options[:parent_bounds].size.width
114
+ total_width = width / (options.delete(:grid_size) || 3)
113
115
  if horizontal_spacing = options.delete(:horizontal_spacing)
114
116
  layout.setMinimumInteritemSpacing horizontal_spacing
115
117
  end
@@ -135,11 +135,11 @@ module MotionPrime
135
135
  end
136
136
 
137
137
  def set_image_options(key, value)
138
- if key.end_with?('background_image')
138
+ if key.end_with?('background_image') && ui_image = value.uiimage
139
139
  if view.is_a?(UIControl) || view.is_a?(UISearchBar)
140
- view.send :"set#{camelize_factory(key)}:forState", value.uiimage, UIControlStateNormal
140
+ view.send :"set#{camelize_factory(key)}:forState", ui_image, UIControlStateNormal
141
141
  else
142
- view.setBackgroundColor value.uiimage.uicolor
142
+ view.setBackgroundColor ui_image.uicolor
143
143
  end
144
144
  true
145
145
  elsif key.end_with?('background_view')
@@ -152,7 +152,10 @@ module MotionPrime
152
152
  end
153
153
  true
154
154
  elsif key.end_with?('image')
155
- view.setValue value.uiimage, forKey: camelize_factory(key)
155
+ if ui_image = value.uiimage
156
+ ui_image = ui_image.imageWithRenderingMode(2) if options[:tint_color]
157
+ view.setValue ui_image, forKey: camelize_factory(key)
158
+ end
156
159
  true
157
160
  end
158
161
  end
@@ -189,7 +192,7 @@ module MotionPrime
189
192
  current_inset.send("#{key.partition('_').first}=", value)
190
193
  view.contentInset = current_inset
191
194
  true
192
- elsif key.end_with?('inset') || key.end_with?('indicator_insets')
195
+ elsif key.end_with?('inset') || key.end_with?('indicator_insets') || (key.end_with?('insets') && value.is_a?(Array))
193
196
  inset = if value.to_s == 'none'
194
197
  UIEdgeInsetsMake(0, 320, 0, 0)
195
198
  elsif value.is_a?(Array) && value.count == 2
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-prime
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iskander Haziev
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-07-06 00:00:00.000000000 Z
12
+ date: 2014-08-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake