motion-prime 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +7 -3
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/ROADMAP.md +12 -0
- data/motion-prime/api_client.rb +1 -0
- data/motion-prime/app_delegate.rb +1 -1
- data/motion-prime/elements/_content_padding_mixin.rb +49 -0
- data/motion-prime/elements/_field_dimensions_mixin.rb +37 -21
- data/motion-prime/elements/_text_dimensions_mixin.rb +0 -4
- data/motion-prime/elements/base.rb +20 -7
- data/motion-prime/elements/button.rb +2 -1
- data/motion-prime/elements/draw/label.rb +19 -8
- data/motion-prime/elements/error_message.rb +2 -1
- data/motion-prime/elements/image.rb +1 -0
- data/motion-prime/elements/label.rb +10 -10
- data/motion-prime/elements/text_field.rb +2 -0
- data/motion-prime/models/bag.rb +8 -3
- data/motion-prime/models/model.rb +1 -1
- data/motion-prime/models/sync.rb +17 -8
- data/motion-prime/screens/_aliases_mixin.rb +2 -0
- data/motion-prime/screens/_base_mixin.rb +19 -52
- data/motion-prime/screens/_navigation_mixin.rb +31 -29
- data/motion-prime/screens/base_screen.rb +8 -0
- data/motion-prime/screens/extensions/_indicators_mixin.rb +26 -0
- data/motion-prime/screens/{_navigation_bar_mixin.rb → extensions/_navigation_bar_mixin.rb} +0 -0
- data/motion-prime/screens/sidebar_container_screen.rb +1 -1
- data/motion-prime/sections/base.rb +1 -1
- data/motion-prime/sections/form.rb +5 -2
- data/motion-prime/sections/form/base_field_section.rb +2 -2
- data/motion-prime/support/_key_value_store.rb +1 -1
- data/motion-prime/support/_padding_attribute.rb +60 -0
- data/motion-prime/support/dm_button.rb +20 -20
- data/motion-prime/support/dm_text_field.rb +12 -17
- data/motion-prime/support/dm_text_view.rb +1 -1
- data/motion-prime/support/mp_label.rb +9 -0
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/layout.rb +1 -0
- data/motion-prime/views/styles.rb +1 -1
- data/motion-prime/views/view_styler.rb +5 -1
- data/spec/helpers/models.rb +8 -1
- data/travis.sh +1 -3
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MjY2ZDk2NzU1ZmRhZTE4Zjc0OTk5ZmQzYmI3MzdhYmM5ZWM5M2VlOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OGQxMTU0YWRhZTAzMGQ1YTc3NDdkYTU2NThlOTcwZTMwY2Y4NzJhOQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NmQxZGEyNjg5OGVhNGU3OTA4ZWIwNmQ0YTMyMGVjYjZjYzEwYzE4NTlkNzZk
|
10
|
+
NjdmOTRmNWUyMjkyOGQ0NTY4MzM3NTgwZDljOGU3MTZhN2Y1NzA2ZWU4N2Nl
|
11
|
+
Zjg3Mzk2Zjk0YmQ2NDQ0OGYwOTQ3MjZhOTQ1OWIyNTQyNzNlMGE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZGUxNDFjMTk3MmZkM2ZkMGY3ZDRkMjA5MThjNjA5YTJmN2U1MTE3ODBmZTc5
|
14
|
+
NDdlNjNkYzdiZWJiZWZiNGRjZDg4M2I4MjhlOWY0NjQ1ZTJhY2E5N2ZmZjRi
|
15
|
+
ODJkMTk0ZDc0ZDdhZTYzNjhjMjM1YmEyZDRmMTg4ZTkyZjFlMzg=
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
-
=== 0.3.
|
1
|
+
=== 0.3.2
|
2
|
+
* Refactor screens
|
3
|
+
* Fix paddings for draw sections
|
4
|
+
* Draw label now supports corner radius
|
5
|
+
|
6
|
+
=== 0.3.1
|
2
7
|
* Added universal AppDelegate#open_screen method for opening screens.
|
3
8
|
* Old AppDelegate#open_screen method renamed to AppDelegate#open_content_screen
|
4
9
|
* Ability to add inherited styles
|
5
|
-
* Small refactoring
|
6
10
|
* Update project template
|
7
|
-
|
11
|
+
* Small refactoring
|
8
12
|
|
9
13
|
=== 0.3.0
|
10
14
|
* Added iOS 7 support
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# MotionPrime [![Build Status](https://travis-ci.org/droidlabs/motion-prime.png)](https://travis-ci.org/droidlabs/motion-prime)
|
1
|
+
# MotionPrime [![Build Status](https://travis-ci.org/droidlabs/motion-prime.png)](https://travis-ci.org/droidlabs/motion-prime) [![Code Climate](https://codeclimate.com/github/droidlabs/motion-prime.png)](https://codeclimate.com/github/droidlabs/motion-prime) [![Roadchange](http://roadchange.com/droidlabs/motion-prime/badge.png)](http://roadchange.com/droidlabs/motion-prime)
|
2
2
|
|
3
3
|
![Prime](https://s3-us-west-2.amazonaws.com/webmate/assets/prime.jpg)
|
4
4
|
|
data/ROADMAP.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
=== 0.4.0
|
2
|
+
* rename support/dm_* to support/mp_*
|
3
|
+
* "id" attribute should always be added to model by default
|
4
|
+
* add DSL for ViewStyles#setValue conditions
|
5
|
+
* add auto-symbol-value for Prime::Config.color items
|
6
|
+
|
7
|
+
=== 0.5.0
|
8
|
+
* add testing framework
|
9
|
+
* add auth backends to ApiClient: password auth and facebook auth
|
10
|
+
|
11
|
+
=== 0.6.0
|
12
|
+
* add sections/screens/models generator
|
data/motion-prime/api_client.rb
CHANGED
@@ -32,7 +32,7 @@ module MotionPrime
|
|
32
32
|
# TODO: move to private methods
|
33
33
|
def open_root_screen(screen)
|
34
34
|
screen.send(:on_screen_load) if screen.respond_to?(:on_screen_load)
|
35
|
-
screen.
|
35
|
+
screen.wrap_in_navigation if screen.respond_to?(:wrap_in_navigation)
|
36
36
|
|
37
37
|
screen = screen.main_controller if screen.respond_to?(:main_controller)
|
38
38
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module ElementContentPaddingMixin
|
3
|
+
def content_padding_left
|
4
|
+
view.try(:padding_left) ||
|
5
|
+
computed_options[:padding_left] ||
|
6
|
+
computed_options[:padding] ||
|
7
|
+
view_class.constantize.default_padding_left || 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def content_padding_right
|
11
|
+
view.try(:padding_right) ||
|
12
|
+
computed_options[:padding_right] ||
|
13
|
+
computed_options[:padding] ||
|
14
|
+
view_class.constantize.default_padding_right || 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def content_padding_top
|
18
|
+
view.try(:padding_top) ||
|
19
|
+
computed_options[:padding_top] ||
|
20
|
+
computed_options[:padding] ||
|
21
|
+
view_class.constantize.default_padding_top || 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def content_padding_bottom
|
25
|
+
view.try(:padding_bottom) ||
|
26
|
+
computed_options[:padding_bottom] ||
|
27
|
+
computed_options[:padding] ||
|
28
|
+
view_class.constantize.default_padding_bottom || 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def content_padding_height
|
32
|
+
content_padding_top + content_padding_bottom
|
33
|
+
end
|
34
|
+
|
35
|
+
def content_padding_width
|
36
|
+
content_padding_left + content_padding_right
|
37
|
+
end
|
38
|
+
|
39
|
+
def content_outer_height
|
40
|
+
height = content_padding_height + content_height
|
41
|
+
[[height, computed_options[:min_outer_height]].compact.max, computed_options[:max_outer_height]].compact.min
|
42
|
+
end
|
43
|
+
|
44
|
+
def content_outer_width
|
45
|
+
width = content_padding_width + content_width
|
46
|
+
[[width, computed_options[:min_outer_width]].compact.max, computed_options[:max_outer_width]].compact.min
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,43 +1,59 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
module ElementFieldDimensionsMixin
|
3
3
|
def text_value
|
4
|
-
|
5
|
-
|
4
|
+
if button?
|
5
|
+
text = view ? view.titleLabel.text : computed_options[:title]
|
6
|
+
else
|
7
|
+
text = view ? view.text : computed_options[:text]
|
8
|
+
end.to_s
|
6
9
|
end
|
7
10
|
|
8
|
-
def
|
9
|
-
|
11
|
+
def content_text
|
12
|
+
text = text_value
|
13
|
+
if !button? && text.empty?
|
14
|
+
text = computed_options[:placeholder]
|
15
|
+
end
|
16
|
+
text.to_s
|
10
17
|
end
|
11
18
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
19
|
+
def font
|
20
|
+
if button?
|
21
|
+
font = computed_options[:title_label][:font]
|
22
|
+
else
|
23
|
+
font = computed_options[:placeholder_font] if text_value.empty?
|
24
|
+
font ||= computed_options[:font]
|
25
|
+
end
|
26
|
+
font || :system.uifont
|
27
|
+
end
|
15
28
|
|
16
|
-
|
17
|
-
|
18
|
-
|
29
|
+
def content_width
|
30
|
+
min_width = computed_options[:min_width].to_f
|
31
|
+
return min_width if content_text.empty?
|
19
32
|
|
20
|
-
attributed_text = NSAttributedString.alloc.initWithString(
|
33
|
+
attributed_text = NSAttributedString.alloc.initWithString(content_text, attributes: {NSFontAttributeName => font })
|
21
34
|
rect = attributed_text.boundingRectWithSize([Float::MAX, Float::MAX], options:NSStringDrawingUsesLineFragmentOrigin, context:nil)
|
22
35
|
|
23
|
-
width =
|
24
|
-
[[width, max_width].min, min_width].max
|
36
|
+
width = rect.size.width.ceil
|
37
|
+
[[width, computed_options[:max_width]].compact.min, min_width].max
|
25
38
|
end
|
26
39
|
|
27
|
-
def
|
28
|
-
|
29
|
-
return
|
40
|
+
def content_height
|
41
|
+
min_height = computed_options[:min_height].to_f
|
42
|
+
return min_height if content_text.blank?
|
30
43
|
|
31
44
|
width = computed_options[:width]
|
32
|
-
font = computed_options[:title_label][:font] || :system.uifont
|
33
45
|
raise "Please set element width for height calculation" unless width
|
34
46
|
|
35
47
|
attributes = {NSFontAttributeName => font }
|
36
|
-
attributed_text = NSAttributedString.alloc.initWithString(
|
48
|
+
attributed_text = NSAttributedString.alloc.initWithString(content_text, attributes: attributes)
|
37
49
|
rect = attributed_text.boundingRectWithSize([width, Float::MAX], options:NSStringDrawingUsesLineFragmentOrigin, context:nil)
|
38
|
-
|
39
|
-
|
40
|
-
rect.size.height + padding_top*2
|
50
|
+
height = rect.size.height.ceil
|
51
|
+
[[height, computed_options[:max_height]].compact.min, min_height].max
|
41
52
|
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def button?
|
56
|
+
self.is_a?(ButtonElement)
|
57
|
+
end
|
42
58
|
end
|
43
59
|
end
|
@@ -16,11 +16,10 @@ module MotionPrime
|
|
16
16
|
|
17
17
|
def initialize(options = {})
|
18
18
|
@options = options
|
19
|
-
@section = options
|
20
|
-
|
19
|
+
@section = options[:section]
|
21
20
|
@name = options[:name]
|
22
|
-
@block = options
|
23
|
-
@view_class = options
|
21
|
+
@block = options[:block]
|
22
|
+
@view_class = options[:view_class] || "UIView"
|
24
23
|
@view_name = self.class_name_without_kvo.demodulize.underscore.gsub('_element', '')
|
25
24
|
end
|
26
25
|
|
@@ -46,9 +45,9 @@ module MotionPrime
|
|
46
45
|
@computed_options ||= {}
|
47
46
|
block_options = compute_block_options || {}
|
48
47
|
compute_style_options(options, block_options)
|
49
|
-
@computed_options.merge!(options)
|
48
|
+
@computed_options.merge!(options.except(:section, :name, :block, :view_class))
|
50
49
|
@computed_options.merge!(block_options)
|
51
|
-
normalize_options(@computed_options, section, %w[text font title_label padding padding_left padding_right max_width width left right])
|
50
|
+
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])
|
52
51
|
end
|
53
52
|
|
54
53
|
# Compute options sent inside block, e.g.
|
@@ -96,7 +95,21 @@ module MotionPrime
|
|
96
95
|
Styles.for(styles)
|
97
96
|
end
|
98
97
|
|
99
|
-
|
98
|
+
def update_with_options(new_options = {})
|
99
|
+
options.merge!(new_options)
|
100
|
+
compute_options!
|
101
|
+
view.try(:removeFromSuperview)
|
102
|
+
@view = nil
|
103
|
+
render(to: screen)
|
104
|
+
end
|
105
|
+
|
106
|
+
def hide
|
107
|
+
view.hidden = true
|
108
|
+
end
|
109
|
+
|
110
|
+
def show
|
111
|
+
view.hidden = false
|
112
|
+
end
|
100
113
|
|
101
114
|
class << self
|
102
115
|
def factory(type, options = {})
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class ButtonElement < BaseElement
|
3
|
+
include MotionPrime::ElementContentPaddingMixin
|
3
4
|
include MotionPrime::ElementFieldDimensionsMixin
|
4
5
|
|
5
6
|
after_render :size_to_fit
|
@@ -7,7 +8,7 @@ module MotionPrime
|
|
7
8
|
def size_to_fit
|
8
9
|
if computed_options[:size_to_fit] || style_options[:size_to_fit]
|
9
10
|
if computed_options[:width]
|
10
|
-
view.setHeight
|
11
|
+
view.setHeight content_outer_height
|
11
12
|
end
|
12
13
|
end
|
13
14
|
end
|
@@ -2,6 +2,7 @@ motion_require '../draw.rb'
|
|
2
2
|
module MotionPrime
|
3
3
|
class LabelDrawElement < DrawElement
|
4
4
|
include MotionPrime::ElementTextDimensionsMixin
|
5
|
+
include MotionPrime::ElementContentPaddingMixin
|
5
6
|
|
6
7
|
def draw_in(rect)
|
7
8
|
options = computed_options
|
@@ -13,19 +14,29 @@ module MotionPrime
|
|
13
14
|
bg_color = options[:background_color]
|
14
15
|
if bg_color
|
15
16
|
rect = CGRectMake(
|
16
|
-
computed_left, computed_top,
|
17
|
+
computed_left, computed_top, computed_width, computed_height
|
17
18
|
)
|
18
|
-
|
19
|
-
|
19
|
+
|
20
|
+
if computed_options[:layer] && radius = options[:layer][:corner_radius]
|
21
|
+
bezierPath = UIBezierPath.bezierPathWithRoundedRect rect, cornerRadius: radius
|
22
|
+
context = UIGraphicsGetCurrentContext()
|
23
|
+
CGContextSetStrokeColorWithColor(context, bg_color.uicolor.cgcolor)
|
24
|
+
CGContextSetFillColorWithColor(context, bg_color.uicolor.cgcolor)
|
25
|
+
bezierPath.stroke
|
26
|
+
bezierPath.fill
|
27
|
+
else
|
28
|
+
bg_color.uicolor.setFill
|
29
|
+
UIRectFill(rect)
|
30
|
+
end
|
20
31
|
end
|
21
32
|
|
22
33
|
# render text
|
23
|
-
color = options[:text_color]
|
24
|
-
color.uicolor.set
|
34
|
+
color = options[:text_color] || :black
|
35
|
+
color.uicolor.set
|
25
36
|
font = options[:font] || :system
|
26
37
|
if options[:number_of_lines] != 0
|
27
38
|
options[:text].to_s.drawAtPoint(
|
28
|
-
CGPointMake(
|
39
|
+
CGPointMake(computed_inner_left, computed_inner_top),
|
29
40
|
withFont: font.uifont
|
30
41
|
)
|
31
42
|
else
|
@@ -45,9 +56,9 @@ module MotionPrime
|
|
45
56
|
|
46
57
|
def size_to_fit_if_needed
|
47
58
|
if computed_options[:size_to_fit]
|
48
|
-
@computed_options[:width] =
|
59
|
+
@computed_options[:width] = content_outer_width
|
49
60
|
if computed_options[:width]
|
50
|
-
@computed_options[:height] =
|
61
|
+
@computed_options[:height] = content_outer_height
|
51
62
|
end
|
52
63
|
reset_computed_values
|
53
64
|
end
|
@@ -7,6 +7,7 @@ module MotionPrime
|
|
7
7
|
|
8
8
|
def fetch_image
|
9
9
|
return unless computed_options[:url]
|
10
|
+
raise "You must set default image for `#{name}`" unless computed_options[:default]
|
10
11
|
view.setImageWithURL NSURL.URLWithString(computed_options[:url]),
|
11
12
|
placeholderImage: computed_options[:default].uiimage
|
12
13
|
end
|
@@ -1,32 +1,32 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class LabelElement < BaseElement
|
3
|
+
include MotionPrime::ElementContentPaddingMixin
|
3
4
|
include MotionPrime::ElementTextDimensionsMixin
|
4
5
|
|
5
6
|
before_render :size_to_fit_if_needed
|
6
7
|
after_render :size_to_fit
|
7
8
|
|
9
|
+
def view_class
|
10
|
+
"MPLabel"
|
11
|
+
end
|
12
|
+
|
8
13
|
def size_to_fit
|
9
14
|
if computed_options[:size_to_fit] || style_options[:size_to_fit]
|
10
15
|
if computed_options[:width]
|
11
|
-
view.setHeight
|
16
|
+
view.setHeight([content_outer_height, computed_options[:height]].compact.min)
|
12
17
|
else
|
13
18
|
view.sizeToFit
|
19
|
+
# we should re-set values, because sizeToFit do not use padding
|
20
|
+
view.setWidth(view.bounds.size.width + content_padding_width)
|
21
|
+
view.setHeight(view.bounds.size.height + content_padding_height)
|
14
22
|
end
|
15
23
|
end
|
16
24
|
end
|
17
25
|
|
18
26
|
def size_to_fit_if_needed
|
19
27
|
if computed_options[:size_to_fit] && computed_options[:width]
|
20
|
-
@computed_options[:height_to_fit] =
|
28
|
+
@computed_options[:height_to_fit] = content_outer_height
|
21
29
|
end
|
22
30
|
end
|
23
|
-
|
24
|
-
def computed_inner_top
|
25
|
-
computed_options[:top].to_i
|
26
|
-
end
|
27
|
-
|
28
|
-
def computed_inner_bottom
|
29
|
-
computed_options[:bottom].to_i
|
30
|
-
end
|
31
31
|
end
|
32
32
|
end
|
data/motion-prime/models/bag.rb
CHANGED
@@ -32,10 +32,12 @@ module MotionPrime
|
|
32
32
|
# @return self
|
33
33
|
def add(object_or_array)
|
34
34
|
error_ptr = Pointer.new(:id)
|
35
|
+
prepared = prepare_for_store(object_or_array)
|
36
|
+
|
35
37
|
if object_or_array.is_a?(Array)
|
36
|
-
self.addObjectsFromArray(
|
38
|
+
self.addObjectsFromArray(prepared, error:error_ptr)
|
37
39
|
else
|
38
|
-
self.addObject(
|
40
|
+
self.addObject(prepared, error:error_ptr)
|
39
41
|
end
|
40
42
|
raise StoreError, error_ptr[0].description if error_ptr[0]
|
41
43
|
self
|
@@ -45,9 +47,12 @@ module MotionPrime
|
|
45
47
|
|
46
48
|
def prepare_for_store(object)
|
47
49
|
if object.is_a?(Array)
|
48
|
-
object.map { |entity| prepare_for_store(entity) }
|
50
|
+
object.map { |entity| prepare_for_store(entity) }.compact
|
49
51
|
else
|
50
52
|
object.bag_key = self.key
|
53
|
+
if object.id.present? && self.store && self.find(id: object.id).any?
|
54
|
+
raise StoreError, "duplicated item added `#{object.class_name_without_kvo}` with `id` = #{object.id}"
|
55
|
+
end
|
51
56
|
object
|
52
57
|
end
|
53
58
|
end
|