motion-prime 1.0.4 → 1.0.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +2 -2
- data/ROADMAP.md +1 -0
- data/files/Gemfile +1 -1
- data/motion-prime/api_client.rb +3 -3
- data/motion-prime/elements/_content_text_mixin.rb +1 -0
- data/motion-prime/elements/_text_mixin.rb +5 -0
- data/motion-prime/elements/draw.rb +21 -6
- data/motion-prime/elements/draw/_draw_background_mixin.rb +68 -4
- data/motion-prime/elements/draw/image.rb +4 -6
- data/motion-prime/elements/draw/label.rb +20 -12
- data/motion-prime/elements/draw/view.rb +1 -0
- data/motion-prime/models/_association_mixin.rb +4 -3
- data/motion-prime/models/_sync_mixin.rb +2 -1
- data/motion-prime/models/association_collection.rb +2 -5
- data/motion-prime/screens/_navigation_mixin.rb +1 -1
- data/motion-prime/screens/controllers/tab_bar_controller.rb +4 -4
- data/motion-prime/screens/extensions/_navigation_bar_mixin.rb +15 -5
- data/motion-prime/sections/_async_table_mixin.rb +8 -2
- data/motion-prime/sections/_draw_section_mixin.rb +1 -1
- data/motion-prime/sections/_section_with_container_mixin.rb +1 -0
- data/motion-prime/sections/abstract_collection.rb +7 -0
- data/motion-prime/sections/base_section.rb +1 -1
- data/motion-prime/sections/form.rb +0 -8
- data/motion-prime/sections/form/base_field_section.rb +1 -1
- data/motion-prime/sections/form/form_delegate.rb +0 -32
- data/motion-prime/sections/table.rb +1 -1
- data/motion-prime/sections/table/table_delegate.rb +31 -0
- data/motion-prime/support/consts.rb +8 -1
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/_frame_calculator_mixin.rb +0 -1
- data/motion-prime/views/view_builder.rb +7 -5
- data/motion-prime/views/view_styler.rb +8 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45140a3e0294c388e06a65d8984b3178d3a61860
|
4
|
+
data.tar.gz: bbdb962a185668be9c8788616fd562697b4dc80f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29e217defff9f85b314495158591cd4bb0215d58f86e3bee2e7660fd4e70e36668c035917f9589345425527d3f10edfd02d57255bfd7608937279b09203682cc
|
7
|
+
data.tar.gz: a459b509909885a8b77d71f94a4cb02cb12e91f56b9c9f91c24b1e1c863d9ba073b105258908fc6648da2487d8225638a98bc34b3bc479ec55f30a7c3f29b78d
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
motion-prime (1.0.
|
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.
|
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
data/motion-prime/api_client.rb
CHANGED
@@ -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:
|
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']
|
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:
|
17
|
-
corner_radius:
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
71
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
94
|
-
computed_options[:width]
|
95
|
-
computed_options[: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
|
98
|
-
computed_options[: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
|
101
|
-
computed_options[: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
|
-
|
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 =
|
111
|
-
@padding_top = (
|
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
|
@@ -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
|
-
|
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.
|
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
|
-
|
57
|
-
if options[:translucent] === false
|
58
|
-
|
56
|
+
ui_image = image.uiimage
|
57
|
+
if ui_image && options[:translucent] === false
|
58
|
+
ui_image = ui_image.imageWithRenderingMode UIImageRenderingModeAlwaysOriginal
|
59
59
|
end
|
60
|
-
|
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
|
-
|
74
|
+
ui_image = args[:icon].uiimage if args[:icon]
|
69
75
|
face = UIButton.buttonWithType UIButtonTypeCustom
|
70
|
-
face.setImage(
|
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
|
-
|
85
|
-
|
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
|
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
|
@@ -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
|
@@ -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
|
data/motion-prime/version.rb
CHANGED
@@ -67,12 +67,12 @@ module MotionPrime
|
|
67
67
|
if image.nil?
|
68
68
|
klass.alloc.initWithFrame CGRectZero
|
69
69
|
else
|
70
|
-
|
71
|
-
|
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
|
73
|
+
klass.alloc.initWithImage ui_image
|
74
74
|
else
|
75
|
-
klass.alloc.initWithImage
|
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
|
-
|
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",
|
140
|
+
view.send :"set#{camelize_factory(key)}:forState", ui_image, UIControlStateNormal
|
141
141
|
else
|
142
|
-
view.setBackgroundColor
|
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
|
-
|
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
|
+
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-
|
12
|
+
date: 2014-08-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|