motion-prime 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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