motion-prime 0.1.0

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.
Files changed (65) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +83 -0
  4. data/README.md +67 -0
  5. data/Rakefile +23 -0
  6. data/app/app_delegate.rb +5 -0
  7. data/doc/SECTION.md +7 -0
  8. data/doc/STYLE.md +39 -0
  9. data/files/Gemfile +3 -0
  10. data/files/Rakefile +16 -0
  11. data/files/app/app_delegate.rb +4 -0
  12. data/files/app/screens/application_screen.rb +3 -0
  13. data/lib/motion-prime.rb +14 -0
  14. data/lib/view_styler.rb +141 -0
  15. data/motion-prime.gemspec +27 -0
  16. data/motion-prime/app_delegate.rb +56 -0
  17. data/motion-prime/elements/base.rb +94 -0
  18. data/motion-prime/elements/button.rb +7 -0
  19. data/motion-prime/elements/draw.rb +56 -0
  20. data/motion-prime/elements/draw/image.rb +43 -0
  21. data/motion-prime/elements/draw/label.rb +13 -0
  22. data/motion-prime/elements/image.rb +14 -0
  23. data/motion-prime/elements/label.rb +20 -0
  24. data/motion-prime/elements/text_field.rb +7 -0
  25. data/motion-prime/elements/text_view.rb +7 -0
  26. data/motion-prime/helpers/has_authorization.rb +10 -0
  27. data/motion-prime/helpers/has_search_bar.rb +25 -0
  28. data/motion-prime/models/base.rb +220 -0
  29. data/motion-prime/screens/_aliases_mixin.rb +32 -0
  30. data/motion-prime/screens/_base_mixin.rb +119 -0
  31. data/motion-prime/screens/_navigation_bar_mixin.rb +57 -0
  32. data/motion-prime/screens/_navigation_mixin.rb +118 -0
  33. data/motion-prime/screens/_orientations_mixin.rb +39 -0
  34. data/motion-prime/screens/base_screen.rb +22 -0
  35. data/motion-prime/screens/sidebar_container_screen.rb +58 -0
  36. data/motion-prime/sections/base.rb +101 -0
  37. data/motion-prime/sections/draw.rb +62 -0
  38. data/motion-prime/sections/form.rb +103 -0
  39. data/motion-prime/sections/form/base_field_section.rb +26 -0
  40. data/motion-prime/sections/form/password_field_section.rb +33 -0
  41. data/motion-prime/sections/form/select_field_section.rb +40 -0
  42. data/motion-prime/sections/form/string_field_section.rb +32 -0
  43. data/motion-prime/sections/form/submit_field_section.rb +20 -0
  44. data/motion-prime/sections/form/text_field_section.rb +33 -0
  45. data/motion-prime/sections/table.rb +97 -0
  46. data/motion-prime/sections/table/refresh_mixin.rb +13 -0
  47. data/motion-prime/styles/forms.rb +93 -0
  48. data/motion-prime/support/_key_value_store.rb +10 -0
  49. data/motion-prime/support/dm_button.rb +22 -0
  50. data/motion-prime/support/dm_cell_with_section.rb +12 -0
  51. data/motion-prime/support/dm_text_field.rb +30 -0
  52. data/motion-prime/support/dm_text_view.rb +93 -0
  53. data/motion-prime/support/dm_view_controller.rb +50 -0
  54. data/motion-prime/support/dm_view_with_section.rb +11 -0
  55. data/motion-prime/support/navigation_controller.rb +4 -0
  56. data/motion-prime/support/ui_search_bar_custom.rb +10 -0
  57. data/motion-prime/support/ui_view.rb +59 -0
  58. data/motion-prime/version.rb +3 -0
  59. data/motion-prime/views/layout.rb +45 -0
  60. data/motion-prime/views/styles.rb +44 -0
  61. data/motion-prime/views/view_builder.rb +80 -0
  62. data/motion-prime/views/view_styler.rb +141 -0
  63. data/resources/Default-568h@2x.png +0 -0
  64. data/spec/main_spec.rb +9 -0
  65. metadata +245 -0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ .repl_history
