motion-prime 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +5 -0
  3. data/Gemfile.lock +14 -11
  4. data/README.md +8 -11
  5. data/Rakefile +2 -1
  6. data/bin/prime.rb +47 -0
  7. data/doc/FAQ.md +1 -1
  8. data/files/app/app_delegate.rb +1 -1
  9. data/files/app/config/base.rb +8 -4
  10. data/files/app/screens/application_screen.rb +1 -1
  11. data/files/app/screens/sidebar_screen.rb +1 -1
  12. data/files/app/sections/sidebar/action.rb +1 -1
  13. data/files/app/sections/sidebar/table.rb +1 -1
  14. data/files/app/styles/sidebar.rb +5 -5
  15. data/motion-prime.gemspec +1 -0
  16. data/motion-prime/api_client.rb +81 -0
  17. data/motion-prime/app_delegate.rb +22 -5
  18. data/motion-prime/config/base.rb +5 -0
  19. data/motion-prime/core_ext/kernel.rb +5 -0
  20. data/motion-prime/elements/_field_dimensions_mixin.rb +43 -0
  21. data/motion-prime/elements/_text_dimensions_mixin.rb +39 -0
  22. data/motion-prime/elements/base.rb +40 -17
  23. data/motion-prime/elements/button.rb +20 -0
  24. data/motion-prime/elements/draw.rb +2 -2
  25. data/motion-prime/elements/draw/image.rb +4 -2
  26. data/motion-prime/elements/draw/label.rb +1 -1
  27. data/motion-prime/elements/error_message.rb +3 -16
  28. data/motion-prime/elements/label.rb +13 -2
  29. data/motion-prime/elements/text_field.rb +1 -0
  30. data/motion-prime/helpers/cell_section.rb +9 -0
  31. data/motion-prime/helpers/has_authorization.rb +4 -3
  32. data/motion-prime/helpers/has_normalizer.rb +20 -6
  33. data/motion-prime/helpers/has_search_bar.rb +19 -7
  34. data/motion-prime/helpers/has_style_chain_builder.rb +7 -0
  35. data/motion-prime/models/association.rb +22 -9
  36. data/motion-prime/models/association_collection.rb +54 -23
  37. data/motion-prime/models/bag.rb +13 -12
  38. data/motion-prime/models/base.rb +2 -0
  39. data/motion-prime/models/errors.rb +23 -14
  40. data/motion-prime/models/finder.rb +4 -1
  41. data/motion-prime/models/model.rb +25 -5
  42. data/motion-prime/models/store_extension.rb +1 -7
  43. data/motion-prime/models/sync.rb +75 -43
  44. data/motion-prime/mp.rb +4 -0
  45. data/motion-prime/screens/_base_mixin.rb +18 -12
  46. data/motion-prime/screens/_navigation_bar_mixin.rb +15 -6
  47. data/motion-prime/screens/_navigation_mixin.rb +15 -16
  48. data/motion-prime/screens/base_screen.rb +5 -1
  49. data/motion-prime/screens/sidebar_container_screen.rb +37 -22
  50. data/motion-prime/sections/base.rb +82 -16
  51. data/motion-prime/sections/form.rb +144 -26
  52. data/motion-prime/sections/form/base_field_section.rb +62 -29
  53. data/motion-prime/sections/form/base_header_section.rb +27 -0
  54. data/motion-prime/sections/form/date_field_section.rb +2 -17
  55. data/motion-prime/sections/form/password_field_section.rb +3 -17
  56. data/motion-prime/sections/form/select_field_section.rb +4 -35
  57. data/motion-prime/sections/form/string_field_section.rb +3 -29
  58. data/motion-prime/sections/form/submit_field_section.rb +1 -7
  59. data/motion-prime/sections/form/switch_field_section.rb +3 -23
  60. data/motion-prime/sections/form/text_field_section.rb +3 -33
  61. data/motion-prime/sections/form/text_with_button_field_section.rb +4 -40
  62. data/motion-prime/sections/tabbed.rb +25 -5
  63. data/motion-prime/sections/table.rb +86 -22
  64. data/motion-prime/sections/table/refresh_mixin.rb +3 -1
  65. data/motion-prime/styles/base.rb +7 -89
  66. data/motion-prime/styles/form.rb +116 -0
  67. data/motion-prime/support/dm_button.rb +32 -5
  68. data/motion-prime/support/dm_text_field.rb +31 -7
  69. data/motion-prime/support/dm_text_view.rb +6 -3
  70. data/motion-prime/support/dm_view_controller.rb +3 -3
  71. data/motion-prime/support/ui_search_bar_custom.rb +1 -1
  72. data/motion-prime/version.rb +1 -1
  73. data/motion-prime/views/layout.rb +18 -10
  74. data/motion-prime/views/styles.rb +19 -9
  75. data/motion-prime/views/view_builder.rb +18 -2
  76. data/motion-prime/views/view_styler.rb +59 -5
  77. data/spec/models/errors_spec.rb +3 -3
  78. data/travis.sh +3 -2
  79. metadata +28 -5
  80. data/motion-prime/elements/_text_height_mixin.rb +0 -17
  81. data/motion-prime/sections/form/table_field_section.rb +0 -51
