motion-pixate-layout 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ app/pixate_code.rb
2
+ vendor/*
3
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in motion-pixate-layout.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ motion-pixate-layout (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ bacon (1.1.0)
10
+ motion-pixate (1.2)
11
+ sass
12
+ rake (10.0.4)
13
+ sass (3.2.7)
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ bacon
20
+ motion-pixate
21
+ motion-pixate-layout!
22
+ rake
@@ -0,0 +1,21 @@
1
+ Copyright 2013 Terrible Labs, Inc.
2
+ http://terriblelabs.com/
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,82 @@
1
+ # MotionPixateLayout
2
+
3
+ This project adds a simple DSL to your Rubymotion UIViewControllers to create subviews to be styled with [Pixate](http://www.pixate.com/).
4
+
5
+ The idea is inspired by [Teacup](https://github.com/rubymotion/teacup), which has an awesome layout/subview DSL for layout out your controllers. While this DSL is great, Teacup brings in a lot of style/stylesheet features that are not useful to Pixate users. MotionPixateLayout also adds a convenient shorthand selector to quickly set the styleId and styleClass of subviews.
6
+
7
+ ## A quick example
8
+
9
+ ````ruby
10
+ class MyViewController < UIViewController
11
+ pixate_layout '#my-view.fancy' do
12
+ UILabel '#title-label.small.green', text: 'My Title'
13
+ UIButton '#ok-button.call-to-action'
14
+ end
15
+ end
16
+ ````
17
+
18
+ This code hooks into UIViewController's `viewDidLoad` mode and:
19
+
20
+ 1. Sets `view.styleId` to 'my-view'
21
+ 1. Sets `view.styleClass` to 'fancy'
22
+ 1. Adds a UILabel with these attributes as a subview of the controller's view:
23
+ * styleId: 'title-label'
24
+ * styleClass: 'small green'
25
+ * text: 'My Title'
26
+ 1. Adds a UIButton with these attributes as a subview of the controller's view:
27
+ * styleId: 'ok-button'
28
+ * styleClass: 'call-to-action'
29
+
30
+ ## Accessing subviews
31
+
32
+ MotionPixateLayout adds a `subviews` accessor to UIViewController that returns a hash of the controller's main view's subviews, where the keys are the styleId of the subview. To set the text of the title-label in the above example, we can access the subview by its id:
33
+
34
+ ````ruby
35
+ class MyViewController < UIViewController
36
+ # pixate_layout { ... }
37
+
38
+ def update_label_text
39
+ subviews['title-label'] = 'An updated title'
40
+ end
41
+ end
42
+ ````
43
+
44
+ ## Context and lifecycle
45
+
46
+ Be aware that inside the pixate_layout block is instance_eval'ed in the context of a proxy object, so you can't call methods on or add instance variables to your controller there. MotionPixateLayout adds 2 lifecycle hooks, `before_pixate_layout` and `after_pixate_layout` that execute in the context of your controller instance before and after the layout block, respectively.
47
+
48
+
49
+ ````ruby
50
+ class MyViewController < UIViewController
51
+ pixate_layout do
52
+ @layout = true # Does not set an instance variable in controller
53
+ end
54
+
55
+ before_pixate_layout do
56
+ @layout = true # sets @layout instance variable in controller
57
+ end
58
+
59
+ after_pixate_layout do
60
+ @layout = true # sets @layout instance variable in controller
61
+ end
62
+ end
63
+ ````
64
+
65
+ ## Installation
66
+
67
+ If you're using Bundler, just add `gem 'motion-pixate-layout'` to your Gemfile, and `bundle install`.
68
+
69
+ Make sure you've vendored the Pixate framework and [set up motion-pixate](https://github.com/Pixate/RubyMotion-Pixate#setup).
70
+
71
+ ## To-do
72
+
73
+ * Generalize to work with NUI in addition to Pixate (rename?)
74
+ * More examples
75
+
76
+ ## Suggestions? Comments?
77
+
78
+ I'd love some.
79
+
80
+ ## Contributions
81
+
82
+ Are welcome. Please fork and submit a pull request with some specs.
@@ -0,0 +1,14 @@
1
+ require "bundler/gem_tasks"
2
+ $:.unshift("/Library/RubyMotion/lib")
3
+ require 'motion/project'
4
+ Bundler.setup
5
+ Bundler.require
6
+
7
+ require 'motion-pixate'
8
+
9
+ Motion::Project::App.setup do |app|
10
+ app.name = 'testSuite'
11
+ app.identifier = 'com.terriblelabs.motionPixateLayout.testSuite'
12
+
13
+ app.pixate.framework = 'vendor/PXEngine.framework'
14
+ end
@@ -0,0 +1,5 @@
1
+ class AppDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ true
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ unless defined?(Motion::Project::Config)
2
+ raise "The motion-pixate-layout gem must be required within a RubyMotion project Rakefile."
3
+ end
4
+
5
+
6
+ Motion::Project::App.setup do |app|
7
+ # scans app.files until it finds app/ (the default)
8
+ # if found, it inserts just before those files, otherwise it will insert to
9
+ # the end of the list
10
+ insert_point = 0
11
+ app.files.each_index do |index|
12
+ file = app.files[index]
13
+ if file =~ /^(?:\.\/)?app\//
14
+ # found app/, so stop looking
15
+ break
16
+ end
17
+ insert_point = index + 1
18
+ end
19
+
20
+ Dir.glob(File.join(File.dirname(__FILE__), 'motion-pixate-layout/**/*.rb')).reverse.each do |file|
21
+ app.files.insert(insert_point, file)
22
+ end
23
+ end
@@ -0,0 +1,60 @@
1
+ module MotionPixateLayout
2
+ class Layout
3
+ attr_accessor :selector
4
+
5
+ def <<(block)
6
+ blocks << block
7
+ end
8
+
9
+ def each
10
+ blocks.each do |block|
11
+ yield block
12
+ end
13
+ end
14
+
15
+ def after
16
+ @_after ||= []
17
+ end
18
+
19
+ def before
20
+ @_before ||= []
21
+ end
22
+
23
+ def blocks
24
+ @_blocks ||= []
25
+ end
26
+ end
27
+
28
+ class Proxy
29
+ attr_reader :view
30
+
31
+ def initialize(view)
32
+ @view = view
33
+ end
34
+
35
+ def method_missing(method_name, *args)
36
+ if Kernel.constants.include?(method_name.to_sym)
37
+ view_class = Kernel.const_get(method_name.to_s)
38
+ raise "#{view_class.name} is not a known UIView subclass" unless view_class < UIView
39
+ return subview(view_class, *args)
40
+ else
41
+ raise "#{method_name} is not defined. Should be a subclass of UIView."
42
+ end
43
+ end
44
+
45
+ def subview(subview_class, selector, attributes = {})
46
+ selector = MotionPixateLayout::Selector.new(selector)
47
+
48
+ subview_class.new.tap do |subview|
49
+ subview.styleId = selector.style_id
50
+ subview.styleClass = selector.style_classes.join(" ")
51
+
52
+ attributes.each do |key, value|
53
+ subview.send "#{key}=", value
54
+ end
55
+
56
+ view.addSubview subview
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,19 @@
1
+ module MotionPixateLayout
2
+ class Selector
3
+ attr_reader :string
4
+ CLASS_PATTERN = (/\.([^#\.\s]+)/)
5
+ ID_PATTERN = (/#([^#\.\s]+)/)
6
+
7
+ def initialize(string)
8
+ @string = string
9
+ end
10
+
11
+ def style_classes
12
+ @_classes ||= string.scan(CLASS_PATTERN).flatten
13
+ end
14
+
15
+ def style_id
16
+ @_style_id ||= string.scan(ID_PATTERN).flatten.first
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module MotionPixateLayout
2
+ Version = '0.0.1'
3
+ end
@@ -0,0 +1,55 @@
1
+ class UIViewController
2
+ class << self
3
+ def pixate_layout(selector='', &block)
4
+ if block_given?
5
+ pixate_layout.selector = MotionPixateLayout::Selector.new(selector)
6
+ pixate_layout << block
7
+ else
8
+ @_pixate_layout ||= MotionPixateLayout::Layout.new
9
+ end
10
+ end
11
+
12
+ def after_pixate_layout(&block)
13
+ pixate_layout.after << block
14
+ end
15
+
16
+ def before_pixate_layout(&block)
17
+ pixate_layout.before << block
18
+ end
19
+ end
20
+
21
+ def pixate_layout
22
+ self.class.pixate_layout
23
+ end
24
+
25
+ def viewDidLoad
26
+ if pixate_layout.selector
27
+ view.styleId = pixate_layout.selector.style_id
28
+ view.styleClass = pixate_layout.selector.style_classes.join(' ')
29
+ end
30
+
31
+ proxy = MotionPixateLayout::Proxy.new(view)
32
+
33
+ pixate_layout.before.each do |block|
34
+ instance_eval &block
35
+ end
36
+
37
+ pixate_layout.each do |block|
38
+ proxy.instance_eval &block
39
+ end
40
+
41
+ view.updateStyles
42
+
43
+ pixate_layout.after.each do |block|
44
+ instance_eval &block
45
+ end
46
+ end
47
+
48
+ def subviews
49
+ Hash[
50
+ view.subviews.select(&:styleId).map do |view|
51
+ [view.styleId, view]
52
+ end
53
+ ].freeze
54
+ end
55
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/motion-pixate-layout/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Joe Lind"]
6
+ gem.email = ["joe@terriblelabs.com"]
7
+ gem.description = "A RubyMotion DSL to add subviews that are styled with Pixate"
8
+ gem.summary = "A RubyMotion DSL to add subviews that are styled with Pixate"
9
+ gem.homepage = 'http://github.com/terriblelabs/motion-pixate-layout'
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.test_files = gem.files.grep(%r{^(test|spec|lib_spec|features)/})
13
+ gem.name = "motion-pixate-layout"
14
+ gem.require_paths = ["lib"]
15
+ gem.version = MotionPixateLayout::Version
16
+
17
+ gem.add_development_dependency 'motion-pixate'
18
+ gem.add_development_dependency 'bacon'
19
+ gem.add_development_dependency 'rake'
20
+ end
@@ -0,0 +1,59 @@
1
+ describe "MotionPixateLayout::Layout" do
2
+ describe "UIViewController Extensions" do
3
+ describe "pixate_layout" do
4
+ class TestViewController < UIViewController
5
+ attr_reader :before_called
6
+
7
+ before_pixate_layout do
8
+ @before_called = true
9
+ end
10
+
11
+ pixate_layout '#view-id.view-class.view-class-2' do
12
+ UILabel '#style-id.class1.class2', text: 'Test Label'
13
+ end
14
+
15
+ after_pixate_layout do
16
+ subviews['style-id'].accessibilityLabel = 'Set after pixate layout'
17
+ end
18
+ end
19
+
20
+ tests TestViewController
21
+
22
+ it "is added to UIViewController" do
23
+ UIViewController.should.respond_to :pixate_layout
24
+ end
25
+
26
+ it 'sets the style id of its view from the selector' do
27
+ controller.view.styleId.should == 'view-id'
28
+ end
29
+
30
+ it 'sets the style class of its view from the selector' do
31
+ controller.view.styleClass.should == 'view-class view-class-2'
32
+ end
33
+
34
+ it "adds subviews that are specified in its block" do
35
+ controller.view.subviews.size.should == 1
36
+ end
37
+
38
+ it "assigns the styleID from subview selectors" do
39
+ controller.view.subviews.first.styleId.should == 'style-id'
40
+ end
41
+
42
+ it 'assigns the styleClass from subview selectors' do
43
+ controller.view.subviews.first.styleClass.should == 'class1 class2'
44
+ end
45
+
46
+ it 'exposes subviews via their styldId' do
47
+ controller.subviews['style-id'].should.be.kind_of UILabel
48
+ end
49
+
50
+ it 'calls the before_pixate_layout blocks' do
51
+ controller.before_called.should.be.true
52
+ end
53
+
54
+ it 'calls the after_pixate_layout blocks' do
55
+ controller.subviews['style-id'].accessibilityLabel.should == 'Set after pixate layout'
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,17 @@
1
+ describe 'Selector' do
2
+ before do
3
+ @selector = MotionPixateLayout::Selector.new('#some-id.class1.class2')
4
+ end
5
+
6
+ describe '.style_classes' do
7
+ it 'returns an array of the parsed classes from the selector' do
8
+ @selector.style_classes.should == %w[class1 class2]
9
+ end
10
+ end
11
+
12
+ describe '.style_id' do
13
+ it "returns the id parsed from the selector" do
14
+ @selector.style_id.should == 'some-id'
15
+ end
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: motion-pixate-layout
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joe Lind
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: motion-pixate
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bacon
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A RubyMotion DSL to add subviews that are styled with Pixate
63
+ email:
64
+ - joe@terriblelabs.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - Gemfile.lock
72
+ - LICENSE.md
73
+ - README.md
74
+ - Rakefile
75
+ - app/app_delegate.rb
76
+ - lib/motion-pixate-layout.rb
77
+ - lib/motion-pixate-layout/layout.rb
78
+ - lib/motion-pixate-layout/selector.rb
79
+ - lib/motion-pixate-layout/version.rb
80
+ - lib/motion-pixate-layout/z_core_extensions/ui_view_controller.rb
81
+ - motion-pixate-layout.gemspec
82
+ - spec/lib/layout_spec.rb
83
+ - spec/lib/selector_spec.rb
84
+ homepage: http://github.com/terriblelabs/motion-pixate-layout
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.23
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: A RubyMotion DSL to add subviews that are styled with Pixate
108
+ test_files:
109
+ - spec/lib/layout_spec.rb
110
+ - spec/lib/selector_spec.rb
111
+ has_rdoc: