motion-prime 0.3.2 → 0.3.3
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 +8 -8
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +1 -1
- data/README.md +10 -0
- data/doc/code/getting_started.rb +61 -0
- data/doc/docs/docco.css +500 -0
- data/doc/docs/getting_started.html +177 -0
- data/doc/docs/public/fonts/aller-bold.eot +0 -0
- data/doc/docs/public/fonts/aller-bold.ttf +0 -0
- data/doc/docs/public/fonts/aller-bold.woff +0 -0
- data/doc/docs/public/fonts/aller-light.eot +0 -0
- data/doc/docs/public/fonts/aller-light.ttf +0 -0
- data/doc/docs/public/fonts/aller-light.woff +0 -0
- data/doc/docs/public/fonts/novecento-bold.eot +0 -0
- data/doc/docs/public/fonts/novecento-bold.ttf +0 -0
- data/doc/docs/public/fonts/novecento-bold.woff +0 -0
- data/doc/docs/public/stylesheets/normalize.css +375 -0
- data/files/app/sections/sidebar/action.rb +1 -1
- data/motion-prime/app_delegate.rb +8 -2
- data/motion-prime/elements/_content_padding_mixin.rb +12 -12
- data/motion-prime/elements/_content_text_mixin.rb +65 -0
- data/motion-prime/elements/base.rb +51 -19
- data/motion-prime/elements/button.rb +1 -1
- data/motion-prime/elements/draw.rb +26 -113
- data/motion-prime/elements/draw/_draw_background_mixin.rb +26 -0
- data/motion-prime/elements/draw/image.rb +10 -1
- data/motion-prime/elements/draw/label.rb +61 -42
- data/motion-prime/elements/draw/view.rb +14 -0
- data/motion-prime/elements/error_message.rb +1 -1
- data/motion-prime/elements/label.rb +1 -1
- data/motion-prime/elements/text_field.rb +2 -2
- data/motion-prime/elements/text_view.rb +3 -0
- data/motion-prime/helpers/has_style_chain_builder.rb +1 -1
- data/motion-prime/helpers/has_styles.rb +28 -0
- data/motion-prime/models/bag.rb +1 -1
- data/motion-prime/models/sync.rb +4 -4
- data/motion-prime/screens/_base_mixin.rb +1 -1
- data/motion-prime/screens/extensions/_navigation_bar_mixin.rb +7 -0
- data/motion-prime/screens/sidebar_container_screen.rb +8 -2
- data/motion-prime/sections/_cell_section_mixin.rb +25 -0
- data/motion-prime/sections/base.rb +17 -16
- data/motion-prime/sections/draw.rb +32 -10
- data/motion-prime/sections/form.rb +27 -17
- data/motion-prime/sections/form/base_field_section.rb +0 -1
- data/motion-prime/sections/form/base_header_section.rb +3 -2
- data/motion-prime/sections/form/password_field_section.rb +1 -1
- data/motion-prime/sections/table.rb +31 -10
- data/motion-prime/sections/table/base_cell_section.rb +1 -22
- data/motion-prime/sections/table/draw_cell_section.rb +5 -0
- data/motion-prime/styles/form.rb +12 -4
- data/motion-prime/support/_key_value_store.rb +0 -2
- data/motion-prime/support/dm_text_field.rb +2 -2
- data/motion-prime/support/tab_bar_controller.rb +28 -0
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/_frame_calculator_mixin.rb +75 -0
- data/motion-prime/views/view_styler.rb +36 -94
- metadata +23 -4
- data/motion-prime/elements/_field_dimensions_mixin.rb +0 -59
- data/motion-prime/elements/_text_dimensions_mixin.rb +0 -35
@@ -1,66 +1,85 @@
|
|
1
1
|
motion_require '../draw.rb'
|
2
2
|
module MotionPrime
|
3
3
|
class LabelDrawElement < DrawElement
|
4
|
-
include
|
5
|
-
include
|
4
|
+
include ElementContentTextMixin
|
5
|
+
include DrawBackgroundMixin
|
6
|
+
|
7
|
+
def default_padding_for(side)
|
8
|
+
return super unless side.to_s == 'top'
|
9
|
+
@padding_top || 0
|
10
|
+
end
|
6
11
|
|
7
12
|
def draw_in(rect)
|
13
|
+
return if computed_options[:hidden]
|
14
|
+
size_to_fit_if_needed or set_text_position
|
8
15
|
options = computed_options
|
9
|
-
return if options[:hidden]
|
10
16
|
|
11
|
-
|
17
|
+
# render background and border
|
18
|
+
background_rect = CGRectMake(computed_left, computed_top, computed_outer_width, computed_outer_height)
|
19
|
+
draw_background_in(background_rect, options)
|
12
20
|
|
13
|
-
# render
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
# render text
|
22
|
+
color = (options[:text_color] || :black).uicolor
|
23
|
+
font = (options[:font] || :system).uifont
|
24
|
+
alignment = (options.has_key?(:text_alignment) ? options[:text_alignment] : :left).uitextalignment
|
25
|
+
line_break_mode = (options.has_key?(:line_break_mode) ? options[:line_break_mode] : :wordwrap).uilinebreakmode
|
26
|
+
label_text = options[:text].to_s
|
19
27
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
CGContextSetStrokeColorWithColor(context, bg_color.uicolor.cgcolor)
|
24
|
-
CGContextSetFillColorWithColor(context, bg_color.uicolor.cgcolor)
|
25
|
-
bezierPath.stroke
|
26
|
-
bezierPath.fill
|
27
|
-
else
|
28
|
-
bg_color.uicolor.setFill
|
29
|
-
UIRectFill(rect)
|
30
|
-
end
|
28
|
+
top_left_corner = CGPointMake(computed_inner_left, computed_inner_top)
|
29
|
+
if options[:number_of_lines].to_i.zero?
|
30
|
+
rect = CGRectMake(*top_left_corner.to_a, computed_width, computed_height)
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
if options[:line_spacing] || options[:underline]
|
34
|
+
# attributed string
|
35
|
+
paragrahStyle = NSMutableParagraphStyle.alloc.init
|
36
|
+
|
37
|
+
paragrahStyle.setLineSpacing(options[:line_spacing]) if options[:line_spacing]
|
38
|
+
paragrahStyle.setAlignment(alignment)
|
39
|
+
paragrahStyle.setLineBreakMode(line_break_mode)
|
40
|
+
attributes = {}
|
41
|
+
attributes[NSParagraphStyleAttributeName] = paragrahStyle
|
42
|
+
attributes[NSForegroundColorAttributeName] = color
|
43
|
+
attributes[NSFontAttributeName] = font
|
44
|
+
|
45
|
+
label_text = NSMutableAttributedString.alloc.initWithString(label_text, attributes: attributes)
|
46
|
+
if underline_range = options[:underline]
|
47
|
+
# FIXME
|
48
|
+
# label_text = NSMutableAttributedString.alloc.initWithAttributedString(label_text)
|
49
|
+
# label_text.addAttributes({NSUnderlineStyleAttributeName => NSUnderlineStyleSingle}, range: underline_range)
|
50
|
+
end
|
51
|
+
|
52
|
+
rect ? label_text.drawInRect(rect) : label_text.drawAtPoint(top_left_corner)
|
42
53
|
else
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
)
|
54
|
+
# regular string
|
55
|
+
color.set
|
56
|
+
if rect
|
57
|
+
label_text.drawInRect(rect,
|
58
|
+
withFont: font,
|
59
|
+
lineBreakMode: line_break_mode,
|
60
|
+
alignment: alignment)
|
61
|
+
else
|
62
|
+
label_text.drawAtPoint(top_left_corner, withFont: font)
|
63
|
+
end
|
54
64
|
end
|
55
65
|
end
|
56
66
|
|
57
67
|
def size_to_fit_if_needed
|
58
68
|
if computed_options[:size_to_fit]
|
59
|
-
@computed_options[:width]
|
69
|
+
@computed_options[:width] ||= content_outer_width
|
60
70
|
if computed_options[:width]
|
61
71
|
@computed_options[:height] = content_outer_height
|
62
72
|
end
|
63
73
|
reset_computed_values
|
74
|
+
true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_text_position
|
79
|
+
if computed_options.slice(:padding_top, :padding_bottom, :padding).none?
|
80
|
+
computed_options[:width] ||= computed_width
|
81
|
+
@padding_top = (computed_outer_height - content_height)/2
|
82
|
+
# @padding_top += 1 unless @padding_top.zero?
|
64
83
|
end
|
65
84
|
end
|
66
85
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
motion_require '../draw.rb'
|
2
|
+
module MotionPrime
|
3
|
+
class ViewDrawElement < DrawElement
|
4
|
+
include DrawBackgroundMixin
|
5
|
+
|
6
|
+
def draw_in(rect)
|
7
|
+
return if computed_options[:hidden]
|
8
|
+
options = computed_options
|
9
|
+
|
10
|
+
background_rect = CGRectMake(computed_left, computed_top, computed_outer_width, computed_outer_height)
|
11
|
+
draw_background_in(background_rect, options)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class LabelElement < BaseElement
|
3
3
|
include MotionPrime::ElementContentPaddingMixin
|
4
|
-
include MotionPrime::
|
4
|
+
include MotionPrime::ElementContentTextMixin
|
5
5
|
|
6
6
|
before_render :size_to_fit_if_needed
|
7
7
|
after_render :size_to_fit
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
module HasStyleChainBuilder
|
3
3
|
def build_styles_chain(base_styles, suffixes)
|
4
|
-
[*base_styles].
|
4
|
+
[*base_styles].compact.map(&:to_s).uniq.map { |base_style| [*suffixes].compact.map(&:to_s).uniq.map { |suffix| [base_style, suffix].join('_').to_sym } }.flatten
|
5
5
|
end
|
6
6
|
end
|
7
7
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module HasStyles
|
3
|
+
def prepare_gradient(options)
|
4
|
+
colors = options[:colors].map(&:uicolor).map(&:cgcolor)
|
5
|
+
locations = options[:locations] if options[:locations]
|
6
|
+
|
7
|
+
if self.is_a?(DrawSection)
|
8
|
+
color_space = CGColorSpaceCreateDeviceRGB()
|
9
|
+
locations_pointer = Pointer.new(:float, 2)
|
10
|
+
locations.each_with_index { |loc, id| locations_pointer[id] = loc }
|
11
|
+
gradient = CGGradientCreateWithColors(color_space, colors, locations_pointer)
|
12
|
+
# CGColorSpaceRelease(color_space)
|
13
|
+
else
|
14
|
+
gradient = CAGradientLayer.layer
|
15
|
+
|
16
|
+
gradient.frame = if options[:frame_width]
|
17
|
+
CGRectMake(options[:frame_x].to_f, options[:frame_y].to_f, options[:frame_width].to_f, options[:frame_height].to_f)
|
18
|
+
else
|
19
|
+
options[:parent_frame] || CGRectZero
|
20
|
+
end
|
21
|
+
|
22
|
+
gradient.colors = colors
|
23
|
+
gradient.locations = locations
|
24
|
+
end
|
25
|
+
gradient
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/motion-prime/models/bag.rb
CHANGED
@@ -50,7 +50,7 @@ module MotionPrime
|
|
50
50
|
object.map { |entity| prepare_for_store(entity) }.compact
|
51
51
|
else
|
52
52
|
object.bag_key = self.key
|
53
|
-
if object.id.present? && self.store && self.find(id: object.id).any?
|
53
|
+
if object.id.present? && self.store && self.find(id: object.id, bag_key: self.key).any?
|
54
54
|
raise StoreError, "duplicated item added `#{object.class_name_without_kvo}` with `id` = #{object.id}"
|
55
55
|
end
|
56
56
|
object
|
data/motion-prime/models/sync.rb
CHANGED
@@ -38,6 +38,9 @@ module MotionPrime
|
|
38
38
|
should_fetch
|
39
39
|
end
|
40
40
|
|
41
|
+
should_fetch = persisted? if should_fetch.nil?
|
42
|
+
should_update ||= new_record? unless should_fetch
|
43
|
+
|
41
44
|
method = sync_options[:method]
|
42
45
|
method ||= if should_update
|
43
46
|
persisted? ? :put : :post
|
@@ -51,9 +54,6 @@ module MotionPrime
|
|
51
54
|
should_update = false
|
52
55
|
end
|
53
56
|
|
54
|
-
should_fetch = !new_record? if should_fetch.nil?
|
55
|
-
should_update ||= new_record? unless should_fetch
|
56
|
-
|
57
57
|
fetch_with_url url do |data, status_code|
|
58
58
|
save if sync_options[:save]
|
59
59
|
block.call(data, status_code) if use_callback
|
@@ -155,7 +155,7 @@ module MotionPrime
|
|
155
155
|
use_callback = block_given?
|
156
156
|
puts "SYNC: started sync for #{key} in #{self.class_name_without_kvo}"
|
157
157
|
api_client.get normalize_sync_url(options[:sync_url]) do |response, status_code|
|
158
|
-
data = options
|
158
|
+
data = options[:sync_key] && response ? response[options[:sync_key]] : response
|
159
159
|
if data
|
160
160
|
# Update/Create existing records
|
161
161
|
data.each do |attributes|
|
@@ -10,7 +10,7 @@ module MotionPrime
|
|
10
10
|
include MotionPrime::ScreenOrientationsMixin
|
11
11
|
include MotionPrime::ScreenNavigationMixin
|
12
12
|
|
13
|
-
attr_accessor :parent_screen, :modal, :params, :main_section, :options
|
13
|
+
attr_accessor :parent_screen, :modal, :params, :main_section, :options, :tab_bar
|
14
14
|
class_attribute :current_screen
|
15
15
|
|
16
16
|
included do
|
@@ -32,6 +32,13 @@ module MotionPrime
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
def set_navigation_right_image(args = {})
|
36
|
+
url = args.delete(:url)
|
37
|
+
view = add_view(UIImageView, args)
|
38
|
+
view.setImageWithURL NSURL.URLWithString(url), placeholderImage: nil
|
39
|
+
navigationItem.rightBarButtonItem = UIBarButtonItem.alloc.initWithCustomView(view)
|
40
|
+
end
|
41
|
+
|
35
42
|
def create_navigation_button(title, args = {})
|
36
43
|
args[:style] ||= UIBarButtonItemStylePlain
|
37
44
|
args[:target] ||= self
|
@@ -39,7 +39,7 @@ module MotionPrime
|
|
39
39
|
|
40
40
|
def content_controller=(c)
|
41
41
|
controller = prepare_controller(c)
|
42
|
-
if
|
42
|
+
if should_reinit_content?(controller)
|
43
43
|
self.setContentViewController controller
|
44
44
|
else
|
45
45
|
content_controller.viewControllers = [controller]
|
@@ -57,9 +57,15 @@ module MotionPrime
|
|
57
57
|
|
58
58
|
private
|
59
59
|
|
60
|
+
def should_reinit_content?(new_controller)
|
61
|
+
content_controller.nil? ||
|
62
|
+
content_controller.is_a?(TabBarController) ||
|
63
|
+
new_controller.is_a?(TabBarController)
|
64
|
+
end
|
65
|
+
|
60
66
|
def prepare_controller(controller)
|
61
67
|
controller = setup_screen_for_open(controller, {})
|
62
|
-
if
|
68
|
+
if should_reinit_content?(controller)
|
63
69
|
controller.wrap_in_navigation if controller.respond_to?(:wrap_in_navigation)
|
64
70
|
controller.send(:on_screen_load) if controller.respond_to?(:on_screen_load)
|
65
71
|
controller = controller.main_controller if controller.respond_to?(:main_controller)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module CellSectionMixin
|
3
|
+
attr_writer :table
|
4
|
+
|
5
|
+
def table
|
6
|
+
@table ||= options[:table]
|
7
|
+
end
|
8
|
+
|
9
|
+
def section_styles
|
10
|
+
@section_styles ||= table.try(:cell_styles, self) || {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def cell_type
|
14
|
+
@cell_type ||= begin
|
15
|
+
self.is_a?(BaseFieldSection) ? :field : :cell
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def cell_name
|
20
|
+
return name unless table
|
21
|
+
table_name = table.name.gsub('_table', '')
|
22
|
+
name.gsub("#{table_name}_", '')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -23,6 +23,7 @@ module MotionPrime
|
|
23
23
|
define_callbacks :render
|
24
24
|
|
25
25
|
def initialize(options = {})
|
26
|
+
super
|
26
27
|
@options = options
|
27
28
|
@model = options[:model]
|
28
29
|
@name = options[:name] ||= default_name
|
@@ -39,17 +40,25 @@ module MotionPrime
|
|
39
40
|
end
|
40
41
|
|
41
42
|
def container_options
|
42
|
-
@
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
43
|
+
@container_options ||= (style_options.delete(:container) || {}).merge(base_container_options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def base_container_options
|
47
|
+
@base_container_options ||= begin
|
48
|
+
container_options = self.class.container_options.try(:clone) || {}
|
49
|
+
container_options.merge!(options.delete(:container) || {})
|
50
|
+
normalize_options(container_options)
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
54
|
+
def container_height
|
55
|
+
container_options[:height] || DEFAULT_CONTENT_HEIGHT
|
56
|
+
end
|
57
|
+
|
58
|
+
def container_styles
|
59
|
+
base_container_options[:styles]
|
60
|
+
end
|
61
|
+
|
53
62
|
def default_name
|
54
63
|
self.class_name_without_kvo.demodulize.underscore.gsub(/\_section$/, '')
|
55
64
|
end
|
@@ -142,14 +151,6 @@ module MotionPrime
|
|
142
151
|
end
|
143
152
|
end
|
144
153
|
|
145
|
-
def container_height
|
146
|
-
container_options[:height] || DEFAULT_CONTENT_HEIGHT
|
147
|
-
end
|
148
|
-
|
149
|
-
def container_styles
|
150
|
-
container_options[:styles]
|
151
|
-
end
|
152
|
-
|
153
154
|
def on_keyboard_show; end
|
154
155
|
def on_keyboard_hide; end
|
155
156
|
def keyboard_will_show; end
|
@@ -10,6 +10,7 @@ module MotionPrime
|
|
10
10
|
# element :avatar, type: :image, image: 'defaults/avatar.jpg'
|
11
11
|
# end
|
12
12
|
#
|
13
|
+
include HasStyles
|
13
14
|
|
14
15
|
attr_accessor :container_view
|
15
16
|
|
@@ -25,19 +26,21 @@ module MotionPrime
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def render!
|
29
|
+
options = view_style_options
|
30
|
+
options.merge!(section: WeakRef.new(self), background_color: :clear)
|
31
|
+
|
28
32
|
if container_options[:as].to_s == 'cell'
|
29
|
-
@container_view = screen.add_view DMCellWithSection, {
|
30
|
-
|
31
|
-
|
32
|
-
}
|
33
|
+
@container_view = screen.add_view DMCellWithSection, options.merge({
|
34
|
+
reuse_identifier: container_options[:reuse_identifier],
|
35
|
+
parent_view: (table if respond_to?(:table))
|
36
|
+
})
|
33
37
|
else
|
34
|
-
@container_view = screen.add_view DMViewWithSection, {
|
35
|
-
|
36
|
-
width: container_options[:width] || 320,
|
38
|
+
@container_view = screen.add_view DMViewWithSection, options.merge({
|
39
|
+
width: container_options[:width] || 320, # TODO: remove these options (use styles)
|
37
40
|
height: container_options[:height] || 100,
|
38
41
|
top: container_options[:top] || 0,
|
39
42
|
left: container_options[:left] || 0
|
40
|
-
}
|
43
|
+
})
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
@@ -61,9 +64,28 @@ module MotionPrime
|
|
61
64
|
end
|
62
65
|
end
|
63
66
|
|
67
|
+
def view_style_options
|
68
|
+
@view_style_options ||= begin
|
69
|
+
options = Styles.for(container_options[:styles])
|
70
|
+
normalize_options(options)
|
71
|
+
options
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
64
75
|
def draw_background(rect)
|
65
|
-
if
|
66
|
-
|
76
|
+
if gradient_options = view_style_options[:gradient]
|
77
|
+
start_point = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect))
|
78
|
+
end_point = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect))
|
79
|
+
|
80
|
+
context = UIGraphicsGetCurrentContext()
|
81
|
+
# CGContextSaveGState(context)
|
82
|
+
CGContextAddRect(context, rect)
|
83
|
+
CGContextClip(context)
|
84
|
+
gradient = prepare_gradient(gradient_options)
|
85
|
+
CGContextDrawLinearGradient(context, gradient, start_point, end_point, 0)
|
86
|
+
# CGContextRestoreGState(context)
|
87
|
+
elsif background_color = (container_options[:background_color] || view_style_options[:background_color])
|
88
|
+
background_color.uicolor.setFill
|
67
89
|
UIRectFill(rect)
|
68
90
|
end
|
69
91
|
end
|