@@ -1,6 +1,8 @@
1
1
  module MotionPrime
2
2
  module TableSectionRefreshMixin
3
- def add_pull_to_refresh(&block)
3
+ def add_pull_to_refresh(options = {}, &block)
4
+ screen.automaticallyAdjustsScrollViewInsets = false
5
+
4
6
  table_view.addPullToRefreshWithActionHandler(block)
5
7
  screen.setup table_view.pullToRefreshView, styles: [:base_pull_to_refresh]
6
8
  end
@@ -10,7 +10,11 @@ MotionPrime::Styles.define :base do
10
10
  top: 0,
11
11
  left: 0,
12
12
  width: 320,
13
- bottom: 0
13
+ bottom: 0,
14
+ separatorInset: 0
15
+
16
+ style :table_cell,
17
+ background_color: :clear
14
18
 
15
19
  # basic form styles
16
20
  # ----------
@@ -24,52 +28,11 @@ MotionPrime::Styles.define :base do
24
28
  separator_color: :clear,
25
29
  scroll_enabled: true
26
30
 
27
- style :form_field,
28
- selection_style: UITableViewCellSelectionStyleNone
29
-
30
- # available options for string label:
31
- # @background_color: COLOR
32
- # @text_color: COLOR
33
- style :field_label,
34
- background_color: :clear,
35
- text_color: :gray,
36
- top: 6,
37
- height: 20,
38
- left: 0,
39
- right: 0,
40
- font: proc { MotionPrime::Config.font.name.uifont(12) },
41
- size_to_fit: true
42
-
43
- # available options for input:
44
- # @layer: @border_width: FLOAT
45
- # @layer: @border_color: COLOR
46
- # @background_color: COLOR
47
- # @background_image: PATH_TO_FILE
48
- style :field_input,
49
- layer: {
50
- border_width: 1,
51
- border_color: :gray
52
- },
53
- font: proc { MotionPrime::Config.font.name.uifont(16) },
54
- placeholder_font: proc { MotionPrime::Config.font.name.uifont(16) },
55
- background_color: :white,
56
- left: 0,
57
- right: 0,
58
- top: 30,
59
- bottom: 0,
60
- padding_top: 4
61
-
62
- style :field_input_with_errors,
63
- layer: {
64
- border_color: proc { MotionPrime::Config.color.error }
65
- },
66
- text_color: proc { MotionPrime::Config.color.error }
67
-
68
31
  # available options for submit button:
69
32
  # @button_type: :rounded, :custom
70
33
  # @background_color: COLOR
