motion-prime 0.9.5 → 0.9.6

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NGU1Njc4YzVkNGIyNmZjNDg0MWIwZGYzYmMwMDliNWZhMDVkNWI5Mg==
4
+ MDhjOWNjZjBiYWMwMGM0YTE5YzRkZTBmZWQyNDZmMzdiM2VjOTE5OQ==
5
5
  data.tar.gz: !binary |-
6
- OGNiYjkyMThmM2QwZWU5YzQzM2E0YWI0ZDgxZjlkMzAzZDQ3NDU1MQ==
6
+ ZTllMmM5YWMyZjg4MDNhYzVhOWY5YzEzM2ExNzZiNWY1NTcwN2E5OA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ODg2YmIyZTc5Y2ZhMGQxZTMzNDlhM2RmNDdlM2FmN2RiOTVjZGJhMjE4ODBl
10
- NjU3NTY2MDNjYjk3ZWMzNmM1MWJjMTI4OGY5NjUzMWRhOWRlNzI2ZmIzNTdl
11
- MjdhYzdjMTk0OGUwODZlYTIzNWQ1ZmZkNTQ3YzBlZWY0YzFhNmM=
9
+ YWQ4YTdhYjhkOWFjMDhmZjc0ZjZkMWY3MmMxYjA4ZWQwMzE1MWMxYjhkZjFl
10
+ OTQ3NjNjMWRjODI1NGQ4Y2RlOGU2N2ZhOGU5OGM1Nzc4MzZjMTU2NGRmMWM1
11
+ N2YxYmEwM2Q1MjFmZGIwOTNhZjcwZmQyZGQwNmIzYzNmMzQyYjA=
12
12
  data.tar.gz: !binary |-
13
- YzdiYTliMTNmNWVhMzI2NDZjNzRlZGVmYzllODI1YTg2ZjAyYmRiMGIyYmU3
14
- N2EzODQ2YWM2OGE2M2U4ZGRjM2NmN2RkODA2NTM3ZTJmNzhkYmEyYmJjYmIw
15
- MWU5ZTkzNzdiY2JjNjhiYTUyZjY0MmE2ZjhiZDk3MmMwYmFhMzk=
13
+ M2M2MjUzNjk0OWI0ZWRkY2I3MzA4YTIxNzcxMTRjNDhiNTg5NjM3ZDNiOWIz
14
+ ZTJjNzg5NTAyODgzODU2MjM2M2Y4MTFiYjc3ZDk4YjE4NzI4ZGRjY2MwYzQ0
15
+ ZjA0YjY0N2IwZDY4OTMwNTU0YTFkMTlmMDBhMjYzMzVkNmM0NzA=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.9.6
2
+ * BREAKING CHANGE: proc for form field option will be executed in context of form, not field.
3
+ * BREAKING CHANGE: screen#setup renamed to screen#set_options.
4
+
1
5
  === 0.9.5
2
6
  * Ability to set wrapper for sections in screen.
3
7
  * Screen refresh reloads all sections in screen.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- motion-prime (0.9.5)
4
+ motion-prime (0.9.6)
5
5
  activesupport
6
6
  afmotion (~> 2.1.0)
7
7
  bubble-wrap (~> 1.5.0)
data/doc/code/sections.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  # ** What is a Section? **
2
2
  #
3
- # "Section" is something like "partial" which you may know from RubyOnRails.
3
+ # "Section" is something like "partial" which you may know from RubyOnRails.
4
4
  # In the first look it's just a list of elements which will be added to the "Screen".
5
- # But the magic is inside.
6
- # When you add "Element" to a "Section", e.g. image or label,
5
+ # But the magic is inside.
6
+ # When you add "Element" to a "Section", e.g. image or label,
7
7
  # it will try to draw it using CALayer/CGContext/etc, instead of adding new UIView.
8
8
  # That way increases application speed (especially on Table elements) by 5-10 times.
9
9
  #
@@ -18,7 +18,7 @@ end
18
18
 
19
19
  # ** Add some elements to the section. **
20
20
  #
21
- # Each element should have name and type: "image", "label", "button", etc.
21
+ # Each element should have name and type: "image", "label", "button", etc.
22
22
  #
23
23
  # When you send `:text` option, type will be "label" by default.
24
24
  #
@@ -31,7 +31,7 @@ class FooSection < Prime::Section
31
31
  end
32
32
 
33
33
  # ** Render Section to Screen **
