motion-prime 0.5.6 → 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,56 +4,59 @@
4
4
  <head>
5
5
  <title>sections.rb</title>
6
6
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
7
- <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
7
+ <link rel="stylesheet" media="all" href="public/stylesheets/normalize.css" />
8
8
  <link rel="stylesheet" media="all" href="docco.css" />
9
9
  </head>
10
10
  <body>
11
- <div id="container">
12
- <div id="background"></div>
13
-
14
- <ul id="jump_to">
15
- <li>
16
- <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
17
- <a class="small" href="javascript:void(0);">+</a>
18
- <div id="jump_wrapper">
19
- <div id="jump_page">
20
-
11
+ <div class="container">
12
+ <div class="page">
13
+
14
+ <div class="header">
15
+
16
+ <h1>sections.rb</h1>
17
+
18
+
19
+
20
+ <div class="toc">
21
+ <h3>Table of Contents</h3>
22
+ <ol>
23
+
24
+
25
+ <li>
26
+ <a class="source" href="getting_started.html">
27
+ getting_started.rb
28
+ </a>
29
+ </li>
30
+
31
+
32
+ <li>
33
+ <a class="source" href="models.html">
34
+ models.rb
35
+ </a>
36
+ </li>
21
37
 
22
- <a class="source" href="getting_started.html">
23
- getting_started.rb
24
- </a>
25
-
38
+
39
+ <li>
40
+ <a class="source" href="screens.html">
41
+ screens.rb
42
+ </a>
43
+ </li>
26
44
 
27
- <a class="source" href="screens.html">
28
- screens.rb
29
- </a>
30
-
45
+
46
+ <li>
47
+ <a class="source" href="sections.html">
48
+ sections.rb
49
+ </a>
50
+ </li>
31
51
 
32
- <a class="source" href="sections.html">
33
- sections.rb
34
- </a>
35
-
52
+ </ol>
36
53
  </div>
37
- </li>
38
- </ul>
39
-
40
- <ul class="sections">
41
-
42
- <li id="title">
43
- <div class="annotation">
44
- <h1>sections.rb</h1>
45
- </div>
46
- </li>
47
-
48
54
 
55
+ </div>
56
+
57
+
49
58
 
50
- <li id="section-1">
51
- <div class="annotation">
52
-
53
- <div class="pilwrap ">
54
- <a class="pilcrow" href="#section-1">&#182;</a>
55
- </div>
56
- <p><strong> What is a Section? </strong></p>
59
+ <p><strong> What is a Section? </strong></p>
57
60
  <p>&quot;Section&quot; is something like &quot;partial&quot; which you may know from RubyOnRails.
58
61
  In the first look it&#39;s just a list of elements which will be added to the &quot;Screen&quot;.
59
62
  But the magic is inside.
@@ -61,74 +64,68 @@ When you add &quot;Element&quot; to a &quot;Section&quot;, e.g. image or label,
61
64
  it will try to draw it using CALayer/CGContext/etc, instead of adding new UIView.
62
65
  That way increases application speed (especially on Table elements) by 5-10 times.</p>
63
66
  <p>Let&#39;s get started.</p>
64
-
65
- </div>
66
-
67
- <div class="content"><div class='highlight'><pre>---</pre></div></div>
68
-
69
- </li>
70
-
71
-
72
- <li id="section-2">
73
- <div class="annotation">
74
-
75
- <div class="pilwrap ">
76
- <a class="pilcrow" href="#section-2">&#182;</a>
77
- </div>
78
- <p><strong> Create a section. </strong></p>
67
+ <p><strong> Create a section. </strong></p>
79
68
  <p>Just inherit it from <code>Prime::Section</code>.</p>
80
69
 
81
- </div>
82
-
83
- <div class="content"><div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">FooSection</span> <span class="inheritance">&lt; <span class="parent">Prime::Section</span></span></span>
84
- <span class="keyword">end</span></pre></div></div>
85
-
86
- </li>
87
70
 
71
+ <div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">FooSection</span> <span class="inheritance">&lt; <span class="parent">Prime::Section</span></span></span>
72
+ <span class="keyword">end</span></pre></div>
88
73
 
