motion-prime 0.5.2 → 0.5.3
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 +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
|