2
+ build
3
+ tags
4
+ app/pixate_code.rb
5
+ resources/*.nib
6
+ resources/*.momd
7
+ resources/*.storyboardc
8
+ .DS_Store
9
+ nbproject
10
+ .redcar
11
+ #*#
12
+ *~
13
+ *.sw[po]
14
+ .eprj
15
+ .sass-cache
16
+ .idea
17
+ vendor
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'cocoapods', '0.19.1'
4
+ gem 'motion-cocoapods', '1.3.2'
5
+
6
+ # ruby sugar
7
+ gem 'sugarcube', '0.20.23'
8
+ gem 'motion-support', '0.2.4'
9
+ gem 'bubble-wrap', '1.3.0'
10
+
11
+ # modelds
12
+ gem 'nano-store', '0.6.3'
13
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,83 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ motion-prime (0.1.0)
5
+ bubble-wrap
6
+ cocoapods
7
+ motion-cocoapods
8
+ motion-require
9
+ motion-support
10
+ nano-store
11
+ sugarcube
12
+
13
+ GEM
14
+ remote: http://rubygems.org/
15
+ specs:
16
+ activesupport (3.2.13)
17
+ i18n (= 0.6.1)
18
+ multi_json (~> 1.0)
19
+ addressable (2.3.5)
20
+ bubble-wrap (1.3.0)
21
+ claide (0.2.0)
22
+ cocoapods (0.19.1)
23
+ activesupport (~> 3.2.13)
24
+ claide (~> 0.2.0)
25
+ cocoapods-core (= 0.19.1)
26
+ cocoapods-downloader (~> 0.1.0)
27
+ colored (~> 1.2)
28
+ escape (~> 0.0.4)
29
+ faraday (~> 0.8.1)
30
+ json (~> 1.7.3)
31
+ octokit (~> 1.7)
32
+ open4 (~> 1.3.0)
33
+ rake (~> 10.0.0)
34
+ xcodeproj (~> 0.5.5)
35
+ cocoapods-core (0.19.1)
36
+ activesupport (~> 3.2.13)
37
+ rake (~> 10.0.0)
38
+ cocoapods-downloader (0.1.1)
39
+ colored (1.2)
40
+ escape (0.0.4)
41
+ faraday (0.8.7)
42
+ multipart-post (~> 1.1)
43
+ faraday_middleware (0.9.0)
44
+ faraday (>= 0.7.4, < 0.9)
45
+ hashie (2.0.5)
46
+ i18n (0.6.1)
47
+ json (1.7.7)
48
+ motion-cocoapods (1.3.2)
49
+ cocoapods (>= 0.17.0)
50
+ motion-require (0.0.7)
51
+ motion-support (0.2.4)
52
+ motion-require (>= 0.0.6)
53
+ multi_json (1.7.7)
54
+ multipart-post (1.2.0)
55
+ nano-store (0.6.3)
56
+ motion-cocoapods (>= 1.2.1)
57
+ netrc (0.7.7)
58
+ octokit (1.25.0)
59
+ addressable (~> 2.2)
60
+ faraday (~> 0.8)
61
+ faraday_middleware (~> 0.9)
62
+ hashie (~> 2.0)
63
+ multi_json (~> 1.3)
64
+ netrc (~> 0.7.7)
65
+ open4 (1.3.0)
66
+ rake (10.0.4)
67
+ sugarcube (0.20.23)
68
+ xcodeproj (0.5.5)
69
+ activesupport (~> 3.2.13)
70
+ colored (~> 1.2)
71
+
72
+ PLATFORMS
73
+ ruby
74
+
75
+ DEPENDENCIES
76
+ bubble-wrap (= 1.3.0)
77
+ cocoapods (= 0.19.1)
78
+ motion-cocoapods (= 1.3.2)
79
+ motion-prime!
80
+ motion-support (= 0.2.4)
81
+ nano-store (= 0.6.3)
82
+ rake
83
+ sugarcube (= 0.20.23)
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # MotionPrime
2
+
3
+ ![Prime](https://s3-us-west-2.amazonaws.com/webmate/assets/prime.jpg)
4
+
5
+ MotionPrime is yet another framework written on RubyMotion.
6
+
7
+ The main feature of MotionPrime is one more level on UI elements: Section.
8
+ "Section" is something like "Partial" in Ruby On Rails, but it's smarter and will help you build application UI.
9
+
10
+ ## Getting Started
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'motion-prime'
15
+
16
+ Or create MotionPrime project:
17
+
18
+ $ motion create --template=git@github.com:droidlabs/motion-prime.git myapp
19
+
20
+ ## Hello World (Sample)
21
+
22
+ # app/app_delegate.rb
23
+ class AppDelegate < MotionPrime::BaseAppDelegate
24
+ def on_load(app, options)
25
+ open_root_screen MainScreen.new
26
+ end
27
+ end
28
+
29
+ # app/screens/main_screen.rb
30
+ class MainScreen < ApplicationScreen
31
+ title 'Main screen'
32
+
33
+ def render
34
+ @main_section = MyProfileSection.new(model: User.first)
35
+ @main_section.render(to: self)
36
+ end
37
+ end
38
+
39
+ # app/sections/my_profile.rb
40
+ class MyProfileSection < MotionPrime::BaseSection
41
+ element :title, text: proc { Hello World }
42
+ element :avatar, image: "images/avatar.png", type: :image
43
+ end
44
+
45
+ # app/styles/my_profile.rb
46
+ MotionPrime::Styles.define :my_profile do
47
+ style :title,
48
+ width: 300, height: 20, color: :black,
49
+ top: 10, left: 5, background_color: :white
50
+
51
+ style :avatar,
52
+ width: 90, height: 90, top: 40, left: 5
53
+ end
54
+
55
+ ## Contributing
56
+
57
+ 1. Fork it
58
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
59
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
60
+ 4. Push to the branch (`git push origin my-new-feature`)
61
+ 5. Create new Pull Request
62
+
63
+ ## Thanks for using MotionPrime!
64
+
65
+ Hope, you'll enjoy MotionPrime!
66
+
67
+ Cheers, [Droid Labs](http://droidlabs.pro).
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ # -*- coding: utf-8 -*-
2
+ $:.unshift("/Library/RubyMotion/lib")
3
+ require 'motion/project/template/ios'
4
+ require "rubygems"
5
+ require "bundler"
6
+ require "bundler/gem_tasks"
7
+ require 'motion-cocoapods'
8
+ Bundler.setup
9
+ Bundler.require
10
+ require 'motion-support'
11
+ require 'nano-store'
12
+ require 'motion-prime'
13
+
14
+ Motion::Project::App.setup do |app|
15
+ app.name = 'MotionPrime'
16
+ app.pods do
17
+ pod 'PKRevealController'
18
+ pod 'NanoStore', '~> 2.6.0'
19
+ pod 'SDWebImage'
20
+ pod 'SVPullToRefresh'
21
+ pod 'MBAlertView'
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ class AppDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ true
4
+ end
5
+ end
data/doc/SECTION.md ADDED
@@ -0,0 +1,7 @@
1
+ == GENERAL
2
+
3
+ Section is the most important part of MotionPrime. Section is container for elements (views), grouped for some aim.
4
+
5
+ == Section attributes
6
+
7
+ * @name - this option is used by part of default styles of any contained element. Check out STYLES doc for more information. default value: section class name without "section word". E.g. LoginFormSection have default name: "login_form"
data/doc/STYLE.md ADDED
@@ -0,0 +1,39 @@
1
+ == Default styling names for elements.
2
+
3
+ === Screen
4
+ * "base_screen"
5
+ * "%screen class name%", e.g. "login_screen"
6
+
7
+ === Table
8
+ * "base_table"
9
+ * "%section_name%", e.g. "tasks_table"
10
+
11
+ === Table cell
12
+ * "base_table_cell"
13
+ * "%section_name%_cell", e.g. "tasks_table_cell"
14
+ * "%cell_section_name%", e.g. "tasks_item"
15
+
16
+ === Form (basically it's table)
17
+ * "base_form"
18
+ * "%section_name%", e.g. "login_form"
19
+
20
+ === Form field (basically it's table cell)
21
+ * "base_form_field"
22
+ * "%section_name%_field", e.g. "login_form_field"
23
+
24
+ === Form field: label
25
+ * "base_field_label"
26
+ * "base_%field_type%_field_label", e.g. "base_string_field_label"
27
+ * "%section_name%_field_label", e.g. "login_form_field_label"
28
+ * "%section_name%_%field_name%_field_label", e.g. "login_form_email_field_label"
29
+
30
+ === Form field: input
31
+ * "base_field_input"
32
+ * "base_%field_name%_field_label", e.g. "base_string_field_input"
33
+ * "%section_name%_field_input", e.g. "login_form_field_input"
34
+ * "%section_name%_%field_name%_field_input", e.g. "login_form_email_field_input"
35
+
36
+ === Form field: button
37
+ * "base_submit_button"
38
+ * "%section_name%_submit_button", e.g. "login_form_submit_button"
39
+ * "%section_name%_%field_name%_button", e.g. "login_form_signup_button"
data/files/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'motion-prime'
data/files/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ $:.unshift("/Library/RubyMotion/lib")
3
+ require 'motion/project/template/ios'
4
+ require "rubygems"
5
+ require 'bundler'
6
+ Bundler.require
7
+ require 'motion-prime'
8
+
9
+ Motion::Project::App.setup do |app|
10
+ # Use `rake config' to see complete project settings.
11
+ app.name = 'MotionPrimeProject'
12
+
13
+ app.pods do
14
+
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ class AppDelegate < MotionPrime::BaseAppDelegate
2
+ def on_load(app, options)
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationScreen < MotionPrime::BaseScreen
2
+
3
+ end
@@ -0,0 +1,14 @@
1
+ require 'motion-require'
2
+
3
+ Motion::Require.all(Dir.glob(File.expand_path('../../motion-prime/**/*.rb', __FILE__)))
4
+
5
+ Motion::Project::App.setup do |app|
6
+ app.pods do
7
+ pod 'PKRevealController'
8
+ pod 'NanoStore', '~> 2.6.0'
9
+ pod 'SDWebImage'
10
+ pod 'SVPullToRefresh'
11
+ pod 'MBAlertView'
12
+ end
13
+ app.detect_dependencies = false
14
+ end
@@ -0,0 +1,141 @@
1
+ module MotionPrime
2
+ class ViewStyler
3
+ attr_reader :view, :options
4
+
5
+ def initialize(view, bounds = CGRectZero, options = {})
6
+ @options = Styles.extend_and_normalize_options options
7
+ @view = view
8
+ calculate_frame_for(bounds) if @options.delete(:calculate_frame)
9
+ end
10
+
11
+ def apply
12
+ convert_primitives_to_objects(options)
13
+ setValuesForKeysWithDictionary(options)
14
+ end
15
+
16
+ def convert_primitives_to_objects(options)
17
+ options.each do |k,v|
18
+ options[k] = STRUCTS_MAP[v.class].call(v) if STRUCTS_MAP.has_key?(v.class)
19
+ end
20
+ end
21
+
22
+ def calculate_frame_for(bounds)
23
+ width = options.delete(:width)
24
+ height = options.delete(:height)
25
+ top = options.delete(:top)
26
+ right = options.delete(:right)
27
+ bottom = options.delete(:bottom)
28
+ left = options.delete(:left)
29
+
30
+ if width.nil? && height.nil? && right.nil? && bottom.nil?
31
+ options[:frame] = CGRectZero
32
+ else
33
+ frame = CGRectZero
34
+ max_width = bounds.size.width
35
+ max_height = bounds.size.height
36
+ width = 0.0 if width.nil?
37
+ height = 0.0 if height.nil?
38
+
39
+ # calculate left and right if width is relative, e.g 0.7
40
+ if width > 0 && width <= 1
41
+ if right.nil?
42
+ left ||= 0
43
+ right = max_width - max_width * width
44
+ else
45
+ left = max_width - max_width * width
46
+ end
47
+ end
48
+
49
+ # calculate top and bottom if height is relative, e.g 0.7
50
+ if height > 0 && height <= 1
51
+ if bottom.nil?
52
+ top ||= 0
53
+ bottom = max_height - max_height * height
54
+ else
55
+ top = max_height - max_height * height
56
+ end
57
+ end
58
+
59
+ mask = UIViewAutoresizingNone
60
+ mask |= UIViewAutoresizingFlexibleTopMargin if top.nil?
61
+ mask |= UIViewAutoresizingFlexibleLeftMargin if left.nil?
62
+ mask |= UIViewAutoresizingFlexibleBottomMargin if bottom.nil?
63
+ mask |= UIViewAutoresizingFlexibleRightMargin if right.nil?
64
+ mask |= UIViewAutoresizingFlexibleWidth if !left.nil? && !right.nil?
65
+ mask |= UIViewAutoresizingFlexibleHeight if !top.nil? && !bottom.nil?
66
+
67
+ if !left.nil? && !right.nil?
68
+ frame.origin.x = left
69
+ frame.size.width = max_width - left - right
70
+ elsif !right.nil?
71
+ frame.origin.x = max_width - width - right
72
+ frame.size.width = width
73
+ elsif !left.nil?
74
+ frame.origin.x = left
75
+ frame.size.width = width
76
+ else
77
+ frame.origin.x = max_width / 2 - width / 2
78
+ frame.size.width = width
79
+ end
80
+
81
+ if !top.nil? && !bottom.nil?
82
+ frame.origin.y = top
83
+ frame.size.height = max_height - top - bottom
84
+ elsif !bottom.nil?
85
+ frame.origin.y = max_height - height - bottom
86
+ frame.size.height = height
87
+ elsif !top.nil?
88
+ frame.origin.y = top
89
+ frame.size.height = height
90
+ else
91
+ frame.origin.y = max_height / 2 - height / 2
92
+ frame.size.height = height
93
+ end
94
+
95
+ options[:frame] = frame
96
+ options[:autoresizingMask] = mask
97
+ end
98
+ end
99
+
100
+ def setValue(value, forUndefinedKey: key)
101
+ return if value.nil?
102
+ # ignore options
103
+ return if key == 'size_to_fit' && view.is_a?(UILabel)
104
+ return if (key == 'url' || key == 'default') && view.is_a?(UIImageView)
105
+
106
+ # apply options
107
+ if key.end_with?('title_color')
108
+ view.setTitleColor value.uicolor, forState: UIControlStateNormal
109
+ elsif key.end_with?('title_shadow_color')
110
+ view.setTitleShadowColor value.uicolor, forState: UIControlStateNormal
111
+ elsif key.end_with?('color')
112
+ color = value.uicolor
113
+ color = color.cgcolor if view.is_a?(CALayer)
114
+ view.send :"#{key.camelize(:lower)}=", color
115
+ elsif key.end_with?('background_image')
116
+ if view.is_a?(UIButton)
117
+ view.setBackgroundImage value.uiimage, forState: UIControlStateNormal
118
+ elsif view.is_a?(UISearchBar) && key == 'search_field_background_image'
119
+ view.setSearchFieldBackgroundImage value.uiimage, forState: UIControlStateNormal
120
+ else
121
+ view.setBackgroundColor value.uiimage.uicolor
122
+ end
123
+ elsif key.end_with?('image')
124
+ view.setValue value.uiimage, forKey: key.camelize
125
+ elsif value.is_a?(Hash)
126
+ self.class.new(view.send(key.camelize(:lower).to_sym), nil, value).apply
127
+ else
128
+ view.setValue value, forKey: key.camelize(:lower)
129
+ end
130
+ end
131
+
132
+ STRUCTS_MAP = {
133
+ CGAffineTransform => Proc.new {|v| NSValue.valueWithCGAffineTransform(v) },
134
+ CGPoint => Proc.new {|v| NSValue.valueWithCGPoint(v) },
135
+ CGRect => Proc.new {|v| NSValue.valueWithCGRect(v) },
136
+ CGSize => Proc.new {|v| NSValue.valueWithCGSize(v) },
137
+ UIEdgeInsets => Proc.new {|v| NSValue.valueWithUIEdgeInsets(v) },
138
+ UIOffset => Proc.new {|v| NSValue.valueWithUIOffset(v) }
139
+ }
140
+ end
141
+ end