34
- #
34
+ #
35
35
  # NOTE: it's recommended to use instance variables for sections, e.g. `@main_section` instead of `main_section`.
36
36
 
37
37
  class FooScreen < Prime::Screen
@@ -42,12 +42,12 @@ class FooScreen < Prime::Screen
42
42
  end
43
43
 
44
44
  # ** Add some styles for section **
45
- #
45
+ #
46
46
  # Generally styles are just attributes of UIView elements.
47
47
  #
48
48
  # Let's style the UILabel element (:welcome label element we added above.)
49
49
  #
50
- # We send :foo parameter to `define`, because we have section named `foo` (FooSection)
50
+ # We send :foo parameter to `define`, because we have section named `foo` (FooSection)
51
51
  # and :welcome parameter to `style`, because the name of element is `welcome`.
52
52
  #
53
53
  Prime::Styles.define :foo do
@@ -56,7 +56,7 @@ Prime::Styles.define :foo do
56
56
  top: 100,
57
57
  width: 320,
58
58
  left: 20,
59
- font: proc { :system.uifont(20) },
59
+ font: :system.uifont(20),
60
60
  size_to_fit: true,
61
61
  end
62
62
 
data/files/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
3
  gem 'motion-cocoapods', '~> 1.4.0'
4
- gem 'motion-prime', '0.9.5'
4
+ gem 'motion-prime', '0.9.6'
5
5
 
6
6
  # add reside menu for sidebar support
7
7
  # gem 'prime_reside_menu', '~> 0.1.4'
@@ -1,15 +1,15 @@
1
1
  class <%= @p_class_name %>FormSection < Prime::FormSection
2
2
  field :title,
3
3
  label: { text: 'Title' },
4
- input: {
5
- text: proc { form.model.title },
4
+ input: {
5
+ text: proc { model.title },
6
6
  placeholder: "Enter title here"
7
7
  }
8
8
 
9
9
  field :delete, type: :submit,
10
- button: {
11
- title: "Delete",
12
- background_color: :red
10
+ button: {
11
+ title: "Delete",
12
+ background_color: :red
13
13
  },
14
14
  action: :on_delete,
15
15
  if: proc { model.persisted? }
@@ -84,7 +84,11 @@ module MotionPrime
84
84
  compute_style_options(raw_options)
85
85
  raw_options = Styles.for(styles).merge(raw_options)
86
86
  @computed_options = raw_options
87
- 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])
87
+ normalize_options(@computed_options, section.try(:elements_eval_object), %w[
88
+ text placeholder font title_label
89
+ padding padding_left padding_right padding_top padding_bottom
90
+ left right min_width min_outer_width max_width max_outer_width width
91
+ top bottom min_height min_outer_height max_height max_outer_height height])
88
92
  end
89
93
 
90
94
  def reload!
@@ -120,7 +124,7 @@ module MotionPrime
120
124
  # {name: model.name}
121
125
  # end
122
126
  def compute_block_options
123
- section.send(:instance_exec, self, &@block) if @block
127
+ normalize_value(@block, section) if @block
124
128
  end
125
129
 
126
130
  def compute_style_options(*style_sources)
@@ -136,10 +140,10 @@ module MotionPrime
136
140
  custom_styles = []
137
141
  style_sources.each do |source|
138
142
  if source_mixins = source.delete(:mixins)
139
- mixins += Array.wrap(normalize_object(source_mixins, section))
143
+ mixins += Array.wrap(normalize_object(source_mixins, section.try(:elements_eval_object)))
140
144
  end
141
145
  if source_styles = source.delete(:styles)
142
- custom_styles += Array.wrap(normalize_object(source_styles, section))
146
+ custom_styles += Array.wrap(normalize_object(source_styles, section.try(:elements_eval_object)))
143
147
  end
144
148
  end
145
149
  # styles got from mixins option
@@ -192,7 +196,6 @@ module MotionPrime
192
196
  base_styles[:common]
193
197
  end
194
198
  all_styles += Array.wrap(common_styles)
195
-
196
199
  # form cell: user_form_field, user_form_string_field, user_form_field_email
197
200
  # form element: user_form_field_text_field, user_form_string_field_text_field, user_form_field_email_text_field
198
201
  # table cell: categories_table_cell, categories_table_title
@@ -1,13 +1,15 @@
1
1
  module MotionPrime
2
2
  module HasNormalizer
