motion-prime 0.1.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.
- data/.gitignore +17 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +83 -0
- data/README.md +67 -0
- data/Rakefile +23 -0
- data/app/app_delegate.rb +5 -0
- data/doc/SECTION.md +7 -0
- data/doc/STYLE.md +39 -0
- data/files/Gemfile +3 -0
- data/files/Rakefile +16 -0
- data/files/app/app_delegate.rb +4 -0
- data/files/app/screens/application_screen.rb +3 -0
- data/lib/motion-prime.rb +14 -0
- data/lib/view_styler.rb +141 -0
- data/motion-prime.gemspec +27 -0
- data/motion-prime/app_delegate.rb +56 -0
- data/motion-prime/elements/base.rb +94 -0
- data/motion-prime/elements/button.rb +7 -0
- data/motion-prime/elements/draw.rb +56 -0
- data/motion-prime/elements/draw/image.rb +43 -0
- data/motion-prime/elements/draw/label.rb +13 -0
- data/motion-prime/elements/image.rb +14 -0
- data/motion-prime/elements/label.rb +20 -0
- data/motion-prime/elements/text_field.rb +7 -0
- data/motion-prime/elements/text_view.rb +7 -0
- data/motion-prime/helpers/has_authorization.rb +10 -0
- data/motion-prime/helpers/has_search_bar.rb +25 -0
- data/motion-prime/models/base.rb +220 -0
- data/motion-prime/screens/_aliases_mixin.rb +32 -0
- data/motion-prime/screens/_base_mixin.rb +119 -0
- data/motion-prime/screens/_navigation_bar_mixin.rb +57 -0
- data/motion-prime/screens/_navigation_mixin.rb +118 -0
- data/motion-prime/screens/_orientations_mixin.rb +39 -0
- data/motion-prime/screens/base_screen.rb +22 -0
- data/motion-prime/screens/sidebar_container_screen.rb +58 -0
- data/motion-prime/sections/base.rb +101 -0
- data/motion-prime/sections/draw.rb +62 -0
- data/motion-prime/sections/form.rb +103 -0
- data/motion-prime/sections/form/base_field_section.rb +26 -0
- data/motion-prime/sections/form/password_field_section.rb +33 -0
- data/motion-prime/sections/form/select_field_section.rb +40 -0
- data/motion-prime/sections/form/string_field_section.rb +32 -0
- data/motion-prime/sections/form/submit_field_section.rb +20 -0
- data/motion-prime/sections/form/text_field_section.rb +33 -0
- data/motion-prime/sections/table.rb +97 -0
- data/motion-prime/sections/table/refresh_mixin.rb +13 -0
- data/motion-prime/styles/forms.rb +93 -0
- data/motion-prime/support/_key_value_store.rb +10 -0
- data/motion-prime/support/dm_button.rb +22 -0
- data/motion-prime/support/dm_cell_with_section.rb +12 -0
- data/motion-prime/support/dm_text_field.rb +30 -0
- data/motion-prime/support/dm_text_view.rb +93 -0
- data/motion-prime/support/dm_view_controller.rb +50 -0
- data/motion-prime/support/dm_view_with_section.rb +11 -0
- data/motion-prime/support/navigation_controller.rb +4 -0
- data/motion-prime/support/ui_search_bar_custom.rb +10 -0
- data/motion-prime/support/ui_view.rb +59 -0
- data/motion-prime/version.rb +3 -0
- data/motion-prime/views/layout.rb +45 -0
- data/motion-prime/views/styles.rb +44 -0
- data/motion-prime/views/view_builder.rb +80 -0
- data/motion-prime/views/view_styler.rb +141 -0
- data/resources/Default-568h@2x.png +0 -0
- data/spec/main_spec.rb +9 -0
- metadata +245 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
motion_require './table/refresh_mixin'
|
2
|
+
module MotionPrime
|
3
|
+
class TableSection < BaseSection
|
4
|
+
include TableSectionRefreshMixin
|
5
|
+
include HasSearchBar
|
6
|
+
|
7
|
+
attr_accessor :table_view
|
8
|
+
before_render :render_table
|
9
|
+
|
10
|
+
def table_data
|
11
|
+
[]
|
12
|
+
end
|
13
|
+
|
14
|
+
def data
|
15
|
+
@data ||= begin
|
16
|
+
table_data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def reload_data
|
21
|
+
@data = nil
|
22
|
+
@data_stamp = Time.now.to_i
|
23
|
+
table_view.reloadData
|
24
|
+
end
|
25
|
+
|
26
|
+
def render_table
|
27
|
+
@data_stamp = Time.now.to_i
|
28
|
+
self.table_view = screen.table_view(styles: [:base_table, name.to_sym], delegate: self, data_source: self).view
|
29
|
+
end
|
30
|
+
|
31
|
+
def render_cell(index, table)
|
32
|
+
cell = cached_cell(index)
|
33
|
+
return cell if cell
|
34
|
+
item = data[index.row]
|
35
|
+
|
36
|
+
# define default styles for cell
|
37
|
+
styles = [:"#{name}_cell"]
|
38
|
+
if item.respond_to?(:container_styles) && item.container_styles.present?
|
39
|
+
styles += Array.wrap(item.container_styles)
|
40
|
+
end
|
41
|
+
if item.respond_to?(:name) && item.name.present?
|
42
|
+
styles += [item.name.to_sym]
|
43
|
+
end
|
44
|
+
|
45
|
+
# DrawSection allows as to draw inside the cell view, so we can setup
|
46
|
+
# to use cell view as container
|
47
|
+
if item.is_a?(MotionPrime::DrawSection)
|
48
|
+
item.render(to: screen, as: :cell,
|
49
|
+
styles: [:base_table_cell] + styles,
|
50
|
+
reuse_identifier: cell_name(table, index)
|
51
|
+
)
|
52
|
+
else
|
53
|
+
screen.table_view_cell styles: [:base_table_cell] + styles, reuse_identifier: cell_name(table, index) do
|
54
|
+
item.render(to: screen)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def on_click(table, index)
|
60
|
+
end
|
61
|
+
|
62
|
+
def cell_name(table, index)
|
63
|
+
record = data[index.row]
|
64
|
+
if record && record.model &&
|
65
|
+
record.model.respond_to?(:id) && record.model.id.present?
|
66
|
+
"cell_#{record.model.id}_#{@data_stamp}"
|
67
|
+
else
|
68
|
+
"cell_#{index.section}_#{index.row}_#{@data_stamp}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def cached_cell(index, table = nil)
|
73
|
+
table ||= self.table_view
|
74
|
+
table.dequeueReusableCellWithIdentifier(cell_name(table, index))
|
75
|
+
end
|
76
|
+
|
77
|
+
# ALIASES
|
78
|
+
# ---------------------
|
79
|
+
|
80
|
+
def tableView(table, cellForRowAtIndexPath:index)
|
81
|
+
cell = cached_cell(index, table) || render_cell(index, table)
|
82
|
+
cell.is_a?(UIView) ? cell : cell.view
|
83
|
+
end
|
84
|
+
|
85
|
+
def tableView(table, numberOfRowsInSection:section)
|
86
|
+
data.length
|
87
|
+
end
|
88
|
+
|
89
|
+
def tableView(table, didSelectRowAtIndexPath:index)
|
90
|
+
on_click(table, index)
|
91
|
+
end
|
92
|
+
|
93
|
+
def tableView(table, heightForRowAtIndexPath:index)
|
94
|
+
data[index.row].container_height
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module TableSectionRefreshMixin
|
3
|
+
def add_pull_to_refresh(&block)
|
4
|
+
table_view.addPullToRefreshWithActionHandler(block)
|
5
|
+
screen.setup table_view.pullToRefreshView, styles: [:base_pull_to_refresh]
|
6
|
+
end
|
7
|
+
|
8
|
+
def fisnish_pull_to_refresh
|
9
|
+
reload_data
|
10
|
+
table_view.pullToRefreshView.stopAnimating
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
motion_require '../views/styles.rb'
|
2
|
+
MotionPrime::Styles.define :base do
|
3
|
+
# basic table styles
|
4
|
+
# ----------
|
5
|
+
style :table,
|
6
|
+
top: 0,
|
7
|
+
left: 0,
|
8
|
+
width: 320,
|
9
|
+
bottom: 0
|
10
|
+
|
11
|
+
# basic form styles
|
12
|
+
# ----------
|
13
|
+
style :form,
|
14
|
+
width: 260,
|
15
|
+
left: 30,
|
16
|
+
top: 0,
|
17
|
+
right: 30,
|
18
|
+
bottom: 0,
|
19
|
+
background_color: :clear,
|
20
|
+
separator_color: :clear,
|
21
|
+
scroll_enabled: true
|
22
|
+
|
23
|
+
style :form_field,
|
24
|
+
selection_style: UITableViewCellSelectionStyleNone
|
25
|
+
|
26
|
+
# available options for string label:
|
27
|
+
# @background_color: COLOR
|
28
|
+
# @text_color: COLOR
|
29
|
+
style :field_label,
|
30
|
+
background_color: :clear,
|
31
|
+
text_color: :gray,
|
32
|
+
top: 6,
|
33
|
+
height: 20,
|
34
|
+
left: 0,
|
35
|
+
right: 0,
|
36
|
+
font: proc { APP_CONFIG[:css_font_base].uifont(12) },
|
37
|
+
size_to_fit: true
|
38
|
+
|
39
|
+
# available options for input:
|
40
|
+
# @layer: @border_width: FLOAT
|
41
|
+
# @layer: @border_color: COLOR
|
42
|
+
# @background_color: COLOR
|
43
|
+
# @background_image: PATH_TO_FILE
|
44
|
+
style :field_input,
|
45
|
+
layer: {
|
46
|
+
border_width: 1,
|
47
|
+
border_color: :gray
|
48
|
+
},
|
49
|
+
font: proc { APP_CONFIG[:css_font_base].uifont(16) },
|
50
|
+
placeholder_font: proc { APP_CONFIG[:css_font_base].uifont(16) },
|
51
|
+
background_color: :white,
|
52
|
+
left: 0,
|
53
|
+
right: 0,
|
54
|
+
top: 30,
|
55
|
+
bottom: 0,
|
56
|
+
padding_top: 4
|
57
|
+
|
58
|
+
# available options for submit button:
|
59
|
+
# @button_type: :rounded, :custom
|
60
|
+
# @background_color: COLOR
|
61
|
+
# @background_image: PATH_TO_FILE
|
62
|
+
style :submit_button,
|
63
|
+
background_color: :gray,
|
64
|
+
left: 0,
|
65
|
+
right: 0,
|
66
|
+
top: 10,
|
67
|
+
height: 44,
|
68
|
+
title_color: :white
|
69
|
+
|
70
|
+
style :select_field_button,
|
71
|
+
background_color: :white,
|
72
|
+
left: 0,
|
73
|
+
right: 0,
|
74
|
+
top: 30,
|
75
|
+
height: 36,
|
76
|
+
title_color: 0x16759a,
|
77
|
+
title_shadow_color: :white,
|
78
|
+
contentHorizontalAlignment: UIControlContentHorizontalAlignmentLeft,
|
79
|
+
layer: {
|
80
|
+
border_color: :gray,
|
81
|
+
border_width: 1
|
82
|
+
},
|
83
|
+
title_color: :gray,
|
84
|
+
title_label: {
|
85
|
+
font: proc { APP_CONFIG[:css_font_base].uifont(16) }
|
86
|
+
}
|
87
|
+
style :select_field_arrow,
|
88
|
+
image: "images/forms/select_arrow.png",
|
89
|
+
top: 42,
|
90
|
+
right: 5,
|
91
|
+
width: 9,
|
92
|
+
height: 14
|
93
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class DMButton < UIButton
|
2
|
+
include MotionPrime::KeyValueStore
|
3
|
+
attr_accessor :paddingLeft, :paddingTop, :padding
|
4
|
+
|
5
|
+
def setTitle(value)
|
6
|
+
setTitle value, forState: UIControlStateNormal
|
7
|
+
end
|
8
|
+
|
9
|
+
def drawPadding(rect)
|
10
|
+
padding_left = self.paddingLeft || self.padding || 5
|
11
|
+
padding_top = self.paddingTop || self.padding || 0
|
12
|
+
self.setTitleEdgeInsets UIEdgeInsetsMake(
|
13
|
+
padding_top, padding_left,
|
14
|
+
padding_top, padding_left
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def drawRect(rect)
|
19
|
+
drawPadding(rect)
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# This class have some modifications for UITextField:
|
2
|
+
# * support padding, padding_left, padding_right options
|
3
|
+
# * support placeholder_color, placeholder_font options
|
4
|
+
class DMTextField < UITextField
|
5
|
+
include MotionPrime::KeyValueStore
|
6
|
+
|
7
|
+
attr_accessor :paddingLeft, :paddingTop, :padding,
|
8
|
+
:placeholderColor, :placeholderFont
|
9
|
+
|
10
|
+
# placeholder position
|
11
|
+
def textRectForBounds(bounds)
|
12
|
+
padding_left = self.paddingLeft || self.padding || 5
|
13
|
+
padding_top = self.paddingTop || self.padding || 3
|
14
|
+
CGRectInset(bounds, padding_left, padding_top)
|
15
|
+
end
|
16
|
+
|
17
|
+
# text position
|
18
|
+
def editingRectForBounds(bounds)
|
19
|
+
padding_left = self.paddingLeft || self.padding || 5
|
20
|
+
padding_top = self.paddingTop || self.padding || 3
|
21
|
+
CGRectInset(bounds, padding_left, padding_top)
|
22
|
+
end
|
23
|
+
|
24
|
+
def drawPlaceholderInRect(rect)
|
25
|
+
color = self.placeholderColor || :gray.uicolor
|
26
|
+
color.setFill
|
27
|
+
font = self.placeholderFont || self.font || :system.uifont(16)
|
28
|
+
self.placeholder.drawInRect(rect, withFont: font)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# This class have some modifications for UITextView:
|
2
|
+
# * support padding, padding_left, padding_right options
|
3
|
+
# * support placeholder, placeholder_color, placeholder_font options
|
4
|
+
class DMTextView < UITextView
|
5
|
+
include MotionPrime::KeyValueStore
|
6
|
+
DEFAULT_PADDING_LEFT = 7
|
7
|
+
|
8
|
+
attr_accessor :paddingLeft, :paddingTop, :padding,
|
9
|
+
:placeholderColor, :placeholderFont, :placeholder
|
10
|
+
|
11
|
+
def drawPadding(rect)
|
12
|
+
# add padding to UITextView
|
13
|
+
padding_left = 0 - DEFAULT_PADDING_LEFT + (self.paddingLeft || self.padding || 5)
|
14
|
+
padding_top = 0 - DEFAULT_PADDING_LEFT + (self.paddingTop || self.padding || 5)
|
15
|
+
padding = UIEdgeInsetsMake(
|
16
|
+
padding_top, padding_left,
|
17
|
+
padding_top, padding_left
|
18
|
+
)
|
19
|
+
self.contentInset = padding
|
20
|
+
|
21
|
+
# must change frame before bounds because the text wrap is reformatted based on frame,
|
22
|
+
# don't include the top and bottom insets
|
23
|
+
insetFrame = UIEdgeInsetsInsetRect(frame, UIEdgeInsetsMake(0, padding.left, 0, padding.right))
|
24
|
+
# offset frame back to original x
|
25
|
+
offsetX = frame.origin.x - (insetFrame.origin.x - ( padding.left + padding.right ) / 2)
|
26
|
+
insetFrame = CGRectApplyAffineTransform(insetFrame, CGAffineTransformMakeTranslation(offsetX, 0))
|
27
|
+
self.frame = insetFrame
|
28
|
+
self.bounds = UIEdgeInsetsInsetRect(self.bounds, UIEdgeInsetsMake(0, -padding.left, 0, -padding.right))
|
29
|
+
end
|
30
|
+
|
31
|
+
def drawPlaceholder(rect)
|
32
|
+
padding_left = self.paddingLeft || self.padding || 5
|
33
|
+
padding_top = self.paddingTop || self.padding || 5
|
34
|
+
padding = UIEdgeInsetsMake(
|
35
|
+
padding_top, padding_left,
|
36
|
+
padding_top, padding_left
|
37
|
+
)
|
38
|
+
if self.placeholder && self.text.blank?
|
39
|
+
color = self.placeholderColor || :gray.uicolor
|
40
|
+
color.setFill
|
41
|
+
font = self.placeholderFont || self.font || :system.uifont(16)
|
42
|
+
|
43
|
+
color.setFill
|
44
|
+
rect = CGRectMake(
|
45
|
+
rect.origin.x + padding_left,
|
46
|
+
rect.origin.y + padding_top,
|
47
|
+
self.frame.size.width - padding_left,
|
48
|
+
self.frame.size.height - padding_top
|
49
|
+
)
|
50
|
+
placeholder.drawInRect(rect, withFont: font)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def drawRect(rect)
|
55
|
+
drawPadding(rect)
|
56
|
+
drawPlaceholder(rect)
|
57
|
+
super
|
58
|
+
end
|
59
|
+
|
60
|
+
def initPlaceholder
|
61
|
+
NSNotificationCenter.defaultCenter.addObserver(self,
|
62
|
+
selector: :textChanged, name: UITextViewTextDidChangeNotification, object: self
|
63
|
+
)
|
64
|
+
@shouldDrawPlaceholder = placeholder && self.text.blank?
|
65
|
+
end
|
66
|
+
|
67
|
+
def textChanged
|
68
|
+
updatePlaceholderDraw
|
69
|
+
end
|
70
|
+
|
71
|
+
def updatePlaceholderDraw
|
72
|
+
prev = @shouldDrawPlaceholder
|
73
|
+
@shouldDrawPlaceholder = placeholder && self.text.blank?
|
74
|
+
if prev != @shouldDrawPlaceholder
|
75
|
+
self.setNeedsDisplay
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# custom initializer
|
80
|
+
def initWithCoder(aDecoder)
|
81
|
+
if super
|
82
|
+
initPlaceholder
|
83
|
+
end
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def initWithFrame(frame)
|
88
|
+
if super
|
89
|
+
initPlaceholder
|
90
|
+
end
|
91
|
+
self
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class DMViewController < UIViewController
|
2
|
+
def self.new(args = {})
|
3
|
+
s = self.alloc.initWithNibName(nil, bundle:nil)
|
4
|
+
s.on_create(args) if s.respond_to?(:on_create)
|
5
|
+
s
|
6
|
+
end
|
7
|
+
|
8
|
+
def viewDidLoad
|
9
|
+
super
|
10
|
+
self.view_did_load if self.respond_to?(:view_did_load)
|
11
|
+
end
|
12
|
+
|
13
|
+
def viewWillAppear(animated)
|
14
|
+
super
|
15
|
+
self.view_will_appear(animated) if self.respond_to?("view_will_appear:")
|
16
|
+
end
|
17
|
+
|
18
|
+
def viewDidAppear(animated)
|
19
|
+
super
|
20
|
+
self.view_did_appear(animated) if self.respond_to?("view_did_appear:")
|
21
|
+
end
|
22
|
+
|
23
|
+
def viewWillDisappear(animated)
|
24
|
+
self.view_will_disappear(animated) if self.respond_to?("view_will_disappear:")
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def viewDidDisappear(animated)
|
29
|
+
if self.respond_to?("view_did_disappear:")
|
30
|
+
self.view_did_disappear(animated)
|
31
|
+
end
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def shouldAutorotateToInterfaceOrientation(orientation)
|
36
|
+
self.should_rotate(orientation)
|
37
|
+
end
|
38
|
+
|
39
|
+
def shouldAutorotate
|
40
|
+
self.should_autorotate
|
41
|
+
end
|
42
|
+
|
43
|
+
def willRotateToInterfaceOrientation(orientation, duration:duration)
|
44
|
+
self.will_rotate(orientation, duration)
|
45
|
+
end
|
46
|
+
|
47
|
+
def didRotateFromInterfaceOrientation(orientation)
|
48
|
+
self.on_rotate
|
49
|
+
end
|
50
|
+
end
|