under-os-ui 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/assets/fontawesome-webfont.ttf +0 -0
- data/lib/assets/under-os.css +115 -0
- data/lib/core/kernel.rb +16 -0
- data/lib/under-os-ui.rb +6 -0
- data/lib/under_os/app.rb +26 -0
- data/lib/under_os/config.rb +25 -0
- data/lib/under_os/history.rb +53 -0
- data/lib/under_os/page.rb +178 -0
- data/lib/under_os/page/builder.rb +96 -0
- data/lib/under_os/page/layout.rb +43 -0
- data/lib/under_os/page/matcher.rb +128 -0
- data/lib/under_os/page/stylesheet.rb +67 -0
- data/lib/under_os/parser.rb +24 -0
- data/lib/under_os/parser/css.rb +37 -0
- data/lib/under_os/parser/html.rb +97 -0
- data/lib/under_os/ui.rb +3 -0
- data/lib/under_os/ui/alert.rb +52 -0
- data/lib/under_os/ui/button.rb +42 -0
- data/lib/under_os/ui/collection.rb +65 -0
- data/lib/under_os/ui/collection/cell.rb +21 -0
- data/lib/under_os/ui/collection/delegate.rb +70 -0
- data/lib/under_os/ui/collection/item.rb +32 -0
- data/lib/under_os/ui/collection/layout.rb +43 -0
- data/lib/under_os/ui/collection/styles.rb +15 -0
- data/lib/under_os/ui/div.rb +3 -0
- data/lib/under_os/ui/form.rb +60 -0
- data/lib/under_os/ui/icon.rb +61 -0
- data/lib/under_os/ui/icon/awesome.rb +376 -0
- data/lib/under_os/ui/icon/engine.rb +9 -0
- data/lib/under_os/ui/image.rb +31 -0
- data/lib/under_os/ui/input.rb +140 -0
- data/lib/under_os/ui/label.rb +21 -0
- data/lib/under_os/ui/locker.rb +42 -0
- data/lib/under_os/ui/navbar.rb +123 -0
- data/lib/under_os/ui/progress.rb +17 -0
- data/lib/under_os/ui/scroll.rb +102 -0
- data/lib/under_os/ui/select.rb +95 -0
- data/lib/under_os/ui/sidebar.rb +45 -0
- data/lib/under_os/ui/slider.rb +37 -0
- data/lib/under_os/ui/spinner.rb +23 -0
- data/lib/under_os/ui/style.rb +21 -0
- data/lib/under_os/ui/style/fonts.rb +56 -0
- data/lib/under_os/ui/style/margins.rb +164 -0
- data/lib/under_os/ui/style/outlining.rb +170 -0
- data/lib/under_os/ui/style/positioning.rb +183 -0
- data/lib/under_os/ui/switch.rb +26 -0
- data/lib/under_os/ui/textarea.rb +19 -0
- data/lib/under_os/ui/utils/animation.rb +101 -0
- data/lib/under_os/ui/utils/commons.rb +70 -0
- data/lib/under_os/ui/utils/dimensions.rb +37 -0
- data/lib/under_os/ui/utils/events.rb +210 -0
- data/lib/under_os/ui/utils/manipulation.rb +44 -0
- data/lib/under_os/ui/utils/position.rb +21 -0
- data/lib/under_os/ui/utils/size.rb +21 -0
- data/lib/under_os/ui/utils/styles.rb +89 -0
- data/lib/under_os/ui/utils/traversing.rb +44 -0
- data/lib/under_os/ui/utils/wrap.rb +77 -0
- data/lib/under_os/ui/view.rb +31 -0
- data/spec/assets/app.css +13 -0
- data/spec/assets/test.css +7 -0
- data/spec/assets/test.html +3 -0
- data/spec/assets/test.png +0 -0
- data/spec/assets/test_page.rb +2 -0
- data/spec/under_os/page/builder_spec.rb +128 -0
- data/spec/under_os/page/layout_spec.rb +18 -0
- data/spec/under_os/page/matcher_spec.rb +260 -0
- data/spec/under_os/page/stylesheet_spec.rb +83 -0
- data/spec/under_os/page_spec.rb +5 -0
- data/spec/under_os/parser/css_spec.rb +77 -0
- data/spec/under_os/parser/html_spec.rb +152 -0
- data/spec/under_os/parser_spec.rb +16 -0
- data/spec/under_os/ui/button_spec.rb +50 -0
- data/spec/under_os/ui/collection_spec.rb +19 -0
- data/spec/under_os/ui/div_spec.rb +24 -0
- data/spec/under_os/ui/form_spec.rb +156 -0
- data/spec/under_os/ui/icon_spec.rb +57 -0
- data/spec/under_os/ui/image_spec.rb +39 -0
- data/spec/under_os/ui/input_spec.rb +109 -0
- data/spec/under_os/ui/label_spec.rb +22 -0
- data/spec/under_os/ui/locker_spec.rb +31 -0
- data/spec/under_os/ui/progress_spec.rb +31 -0
- data/spec/under_os/ui/scroll_spec.rb +75 -0
- data/spec/under_os/ui/select_spec.rb +135 -0
- data/spec/under_os/ui/sidebar_spec.rb +35 -0
- data/spec/under_os/ui/slider_spec.rb +69 -0
- data/spec/under_os/ui/spinner_spec.rb +57 -0
- data/spec/under_os/ui/style/fonts_spec.rb +111 -0
- data/spec/under_os/ui/style/margins_spec.rb +106 -0
- data/spec/under_os/ui/style/outlining_spec.rb +101 -0
- data/spec/under_os/ui/style/positioning_spec.rb +69 -0
- data/spec/under_os/ui/style_spec.rb +19 -0
- data/spec/under_os/ui/switch_spec.rb +60 -0
- data/spec/under_os/ui/textarea_spec.rb +34 -0
- data/spec/under_os/ui/utils/commons_spec.rb +81 -0
- data/spec/under_os/ui/utils/events_spec.rb +87 -0
- data/spec/under_os/ui/utils/manipulation_spec.rb +130 -0
- data/spec/under_os/ui/utils/styles_spec.rb +140 -0
- data/spec/under_os/ui/utils/traversing_spec.rb +124 -0
- data/spec/under_os/ui/utils/wrap_spec.rb +69 -0
- data/spec/under_os/ui/view_spec.rb +39 -0
- data/under-os-ui.gemspec +23 -0
- metadata +216 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
class UnderOs::UI::Label < UnderOs::UI::View
|
2
|
+
wraps UILabel, tag: 'label'
|
3
|
+
|
4
|
+
def initialize(options={})
|
5
|
+
super
|
6
|
+
|
7
|
+
self.text = options.delete(:text) || ''
|
8
|
+
@_.sizeToFit
|
9
|
+
|
10
|
+
@_.numberOfLines = 1;
|
11
|
+
@_.adjustsFontSizeToFitWidth = true;
|
12
|
+
end
|
13
|
+
|
14
|
+
def text
|
15
|
+
@_.text
|
16
|
+
end
|
17
|
+
|
18
|
+
def text=(text)
|
19
|
+
@_.text = text
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class UnderOs::UI::Locker < UnderOs::UI::View
|
2
|
+
wraps UIView, tag: :locker
|
3
|
+
|
4
|
+
attr_reader :label, :spinner
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
super options
|
8
|
+
|
9
|
+
@dialog = UnderOs::UI::View.new(class: 'locker-dialog')
|
10
|
+
@spinner = UnderOs::UI::Spinner.new
|
11
|
+
@label = UnderOs::UI::Label.new(text: options[:text] || '')
|
12
|
+
|
13
|
+
append @dialog.append(@spinner, @label)
|
14
|
+
|
15
|
+
addClass 'with-label' if options[:text]
|
16
|
+
end
|
17
|
+
|
18
|
+
def show
|
19
|
+
insertTo(UnderOs::App.history.current_page.view) if ! parent
|
20
|
+
repaint
|
21
|
+
end
|
22
|
+
|
23
|
+
def hide
|
24
|
+
remove
|
25
|
+
end
|
26
|
+
|
27
|
+
def text
|
28
|
+
@label.text
|
29
|
+
end
|
30
|
+
|
31
|
+
def text=(text)
|
32
|
+
@label.text = text
|
33
|
+
end
|
34
|
+
|
35
|
+
def show_for(&block)
|
36
|
+
show
|
37
|
+
1.ms.later do
|
38
|
+
block.call
|
39
|
+
1.ms.later { hide }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
class UnderOs::UI::Navbar
|
2
|
+
attr_reader :_
|
3
|
+
|
4
|
+
def initialize(ui_navigation_controller)
|
5
|
+
@_ = ui_navigation_controller
|
6
|
+
end
|
7
|
+
|
8
|
+
def repaint(stylesheet)
|
9
|
+
end
|
10
|
+
|
11
|
+
def hide(animated=true)
|
12
|
+
@_.setNavigationBarHidden(true, animated:animated)
|
13
|
+
end
|
14
|
+
|
15
|
+
def show(animated=true)
|
16
|
+
@_.setNavigationBarHidden(false, animated:animated)
|
17
|
+
end
|
18
|
+
|
19
|
+
def hidden
|
20
|
+
@_.navigationBarHidden
|
21
|
+
end
|
22
|
+
|
23
|
+
def visible
|
24
|
+
!hidden
|
25
|
+
end
|
26
|
+
|
27
|
+
def disable_swipes
|
28
|
+
@_.interactivePopGestureRecognizer.enabled = false
|
29
|
+
end
|
30
|
+
|
31
|
+
def enable_swipes
|
32
|
+
@_.interactivePopGestureRecognizer.enabled = true
|
33
|
+
end
|
34
|
+
|
35
|
+
def left_button
|
36
|
+
@left_button
|
37
|
+
end
|
38
|
+
|
39
|
+
def left_button=(view)
|
40
|
+
@left_button = view
|
41
|
+
@_.topViewController.navigationItem.leftBarButtonItem = to_navigation_item(view)
|
42
|
+
end
|
43
|
+
|
44
|
+
def right_button
|
45
|
+
right_buttons[0]
|
46
|
+
end
|
47
|
+
|
48
|
+
def right_button=(view)
|
49
|
+
self.right_buttons = [view]
|
50
|
+
end
|
51
|
+
|
52
|
+
def right_buttons
|
53
|
+
@right_buttons || []
|
54
|
+
end
|
55
|
+
|
56
|
+
def right_buttons=(views)
|
57
|
+
views = [views] if views.is_a?(Hash)
|
58
|
+
@right_buttons = views
|
59
|
+
@_.topViewController.navigationItem.rightBarButtonItems =
|
60
|
+
views.map{|v| to_navigation_item(v)}.flatten.compact.reverse
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def to_navigation_item(view)
|
66
|
+
view = to_raw_uiview(view)
|
67
|
+
|
68
|
+
if view.is_a?(UIBarButtonItem)
|
69
|
+
view
|
70
|
+
elsif view.is_a?(UIView)
|
71
|
+
UIBarButtonItem.alloc.initWithCustomView(view)
|
72
|
+
elsif view.is_a?(Hash)
|
73
|
+
view.map do |type, callback|
|
74
|
+
if SYSTEM_BUTTONS[type.to_sym]
|
75
|
+
UIBarButtonItem.alloc.initWithBarButtonSystemItem SYSTEM_BUTTONS[type.to_sym], target: callback, action: :call
|
76
|
+
elsif type.is_a?(UIImage)
|
77
|
+
UIBarButtonItem.alloc.initWithImage(type, style: UIBarButtonItemStylePlain, target: callback, action: :call)
|
78
|
+
else
|
79
|
+
UIBarButtonItem.alloc.initWithTitle(type.to_s, style: UIBarButtonItemStylePlain, target: callback, action: :call)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_raw_uiview(view)
|
86
|
+
view = view.to_sym if view.is_a?(String)
|
87
|
+
view = {view: Proc.new{}} if view.is_a?(Symbol)
|
88
|
+
|
89
|
+
if view.is_a?(UnderOs::UI::View)
|
90
|
+
view.addClass('navbar-item')
|
91
|
+
view.repaint(UnderOs::App.history.current_page.stylesheet)
|
92
|
+
view = view._
|
93
|
+
end
|
94
|
+
|
95
|
+
view
|
96
|
+
end
|
97
|
+
|
98
|
+
SYSTEM_BUTTONS = {
|
99
|
+
done: UIBarButtonSystemItemDone,
|
100
|
+
cancel: UIBarButtonSystemItemCancel,
|
101
|
+
edit: UIBarButtonSystemItemEdit,
|
102
|
+
save: UIBarButtonSystemItemSave,
|
103
|
+
add: UIBarButtonSystemItemAdd,
|
104
|
+
space: UIBarButtonSystemItemFlexibleSpace,
|
105
|
+
compose: UIBarButtonSystemItemCompose,
|
106
|
+
reply: UIBarButtonSystemItemReply,
|
107
|
+
action: UIBarButtonSystemItemAction,
|
108
|
+
organize: UIBarButtonSystemItemOrganize,
|
109
|
+
bookmarks: UIBarButtonSystemItemBookmarks,
|
110
|
+
search: UIBarButtonSystemItemSearch,
|
111
|
+
refresh: UIBarButtonSystemItemRefresh,
|
112
|
+
camera: UIBarButtonSystemItemCamera,
|
113
|
+
trash: UIBarButtonSystemItemTrash,
|
114
|
+
stop: UIBarButtonSystemItemStop,
|
115
|
+
play: UIBarButtonSystemItemPlay,
|
116
|
+
pause: UIBarButtonSystemItemPause,
|
117
|
+
rewind: UIBarButtonSystemItemRewind,
|
118
|
+
forward: UIBarButtonSystemItemFastForward,
|
119
|
+
undor: UIBarButtonSystemItemUndo,
|
120
|
+
redo: UIBarButtonSystemItemRedo,
|
121
|
+
curl: UIBarButtonSystemItemPageCurl,
|
122
|
+
}
|
123
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class UnderOs::UI::Progress < UnderOs::UI::View
|
2
|
+
wraps UIProgressView, tag: :progress
|
3
|
+
|
4
|
+
def initialize(options={})
|
5
|
+
super
|
6
|
+
|
7
|
+
self.value = options[:value] if options[:value]
|
8
|
+
end
|
9
|
+
|
10
|
+
def value
|
11
|
+
@_.progress
|
12
|
+
end
|
13
|
+
|
14
|
+
def value=(value)
|
15
|
+
@_.setProgress value.to_f, animated: true
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
class UnderOs::UI::Scroll < UnderOs::UI::View
|
2
|
+
wraps UIScrollView, tag: :scroll
|
3
|
+
|
4
|
+
def initialize(options={})
|
5
|
+
super
|
6
|
+
|
7
|
+
self.paging = options.delete(:paging)
|
8
|
+
|
9
|
+
@_.delegate = self
|
10
|
+
end
|
11
|
+
|
12
|
+
def paging
|
13
|
+
@paging == nil ? false : @paging
|
14
|
+
end
|
15
|
+
|
16
|
+
def paging=(value)
|
17
|
+
@paging = value == true ? true : nil
|
18
|
+
@_.pagingEnabled = paging
|
19
|
+
end
|
20
|
+
|
21
|
+
def contentSize
|
22
|
+
UnderOs::Point.new(x: @_.contentSize.width, y: @_.contentSize.height)
|
23
|
+
end
|
24
|
+
|
25
|
+
def contentSize=(*args)
|
26
|
+
size = UnderOs::Point.new(*args)
|
27
|
+
@_.contentSize = CGSizeMake(size.x, size.y)
|
28
|
+
end
|
29
|
+
|
30
|
+
def contentOffset
|
31
|
+
UnderOs::Point.new(x: @_.contentOffset.x, y: @_.contentOffset.y)
|
32
|
+
end
|
33
|
+
|
34
|
+
def contentOffset=(*args)
|
35
|
+
offset = UnderOs::Point.new(*args)
|
36
|
+
@_.contentOffset = CGPointMake(offset.x, offset.y)
|
37
|
+
end
|
38
|
+
|
39
|
+
def repaint(*args)
|
40
|
+
content_size = {}
|
41
|
+
|
42
|
+
super *args do |styles|
|
43
|
+
styles.reject do |key, value|
|
44
|
+
if [:contentWidth, :contentHeight].include?(key)
|
45
|
+
content_size[key] = value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
self.style = content_size unless content_size.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
def centerContent
|
54
|
+
left = @_.contentSize.width > @_.bounds.size.width ? 0 :
|
55
|
+
(@_.bounds.size.width - @_.contentSize.width) * 0.5
|
56
|
+
|
57
|
+
top = @_.contentSize.height > @_.bounds.size.height ? 0 :
|
58
|
+
(@_.bounds.size.height - @_.contentSize.height) * 0.5
|
59
|
+
|
60
|
+
@_.contentInset = UIEdgeInsetsMake(top, left, top, left)
|
61
|
+
end
|
62
|
+
|
63
|
+
def scale
|
64
|
+
@_.zoomScale
|
65
|
+
end
|
66
|
+
|
67
|
+
def scale=(scale)
|
68
|
+
@_.zoomScale = scale
|
69
|
+
end
|
70
|
+
|
71
|
+
def minScale
|
72
|
+
@_.minimumZoomScale
|
73
|
+
end
|
74
|
+
|
75
|
+
def minScale=(scale)
|
76
|
+
@_.minimumZoomScale = scale
|
77
|
+
end
|
78
|
+
|
79
|
+
def maxScale
|
80
|
+
@_.maximumZoomScale
|
81
|
+
end
|
82
|
+
|
83
|
+
def maxScale=(scale)
|
84
|
+
@_.maximumZoomScale = scale
|
85
|
+
end
|
86
|
+
|
87
|
+
def zoomItem
|
88
|
+
@zoomItem
|
89
|
+
end
|
90
|
+
|
91
|
+
def zoomItem=(item)
|
92
|
+
@zoomItem = item.is_a?(UnderOs::UI::View) ? item._ : item
|
93
|
+
end
|
94
|
+
|
95
|
+
def viewForZoomingInScrollView(scrollView)
|
96
|
+
@zoomItem
|
97
|
+
end
|
98
|
+
|
99
|
+
def scrollViewDidZoom(scrollView)
|
100
|
+
emit :zoom
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
class UnderOs::UI::Select < UnderOs::UI::Input
|
2
|
+
wraps UIPickerView, tag: :select
|
3
|
+
|
4
|
+
def initialize(options={})
|
5
|
+
super
|
6
|
+
|
7
|
+
self.options = options.delete(:options) if options[:options]
|
8
|
+
@_.showsSelectionIndicator = true if options[:lense]
|
9
|
+
|
10
|
+
@_.dataSource = self
|
11
|
+
end
|
12
|
+
|
13
|
+
def optgroups
|
14
|
+
@optgroups ||= [{}]
|
15
|
+
end
|
16
|
+
|
17
|
+
def optgroups=(list)
|
18
|
+
@optgroups = list.map do |hash|
|
19
|
+
{}.tap do |clean_hash|
|
20
|
+
hash.each do |key, value|
|
21
|
+
clean_hash[key.to_s] = value if key && value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def options
|
28
|
+
optgroups.size == 1 ? optgroups[0] : optgroups
|
29
|
+
end
|
30
|
+
|
31
|
+
def options=(value)
|
32
|
+
self.optgroups = value.is_a?(Array) ? value : [value]
|
33
|
+
@_.reloadAllComponents
|
34
|
+
end
|
35
|
+
|
36
|
+
def value
|
37
|
+
@value ||= []
|
38
|
+
optgroups.size == 1 ? @value[0] : @value
|
39
|
+
end
|
40
|
+
|
41
|
+
def value=(value)
|
42
|
+
prev_val = @value
|
43
|
+
@value = Array(value).map(&:to_s)
|
44
|
+
handle_change if @value != prev_val
|
45
|
+
|
46
|
+
@value.each_with_index do |value, group|
|
47
|
+
i = 0;
|
48
|
+
optgroups[group].each do |v, label|
|
49
|
+
if value == v
|
50
|
+
@_.selectRow i, inComponent: group, animated: false
|
51
|
+
else
|
52
|
+
i += 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def show
|
59
|
+
page.find('select').each do |select|
|
60
|
+
select.hide if select.visible && select != self
|
61
|
+
end
|
62
|
+
|
63
|
+
self.style = {bottom: -size.y, display: :block}
|
64
|
+
|
65
|
+
animate bottom: 0
|
66
|
+
end
|
67
|
+
|
68
|
+
def hide
|
69
|
+
animate bottom: -size.y, complete: -> {
|
70
|
+
style.display = :none
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
# UIPickerView delegate
|
76
|
+
|
77
|
+
def numberOfComponentsInPickerView(picker)
|
78
|
+
optgroups.size
|
79
|
+
end
|
80
|
+
|
81
|
+
def pickerView(picker, numberOfRowsInComponent: group)
|
82
|
+
optgroups[group].size
|
83
|
+
end
|
84
|
+
|
85
|
+
def pickerView(picker, titleForRow:index, forComponent:group)
|
86
|
+
optgroups[group].to_a[index][1]
|
87
|
+
end
|
88
|
+
|
89
|
+
def pickerView(picker, didSelectRow:index, inComponent:group)
|
90
|
+
value = (@value || []).dup
|
91
|
+
value[group] = optgroups[group].to_a[index][0]
|
92
|
+
|
93
|
+
self.value = value
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class UnderOs::UI::Sidebar < UnderOs::UI::View
|
2
|
+
wraps UIView, tag: :sidebar
|
3
|
+
|
4
|
+
LOCATIONS = [:top, :left, :right, :bottom]
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
super
|
8
|
+
|
9
|
+
self.location = options.delete(:location) if options.has_key?(:location)
|
10
|
+
end
|
11
|
+
|
12
|
+
def location
|
13
|
+
@location || :bottom
|
14
|
+
end
|
15
|
+
|
16
|
+
def location=(value)
|
17
|
+
@location = value.to_sym
|
18
|
+
@location = nil if ! LOCATIONS.include?(@location)
|
19
|
+
end
|
20
|
+
|
21
|
+
def show
|
22
|
+
class_names = self.classNames
|
23
|
+
class_names.reject!{ |n| LOCATIONS.include?(n.to_sym) }
|
24
|
+
|
25
|
+
self.classNames = class_names + [location, 'visible']
|
26
|
+
self.style = {location => -slide_distance, display: :block}
|
27
|
+
|
28
|
+
animate location => 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def hide
|
32
|
+
@_class_names -= ['visible']
|
33
|
+
|
34
|
+
animate location => -slide_distance
|
35
|
+
end
|
36
|
+
|
37
|
+
def hidden
|
38
|
+
!classNames.include?('visible')
|
39
|
+
end
|
40
|
+
|
41
|
+
def slide_distance
|
42
|
+
[:top, :bottom].include?(location) ? size.y : size.x
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|