motion-pixate-layout 0.0.1

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.
@@ -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: