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
@@ -7,21 +7,31 @@ module MotionPrime
7
7
  @namespace = namespace
8
8
  end
9
9
 
10
- def style(name, options = {})
11
- name = "#{@namespace}_#{name}".to_sym if @namespace
12
- @@repo[name] ||= {}
13
- if parent = options.delete(:parent)
14
- parent ="#{@namespace}_#{parent}".to_sym if @namespace
15
- @@repo[name].deep_merge! self.class.for(parent)
10
+ def style(*args)
11
+ names = Array.wrap(args)
12
+ options = names.pop if args.last.is_a?(Hash)
13
+
14
+ raise "No style rules specified for `#{names.join(', ')}`. Namespace: `#{@namespace}`" unless options
15
+ names.each do |name|
16
+ name = "#{@namespace}_#{name}".to_sym if @namespace
17
+
18
+ @@repo[name] ||= {}
19
+ if parent = options.delete(:parent)
20
+ namespace = options.delete(:parent_namspace) || @namespace
21
+ parent ="#{namespace}_#{parent}".to_sym if namespace
22
+ @@repo[name].deep_merge! self.class.for(parent)
23
+ end
24
+ @@repo[name].deep_merge! options
16
25
  end
17
- @@repo[name].deep_merge! options
18
26
  end
19
27
 
20
28
  class << self
21
29
  include HasNormalizer
22
30
 
23
- def define(namespace = nil, &block)
24
- self.new(namespace).instance_eval(&block)
31
+ def define(*namespaces, &block)
32
+ Array.wrap(namespaces).each do |namespace|
33
+ self.new(namespace).instance_eval(&block)
34
+ end
25
35
  end
26
36
 
27
37
  def for(style_names)
@@ -31,7 +31,21 @@ module MotionPrime
31
31
  def default_views_map
