under-os-ui 1.4.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.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +26 -0
  3. data/lib/assets/fontawesome-webfont.ttf +0 -0
  4. data/lib/assets/under-os.css +115 -0
  5. data/lib/core/kernel.rb +16 -0
  6. data/lib/under-os-ui.rb +6 -0
  7. data/lib/under_os/app.rb +26 -0
  8. data/lib/under_os/config.rb +25 -0
  9. data/lib/under_os/history.rb +53 -0
  10. data/lib/under_os/page.rb +178 -0
  11. data/lib/under_os/page/builder.rb +96 -0
  12. data/lib/under_os/page/layout.rb +43 -0
  13. data/lib/under_os/page/matcher.rb +128 -0
  14. data/lib/under_os/page/stylesheet.rb +67 -0
  15. data/lib/under_os/parser.rb +24 -0
  16. data/lib/under_os/parser/css.rb +37 -0
  17. data/lib/under_os/parser/html.rb +97 -0
  18. data/lib/under_os/ui.rb +3 -0
  19. data/lib/under_os/ui/alert.rb +52 -0
  20. data/lib/under_os/ui/button.rb +42 -0
  21. data/lib/under_os/ui/collection.rb +65 -0
  22. data/lib/under_os/ui/collection/cell.rb +21 -0
  23. data/lib/under_os/ui/collection/delegate.rb +70 -0
  24. data/lib/under_os/ui/collection/item.rb +32 -0
  25. data/lib/under_os/ui/collection/layout.rb +43 -0
  26. data/lib/under_os/ui/collection/styles.rb +15 -0
  27. data/lib/under_os/ui/div.rb +3 -0
  28. data/lib/under_os/ui/form.rb +60 -0
  29. data/lib/under_os/ui/icon.rb +61 -0
  30. data/lib/under_os/ui/icon/awesome.rb +376 -0
  31. data/lib/under_os/ui/icon/engine.rb +9 -0
  32. data/lib/under_os/ui/image.rb +31 -0
  33. data/lib/under_os/ui/input.rb +140 -0
  34. data/lib/under_os/ui/label.rb +21 -0
  35. data/lib/under_os/ui/locker.rb +42 -0
  36. data/lib/under_os/ui/navbar.rb +123 -0
  37. data/lib/under_os/ui/progress.rb +17 -0
  38. data/lib/under_os/ui/scroll.rb +102 -0
  39. data/lib/under_os/ui/select.rb +95 -0
  40. data/lib/under_os/ui/sidebar.rb +45 -0
  41. data/lib/under_os/ui/slider.rb +37 -0
  42. data/lib/under_os/ui/spinner.rb +23 -0
  43. data/lib/under_os/ui/style.rb +21 -0
  44. data/lib/under_os/ui/style/fonts.rb +56 -0
  45. data/lib/under_os/ui/style/margins.rb +164 -0
  46. data/lib/under_os/ui/style/outlining.rb +170 -0
  47. data/lib/under_os/ui/style/positioning.rb +183 -0
  48. data/lib/under_os/ui/switch.rb +26 -0
  49. data/lib/under_os/ui/textarea.rb +19 -0
  50. data/lib/under_os/ui/utils/animation.rb +101 -0
  51. data/lib/under_os/ui/utils/commons.rb +70 -0
  52. data/lib/under_os/ui/utils/dimensions.rb +37 -0
  53. data/lib/under_os/ui/utils/events.rb +210 -0
  54. data/lib/under_os/ui/utils/manipulation.rb +44 -0
  55. data/lib/under_os/ui/utils/position.rb +21 -0
  56. data/lib/under_os/ui/utils/size.rb +21 -0
  57. data/lib/under_os/ui/utils/styles.rb +89 -0
  58. data/lib/under_os/ui/utils/traversing.rb +44 -0
  59. data/lib/under_os/ui/utils/wrap.rb +77 -0
  60. data/lib/under_os/ui/view.rb +31 -0
  61. data/spec/assets/app.css +13 -0
  62. data/spec/assets/test.css +7 -0
  63. data/spec/assets/test.html +3 -0
  64. data/spec/assets/test.png +0 -0
  65. data/spec/assets/test_page.rb +2 -0
  66. data/spec/under_os/page/builder_spec.rb +128 -0
  67. data/spec/under_os/page/layout_spec.rb +18 -0
  68. data/spec/under_os/page/matcher_spec.rb +260 -0
  69. data/spec/under_os/page/stylesheet_spec.rb +83 -0
  70. data/spec/under_os/page_spec.rb +5 -0
  71. data/spec/under_os/parser/css_spec.rb +77 -0
  72. data/spec/under_os/parser/html_spec.rb +152 -0
  73. data/spec/under_os/parser_spec.rb +16 -0
  74. data/spec/under_os/ui/button_spec.rb +50 -0
  75. data/spec/under_os/ui/collection_spec.rb +19 -0
  76. data/spec/under_os/ui/div_spec.rb +24 -0
  77. data/spec/under_os/ui/form_spec.rb +156 -0
  78. data/spec/under_os/ui/icon_spec.rb +57 -0
  79. data/spec/under_os/ui/image_spec.rb +39 -0
  80. data/spec/under_os/ui/input_spec.rb +109 -0
  81. data/spec/under_os/ui/label_spec.rb +22 -0
  82. data/spec/under_os/ui/locker_spec.rb +31 -0
  83. data/spec/under_os/ui/progress_spec.rb +31 -0
  84. data/spec/under_os/ui/scroll_spec.rb +75 -0
  85. data/spec/under_os/ui/select_spec.rb +135 -0
  86. data/spec/under_os/ui/sidebar_spec.rb +35 -0
  87. data/spec/under_os/ui/slider_spec.rb +69 -0
  88. data/spec/under_os/ui/spinner_spec.rb +57 -0
  89. data/spec/under_os/ui/style/fonts_spec.rb +111 -0
  90. data/spec/under_os/ui/style/margins_spec.rb +106 -0
  91. data/spec/under_os/ui/style/outlining_spec.rb +101 -0
  92. data/spec/under_os/ui/style/positioning_spec.rb +69 -0
  93. data/spec/under_os/ui/style_spec.rb +19 -0
  94. data/spec/under_os/ui/switch_spec.rb +60 -0
  95. data/spec/under_os/ui/textarea_spec.rb +34 -0
  96. data/spec/under_os/ui/utils/commons_spec.rb +81 -0
  97. data/spec/under_os/ui/utils/events_spec.rb +87 -0
  98. data/spec/under_os/ui/utils/manipulation_spec.rb +130 -0
  99. data/spec/under_os/ui/utils/styles_spec.rb +140 -0
  100. data/spec/under_os/ui/utils/traversing_spec.rb +124 -0
  101. data/spec/under_os/ui/utils/wrap_spec.rb +69 -0
  102. data/spec/under_os/ui/view_spec.rb +39 -0
  103. data/under-os-ui.gemspec +23 -0
  104. metadata +216 -0