89
- <li id="section-3">
90
- <div class="annotation">
91
-
92
- <div class="pilwrap ">
93
- <a class="pilcrow" href="#section-3">&#182;</a>
94
- </div>
95
- <p><strong> Add some elements to the section. </strong></p>
96
- <p>Each element should have name and type: &quot;image&quot;, &quot;label&quot;, &quot;button&quot;, etc.
97
- When you send <code>:text</code> option, type will be &quot;label&quot; by default.
98
- When you send <code>:image</code> option, type will be &quot;image&quot; by default.</p>
74
+
75
+
76
+ <p><strong> Add some elements to the section. </strong></p>
77
+ <p>Each element should have name and type: &quot;image&quot;, &quot;label&quot;, &quot;button&quot;, etc. </p>
78
+ <p>When you send <code>:text</code> option, type will be &quot;label&quot; by default.</p>
79
+ <p>When you send <code>:image</code> option, type will be &quot;image&quot; by default.</p>
99
80
 
100
- </div>
101
-
102
- <div class="content"><div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">FooSection</span> <span class="inheritance">&lt; <span class="parent">Prime::Section</span></span></span>
81
+
82
+ <div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">FooSection</span> <span class="inheritance">&lt; <span class="parent">Prime::Section</span></span></span>
103
83
  element <span class="symbol">:welcome</span>, <span class="symbol">text:</span> <span class="string">'Hello World!'</span>
104
84
  element <span class="symbol">:avatar</span>, <span class="symbol">image:</span> <span class="string">'images/users/avatar.jpg'</span>
105
85
  element <span class="symbol">:cheer</span>, <span class="symbol">type:</span> <span class="symbol">:button</span>
106
- <span class="keyword">end</span></pre></div></div>
107
-
108
- </li>
86
+ <span class="keyword">end</span></pre></div>
109
87
 
88
+
110
89
 
111
- <li id="section-4">
112
- <div class="annotation">
113
-
114
- <div class="pilwrap ">
115
- <a class="pilcrow" href="#section-4">&#182;</a>
116
- </div>
117
- <p><strong> Render Section in Screen </strong></p>
118
- <p>NOTE: You must send &quot;screen&quot; option on section initialization.</p>
90
+ <p><strong> Render Section to Screen </strong></p>
91
+ <p>NOTE: it&#39;s recommended to use instance variables for sections, e.g. <code>@main_section</code> instead of <code>main_section</code>.</p>
119
92
 
120
- </div>
121
-
122
- <div class="content"><div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">FooScreen</span> <span class="inheritance">&lt; <span class="parent">Prime::Screen</span></span></span>
93
+
94
+ <div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">FooScreen</span> <span class="inheritance">&lt; <span class="parent">Prime::Screen</span></span></span>
123
95
  <span class="function"><span class="keyword">def</span> <span class="title">render</span></span>
124
96
  <span class="variable">@main_section</span> = <span class="constant">FooSection</span>.new(<span class="symbol">screen:</span> <span class="keyword">self</span>)
125
97
  <span class="variable">@main_section</span>.render
126
98
  <span class="keyword">end</span>
127
- <span class="keyword">end</span></pre></div></div>
128
-
129
- </li>
99
+ <span class="keyword">end</span></pre></div>
100
+
101
+
102
+
103
+ <p><strong> Add some styles for section </strong></p>
104
+ <p>Generally styles are just attributes of UIView elements.</p>
105
+ <p>Let&#39;s style the UILabel element (:welcome label element we added above.)</p>
106
+ <p>We send :foo parameter to <code>define</code>, because we have section named <code>foo</code> (FooSection)
107
+ and :welcome parameter to <code>style</code>, because the name of element is <code>welcome</code>.</p>
108
+
109
+
110
+ <div class='highlight'><pre><span class="constant">Prime::Styles</span>.define <span class="symbol">:foo</span> <span class="keyword">do</span>
111
+ style <span class="symbol">:welcome</span>,
112
+ <span class="symbol">text_color:</span> <span class="symbol">:black</span>,
113
+ <span class="symbol">top:</span> <span class="number">100</span>,
114
+ <span class="symbol">width:</span> <span class="number">320</span>,
115
+ <span class="symbol">left:</span> <span class="number">20</span>,
116
+ <span class="symbol">font:</span> proc { <span class="symbol">:system</span>.uifont(<span class="number">20</span>) },
117
+ <span class="symbol">size_to_fit:</span> <span class="keyword">true</span>,
118
+ <span class="keyword">end</span></pre></div>
119
+
120
+
121
+
122
+ <p><strong> Next </strong></p>
123
+ <p><a href="models.html">Read more about Models</a></p>
124
+
130
125
 
131
- </ul>
126
+
127
+ <div class="fleur">h</div>
128
+ </div>
132
129
  </div>
133
130
  </body>
134
131
  </html>
