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.
Files changed (43) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +7 -3
  3. data/Gemfile.lock +1 -1
  4. data/README.md +1 -1
  5. data/ROADMAP.md +12 -0
  6. data/motion-prime/api_client.rb +1 -0
  7. data/motion-prime/app_delegate.rb +1 -1
  8. data/motion-prime/elements/_content_padding_mixin.rb +49 -0
  9. data/motion-prime/elements/_field_dimensions_mixin.rb +37 -21
  10. data/motion-prime/elements/_text_dimensions_mixin.rb +0 -4
  11. data/motion-prime/elements/base.rb +20 -7
  12. data/motion-prime/elements/button.rb +2 -1
  13. data/motion-prime/elements/draw/label.rb +19 -8
  14. data/motion-prime/elements/error_message.rb +2 -1
  15. data/motion-prime/elements/image.rb +1 -0
  16. data/motion-prime/elements/label.rb +10 -10
  17. data/motion-prime/elements/text_field.rb +2 -0
  18. data/motion-prime/models/bag.rb +8 -3
  19. data/motion-prime/models/model.rb +1 -1
  20. data/motion-prime/models/sync.rb +17 -8
  21. data/motion-prime/screens/_aliases_mixin.rb +2 -0
  22. data/motion-prime/screens/_base_mixin.rb +19 -52
  23. data/motion-prime/screens/_navigation_mixin.rb +31 -29
  24. data/motion-prime/screens/base_screen.rb +8 -0
  25. data/motion-prime/screens/extensions/_indicators_mixin.rb +26 -0
  26. data/motion-prime/screens/{_navigation_bar_mixin.rb → extensions/_navigation_bar_mixin.rb} +0 -0
  27. data/motion-prime/screens/sidebar_container_screen.rb +1 -1
  28. data/motion-prime/sections/base.rb +1 -1
  29. data/motion-prime/sections/form.rb +5 -2
  30. data/motion-prime/sections/form/base_field_section.rb +2 -2
  31. data/motion-prime/support/_key_value_store.rb +1 -1
  32. data/motion-prime/support/_padding_attribute.rb +60 -0
  33. data/motion-prime/support/dm_button.rb +20 -20
  34. data/motion-prime/support/dm_text_field.rb +12 -17
  35. data/motion-prime/support/dm_text_view.rb +1 -1
  36. data/motion-prime/support/mp_label.rb +9 -0
  37. data/motion-prime/version.rb +1 -1
  38. data/motion-prime/views/layout.rb +1 -0
  39. data/motion-prime/views/styles.rb +1 -1
  40. data/motion-prime/views/view_styler.rb +5 -1
  41. data/spec/helpers/models.rb +8 -1
  42. data/travis.sh +1 -3
  43. metadata +8 -3
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MDQ1ZmFmOTg1ZWQ4MTliMDI3ZmY4ZmE0NGM5OTA2YjJjZjk4NmIxYQ==
4
+ MjY2ZDk2NzU1ZmRhZTE4Zjc0OTk5ZmQzYmI3MzdhYmM5ZWM5M2VlOA==
5
5
  data.tar.gz: !binary |-
6
- ODQzMzg0NGZiYzgxMDM5MTMwZGEzNGM4ODcwOTg5ZGEzNWE1OTEwMA==
6
+ OGQxMTU0YWRhZTAzMGQ1YTc3NDdkYTU2NThlOTcwZTMwY2Y4NzJhOQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ZjkyZGFmYTg3NzQ3ZDM0ZGRmOTg4MThiNTNlMDNjNGEwZDc3YTI5YmRhZGFi
10
- MGU5ZjQ2MTJiNmIzMzc0YWFmMTg0ZTBhNzY0NzQxMzU3OTFlZDVjNjRkNzA4
11
- YjVlM2EzNmU0MTkyOWYxM2I2MTg0N2VlYjg2NmE0NzY4NzA1NWQ=
9
+ NmQxZGEyNjg5OGVhNGU3OTA4ZWIwNmQ0YTMyMGVjYjZjYzEwYzE4NTlkNzZk
10
+ NjdmOTRmNWUyMjkyOGQ0NTY4MzM3NTgwZDljOGU3MTZhN2Y1NzA2ZWU4N2Nl
11
+ Zjg3Mzk2Zjk0YmQ2NDQ0OGYwOTQ3MjZhOTQ1OWIyNTQyNzNlMGE=
12
12
  data.tar.gz: !binary |-
