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.
- 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
data/lib/under_os/ui.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
class UnderOs::UI::Alert
|
|
2
|
+
include UnderOs::Events
|
|
3
|
+
|
|
4
|
+
def initialize(options={})
|
|
5
|
+
options = {message: options} if options.is_a?(String)
|
|
6
|
+
self.on = options.delete[:on] if options[:on]
|
|
7
|
+
|
|
8
|
+
@_ = CustomAlertView.alloc.initiWithOptions(self, options)
|
|
9
|
+
@_.show unless options[:show] == false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def show
|
|
13
|
+
@_.show
|
|
14
|
+
self
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def hide(animated=true)
|
|
18
|
+
@_.dismissWithClickedButtonIndex(0, animated: animated)
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def visible
|
|
23
|
+
@_.visible
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def hidden
|
|
27
|
+
!visible
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class CustomAlertView < UIAlertView
|
|
31
|
+
def initiWithOptions(wrapper, options)
|
|
32
|
+
@wrapper = wrapper
|
|
33
|
+
|
|
34
|
+
initWithTitle( options[:title] || "",
|
|
35
|
+
message: options[:message] || "No message given",
|
|
36
|
+
delegate: self,
|
|
37
|
+
cancelButtonTitle: options[:button] || "Ok",
|
|
38
|
+
otherButtonTitles: nil )
|
|
39
|
+
|
|
40
|
+
(options[:buttons] || []).each do |title|
|
|
41
|
+
addButtonWithTitle title
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
self
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def alertView(alertView, willDismissWithButtonIndex:buttonIndex)
|
|
48
|
+
@wrapper.emit(:tap, buttonIndex: buttonIndex, buttonTitle: buttonTitleAtIndex(buttonIndex))
|
|
49
|
+
@wrapper.emit(:close)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class UnderOS::UI::Button < UnderOS::UI::View
|
|
2
|
+
wraps UIButton, tag: 'button'
|
|
3
|
+
|
|
4
|
+
def initialize(options={})
|
|
5
|
+
super
|
|
6
|
+
|
|
7
|
+
self.text = options.delete(:text) || ''
|
|
8
|
+
self.disable if options[:disabled]
|
|
9
|
+
|
|
10
|
+
@_.showsTouchWhenHighlighted = true
|
|
11
|
+
@_.setBackgroundImage(options.delete(:image), forState:UIControlStateNormal) if options[:image]
|
|
12
|
+
@_.sizeToFit
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def text
|
|
16
|
+
@_.currentTitle
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def text=(new_text, state=UIControlStateNormal)
|
|
20
|
+
@_.setTitle new_text, forState:state
|
|
21
|
+
repaint
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def disabled
|
|
25
|
+
! @_.isEnabled
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
alias :disabled? :disabled
|
|
29
|
+
|
|
30
|
+
def disabled=(value)
|
|
31
|
+
@_.enabled = ! value
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def disable
|
|
35
|
+
self.disabled = true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def enable
|
|
39
|
+
self.disabled = false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
class UnderOs::UI::Collection < UnderOs::UI::View
|
|
2
|
+
wraps UICollectionView, tag: :collection
|
|
3
|
+
|
|
4
|
+
def initialize(options={})
|
|
5
|
+
super
|
|
6
|
+
|
|
7
|
+
self.layout = Layout.new if ! options[:layout]
|
|
8
|
+
self.layout = options.delete(:layout) if options[:layout].is_a?(Class)
|
|
9
|
+
self.layout = options.delete(:layout).constantize if options[:layout].is_a?(String)
|
|
10
|
+
|
|
11
|
+
@_.delegate = @_.dataSource = Delegate.new(self)
|
|
12
|
+
@_.registerClass(Cell, forCellWithReuseIdentifier:'UOSCollectionCell')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def on(*args, &block)
|
|
16
|
+
super *args do |event|
|
|
17
|
+
params = [event.item, event.index, event.section]
|
|
18
|
+
params = params.slice(0, block.arity) if block.arity > -1
|
|
19
|
+
|
|
20
|
+
block.call *params
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def layout
|
|
25
|
+
@layout
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def layout=(layout)
|
|
29
|
+
layout = Layout.new(layout) if layout.is_a?(UICollectionViewLayout)
|
|
30
|
+
@_.collectionViewLayout = (@layout = layout)._
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def item_class
|
|
34
|
+
Cell.classes[self]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def item_class=(klass)
|
|
38
|
+
Cell.classes[self] = klass
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def reload
|
|
42
|
+
@_.reloadData
|
|
43
|
+
self
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def number_of_items(section=0)
|
|
47
|
+
(@number_of_items || [0])[section]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def number_of_items=(value)
|
|
51
|
+
@number_of_items = value.is_a?(Numeric) ? [value] : value
|
|
52
|
+
reload
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def number_of_sections
|
|
56
|
+
(@number_of_items || [0]).size
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def repaint(stylesheet=nil)
|
|
60
|
+
stylesheet ||= page && page.stylesheet
|
|
61
|
+
|
|
62
|
+
self.style = stylesheet.styles_for(self) if stylesheet
|
|
63
|
+
Styles.build(self, stylesheet) if stylesheet
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#
|
|
2
|
+
# This is a bridge to the iOS native functionality
|
|
3
|
+
# please do not use it in your code
|
|
4
|
+
#
|
|
5
|
+
class UnderOs::UI::Collection::Cell < UICollectionViewCell
|
|
6
|
+
|
|
7
|
+
def self.classes
|
|
8
|
+
@classes ||= {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def uos_view_for(collection)
|
|
12
|
+
@uos_view ||= self.class.classes[collection].for(collection).tap do |view|
|
|
13
|
+
contentView.addSubview(view._)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def prepareForReuse
|
|
18
|
+
super
|
|
19
|
+
@uos_view.cleanup if @uos_view
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#
|
|
2
|
+
# The iOS level events receiver, not for a public use
|
|
3
|
+
#
|
|
4
|
+
class UnderOs::UI::Collection::Delegate < UIViewController
|
|
5
|
+
|
|
6
|
+
def self.new(collection)
|
|
7
|
+
alloc.tap do |instance|
|
|
8
|
+
instance.instance_eval do
|
|
9
|
+
@collection = collection
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
################################################################
|
|
15
|
+
# DataSource API
|
|
16
|
+
################################################################
|
|
17
|
+
|
|
18
|
+
def numberOfSectionsInCollectionView(collection)
|
|
19
|
+
@collection.number_of_sections
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def collectionView(collection, numberOfItemsInSection: section)
|
|
23
|
+
@collection.number_of_items(section)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def collectionView(collection, cellForItemAtIndexPath: indexPath)
|
|
27
|
+
collection.dequeueReusableCellWithReuseIdentifier('UOSCollectionCell', forIndexPath:indexPath).tap do |item|
|
|
28
|
+
@collection.emit(:item, item: item.uos_view_for(@collection), index: indexPath.row, section: indexPath.section)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# def collectionView(collection, viewForSupplementaryElementOfKind: kind, atIndexPath: indexPath)
|
|
33
|
+
# # kind is a string
|
|
34
|
+
# UICollectionReusableView.alloc.init
|
|
35
|
+
# UICollectionReusableView * reusableview = nil ;
|
|
36
|
+
|
|
37
|
+
# if ( kind == UICollectionElementKindSectionHeader ) {
|
|
38
|
+
# RecipeCollectionHeaderView * headerView = [ collectionView dequeueReusableSupplementaryViewOfKind : UICollectionElementKindSectionHeader withReuseIdentifier : @ "HeaderView" forIndexPath : indexPath ] ;
|
|
39
|
+
# NSString * title = [ [ NSString alloc ] initWithFormat : @ "Recipe Group #%i" , indexPath.section + 1 ] ;
|
|
40
|
+
# headerView.title.text = title;
|
|
41
|
+
# UIImage * headerImage = [ UIImage imageNamed : @ "header_banner.png" ] ;
|
|
42
|
+
# headerView.backgroundImage.image = headerImage;
|
|
43
|
+
|
|
44
|
+
# reusableview = headerView;
|
|
45
|
+
# }
|
|
46
|
+
|
|
47
|
+
# if ( kind == UICollectionElementKindSectionFooter ) {
|
|
48
|
+
# UICollectionReusableView * footerview = [ collectionView dequeueReusableSupplementaryViewOfKind : UICollectionElementKindSectionFooter withReuseIdentifier : @ "FooterView" forIndexPath : indexPath ] ;
|
|
49
|
+
|
|
50
|
+
# reusableview = footerview;
|
|
51
|
+
# }
|
|
52
|
+
|
|
53
|
+
# return reusableview;
|
|
54
|
+
# end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
################################################################
|
|
58
|
+
# DataSource API
|
|
59
|
+
################################################################
|
|
60
|
+
|
|
61
|
+
def collectionView(collection, didSelectItemAtIndexPath: indexPath)
|
|
62
|
+
item = collection.cellForItemAtIndexPath(indexPath).uos_view_for(@collection)
|
|
63
|
+
@collection.emit(:select, item: item, index: indexPath.row, section: indexPath.section)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def collectionView(collection, didDeselectItemAtIndexPath: indexPath)
|
|
67
|
+
item = collection.cellForItemAtIndexPath(indexPath).uos_view_for(@collection)
|
|
68
|
+
@collection.emit(:unselect, item: item, index: indexPath.row, section: indexPath.section)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#
|
|
2
|
+
# This is the collection item class that you supposed
|
|
3
|
+
# to inherit (well, if you need to)
|
|
4
|
+
#
|
|
5
|
+
class UnderOs::UI::Collection::Item < UnderOs::UI::View
|
|
6
|
+
|
|
7
|
+
tag :item
|
|
8
|
+
|
|
9
|
+
def self.build(collection, &builder)
|
|
10
|
+
@builders ||= {}
|
|
11
|
+
@builders[collection] = builder
|
|
12
|
+
collection.item_class = self
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.for(collection, stylesheet=nil)
|
|
16
|
+
new.tap do |view|
|
|
17
|
+
def view.parent; @_parent; end
|
|
18
|
+
view.instance_variable_set('@_parent', collection)
|
|
19
|
+
|
|
20
|
+
@builders[collection] && @builders[collection].call.each do |child|
|
|
21
|
+
view.insert child
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
view.repaint(stylesheet || UnderOs::App.history.current_page.stylesheet)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def cleanup
|
|
29
|
+
# implement me if you need to clean cells between reuse
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#
|
|
2
|
+
# The basic, grid (flow) layout. inheritable.
|
|
3
|
+
#
|
|
4
|
+
class Layout
|
|
5
|
+
attr_reader :_
|
|
6
|
+
|
|
7
|
+
def initialize(layout=nil)
|
|
8
|
+
@_ = layout || UICollectionViewFlowLayout.alloc.init
|
|
9
|
+
|
|
10
|
+
self.items_spacing = 0
|
|
11
|
+
self.rows_spacing = 1
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def item_size
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def item_size=(*size)
|
|
18
|
+
size = UnderOs::Point.new(*size)
|
|
19
|
+
@_.itemSize = CGSizeMake(size.x, size.y)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def items_spacing
|
|
23
|
+
@_.minimumInteritemSpacing
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def items_spacing=(value)
|
|
27
|
+
@_.minimumInteritemSpacing = value
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def rows_spacing
|
|
31
|
+
@_.minimumLineSpacing
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def rows_spacing=(value)
|
|
35
|
+
@_.minimumLineSpacing = value
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def section_inset
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def section_inset=(value)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#
|
|
2
|
+
# This thing catches styles from the collection element
|
|
3
|
+
# and adjusts the layout settings for them
|
|
4
|
+
#
|
|
5
|
+
class UnderOs::UI::Collection::Styles
|
|
6
|
+
def self.build(collection, stylesheet)
|
|
7
|
+
item = UnderOs::UI::Collection::Item.for(collection, stylesheet)
|
|
8
|
+
|
|
9
|
+
collection.layout.item_size = item.size
|
|
10
|
+
collection.layout.items_spacing = item.style.marginLeft + item.style.marginRight
|
|
11
|
+
collection.layout.rows_spacing = item.style.marginTop + item.style.marginBottom
|
|
12
|
+
|
|
13
|
+
# TODO header/footer
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
class UnderOs::UI::Form < UnderOs::UI::View
|
|
2
|
+
tag :form
|
|
3
|
+
|
|
4
|
+
def elements
|
|
5
|
+
find('*').select do |view|
|
|
6
|
+
view.is_a?(UnderOs::UI::Input) || view._.is_a?(UIButton)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def inputs
|
|
11
|
+
find('*').select do |view|
|
|
12
|
+
view.is_a?(UnderOs::UI::Input)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def values
|
|
17
|
+
{}.tap do |values|
|
|
18
|
+
inputs.each do |input|
|
|
19
|
+
next if input.disabled || ! input.name || (input.is_a?(UnderOs::UI::Switch) && !input.checked)
|
|
20
|
+
|
|
21
|
+
hash = values; key = nil
|
|
22
|
+
keys = input.name.scan(/[^\[]+/)
|
|
23
|
+
|
|
24
|
+
# getting throught the smth[smth][smth][] in the name
|
|
25
|
+
while keys.size > 1
|
|
26
|
+
key = keys.shift
|
|
27
|
+
key = key.slice(0, key.size-1) if key.ends_with?(']')
|
|
28
|
+
|
|
29
|
+
hash[key] = keys[0] == ']' ? [] : {} if ! hash[key]
|
|
30
|
+
hash = hash[key]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
key = keys.shift
|
|
34
|
+
key = key.slice(0, key.size-1) if key.ends_with?(']')
|
|
35
|
+
|
|
36
|
+
if hash.is_a?(Array)
|
|
37
|
+
hash << input.value
|
|
38
|
+
else
|
|
39
|
+
hash[key] = input.value
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def disable
|
|
46
|
+
elements.each(&:disable)
|
|
47
|
+
self
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def enable
|
|
51
|
+
elements.each(&:enable)
|
|
52
|
+
self
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def focus
|
|
56
|
+
if input = inputs.first
|
|
57
|
+
input.focus
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
class UnderOs::UI::Icon < UnderOs::UI::View
|
|
2
|
+
include UnderOs::UI::IconEngine
|
|
3
|
+
engine UnderOs::UI::IconEngineAwesome
|
|
4
|
+
|
|
5
|
+
wraps UIButton, tag: 'icon'
|
|
6
|
+
|
|
7
|
+
def initialize(options)
|
|
8
|
+
options = {type: options} if ! options.is_a?(Hash)
|
|
9
|
+
|
|
10
|
+
super(options)
|
|
11
|
+
|
|
12
|
+
self.type = options.delete(:type) || :bug
|
|
13
|
+
self.size = options.delete(:size) || 20
|
|
14
|
+
self.disable if options[:disabled]
|
|
15
|
+
|
|
16
|
+
@_.sizeToFit
|
|
17
|
+
@_.showsTouchWhenHighlighted = true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def type
|
|
21
|
+
@type
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def type=(type)
|
|
25
|
+
@type = type
|
|
26
|
+
@_.setTitle self.class.engine.text(type), forState:UIControlStateNormal
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def size(size=nil)
|
|
30
|
+
if size
|
|
31
|
+
self.size = size
|
|
32
|
+
self
|
|
33
|
+
else
|
|
34
|
+
@size
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def size=(size)
|
|
39
|
+
@size = size
|
|
40
|
+
@_.setFont self.class.engine.font(size)
|
|
41
|
+
@_.sizeToFit
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def disabled
|
|
45
|
+
! @_.isEnabled
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
alias :disabled? :disabled
|
|
49
|
+
|
|
50
|
+
def disabled=(value)
|
|
51
|
+
@_.enabled = ! value
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def disable
|
|
55
|
+
self.disabled = true
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def enable
|
|
59
|
+
self.disabled = false
|
|
60
|
+
end
|
|
61
|
+
end
|