@@ -5,7 +5,7 @@ gem 'motion-support', '~> 0.2.4'
5
5
  gem 'sugarcube', '~> 1.3.7', require: 'sugarcube-classic'
6
6
  gem 'bubble-wrap', '~> 1.4.0'
7
7
 
8
- gem 'motion-prime', '~> 0.5.4'
8
+ gem 'motion-prime', '~> 0.5.6'
9
9
 
10
10
  # add reside menu for sidebar support
11
11
  gem 'prime_reside_menu', '~> 0.1.3'
@@ -34,7 +34,7 @@ GEM
34
34
  bundler
35
35
  motion-cocoapods (1.4.0)
36
36
  cocoapods (>= 0.26.2)
37
- motion-prime (0.5.4)
37
+ motion-prime (0.5.6)
38
38
  bubble-wrap
39
39
  cocoapods
40
40
  methadone
@@ -67,7 +67,7 @@ PLATFORMS
67
67
  DEPENDENCIES
68
68
  bubble-wrap (~> 1.4.0)
69
69
  motion-cocoapods (~> 1.4.0)
70
- motion-prime (~> 0.5.4)
70
+ motion-prime (~> 0.5.6)
71
71
  motion-support (~> 0.2.4)
72
72
  prime_reside_menu (~> 0.1.3)
73
73
  sugarcube (~> 1.3.7)
@@ -0,0 +1,10 @@
1
+ class Time
2
+ def to_short_iso8601
3
+ clone.utc.strftime("%Y%m%dT%H%M%SZ")
4
+ end
5
+
6
+ def self.short_iso8601(time)
7
+ cached_date_formatter("yyyyMMdd'T'HHmmss'Z'").
8
+ dateFromString(time.gsub(/[\:\-]*/, ''))
9
+ end
10
+ end
@@ -15,6 +15,10 @@ module MotionPrime
15
15
  bag.save
16
16
  end
17
17
  super
18
+ rescue StoreError => e
19
+ if Prime.env.development?
20
+ raise StoreError, e.description
21
+ end
18
22
  end
19
23
 
20
24
  module ClassMethods
@@ -156,14 +156,23 @@ module MotionPrime
156
156
  attributes << name
157
157
 
158
158
  define_method(name) do |*args, &block|
159
- self.info[name]
159
+ value = self.info[name]
160
+ case options[:type].to_s
161
+ when 'time'
162
+ value = Time.short_iso8601(value) if value
163
+ end
164
+ value
160
165
  end
161
166
 
162
167
  define_method((name + "=").to_sym) do |*args, &block|
163
168
  value = args[0]
164
169
  case options[:type].to_s
165
- when 'integer' then value = value.to_i
166
- when 'float' then value = value.to_f
170
+ when 'integer'
171
+ value = value.to_i
172
+ when 'float'
173
+ value = value.to_f
174
+ when 'time'
175
+ value = value.to_short_iso8601 unless value.is_a?(String)
167
176
  end unless value.nil?
168
177
 
169
178
  self.info[name] = value
@@ -11,8 +11,14 @@ module MotionPrime
11
11
  old_attrs = self.info.clone
12
12
  result = block.call
13
13
  new_attrs = self.info.clone
14
+ new_bags = self._bags.clone
14
15
  new_attrs.each do |key, value|
15
- if value != old_attrs[key] && ! @_changed_attributes.has_key?(key.to_s)
16
+ if value != old_attrs[key] && !@_changed_attributes.has_key?(key.to_s)
17
+ @_changed_attributes[key.to_s] = old_attrs[key]
18
+ end
19
+ end
20
+ new_bags.each do |key, value|
21
+ if value.key != old_attrs[key] && !@_changed_attributes.has_key?(key.to_s)
16
22
  @_changed_attributes[key.to_s] = old_attrs[key]
17
23
  end
18
24
  end
@@ -100,8 +100,15 @@ module MotionPrime
100
100
  alias_method :clear, :delete_all
101
101
 
102
102
 
103
- def store=(store)
104
- store.addObject(self, error:nil)
103
+ def store=(store, retry_count = 0)
104
+ store.addObject(self, error: nil)
105
+ rescue Exception => e
106
+ sleep(0.1)
107
+ if retry_count == 3
108
+ raise StoreError, e.description
109
+ else
110
+ send (:store=, store, retry_count + 1)
111
+ end
105
112
  end
106
113
 
107
114
  def save
@@ -236,22 +236,24 @@ module MotionPrime
236
236
  model_class = key.classify.constantize
