motion-prime 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +1 -1
- data/ROADMAP.md +9 -4
- data/doc/code/getting_started.rb +1 -2
- data/doc/code/screens.rb +54 -0
- data/doc/docs/getting_started.html +27 -6
- data/doc/docs/screens.html +166 -0
- data/files/Gemfile +1 -1
- data/files/Gemfile.lock +64 -0
- data/files/app/environment.rb +10 -0
- data/files/app/styles/sidebar.rb +3 -10
- data/files/resources/images/menu_button.png +0 -0
- data/files/resources/images/menu_button@2x.png +0 -0
- data/motion-prime/app_delegate.rb +19 -0
- data/motion-prime/core_ext/kernel.rb +4 -0
- data/motion-prime/elements/_content_text_mixin.rb +23 -11
- data/motion-prime/elements/_text_mixin.rb +54 -0
- data/motion-prime/elements/base_element.rb +19 -14
- data/motion-prime/elements/draw.rb +22 -1
- data/motion-prime/elements/draw/_draw_background_mixin.rb +28 -28
- data/motion-prime/elements/draw/image.rb +67 -48
- data/motion-prime/elements/draw/label.rb +59 -49
- data/motion-prime/elements/draw/view.rb +5 -3
- data/motion-prime/helpers/has_style_chain_builder.rb +1 -3
- data/motion-prime/models/association_collection.rb +8 -0
- data/motion-prime/models/finder.rb +8 -0
- data/motion-prime/mp.rb +4 -0
- data/motion-prime/screens/_navigation_mixin.rb +4 -0
- data/motion-prime/screens/base_screen.rb +7 -0
- data/motion-prime/screens/sidebar_container_screen.rb +2 -2
- data/motion-prime/sections/_cell_section_mixin.rb +44 -5
- data/motion-prime/sections/_draw_section_mixin.rb +120 -0
- data/motion-prime/sections/base_section.rb +29 -24
- data/motion-prime/sections/form.rb +48 -65
- data/motion-prime/sections/form/base_field_section.rb +2 -2
- data/motion-prime/sections/table.rb +143 -82
- data/motion-prime/sections/table/table_delegate.rb +48 -0
- data/motion-prime/styles/form.rb +1 -1
- data/motion-prime/support/mp_cell_with_section.rb +6 -2
- data/motion-prime/support/mp_view_with_section.rb +1 -1
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/_frame_calculator_mixin.rb +4 -8
- data/motion-prime/views/layout.rb +1 -0
- data/motion-prime/views/view_styler.rb +3 -12
- metadata +34 -26
- data/motion-prime/sections/_draw_mixin.rb +0 -66
@@ -2,82 +2,92 @@ motion_require '../draw.rb'
|
|
2
2
|
module MotionPrime
|
3
3
|
class LabelDrawElement < DrawElement
|
4
4
|
include ElementContentTextMixin
|
5
|
+
include ElementTextMixin
|
5
6
|
include DrawBackgroundMixin
|
6
7
|
|
7
|
-
def
|
8
|
-
return super unless side.to_s == 'top'
|
9
|
-
@padding_top || 0
|
10
|
-
end
|
11
|
-
|
12
|
-
def draw_in(rect)
|
13
|
-
size_to_fit_if_needed or set_text_position
|
8
|
+
def draw_options
|
14
9
|
options = computed_options
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# render background and border
|
19
|
-
background_rect = CGRectMake(computed_left, computed_top, computed_outer_width, computed_outer_height)
|
20
|
-
draw_background_in(background_rect, options)
|
21
|
-
|
22
|
-
# render text
|
23
|
-
color = (options[:text_color] || :black).uicolor
|
10
|
+
text = (options[:html] || options[:text]).to_s.gsub(/^[\n\r]+/, '')
|
11
|
+
text_color = (options[:text_color] || :black).uicolor
|
24
12
|
font = (options[:font] || :system).uifont
|
25
|
-
|
26
|
-
|
27
|
-
|
13
|
+
|
14
|
+
text_alignment_name = options.has_key?(:text_alignment) ? options[:text_alignment] : :left
|
15
|
+
text_alignment = text_alignment_name.uitextalignment
|
16
|
+
line_break_mode_name = options.has_key?(:line_break_mode) ? options[:line_break_mode] : :tail_truncation
|
17
|
+
line_break_mode = line_break_mode_name.uilinebreakmode
|
28
18
|
|
29
19
|
top_left_corner = CGPointMake(computed_inner_left, computed_inner_top)
|
30
20
|
if options[:number_of_lines].to_i.zero?
|
31
|
-
|
21
|
+
inner_rect = CGRectMake(*top_left_corner.to_a, computed_width, computed_height)
|
32
22
|
end
|
23
|
+
super.merge({
|
24
|
+
text: text,
|
25
|
+
is_html: options[:html].present?,
|
26
|
+
text_color: text_color,
|
27
|
+
font: font,
|
28
|
+
text_alignment_name: text_alignment_name,
|
29
|
+
text_alignment: text_alignment,
|
30
|
+
line_break_mode_name: line_break_mode_name,
|
31
|
+
line_break_mode: line_break_mode,
|
32
|
+
line_spacing: options[:line_spacing],
|
33
|
+
underline: options[:underline],
|
34
|
+
top_left_corner: top_left_corner,
|
35
|
+
inner_rect: inner_rect
|
36
|
+
})
|
37
|
+
end
|
33
38
|
|
34
|
-
|
35
|
-
|
36
|
-
|
39
|
+
def draw_in(rect)
|
40
|
+
draw_in_context(UIGraphicsGetCurrentContext())
|
41
|
+
end
|
37
42
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
attributes[NSParagraphStyleAttributeName] = paragrahStyle
|
43
|
-
attributes[NSForegroundColorAttributeName] = color
|
44
|
-
attributes[NSFontAttributeName] = font
|
43
|
+
def draw_in_context(context)
|
44
|
+
return if computed_options[:hidden]
|
45
|
+
size_to_fit_if_needed
|
46
|
+
set_text_position
|
45
47
|
|
46
|
-
|
47
|
-
if underline_range = options[:underline]
|
48
|
-
# FIXME
|
49
|
-
# label_text = NSMutableAttributedString.alloc.initWithAttributedString(label_text)
|
50
|
-
# label_text.addAttributes({NSUnderlineStyleAttributeName => NSUnderlineStyleSingle}, range: underline_range)
|
51
|
-
end
|
48
|
+
draw_background_in_context(context)
|
52
49
|
|
53
|
-
|
50
|
+
UIGraphicsPushContext(context)
|
51
|
+
options = draw_options
|
52
|
+
if options[:is_html] || options[:line_spacing] || options[:underline]
|
53
|
+
prepared_text = options[:is_html] ? html_string(options) : attributed_string(options)
|
54
|
+
|
55
|
+
if options[:inner_rect]
|
56
|
+
prepared_text.drawInRect(options[:inner_rect])
|
57
|
+
else
|
58
|
+
prepared_text.drawAtPoint(options[:top_left_corner])
|
59
|
+
end
|
54
60
|
else
|
55
61
|
# regular string
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
+
prepared_text = options[:text]
|
63
|
+
options[:text_color].set
|
64
|
+
if options[:inner_rect]
|
65
|
+
prepared_text.drawInRect(options[:inner_rect],
|
66
|
+
withFont: options[:font],
|
67
|
+
lineBreakMode: options[:line_break_mode],
|
68
|
+
alignment: options[:text_alignment])
|
62
69
|
else
|
63
|
-
|
70
|
+
prepared_text.drawAtPoint(options[:top_left_corner], withFont: options[:font])
|
64
71
|
end
|
65
72
|
end
|
73
|
+
UIGraphicsPopContext()
|
74
|
+
end
|
75
|
+
|
76
|
+
def default_padding_for(side)
|
77
|
+
return super unless side.to_s == 'top'
|
78
|
+
@padding_top || 0
|
66
79
|
end
|
67
80
|
|
68
81
|
def size_to_fit_if_needed
|
69
82
|
if computed_options[:size_to_fit]
|
70
83
|
computed_options[:width] ||= cached_content_outer_width
|
71
|
-
|
72
|
-
computed_options[:height] ||= cached_content_outer_height
|
73
|
-
end
|
84
|
+
computed_options[:height] ||= cached_content_outer_height
|
74
85
|
reset_computed_values
|
75
|
-
true
|
76
86
|
end
|
77
87
|
end
|
78
88
|
|
79
89
|
def set_text_position
|
80
|
-
if computed_options.slice(:padding_top, :padding_bottom, :padding).none?
|
90
|
+
if computed_options.slice(:padding_top, :padding_bottom, :padding).values.none?
|
81
91
|
computed_options[:width] ||= computed_width
|
82
92
|
@padding_top = (computed_outer_height - cached_content_height)/2
|
83
93
|
# @padding_top += 1 unless @padding_top.zero?
|
@@ -4,11 +4,13 @@ module MotionPrime
|
|
4
4
|
include DrawBackgroundMixin
|
5
5
|
|
6
6
|
def draw_in(rect)
|
7
|
+
draw_in_context(UIGraphicsGetCurrentContext())
|
8
|
+
end
|
9
|
+
|
10
|
+
def draw_in_context(context)
|
7
11
|
return if computed_options[:hidden]
|
8
|
-
options = computed_options
|
9
12
|
|
10
|
-
|
11
|
-
draw_background_in(background_rect, options)
|
13
|
+
draw_background_in_context(context)
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
@@ -5,9 +5,7 @@ module MotionPrime
|
|
5
5
|
[*base_styles].each do |base_style|
|
6
6
|
[*suffixes].each do |suffix|
|
7
7
|
components = []
|
8
|
-
|
9
|
-
components << suffix.to_s if suffix.present?
|
10
|
-
styles << components.join('_').to_sym if components.present?
|
8
|
+
styles << [base_style.to_s, suffix.to_s].join('_').to_sym if base_style.present? && suffix.present?
|
11
9
|
end
|
12
10
|
end
|
13
11
|
styles
|
data/motion-prime/mp.rb
CHANGED
@@ -10,6 +10,10 @@ module MotionPrime
|
|
10
10
|
def self.low_camelize_factory_cache
|
11
11
|
@camelize_factory_cache ||= {}
|
12
12
|
end
|
13
|
+
|
14
|
+
def self.env
|
15
|
+
ENV['PRIME_ENV'] || ENV['RUBYMOTION_ENV'] || 'development'
|
16
|
+
end
|
13
17
|
end
|
14
18
|
::MP = MotionPrime unless defined?(::MP)
|
15
19
|
::Prime = MotionPrime unless defined?(::Prime)
|
@@ -99,8 +99,12 @@ module MotionPrime
|
|
99
99
|
def close_screen_navigational(args = {})
|
100
100
|
if args[:to_screen] && args[:to_screen].is_a?(UIViewController)
|
101
101
|
self.parent_screen = args[:to_screen]
|
102
|
+
|
103
|
+
screens = self.navigation_controller.childViewControllers
|
104
|
+
app_delegate.close_screens(screens[screens.index(parent_screen)+1..-1])
|
102
105
|
self.navigation_controller.popToViewController(args[:to_screen], animated: args[:animated])
|
103
106
|
else
|
107
|
+
app_delegate.close_screens(self)
|
104
108
|
self.navigation_controller.popViewControllerAnimated(args[:animated])
|
105
109
|
end
|
106
110
|
send_on_return(args)
|
@@ -4,7 +4,7 @@ module MotionPrime
|
|
4
4
|
|
5
5
|
def self.new(menu, content, options={})
|
6
6
|
screen = self.alloc.initWithContentViewController(nil, menuViewController: nil)
|
7
|
-
screen.backgroundImage =
|
7
|
+
screen.backgroundImage = Prime::Config.sidebar.background_image
|
8
8
|
screen.parallaxEnabled = false
|
9
9
|
|
10
10
|
full_width = UIScreen.mainScreen.bounds.size.width
|
@@ -71,7 +71,7 @@ module MotionPrime
|
|
71
71
|
controller.send(:on_screen_load) if controller.respond_to?(:on_screen_load)
|
72
72
|
controller = controller.main_controller if controller.respond_to?(:main_controller)
|
73
73
|
else
|
74
|
-
controller.navigation_controller = content_controller
|
74
|
+
controller.navigation_controller = content_controller if controller.respond_to?(:navigation_controller)
|
75
75
|
controller.send(:on_screen_load) if controller.respond_to?(:on_screen_load)
|
76
76
|
end
|
77
77
|
controller
|
@@ -1,9 +1,16 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
module CellSectionMixin
|
3
|
+
extend ::MotionSupport::Concern
|
4
|
+
|
3
5
|
attr_writer :table
|
6
|
+
attr_reader :pending_display
|
7
|
+
|
8
|
+
included do
|
9
|
+
class_attribute :custom_cell_name
|
10
|
+
end
|
4
11
|
|
5
12
|
def table
|
6
|
-
@table ||= options[:table]
|
13
|
+
@table ||= options[:table].try(:weak_ref)
|
7
14
|
end
|
8
15
|
|
9
16
|
def section_styles
|
@@ -17,22 +24,54 @@ module MotionPrime
|
|
17
24
|
end
|
18
25
|
|
19
26
|
def cell_name
|
20
|
-
self.class.
|
27
|
+
self.class.custom_cell_name || begin
|
21
28
|
return name unless table
|
22
29
|
table_name = table.name.gsub('_table', '')
|
23
30
|
name.gsub("#{table_name}_", '')
|
24
31
|
end
|
25
32
|
end
|
26
33
|
|
27
|
-
def
|
34
|
+
def container_bounds
|
35
|
+
@container_bounds ||= CGRectMake(0, 0, table.table_view.bounds.size.width, container_height)
|
36
|
+
end
|
37
|
+
|
38
|
+
def init_container_element(options = {})
|
28
39
|
@container_element ||= begin
|
29
40
|
options.merge!({
|
30
|
-
screen: screen,
|
31
|
-
section: self,
|
41
|
+
screen: screen.try(:weak_ref),
|
42
|
+
section: self.weak_ref,
|
32
43
|
has_drawn_content: true
|
33
44
|
})
|
45
|
+
options[:styles] ||= []
|
46
|
+
options[:styles] = [:"#{table.name}_first_cell"] if table.data.first == self
|
47
|
+
options[:styles] = [:"#{table.name}_last_cell"] if table.data.last == self
|
34
48
|
MotionPrime::BaseElement.factory(:table_view_cell, options)
|
35
49
|
end
|
36
50
|
end
|
51
|
+
|
52
|
+
def load_container_element(options = {})
|
53
|
+
init_container_element(options)
|
54
|
+
load_elements
|
55
|
+
@container_element.compute_options! unless @container_element.computed_options
|
56
|
+
if respond_to?(:prerender_elements_for_state) && prerender_enabled?
|
57
|
+
prerender_elements_for_state(:normal)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def pending_display!
|
62
|
+
@pending_display = true
|
63
|
+
display unless table.decelerating
|
64
|
+
end
|
65
|
+
|
66
|
+
def display
|
67
|
+
@pending_display = false
|
68
|
+
container_view.setNeedsDisplay
|
69
|
+
end
|
70
|
+
|
71
|
+
module ClassMethods
|
72
|
+
def set_cell_name(value)
|
73
|
+
self.custom_cell_name = value
|
74
|
+
end
|
75
|
+
end
|
37
76
|
end
|
38
77
|
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module DrawSectionMixin
|
3
|
+
extend ::MotionSupport::Concern
|
4
|
+
|
5
|
+
include HasStyles
|
6
|
+
include FrameCalculatorMixin
|
7
|
+
attr_accessor :container_element, :container_gesture_recognizers, :cached_draw_image
|
8
|
+
included do
|
9
|
+
class_attribute :prerender_enabled
|
10
|
+
end
|
11
|
+
|
12
|
+
def container_view
|
13
|
+
container_element.try(:view)
|
14
|
+
end
|
15
|
+
|
16
|
+
def draw_in(rect, state = :normal)
|
17
|
+
if cached_draw_image[state]
|
18
|
+
context = UIGraphicsGetCurrentContext()
|
19
|
+
CGContextDrawImage(context, container_bounds, cached_draw_image[state])
|
20
|
+
render_image_elements
|
21
|
+
elsif prerender_enabled?
|
22
|
+
prerender_elements_for_state(state)
|
23
|
+
draw_in(rect, state)
|
24
|
+
else
|
25
|
+
draw_background_in_context(UIGraphicsGetCurrentContext(), rect)
|
26
|
+
draw_elements(rect)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def bind_gesture_on_container_for(element, action, receiver = nil)
|
31
|
+
self.container_gesture_recognizers ||= begin
|
32
|
+
set_container_gesture_recognizer
|
33
|
+
[]
|
34
|
+
end
|
35
|
+
self.container_gesture_recognizers << {element: element, action: action, receiver: receiver}
|
36
|
+
end
|
37
|
+
|
38
|
+
def prerender_elements_for_state(state = :normal)
|
39
|
+
scale = UIScreen.mainScreen.scale
|
40
|
+
space = CGColorSpaceCreateDeviceRGB()
|
41
|
+
bits_per_component = 8
|
42
|
+
context = CGBitmapContextCreate(nil, container_bounds.size.width*scale, container_bounds.size.height*scale,
|
43
|
+
bits_per_component, container_bounds.size.width*scale*4, space, KCGImageAlphaPremultipliedLast)
|
44
|
+
|
45
|
+
CGContextScaleCTM(context, scale, scale)
|
46
|
+
|
47
|
+
draw_background_in_context(context, container_bounds)
|
48
|
+
elements_to_draw.each do |key, element|
|
49
|
+
element.draw_in_context(context)
|
50
|
+
end
|
51
|
+
|
52
|
+
cached_draw_image[state] = CGBitmapContextCreateImage(context)
|
53
|
+
end
|
54
|
+
|
55
|
+
def prerender_enabled?
|
56
|
+
self.class.prerender_enabled
|
57
|
+
end
|
58
|
+
|
59
|
+
def cached_draw_image
|
60
|
+
@cached_draw_image ||= MotionSupport::HashWithIndifferentAccess.new
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def set_container_gesture_recognizer
|
65
|
+
single_tap = UITapGestureRecognizer.alloc.initWithTarget(self, action: 'on_container_tap_gesture:')
|
66
|
+
single_tap.cancelsTouchesInView = false
|
67
|
+
container_view.addGestureRecognizer single_tap
|
68
|
+
container_view.setUserInteractionEnabled true
|
69
|
+
end
|
70
|
+
|
71
|
+
def on_container_tap_gesture(recognizer)
|
72
|
+
target = Array.wrap(container_gesture_recognizers).detect do |gesture_data|
|
73
|
+
CGRectContainsPoint(gesture_data[:element].computed_frame, recognizer.locationInView(container_view))
|
74
|
+
end
|
75
|
+
(target[:receiver] || self).send(target[:action], recognizer, target[:element]) if target
|
76
|
+
end
|
77
|
+
|
78
|
+
def draw_elements(rect)
|
79
|
+
elements_to_draw.each do |key, element|
|
80
|
+
element.draw_in(rect)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def draw_background_in_context(context, rect)
|
85
|
+
return unless container_element
|
86
|
+
|
87
|
+
options = container_element.computed_options
|
88
|
+
background_color = options[:background_color].try(:uicolor)
|
89
|
+
|
90
|
+
if gradient_options = options[:gradient]
|
91
|
+
start_point = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect))
|
92
|
+
end_point = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect))
|
93
|
+
|
94
|
+
# CGContextSaveGState(context)
|
95
|
+
CGContextAddRect(context, rect)
|
96
|
+
CGContextClip(context)
|
97
|
+
gradient = prepare_gradient(gradient_options)
|
98
|
+
CGContextDrawLinearGradient(context, gradient, start_point, end_point, 0)
|
99
|
+
# CGContextRestoreGState(context)
|
100
|
+
elsif background_color && background_color != :clear.uicolor
|
101
|
+
UIGraphicsPushContext(context)
|
102
|
+
background_color.uicolor.setFill
|
103
|
+
UIRectFill(rect)
|
104
|
+
UIGraphicsPopContext()
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def render_image_elements
|
109
|
+
elements_to_draw.each do |key, element|
|
110
|
+
element.load_image if element.is_a?(ImageDrawElement)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
module ClassMethods
|
115
|
+
def enable_prerender
|
116
|
+
self.prerender_enabled = true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|