71
34
  # @background_image: PATH_TO_FILE
72
- style :submit_button,
35
+ style :submit_button, :form_submit_field_button,
73
36
  background_color: :gray,
74
37
  title_color: :white,
75
38
  left: 0,
@@ -77,59 +40,14 @@ MotionPrime::Styles.define :base do
77
40
  top: 10,
78
41
  height: 44
79
42
 
80
- style :select_field_button,
81
- background_color: :white,
82
- left: 0,
83
- right: 0,
84
- top: 30,
85
- height: 36,
86
- title_color: 0x16759a,
87
- title_shadow_color: :white,
88
- contentHorizontalAlignment: UIControlContentHorizontalAlignmentLeft,
89
- layer: {
90
- border_color: :gray,
91
- border_width: 1
92
- },
93
- title_color: :gray,
94
- title_label: {
95
- font: proc { MotionPrime::Config.font.name.uifont(16) }
96
- }
97
- style :select_field_arrow,
98
- image: "images/forms/select_arrow.png",
99
- top: 42,
100
- right: 5,
101
- width: 9,
102
- height: 14
103
-
104
43
  style :segmented_control,
105
44
  height: 40, width: 320, top: 0
106
45
 
107
46
  style :google_map,
108
47
  top: 0, left: 0, right: 0, bottom: 0
109
48
 
110
- style :date_picker,
49
+ style :date_picker, :form_field_date_picker,
111
50
  width: 300,
112
51
  height: 150,
113
52
  top: 30, left: 0
114
-
115
- style :error_message,
116
- top: nil,
117
- bottom: 0,
118
- width: 300,
119
- line_break_mode: :wordwrap,
120
- number_of_lines: 0,
121
- text_color: proc { MotionPrime::Config.color.error }
122
-
123
- style :field_switch,
124
- top: 10,
125
- width: 79,
126
- height: 27,
127
- right: 0
128
-
129
- style :switch_label,
130
- top: 10,
131
- font: proc { MotionPrime::Config.font.name.uifont(16) }
132
-
133
- style :switch_hint,
134
- top: 40
135
53
  end
