under-os 1.2.1 → 1.3.0

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