droidproj 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzVlYTdhMjcxZmFlNTMwNDEwMjdhNmRkYjdkOWE0NjU2MWJlOTQxNA==
5
+ data.tar.gz: !binary |-
6
+ MGVhZDYxMzNlMjZjYzdiN2U2OWExNzdiMjA0NWUwNjNmYTJlYzZjMA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ YjQ2ZjZjOGNlNWIxNDQwOTMxYTA3MWNiZDE4NjlmMGQwM2FmMTdlYjI0YTBl
10
+ YzI0NTFlMmVmMGYzYjE5YWM4OWY5MDNhNjI3NzhhZDc0YzFjODYyNmNlNzli
11
+ YWNiNDUxOTdiNjY4OTQ3YWYwNDAxNTI2ODU4MjllOTlkYmFjZDQ=
12
+ data.tar.gz: !binary |-
13
+ NTBhNDViZDBiNjQwYjg0NThiMjgwZjA0NDlkYTM3YTlkYTRiNzcyMmExZDZh
14
+ NTIzYjRiZGVjNWI0MDI3NzJjN2U5Y2JjZmQxOGUxN2QzOTRkNmZkYTFjYTg2
15
+ MzQ2NjdhMmIyZjkzOTE5YTYzYjkxNThmN2NiZTRmMDk2ZmZkMzQ=
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ droidproj (0.0.1)
5
+ colorize (~> 0.5.8)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ colorize (0.5.8)
11
+ diff-lcs (1.2.4)
12
+ rake (10.0.4)
13
+ rspec (2.13.0)
14
+ rspec-core (~> 2.13.0)
15
+ rspec-expectations (~> 2.13.0)
16
+ rspec-mocks (~> 2.13.0)
17
+ rspec-core (2.13.1)
18
+ rspec-expectations (2.13.0)
19
+ diff-lcs (>= 1.1.3, < 2.0)
20
+ rspec-mocks (2.13.1)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ droidproj!
27
+ rake
28
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 TurboProp, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,144 @@
1
+ # DroidProj - Automating Android Management
2
+
3
+ Managing Android projects sucks. Static XML sucks. Do it all in Ruby, with a `Droidfile` and a DSL:
4
+
5
+ ```ruby
6
+ # ./Droidfile
7
+
8
+ res do
9
+ drawable 'back_icon' do
10
+ state(enabled: false) do
11
+ hdpi './images/back_disabled@hdpi.png'
12
+ ldpi './images/back_disabled@ldpi.png'
13
+ mdpi './images/back_disabled.png'
14
+ end
15
+ hdpi './images/back@hdpi.png'
16
+ ldpi './images/back@ldpi.png'
17
+ mdpi './images/back.png'
18
+ end
19
+ end
20
+ ```
21
+
22
+ This will (non-destructively) create the following directory structure in your Android project:
23
+
24
+ ```
25
+ .
26
+ |-- res
27
+ |---- drawable
28
+ |------ back_icon.xml
29
+ |---- drawable-ldpi
30
+ |------ x_back_icon.png
31
+ |------ x_back_icon_enabled_false.png
32
+ |---- drawable-hdpi
33
+ |------ x_back_icon.png
34
+ |------ x_back_icon_enabled_false.png
35
+ |---- drawable-mdpi
36
+ |------ x_back_icon.png
37
+ |------ x_back_icon_enabled_false.png
38
+ ```
39
+
40
+ ## Installation
41
+
42
+ `gem install droidproj`
43
+
44
+ This will install the `droid` CLI, which you can use in any directory with a `Droidfile`:
45
+
46
+ ```bash
47
+ $ ls -l
48
+ ...
49
+ AndroidManifest.xml
50
+ images
51
+ src
52
+ target
53
+ Droidfile
54
+
55
+ $ droid
56
+ Evaluating Droidfile...
57
+ Creating filesystem...
58
+ Creating ./res...
59
+ ...
60
+ Copying ./images/back.png to ./res/drawable-mdpi/x_back_icon.png...
61
+ Done!
62
+
63
+ $ ls -l
64
+ ...
65
+ AndroidManifest.xml
66
+ images
67
+ res
68
+ ...
69
+ ```
70
+
71
+ ## Usage
72
+
73
+ ```ruby
74
+ # ./Droidfile
75
+ # This is all plain-old *Ruby*, like a Gemfile or Rakefile
76
+
77
+ # Declare that you're writing to the `res` folder
78
+ res do
79
+ # Create a new drawable XML with name `back_icon.xml`
80
+ # (this is what you'll access in code as R.drawable.back_icon)
81
+ drawable 'back_icon' do
82
+ # Assign new images using [hdpi, ldpi, mdpi, or xhdpi]
83
+ xhdpi './images/back@xhdpi.png'
84
+ hdpi './images/back@hdpi.png'
85
+ ldpi './images/back@ldpi.png'
86
+ mdpi './images/back.png'
87
+
88
+ # Assign new images for different states with `state`
89
+ # (these are translated to the `android:state_[enabled/focused/etc]` XML)
90
+ state(focused: true) do
91
+ hdpi './images/back_focused@hdpi.png'
92
+ ldpi './images/back_focused@ldpi.png'
93
+ mdpi './images/back_focused.png'
94
+ end
95
+ state(enabled: false) do
96
+ hdpi './images/back_disabled@hdpi.png'
97
+ ldpi './images/back_disabled@ldpi.png'
98
+ mdpi './images/back_disabled.png'
99
+ end
100
+
101
+ end
102
+ end
103
+ ```
104
+
105
+ ## Why?
106
+
107
+ You may think this seems like a glorified `cp` wrapper, right? Actually, DroidProj's benefits are that:
108
+
109
+ - Your original resource file names are not explicitly tied to how they're used in code. Often times designers will deliver assets with their own naming or folder scheme, which doesn't exactly jive with what Android expects them to be. DroidProj will name everything to make sense and just work.
110
+
111
+ - You can execute normal Ruby to automate and/or manipulate your Android projects. This is taken from [Propeller](http://usepropeller.com)'s own `Droidfile`:
112
+
113
+ ```ruby
114
+ res do
115
+ drawable 'back_icon' do
116
+ # DRY up the images
117
+ ["hdpi", "xhdpi", "mdpi"].each do |size|
118
+ self.send(size, "./images/back_white@#{size}.png")
119
+ end
120
+
121
+ # Automatically create disabled-state images
122
+ state(enabled: false) do
123
+ ["hdpi", "xhdpi", "mdpi"].each do |size|
124
+ original = "./images/back_white@#{size}.png"
125
+ new_path = original.gsub("@#{size}", "_disabled@#{size}")
126
+ transparency = "convert " << original << ' -channel A -fx "A*0.5" ' << new_path
127
+ system(transparency)
128
+ self.send(size, new_path)
129
+ end
130
+ end
131
+ end
132
+ end
133
+ ```
134
+
135
+ ## Contact
136
+
137
+ Clay Allsopp ([http://clayallsopp.com](http://clayallsopp.com))
138
+
139
+ - [http://twitter.com/clayallsopp](http://twitter.com/clayallsopp)
140
+ - [clay@usepropeller.com](clay@usepropeller.com)
141
+
142
+ ## License
143
+
144
+ DroidProj is available under the MIT license. See the LICENSE file for more info.
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "bundler/setup"
3
+
4
+ # `rake spec`
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new('spec')
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if $0 == __FILE__
4
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
5
+ require "rubygems"
6
+ require "bundler/setup"
7
+ Bundler.require :default
8
+ $:.unshift File.expand_path('../../lib', __FILE__)
9
+ end
10
+
11
+ if (ENV['CP_STDOUT_SYNC'] == 'TRUE')
12
+ STDOUT.sync = true
13
+ end
14
+
15
+ require 'droidproj'
16
+
17
+ DroidProj::Runner.run
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "droidproj"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "droidproj"
7
+ s.license = "MIT"
8
+ s.authors = ["Clay Allsopp"]
9
+ s.email = "clay@usepropeller.com"
10
+ s.homepage = "http://usepropeler.com"
11
+ s.version = DroidProj::VERSION
12
+ s.platform = Gem::Platform::RUBY
13
+ s.summary = "DroidProj"
14
+ s.description = "Manage Android projects with a Droidfile"
15
+
16
+ s.add_dependency "colorize", "~> 0.5.8"
17
+
18
+ s.add_development_dependency "rspec"
19
+ s.add_development_dependency "rake"
20
+
21
+ s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,11 @@
1
+ module DroidProj
2
+ VERSION = "0.0.1"
3
+ end
4
+
5
+ require 'colorize'
6
+ require 'droidproj/logger'
7
+ require 'droidproj/runner'
8
+ require 'droidproj/app'
9
+ require 'droidproj/res'
10
+ require 'droidproj/drawable'
11
+ require 'droidproj/drawable_state'
@@ -0,0 +1,73 @@
1
+ require 'fileutils'
2
+ require 'ap'
3
+
4
+ module DroidProj
5
+ module Android
6
+ class App
7
+ attr_accessor :root_dir, :res_path, :res
8
+
9
+ def initialize(root_dir)
10
+ @root_dir = root_dir
11
+ end
12
+
13
+ def res_path
14
+ @res_path || File.join(self.root_dir, 'res')
15
+ end
16
+
17
+ # Public: DSL for setting the app's resources
18
+ #
19
+ # &block - (optional) Block which is called to create a new Android::Resources
20
+ # object, which is then set to self.res
21
+ #
22
+ # Returns either the existing Android::Resources object or the newly
23
+ # created one.
24
+ def res(&block)
25
+ if block
26
+ @res ||= DroidProj::Android::Resources.new
27
+ @res.app = self
28
+ case block.arity
29
+ when 0
30
+ @res.instance_eval &block
31
+ when 1
32
+ block.call(@res)
33
+ end
34
+ end
35
+
36
+ @res
37
+ end
38
+
39
+ # Public: Creates the necessary filesystem considering all options
40
+ #
41
+ def create_filesystem!
42
+ return if !self.res
43
+
44
+ res_filesystem = self.res.filesystem_hash
45
+
46
+ DroidProj::Logger.log "Creating #{res_path}..."
47
+ FileUtils.mkdir_p res_path
48
+
49
+ res_filesystem.each do |folder, files|
50
+ folder = folder.to_s
51
+ folder_path = File.join(res_path, folder)
52
+ DroidProj::Logger.log "Creating #{folder_path}...".green
53
+ FileUtils.mkdir_p folder_path
54
+ files.each do |file_op|
55
+ case file_op
56
+ when Android::Resources::MoveOp
57
+ to = File.join(res_path, folder, file_op.to)
58
+ DroidProj::Logger.log "Copying #{file_op.from} to #{to}...".green
59
+ FileUtils.cp file_op.from, to
60
+ when Android::Resources::WriteOp
61
+ at = File.join(res_path, folder, file_op.at)
62
+ DroidProj::Logger.log "Writing #{at}...".green
63
+ FileUtils.rm_f at
64
+ File.open(at, 'w') { |f|
65
+ f.write(file_op.content)
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,138 @@
1
+ module DroidProj
2
+ module Android
3
+ class Drawable
4
+ FINAL_FILE_PREFIX = "x_"
5
+ # Hash of STATE_HASH =>
6
+ attr_accessor :states
7
+ # The final name for this drawable, used in your code
8
+ attr_accessor :name
9
+ # The current state being set for this drawable
10
+ attr_accessor :active_state
11
+
12
+ SIZES = [:hdpi, :ldpi, :mdpi, :xhdpi]
13
+ attr_accessor *SIZES
14
+
15
+ def initialize
16
+ @active_state = {}
17
+ @states = {}
18
+ end
19
+
20
+ # Public: The DSL for creating drawables corresponding to a certain state
21
+ #
22
+ # active_state - The Hash of options to set the `active_state`
23
+ # &block - A block to be execute with the new `active_state`
24
+ #
25
+ # Examples
26
+ #
27
+ # drawable.state(enabled: true, focused: false) do
28
+ # # In this block, all drawables are set with the above state
29
+ # hdpi 'image.png'
30
+ # end
31
+ #
32
+ # Returns the Drawable instance being used
33
+ def state(active_state, &block)
34
+ self.active_state = Hash[active_state.map {|k, v| [k.to_sym, v] }]
35
+ block.call
36
+ self.active_state = {}
37
+ self
38
+ end
39
+
40
+ # Public: The DSL for creating & setting Anroid::DrawableState objects
41
+ #
42
+ # file_path = nil - The String path where the image file is located
43
+ #
44
+ # Examples
45
+ #
46
+ # self.hdpi
47
+ # # => #<Android::Drawable::State> # the current drawable state
48
+ # self.hdpi "some_file.png"
49
+ # # => #<Android::Drawable::State> # a new drawable state, setting self.hdpi
50
+ #
51
+ # Returns the new Android::Drawable::State
52
+ SIZES.each do |size|
53
+ define_method(size, ->(file_path = nil, options = {}) {
54
+ size_list = self.instance_variable_get("@#{size}")
55
+ # EX self.hdpi
56
+ # => #<Android::Drawable::State>
57
+ if !file_path
58
+ return size_list
59
+ end
60
+
61
+ # EX self.hdpi "some_file.png"
62
+ drawable_state = DroidProj::Android::DrawableState.new
63
+ drawable_state.drawable = self
64
+ drawable_state.file_path = file_path
65
+ drawable_state.size = size.to_sym
66
+ temp_state = {}
67
+ temp_state.merge!(self.active_state)
68
+ options.merge(self.active_state).each do |key, value|
69
+ if key.to_s.start_with?("state_")
70
+ key_state = key.to_s.split("state_")[-1].to_sym
71
+ temp_state[key_state] = value
72
+ end
73
+ end
74
+ drawable_state.state = temp_state
75
+ self.states[temp_state] ||= []
76
+ self.states[temp_state] << drawable_state
77
+ drawable_state
78
+ })
79
+ end
80
+
81
+ def to_size_buckets
82
+ size_buckets = {}
83
+ self.states.each do |state, drawable_states|
84
+ drawable_states.each do |drawable_state|
85
+ size_buckets[drawable_state.size] ||= []
86
+ size_buckets[drawable_state.size] << drawable_state
87
+ end
88
+ end
89
+ size_buckets
90
+ end
91
+
92
+ # Public: The StateList XML representation of this drawable, used by Android
93
+ #
94
+ # Returns the String representation
95
+ def xml_string
96
+ str =
97
+ %Q{<?xml version="1.0" encoding="utf-8"?>
98
+ <selector xmlns:android="http://schemas.android.com/apk/res/android">
99
+ }
100
+
101
+ self.sorted_states.each do |state, drawable_states|
102
+ drawable_states.each do |drawable_state|
103
+ if !str.include?(drawable_state.xml_string)
104
+ str <<
105
+ %Q{ #{drawable_state.xml_string}
106
+ }
107
+ end
108
+ end
109
+ end
110
+
111
+ default_drawable = "<item android:drawable=\"@drawable/#{FINAL_FILE_PREFIX}#{self.name}\" />\n"
112
+ if !str.include?(default_drawable)
113
+ str <<
114
+ %Q{ #{default_drawable}}
115
+ end
116
+
117
+ str <<
118
+ %Q{</selector>}
119
+ end
120
+
121
+ # Internal: Sort `self.states` by how long each state is
122
+ # (because Android wants the XML file to be sorted by specificity)
123
+ #
124
+ # Returns an Array relating to `self.states` as [:key, :value], sorted
125
+ # by :key length
126
+ def sorted_states
127
+ keys = self.states.keys
128
+ keys.sort_by! {|x|
129
+ x.to_s.length
130
+ }.reverse!
131
+ sorted_hash = keys.map {|key|
132
+ [key, self.states[key]]
133
+ }
134
+ sorted_hash
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,46 @@
1
+ require 'pathname'
2
+
3
+ module DroidProj
4
+ module Android
5
+ class DrawableState
6
+ # Hash of options which define what android:state this is for
7
+ attr_accessor :state
8
+ # Symbol for what size folder this goes into
9
+ attr_accessor :size
10
+ # String original path of the image file
11
+ attr_accessor :file_path
12
+ # Android::Drawable instance this state is for
13
+ attr_accessor :drawable
14
+
15
+ def initialize
16
+ @state = {}
17
+ end
18
+
19
+ def xml_string
20
+ str = "<item "
21
+ self.state.each do |state, value|
22
+ str << "android:state_#{state}=\"#{value}\" "
23
+ end
24
+
25
+ str << "android:drawable=\"@drawable/#{final_drawable_name}\" />"
26
+ end
27
+
28
+ def final_file_name
29
+ final_drawable_name + "." + final_extension
30
+ end
31
+
32
+ def final_drawable_name
33
+ final_file_name = DroidProj::Android::Drawable::FINAL_FILE_PREFIX + self.drawable.name
34
+ self.state.each do |state, value|
35
+ final_file_name << "_#{state}_#{value}"
36
+ end
37
+ final_file_name
38
+ end
39
+
40
+ def final_extension
41
+ file_name = Pathname.new(self.file_path).basename
42
+ file_name.to_s.split('.')[1..-1].join('.')
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,23 @@
1
+ module DroidProj
2
+ class Logger
3
+ class << self
4
+ def log(message)
5
+ logger.log(message)
6
+ end
7
+
8
+ def logger
9
+ @logger ||= new
10
+ end
11
+ end
12
+
13
+ attr_accessor :enabled
14
+
15
+ def initialize
16
+ @enabled = true
17
+ end
18
+
19
+ def log(message)
20
+ puts message.green if self.enabled
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,109 @@
1
+ module DroidProj
2
+ module Android
3
+ class ResourcesDrawables < Array
4
+ def [](index_or_key)
5
+ if index_or_key.is_a?(Numeric)
6
+ super
7
+ else
8
+ self.select { |drawable|
9
+ drawable.name == index_or_key
10
+ }.first
11
+ end
12
+ end
13
+ end
14
+
15
+ class Resources
16
+ class MoveOp
17
+ attr_accessor :to, :from
18
+
19
+ def ==(other)
20
+ other.to == self.to && other.from == self.from
21
+ end
22
+ end
23
+
24
+ class WriteOp
25
+ attr_accessor :at, :content
26
+
27
+ def ==(other)
28
+ other.at == self.at && other.content == self.content
29
+ end
30
+ end
31
+
32
+ attr_accessor :app
33
+ attr_accessor :drawables
34
+
35
+ def initialize
36
+ @drawables = ResourcesDrawables.new
37
+ end
38
+
39
+ # Public: DSL for creating new drawables in the resources
40
+ #
41
+ # name - The String name of the drawable; *this* is what will be referred to
42
+ # in your Java code
43
+ # &block - A DSL block where you can setup aspects of the drawable
44
+ #
45
+ # Examples
46
+ #
47
+ # res.drawable 'my_image' do
48
+ # hdpi 'some_file.png', state_enabled: false
49
+ # end
50
+ # # => #<Android::Drawable>
51
+ # res.drawable 'my_image' do |drawable|
52
+ # drawable.hdpi 'some_file.png', state_enabled: false
53
+ # end
54
+ # # => #<Android::Drawable>
55
+ #
56
+ # Returns the new Android::Drawable instance
57
+ def drawable(name, &block)
58
+ drawable = DroidProj::Android::Drawable.new
59
+ drawable.name = name
60
+ @drawables << drawable
61
+
62
+ case block.arity
63
+ when 0
64
+ drawable.instance_eval &block
65
+ when 1
66
+ block.call(drawable)
67
+ end
68
+ drawable
69
+ end
70
+
71
+ def [](key)
72
+ self.drawables[key]
73
+ end
74
+
75
+ # Public: A Hash representing how the resources should be created in the
76
+ # filesytem
77
+ #
78
+ # Examples
79
+ #
80
+ # res.filesystem_hash
81
+ # # => {drawable: ["drawable.xml"], drawable-hdpi: ["drawable.png"]}
82
+ #
83
+ # Returns the Hash
84
+ def filesystem_hash
85
+ hash = {
86
+ drawable: []
87
+ }
88
+ self.drawables.each do |drawable|
89
+ write_op = WriteOp.new
90
+ write_op.at = drawable.name + ".xml"
91
+ write_op.content = drawable.xml_string
92
+ hash[:drawable] << write_op
93
+
94
+ drawable.to_size_buckets.each do |size, drawable_states|
95
+ drawable_states.each do |drawable_state|
96
+ folder = (hash["drawable-#{size}".to_sym] ||= [])
97
+ op = MoveOp.new
98
+ op.from = drawable_state.file_path
99
+ op.to = drawable_state.final_file_name
100
+ folder << op
101
+ end
102
+ end
103
+ end
104
+
105
+ hash
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,73 @@
1
+ module DroidProj
2
+ class Runner
3
+ POSSIBLE_FILES = [
4
+ 'droidfile',
5
+ 'Droidfile',
6
+ 'droidfile.rb',
7
+ 'Droidfile.rb'
8
+ ].freeze
9
+
10
+ attr_accessor :droidfile, :app
11
+
12
+ class << self
13
+ def run
14
+ new.run
15
+ end
16
+ end
17
+
18
+ def initialize
19
+ @possible_files = POSSIBLE_FILES.dup
20
+ end
21
+
22
+ def run
23
+ @droidfile = find_droidfile_location
24
+
25
+ raise "You need to supply a Droidfile in the current directory" if !@droidfile
26
+
27
+ @app = DroidProj::Android::App.new(File.dirname(@droidfile))
28
+
29
+ DroidProj::Logger.log "Evaluating Droidfile...".green
30
+ eval_droidfile
31
+
32
+ DroidProj::Logger.log "Creating filesystem...".green
33
+ @app.create_filesystem!
34
+
35
+ DroidProj::Logger.log "Done!".green
36
+ end
37
+
38
+ def eval_droidfile
39
+ content = nil
40
+ File.open(@droidfile, 'r') {|file|
41
+ content = file.read
42
+ }
43
+
44
+ context = RunnerContext.new
45
+ context.app = @app
46
+
47
+ eval content, context.create_context.binding
48
+ end
49
+
50
+ def find_droidfile_location
51
+ @possible_files.each do |file|
52
+ return file if File.exist?(file)
53
+ end
54
+ nil
55
+ end
56
+ end
57
+
58
+ class RunnerContext
59
+ attr_accessor :app
60
+
61
+ def create_context
62
+ Proc.new {}
63
+ end
64
+
65
+ def method_missing(method, *args, &block)
66
+ if app.respond_to?(method)
67
+ app.send(method, *args, &block)
68
+ else
69
+ super
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe DroidProj::Android::App do
4
+ TEST_FOLDER = File.join(File.dirname(__FILE__), 'test_app')
5
+
6
+ before do
7
+ FileUtils.mkdir TEST_FOLDER
8
+
9
+ @app = DroidProj::Android::App.new TEST_FOLDER
10
+ end
11
+
12
+ after do
13
+ FileUtils.rm_rf TEST_FOLDER
14
+ end
15
+
16
+
17
+ describe "#res" do
18
+ describe "with instance_eval" do
19
+ it "should create a new Resources" do
20
+ @res = @app.res do
21
+ drawable 'my_image' do
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ describe "with one argument" do
28
+ it "should create a new Drawable" do
29
+ @res = @app.res do |res|
30
+ res.drawable 'my_image' do
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ after do
37
+ @res.should_not == nil
38
+ @res.drawables.count.should == 1
39
+ @res = nil
40
+ end
41
+ end
42
+
43
+ describe "#create_filesystem!" do
44
+ before do
45
+ @app.res do
46
+ drawable 'my_image' do
47
+ end
48
+ end
49
+
50
+ @app.create_filesystem!
51
+ end
52
+
53
+ it "should create a res folder if it doesn't exist" do
54
+ Dir.exists?(File.join(TEST_FOLDER, 'res')).should == true
55
+ end
56
+
57
+ it "should create a my_image xml file" do
58
+ file = File.join(TEST_FOLDER, 'res', 'drawable', 'my_image.xml')
59
+ File.exists?(file).should == true
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe DroidProj::Android::Drawable do
4
+ before do
5
+ @drawable = DroidProj::Android::Drawable.new
6
+ @drawable.name = "drawable_name"
7
+ end
8
+
9
+ describe DroidProj::Android::Drawable::SIZES, "DSL" do
10
+ it "returns existing values" do
11
+ @drawable.hdpi = "something"
12
+ @drawable.hdpi.should == "something"
13
+ end
14
+
15
+ it "sets new values with the DSL" do
16
+ drawable_state = @drawable.hdpi "some_file.png", state_enabled: true
17
+ drawable_state.class.should == DroidProj::Android::DrawableState
18
+ drawable_state.file_path.should == "some_file.png"
19
+ drawable_state.state.should == {enabled: true}
20
+ end
21
+ end
22
+
23
+ describe "#xml_string" do
24
+ it "should produce the correct XML with basic options" do
25
+ @drawable.hdpi "some_file.png", state_enabled: true
26
+
27
+ @drawable.xml_string.should ==
28
+ %Q{<?xml version="1.0" encoding="utf-8"?>
29
+ <selector xmlns:android="http://schemas.android.com/apk/res/android">
30
+ <item android:state_enabled="true" android:drawable="@drawable/#{DroidProj::Android::Drawable::FINAL_FILE_PREFIX}drawable_name_enabled_true" />
31
+ <item android:drawable="@drawable/#{DroidProj::Android::Drawable::FINAL_FILE_PREFIX}drawable_name" />
32
+ </selector>}
33
+ end
34
+
35
+ it "should produce the correct XML with multiple files" do
36
+ @drawable.hdpi "some_file.png"
37
+ @drawable.hdpi "some_file.png", state_enabled: true
38
+ @drawable.ldpi "some_file@ldpi.png", state_enabled: true
39
+
40
+ @drawable.xml_string.should ==
41
+ %Q{<?xml version="1.0" encoding="utf-8"?>
42
+ <selector xmlns:android="http://schemas.android.com/apk/res/android">
43
+ <item android:state_enabled="true" android:drawable="@drawable/#{DroidProj::Android::Drawable::FINAL_FILE_PREFIX}drawable_name_enabled_true" />
44
+ <item android:drawable="@drawable/#{DroidProj::Android::Drawable::FINAL_FILE_PREFIX}drawable_name" />
45
+ </selector>}
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe DroidProj::Android::Resources do
4
+ before do
5
+ @res = DroidProj::Android::Resources.new
6
+ end
7
+
8
+ describe "#drawable" do
9
+ describe "with instance_eval" do
10
+ it "should create a new Drawable" do
11
+ @drawable = @res.drawable 'my_image' do
12
+ hdpi 'some_file.png', state_enabled: false
13
+ end
14
+ end
15
+ end
16
+
17
+ describe "with one argument" do
18
+ it "should create a new Drawable" do
19
+ @drawable = @res.drawable 'my_image' do |drawable|
20
+ drawable.hdpi 'some_file.png', state_enabled: false
21
+ end
22
+ end
23
+ end
24
+
25
+ after do
26
+ @drawable = @res['my_image']
27
+ drawable_state = @drawable.states[{enabled: false}][0]
28
+ drawable_state.file_path.should == "some_file.png"
29
+ drawable_state.state[:enabled].should == false
30
+ drawable_state.size.should == :hdpi
31
+ @drawable = nil
32
+ end
33
+ end
34
+
35
+ describe "#[]" do
36
+ it "should return the correct drawable" do
37
+ drawable = DroidProj::Android::Drawable.new
38
+ drawable.name = "this is some random name"
39
+ @res.drawables << drawable
40
+ @res[drawable.name].should == drawable
41
+ end
42
+ end
43
+
44
+ describe "#filesystem_hash" do
45
+ it "should return the correct structure" do
46
+ drawable = @res.drawable 'my_image' do
47
+ state(enabled: false) do
48
+ hdpi 'some_file_disabled@hdpi.png'
49
+ end
50
+ hdpi 'some_file@hdpi.png'
51
+ ldpi 'some_file@ldpi.png'
52
+ end
53
+
54
+ write_op = DroidProj::Android::Resources::WriteOp.new
55
+ write_op.at = "my_image.xml"
56
+ write_op.content = drawable.xml_string
57
+
58
+ hdpi_op = DroidProj::Android::Resources::MoveOp.new
59
+ hdpi_op.from = 'some_file@hdpi.png'
60
+ hdpi_op.to = "#{DroidProj::Android::Drawable::FINAL_FILE_PREFIX}my_image.png"
61
+
62
+ hdpi_dis_op = DroidProj::Android::Resources::MoveOp.new
63
+ hdpi_dis_op.from = 'some_file_disabled@hdpi.png'
64
+ hdpi_dis_op.to = "#{DroidProj::Android::Drawable::FINAL_FILE_PREFIX}my_image_enabled_false.png"
65
+
66
+ ldpi_op = DroidProj::Android::Resources::MoveOp.new
67
+ ldpi_op.from = 'some_file@ldpi.png'
68
+ ldpi_op.to = "#{DroidProj::Android::Drawable::FINAL_FILE_PREFIX}my_image.png"
69
+
70
+ filesystem_hash = @res.filesystem_hash
71
+
72
+ filesystem_hash[:drawable].should == [write_op]
73
+ filesystem_hash["drawable-hdpi".to_sym].should == [hdpi_dis_op, hdpi_op]
74
+ filesystem_hash["drawable-ldpi".to_sym].should == [ldpi_op]
75
+ end
76
+ end
77
+ end
Binary file
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe DroidProj::Runner do
4
+ BASIC_DROIDFILE = %Q{
5
+ magic
6
+ block_magic do
7
+ 3
8
+ end}
9
+
10
+ WORKING_DROIDFILE = %Q{
11
+ res do
12
+ drawable 'back_icon' do
13
+ hdpi './images/back@hdpi.png'
14
+ ldpi './images/back@ldpi.png'
15
+ mdpi './images/back.png'
16
+ end
17
+ end}
18
+
19
+ TEST_FOLDER = File.join(File.dirname(__FILE__), 'runnable_spec')
20
+
21
+ before do
22
+ FileUtils.mkdir TEST_FOLDER
23
+ FileUtils.cp_r SPEC_RESOURCES, File.join(TEST_FOLDER, 'images')
24
+
25
+ droidfile = File.join(TEST_FOLDER, 'Droidfile')
26
+ File.open(droidfile, 'w') { |f| f.write(WORKING_DROIDFILE) }
27
+
28
+ @runner = DroidProj::Runner.new
29
+ end
30
+
31
+ after do
32
+ FileUtils.rm_rf TEST_FOLDER
33
+ end
34
+
35
+ describe "#eval_droidfile" do
36
+ before do
37
+ @temp_droidfile = File.join(File.dirname(__FILE__), '_droidfile')
38
+ File.open(@temp_droidfile, 'w') { |file|
39
+ file.write(BASIC_DROIDFILE)
40
+ }
41
+ end
42
+
43
+ after do
44
+ FileUtils.rm_f @temp_droidfile
45
+ end
46
+
47
+ it "should call methods of Android::App" do
48
+ @runner.droidfile = @temp_droidfile
49
+ @runner.app = Object.new.tap do |o|
50
+ def o.magic
51
+ @magic = true
52
+ end
53
+
54
+ def o.block_magic(&block)
55
+ @block_magic = block.call
56
+ end
57
+ end
58
+
59
+ @runner.eval_droidfile
60
+
61
+ @runner.app.instance_variable_get("@magic").should == true
62
+ @runner.app.instance_variable_get("@block_magic").should == 3
63
+ end
64
+ end
65
+
66
+ describe ".run" do
67
+ before do
68
+ @original_dir = Dir.pwd
69
+ Dir.chdir(TEST_FOLDER)
70
+ DroidProj::Logger.logger.enabled = true
71
+ end
72
+
73
+ after do
74
+ Dir.chdir @original_dir
75
+ DroidProj::Logger.logger.enabled = false
76
+ end
77
+
78
+ it "should create the correct filesystem" do
79
+ DroidProj::Runner.run
80
+
81
+ ['drawable', 'drawable-hdpi', 'drawable-ldpi', 'drawable-mdpi'].each do |folder|
82
+ Dir.exists?(File.join(TEST_FOLDER, 'res', folder)).should == true
83
+ if folder != 'drawable'
84
+ File.exists?(File.join(TEST_FOLDER, 'res', folder, "#{DroidProj::Android::Drawable::FINAL_FILE_PREFIX}back_icon.png")).should == true
85
+ else
86
+ File.exists?(File.join(TEST_FOLDER, 'res', folder, 'back_icon.xml')).should == true
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspec'
2
+ require_relative '../lib/droidproj'
3
+
4
+ DroidProj::Logger.logger.enabled = false
5
+
6
+ SPEC_RESOURCES = File.join(File.dirname(__FILE__), 'resources')
7
+
8
+ RSpec.configure do |config|
9
+ config.color_enabled = true
10
+ config.formatter = 'documentation'
11
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: droidproj
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Clay Allsopp
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colorize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.5.8
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.8
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Manage Android projects with a Droidfile
56
+ email: clay@usepropeller.com
57
+ executables:
58
+ - droid
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ./droidproj.gemspec
63
+ - ./Gemfile
64
+ - ./Gemfile.lock
65
+ - ./lib/droidproj/app.rb
66
+ - ./lib/droidproj/drawable.rb
67
+ - ./lib/droidproj/drawable_state.rb
68
+ - ./lib/droidproj/logger.rb
69
+ - ./lib/droidproj/res.rb
70
+ - ./lib/droidproj/runner.rb
71
+ - ./lib/droidproj.rb
72
+ - ./LICENSE
73
+ - ./Rakefile
74
+ - ./README.md
75
+ - spec/app_spec.rb
76
+ - spec/drawable_spec.rb
77
+ - spec/res_spec.rb
78
+ - spec/resources/back.png
79
+ - spec/resources/back@hdpi.png
80
+ - spec/resources/back@ldpi.png
81
+ - spec/runner_spec.rb
82
+ - spec/spec_helper.rb
83
+ - bin/droid
84
+ homepage: http://usepropeler.com
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.0.3
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: DroidProj
108
+ test_files:
109
+ - spec/app_spec.rb
110
+ - spec/drawable_spec.rb
111
+ - spec/res_spec.rb
112
+ - spec/resources/back.png
113
+ - spec/resources/back@hdpi.png
114
+ - spec/resources/back@ldpi.png
115
+ - spec/runner_spec.rb
116
+ - spec/spec_helper.rb