32
32
  {
33
33
  'UIView' => Proc.new {|klass, options| klass.alloc.initWithFrame CGRectZero },
34
+ 'UILabel' => Proc.new {|klass, options|
35
+ if options[:line_spacing]
36
+ options[:attributed_text_options] = {
37
+ text: options.delete(:text),
38
+ line_spacing: options.delete(:line_spacing)
39
+ }
40
+ end
41
+ klass.alloc.initWithFrame CGRectZero
42
+ },
34
43
  'UIControl' => Proc.new {|klass, options| klass.alloc.init },
44
+ 'UISwitch' => Proc.new {|klass, options|
45
+ view = klass.alloc.init
46
+ view.setOn options.delete(:on)
47
+ view
48
+ },
35
49
  'UIActionSheet' => Proc.new {|klass, options|
36
50
  title = options.delete(:title) || ''
37
51
  delegate = options.delete(:delegate)
@@ -53,7 +67,7 @@ module MotionPrime
53
67
  is_custom_button = options[:background_image] || options[:title_color]
54
68
  default_button_type = is_custom_button ? :custom : :rounded
55
69
  button_type = (options.delete(:button_type) || default_button_type).uibuttontype
56
- klass.buttonWithType button_type
70
+ button = klass.buttonWithType button_type
57
71
  },
58
72
  'UIImageView' => Proc.new{|klass, options|
59
73
  image = options.delete(:image)
@@ -77,7 +91,9 @@ module MotionPrime
77
91
  },
78
92
  'UITableView' => Proc.new{|klass, options|
79
93
  style = options.delete(:style) || UITableViewStylePlain
80
- klass.alloc.initWithFrame CGRectZero, style: style
94
+ view = klass.alloc.initWithFrame CGRectZero, style: style
95
+ view.tableFooterView = UIView.new
96
+ view
81
97
  },
82
98
  'UITableViewCell' => Proc.new{|klass, options|
83
99
  style = options.delete(:style) || UITableViewCellStyleDefault
@@ -26,9 +26,14 @@ module MotionPrime
26
26
  right = options.delete(:right)
27
27
  bottom = options.delete(:bottom)
28
28
  left = options.delete(:left)
29
+ value_type = options.delete(:value_type).to_s # absolute/relative
30
+
31
+ if options[:height_to_fit].present? && height.nil? && (top.nil? || bottom.nil?)
32
+ height = options[:height_to_fit]
33
+ end
29
34
 
30
35
  if width.nil? && height.nil? && right.nil? && bottom.nil?
31
- options[:frame] = CGRectZero
36
+ options[:frame] = bounds
32
37
  else
33
38
  frame = CGRectZero
34
39
  max_width = bounds.size.width
@@ -37,7 +42,7 @@ module MotionPrime
37
42
  height = 0.0 if height.nil?
38
43
 
39
44
  # calculate left and right if width is relative, e.g 0.7
40
- if width > 0 && width <= 1
45
+ if width && width > 0 && width <= 1 && value_type != 'absolute'
41
46
  if right.nil?
42
47
  left ||= 0
43
48
  right = max_width - max_width * width
@@ -47,7 +52,7 @@ module MotionPrime
47
52
  end
48
53
 
49
54
  # calculate top and bottom if height is relative, e.g 0.7
50
- if height > 0 && height <= 1
55
+ if height && height > 0 && height <= 1 && value_type != 'absolute'
51
56
  if bottom.nil?
52
57
  top ||= 0
53
58
  bottom = max_height - max_height * height
@@ -98,10 +103,11 @@ module MotionPrime
98
103
  end
99
104
 
100
105
  def setValue(value, forUndefinedKey: key)
101
- return if value.nil?
106
+ # return if value.nil?
102
107
  # ignore options
103
108
  return if key == 'size_to_fit' && view.is_a?(UILabel)
104
109
  return if (key == 'url' || key == 'default') && view.is_a?(UIImageView)
110
+ return if %w[max_width min_width height_to_fit container].include? key.to_s
105
111
 
106
112
  # apply options
107
113
  if key.end_with?('title_color')
@@ -113,7 +119,7 @@ module MotionPrime
113
119
  elsif key.end_with?('title_shadow_color')
114
120
  view.setTitleShadowColor value.uicolor, forState: UIControlStateNormal
115
121
  elsif key.end_with?('color')
116
- color = value.uicolor
122
+ color = value.try(:uicolor)
117
123
  color = color.cgcolor if view.is_a?(CALayer)
118
124
  view.send :"#{key.camelize(:lower)}=", color
119
125
  elsif key.end_with?('background_image')
@@ -124,10 +130,58 @@ module MotionPrime
124
130
  else
125
131
  view.setBackgroundColor value.uiimage.uicolor
126
132
  end
133
+ elsif key.end_with?('background_view')
134
+ if view.is_a?(UITableView)
135
+ bg_view = UIView.alloc.initWithFrame(view.bounds)
136
+ bg_view.backgroundColor = value[:color].uicolor
137
+ view.backgroundView = bg_view
138
+ else
139
+ view.setValue value, forKey: key.camelize(:lower)
140
+ end
127
141
  elsif key.end_with?('image')
128
142
  view.setValue value.uiimage, forKey: key.camelize
143
+ elsif key.end_with?('_content_offset')
144
+ current_inset = view.contentInset
145
+ current_inset.send("#{key.partition('_').first}=", value)
146
+ view.contentInset = current_inset
147
+ elsif key == 'autocapitalization'
148
+ view.autocapitalizationType = UITextAutocapitalizationTypeNone if value === false
129
149
  elsif key == 'keyboard_type'
130
150
  view.setKeyboardType value.uikeyboardtype
151
+ elsif key == 'mask'
152
+ radius = value[:radius]
153
+ bounds = CGRectMake(0, 0, value[:width], value[:height])
154
+ mask_path = UIBezierPath.bezierPathWithRoundedRect(bounds, byRoundingCorners: UIRectCornerAllCorners, cornerRadii: CGSizeMake(radius, radius))
155
+ mask_layer = CAShapeLayer.layer
156
+ mask_layer.frame = bounds
157
+ mask_layer.path = mask_path.CGPath
158
+ view.layer.mask = mask_layer
159
+ # TODO: apply for corner_radius_top/bottom
160
+ # CAShapeLayer *shape = [[CAShapeLayer alloc] init];
161
+ # shape.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height) byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:CGSizeMake(10, 10)].CGPath;
162
+ # self.layer.mask = shape;
163
+ # self.layer.masksToBounds = YES;
164
+ elsif key == 'attributed_text_options'
165
+ attributes = {}
166
+ if line_spacing = value[:line_spacing]
167
+ paragrahStyle = NSMutableParagraphStyle.alloc.init
168
+ paragrahStyle.setLineSpacing(line_spacing)
169
+ attributes[NSParagraphStyleAttributeName] = paragrahStyle
170
+ end
171
+
172
+
173
+ attributedString = NSAttributedString.alloc.initWithString(value[:text], attributes: attributes)
174
+ if underline_range = value[:underline]
175
+ attributedString = NSMutableAttributedString.alloc.initWithAttributedString(attributedString)
176
+ attributedString.addAttributes({NSUnderlineStyleAttributeName => NSUnderlineStyleSingle}, range: underline_range)
177
+ end
178
+
179
+ if view.is_a?(UIButton)
180
+ view.setAttributedTitle attributedString, forState: UIControlStateNormal
181
+ else
182
+ view.attributedText = attributedString
183
+ end
184
+
131
185
  elsif value.is_a?(Hash)
132
186
  self.class.new(view.send(key.camelize(:lower).to_sym), nil, value).apply
133
187
  else
@@ -10,19 +10,19 @@ describe "Model Errors" do
10
10
  end
11
11
 
12
12
  it "should not be blank after adding error" do
13
- @user.errors.add(:foo, 'bar')
13
+ @user.errors.add(:name, 'bar')
14
14
  @user.errors.blank?.should == false
15
15
  end
16
16
 
17
17
  it "should not present after reset" do
18
- @user.errors.add(:foo, 'bar')
18
+ @user.errors.add(:name, 'bar')
19
19
  @user.errors.present?.should == true
20
20
  @user.errors.reset
21
21
  @user.errors.present?.should == false
22
22
  end
23
23
 
24
24
  it "should be convertable to string" do
25
- @user.errors.add(:foo, 'bar')
25
+ @user.errors.add(:name, 'bar')
26
26
  @user.errors.to_s.match(/bar/).should != nil
27
27
  end
28
28
  end
data/travis.sh CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env sh
2
2
 
3
- sudo gem install bundler &&
4
- sudo bundle install &&
3
+ sudo gem install bundler
4
+ sudo bundle install
5
+ sudo pod install
5
6
  sudo bundle exec rake clean &&
6
7
  sudo bundle exec rake spec &&
7
8
  sudo bundle exec rake clean &&
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-prime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iskander Haziev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-12 00:00:00.000000000 Z
11
+ date: 2013-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -150,10 +150,25 @@ dependencies:
150
150
  - - ! '>='
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: methadone
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ! '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
153
167
  description: RubyMotion apps development framework
154
168
  email:
155
169
  - gvalmon@gmail.com
156
- executables: []
170
+ executables:
171
+ - prime.rb
157
172
  extensions: []
158
173
  extra_rdoc_files: []
159
174
  files:
@@ -165,6 +180,7 @@ files:
165
180
  - README.md
166
181
  - Rakefile
167
182
  - app/app_delegate.rb
183
+ - bin/prime.rb
168
184
  - doc/FAQ.md
169
185
  - doc/SECTION.md
170
186
  - doc/STYLE.md
@@ -186,10 +202,13 @@ files:
186
202
  - files/resources/images/navigation/button@2x.png
187
203
  - lib/motion-prime.rb
188
204
  - motion-prime.gemspec
205
+ - motion-prime/api_client.rb
189
206
  - motion-prime/app_delegate.rb
190
207
  - motion-prime/config/base.rb
191
208
  - motion-prime/config/config.rb
192
- - motion-prime/elements/_text_height_mixin.rb
209
+ - motion-prime/core_ext/kernel.rb
210
+ - motion-prime/elements/_field_dimensions_mixin.rb
211
+ - motion-prime/elements/_text_dimensions_mixin.rb
193
212
  - motion-prime/elements/base.rb
194
213
  - motion-prime/elements/button.rb
195
214
  - motion-prime/elements/draw.rb
@@ -202,9 +221,11 @@ files:
202
221
  - motion-prime/elements/map.rb
203
222
  - motion-prime/elements/text_field.rb
204
223
  - motion-prime/elements/text_view.rb
224
+ - motion-prime/helpers/cell_section.rb
205
225
  - motion-prime/helpers/has_authorization.rb
206
226
  - motion-prime/helpers/has_normalizer.rb
207
227
  - motion-prime/helpers/has_search_bar.rb
228
+ - motion-prime/helpers/has_style_chain_builder.rb
208
229
  - motion-prime/models/association.rb
209
230
  - motion-prime/models/association_collection.rb
210
231
  - motion-prime/models/bag.rb
@@ -217,6 +238,7 @@ files:
217
238
  - motion-prime/models/store.rb
218
239
  - motion-prime/models/store_extension.rb
219
240
  - motion-prime/models/sync.rb
241
+ - motion-prime/mp.rb
220
242
  - motion-prime/screens/_aliases_mixin.rb
221
243
  - motion-prime/screens/_base_mixin.rb
222
244
  - motion-prime/screens/_navigation_bar_mixin.rb
@@ -228,19 +250,20 @@ files:
228
250
  - motion-prime/sections/draw.rb
229
251
  - motion-prime/sections/form.rb
230
252
  - motion-prime/sections/form/base_field_section.rb
253
+ - motion-prime/sections/form/base_header_section.rb
231
254
  - motion-prime/sections/form/date_field_section.rb
232
255
  - motion-prime/sections/form/password_field_section.rb
233
256
  - motion-prime/sections/form/select_field_section.rb
234
257
  - motion-prime/sections/form/string_field_section.rb
235
258
  - motion-prime/sections/form/submit_field_section.rb
236
259
  - motion-prime/sections/form/switch_field_section.rb
237
- - motion-prime/sections/form/table_field_section.rb
238
260
  - motion-prime/sections/form/text_field_section.rb
239
261
  - motion-prime/sections/form/text_with_button_field_section.rb
240
262
  - motion-prime/sections/tabbed.rb
241
263
  - motion-prime/sections/table.rb
242
264
  - motion-prime/sections/table/refresh_mixin.rb
243
265
  - motion-prime/styles/base.rb
266
+ - motion-prime/styles/form.rb
244
267
  - motion-prime/support/_key_value_store.rb
245
268
  - motion-prime/support/dm_button.rb
246
269
  - motion-prime/support/dm_cell_with_section.rb
@@ -1,17 +0,0 @@
1
- module MotionPrime
2
- module ElementTextHeightMixin
3
- def content_height
4
- return 0 if computed_options[:text].blank?
5
- width = computed_options[:width]
6
- font = computed_options[:font] || :system.uifont
7
- raise "Please set element width for height calculation" unless width
8
- computed_options[:text].sizeWithFont(font,
9
- constrainedToSize: [width, Float::MAX],
10
- lineBreakMode: UILineBreakModeWordWrap).height
11
- end
12
-
13
- def content_outer_height
14
- content_height + computed_inner_top + computed_inner_bottom
15
- end
16
- end
17
- end
@@ -1,51 +0,0 @@
1
- motion_require '../table.rb'
2
- module MotionPrime
3
- class TableFieldSection < TableSection
4
- attr_accessor :form, :cell_element, :delegate
5
- after_render :on_render
6
-
7
- def initialize(options = {})
8
- @form = options.delete(:form)
9
- @delegate = options.delete(:delegate) || form
10
- @container_options = options.delete(:container)
11
- super
12
- end
13
-
14
- def on_render
15
- add_pull_to_refresh do
16
- model.sync! do
17
- finish_pull_to_refresh
18
- end
19
- end if @options[:pull_to_refresh] && model.present?
20
- end
21
-
22
- def render_table
23
- @styles ||= []
24
- @styles += [
25
- :"#{form.name}_table",
26
- :"#{form.name}_#{name}_table"]
27
- super
28
- end
29
-
30
- def cell
31
- cell_element || begin
32
- first_element = elements.values.first
33
- first_element.view.superview
34
- end
35
- end
36
-
37
- def on_click(table, index)
38
- section = data[index.row]
39
- delegate.send("#{name}_selected", section) if delegate.respond_to?("#{name}_selected")
40
- end
41
-
42
- def self.delegate_method(method_name)
43
- define_method method_name do |*args|
44
- delegate.send("#{name}_#{method_name}", *args) if delegate.respond_to?("#{name}_#{method_name}")
45
- end
46
- end
47
-
48
- delegate_method :table_data
49
- delegate_method :container_height
50
- end
51
- end