motion-prime 0.5.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +3 -1
- data/README.md +10 -1
- data/ROADMAP.md +10 -6
- data/files/Gemfile +2 -2
- data/files/Gemfile.lock +15 -13
- data/files/Rakefile +1 -0
- data/files/app/app_delegate.rb +1 -1
- data/lib/motion-prime.rb +2 -2
- data/motion-prime.gemspec +1 -0
- data/motion-prime/api_client.rb +71 -29
- data/motion-prime/app_delegate.rb +1 -1
- data/motion-prime/config/base.rb +8 -1
- data/motion-prime/core_ext/kernel.rb +4 -3
- data/motion-prime/elements/_content_text_mixin.rb +5 -3
- data/motion-prime/elements/_text_mixin.rb +1 -1
- data/motion-prime/elements/base_element.rb +5 -4
- data/motion-prime/elements/draw/image.rb +3 -4
- data/motion-prime/elements/draw/label.rb +3 -3
- data/motion-prime/env.rb +3 -1
- data/motion-prime/models/errors.rb +1 -0
- data/motion-prime/models/store.rb +1 -1
- data/motion-prime/screens/screen.rb +11 -6
- data/motion-prime/sections/_draw_section_mixin.rb +4 -0
- data/motion-prime/sections/base_section.rb +3 -3
- data/motion-prime/sections/form/base_field_section.rb +21 -2
- data/motion-prime/sections/form/date_field_section.rb +9 -2
- data/motion-prime/sections/form/submit_field_section.rb +3 -1
- data/motion-prime/sections/table.rb +7 -2
- data/motion-prime/styles/base.rb +2 -2
- data/motion-prime/styles/form.rb +8 -2
- data/motion-prime/support/mp_cell_content_view.rb +12 -0
- data/motion-prime/support/mp_cell_with_section.rb +16 -14
- data/motion-prime/support/tab_bar_controller.rb +28 -7
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/layout.rb +2 -1
- data/motion-prime/views/view_builder.rb +5 -2
- data/motion-prime/views/view_styler.rb +33 -17
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NWM1NzdlODhjMWNjZjU2ZDMwYjNhYzExNDBiNjA2OTE1MDAyYThmNg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzE4MTM4ZGI1YmIxZjExNjkxZWYwMzM5NWRlMmNjZDViZDBhMjBjOA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NWQ0NjVjYzAyYzQ2NThiOGJkNGU2OTNiYzZmMDA1N2JhOTQ4MTBjNjc1N2Jl
|
10
|
+
NjI4ZWRkM2IzNWRjOTZhOTdmYzNjMDkyMzFjMjcwZTczNmYxMzAyZjRmZmIw
|
11
|
+
NDQzZGY3Y2EwYjIxZmY4OGEyODVhMWViNTM0MWUxYjhhMWRkMTU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZGIxZTA4OWY1NzRhMTRjMDY0NDE3YmIwMDM5M2ZjZTBjNGFlYWI0Yzk2YzI0
|
14
|
+
NDBmOTQ0MWVhNDdhZGEzNGU0ZTY0MzdlYmU3MzY5YjE1MTBmZWIyY2RhYjE5
|
15
|
+
YTQ5NjI5ZGVkNjM1OTQzM2ZhOTU3NzBkYzBlZmM5OWU5OTQyOTY=
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
motion-prime (0.5.
|
4
|
+
motion-prime (0.5.3)
|
5
5
|
bubble-wrap
|
6
6
|
cocoapods
|
7
7
|
methadone
|
8
8
|
motion-cocoapods
|
9
9
|
motion-require
|
10
10
|
motion-support
|
11
|
+
rm-digest
|
11
12
|
sugarcube
|
12
13
|
|
13
14
|
GEM
|
@@ -53,6 +54,7 @@ GEM
|
|
53
54
|
nap (0.6.0)
|
54
55
|
open4 (1.3.0)
|
55
56
|
rake (10.1.0)
|
57
|
+
rm-digest (0.0.2)
|
56
58
|
sugarcube (1.3.7)
|
57
59
|
xcodeproj (0.14.1)
|
58
60
|
activesupport (~> 3.0)
|
data/README.md
CHANGED
@@ -4,6 +4,11 @@
|
|
4
4
|
|
5
5
|
MotionPrime is yet another framework written on RubyMotion for creating really fast iOS applications.
|
6
6
|
|
7
|
+
## Why MotionPrime?
|
8
|
+
|
9
|
+
* Performance. MotionPrime designed to improve creating and scrolling performance of table views.
|
10
|
+
* Simplicity. Creating first MotionPrime application is as simple as creating new RubyOnRails application.
|
11
|
+
|
7
12
|
## Getting Started
|
8
13
|
|
9
14
|
### 1. Install MotionPrime:
|
@@ -65,6 +70,10 @@ MotionPrime is yet another framework written on RubyMotion for creating really f
|
|
65
70
|
* [ECSlidingViewController 2 integration](https://github.com/droidlabs/prime_sliding_menu) (Sidebar)
|
66
71
|
* [RESideMenu integration](https://github.com/droidlabs/prime_reside_menu) (Sidebar)
|
67
72
|
|
73
|
+
## Samples
|
74
|
+
|
75
|
+
* [Simple to-do app](https://github.com/droidlabs/prime_sample_todo)
|
76
|
+
|
68
77
|
## Contributing
|
69
78
|
|
70
79
|
1. Fork it
|
@@ -73,7 +82,7 @@ MotionPrime is yet another framework written on RubyMotion for creating really f
|
|
73
82
|
4. Push to the branch (`git push origin my-new-feature`)
|
74
83
|
5. Create new Pull Request
|
75
84
|
|
76
|
-
## Documentation
|
85
|
+
## Help with Documentation
|
77
86
|
|
78
87
|
We are using [Docco](http://jashkenas.github.io/docco/) to generate documentation.
|
79
88
|
|
data/ROADMAP.md
CHANGED
@@ -1,16 +1,20 @@
|
|
1
1
|
=== 0.6.0
|
2
|
+
* deprecate root level :title option for submit field
|
3
|
+
* rename submit element in submit field to button element
|
4
|
+
* rename date_picker element in date_picker field to input element
|
5
|
+
* add more and better default options for fields
|
6
|
+
|
7
|
+
=== 0.7.0
|
2
8
|
* add cleanup for section events
|
3
|
-
* add computed_options.get(), this will allow to make sure that options is computed.
|
4
9
|
* add dsl for push notifications
|
5
10
|
* add some extensions/middleware system, at least for networking.
|
6
11
|
* create "display_network_error" extension.
|
7
12
|
* add different templates. some templates should be more like final app.
|
8
13
|
|
9
|
-
=== 0.
|
14
|
+
=== 0.8.0
|
15
|
+
* add computed_options.get(), this will allow to make sure that options is computed.
|
10
16
|
* add testing framework
|
11
|
-
* add auth backends to ApiClient: password auth and facebook auth
|
12
17
|
|
13
|
-
=== 0.
|
18
|
+
=== 0.9.0
|
14
19
|
* add sections/screens/models generator
|
15
|
-
* add DSL for ViewStyles#setValue conditions
|
16
|
-
* add auto-symbol-value for Prime::Config.color items
|
20
|
+
* add DSL for ViewStyles#setValue conditions
|
data/files/Gemfile
CHANGED
@@ -3,9 +3,9 @@ source 'http://rubygems.org'
|
|
3
3
|
gem 'motion-cocoapods', '~> 1.4.0'
|
4
4
|
gem 'motion-support', '~> 0.2.4'
|
5
5
|
gem 'sugarcube', '~> 1.3.7', require: 'sugarcube-classic'
|
6
|
-
gem 'bubble-wrap', '~> 1.
|
6
|
+
gem 'bubble-wrap', '~> 1.4.0'
|
7
7
|
|
8
|
-
gem 'motion-prime', '~> 0.5.
|
8
|
+
gem 'motion-prime', '~> 0.5.2'
|
9
9
|
|
10
10
|
# add reside menu for sidebar support
|
11
11
|
gem 'prime_reside_menu', '~> 0.1.3'
|
data/files/Gemfile.lock
CHANGED
@@ -4,35 +4,37 @@ GEM
|
|
4
4
|
activesupport (3.2.16)
|
5
5
|
i18n (~> 0.6, >= 0.6.4)
|
6
6
|
multi_json (~> 1.0)
|
7
|
-
bubble-wrap (1.
|
7
|
+
bubble-wrap (1.4.0)
|
8
8
|
claide (0.4.0)
|
9
|
-
cocoapods (0.
|
9
|
+
cocoapods (0.29.0)
|
10
10
|
activesupport (>= 3.2.15, < 4)
|
11
11
|
claide (~> 0.4.0)
|
12
|
-
cocoapods-core (= 0.
|
13
|
-
cocoapods-downloader (~> 0.
|
12
|
+
cocoapods-core (= 0.29.0)
|
13
|
+
cocoapods-downloader (~> 0.3.0)
|
14
|
+
cocoapods-try-release-fix (~> 0.1.1)
|
14
15
|
colored (~> 1.2)
|
15
16
|
escape (~> 0.0.4)
|
16
17
|
json_pure (~> 1.8)
|
18
|
+
nap (~> 0.5)
|
17
19
|
open4 (~> 1.3)
|
18
20
|
xcodeproj (~> 0.14.1)
|
19
|
-
cocoapods-core (0.
|
21
|
+
cocoapods-core (0.29.0)
|
20
22
|
activesupport (>= 3.2.15, < 4)
|
21
23
|
fuzzy_match (~> 2.0.4)
|
22
|
-
|
24
|
+
json_pure (~> 1.8)
|
23
25
|
nap (~> 0.5)
|
24
|
-
cocoapods-downloader (0.
|
26
|
+
cocoapods-downloader (0.3.0)
|
27
|
+
cocoapods-try-release-fix (0.1.1)
|
25
28
|
colored (1.2)
|
26
29
|
escape (0.0.4)
|
27
30
|
fuzzy_match (2.0.4)
|
28
31
|
i18n (0.6.9)
|
29
|
-
json (1.8.1)
|
30
32
|
json_pure (1.8.1)
|
31
33
|
methadone (1.3.1)
|
32
34
|
bundler
|
33
35
|
motion-cocoapods (1.4.0)
|
34
36
|
cocoapods (>= 0.26.2)
|
35
|
-
motion-prime (0.5.
|
37
|
+
motion-prime (0.5.2)
|
36
38
|
bubble-wrap
|
37
39
|
cocoapods
|
38
40
|
methadone
|
@@ -41,9 +43,9 @@ GEM
|
|
41
43
|
motion-support
|
42
44
|
sugarcube
|
43
45
|
motion-require (0.0.7)
|
44
|
-
motion-support (0.2.
|
46
|
+
motion-support (0.2.6)
|
45
47
|
motion-require (>= 0.0.6)
|
46
|
-
multi_json (1.8.
|
48
|
+
multi_json (1.8.4)
|
47
49
|
nap (0.6.0)
|
48
50
|
open4 (1.3.0)
|
49
51
|
prime_reside_menu (0.1.3)
|
@@ -61,9 +63,9 @@ PLATFORMS
|
|
61
63
|
ruby
|
62
64
|
|
63
65
|
DEPENDENCIES
|
64
|
-
bubble-wrap (~> 1.
|
66
|
+
bubble-wrap (~> 1.4.0)
|
65
67
|
motion-cocoapods (~> 1.4.0)
|
66
|
-
motion-prime (~> 0.5.
|
68
|
+
motion-prime (~> 0.5.2)
|
67
69
|
motion-support (~> 0.2.4)
|
68
70
|
prime_reside_menu (~> 0.1.3)
|
69
71
|
sugarcube (~> 1.3.7)
|
data/files/Rakefile
CHANGED
data/files/app/app_delegate.rb
CHANGED
data/lib/motion-prime.rb
CHANGED
@@ -3,6 +3,7 @@ require 'motion-support'
|
|
3
3
|
require 'sugarcube-common'
|
4
4
|
require 'bubble-wrap'
|
5
5
|
require 'bubble-wrap/reactor'
|
6
|
+
require 'rm-digest'
|
6
7
|
require File.expand_path('../../motion-prime/env.rb', __FILE__)
|
7
8
|
require File.expand_path('../../motion-prime/prime.rb', __FILE__)
|
8
9
|
|
@@ -16,7 +17,6 @@ Motion::Project::App.setup do |app|
|
|
16
17
|
pod 'SDWebImage'
|
17
18
|
pod 'SVPullToRefresh'
|
18
19
|
pod 'MBAlertView'
|
19
|
-
pod '
|
20
|
-
pod 'MBProgressHUD'
|
20
|
+
pod 'MBProgressHUD', '~> 0.8'
|
21
21
|
end
|
22
22
|
end
|
data/motion-prime.gemspec
CHANGED
data/motion-prime/api_client.rb
CHANGED
@@ -5,35 +5,39 @@ class ApiClient
|
|
5
5
|
self.access_token = options[:access_token]
|
6
6
|
end
|
7
7
|
|
8
|
-
def parse_json(text)
|
9
|
-
Prime::JSON.parse(text)
|
10
|
-
rescue
|
11
|
-
NSLog("Can't parse json: #{text}")
|
12
|
-
false
|
13
|
-
end
|
14
|
-
|
15
8
|
def request_params(data)
|
9
|
+
data = data.clone
|
16
10
|
files = data.delete(:files)
|
17
|
-
params = {
|
11
|
+
params = {
|
12
|
+
payload: data,
|
13
|
+
no_redirect: !config.allow_redirect,
|
14
|
+
format: config.request_format
|
15
|
+
}
|
18
16
|
if files.present?
|
19
17
|
params.merge!(files: files)
|
20
18
|
end
|
21
|
-
if
|
22
|
-
params.merge!(credentials:
|
19
|
+
if config.http_auth?
|
20
|
+
params.merge!(credentials: config.http_auth.to_hash)
|
21
|
+
end
|
22
|
+
if config.sign_request?
|
23
|
+
signature = RmDigest::MD5.hexdigest(
|
24
|
+
config.signature_secret + data.keys.map(&:to_s).sort.join
|
25
|
+
)
|
26
|
+
params[:payload].merge!(sign: signature)
|
23
27
|
end
|
24
28
|
params
|
25
29
|
end
|
26
30
|
|
27
|
-
def authenticate(username, password, &block)
|
28
|
-
data
|
31
|
+
def authenticate(username = nil, password = nil, data = nil, &block)
|
32
|
+
data ||= {
|
29
33
|
grant_type: "password",
|
30
34
|
username: username,
|
31
35
|
password: password,
|
32
|
-
client_id:
|
33
|
-
client_secret:
|
36
|
+
client_id: config.client_id,
|
37
|
+
client_secret: config.client_secret
|
34
38
|
}
|
35
39
|
use_callback = block_given?
|
36
|
-
BW::HTTP.post("#{
|
40
|
+
BW::HTTP.post("#{config.base}#{config.auth_path}", request_params(data)) do |response|
|
37
41
|
access_token = if response.ok?
|
38
42
|
json = parse_json(response.body)
|
39
43
|
json[:access_token]
|
@@ -48,40 +52,78 @@ class ApiClient
|
|
48
52
|
|
49
53
|
def api_url(path)
|
50
54
|
return path if path =~ /^http(s)?:\/\//
|
51
|
-
"#{
|
55
|
+
"#{config.base}#{config.api_namespace}#{path}"
|
52
56
|
end
|
53
57
|
|
54
58
|
def page_url(path)
|
55
|
-
"#{
|
59
|
+
"#{config.base}#{path}"
|
56
60
|
end
|
57
61
|
|
58
62
|
def resource_url(path)
|
59
63
|
# return if path.blank?
|
60
|
-
base =
|
64
|
+
base = config.resource_base? ? config.resource_base : config.base
|
61
65
|
"#{base}#{path}"
|
62
66
|
end
|
63
67
|
|
64
|
-
def request(method, path, params = {}, &block)
|
68
|
+
def request(method, path, params = {}, options = {}, &block)
|
65
69
|
params.merge!(access_token: access_token)
|
70
|
+
use_callback = block_given?
|
66
71
|
BW::HTTP.send method, api_url(path), request_params(params) do |response|
|
67
|
-
|
68
|
-
|
72
|
+
if !response.ok? && options[:allow_queue] && config.allow_queue?
|
73
|
+
add_to_queue(method: method, path: path, params: params)
|
74
|
+
else
|
75
|
+
json = parse_json(response.body.to_s)
|
76
|
+
block.call(json, response.status_code) if use_callback
|
77
|
+
process_queue
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def process_queue
|
83
|
+
queue = user_defaults['api_client_queue']
|
84
|
+
user_defaults['api_client_queue'] = []
|
85
|
+
Array.wrap(queue).each do |item|
|
86
|
+
request(item[:method], item[:path], item[:params].clone.symbolize_keys)
|
69
87
|
end
|
70
88
|
end
|
71
89
|
|
72
|
-
def
|
73
|
-
|
90
|
+
def add_to_queue(item)
|
91
|
+
queue = user_defaults['api_client_queue'].clone || []
|
92
|
+
queue.push(item)
|
93
|
+
user_defaults['api_client_queue'] = queue
|
94
|
+
end
|
95
|
+
|
96
|
+
def get(path, params = {}, options = {}, &block)
|
97
|
+
request(:get, path, params, options, &block)
|
74
98
|
end
|
75
99
|
|
76
|
-
def put(path, params = {}, &block)
|
77
|
-
request(:put, path, params, &block)
|
100
|
+
def put(path, params = {}, options = {}, &block)
|
101
|
+
request(:put, path, params, options, &block)
|
78
102
|
end
|
79
103
|
|
80
|
-
def post(path, params = {}, &block)
|
81
|
-
|
104
|
+
def post(path, params = {}, options = {}, &block)
|
105
|
+
options[:allow_queue] = true unless options.has_key?(:allow_queue)
|
106
|
+
request(:post, path, params, options, &block)
|
82
107
|
end
|
83
108
|
|
84
|
-
def delete(path, params = {}, &block)
|
85
|
-
|
109
|
+
def delete(path, params = {}, options = {}, &block)
|
110
|
+
options[:allow_queue] = true unless options.has_key?(:allow_queue)
|
111
|
+
request(:delete, path, params, options, &block)
|
86
112
|
end
|
113
|
+
|
114
|
+
private
|
115
|
+
def user_defaults
|
116
|
+
@user_defaults ||= NSUserDefaults.standardUserDefaults
|
117
|
+
end
|
118
|
+
|
119
|
+
def parse_json(text)
|
120
|
+
Prime::JSON.parse(text)
|
121
|
+
rescue
|
122
|
+
NSLog("Can't parse json: #{text}")
|
123
|
+
false
|
124
|
+
end
|
125
|
+
|
126
|
+
def config
|
127
|
+
MotionPrime::Config.api_client
|
128
|
+
end
|
87
129
|
end
|
data/motion-prime/config/base.rb
CHANGED
@@ -10,9 +10,16 @@ MotionPrime::Config.configure do |config|
|
|
10
10
|
colors.base = 0x424242
|
11
11
|
colors.error = 0xef471f
|
12
12
|
end
|
13
|
-
config.
|
13
|
+
config.api_client do |api|
|
14
14
|
api.base = "http://example.com"
|
15
15
|
api.client_id = ""
|
16
16
|
api.client_secret = ""
|
17
|
+
api.signature_secret = ""
|
18
|
+
api.sign_request = false
|
19
|
+
api.auth_path = '/oauth/token'
|
20
|
+
api.api_namespace = '/api'
|
21
|
+
api.request_format = :form_data
|
22
|
+
api.allow_redirect = false
|
23
|
+
api.allow_queue = false
|
17
24
|
end
|
18
25
|
end
|
@@ -16,10 +16,11 @@ class Kernel
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def clear_instance_variables(options = {})
|
19
|
-
ivars = self.instance_variables
|
20
|
-
|
19
|
+
ivars = self.instance_variables
|
20
|
+
clear_block = proc { |ivar|
|
21
21
|
next if Array.wrap(options[:except]).include?(ivar[1..-1])
|
22
22
|
self.instance_variable_set(ivar, nil)
|
23
|
-
|
23
|
+
}.weak!
|
24
|
+
ivars.each(&clear_block)
|
24
25
|
end
|
25
26
|
end
|
@@ -54,9 +54,11 @@ module MotionPrime
|
|
54
54
|
def get_content_rect(width)
|
55
55
|
raise "Please set element width for content size calculation" unless width
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
options = NSStringDrawingUsesLineFragmentOrigin
|
58
|
+
if is_a?(TextViewElement)
|
59
|
+
options |= NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine
|
60
|
+
end
|
61
|
+
content_attributed_text.boundingRectWithSize([width, Float::MAX], options: options, context:nil)
|
60
62
|
end
|
61
63
|
|
62
64
|
def button_content_text
|
@@ -13,7 +13,7 @@ module MotionPrime
|
|
13
13
|
def html_string(options)
|
14
14
|
styles = []
|
15
15
|
styles << "color: #{options[:text_color].hex};" if options[:text_color]
|
16
|
-
styles << "line-height: #{options
|
16
|
+
styles << "line-height: #{options[:line_height] || (options[:line_spacing].to_f + options[:font].pointSize)}px;"
|
17
17
|
styles << "font-family: '#{options[:font].familyName}';"
|
18
18
|
styles << "font-size: #{options[:font].pointSize}px;"
|
19
19
|
styles << "text-align: #{options[:text_alignment_name]};" if options[:text_alignment_name]
|
@@ -28,10 +28,10 @@ module MotionPrime
|
|
28
28
|
@view_name = self.class_name_without_kvo.demodulize.underscore.gsub(/(_draw)?_element/, '')
|
29
29
|
end
|
30
30
|
|
31
|
-
def dealloc
|
32
|
-
|
33
|
-
|
34
|
-
end
|
31
|
+
# def dealloc
|
32
|
+
# pp 'deallocating elemenet', self.name, self.to_s, view_class#, view.try(:to_s)
|
33
|
+
# super
|
34
|
+
# end
|
35
35
|
|
36
36
|
def add_target(target = nil, action = 'on_click:', event = :touch)
|
37
37
|
return false unless self.view
|
@@ -164,6 +164,7 @@ module MotionPrime
|
|
164
164
|
end.flatten
|
165
165
|
@styles += custom_styles
|
166
166
|
# puts @view_class.to_s + @styles.inspect, ''
|
167
|
+
@styles
|
167
168
|
end
|
168
169
|
|
169
170
|
class << self
|
@@ -68,14 +68,13 @@ module MotionPrime
|
|
68
68
|
return if image_data || !computed_options[:url]
|
69
69
|
BW::Reactor.schedule do
|
70
70
|
manager = SDWebImageManager.sharedManager
|
71
|
-
@
|
72
|
-
@section_ref = section.strong_ref
|
71
|
+
@strong_refs = section.strong_references
|
73
72
|
manager.downloadWithURL(computed_options[:url],
|
74
73
|
options: 0,
|
75
74
|
progress: lambda{ |r_size, e_size| },
|
76
75
|
completed: lambda{ |image, error, type, finished|
|
77
76
|
if !image || screen.retainCount == 1 || section.retainCount == 1
|
78
|
-
@
|
77
|
+
@strong_refs = nil
|
79
78
|
return
|
80
79
|
end
|
81
80
|
|
@@ -87,7 +86,7 @@ module MotionPrime
|
|
87
86
|
else
|
88
87
|
self.view.performSelectorOnMainThread :setNeedsDisplay, withObject: nil, waitUntilDone: false
|
89
88
|
end
|
90
|
-
@
|
89
|
+
@strong_refs = nil
|
91
90
|
}
|
92
91
|
)
|
93
92
|
end
|
@@ -7,13 +7,13 @@ module MotionPrime
|
|
7
7
|
|
8
8
|
def draw_options
|
9
9
|
options = computed_options
|
10
|
-
text = (options[:html] || options[:text]).to_s.gsub(
|
10
|
+
text = (options[:html] || options[:text]).to_s.gsub(/\A[\n\r]+/, '')
|
11
11
|
text_color = (options[:text_color] || :black).uicolor
|
12
12
|
font = (options[:font] || :system).uifont
|
13
13
|
|
14
|
-
text_alignment_name = options.
|
14
|
+
text_alignment_name = options.fetch(:text_alignment, :left)
|
15
15
|
text_alignment = text_alignment_name.uitextalignment
|
16
|
-
line_break_mode_name = options.
|
16
|
+
line_break_mode_name = options.fetch(:line_break_mode, :tail_truncation)
|
17
17
|
line_break_mode = line_break_mode_name.uilinebreakmode
|
18
18
|
|
19
19
|
top_left_corner = CGPointMake(computed_inner_left, computed_inner_top)
|
data/motion-prime/env.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class Env
|
3
3
|
def env
|
4
|
-
|
4
|
+
(defined?(NSBundle) && NSBundle.mainBundle.objectForInfoDictionaryKey('PRIME_ENV')) ||
|
5
|
+
ENV['PRIME_ENV'] ||
|
6
|
+
ENV['RUBYMOTION_ENV'] ||
|
5
7
|
(defined?(RUBYMOTION_ENV) && RUBYMOTION_ENV) ||
|
6
8
|
'development'
|
7
9
|
end
|
@@ -11,7 +11,7 @@ module MotionPrime
|
|
11
11
|
when :persistent, :file
|
12
12
|
path ||= begin
|
13
13
|
documents_path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true)[0]
|
14
|
-
documents_path + "/
|
14
|
+
documents_path + "/nano_#{Prime.env.to_s}.db"
|
15
15
|
end
|
16
16
|
store = NSFNanoStore.createAndOpenStoreWithType(NSFPersistentStoreType, path: path, error: error_ptr)
|
17
17
|
else
|
@@ -30,24 +30,29 @@ module MotionPrime
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def will_appear
|
33
|
-
|
33
|
+
@visible = true
|
34
|
+
@on_appear_happened ||= {}
|
35
|
+
unless @on_appear_happened[view.object_id]
|
34
36
|
setup view, styles: default_styles do
|
35
37
|
run_callbacks :render { render }
|
36
38
|
end
|
37
39
|
end
|
38
|
-
@on_appear_happened = true
|
40
|
+
@on_appear_happened[view.object_id] = true
|
41
|
+
end
|
42
|
+
|
43
|
+
def will_disappear
|
44
|
+
@visible = false
|
39
45
|
end
|
40
46
|
|
41
47
|
def dealloc
|
42
|
-
pp
|
48
|
+
pp 'Deallocating Screen', self.object_id, self.to_s
|
43
49
|
# FIXME: calling instance_eval in title method (_base_screen_mixin) instance variables need to be cleared manually
|
44
|
-
|
45
|
-
@main_section = nil
|
50
|
+
clear_instance_variables
|
46
51
|
super
|
47
52
|
end
|
48
53
|
|
49
54
|
def visible?
|
50
|
-
|
55
|
+
@visible
|
51
56
|
end
|
52
57
|
end
|
53
58
|
end
|
@@ -77,6 +77,10 @@ module MotionPrime
|
|
77
77
|
@cached_draw_image ||= MotionSupport::HashWithIndifferentAccess.new
|
78
78
|
end
|
79
79
|
|
80
|
+
def strong_references
|
81
|
+
[self, screen].map(&:strong_ref)
|
82
|
+
end
|
83
|
+
|
80
84
|
private
|
81
85
|
def set_container_gesture_recognizer
|
82
86
|
single_tap = UITapGestureRecognizer.alloc.initWithTarget(self, action: 'on_container_tap_gesture:')
|
@@ -37,7 +37,7 @@ module MotionPrime
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def dealloc
|
40
|
-
pp 'deallocating section', self.name, self.elements.try(:count), self.to_s, self.object_id
|
40
|
+
# pp 'deallocating section', self.name, self.elements.try(:count), self.to_s, self.object_id
|
41
41
|
NSNotificationCenter.defaultCenter.removeObserver self # unbinding events created in bind_keyboard_events
|
42
42
|
super
|
43
43
|
end
|
@@ -110,7 +110,7 @@ module MotionPrime
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
-
def add_element(key, options)
|
113
|
+
def add_element(key, options = {})
|
114
114
|
return unless render_element?(key)
|
115
115
|
opts = options.clone
|
116
116
|
index = opts.delete(:at)
|
@@ -254,7 +254,7 @@ module MotionPrime
|
|
254
254
|
# we should clone options to prevent overriding options
|
255
255
|
# in next element with same name in another class
|
256
256
|
options = opts.clone
|
257
|
-
options[:type] ||= (options[:text] || options[:attributed_text_options]) ? :label : :view
|
257
|
+
options[:type] ||= (options[:text] || options[:html] || options[:attributed_text_options]) ? :label : :view
|
258
258
|
options.merge(screen: screen, section: self.weak_ref)
|
259
259
|
end
|
260
260
|
|
@@ -11,9 +11,15 @@ module MotionPrime
|
|
11
11
|
|
12
12
|
def prepare_table_data
|
13
13
|
@form = @options[:table]
|
14
|
-
|
14
|
+
if options[:observe_errors]
|
15
|
+
@errors_observer_options = normalize_options(options.delete(:observe_errors), self)
|
16
|
+
end
|
15
17
|
end
|
16
18
|
|
19
|
+
# Returns true if we should render element in current state
|
20
|
+
#
|
21
|
+
# @param element_name [Symbol] name of element in field
|
22
|
+
# @return [Boolean]
|
17
23
|
def render_element?(element_name)
|
18
24
|
case element_name.to_sym
|
19
25
|
when :error_message
|
@@ -24,6 +30,19 @@ module MotionPrime
|
|
24
30
|
end
|
25
31
|
end
|
26
32
|
|
33
|
+
# Changes height of the field (the cell in table) with animation.
|
34
|
+
#
|
35
|
+
# @param height [Integet] new height of field
|
36
|
+
# @return [MotionPrime::BaseFieldSection]
|
37
|
+
def update_height(height)
|
38
|
+
container_options[:height] = height
|
39
|
+
field_index = form.field_indexes[name]
|
40
|
+
index = field_index.split('_').map(&:to_i)
|
41
|
+
path = NSIndexPath.indexPathForRow(index.last, inSection: index.first)
|
42
|
+
form.table_view.reloadRowsAtIndexPaths([path], withRowAnimation: UITableViewRowAnimationNone)
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
27
46
|
def on_section_render
|
28
47
|
@status_for_updated = :rendered
|
29
48
|
form.register_elements_from_section(self)
|
@@ -57,7 +76,7 @@ module MotionPrime
|
|
57
76
|
|
58
77
|
def focus(begin_editing = true)
|
59
78
|
# scroll to cell
|
60
|
-
path = form.table_view.indexPathForCell
|
79
|
+
path = form.table_view.indexPathForCell(cell)
|
61
80
|
form.table_view.scrollToRowAtIndexPath path,
|
62
81
|
atScrollPosition: UITableViewScrollPositionTop, animated: true
|
63
82
|
# focus on text field
|
@@ -4,14 +4,21 @@ module MotionPrime
|
|
4
4
|
element :label, type: :label do
|
5
5
|
options[:label] || {}
|
6
6
|
end
|
7
|
-
element :date_picker, type: :date_picker
|
7
|
+
element :date_picker, type: :date_picker do
|
8
|
+
options[:input] || {}
|
9
|
+
end
|
8
10
|
|
9
11
|
after_render :bind_date_picker
|
10
12
|
|
11
13
|
def bind_date_picker
|
12
14
|
picker = view(:date_picker)
|
13
15
|
picker.setDelegate form
|
14
|
-
picker.
|
16
|
+
unless picker.date
|
17
|
+
picker.setDate NSDate.date, animated: true
|
18
|
+
end
|
19
|
+
picker.on :change do
|
20
|
+
form.send(options[:action]) if options[:action]
|
21
|
+
end
|
15
22
|
end
|
16
23
|
end
|
17
24
|
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class SubmitFieldSection < BaseFieldSection
|
3
3
|
element :submit, type: :button do
|
4
|
-
{title: options[:title]}
|
4
|
+
{title: options[:title]}.merge(options[:button] || {})
|
5
5
|
end
|
6
|
+
element :error_message, type: :error_message, text: proc { all_errors.join("\n") if observing_errors? }
|
7
|
+
|
6
8
|
after_render :bind_submit
|
7
9
|
|
8
10
|
def bind_submit
|
@@ -51,11 +51,17 @@ module MotionPrime
|
|
51
51
|
@preloader_queue[-1] = :cancelled if @preloader_queue.present?
|
52
52
|
end
|
53
53
|
|
54
|
+
def reload_cell(section)
|
55
|
+
section.elements.values.each(&:compute_options!)
|
56
|
+
section.cached_draw_image = nil
|
57
|
+
# TODO: reset date stamps, reload row
|
58
|
+
end
|
59
|
+
|
54
60
|
def table_styles
|
55
61
|
type = self.is_a?(FormSection) ? :base_form : :base_table
|
56
62
|
|
57
63
|
base_styles = [type]
|
58
|
-
base_styles << :"#{type}_with_sections"
|
64
|
+
base_styles << :"#{type}_with_sections" unless flat_data?
|
59
65
|
item_styles = [name.to_sym]
|
60
66
|
item_styles << @styles if @styles.present?
|
61
67
|
{common: base_styles, specific: item_styles}
|
@@ -371,7 +377,6 @@ module MotionPrime
|
|
371
377
|
BW::Reactor.schedule(@preloader_queue.count) do |queue_id|
|
372
378
|
@preloader_queue[queue_id] = :in_progress
|
373
379
|
@strong_refs[queue_id] = screen.strong_ref
|
374
|
-
|
375
380
|
result = load_count.times do |offset|
|
376
381
|
if @preloader_queue[queue_id] == :cancelled
|
377
382
|
@strong_refs[queue_id] = nil
|
data/motion-prime/styles/base.rb
CHANGED
data/motion-prime/styles/form.rb
CHANGED
@@ -37,7 +37,8 @@ MotionPrime::Styles.define :base_form do
|
|
37
37
|
style :field_error_message,
|
38
38
|
top: nil,
|
39
39
|
bottom: 0,
|
40
|
-
width:
|
40
|
+
width: 280,
|
41
|
+
left: 0,
|
41
42
|
line_break_mode: :word_wrap,
|
42
43
|
number_of_lines: 0,
|
43
44
|
size_to_fit: true,
|
@@ -79,6 +80,7 @@ MotionPrime::Styles.define :base_form do
|
|
79
80
|
title_label: {
|
80
81
|
font: proc { MotionPrime::Config.font.name.uifont(16) }
|
81
82
|
}
|
83
|
+
|
82
84
|
style :select_field_image,
|
83
85
|
image: "images/forms/select_arrow.png",
|
84
86
|
top: 40,
|
@@ -89,7 +91,11 @@ MotionPrime::Styles.define :base_form do
|
|
89
91
|
style :with_sections_field_switch,
|
90
92
|
right: 20
|
91
93
|
|
92
|
-
style :with_sections_field_text_field,
|
94
|
+
style :with_sections_field_text_field,
|
95
|
+
:with_sections_field_text_view,
|
96
|
+
:with_sections_field_password_field,
|
97
|
+
:with_sections_field_label,
|
98
|
+
:with_sections_field_button,
|
93
99
|
left: 20,
|
94
100
|
right: 20
|
95
101
|
|
@@ -1,23 +1,25 @@
|
|
1
1
|
class MPCellWithSection < UITableViewCell
|
2
2
|
attr_reader :section
|
3
|
+
attr_accessor :scroll_view, :content_view
|
3
4
|
|
4
|
-
def
|
5
|
-
|
6
|
-
@section_name = section.try(:name) # TODO: remove after debug
|
7
|
-
end
|
8
|
-
|
9
|
-
def drawRect(rect)
|
5
|
+
def setNeedsDisplay
|
6
|
+
content_view.try(:setNeedsDisplay)
|
10
7
|
super
|
11
|
-
draw_in(rect)
|
12
8
|
end
|
13
9
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
10
|
+
def setSection(section)
|
11
|
+
@section = section.try(:weak_ref)
|
12
|
+
self.content_view.setSection(@section)
|
17
13
|
end
|
18
14
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
def initialize_content
|
16
|
+
self.scroll_view = self.subviews.first
|
17
|
+
self.scroll_view.subviews.first.removeFromSuperview
|
18
|
+
self.content_view = MPTableViewCellContentView.alloc.initWithFrame(self.bounds)
|
19
|
+
self.content_view.setBackgroundColor(:clear.uicolor)
|
20
|
+
self.content_view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
|
21
|
+
self.content_view.top = 0
|
22
|
+
self.content_view.left = 0
|
23
|
+
self.scroll_view.addSubview(content_view)
|
24
|
+
end
|
23
25
|
end
|
@@ -5,14 +5,11 @@ module MotionPrime
|
|
5
5
|
|
6
6
|
view_controllers = []
|
7
7
|
|
8
|
-
screens.each_with_index do |
|
9
|
-
if
|
10
|
-
screen
|
11
|
-
screen = Screen.create_with_options(screen).try(:weak_ref)
|
12
|
-
title ||= screen.title
|
13
|
-
image = image.uiimage if image
|
14
|
-
screen.tabBarItem = UITabBarItem.alloc.initWithTitle title, image: image, tag: index
|
8
|
+
screens.each_with_index do |options, index|
|
9
|
+
if options.is_a?(Hash)
|
10
|
+
screen = init_screen_with_options(options, tag: index)
|
15
11
|
else
|
12
|
+
screen = options
|
16
13
|
screen.tabBarItem.tag = index
|
17
14
|
end
|
18
15
|
|
@@ -33,5 +30,29 @@ module MotionPrime
|
|
33
30
|
end
|
34
31
|
controller
|
35
32
|
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
def self.init_screen_with_options(options, tag: tag)
|
36
|
+
screen, image, title = options[:screen], options[:image], options[:title]
|
37
|
+
screen = Screen.create_with_options(screen).try(:weak_ref)
|
38
|
+
title ||= screen.title
|
39
|
+
|
40
|
+
image = extract_image_from_options(options, with_key: :image)
|
41
|
+
screen.tabBarItem = UITabBarItem.alloc.initWithTitle title, image: image, tag: tag
|
42
|
+
|
43
|
+
selected_image = extract_image_from_options(options, with_key: :selected_image)
|
44
|
+
screen.tabBarItem.setSelectedImage(selected_image) if selected_image
|
45
|
+
screen
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.extract_image_from_options(options, with_key: key)
|
49
|
+
image = options[key]
|
50
|
+
return unless image
|
51
|
+
image = image.uiimage
|
52
|
+
if options[:translucent] === false
|
53
|
+
image = image.imageWithRenderingMode UIImageRenderingModeAlwaysOriginal
|
54
|
+
end
|
55
|
+
image
|
56
|
+
end
|
36
57
|
end
|
37
58
|
end
|
data/motion-prime/version.rb
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
motion_require '../support/mp_cell_with_section'
|
3
3
|
module MotionPrime
|
4
4
|
module Layout
|
5
|
-
def add_view(klass, options = {}, &block)
|
5
|
+
def add_view(klass, options = {}, &block)
|
6
|
+
options = options.clone
|
6
7
|
bounds = if view_stack.empty?
|
7
8
|
options.delete(:parent_view).try(:bounds) || CGRectZero
|
8
9
|
else
|
@@ -35,6 +35,7 @@ module MotionPrime
|
|
35
35
|
if options.slice(:line_spacing, :line_height, :underline, :fragment_color).any?
|
36
36
|
options[:attributed_text_options] = {
|
37
37
|
text: options.delete(:text),
|
38
|
+
html: options.delete(:html),
|
38
39
|
line_spacing: options.delete(:line_spacing),
|
39
40
|
line_height: options.delete(:line_height),
|
40
41
|
fragment_color: options.delete(:fragment_color),
|
@@ -74,7 +75,7 @@ module MotionPrime
|
|
74
75
|
is_custom_button = options[:background_image] || options[:title_color]
|
75
76
|
default_button_type = is_custom_button ? :custom : :rounded
|
76
77
|
button_type = (options.delete(:button_type) || default_button_type).uibuttontype
|
77
|
-
|
78
|
+
klass.buttonWithType button_type
|
78
79
|
},
|
79
80
|
'UIImageView' => Proc.new{|klass, options|
|
80
81
|
image = options.delete(:image)
|
@@ -109,7 +110,9 @@ module MotionPrime
|
|
109
110
|
options.delete(:gradient)
|
110
111
|
end
|
111
112
|
|
112
|
-
klass.alloc.initWithStyle style, reuseIdentifier: options.delete(:reuse_identifier)
|
113
|
+
obj = klass.alloc.initWithStyle style, reuseIdentifier: options.delete(:reuse_identifier)
|
114
|
+
obj.initialize_content
|
115
|
+
obj
|
113
116
|
},
|
114
117
|
'MPViewWithSection' => Proc.new{|klass, options|
|
115
118
|
if options[:has_drawn_content]
|
@@ -106,25 +106,41 @@ module MotionPrime
|
|
106
106
|
view.mask = mask_layer
|
107
107
|
elsif key == 'attributed_text_options'
|
108
108
|
attributes = {}
|
109
|
-
if
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
109
|
+
if value[:html] # TODO: use _text_mixin
|
110
|
+
styles = []
|
111
|
+
styles << "color: #{options[:text_color].hex};" if options[:text_color]
|
112
|
+
styles << "line-height: #{options[:line_height] || (options[:line_spacing].to_f + options[:font].pointSize)}px;"
|
113
|
+
styles << "font-family: '#{options[:font].familyName}';"
|
114
|
+
styles << "font-size: #{options[:font].pointSize}px;"
|
114
115
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
attributedString = NSMutableAttributedString.alloc.initWithAttributedString(attributedString)
|
122
|
-
attributedString.addAttributes({NSForegroundColorAttributeName => fragment_color[:color].uicolor}, range: fragment_color[:range])
|
123
|
-
end
|
124
|
-
if view.is_a?(UIButton)
|
125
|
-
view.setAttributedTitle attributedString, forState: UIControlStateNormal
|
116
|
+
html_options = {
|
117
|
+
NSDocumentTypeDocumentAttribute => NSHTMLTextDocumentType,
|
118
|
+
NSCharacterEncodingDocumentAttribute => NSNumber.numberWithInt(NSUTF8StringEncoding)
|
119
|
+
}
|
120
|
+
text = "#{value[:html]}<style>* { #{styles.join} }</style>"
|
121
|
+
view.attributedText = NSAttributedString.alloc.initWithData(text.dataUsingEncoding(NSUTF8StringEncoding), options: html_options, documentAttributes: nil, error: nil)
|
126
122
|
else
|
127
|
-
|
123
|
+
if line_spacing = value[:line_spacing] || line_height = value[:line_height]
|
124
|
+
paragrahStyle = NSMutableParagraphStyle.alloc.init
|
125
|
+
line_height ? paragrahStyle.setMinimumLineHeight(line_height) : paragrahStyle.setLineSpacing(line_spacing)
|
126
|
+
attributes[NSParagraphStyleAttributeName] = paragrahStyle
|
127
|
+
end
|
128
|
+
|
129
|
+
attributedString = NSAttributedString.alloc.initWithString(value[:text].to_s, attributes: attributes)
|
130
|
+
if underline_range = value[:underline]
|
131
|
+
underline_range = [0, value[:text].length] if underline_range === true
|
132
|
+
attributedString = NSMutableAttributedString.alloc.initWithAttributedString(attributedString)
|
133
|
+
attributedString.addAttributes({NSUnderlineStyleAttributeName => NSUnderlineStyleSingle}, range: underline_range)
|
134
|
+
end
|
135
|
+
if fragment_color = value[:fragment_color]
|
136
|
+
attributedString = NSMutableAttributedString.alloc.initWithAttributedString(attributedString)
|
137
|
+
attributedString.addAttributes({NSForegroundColorAttributeName => fragment_color[:color].uicolor}, range: fragment_color[:range])
|
138
|
+
end
|
139
|
+
if view.is_a?(UIButton)
|
140
|
+
view.setAttributedTitle attributedString, forState: UIControlStateNormal
|
141
|
+
else
|
142
|
+
view.attributedText = attributedString
|
143
|
+
end
|
128
144
|
end
|
129
145
|
elsif key == 'gradient'
|
130
146
|
gradient = prepare_gradient(value)
|
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.5.
|
4
|
+
version: 0.5.3
|
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-01-
|
12
|
+
date: 2014-01-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -151,6 +151,20 @@ dependencies:
|
|
151
151
|
- - ! '>='
|
152
152
|
- !ruby/object:Gem::Version
|
153
153
|
version: '0'
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: rm-digest
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ! '>='
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
type: :runtime
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ! '>='
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
154
168
|
description: RubyMotion apps development framework
|
155
169
|
email:
|
156
170
|
- gvalmon@gmail.com
|
@@ -294,6 +308,7 @@ files:
|
|
294
308
|
- motion-prime/support/_key_value_store.rb
|
295
309
|
- motion-prime/support/_padding_attribute.rb
|
296
310
|
- motion-prime/support/mp_button.rb
|
311
|
+
- motion-prime/support/mp_cell_content_view.rb
|
297
312
|
- motion-prime/support/mp_cell_with_section.rb
|
298
313
|
- motion-prime/support/mp_label.rb
|
299
314
|
- motion-prime/support/mp_search_bar_custom.rb
|