under-os-core 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +26 -0
- data/lib/core/json.rb +19 -0
- data/lib/core/numeric.rb +23 -0
- data/lib/core/object.rb +5 -0
- data/lib/core/string.rb +72 -0
- data/lib/under-os-core.rb +40 -0
- data/lib/under_os.rb +5 -0
- data/lib/under_os/app.rb +29 -0
- data/lib/under_os/color.rb +184 -0
- data/lib/under_os/config.rb +10 -0
- data/lib/under_os/delegate.rb +10 -0
- data/lib/under_os/events.rb +85 -0
- data/lib/under_os/file.rb +110 -0
- data/lib/under_os/point.rb +50 -0
- data/lib/under_os/screen.rb +9 -0
- data/lib/under_os/timer.rb +65 -0
- data/spec/core/json_spec.rb +32 -0
- data/spec/core/numeric_spec.rb +37 -0
- data/spec/core/string_spec.rb +101 -0
- data/spec/under_os/color_spec.rb +133 -0
- data/spec/under_os/events_spec.rb +71 -0
- data/spec/under_os/file_spec.rb +98 -0
- data/spec/under_os/point_spec.rb +156 -0
- data/spec/under_os/screen_spec.rb +11 -0
- data/spec/under_os/timer_spec.rb +93 -0
- data/under-os-core.gemspec +20 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9c59302d4cbaf3130505f71c3c9a59b5e2e0390b
|
4
|
+
data.tar.gz: 11350ff86197f7167fe586fe081629cab65a8441
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6f2f84f2c4440e64e0a74d7dd62dcbde110951c1fbb1a7019f1fb3abf4588d8f5bfc0beacc49ddf7a658620e6c2ed12bf215542162e999429ced68d86c2fb6a0
|
7
|
+
data.tar.gz: 43aa63ab2c0e44234e58cb7c879c1d89bf570028bd54c02c4a8abe2f7dde83dfde24869084cb8ae81af81751b133d0ed0c86740ad870ef76160f4c95ca211a50
|
data/README.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# UnderOs Core
|
2
|
+
|
3
|
+
This is the core part of the [UnderOs](http://under-os.com) project
|
4
|
+
|
5
|
+
## Copyright & License
|
6
|
+
|
7
|
+
All code in this library is released under the terms of the MIT license
|
8
|
+
|
9
|
+
Copyright (C) 2013-2014 Nikolay Nemshilov
|
10
|
+
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
13
|
+
in the Software without restriction, including without limitation the rights
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
15
|
+
of the Software, and to permit persons to whom the Software is furnished to do so,
|
16
|
+
subject to the following conditions:
|
17
|
+
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
19
|
+
copies or substantial portions of the Software.
|
20
|
+
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
22
|
+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
23
|
+
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
24
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
25
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
26
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/core/json.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class JSON
|
2
|
+
class Malformed < StandardError ; end
|
3
|
+
|
4
|
+
def self.parse(string, encoding=nil)
|
5
|
+
error = Pointer.new(:object)
|
6
|
+
data = NSJSONSerialization.JSONObjectWithData string.to_data(encoding), options:0, error:error
|
7
|
+
|
8
|
+
if error[0]
|
9
|
+
raise Malformed
|
10
|
+
else
|
11
|
+
data
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.generate(object, pretty=false)
|
16
|
+
options = pretty ? NSJSONWritingPrettyPrinted : 0
|
17
|
+
NSJSONSerialization.dataWithJSONObject(object, options:options, error:nil).to_s
|
18
|
+
end
|
19
|
+
end
|
data/lib/core/numeric.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
class Numeric
|
2
|
+
def milliseconds
|
3
|
+
UnderOs::Timer::Duration.new(self.to_f / 1000)
|
4
|
+
end
|
5
|
+
|
6
|
+
alias :ms :milliseconds
|
7
|
+
|
8
|
+
def seconds
|
9
|
+
UnderOs::Timer::Duration.new(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def minutes
|
13
|
+
UnderOs::Timer::Duration.new(self * 60)
|
14
|
+
end
|
15
|
+
|
16
|
+
def hours
|
17
|
+
UnderOs::Timer::Duration.new(self * 3600)
|
18
|
+
end
|
19
|
+
|
20
|
+
def days
|
21
|
+
UnderOs::Timer::Duration.new(self * 86400)
|
22
|
+
end
|
23
|
+
end
|
data/lib/core/object.rb
ADDED
data/lib/core/string.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
class String
|
2
|
+
def underscore
|
3
|
+
gsub(/([a-z\d])([A-Z]+)/, '\1_\2').gsub('-', '_').downcase
|
4
|
+
end
|
5
|
+
|
6
|
+
def camelize
|
7
|
+
gsub(/(\-|_)+([a-z])?/){|m| $2 ? $2.upcase : ''}
|
8
|
+
end
|
9
|
+
|
10
|
+
def dasherize
|
11
|
+
underscore.gsub('_', '-')
|
12
|
+
end
|
13
|
+
|
14
|
+
def capitalize
|
15
|
+
self[0].upcase + slice(1, size)
|
16
|
+
end
|
17
|
+
|
18
|
+
def starts_with?(substr)
|
19
|
+
index(substr) == 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def ends_with?(substr)
|
23
|
+
rindex(substr) == size - substr.size
|
24
|
+
end
|
25
|
+
|
26
|
+
def blank?
|
27
|
+
self !~ /[^[:space:]]/
|
28
|
+
end
|
29
|
+
|
30
|
+
def constantize
|
31
|
+
names = self.split('::')
|
32
|
+
names.shift if names.empty? || names.first.empty?
|
33
|
+
|
34
|
+
constant = Object
|
35
|
+
names.each do |name|
|
36
|
+
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
37
|
+
end
|
38
|
+
constant
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_data(encoding=nil)
|
42
|
+
dataUsingEncoding ENCODINGS[encoding] || NSUTF8StringEncoding
|
43
|
+
end
|
44
|
+
|
45
|
+
ENCODINGS = {
|
46
|
+
'utf-8' => NSUTF8StringEncoding,
|
47
|
+
'utf-16' => NSUTF16StringEncoding,
|
48
|
+
'utf-32' => NSUTF32StringEncoding,
|
49
|
+
'ascii' => NSASCIIStringEncoding,
|
50
|
+
'latin1' => NSISOLatin1StringEncoding,
|
51
|
+
'latin2' => NSISOLatin2StringEncoding,
|
52
|
+
'cp1250' => NSWindowsCP1250StringEncoding,
|
53
|
+
'cp1251' => NSWindowsCP1251StringEncoding,
|
54
|
+
'cp1252' => NSWindowsCP1252StringEncoding,
|
55
|
+
'cp1253' => NSWindowsCP1253StringEncoding,
|
56
|
+
'cp1254' => NSWindowsCP1254StringEncoding,
|
57
|
+
|
58
|
+
|
59
|
+
# NSNEXTSTEPStringEncoding = 2,
|
60
|
+
# NSJapaneseEUCStringEncoding = 3,
|
61
|
+
# NSSymbolStringEncoding = 6,
|
62
|
+
# NSNonLossyASCIIStringEncoding = 7,
|
63
|
+
# NSShiftJISStringEncoding = 8,
|
64
|
+
# NSISO2022JPStringEncoding = 21,
|
65
|
+
# NSMacOSRomanStringEncoding = 30,
|
66
|
+
# NSUTF16BigEndianStringEncoding = 0x90000100,
|
67
|
+
# NSUTF16LittleEndianStringEncoding = 0x94000100,
|
68
|
+
# NSUTF32BigEndianStringEncoding = 0x98000100,
|
69
|
+
# NSUTF32LittleEndianStringEncoding = 0x9c000100,
|
70
|
+
# NSProprietaryStringEncoding = 65536
|
71
|
+
}
|
72
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "under_os"
|
2
|
+
|
3
|
+
UnderOs.instance_eval do
|
4
|
+
#
|
5
|
+
# Generic ecosystem extension hook, for plugins and such
|
6
|
+
#
|
7
|
+
# UnderOs.extend __FILE__ do |app|
|
8
|
+
# app.extra_things..
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
def self.extend(__file__, &block)
|
12
|
+
UnderOs.setup_callbacks[__file__] = block
|
13
|
+
UnderOs.setup_callbacks.size == 1 && Motion::Project::App.instance_eval do
|
14
|
+
alias :setup_before_under_os :setup
|
15
|
+
def setup(*args, &block)
|
16
|
+
config.setup_blocks << proc do |app|
|
17
|
+
UnderOs.setup_callbacks.each do |__file__, block|
|
18
|
+
Dir.glob(File.dirname(__file__) + '/**/*.rb').sort.each do |file|
|
19
|
+
position = app.files.index {|i| i.slice(0, 2) == "./" }
|
20
|
+
app.files.insert(position, file) if file != __file__
|
21
|
+
end
|
22
|
+
|
23
|
+
module_assets_folder = File.dirname(__file__) + "/assets"
|
24
|
+
app.resources_dirs << module_assets_folder if File.exists?(module_assets_folder)
|
25
|
+
|
26
|
+
block.call(app) if block
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
setup_before_under_os *args, &block
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.setup_callbacks
|
36
|
+
@callbacks ||= {}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
UnderOs.extend __FILE__
|
data/lib/under_os.rb
ADDED
data/lib/under_os/app.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
class UnderOs::App
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def start(&block)
|
6
|
+
@start_block = block
|
7
|
+
end
|
8
|
+
|
9
|
+
def setup(ios_app, options)
|
10
|
+
instance_exec self, &@start_block
|
11
|
+
|
12
|
+
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
13
|
+
@window.rootViewController = root_controller
|
14
|
+
@window.makeKeyAndVisible
|
15
|
+
end
|
16
|
+
|
17
|
+
def config
|
18
|
+
@config ||= UnderOs::Config.new(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def root_controller
|
24
|
+
# just a fallback, supposed to be replaced with the real thing in a submodule
|
25
|
+
UIViewController.alloc.initWithNibName(nil, bundle: nil)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
class UnderOs::Color
|
2
|
+
attr_accessor :ui
|
3
|
+
|
4
|
+
CACHE = {}
|
5
|
+
|
6
|
+
def self.new(*args)
|
7
|
+
color = Converter.ui_color_from(*args)
|
8
|
+
CACHE[color] ||= super(color)
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(ui_color)
|
12
|
+
@ui = ui_color
|
13
|
+
end
|
14
|
+
|
15
|
+
def cg
|
16
|
+
@ui.CGColor
|
17
|
+
end
|
18
|
+
|
19
|
+
def ci
|
20
|
+
@ui.CIColor
|
21
|
+
end
|
22
|
+
|
23
|
+
def invert
|
24
|
+
self.class.new to_rgba.tap do |rgba|
|
25
|
+
rgba[0] = 255 - rgba[0]
|
26
|
+
rgba[1] = 255 - rgba[1]
|
27
|
+
rgba[2] = 255 - rgba[2]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_rgba
|
32
|
+
r = Pointer.new(:float)
|
33
|
+
g = Pointer.new(:float)
|
34
|
+
b = Pointer.new(:float)
|
35
|
+
a = Pointer.new(:float)
|
36
|
+
|
37
|
+
@ui.getRed(r, green:g, blue:b, alpha:a)
|
38
|
+
|
39
|
+
r = (255 * r[0]).round
|
40
|
+
g = (255 * g[0]).round
|
41
|
+
b = (255 * b[0]).round
|
42
|
+
|
43
|
+
[r,g,b,a[0]]
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_rgb
|
47
|
+
to_rgba.slice(0, 3)
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_hex
|
51
|
+
r, g, b = to_rgb
|
52
|
+
int = (r << 16) + (g << 8) + b
|
53
|
+
'#' + int.to_s(16).rjust(6, '0')
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
to_hex
|
58
|
+
end
|
59
|
+
|
60
|
+
def ==(color)
|
61
|
+
color = if color.is_a?(self.class)
|
62
|
+
color
|
63
|
+
else
|
64
|
+
color = [color] if ! color.is_a?(Array)
|
65
|
+
self.class.new(*color)
|
66
|
+
end
|
67
|
+
|
68
|
+
to_s == color.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
module Converter
|
72
|
+
extend self
|
73
|
+
|
74
|
+
def ui_color_from(*args)
|
75
|
+
origin = args.size == 1 ? args[0] : args
|
76
|
+
|
77
|
+
if origin.is_a?(UIColor) then origin
|
78
|
+
elsif origin.is_a?(Array) then color_from_array(*origin)
|
79
|
+
elsif origin.is_a?(String) then color_from_string(origin)
|
80
|
+
elsif origin.is_a?(Symbol) then color_from_string(origin.to_s)
|
81
|
+
elsif origin.is_a?(Float) then color_from_param(origin)
|
82
|
+
elsif origin.is_a?(Integer) then color_from_param(origin / 100.0)
|
83
|
+
else UIColor.redColor # fallback
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def color_from_array(r,g,b,a=1.0)
|
88
|
+
r = r / 255.0 if r.is_a?(Integer) || r > 1.0
|
89
|
+
g = g / 255.0 if g.is_a?(Integer) || g > 1.0
|
90
|
+
b = b / 255.0 if b.is_a?(Integer) || b > 1.0
|
91
|
+
|
92
|
+
UIColor.colorWithRed(r, green: g, blue: b, alpha: a)
|
93
|
+
end
|
94
|
+
|
95
|
+
def color_from_string(name)
|
96
|
+
name = name.downcase.strip
|
97
|
+
name = ALIASES[name] || name
|
98
|
+
|
99
|
+
return UIColor.send("#{name}Color") if IOS_COLORS.include?(name)
|
100
|
+
|
101
|
+
name = HTML_COLORS[name] || name
|
102
|
+
name = "#" + name[1]*2 + name[2]*2 + name[3]*2 if name =~ /^#[abcdef0-9]{3}$/
|
103
|
+
|
104
|
+
r, g, b, a = color_2_rgba(name)
|
105
|
+
|
106
|
+
color_from_array(r, g, b, a || 1.0)
|
107
|
+
end
|
108
|
+
|
109
|
+
def color_2_rgba(color)
|
110
|
+
if color =~ /^#[abcdef0-9]{6}$/
|
111
|
+
hex_2_rgb(color)
|
112
|
+
elsif m = color.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*)\s*\)$/)
|
113
|
+
[m[1].to_i, m[2].to_i, m[3].to_i]
|
114
|
+
elsif m = color.match(/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*)\s*,\s*([\d\.]+)\s*\)$/)
|
115
|
+
[m[1].to_i, m[2].to_i, m[3].to_i, m[4].to_f]
|
116
|
+
else
|
117
|
+
raise "Malformed color spec: #{color.inspect}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def color_from_param(param) # 0.0..1.0
|
122
|
+
color_from_array *param_2_rgb(param)
|
123
|
+
end
|
124
|
+
|
125
|
+
def hex_2_rgb(hex)
|
126
|
+
int = hex[1..-1].to_i(16)
|
127
|
+
|
128
|
+
r = (int & 0xFF0000) >> 16
|
129
|
+
g = (int & 0xFF00) >> 8
|
130
|
+
b = (int & 0xFF)
|
131
|
+
|
132
|
+
[r, g, b]
|
133
|
+
end
|
134
|
+
|
135
|
+
def param_2_rgb(a) # 0.0..1.0
|
136
|
+
x = 1 / 6.0
|
137
|
+
s = a % x / x
|
138
|
+
r = 1 - s
|
139
|
+
|
140
|
+
if a < x then [1.0, s, 0.0]
|
141
|
+
elsif a < x * 2 then [r, 1.0, 0.0]
|
142
|
+
elsif a < x * 3 then [0.0, 1.0, s]
|
143
|
+
elsif a < x * 4 then [0.0, r, 1.0]
|
144
|
+
elsif a < x * 5 then [s, 0.0, 1.0]
|
145
|
+
else [1.0, 0.0, r]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
ALIASES = {
|
150
|
+
'transparent' => 'clear',
|
151
|
+
'darkgray' => 'darkGray',
|
152
|
+
'lightgray' => 'lightGray'
|
153
|
+
}
|
154
|
+
|
155
|
+
IOS_COLORS = %w[
|
156
|
+
black
|
157
|
+
darkGray
|
158
|
+
lightGray
|
159
|
+
white
|
160
|
+
gray
|
161
|
+
red
|
162
|
+
green
|
163
|
+
blue
|
164
|
+
cyan
|
165
|
+
yellow
|
166
|
+
magenta
|
167
|
+
orange
|
168
|
+
purple
|
169
|
+
brown
|
170
|
+
clear
|
171
|
+
].freeze
|
172
|
+
|
173
|
+
HTML_COLORS = {
|
174
|
+
maroon: '#800000',
|
175
|
+
olive: '#808000',
|
176
|
+
fuchsia: '#ff00ff',
|
177
|
+
lime: '#00ff00',
|
178
|
+
navy: '#000080',
|
179
|
+
aqua: '#00ffff',
|
180
|
+
teal: '#008080',
|
181
|
+
silver: '#c0c0c0',
|
182
|
+
}.freeze
|
183
|
+
end
|
184
|
+
end
|