@@ -0,0 +1,116 @@
1
+ motion_require '../views/styles.rb'
2
+ MotionPrime::Styles.define :base_form do
3
+ style :header, container: {height: 25}
4
+ style :header_label,
5
+ left: 0, right: 0, size_to_fit: true,
6
+ bottom: 20, top: nil
7
+
8
+ style :field,
9
+ selection_style: UITableViewCellSelectionStyleNone,
10
+ background_color: :clear
11
+
12
+ style :with_sections,
13
+ left: 0,
14
+ right: 0
15
+
16
+ # available options for string label:
17
+ # @background_color: COLOR
18
+ # @text_color: COLOR
19
+ style :field_label,
20
+ background_color: :clear,
21
+ text_color: :gray,
22
+ top: 15,
23
+ height: 16,
24
+ left: 0,
25
+ right: 0,
26
+ font: proc { MotionPrime::Config.font.name.uifont(12) },
27
+ size_to_fit: true
28
+
29
+ style :field_error_message,
30
+ top: nil,
31
+ bottom: 0,
32
+ width: 300,
33
+ line_break_mode: :wordwrap,
34
+ number_of_lines: 0,
35
+ size_to_fit: true,
36
+ text_color: proc { MotionPrime::Config.color.error },
37
+ font: proc { MotionPrime::Config.font.name.uifont(12) }
38
+
39
+ # available options for input:
40
+ # @layer: @border_width: FLOAT
41
+ # @layer: @border_color: COLOR
42
+ # @background_color: COLOR
43
+ # @background_image: PATH_TO_FILE
44
+ style :field_text_field, :field_text_view,
45
+ layer: {
46
+ border_width: 1,
47
+ border_color: :gray
48
+ },
49
+ font: proc { MotionPrime::Config.font.name.uifont(16) },
50
+ placeholder_font: proc { MotionPrime::Config.font.name.uifont(16) },
51
+ background_color: :white,
52
+ left: 0,
53
+ right: 0,
54
+ top: 30,
55
+ bottom: 0
56
+
57
+ style :select_field_button,
58
+ background_color: :white,
59
+ left: 0,
60
+ right: 0,
61
+ top: 30,
62
+ height: 35,
63
+ title_color: 0x16759a,
64
+ title_shadow_color: :white,
65
+ contentHorizontalAlignment: UIControlContentHorizontalAlignmentLeft,
66
+ layer: {
67
+ border_color: :gray,
68
+ border_width: 1
69
+ },
70
+ title_color: :gray,
71
+ title_label: {
72
+ font: proc { MotionPrime::Config.font.name.uifont(16) }
73
+ }
74
+ style :select_field_arrow,
75
+ image: "images/forms/select_arrow.png",
76
+ top: 40,
77
+ right: 5,
78
+ width: 9,
79
+ height: 14
80
+
81
+ style :with_sections_field_switch,
82
+ right: 20
83
+
84
+ style :with_sections_field_text_field, :with_sections_field_text_view, :with_sections_field_password_field, :with_sections_field_label, :with_sections_field_button,
85
+ left: 20,
86
+ right: 20
87
+
88
+ style :with_sections_select_field_arrow,
89
+ right: 25
90
+
91
+ style :with_sections_switch_field_input,
92
+ right: 25
93
+ style :with_sections_switch_field_label,
94
+ left: 25
95
+ style :with_sections_switch_hint,
96
+ left: 25
97
+
98
+ style :field_input_with_errors,
99
+ layer: {
100
+ border_color: proc { MotionPrime::Config.color.error }
101
+ },
102
+ text_color: proc { MotionPrime::Config.color.error }
103
+
104
+ style :switch_field_input,
105
+ top: 10,
106
+ right: 0,
107
+ width: 51
108
+
109
+ style :switch_field_label,
110
+ top: 10,
111
+ font: proc { MotionPrime::Config.font.name.uifont(16) }
112
+
113
+ style :switch_field_hint,
114
+ top: 40,
115
+ font: proc { MotionPrime::Config.font.name.uifont(12) }
116
+ end
@@ -1,18 +1,45 @@
1
1
  class DMButton < UIButton
2
2
  include MotionPrime::KeyValueStore
3
- attr_accessor :paddingLeft, :paddingRight, :paddingTop, :padding
3
+ DEFAULT_PADDING_LEFT = 5
4
+ attr_accessor :paddingLeft, :paddingRight, :paddingTop, :padding, :sizeToFit
4
5
 
5
6
  def setTitle(value)
6
7
  setTitle value, forState: UIControlStateNormal
7
8
  end
8
9
 
10
+ def setImage(value)
11
+ setImage value, forState: UIControlStateNormal
12
+ end
13
+
14
+ def setTitleEdgeInsets(value)
15
+ @custom_title_inset_drawn = true
16
+ super
17
+ end
18
+
19
+ def padding_left
20
+ self.paddingLeft || self.padding || DEFAULT_PADDING_LEFT
21
+ end
22
+
23
+ def padding_right
24
+ self.paddingRight || padding_left || DEFAULT_PADDING_LEFT
25
+ end
26
+
27
+ def padding_top
28
+ self.paddingTop || self.padding || default_padding_top
29
+ end
30
+
31
+ def default_padding_top # to center title label
32
+ single_line_height = self.font.pointSize
33
+ (self.bounds.size.height - single_line_height)/2 + 1
34
+ end
35
+
9
36
  def drawPadding(rect)
