motion-prime 0.9.5 → 0.9.6

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