@@ -0,0 +1,44 @@
1
+ #
2
+ # The ui-views manipulation functionality
3
+ #
4
+ module UnderOs::UI::Manipulation
5
+
6
+ def insert(view, position=:end)
7
+ if view.is_a?(Array)
8
+ view.each{|v| insert(v, position)}
9
+ else
10
+ if position == :top
11
+ @_.insertSubview(view._, atIndex: 0)
12
+ else
13
+ @_.addSubview(view._)
14
+ end
15
+ end
16
+
17
+ self
18
+ end
19
+
20
+ def append(*views)
21
+ views.each{|v| insert(v)}
22
+ self
23
+ end
24
+
25
+ def prepend(*views)
26
+ views.each{|v| insert(v, :top) }
27
+ self
28
+ end
29
+
30
+ def insertTo(view, position=nil)
31
+ view.insert(self, position)
32
+ self
33
+ end
34
+
35
+ def remove
36
+ @_.removeFromSuperview
37
+ self
38
+ end
39
+
40
+ def clear
41
+ children.each(&:remove)
42
+ self
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ class UnderOs::UI::Position < UnderOs::Point
2
+ def initialize(view)
3
+ @view = view
4
+ end
5
+
6
+ def x
7
+ @view.style.left
8
+ end
9
+
10
+ def x=(position)
11
+ @view.style.left = position
12
+ end
13
+
14
+ def y
15
+ @view.style.top
16
+ end
17
+
18
+ def y=(position)
19
+ @view.style.top = position
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ class UnderOs::UI::Size < UnderOs::Point
2
+ def initialize(view)
3
+ @view = view
4
+ end
5
+
6
+ def x
7
+ @view.style.width
8
+ end
9
+
10
+ def x=(size)
11
+ @view.style.width = size
12
+ end
13
+
14
+ def y
15
+ @view.style.height
16
+ end
17
+
18
+ def y=(size)
19
+ @view.style.height = size
20
+ end
21
+ end
@@ -0,0 +1,89 @@
1
+ #
2
+ # The styles handling API for UIView
3
+ #
4
+ module UnderOs::UI::Styles
5
+ def style(hash=nil)
6
+ if hash
7
+ self.style = hash
8
+ self
9
+ else
10
+ @_style ||= UnderOs::UI::Style.new(_, tagName.downcase.to_sym)
11
+ end
12
+ end
13
+
14
+ def style=(hash)
15
+ hash.each{ |key, value| style.__send__("#{key}=", value)}
16
+ end
17
+
18
+ def className
19
+ classNames.join(' ')
20
+ end
21
+
22
+ def className=(names)
23
+ self.classNames = names.scan(/([a-z0-9\-_]+)/).map{|e| e[0]}
24
+ end
25
+
26
+ def classNames
27
+ @_class_names ||= []
28
+ end
29
+
30
+ def classNames=(list)
31
+ repaint_if_classes_change do
32
+ @_class_names = list.uniq.map(&:to_s)
33
+ end
34
+ end
35
+
36
+ def hasClass(name)
37
+ classNames.include?(name)
38
+ end
39
+
40
+ def addClass(name)
41
+ repaint_if_classes_change do
42
+ self.classNames += [name]
43
+ end
44
+ end
45
+
46
+ def removeClass(name)
47
+ repaint_if_classes_change do
48
+ self.classNames -= [name]
49
+ end
50
+ end
51
+
52
+ def toggleClass(name)
53
+ if hasClass(name)
54
+ removeClass name
55
+ else
56
+ addClass name
57
+ end
58
+ end
59
+
60
+ def radioClass(name)
61
+ parent.children.each do |view|
62
+ view.removeClass(name) if view != self
63
+ end
64
+
65
+ addClass name
66
+ end
67
+
68
+ def repaint(stylesheet=nil, &block)
69
+ stylesheet ||= page && page.stylesheet
70
+
71
+ if stylesheet
72
+ styles = stylesheet.styles_for(self)
73
+ styles = block.call(styles) if block_given?
74
+ self.style = styles
75
+ children.each{ |view| view.repaint(stylesheet) }
76
+ end
77
+
78
+ self
79
+ end
80
+
81
+ private
82
+
83
+ def repaint_if_classes_change
84
+ prev_list = @_class_names.to_s
85
+ yield if block_given?
86
+ repaint if prev_list != @_class_names.to_s
87
+ self
88
+ end
89
+ end
@@ -0,0 +1,44 @@
1
+ module UnderOs::UI::Traversing
2
+ def first(css_rule)
3
+ find(css_rule)[0]
4
+ end
5
+
6
+ def find(css_rule)
7
+ [].tap do |result|
8
+ children.each do |view|
9
+ result << view if view.matches(css_rule)
10
+ view.find(css_rule).each do |sub|
11
+ result << sub
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ def matches(css_rule)
18
+ UnderOs::Page::StylesMatcher.new(css_rule).match(self)
19
+ end
20
+
21
+ def parent(css_rule=nil)
22
+ if ! css_rule
23
+ UnderOs::UI::View.new(@_.superview) if @_.superview
24
+ else
25
+ parent = self
26
+ while parent.is_a?(UnderOs::UI::View) && (parent = parent.parent)
27
+ return parent if parent.matches(css_rule)
28
+ end
29
+ end
30
+ end
31
+
32
+ def children(css_rule=nil)
33
+ result = @_.subviews.map{|v| UnderOs::UI::View.new(v) if v}.compact
34
+ css_rule ? result.select{|v| v.matches(css_rule)} : result
35
+ end
36
+
37
+ def siblings(css_rule=nil)
38
+ parent ? (parent.children(css_rule) - [self]) : []
39
+ end
40
+
41
+ def empty?
42
+ @_.subviews.empty?
43
+ end
44
+ end
@@ -0,0 +1,77 @@
1
+ #
2
+ # The raw -> abstraction wrapping code
3
+ # for UI::Views
4
+ #
5
+ module UnderOs::UI::Wrap
6
+ INSTANCES_CACHE = {}
7
+ RAW_WRAPS_MAP = {}
8
+ WRAPS_TAGS_MAP = {}
9
+
10
+ def self.included(base)
11
+ base.instance_eval do
12
+ attr_accessor :_
13
+
14
+ def self.wraps(raw_class, options={})
15
+ RAW_WRAPS_MAP[self] = raw_class
16
+ tag(options[:tag]) if options[:tag]
17
+ end
18
+
19
+ def self.tag(name)
20
+ WRAPS_TAGS_MAP[name.to_s] = self
21
+ end
22
+
23
+ def self.new(options={}, *args, &block)
24
+ return INSTANCES_CACHE[options] if INSTANCES_CACHE[options]
25
+
26
+ if options.is_a?(UIView)
27
+ klass = find_wrap_for(options.class)
28
+ view = options; options = args.shift || {}
29
+ else
30
+ klass = self
31
+ view = find_raw_class_for(self).alloc
32
+ if view.class == UICollectionView
33
+ view.initWithFrame([[0, 0], [0, 0]], collectionViewLayout: UICollectionViewFlowLayout.alloc.init)
34
+ else
35
+ view.initWithFrame([[0, 0], [0, 0]])
36
+ end
37
+ end
38
+
39
+ return nil if ! klass
40
+
41
+ klass.alloc.tap do |inst|
42
+ INSTANCES_CACHE[inst._ = view] = inst
43
+ inst.__send__ :initialize, options, *args, &block
44
+ end
45
+ end
46
+
47
+ def self.rewrap(view, *args, &block)
48
+ view = view._ if view.is_a?(UnderOs::UI::View)
49
+
50
+ alloc.tap do |inst|
51
+ INSTANCES_CACHE[inst._ = view] = inst
52
+ inst.__send__ :initialize, *args, &block
53
+ end
54
+ end
55
+
56
+ def self.find_wrap_for(raw_class)
57
+ RAW_WRAPS_MAP.each do |wrap, raw|
58
+ return wrap if raw == raw_class
59
+ end
60
+
61
+ return nil
62
+ end
63
+
64
+ def self.find_raw_class_for(wrap)
65
+ while wrap
66
+ return RAW_WRAPS_MAP[wrap] if RAW_WRAPS_MAP[wrap]
67
+ wrap = wrap.superclass
68
+ end
69
+ end
70
+
71
+ def self.wrap_for(raw_view)
72
+ INSTANCES_CACHE[raw_view]
73
+ end
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,31 @@
1
+ class UnderOs::UI::View
2
+ include UnderOs::UI::Wrap
3
+ include UnderOs::UI::Events
4
+ include UnderOs::UI::Styles
5
+ include UnderOs::UI::Commons
6
+ include UnderOs::UI::Animation
7
+ include UnderOs::UI::Dimensions
8
+ include UnderOs::UI::Traversing
9
+ include UnderOs::UI::Manipulation
10
+
11
+ wraps UIView, tag: 'view'
12
+
13
+ def initialize(options={})
14
+ self.id = options.delete(:id) if options.has_key?(:id)
15
+ self.className = options.delete(:class) if options.has_key?(:class)
16
+ self.style = options.delete(:style) if options.has_key?(:style)
17
+ self.on = options.delete(:on) if options.has_key?(:on)
18
+ self.data = options.delete(:data) if options.has_key?(:data)
19
+ end
20
+
21
+ def inspect
22
+ params = {tag: tagName}
23
+ params[:id] = id if id
24
+ params[:class] = className unless classNames.empty?
25
+ params = params.map do |key, value|
26
+ "#{key}=\"#{value}\""
27
+ end
28
+
29
+ "#<#{self.class.name} #{params.join(" ")}>"
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ page {
2
+ background: white;
3
+ }
4
+
5
+ .test {
6
+ background: blue;
7
+ border-radius: 5;
8
+ color: yellow;
9
+ }
10
+
11
+ view.test {
12
+ border-radius: 10;
13
+ }
@@ -0,0 +1,7 @@
1
+ page {
2
+ background: yellow;
3
+ }
4
+
5
+ .test {
6
+ background: green;
7
+ }
@@ -0,0 +1,3 @@
1
+ <page title="Hello World">
2
+ <button id="hello">Say Hello</button>
3
+ </page>
Binary file
@@ -0,0 +1,2 @@
1
+ class TestPage < UnderOs::Page
2
+ end
@@ -0,0 +1,128 @@
1
+ describe UnderOs::Page::Builder do
2
+ def build(html)
3
+ UnderOs::Page::Builder.views_from(html)
4
+ end
5
+
6
+ describe 'generic build' do
7
+ before do
8
+ @result = build("<view id='my-view'></view>")
9
+ end
10
+
11
+ it "should return an array" do
12
+ @result.class.should == Array
13
+ end
14
+
15
+ it "should build just one item" do
16
+ @result.size.should == 1
17
+ end
18
+
19
+ it "should build an UnderOs::UI::View instance" do
20
+ @result[0].class.should == UnderOs::UI::View
21
+ end
22
+
23
+ it "should assign the element properties" do
24
+ @result[0].id.should == 'my-view'
25
+ end
26
+ end
27
+
28
+ describe 'types building' do
29
+ it "should build buttons" do
30
+ button = build(%Q{<button class="my-button">Some text</button>})[0]
31
+ button.class.should == UnderOs::UI::Button
32
+ button.classNames.should == ['my-button']
33
+ button.text.should == 'Some text'
34
+ end
35
+
36
+ it "should build labels" do
37
+ label = build(%Q{<label>The Text</label>})[0]
38
+ label.class.should == UnderOs::UI::Label
39
+ label.text.should == 'The Text'
40
+ end
41
+
42
+ it "should build images" do
43
+ image = build(%Q{<img src="test.png">})[0]
44
+ image.class.should == UnderOs::UI::Image
45
+ image.src.class.should == UIImage
46
+ end
47
+
48
+ it "should build icons" do
49
+ icon = build(%Q{<icon type="ok" />})[0]
50
+ icon.class.should == UnderOs::UI::Icon
51
+ icon.type.should == 'ok'
52
+ end
53
+ end
54
+
55
+ describe 'nested build' do
56
+ before do
57
+ @result = build(%Q{
58
+ <page id="level1">
59
+ <view id="level2">
60
+ <label>A</label>
61
+ <button>B</button>
62
+ </view>
63
+ </page>
64
+ })[0]
65
+ end
66
+
67
+ it "should still assign the top level element attributes" do
68
+ @result.id.should == 'level1'
69
+ end
70
+
71
+ it "should build the second level elements" do
72
+ level2 = @result.children
73
+ level2.size.should == 1
74
+ level2[0].id.should == 'level2'
75
+ end
76
+
77
+ it "should build the third level of the elements" do
78
+ level3 = @result.children[0].children
79
+ level3.size.should == 2
80
+ level3.map(&:class).should == [UnderOs::UI::Label, UnderOs::UI::Button]
81
+ level3.map(&:text).should == ['A', 'B']
82
+ end
83
+ end
84
+
85
+ describe 'selectboxes build' do
86
+ before do
87
+ @result = build(%Q{
88
+ <select>
89
+ <option value="1">One</option>
90
+ <option value="2">Two</option>
91
+ <option>Three</option>
92
+ </select>
93
+ })[0]
94
+ end
95
+
96
+ it "should allow to build a select box" do
97
+ @result.class.should == UnderOs::UI::Select
98
+ end
99
+
100
+ it "should recognize options" do
101
+ @result.options.should == {
102
+ '1' => 'One',
103
+ '2' => 'Two',
104
+ 'Three' => 'Three'
105
+ }
106
+ end
107
+
108
+ it "should allow to build multi-select boxes" do
109
+ select = build(%Q{
110
+ <select>
111
+ <optgroup>
112
+ <option value="1">One</option>
113
+ </optgroup>
114
+ <optgroup>
115
+ <option value="2">Two</option>
116
+ </optgroup>
117
+ <optgroup>
118
+ <option value="3">Three</option>
119
+ </optgroup>
120
+ </select>
121
+ })[0]
122
+
123
+ select.optgroups.should == [
124
+ {'1' => 'One'}, {'2' => 'Two'}, {'3' => 'Three'}
125
+ ]
126
+ end
127
+ end
128
+ end