10
- padding_left = self.paddingLeft || self.padding || 5
11
- padding_right = self.paddingRight || padding_left || 5
12
- padding_top = self.paddingTop || self.padding || 0
37
+ return if @custom_title_inset_drawn || [padding_top, padding_left, padding_right].all?(&:zero?)
38
+
39
+ height_diff = self.bounds.size.height - (self.font.pointSize + padding_top*2)
13
40
  self.setTitleEdgeInsets UIEdgeInsetsMake(
14
41
  padding_top, padding_left,
15
- padding_top, padding_right
42
+ padding_top + height_diff, padding_right
16
43
  )
17
44
  end
18
45
 
@@ -2,23 +2,20 @@
2
2
  # * support padding, padding_left, padding_right options
3
3
  # * support placeholder_color, placeholder_font options
4
4
  class DMTextField < UITextField
5
+ DEFAULT_PADDING_LEFT = 5
5
6
  include MotionPrime::KeyValueStore
6
7
 
7
- attr_accessor :paddingLeft, :paddingTop, :padding,
8
+ attr_accessor :paddingLeft, :paddingRight, :paddingTop, :padding,
8
9
  :placeholderColor, :placeholderFont
9
10
 
10
11
  # placeholder position
11
12
  def textRectForBounds(bounds)
12
- padding_left = self.paddingLeft || self.padding || 5
13
- padding_top = self.paddingTop || self.padding || 3
14
- CGRectInset(bounds, padding_left, padding_top)
13
+ calculate_rect_for(bounds)
15
14
  end
16
15
 
17
16
  # text position
18
17
  def editingRectForBounds(bounds)
19
- padding_left = self.paddingLeft || self.padding || 5
20
- padding_top = self.paddingTop || self.padding || 3
21
- CGRectInset(bounds, padding_left, padding_top)
18
+ calculate_rect_for(bounds)
22
19
  end
23
20
 
24
21
  def drawPlaceholderInRect(rect)
@@ -27,4 +24,31 @@ class DMTextField < UITextField
27
24
  font = self.placeholderFont || self.font || :system.uifont(16)
28
25
  self.placeholder.drawInRect(rect, withFont: font)
29
26
  end
27
+
28
+ def padding_left
29
+ self.paddingLeft || self.padding || DEFAULT_PADDING_LEFT
30
+ end
31
+
32
+ def padding_right
33
+ self.paddingRight || self.padding_left
34
+ end
35
+
36
+ def padding_top
37
+ self.paddingTop || self.padding || default_padding_top
38
+ end
39
+
40
+ def default_padding_top # to center title label
41
+ single_line_height = self.font.pointSize
42
+ (self.bounds.size.height - single_line_height)/2 + 2
43
+ end
44
+
45
+ private
46
+ def calculate_rect_for(bounds)
47
+ height_diff = self.bounds.size.height - (self.font.pointSize + padding_top*2)
48
+ bounds = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height - height_diff)
49
+ CGRectMake(
50
+ bounds.origin.x + padding_left, bounds.origin.y + padding_top,
51
+ bounds.size.width - (padding_left + padding_right), bounds.size.height - padding_top*2)
52
+ end
53
+
30
54
  end
@@ -8,10 +8,14 @@ class DMTextView < UITextView
8
8
  attr_accessor :paddingLeft, :paddingTop, :padding,
9
9
  :placeholderColor, :placeholderFont, :placeholder
10
10
 
11
+ def padding_top
12
+ paddingTop || padding || paddingLeft || 5
13
+ end
14
+
11
15
  def drawPadding(rect)
12
16
  # add padding to UITextView
