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
@@ -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