3
- def normalize_options(unordered_options, receiver = nil, order = nil)
3
+ def normalize_options(unordered_options, receiver = nil, order = nil, keys = nil)
4
4
  options = if order
5
5
  Hash[unordered_options.sort_by { |k,v| order.index(k.to_s).to_i }]
6
6
  else
7
7
  unordered_options
8
8
  end
9
9
 
10
- options.each do |key, option|
10
+ filtered_options = keys.nil? ? options : options.slice(*keys)
11
+ filtered_options.each do |key, option|
12
+ @_key_chain = [key]
11
13
  unordered_options[key] = normalize_object(option, receiver)
12
14
  end
13
15
  end
@@ -15,14 +17,41 @@ module MotionPrime
15
17
  def normalize_object(object, receiver = nil)
16
18
  receiver ||= self
17
19
  if object.is_a?(Proc)
18
- receiver.send(:instance_exec, self, &object)
20
+ normalize_value(object, receiver)
19
21
  elsif object.is_a?(Hash)
20
22
  object.inject({}) do |result, (key, nested_object)|
23
+ @_key_chain ||= []
24
+ @_key_chain << key
21
25
  result.merge(key => normalize_object(nested_object, receiver))
22
26
  end
23
27
  else
24
28
  object
25
29
  end
26
30
  end
31
+
32
+ def normalize_value(object, receiver)
33
+ if element?
34
+ receiver.send(:instance_exec, section || screen, self, &object)
35
+ else
36
+ receiver.send(:instance_exec, self, &object)
37
+ end
38
+ rescue => e
39
+ Prime.logger.error "Can't normalize: ", *debug_info, @_key_chain
40
+ raise e
41
+ end
42
+
43
+ def element?
44
+ self.is_a?(BaseElement)
45
+ end
46
+
47
+ def debug_info
48
+ if element?
49
+ [self.class.name, self.name, section.try(:name)]
50
+ elsif self.is_a?(Section)
51
+ [self.class.name, self.name, @table.try(:class).try(:name)]
52
+ else
53
+ [self.class.name]
54
+ end
55
+ end
27
56
  end
28
57
  end
@@ -24,7 +24,7 @@ module MotionPrime
24
24
  options[:add_to_view] ||= self.view
25
25
  @progress_indicator_view = self.progress_hud(options).view
26
26
  else
27
- self.setup(@progress_indicator_view, options.except(:add_to_view))
27
+ self.set_options(@progress_indicator_view, options.except(:add_to_view))
28
28
  @progress_indicator_view.show options.has_key?(:animated) ? options[:animatetd] : true
29
29
  end
30
30
  end
@@ -35,8 +35,8 @@ module MotionPrime
35
35
  @visible = true
36
36
  @on_appear_happened ||= {}
37
37
  unless @on_appear_happened[view.object_id]
38
- setup view, styles: default_styles do
39
- run_callbacks :render do
38
+ set_options view, styles: default_styles do
39
+ run_callbacks :render do
40
40
  send((action).to_sym)
41
41
  end
42
42
  end
@@ -131,7 +131,7 @@ module MotionPrime
131
131
  elements_options.each do |key, opts|
132
132
  add_element(key, opts)
133
133
  end
134
- self.instance_eval(&@options_block) if @options_block.is_a?(Proc)
134
+ elements_eval(&@options_block) if @options_block.is_a?(Proc)
135
135
 
136
136
  @section_loading = false
137
137
  return @section_loaded = true
@@ -309,6 +309,14 @@ module MotionPrime
309
309
  end
310
310
 
311
311
  protected
312
+ def elements_eval_object
313
+ self
314
+ end
315
+
316
+ def elements_eval(&block)
317
+ elements_eval_object.instance_exec(self, &block)
318
+ end
319
+
312
320
  def bind_keyboard_close
313
321
  bindings = self.class.keyboard_close_bindings
314
322
  return unless bindings.present?
@@ -323,7 +331,7 @@ module MotionPrime
323
331
 
324
332
  def keyboard_close_bindings_options
325
333
  return {} unless self.class.keyboard_close_bindings.present?
326
- @keyboard_close_bindings_options ||= normalize_options(self.class.keyboard_close_bindings.clone, self)
334
+ @keyboard_close_bindings_options ||= normalize_options(self.class.keyboard_close_bindings.clone, elements_eval_object)
327
335
  end
328
336
 
329
337
  def build_options_for_element(opts)