13
- padding_left = 0 - DEFAULT_PADDING_LEFT + (self.paddingLeft || self.padding || 5)
14
- padding_top = 0 - DEFAULT_PADDING_LEFT + (self.paddingTop || self.padding || 5)
17
+ padding_left = (self.paddingLeft || self.padding || 5) - 5
18
+ padding_top = self.padding_top - 8
15
19
  padding = UIEdgeInsetsMake(
16
20
  padding_top, padding_left,
17
21
  padding_top, padding_left
@@ -30,7 +34,6 @@ class DMTextView < UITextView
30
34
 
31
35
  def drawPlaceholder(rect)
32
36
  padding_left = self.paddingLeft || self.padding || 5
33
- padding_top = self.paddingTop || self.padding || 5
34
37
  padding = UIEdgeInsetsMake(
35
38
  padding_top, padding_left,
36
39
  padding_top, padding_left
@@ -1,8 +1,8 @@
1
1
  class DMViewController < UIViewController
2
2
  def self.new(args = {})
3
- s = self.alloc.initWithNibName(nil, bundle: nil)
4
- s.on_create(args) if s.respond_to?(:on_create)
5
- s
3
+ self.alloc.initWithNibName(nil, bundle: nil).tap do |screen|
4
+ screen.on_create(args) if screen.respond_to?(:on_create)
5
+ end
6
6
  end
7
7
 
8
8
  def viewDidLoad
@@ -2,7 +2,7 @@
2
2
  class UISearchBarCustom < UISearchBar
3
3
  def layoutSubviews
4
4
  super
5
- text_field = subviews.detect do |view|
5
+ text_field = subviews.objectAtIndex(0).subviews.detect do |view|
6
6
  view.is_a?(UISearchBarTextField)
7
7
  end
8
8
  text_field.frame = CGRectMake(0, 0, 320, 44)
@@ -1,3 +1,3 @@
1
1
  module MotionPrime
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -1,25 +1,33 @@
1
1
  # TODO: make it part of Sections
2
2
  module MotionPrime
3
3
  module Layout
4
- def setup(view, options = {}, &block)
5
- ViewStyler.new(view, options.delete(:bounds), options).apply
6
- view_stack.push(view)
7
- block.call(view) if block_given?
8
- view_stack.pop
9
- end
10
-
11
4
  def add_view(klass, options = {}, &block)
12
- bounds = view_stack.empty? ? CGRectZero : view_stack.last.bounds
5
+ bounds = if view_stack.empty?
6
+ options.delete(:parent_view).try(:bounds) || CGRectZero
7
+ else
8
+ view_stack.last.bounds
9
+ end
13
10
  builder = ViewBuilder.new(klass, options)
14
11
  options = builder.options.merge(calculate_frame: true, bounds: bounds)
15
12
  view = builder.view
16
- view_stack.last.addSubview(view) unless view_stack.empty?
13
+ if render_target = options.delete(:render_target)
14
+ render_target.addSubview(view)
15
+ elsif view_stack.any?
16
+ view_stack.last.addSubview(view)
17
+ end
17
18
  setup(view, options, &block)
18
19
  view.on_added if view.respond_to?(:on_added)
19
20
 
20
21
  view
21
22
  end
22
23
 
24
+ def setup(view, options = {}, &block)
25
+ ViewStyler.new(view, options.delete(:bounds), options).apply
26
+ view_stack.push(view)
27
+ block.call(view) if block_given?
28
+ view_stack.pop
29
+ end
30
+
23
31
  def view_stack
24
32
  @view_stack ||= []
25
33
  end
@@ -29,7 +37,7 @@ module MotionPrime
29
37
  [::UIActionSheet, ::UIActivityIndicatorView, ::UIButton, ::UIDatePicker, ::UIImageView, ::UILabel,
30
38
  ::UIPageControl, ::UIPickerView, ::UIProgressView, ::UIScrollView, ::UISearchBar, ::UISegmentedControl,
31
39
  ::UISlider, ::UIStepper, ::UISwitch, ::UITabBar, ::UITableView, ::UITableViewCell, ::UITextField, ::UITextView,
32
- ::UIToolbar, ::UIWebView].each do |klass|
40
+ ::UIToolbar, ::UIWebView, ::UINavigationBar].each do |klass|
33
41
 
34
42
  shorthand = "#{klass}"[2..-1].underscore.to_sym
35
43