13
- NzEwYTA3NjRkMTUxZGQ1NGQzMjk2MTQzMWFlYWM2NzkxZmZkNzkxN2E5NTAy
14
- OTg2MWY1ZmMzMzcwYzhmNzYyODIyZTFhNzczM2ZlZTY1OGQ0ZWUwM2E0MDcy
15
- ODA2ZTI2MmVkZGRiODljM2NjNmY2MzIzNzRmMTBlNjI1NTFhYjU=
13
+ ZGUxNDFjMTk3MmZkM2ZkMGY3ZDRkMjA5MThjNjA5YTJmN2U1MTE3ODBmZTc5
14
+ NDdlNjNkYzdiZWJiZWZiNGRjZDg4M2I4MjhlOWY0NjQ1ZTJhY2E5N2ZmZjRi
15
+ ODJkMTk0ZDc0ZDdhZTYzNjhjMjM1YmEyZDRmMTg4ZTkyZjFlMzg=
data/CHANGELOG.md CHANGED
@@ -1,10 +1,14 @@
1
- === 0.3.1.beta
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- motion-prime (0.3.1)
4
+ motion-prime (0.3.2)
5
5
  bubble-wrap
6
6
  cocoapods
7
7
  methadone
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
@@ -52,6 +52,7 @@ class ApiClient
52
52
  end
53
53
 
54
54
  def resource_url(path)
55
+ # return if path.blank?
55
56
  "#{MotionPrime::Config.api.base}#{path}"
56
57
  end
57
58
 
@@ -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.ensure_wrapper_controller_in_place if screen.respond_to?(:ensure_wrapper_controller_in_place)
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
- text = view ? view.text : computed_options[:text].to_s
5
- text.empty? ? computed_options[:placeholder] : text
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 font
9
- computed_options[:font] || :system.uifont
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 computed_width
13
- min_width = computed_options[:min_width] || 20
14
- return min_width if text_value.to_s.empty?
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
- padding_left = view.try(:padding_left) || computed_options[:padding_left] || computed_options[:padding] || view_class.constantize::DEFAULT_PADDING_LEFT
17
- padding_right = view.try(:padding_right) || computed_options[:padding_right] || padding_left
18
- max_width = computed_options[:max_width] || Float::MAX
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(text_value, attributes: {NSFontAttributeName => font })
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 = (rect.size.width + padding_left + padding_right).ceil
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 computed_height
28
- text = view ? view.titleLabel.text : computed_options[:title]
29
- return 0 if text.blank?
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(text, attributes: attributes)
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
- padding_top = computed_options[:padding_top] || computed_options[:padding] || view.try(:default_padding_top)
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
@@ -31,9 +31,5 @@ module MotionPrime
31
31
 
32
32
  rect.size.width
33
33
  end
34
-
35
- def content_outer_height
36
- content_height + computed_inner_top + computed_inner_bottom
37
- end
38
34
  end
39
35
  end
@@ -16,11 +16,10 @@ module MotionPrime
16
16
 
17
17
  def initialize(options = {})
18
18
  @options = options
19
- @section = options.delete(:section)
20
-
19
+ @section = options[:section]
21
20
  @name = options[:name]
22
- @block = options.delete(:block)
23
- @view_class = options.delete(:view_class) || "UIView"
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
- private
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 computed_height
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, computed_outer_width, computed_outer_height
17
+ computed_left, computed_top, computed_width, computed_height
17
18
  )
18
- bg_color.uicolor.setFill
19
- UIRectFill(rect)
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 if color
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(computed_left, computed_top),
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] = content_width
59
+ @computed_options[:width] = content_outer_width
49
60
  if computed_options[:width]
50
- @computed_options[:height] = content_height
61
+ @computed_options[:height] = content_outer_height
51
62
  end
52
63
  reset_computed_values
53
64
  end
@@ -1,10 +1,11 @@
1
1
  motion_require './label'
2
2
  module MotionPrime
3
3
  class ErrorMessageElement < LabelElement
4
+ include MotionPrime::ElementContentPaddingMixin
4
5
  include MotionPrime::ElementTextDimensionsMixin
5
6
 
6
7
  def view_class
7
- "UILabel"
8
+ "MPLabel"
8
9
  end
9
10
  end
10
11
  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 content_height + 2 # TODO maybe set width too as it can be wider
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] = content_height
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
@@ -1,6 +1,8 @@
1
1
  module MotionPrime
2
2
  class TextFieldElement < BaseElement
3
+ include MotionPrime::ElementContentPaddingMixin
3
4
  include MotionPrime::ElementFieldDimensionsMixin
5
+
4
6
  def view_class
5
7
  "DMTextField"
6
8
  end
@@ -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(prepare_for_store(object_or_array), error:error_ptr)
38
+ self.addObjectsFromArray(prepared, error:error_ptr)
37
39
  else
38
- self.addObject(prepare_for_store(object_or_array), error:error_ptr)
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