under-os 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f26c97edd3027e97c225827fd8bd869ae1590cc0
4
- data.tar.gz: 517d1b9dbcbb2ed6008a4211ce765705e1c58a65
3
+ metadata.gz: c85e8e24c0882f5dd2129ab806fc38c6af5086b9
4
+ data.tar.gz: 943c82a084c7b39be0c67d9931f6b956e90b5e7b
5
5
  SHA512:
6
- metadata.gz: 6eb0aeb8452c02e6b7777f37b2f4cd4187dcd9e03aad75542bd91350a961c592edfa1c315b8d26075606a9199c1cda707dd54cf8b62a4cb4e0256b19dae73dd1
7
- data.tar.gz: 289fbfefe89706b5abc4e31f97d461a635ead887d28fd360a8463ba4430e0efe7dd08c9f4d5b2c2e524cc37dc2b1c6c281327953a3d84f106425a627ea3508f6
6
+ metadata.gz: b49c68493a565fe87549b70cfb19f33d861ad8d7a164b918a3875485c4b965a11eddf636a26800b72384d7a881acf14ecd24f313445317bf1369d68a434a5ef8
7
+ data.tar.gz: b3b2067131c19751aed7c5e3478b60bae458aaedd59d8bde0cf84e1ab7fde5c5094113566b942e520aa3d01fe203f19b4a3f904459bc7aa9936377bd7f187dba
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- under-os (1.2.0)
4
+ under-os (1.2.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # Under OS [![Build Status](https://travis-ci.org/under-os/under-os.png)](https://travis-ci.org/under-os/under-os) [![Code Climate](https://codeclimate.com/github/under-os/under-os.png)](https://codeclimate.com/github/under-os/under-os)
2
2
 
3
- [UnderOS](http://under-os.com) is an experiment in building a thin web-like wrapper over iOS using rubymotion
3
+ [UnderOS](http://under-os.com) is an experiment in building a thin web-browser like
4
+ envirnonment over iOS using rubymotion
4
5
 
5
- The idea is to use encapsulation instead of monkey patching and build the
6
- entire development platform correctly and from scratch.
6
+ The idea is to create a native mobile apps development environment that will be
7
+ using concepts familiar to all web-developers, like HTML, CSS, jQuery style
8
+ events handling, etc.
7
9
 
8
10
  The result should be a _webbish_ infrastructure that uses ruby instead
9
11
  of JavaScript and compiles into native code in the end.
@@ -18,20 +20,13 @@ That's gonna be legendary!
18
20
  gem install under-os
19
21
  ```
20
22
 
21
- 2) Clone the RubyMotion template in place
22
-
23
- ```
24
- mkdir -p ~/Library/RubyMotion/template/uos
25
- git clone https://github.com/under-os/under-os-template.git ~/Library/RubyMotion/template/uos
26
- ```
27
-
28
- 3) Make a new app using the `uos` template
23
+ 2) Make a new app using the `uos` template
29
24
 
30
25
  ```
31
26
  motion create test --template=uos
32
27
  ```
33
28
 
34
- Now, Run it!
29
+ 3) Run it!
35
30
 
36
31
  ```
37
32
  cd test && rake
@@ -42,7 +37,7 @@ cd test && rake
42
37
 
43
38
  All code in this library is released under the terms of the MIT license
44
39
 
45
- Copyright (C) 2013 Nikolay Nemshilov
40
+ Copyright (C) 2013-2014 Nikolay Nemshilov
46
41
 
47
42
  Permission is hereby granted, free of charge, to any person obtaining a copy
48
43
  of this software and associated documentation files (the "Software"), to deal
data/lib/under-os.rb CHANGED
@@ -1,21 +1,8 @@
1
- # just a gem hook
1
+ require File.dirname(__FILE__) + "/under_os.rb"
2
2
 
3
- Motion::Project::App.instance_eval do
4
- alias :setup_before_under_os :setup
3
+ UnderOs.extend __FILE__ do |app|
4
+ app.resources_dirs << "app/styles/" if File.exists?("app/styles")
5
+ app.resources_dirs << "app/layouts/" if File.exists?("app/layouts")
5
6
 
6
- def setup(*args, &block)
7
- config.setup_blocks << proc do |app|
8
- Dir.glob(File.dirname(__FILE__) + '/**/*.rb').reverse.each do |file|
9
- app.files.insert(0, file) if file != __FILE__
10
- end
11
-
12
- app.resources_dirs << File.dirname(__FILE__) + "/assets"
13
- app.resources_dirs << "app/styles/" if File.exists?("app/styles")
14
- app.resources_dirs << "app/layouts/" if File.exists?("app/layouts")
15
-
16
- app.fonts << "fontawesome-webfont.ttf"
17
- end
18
-
19
- setup_before_under_os *args, &block
20
- end
7
+ app.fonts << "fontawesome-webfont.ttf"
21
8
  end
@@ -19,19 +19,17 @@ module UnderOs::Events
19
19
  extend self
20
20
 
21
21
  def list(model, event=nil)
22
- @listeners ||= {}
23
- @listeners[model] ||= {}
24
- @listeners[model][event.to_sym] ||= [] if event
22
+ @listeners ||= Hash.new{|h,k| h[k] = Hash.new{|h,k| h[k] = []} }
25
23
  event ? @listeners[model][event.to_sym] : @listeners[model]
26
24
  end
27
25
 
28
26
  def add(model, event, *args, block)
29
- list(model, event.to_sym) << [block, *args]
27
+ list(model, event) << [block, *args]
30
28
  model
31
29
  end
32
30
 
33
31
  def all(model, event)
34
- list(model, event.to_sym)
32
+ list(model, event)
35
33
  end
36
34
 
37
35
  def remove(model, event)
@@ -44,7 +42,9 @@ module UnderOs::Events
44
42
 
45
43
  all(model, event.name).each do |block, method_name, *args|
46
44
  if !block && method_name
47
- block = Proc.new{ __send__(method_name, *args) }
45
+ block = Proc.new{ |e|
46
+ a = method(method_name).arity == 0 ? [] : [e];
47
+ __send__(method_name, *a) }
48
48
  context = model
49
49
  elsif block && method_name # <- considering it's a context reference
50
50
  context = method_name
@@ -15,7 +15,10 @@ class UnderOs::History
15
15
  end
16
16
 
17
17
  def current_page
18
- @_.visibleViewController.wrapper
18
+ controller = @_.topViewController
19
+
20
+ controller.is_a?(UnderOs::Page::UIViewControllerWrap) ?
21
+ controller.wrapper : root_page
19
22
  end
20
23
 
21
24
  def push(page, animated=true)
data/lib/under_os/page.rb CHANGED
@@ -149,5 +149,21 @@ class UnderOs::Page
149
149
  def prefersStatusBarHidden
150
150
  !UnderOs::App.config.status_bar
151
151
  end
152
+
153
+ def touchesBegan(touches, withEvent:event)
154
+ UnderOs::UI::Events::TouchListeners.notify :touchstart, event
155
+ end
156
+
157
+ def touchesMoved(touches, withEvent:event)
158
+ UnderOs::UI::Events::TouchListeners.notify :touchmove, event
159
+ end
160
+
161
+ def touchesEnded(touches, withEvent: event)
162
+ UnderOs::UI::Events::TouchListeners.notify :touchend, event
163
+ end
164
+
165
+ def touchesCancelled(touches, withEvent: event)
166
+ UnderOs::UI::Events::TouchListeners.notify :touchcancel, event
167
+ end
152
168
  end
153
169
  end
@@ -24,13 +24,21 @@ class UnderOs::UI::Navbar
24
24
  !hidden
25
25
  end
26
26
 
27
+ def disable_swipes
28
+ @_.interactivePopGestureRecognizer.enabled = false
29
+ end
30
+
31
+ def enable_swipes
32
+ @_.interactivePopGestureRecognizer.enabled = true
33
+ end
34
+
27
35
  def left_button
28
36
  @left_button
29
37
  end
30
38
 
31
39
  def left_button=(view)
32
40
  @left_button = view
33
- @_.visibleViewController.navigationItem.leftBarButtonItem = to_navigation_item(view)
41
+ @_.topViewController.navigationItem.leftBarButtonItem = to_navigation_item(view)
34
42
  end
35
43
 
36
44
  def right_button
@@ -48,7 +56,7 @@ class UnderOs::UI::Navbar
48
56
  def right_buttons=(views)
49
57
  views = [views] if views.is_a?(Hash)
50
58
  @right_buttons = views
51
- @_.visibleViewController.navigationItem.rightBarButtonItems =
59
+ @_.topViewController.navigationItem.rightBarButtonItems =
52
60
  views.map{|v| to_navigation_item(v)}.flatten.compact.reverse
53
61
  end
54
62
 
@@ -88,11 +88,83 @@ module UnderOs::UI
88
88
  @view.layer.borderWidth = width
89
89
  end
90
90
 
91
+ def boxShadow
92
+ get_layer_shadow @view.layer
93
+ end
94
+
95
+ def boxShadow=(value)
96
+ set_layer_shadow @view.layer, value
97
+ end
98
+
99
+ def textShadow
100
+ get_layer_shadow text_layer
101
+ end
102
+
103
+ def textShadow=(value)
104
+ set_layer_shadow text_layer, value
105
+ end
106
+
91
107
  private
92
108
 
93
109
  def convert_color(color)
94
110
  UnderOs::Color.new(color).ui
95
111
  end
112
+
113
+ def text_layer
114
+ @view.is_a?(UIButton) ? @view.titleLabel : @view.layer
115
+ end
116
+
117
+ def get_layer_shadow(layer)
118
+ [
119
+ layer.shadowOffset.width,
120
+ layer.shadowOffset.height,
121
+ layer.shadowRadius,
122
+ layer.shadowOpacity,
123
+ UnderOs::Color.new(layer.shadowColor).to_hex
124
+ ].compact.join(" ")
125
+ end
126
+
127
+ def set_layer_shadow(layer, value)
128
+ x, y, radius, opacity, color = parse_shadow_params(value)
129
+
130
+ layer.shadowOffset = CGSizeMake(x, y) if x && y
131
+ layer.shadowColor = color.CGColor if color
132
+ layer.shadowRadius = radius if radius
133
+ layer.shadowOpacity = opacity if opacity
134
+ layer.shadowPath = UIBezierPath.bezierPathWithRect(@view.layer.bounds).CGPath
135
+ end
136
+
137
+ def parse_shadow_params(string)
138
+ x, y, radius, opacity, color = string.strip.split
139
+
140
+ x = x.gsub /px$/, ''
141
+ y = y.gsub /px$/, ''
142
+ radius = radius.gsub /px$/, '' if radius
143
+ opacity = opacity.gsub /px$/, '' if opacity
144
+
145
+ if ! color
146
+ if opacity
147
+ unless opacity =~ /^[\d\.]+$/
148
+ color = opacity
149
+ opacity = nil
150
+ end
151
+ elsif radius
152
+ unless radius =~ /^[\d\.]+$/
153
+ color = radius
154
+ radius = nil
155
+ end
156
+ end
157
+ end
158
+
159
+ x = x.to_f if x
160
+ y = y.to_f if y
161
+
162
+ radius = radius.to_f if radius
163
+ opacity = opacity.to_f if opacity
164
+ color = convert_color(color) if color
165
+
166
+ [x, y, radius, opacity, color]
167
+ end
96
168
  end
97
169
  end
98
170
  end
@@ -6,11 +6,10 @@ module UnderOs::UI::Events
6
6
  def on(event, *args, &block)
7
7
  return event.map{|e,b| self.on(e,&b)}[0] || self if event.is_a?(Hash)
8
8
 
9
- event, recognizer = find_recognizer_from(event)
10
-
11
- @_.addGestureRecognizer(recognizer.alloc.initWithTarget(self, action: :emit)) if recognizer
12
9
  @_.userInteractionEnabled = true
13
10
 
11
+ event = add_ui_event_listener(event)
12
+
14
13
  UnderOs::Events::Listeners.add(self, event, *args, block)
15
14
  end
16
15
 
@@ -20,6 +19,7 @@ module UnderOs::UI::Events
20
19
 
21
20
  def emit(*event)
22
21
  if event.is_a?(UIGestureRecognizer)
22
+ event, r = find_recognizer_from(event.class)
23
23
  event = Event.new(self, event)
24
24
  else
25
25
  event = Event.new(self, *event)
@@ -32,8 +32,105 @@ module UnderOs::UI::Events
32
32
  on hash
33
33
  end
34
34
 
35
+ class TouchListeners
36
+ def self.listeners
37
+ @listeners ||= Hash.new{ |h,k| h[k] = [] }
38
+ end
39
+
40
+ def self.add(eventname, view)
41
+ listeners[eventname] << view
42
+ end
43
+
44
+ def self.notify(eventname, event)
45
+ listeners[eventname].each do |view|
46
+ if eventname == :touchmove # being nice and throttling the touchmove events
47
+ return if @__working
48
+ @__working = true
49
+ end
50
+
51
+ touches = touches_for_view(view, event)
52
+
53
+ view.emit(eventname, touches: touches) if touches.size > 0
54
+
55
+ @__working = false
56
+ end
57
+ end
58
+
59
+ def self.touches_for_view(view, event)
60
+ frame = view._.frame
61
+ touches = []
62
+
63
+ event.allTouches.each do |touch|
64
+ if point = touch_inside_of(frame, touch)
65
+ touches << Touch.new(view, point)
66
+ end
67
+ end
68
+
69
+ touches
70
+ end
71
+
72
+ def self.touch_inside_of(frame, touch)
73
+ point = touch.locationInView(nil)
74
+ point = nil if point.x < frame.origin.x ||
75
+ point.y < frame.origin.y ||
76
+ point.x > frame.origin.x + frame.size.width ||
77
+ point.y > frame.origin.y + frame.size.height
78
+
79
+ point
80
+ end
81
+
82
+ class Touch
83
+ attr_reader :view, :position
84
+
85
+ def initialize(view, position)
86
+ @view = view
87
+ @position = position
88
+ end
89
+
90
+ def pageX
91
+ position.x
92
+ end
93
+
94
+ def pageY
95
+ position.y
96
+ end
97
+
98
+ def viewX
99
+ @position.x - view._.frame.origin.x
100
+ end
101
+
102
+ def viewY
103
+ @position.y - view._.frame.origin.y
104
+ end
105
+
106
+ def inspect
107
+ "#<Touch x=#{pageX} y=#{pageY}"
108
+ end
109
+ end
110
+ end
111
+
35
112
  private
36
113
 
114
+ def add_ui_event_listener(event)
115
+ event = event.to_sym if event.is_a?(String)
116
+ event = try_add_touch_event_listener(event)
117
+ event, recognizer = find_recognizer_from(event)
118
+
119
+ @_.addGestureRecognizer(recognizer.alloc.initWithTarget(self, action: :emit)) if recognizer
120
+
121
+ event
122
+ end
123
+
124
+ TOUCH_EVENTS = [:touchstart, :touchmove, :touchend, :touchcancel]
125
+
126
+ def try_add_touch_event_listener(event)
127
+ if TOUCH_EVENTS.include?(event)
128
+ UnderOs::UI::Events::TouchListeners.add(event, self)
129
+ end
130
+
131
+ event
132
+ end
133
+
37
134
  RECOGNIZERS = {
38
135
  tap: UITapGestureRecognizer,
39
136
  pinch: UIPinchGestureRecognizer,
@@ -45,8 +142,6 @@ private
45
142
 
46
143
  # tries to figure event name and gesture recognizer
47
144
  def find_recognizer_from(event)
48
- event = event.to_sym if event.is_a?(String)
49
-
50
145
  if event.is_a?(Class) && event < UIGestureRecognizer
51
146
  recognizer = event
52
147
 
@@ -68,7 +163,7 @@ private
68
163
 
69
164
  def initialize(view, event, params={})
70
165
  @target = view
71
- event, r = view.__send__ :find_recognizer_from, event.class if event.is_a?(UIGestureRecognizer)
166
+
72
167
  super event, params
73
168
  end
74
169
  end
data/lib/under_os.rb CHANGED
@@ -1,5 +1,41 @@
1
1
  module UnderOs
2
- VERSION='1.2.1'
2
+ VERSION='1.3.0'
3
+
4
+ #
5
+ # Generic ecosystem extension hook, for plugins and such
6
+ #
7
+ # require('under-os')
8
+ #
9
+ # UnderOs.extend __FILE__ do |app|
10
+ # app.extra_things..
11
+ # end
12
+ #
13
+ def self.extend(__file__, &block)
14
+ UnderOs.setup_callbacks[__file__] = block
15
+ UnderOs.setup_callbacks.size == 1 && Motion::Project::App.instance_eval do
16
+ alias :setup_before_under_os :setup
17
+ def setup(*args, &block)
18
+ config.setup_blocks << proc do |app|
19
+ UnderOs.setup_callbacks.each do |__file__, block|
20
+ Dir.glob(File.dirname(__file__) + '/**/*.rb').reverse.each do |file|
21
+ app.files.insert(0, file) if file != __file__
22
+ end
23
+
24
+ module_assets_folder = File.dirname(__file__) + "/assets"
25
+ app.resources_dirs << module_assets_folder if File.exists?(module_assets_folder)
26
+
27
+ block.call(app) if block
28
+ end
29
+ end
30
+
31
+ setup_before_under_os *args, &block
32
+ end
33
+ end
34
+ end
35
+
36
+ def self.setup_callbacks
37
+ @callbacks ||= {}
38
+ end
3
39
  end
4
40
 
5
41
  UOS = UnderOS = UnderOs
@@ -66,4 +66,36 @@ describe UnderOs::UI::Style::Outlining do
66
66
  end
67
67
  end
68
68
  end
69
+
70
+ describe '#boxShadow' do
71
+ it "recognizes the x, y values" do
72
+ @view.style.boxShadow = "1px 2px"
73
+ @view.style.boxShadow.should == "1.0 2.0 3.0 0.0 #ff0000"
74
+ end
75
+
76
+ it "recognizes the x, y, radius values" do
77
+ @view.style.boxShadow = "-1 -2 4"
78
+ @view.style.boxShadow.should == "-1.0 -2.0 4.0 0.0 #ff0000"
79
+ end
80
+
81
+ it "recognizes the x, y, radius, opacity values" do
82
+ @view.style.boxShadow = "4 5 6 7"
83
+ @view.style.boxShadow.should == "4.0 5.0 6.0 7.0 #ff0000"
84
+ end
85
+
86
+ it "recognizes the x, y, radius, opacity, color values" do
87
+ @view.style.boxShadow = "4 5 6 7 blue"
88
+ @view.style.boxShadow.should == "4.0 5.0 6.0 7.0 #ff0000"
89
+ end
90
+
91
+ it "recognizes the x, y, radius, color values" do
92
+ @view.style.boxShadow = "4 5 6 blue"
93
+ @view.style.boxShadow.should == "4.0 5.0 6.0 0.0 #ff0000"
94
+ end
95
+
96
+ it "recognizes the x, y, color values" do
97
+ @view.style.boxShadow = "4 5 green"
98
+ @view.style.boxShadow.should == "4.0 5.0 3.0 0.0 #ff0000"
99
+ end
100
+ end
69
101
  end
@@ -0,0 +1,87 @@
1
+ class MyView < UnderOs::UI::View
2
+ attr_reader :args
3
+
4
+ def handler_with_event(event)
5
+ @args = [event]
6
+ end
7
+
8
+ def handler_without_event
9
+ @args = []
10
+ end
11
+ end
12
+
13
+ describe UnderOs::UI::Events do
14
+ before do
15
+ @view = UnderOs::UI::View.new
16
+ end
17
+
18
+ describe "#on" do
19
+ before do
20
+ @tapped = false
21
+ @result = @view.on(:tap) { @tapped = true }
22
+
23
+ @view.emit(:tap)
24
+ end
25
+
26
+ it "binds the event listener" do
27
+ @tapped.should == true
28
+ end
29
+
30
+ it "returns the view object itself back" do
31
+ @result.should.be.same_as @view
32
+ end
33
+ end
34
+
35
+ describe "#off" do
36
+ before do
37
+ @tapped = false
38
+ @view.on(:tap) { @tapped = true }
39
+
40
+ @result = @view.off(:tap)
41
+
42
+ @view.emit(:tap)
43
+ end
44
+
45
+ it "un-binds the event listener" do
46
+ @tapped.should == false
47
+ end
48
+
49
+ it "returns the view object itself back" do
50
+ @result.should.be.same_as @view
51
+ end
52
+ end
53
+
54
+ describe "#emit" do
55
+ before do
56
+ @view.on(:tap) { |e| @event = e }
57
+ @view.emit(:tap, custom: 'param')
58
+ end
59
+
60
+ it "emits an UI::Event" do
61
+ @event.class.should == UnderOs::UI::Events::Event
62
+ end
63
+
64
+ it "sets the event target to the view" do
65
+ @event.target.should.be.same_as @view
66
+ end
67
+ end
68
+
69
+ describe "named event handlers" do
70
+ before do
71
+ @view = MyView.new
72
+ end
73
+
74
+ it "allows to bind a method by name with an event listener" do
75
+ @view.on :tap, :handler_with_event
76
+ @view.emit(:tap)
77
+ @view.args.size.should == 1
78
+ @view.args[0].class.should == UnderOs::UI::Events::Event
79
+ end
80
+
81
+ it "allows to bind a method by name without an event argument" do
82
+ @view.on :tap, :handler_without_event
83
+ @view.emit(:tap)
84
+ @view.args.size.should == 0
85
+ end
86
+ end
87
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: under-os
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nikolay Nemshilov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-13 00:00:00.000000000 Z
11
+ date: 2014-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -210,6 +210,7 @@ files:
210
210
  - spec/lib/under_os/ui/switch_spec.rb
211
211
  - spec/lib/under_os/ui/textarea_spec.rb
212
212
  - spec/lib/under_os/ui/utils/commons_spec.rb
213
+ - spec/lib/under_os/ui/utils/events_spec.rb
213
214
  - spec/lib/under_os/ui/utils/manipulation_spec.rb
214
215
  - spec/lib/under_os/ui/utils/styles_spec.rb
215
216
  - spec/lib/under_os/ui/utils/traversing_spec.rb
@@ -233,7 +234,7 @@ licenses:
233
234
  - MIT
234
235
  metadata: {}
235
236
  post_install_message: |2+
236
- = UnderOS 1.2.1 =
237
+ = UnderOS 1.3.0 =
237
238
 
238
239
  To get started run the following:
239
240
 
@@ -309,6 +310,7 @@ test_files:
309
310
  - spec/lib/under_os/ui/switch_spec.rb
310
311
  - spec/lib/under_os/ui/textarea_spec.rb
311
312
  - spec/lib/under_os/ui/utils/commons_spec.rb
313
+ - spec/lib/under_os/ui/utils/events_spec.rb
312
314
  - spec/lib/under_os/ui/utils/manipulation_spec.rb
313
315
  - spec/lib/under_os/ui/utils/styles_spec.rb
314
316
  - spec/lib/under_os/ui/utils/traversing_spec.rb