@@ -366,14 +374,15 @@ module MotionPrime
366
374
  raw_options.merge!(self.class.container_options.try(:clone) || {})
367
375
  raw_options.merge!(options.delete(:container) || {})
368
376
 
369
- @container_options = raw_options
377
+ # allow to pass styles as proc
378
+ normalize_options(raw_options, elements_eval_object, nil, [:styles])
379
+ @container_options = raw_options # must be here because section_styles may use container_options for custom styles
370
380
 
371
- # must be here because section_styles may use container_options for custom styles
372
381
  container_options_from_styles = Styles.for(section_styles.values.flatten)[:container] if section_styles
373
382
  if container_options_from_styles.present?
374
383
  @container_options = container_options_from_styles.merge(@container_options)
375
384
  end
376
- normalize_options(@container_options)
385
+ normalize_options(@container_options, elements_eval_object)
377
386
  end
378
387
 
379
388
  class << self
@@ -6,14 +6,13 @@ module MotionPrime
6
6
  attr_reader :form
7
7
  after_render :on_section_render
8
8
 
9
- before_initialize :prepare_table_data
10
9
  after_initialize :observe_model_errors
11
10
 
12
11
  def prepare_table_data
13
12
  @form = @options[:table]
14
13
  if options[:observe_errors]
15
14
  # Do not remove clone() after delete()
16
- @errors_observer_options = normalize_options(options.delete(:observe_errors).clone, self)
15
+ @errors_observer_options = normalize_options(options.delete(:observe_errors).clone, elements_eval_object)
17
16
  end
18
17
  end
19
18
 
@@ -50,6 +49,7 @@ module MotionPrime
50
49
  end
51
50
 
52
51
  def observe_model_errors
52
+ prepare_table_data
53
53
  return unless observing_errors?
