motion-prime 0.9.9 → 0.9.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/CHANGELOG.md +8 -2
- data/Gemfile.lock +2 -2
- data/ROADMAP.md +1 -3
- data/files/Gemfile +1 -1
- data/generators/templates/scaffold/table.rb +1 -1
- data/generators/templates/table.rb +1 -1
- data/motion-prime/config/base.rb +2 -2
- data/motion-prime/elements/_content_text_mixin.rb +1 -1
- data/motion-prime/elements/base_element.rb +14 -7
- data/motion-prime/elements/collection_view_cell.rb +7 -0
- data/motion-prime/elements/draw/image.rb +7 -2
- data/motion-prime/elements/table_view_cell.rb +1 -1
- data/motion-prime/helpers/has_normalizer.rb +1 -1
- data/motion-prime/helpers/has_search_bar.rb +1 -1
- data/motion-prime/models/_nano_bag_mixin.rb +1 -1
- data/motion-prime/models/model.rb +8 -8
- data/motion-prime/models/store.rb +1 -1
- data/motion-prime/screens/screen.rb +3 -3
- data/motion-prime/sections/_async_form_mixin.rb +2 -2
- data/motion-prime/sections/_async_table_mixin.rb +7 -7
- data/motion-prime/sections/_cell_section_mixin.rb +16 -11
- data/motion-prime/sections/_draw_section_mixin.rb +1 -0
- data/motion-prime/sections/{__section_with_container_mixin.rb → _section_with_container_mixin.rb} +2 -2
- data/motion-prime/sections/abstract_collection.rb +291 -0
- data/motion-prime/sections/base_section.rb +2 -2
- data/motion-prime/sections/collection/collection_delegate.rb +62 -0
- data/motion-prime/sections/form.rb +22 -18
- data/motion-prime/sections/form/base_field_section.rb +7 -7
- data/motion-prime/sections/form/form_delegate.rb +1 -1
- data/motion-prime/sections/form/form_header_section.rb +1 -1
- data/motion-prime/sections/form/password_field_section.rb +1 -1
- data/motion-prime/sections/form/static_field_section.rb +1 -1
- data/motion-prime/sections/form/string_field_section.rb +1 -1
- data/motion-prime/sections/form/text_field_section.rb +1 -1
- data/motion-prime/sections/grid.rb +92 -0
- data/motion-prime/sections/table.rb +26 -260
- data/motion-prime/sections/table/refresh_mixin.rb +3 -3
- data/motion-prime/sections/table/table_delegate.rb +1 -0
- data/motion-prime/styles/_mixins.rb +1 -1
- data/motion-prime/styles/base.rb +20 -6
- data/motion-prime/styles/form.rb +1 -1
- data/motion-prime/support/_control_content_alignment.rb +39 -0
- data/motion-prime/support/mp_button.rb +5 -13
- data/motion-prime/support/mp_collection_cell_with_section.rb +12 -0
- data/motion-prime/support/{mp_cell_content_view.rb → mp_table_cell_content_view.rb} +0 -0
- data/motion-prime/support/{mp_cell_with_section.rb → mp_table_cell_with_section.rb} +1 -1
- data/motion-prime/support/mp_text_field.rb +24 -18
- data/motion-prime/support/mp_text_view.rb +1 -0
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/_frame_calculator_mixin.rb +15 -11
- data/motion-prime/views/layout.rb +6 -4
- data/motion-prime/views/view_builder.rb +10 -0
- data/motion-prime/views/view_styler.rb +5 -1
- data/spec/factories/scaffold/sections/tasks/index_table.rb +1 -1
- data/spec/unit/support/filter_mixin_spec.rb +7 -3
- data/spec/unit/support/frame_calculator_mixin_spec.rb +43 -0
- metadata +13 -5
@@ -3,13 +3,13 @@ module MotionPrime
|
|
3
3
|
def add_pull_to_refresh(options = {}, &block)
|
4
4
|
screen.automaticallyAdjustsScrollViewInsets = false
|
5
5
|
|
6
|
-
|
7
|
-
screen.set_options_for
|
6
|
+
collection_view.addPullToRefreshWithActionHandler(block) # block must be a variable
|
7
|
+
screen.set_options_for collection_view.pullToRefreshView, styles: [:base_pull_to_refresh]
|
8
8
|
end
|
9
9
|
|
10
10
|
def finish_pull_to_refresh
|
11
11
|
reload_data
|
12
|
-
|
12
|
+
collection_view.pullToRefreshView.stopAnimating
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
data/motion-prime/styles/base.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
motion_require '../views/styles
|
1
|
+
motion_require '../views/styles'
|
2
2
|
MotionPrime::Styles.define :base do
|
3
3
|
# basic screen styles
|
4
4
|
style :screen,
|
@@ -9,17 +9,23 @@ MotionPrime::Styles.define :base do
|
|
9
9
|
style :table,
|
10
10
|
top: 0,
|
11
11
|
left: 0,
|
12
|
-
|
12
|
+
right: 0,
|
13
13
|
bottom: 0,
|
14
14
|
separator_inset: 0
|
15
15
|
|
16
|
+
style :collection,
|
17
|
+
top: 0,
|
18
|
+
left: 0,
|
19
|
+
right: 0,
|
20
|
+
bottom: 0
|
21
|
+
|
16
22
|
style :table_cell,
|
17
23
|
background_color: :clear
|
18
24
|
|
19
25
|
# basic form styles
|
20
26
|
# ----------
|
21
27
|
style :form,
|
22
|
-
|
28
|
+
right: 0,
|
23
29
|
left: 0,
|
24
30
|
top: 0,
|
25
31
|
right: 0,
|
@@ -41,14 +47,22 @@ MotionPrime::Styles.define :base do
|
|
41
47
|
height: 44
|
42
48
|
|
43
49
|
style :segmented_control,
|
44
|
-
height: 40,
|
50
|
+
height: 40,
|
51
|
+
left: 0,
|
52
|
+
right: 0,
|
53
|
+
top: 0
|
45
54
|
|
46
55
|
style :google_map,
|
47
|
-
top: 0,
|
56
|
+
top: 0,
|
57
|
+
left: 0,
|
58
|
+
right: 0,
|
59
|
+
bottom: 0
|
48
60
|
|
49
61
|
style :spinner,
|
50
62
|
annular: true,
|
51
|
-
center: proc { screen.view.center },
|
63
|
+
center: proc { screen.view.center },
|
64
|
+
width: 37,
|
65
|
+
height: 37,
|
52
66
|
progress_tint_color: :app_base.uicolor,
|
53
67
|
background_tint_color: :black.uicolor(0.05),
|
54
68
|
progress: 0.25
|
data/motion-prime/styles/form.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module SupportControlContentAlignment
|
3
|
+
VERTICAL_ALIGNMENT_CONSTS = {
|
4
|
+
UIControlContentVerticalAlignmentCenter => :center,
|
5
|
+
UIControlContentVerticalAlignmentTop => :top,
|
6
|
+
UIControlContentVerticalAlignmentBottom => :bottom,
|
7
|
+
UIControlContentVerticalAlignmentFill => :fill # TODO: handle this value
|
8
|
+
}
|
9
|
+
def setContentVerticalAlignment(value)
|
10
|
+
return unless @_content_vertical_alignment = VERTICAL_ALIGNMENT_CONSTS[value]
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def padding_top
|
15
|
+
padding_top = self.paddingTop || self.padding
|
16
|
+
if @_content_vertical_alignment == :bottom
|
17
|
+
padding_bottom = self.paddingBottom || self.padding
|
18
|
+
bounds_height - padding_bottom.to_i - line_height
|
19
|
+
elsif @_content_vertical_alignment == :top
|
20
|
+
padding_top.to_i
|
21
|
+
else # center label
|
22
|
+
padding_top_offset = padding_top.to_i - (self.paddingBottom || self.padding).to_i
|
23
|
+
(bounds_height - line_height)/2 + 1 + padding_top_offset
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def padding_bottom
|
28
|
+
(bounds_height - (line_height + padding_top))
|
29
|
+
end
|
30
|
+
|
31
|
+
def line_height
|
32
|
+
@_line_height || self.font.pointSize
|
33
|
+
end
|
34
|
+
|
35
|
+
def bounds_height
|
36
|
+
self.bounds.size.height
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,8 +1,11 @@
|
|
1
|
-
motion_require '
|
2
|
-
motion_require '
|
1
|
+
motion_require '_key_value_store'
|
2
|
+
motion_require '_padding_attribute'
|
3
|
+
motion_require '_control_content_alignment'
|
3
4
|
class MPButton < UIButton
|
4
5
|
include MotionPrime::SupportKeyValueStore
|
5
6
|
include MotionPrime::SupportPaddingAttribute
|
7
|
+
include MotionPrime::SupportControlContentAlignment
|
8
|
+
|
6
9
|
attr_accessor :sizeToFit
|
7
10
|
|
8
11
|
def setTitle(value)
|
@@ -26,17 +29,6 @@ class MPButton < UIButton
|
|
26
29
|
5
|
27
30
|
end
|
28
31
|
|
29
|
-
def padding_top # to center title label
|
30
|
-
self.paddingTop || self.padding || begin
|
31
|
-
single_line_height = self.font.pointSize
|
32
|
-
(self.bounds.size.height - single_line_height)/2 + 1
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def padding_bottom
|
37
|
-
self.bounds.size.height - (self.font.pointSize + padding_top)
|
38
|
-
end
|
39
|
-
|
40
32
|
def apply_padding!(rect)
|
41
33
|
self.setTitleEdgeInsets(padding_insets)
|
42
34
|
end
|
File without changes
|
@@ -1,13 +1,15 @@
|
|
1
1
|
# This class have some modifications for UITextField:
|
2
2
|
# * support padding, padding_left, padding_right options
|
3
3
|
# * support placeholder_color, placeholder_font options
|
4
|
-
motion_require '
|
5
|
-
motion_require '
|
4
|
+
motion_require '_key_value_store'
|
5
|
+
motion_require '_padding_attribute'
|
6
|
+
motion_require '_control_content_alignment'
|
6
7
|
class MPTextField < UITextField
|
7
8
|
include MotionPrime::SupportKeyValueStore
|
8
9
|
include MotionPrime::SupportPaddingAttribute
|
9
|
-
|
10
|
+
include MotionPrime::SupportControlContentAlignment
|
10
11
|
|
12
|
+
attr_accessor :placeholderColor, :placeholderFont, :readonly, :placeholderAlignment
|
11
13
|
|
12
14
|
def self.default_padding_left
|
13
15
|
5
|
@@ -19,38 +21,42 @@ class MPTextField < UITextField
|
|
19
21
|
|
20
22
|
# placeholder position
|
21
23
|
def textRectForBounds(bounds)
|
22
|
-
|
24
|
+
@_line_height = placeholder_font.pointSize
|
25
|
+
rect = calculate_rect_for(bounds)
|
26
|
+
@_line_height = nil
|
27
|
+
rect
|
23
28
|
end
|
24
29
|
|
25
30
|
# text position
|
26
31
|
def editingRectForBounds(bounds)
|
27
|
-
|
32
|
+
@_line_height = self.font.pointSize
|
33
|
+
rect = calculate_rect_for(bounds)
|
34
|
+
@_line_height = nil
|
35
|
+
rect
|
28
36
|
end
|
29
37
|
|
30
38
|
def drawPlaceholderInRect(rect)
|
31
39
|
color = self.placeholderColor || :gray.uicolor
|
32
40
|
color.setFill
|
33
|
-
font = self.placeholderFont || self.font || :system.uifont(16)
|
34
41
|
|
35
42
|
truncation = :tail_truncation.uilinebreakmode
|
36
|
-
alignment = (placeholderAlignment || :left)
|
37
|
-
|
38
|
-
self.placeholder.drawInRect(rect, withFont: font, lineBreakMode: truncation, alignment: alignment)
|
43
|
+
alignment = (placeholderAlignment || :left.nstextalignment)
|
44
|
+
self.placeholder.drawInRect(rect, withFont: placeholder_font, lineBreakMode: truncation, alignment: alignment)
|
39
45
|
end
|
40
46
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
(self.bounds.size.height - single_line_height)/2 + 1
|
47
|
+
private
|
48
|
+
def placeholder_font
|
49
|
+
self.placeholderFont || self.font || :system.uifont(16)
|
45
50
|
end
|
46
|
-
end
|
47
51
|
|
48
|
-
private
|
49
52
|
def calculate_rect_for(bounds)
|
50
|
-
height_diff = self.bounds.size.height - (
|
53
|
+
height_diff = self.bounds.size.height - (line_height + padding_top + padding_bottom)
|
51
54
|
bounds = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height - height_diff)
|
52
55
|
CGRectMake(
|
53
|
-
bounds.origin.x + padding_left,
|
54
|
-
bounds.
|
56
|
+
bounds.origin.x + padding_left,
|
57
|
+
bounds.origin.y + padding_top,
|
58
|
+
bounds.size.width - (padding_left + padding_right),
|
59
|
+
bounds.size.height - (padding_top + padding_bottom)
|
60
|
+
)
|
55
61
|
end
|
56
62
|
end
|
@@ -6,6 +6,7 @@ motion_require '../support/_padding_attribute'
|
|
6
6
|
class MPTextView < UITextView
|
7
7
|
include MotionPrime::SupportKeyValueStore
|
8
8
|
include MotionPrime::SupportPaddingAttribute
|
9
|
+
|
9
10
|
attr_accessor :placeholderColor, :placeholderFont, :placeholder
|
10
11
|
|
11
12
|
def self.default_padding_left
|
data/motion-prime/version.rb
CHANGED
@@ -19,8 +19,8 @@ module MotionPrime
|
|
19
19
|
|
20
20
|
max_width = parent_bounds.size.width
|
21
21
|
max_height = parent_bounds.size.height
|
22
|
-
|
23
|
-
|
22
|
+
temp_width = width || 0.0
|
23
|
+
temp_height = height || 0.0
|
24
24
|
|
25
25
|
if left && left > 0 && left <= 1 && value_type != 'absolute' && left.is_a?(Float)
|
26
26
|
left = max_width * left
|
@@ -41,7 +41,7 @@ module MotionPrime
|
|
41
41
|
end
|
42
42
|
|
43
43
|
# calculate top and bottom if height is relative, e.g 0.7
|
44
|
-
if height && height > 0 && height <= 1 && value_type != 'absolute' &&
|
44
|
+
if height && height > 0 && height <= 1 && value_type != 'absolute' && height.is_a?(Float)
|
45
45
|
if bottom.nil?
|
46
46
|
top ||= 0
|
47
47
|
bottom = max_height - max_height * height
|
@@ -52,27 +52,31 @@ module MotionPrime
|
|
52
52
|
|
53
53
|
if !left.nil? && !right.nil?
|
54
54
|
frame.origin.x = left
|
55
|
-
|
55
|
+
if options[:height_to_fit].nil? && width.nil?
|
56
|
+
width = max_width - left - right
|
57
|
+
end
|
56
58
|
elsif !right.nil?
|
57
|
-
frame.origin.x = max_width -
|
59
|
+
frame.origin.x = max_width - temp_width - right
|
58
60
|
elsif !left.nil?
|
59
61
|
frame.origin.x = left
|
60
62
|
else
|
61
|
-
frame.origin.x = max_width / 2 -
|
63
|
+
frame.origin.x = max_width / 2 - temp_width / 2
|
62
64
|
end
|
63
|
-
frame.size.width = width
|
65
|
+
frame.size.width = width || 0.0
|
64
66
|
|
65
67
|
if !top.nil? && !bottom.nil?
|
66
68
|
frame.origin.y = top
|
67
|
-
|
69
|
+
if options[:height_to_fit].nil? && height.nil?
|
70
|
+
height = max_height - top - bottom
|
71
|
+
end
|
68
72
|
elsif !bottom.nil?
|
69
|
-
frame.origin.y = max_height -
|
73
|
+
frame.origin.y = max_height - temp_height - bottom
|
70
74
|
elsif !top.nil?
|
71
75
|
frame.origin.y = top
|
72
76
|
else
|
73
|
-
frame.origin.y = max_height / 2 -
|
77
|
+
frame.origin.y = max_height / 2 - temp_height / 2
|
74
78
|
end
|
75
|
-
frame.size.height = height
|
79
|
+
frame.size.height = height || 0.0
|
76
80
|
|
77
81
|
frame
|
78
82
|
rescue => e
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# TODO: make it part of Sections
|
2
|
-
motion_require '../support/
|
2
|
+
motion_require '../support/mp_table_cell_with_section'
|
3
|
+
motion_require '../support/mp_collection_cell_with_section'
|
3
4
|
motion_require '../support/mp_spinner'
|
4
5
|
motion_require '../support/mp_button'
|
5
6
|
motion_require '../support/mp_label'
|
@@ -17,7 +18,7 @@ module MotionPrime
|
|
17
18
|
else
|
18
19
|
view_stack.last.bounds
|
19
20
|
end
|
20
|
-
builder = ViewBuilder.new(klass, options)
|
21
|
+
builder = ViewBuilder.new(klass, options.merge(parent_bounds: parent_bounds))
|
21
22
|
options = builder.options.merge(calculate_frame: true, parent_bounds: parent_bounds)
|
22
23
|
view = builder.view
|
23
24
|
insert_index = options.delete(:at_index)
|
@@ -51,8 +52,9 @@ module MotionPrime
|
|
51
52
|
base.class_eval do
|
52
53
|
[::UIActionSheet, ::UIActivityIndicatorView, ::MPButton, ::UIDatePicker, ::UIImageView, ::MPLabel,
|
53
54
|
::UIPageControl, ::UIPickerView, ::UIProgressView, ::UIScrollView, ::UISearchBar, ::UISegmentedControl,
|
54
|
-
::UISlider, ::UIStepper, ::UISwitch, ::UITabBar, ::
|
55
|
-
::
|
55
|
+
::UISlider, ::UIStepper, ::UISwitch, ::UITabBar, ::UICollectionView, ::UITableView, ::UITableViewCell,
|
56
|
+
::MPTextField, ::MPTextView, ::UIToolbar, ::UIWebView, ::UINavigationBar,
|
57
|
+
::MPTableCellWithSection, ::MPCollectionCellWithSection, ::MBProgressHUD, ::MPSpinner].each do |klass|
|
56
58
|
|
57
59
|
shorthand = "#{klass}"[2..-1].underscore.to_sym
|
58
60
|
|
@@ -86,6 +86,16 @@ module MotionPrime
|
|
86
86
|
view.tableFooterView = UIView.new
|
87
87
|
view
|
88
88
|
},
|
89
|
+
'UICollectionView' => Proc.new{|klass, options|
|
90
|
+
unless layout = options.delete(:layout)
|
91
|
+
layout = UICollectionViewFlowLayout.alloc.init
|
92
|
+
total_width = options[:parent_bounds].size.width / (options.delete(:grid_size) || 4)
|
93
|
+
width = total_width - layout.minimumInteritemSpacing
|
94
|
+
layout.setItemSize CGSizeMake(width, options.delete(:item_height) || 100)
|
95
|
+
end
|
96
|
+
view = klass.alloc.initWithFrame CGRectZero, collectionViewLayout: layout
|
97
|
+
view
|
98
|
+
},
|
89
99
|
'UITableViewCell' => Proc.new{|klass, options|
|
90
100
|
style = options.delete(:style) || UITableViewCellStyleDefault
|
91
101
|
if options[:has_drawn_content]
|
@@ -5,6 +5,8 @@ module MotionPrime
|
|
5
5
|
include HasClassFactory
|
6
6
|
include ElementTextMixin
|
7
7
|
|
8
|
+
ORDER = %w[font placeholder_font text]
|
9
|
+
|
8
10
|
attr_reader :view, :options
|
9
11
|
|
10
12
|
def initialize(view, parent_bounds = CGRectZero, options = {})
|
@@ -46,7 +48,7 @@ module MotionPrime
|
|
46
48
|
def prepare_options!
|
47
49
|
if options[:size_to_fit]
|
48
50
|
options[:line_break_mode] ||= :word_wrap
|
49
|
-
options[:number_of_lines] ||= 0
|
51
|
+
options[:number_of_lines] ||= 0 if view.is_a?(UILabel)
|
50
52
|
end
|
51
53
|
|
52
54
|
if options.slice(:html, :line_spacing, :line_height, :underline, :fragment_color).any?
|
@@ -63,6 +65,8 @@ module MotionPrime
|
|
63
65
|
end
|
64
66
|
extract_font_options(options)
|
65
67
|
extract_font_options(options, 'placeholder')
|
68
|
+
|
69
|
+
@options = Hash[options.sort_by { |k,v| ORDER.index(k.to_s).to_i }]
|
66
70
|
end
|
67
71
|
|
68
72
|
def extract_font_options(options, prefix = nil)
|
@@ -1,4 +1,8 @@
|
|
1
1
|
describe MotionPrime::FilterMixin do
|
2
|
+
before do
|
3
|
+
@subject = MotionPrime::FilterMixin.new
|
4
|
+
end
|
5
|
+
|
2
6
|
def data
|
3
7
|
model_stub = Struct.new(:info, :id) # :id is used for sorting
|
4
8
|
data_array.map do |item|
|
@@ -11,15 +15,15 @@ describe MotionPrime::FilterMixin do
|
|
11
15
|
end
|
12
16
|
|
13
17
|
it "should filter array by inclusion" do
|
14
|
-
|
18
|
+
@subject.filter_array(data, {id: %w[4 5]}).count.should.equal 2
|
15
19
|
end
|
16
20
|
|
17
21
|
it "should find a single record (case sensitive)" do
|
18
|
-
|
22
|
+
@subject.filter_array(data, {id: 4, name: 'iPhone'}).count.should.equal 1
|
19
23
|
end
|
20
24
|
|
21
25
|
it "order filtered records" do
|
22
|
-
result =
|
26
|
+
result = @subject.filter_array(data, {id: %w[4 5]}, sort: {id: :desc})
|
23
27
|
result.first[:id].should.equal 5
|
24
28
|
end
|
25
29
|
end
|