237
237
  self.store.save_interval = data.count
238
238
  # Update/Create existing records
239
- data.each do |attributes|
240
- model = old_collection.detect{ |model| model.id == attributes[:id]}
241
- unless model
242
- model = model_class.new
243
- self.send(:"#{key}_bag") << model
239
+ track_changed_attributes do
240
+ data.each do |attributes|
241
+ model = old_collection.detect{ |model| model.id == attributes[:id]}
242
+ unless model
243
+ model = model_class.new
244
+ self.send(:"#{key}_bag") << model
245
+ end
246
+ model.fetch_with_attributes(attributes, save_associations: sync_options[:save])
247
+ model.save if sync_options[:save] && model.has_changed?
244
248
  end
245
- model.fetch_with_attributes(attributes, save_associations: sync_options[:save])
246
- model.save if sync_options[:save] && model.has_changed?
247
- end
248
- old_collection.each do |old_model|
249
- model = data.detect{ |model| model[:id] == old_model.id}
250
- unless model
251
- old_model.delete
249
+ old_collection.each do |old_model|
250
+ model = data.detect{ |model| model[:id] == old_model.id}
251
+ unless model
252
+ old_model.delete
253
+ end
252
254
  end
253
255
  end
254
- save if sync_options[:save]
256
+ save if sync_options[:save] && has_changed?
255
257
  self.store.save_interval = 1
256
258
  end
257
259
 
@@ -271,13 +273,16 @@ module MotionPrime
271
273
  end
272
274
 
273
275
  def fetch_has_one_with_attributes(key, data, sync_options = {})
274
- model = self.send(key)
275
- unless model
276
- model = key.classify.constantize.new
277
- self.send(:"#{key}_bag") << model
276
+ track_changed_attributes do
277
+ model = self.send(key)
278
+ unless model
279
+ model = key.classify.constantize.new
280
+ self.send(:"#{key}_bag") << model
281
+ end
282
+ model.fetch_with_attributes(data)
283
+ model.save if sync_options[:save]
278
284
  end
279
- model.fetch_with_attributes(data)
280
- model.save if sync_options[:save]
285
+ save if sync_options[:save] && has_changed?
281
286
  end
282
287
 
283
288
  def filtered_updatable_attributes(options = {})
@@ -158,18 +158,22 @@ module MotionPrime
158
158
  index = opts.delete(:at)
159
159
  options = build_options_for_element(opts)
160
160
  options[:name] ||= key
161
-
162
- type = options.delete(:type)
163
- element = if self.is_a?(BaseFieldSection) || self.is_a?(BaseHeaderSection) || options.delete(:as).to_s == 'view'
164
- MotionPrime::BaseElement.factory(type, options)
161
+ element = build_element(options)
162
+ if index
163
+ new_elements_array = elements.to_a.insert(index, [key, element])
164
+ self.elements = Hash[new_elements_array]
165
165
  else
166
- MotionPrime::DrawElement.factory(type, options) || MotionPrime::BaseElement.factory(type, options)
166
+ self.elements[key] = element
167
167
  end
168
+ end
168
169
 
169
- if index
170
- self.elements = Hash[self.elements.to_a.insert index, [key, element]]
170
+ def build_element(options = {})
171
+ type = options.delete(:type)
172
+ render_as = options.delete(:as).to_s
173
+ if self.is_a?(BaseFieldSection) || self.is_a?(BaseHeaderSection) || render_as == 'view'
174
+ BaseElement.factory(type, options)
171
175
  else
172
- self.elements[key] = element
176
+ DrawElement.factory(type, options) || BaseElement.factory(type, options)
173
177
  end
174
178
  end
175
179
 
@@ -282,8 +286,11 @@ module MotionPrime
282
286
 
283
287
  protected
284
288
  def bind_keyboard_close
285
- return unless self.class.keyboard_close_bindings.present?
286
- Array.wrap(self.instance_eval(&self.class.keyboard_close_bindings[:tap_on])).each do |view|
289
+ bindings = self.class.keyboard_close_bindings
290
+ return unless bindings.present?
291
+ bind_proc = bindings[:tap_on]
292
+ bind_views = instance_eval(&bind_proc)
293
+ Array.wrap(bind_views).each do |view|
287
294
  gesture_recognizer = UITapGestureRecognizer.alloc.initWithTarget(self, action: :hide_keyboard)
288
295
  view.addGestureRecognizer(gesture_recognizer)
289
296
  gesture_recognizer.cancelsTouchesInView = false