54
54
  on_error_change = proc { |old_value, new_value|
55
55
  changes = observing_errors_for.errors.changes
@@ -187,5 +187,10 @@ module MotionPrime
187
187
  error_height = element ? element.cached_content_height + 5 : 0
188
188
  super + error_height
189
189
  end
190
+
191
+ protected
192
+ def elements_eval_object
193
+ form
194
+ end
190
195
  end
191
196
  end
@@ -3,10 +3,10 @@ module MotionPrime
3
3
  element :label, type: :label do
4
4
  default_label_options
5
5
  end
6
- element :input, type: :text_field, delegate: proc { form.table_delegate } do
6
+ element :input, type: :text_field, delegate: proc { table_delegate } do
7
7
  {secure_text_entry: true}.merge(options[:input] || {})
8
8
  end
9
- element :error_message, type: :error_message, text: proc { all_errors.join("\n") if observing_errors? }
9
+ element :error_message, type: :error_message, text: proc { |field| field.all_errors.join("\n") if field.observing_errors? }
10
10
  after_render :bind_text_input
11
11
 
12
12
  def value
@@ -9,7 +9,7 @@ module MotionPrime
9
9
  element :arrow, type: :image do
10
10
  options[:arrow] || {}
11
11
  end
12
- element :error_message, type: :error_message, text: proc { observing_errors? and all_errors.join("\n") }
12
+ element :error_message, type: :error_message, text: proc { |field| field.observing_errors? and field.all_errors.join("\n") }
13
13
 
14
14
  after_render :bind_select_button
15
15
 
@@ -5,5 +5,10 @@ module MotionPrime
5
5
  def form
6
6
  table
7
7
  end
8
+
9
+ protected
10
+ def elements_eval_object
11
+ form
12
+ end
8
13
  end
9
14
  end
@@ -4,11 +4,11 @@ module MotionPrime
4
4
  default_label_options
5
5
  end
6
6
 
7
- element :input, type: :text_field, delegate: proc { form.table_delegate } do
7
+ element :input, type: :text_field, delegate: proc { table_delegate } do
8
8
  options[:input] || {}
9
9
  end
10
10
 
11
- element :error_message, type: :error_message, text: proc { all_errors.join("\n") if observing_errors? }
11
+ element :error_message, type: :error_message, text: proc { |field| field.all_errors.join("\n") if field.observing_errors? }
12
12
  after_render :bind_text_input
13
13
 
14
14
  def value
@@ -3,7 +3,7 @@ module MotionPrime
3
3
  element :button, type: :button do
4
4
  {title: options[:name].to_s.titleize}.merge(options[:button] || {})
5
5
  end
6
- element :error_message, type: :error_message, text: proc { all_errors.join("\n") if observing_errors? }
6
+ element :error_message, type: :error_message, text: proc { |field| field.all_errors.join("\n") if field.observing_errors? }
7
7
 
8
8
  after_render :bind_button
9
9
 
@@ -3,11 +3,11 @@ module MotionPrime
3
3
  element :label, type: :label do
4
4
  default_label_options
5
5
  end
6
- element :input, type: :text_view, delegate: proc { form.table_delegate } do
6
+ element :input, type: :text_view, delegate: proc { table_delegate } do
7
7
  {editable: true}.merge(options[:input] || {})
8
8
  end
9
9
 
10
- element :error_message, type: :error_message, text: proc { observing_errors? and all_errors.join("\n") }
10
+ element :error_message, type: :error_message, text: proc { |field| field.observing_errors? and field.all_errors.join("\n") }
11
11
  after_render :bind_text_input
12
12
 
13
13
  def value
@@ -165,7 +165,7 @@ module MotionPrime
165
165
  base_styles = [type]
166
166
  base_styles << :"#{type}_with_sections" unless flat_data?
167
167
  item_styles = [name.to_sym]
168
- item_styles << @styles if @styles.present?
168
+ item_styles += Array.wrap(@styles) if @styles.present?
169
169
  {common: base_styles, specific: item_styles}
170
170
  end
171
171
 
@@ -216,13 +216,13 @@ module MotionPrime
216
216
  end
217
217
 
218
218
  def table_element_options
219
- {
219
+ container_options.slice(:render_target).merge({
220
220
  section: self.weak_ref,
221
221
  styles: table_styles.values.flatten,
222
222
  delegate: table_delegate,
223
223
  data_source: table_delegate,
224
224
  style: (UITableViewStyleGrouped unless flat_data?)
225
- }
225
+ })
226
226
  end
227
227
 
228
228
  def render_table
@@ -388,9 +388,11 @@ module MotionPrime
388
388
  end
389
389
 
390
390
  def container_element_options_for(index)
391
+ cell_section = cell_section_by_index(index)
391
392
  {
392
393
  reuse_identifier: cell_name(table_view, index),
393
- parent_view: table_view
394
+ parent_view: table_view,
395
+ bounds: {height: cell_section.container_height}
394
396
  }
395
397
  end
396
398
 
@@ -4,7 +4,7 @@ module MotionPrime
4
4
  screen.automaticallyAdjustsScrollViewInsets = false
5
5
 
6
6
  table_view.addPullToRefreshWithActionHandler(block) # block must be a variable
7
- screen.setup table_view.pullToRefreshView, styles: [:base_pull_to_refresh]
7
+ screen.set_options table_view.pullToRefreshView, styles: [:base_pull_to_refresh]
8
8
  end
9
9
 
10
10
  def finish_pull_to_refresh
@@ -66,7 +66,6 @@ MotionPrime::Styles.define :base_form do
66
66
  top: 30,
67
67
  height: 35,
68
68
  title_shadow_color: :white,
69
- content_horizontal_alignment: :left,
70
69
  layer: {
71
70
  border_color: :gray,
72
71
  border_width: 1
@@ -1,3 +1,3 @@
1
1
  module MotionPrime
2
- VERSION = "0.9.5"
2
+ VERSION = "0.9.6"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  module MotionPrime
2
2
  module FrameCalculatorMixin
3
- def calculate_frame_for(bounds, options)
3
+ def calculate_frame_for(parent_bounds, options)
4
4
  width = options[:width]
5
5
  height = options[:height]
6
6
  top = options[:top]
@@ -14,11 +14,11 @@ module MotionPrime
14
14
  height = options[:height_to_fit]
15
15
  end
16
16
 
17
- return bounds if width.nil? && height.nil? && right.nil? && bottom.nil?
17
+ return parent_bounds if width.nil? && height.nil? && right.nil? && bottom.nil?
18
18
  frame = CGRectMake(0,0,0,0)
19
19
 
20
- max_width = bounds.size.width
21
- max_height = bounds.size.height
20
+ max_width = parent_bounds.size.width
21
+ max_height = parent_bounds.size.height
22
22
  width = 0.0 if width.nil?
23
23
  height = 0.0 if height.nil?
24
24
 
@@ -8,36 +8,36 @@ module MotionPrime
8
8
  render_target = options.delete(:render_target)
9
9
  parent_view = options.delete(:parent_view) || render_target
10
10
 
11
- bounds = if view_stack.empty?
11
+ parent_bounds = if view_stack.empty?
12
12
  parent_view.try(:bounds) || CGRectZero
13
13
  else
14
14
  view_stack.last.bounds
15
15
  end
16
16
  builder = ViewBuilder.new(klass, options)
17
- options = builder.options.merge(calculate_frame: true, bounds: bounds)
17
+ options = builder.options.merge(calculate_frame: true, parent_bounds: parent_bounds)
18
18
  view = builder.view
19
19
  insert_index = options.delete(:at_index)
20
20
 
21
- if render_target
22
- options[:bounds] = render_target.bounds
23
- insert_index ? render_target.insertSubview(view, atIndex: insert_index) : render_target.addSubview(view)
24
- elsif view_stack.any?
25
- insert_index ? view_stack.last.insertSubview(view, atIndex: insert_index) : view_stack.last.addSubview(view)
21
+ set_options(view, options, &block)
22
+ if superview = render_target || view_stack.last
23
+ insert_index ? superview.insertSubview(view, atIndex: insert_index) : superview.addSubview(view)
26
24
  end
27
-
28
- setup(view, options, &block)
29
25
  view.on_added if view.respond_to?(:on_added)
30
-
31
26
  view
32
27
  end
33
28
 
34
- def setup(view, options = {}, &block)
35
- ViewStyler.new(view, options.delete(:bounds), options).apply
29
+ def set_options(view, options = {}, &block)
30
+ ViewStyler.new(view, options.delete(:parent_bounds), options).apply
36
31
  view_stack.push(view)
37
32
  block.call(view) if block_given?
38
33
  view_stack.pop
39
34
  end
40
35
 
36
+ def setup(view, options = {}, &block)
37
+ puts "DEPRECATION: screen#setup is deprecated, please use screen#set_options instead"
38
+ set_options(view, options, &block)
39
+ end
40
+
41
41
  def view_stack
42
42
  @view_stack ||= []
43
43
  end
@@ -7,10 +7,10 @@ module MotionPrime
7
7
 
8
8
  attr_reader :view, :options
9
9
 
10
- def initialize(view, bounds = CGRectZero, options = {})
10
+ def initialize(view, parent_bounds = CGRectZero, options = {})
11
11
  @options = Styles.extend_and_normalize_options options
12
12
  @view = view
13
- prepare_frame_for(bounds) if @options.delete(:calculate_frame)
13
+ prepare_frame_for(parent_bounds) if @options.delete(:calculate_frame)
14
14
  prepare_options!
15
15
  end
16
16
 
@@ -29,8 +29,8 @@ module MotionPrime
29
29
  end
30
30
  end
31
31
 
32
- def prepare_frame_for(bounds)
33
- options[:frame] = calculate_frame_for(bounds, options.merge(test: view.is_a?(UITextView)))
32
+ def prepare_frame_for(parent_bounds)
33
+ options[:frame] = calculate_frame_for(parent_bounds, options)
34
34
  if options.slice(:width, :height, :right, :bottom, :height_to_fit).values.any?
35
35
  mask = UIViewAutoresizingNone
36
36
  mask |= UIViewAutoresizingFlexibleTopMargin if options[:top].nil?
@@ -77,6 +77,9 @@ module MotionPrime
77
77
  :text_alignment, :font, :line_break_mode, :number_of_lines
78
78
  ]
79
79
  attributed_text_options = options.slice(*text_attributes)
80
+ if view.is_a?(UIButton)
81
+ attributed_text_options[:text] ||= options[:title]
82
+ end
80
83
  options.except!(*text_attributes)
81
84
  attributed_text_options
82
85
  end
@@ -141,7 +144,10 @@ module MotionPrime
141
144
  end
142
145
 
143
146
  def set_text_options(key, value)
144
- if key.end_with?('alignment') && value.is_a?(Symbol)
147
+ if key == 'content_horizontal_alignment' && value.is_a?(Symbol) && %[left right center fill].include?(value.to_s)
148
+ view.setValue "UIControlContentHorizontalAlignment#{value.camelize}".constantize, forKey: camelize_factory(key)
149
+ true
150
+ elsif key.end_with?('alignment') && value.is_a?(Symbol)
145
151
  view.setValue value.uitextalignment, forKey: camelize_factory(key)
146
152
  true
147
153
  elsif key.end_with?('line_break_mode') && value.is_a?(Symbol)
@@ -166,7 +172,7 @@ module MotionPrime
166
172
  current_inset.send("#{key.partition('_').first}=", value)
167
173
  view.contentInset = current_inset
168
174
  true
169
- elsif key.end_with?('inset')
175
+ elsif key.end_with?('inset') || key.end_with?('indicator_insets')
170
176
  inset = if value.to_s == 'none'
171
177
  UIEdgeInsetsMake(0, 320, 0, 0)
172
178
  elsif value.is_a?(Array) && value.count == 2
@@ -181,16 +187,38 @@ module MotionPrime
181
187
 
182
188
  def set_layer_options(key, value)
183
189
  if key == 'rounded_corners'
190
+ layer_bounds = bounds
191
+ if value[:overlap]
192
+ size = layer_bounds.size
193
+ size.height += value.fetch(:border_width, 0) # overlap to the next cell
194
+ layer_bounds.size = size
195
+ end
196
+
184
197
  radius = value[:radius].to_f
185
198
  corner_consts = {top_left: UIRectCornerTopLeft, bottom_left: UIRectCornerBottomLeft, bottom_right: UIRectCornerBottomRight, top_right: UIRectCornerTopRight}
186
199
  corners = value[:corners].inject(0) { |result, corner| result|corner_consts[corner] }
187
- size = options[:parent_frame].size
188
- bounds = CGRectMake(0, 0, size.width, size.height)
189
- mask_path = UIBezierPath.bezierPathWithRoundedRect(bounds, byRoundingCorners: corners, cornerRadii: CGSizeMake(radius, radius))
200
+ mask_path = UIBezierPath.bezierPathWithRoundedRect(layer_bounds, byRoundingCorners: corners, cornerRadii: CGSizeMake(radius, radius))
190
201
  mask_layer = CAShapeLayer.layer
191
- mask_layer.frame = bounds
202
+
203
+
204
+ mask_layer.frame = layer_bounds
192
205
  mask_layer.path = mask_path.CGPath
193
206
  view.mask = mask_layer
207
+
208
+ if value[:border_color] && value[:border_width]
209
+ stroke_layer = CAShapeLayer.layer
210
+ stroke_layer.path = mask_path.CGPath
211
+ stroke_layer.fillColor = :clear.uicolor.cgcolor
212
+ stroke_layer.strokeColor = value[:border_color].uicolor.cgcolor
213
+ stroke_layer.lineWidth = value[:border_width].to_f*2 # another half is hidden by the mask
214
+
215
+ container_view = view.delegate
216
+ stroke_view = UIView.alloc.initWithFrame(layer_bounds)
217
+ stroke_view.userInteractionEnabled = false
218
+ stroke_view.layer.addSublayer(stroke_layer)
219
+ container_view.addSubview(stroke_view)
220
+ view.addSublayer(stroke_layer)
221
+ end
194
222
  true
195
223
  end
196
224
  end
@@ -199,7 +227,7 @@ module MotionPrime
199
227
  if value.is_a?(Hash)
200
228
  self.class.new(
201
229
  view.send(low_camelize_factory(key).to_sym), nil,
202
- value.merge(parent_frame: options[:frame] || options[:parent_frame])
230
+ value.merge(parent_frame: options[:frame] || options[:parent_frame], bounds: options[:bounds])
203
231
  ).apply
204
232
  true
205
233
  end
@@ -227,9 +255,17 @@ module MotionPrime
227
255
  width height top right bottom left
228
256
  max_width max_outer_width min_width min_outer_width
229
257
  max_height max_outer_height min_height min_outer_width
258
+ bounds
230
259
  ].include?(key.to_s)
231
260
  end
232
261
 
262
+ def bounds
263
+ # TODO: raise error if parent_frame is nill
264
+ frame_size = options[:parent_frame].size
265
+ bounds_options = options[:bounds] || {}
266
+ CGRectMake(0, 0, bounds_options.fetch(:width, frame_size.width), bounds_options.fetch(:height, frame_size.height))
267
+ end
268
+
233
269
  STRUCTS_MAP = {
234
270
  CGAffineTransform => Proc.new {|v| NSValue.valueWithCGAffineTransform(v) },
235
271
  CGPoint => Proc.new {|v| NSValue.valueWithCGPoint(v) },
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-prime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5
4
+ version: 0.9.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iskander Haziev
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-24 00:00:00.000000000 Z
12
+ date: 2014-03-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake