motion-prime 0.1.0

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