motion-prime 0.7.2 → 0.8.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 +8 -8
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +8 -9
- data/ROADMAP.md +4 -5
- data/bin/prime +19 -14
- data/files/Rakefile +0 -1
- data/files/app/app_delegate.rb +0 -12
- data/files/app/config/base.rb +1 -12
- data/files/app/screens/application.rb +1 -5
- data/files/app/sections/.gitkeep +0 -0
- data/files/app/styles/.gitkeep +0 -0
- data/files/resources/Default-568h@2x.png +0 -0
- data/files/resources/Default.png +0 -0
- data/files/resources/Default@2x.png +0 -0
- data/motion-prime/api_client.rb +2 -1
- data/motion-prime/config/base.rb +8 -3
- data/motion-prime/config/config.rb +18 -0
- data/motion-prime/elements/_text_mixin.rb +0 -4
- data/motion-prime/elements/base_element.rb +64 -51
- data/motion-prime/elements/draw/image.rb +3 -2
- data/motion-prime/elements/draw/label.rb +9 -2
- data/motion-prime/helpers/has_search_bar.rb +10 -1
- data/motion-prime/screens/_base_mixin.rb +1 -1
- data/motion-prime/screens/_sections_mixin.rb +8 -4
- data/motion-prime/sections/__section_with_container_mixin.rb +52 -0
- data/motion-prime/sections/_cell_section_mixin.rb +7 -21
- data/motion-prime/sections/_delegate_mixin.rb +12 -0
- data/motion-prime/sections/_draw_section_mixin.rb +4 -21
- data/motion-prime/sections/base_section.rb +7 -7
- data/motion-prime/sections/form.rb +7 -0
- data/motion-prime/sections/form/base_field_section.rb +9 -0
- data/motion-prime/sections/form/date_field_section.rb +1 -1
- data/motion-prime/sections/form/form_delegate.rb +0 -1
- data/motion-prime/sections/form/password_field_section.rb +1 -1
- data/motion-prime/sections/form/select_field_section.rb +1 -1
- data/motion-prime/sections/form/string_field_section.rb +1 -1
- data/motion-prime/sections/form/submit_field_section.rb +1 -1
- data/motion-prime/sections/form/switch_field_section.rb +1 -1
- data/motion-prime/sections/form/text_field_section.rb +1 -1
- data/motion-prime/sections/tabbed.rb +7 -0
- data/motion-prime/sections/table.rb +20 -7
- data/motion-prime/sections/table/table_delegate.rb +1 -9
- data/motion-prime/styles/base.rb +1 -1
- data/motion-prime/styles/form.rb +7 -7
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/layout.rb +4 -2
- metadata +6 -14
- data/files/app/screens/help.rb +0 -6
- data/files/app/screens/home.rb +0 -8
- data/files/app/screens/sidebar.rb +0 -14
- data/files/app/sections/home/section.rb +0 -3
- data/files/app/sections/sidebar/action.rb +0 -5
- data/files/app/sections/sidebar/table.rb +0 -20
- data/files/app/styles/home.rb +0 -9
- data/files/resources/fonts/ubuntu.ttf +0 -0
- data/files/resources/images/arrow.png +0 -0
- data/files/resources/images/menu_button.png +0 -0
- data/files/resources/images/menu_button@2x.png +0 -0
- data/motion-prime/styles/sidebar.rb +0 -23
@@ -66,14 +66,15 @@ module MotionPrime
|
|
66
66
|
|
67
67
|
def load_image
|
68
68
|
return if image_data || !computed_options[:url]
|
69
|
+
# TODO: why so many references?
|
70
|
+
@strong_refs = section.strong_references + [screen.main_controller.strong_ref]
|
69
71
|
BW::Reactor.schedule do
|
70
72
|
manager = SDWebImageManager.sharedManager
|
71
|
-
@strong_refs = section.strong_references
|
72
73
|
manager.downloadWithURL(computed_options[:url],
|
73
74
|
options: 0,
|
74
75
|
progress: lambda{ |r_size, e_size| },
|
75
76
|
completed: lambda{ |image, error, type, finished|
|
76
|
-
if !image || screen.retainCount == 1 || section.retainCount == 1
|
77
|
+
if !image || screen.main_controller.retainCount == 1 || section.retainCount == 1
|
77
78
|
@strong_refs = nil
|
78
79
|
return
|
79
80
|
end
|
@@ -41,6 +41,8 @@ module MotionPrime
|
|
41
41
|
draw_in_context(UIGraphicsGetCurrentContext())
|
42
42
|
end
|
43
43
|
|
44
|
+
# using hack for bug described here: http://stackoverflow.com/questions/19232850/nsattributedstring-drawinrect-disappears-when-the-frame-is-offset
|
45
|
+
# TODO: check it in iOS 7.1 and remove CGContext manuplations (pass innerRect/topLeftCorner) if fixed
|
44
46
|
def draw_in_context(context)
|
45
47
|
return if computed_options[:hidden]
|
46
48
|
size_to_fit_if_needed
|
@@ -53,11 +55,16 @@ module MotionPrime
|
|
53
55
|
if options[:is_html] || options[:line_spacing] || options[:line_height] || options[:underline]
|
54
56
|
prepared_text = options[:is_html] ? html_string(options) : attributed_string(options)
|
55
57
|
|
58
|
+
CGContextSaveGState(context)
|
56
59
|
if options[:inner_rect]
|
57
|
-
|
60
|
+
rect = options[:inner_rect]
|
61
|
+
CGContextTranslateCTM(context, *rect.origin.to_a)
|
62
|
+
prepared_text.drawInRect(CGRectMake(0, 0, *rect.size.to_a))
|
58
63
|
else
|
59
|
-
|
64
|
+
CGContextTranslateCTM(context, *options[:top_left_corner].to_a)
|
65
|
+
prepared_text.drawAtPoint(CGPointMake(0, 0))
|
60
66
|
end
|
67
|
+
CGContextRestoreGState(context)
|
61
68
|
else
|
62
69
|
# regular string
|
63
70
|
prepared_text = options[:text]
|
@@ -2,6 +2,7 @@
|
|
2
2
|
module MotionPrime
|
3
3
|
module HasSearchBar
|
4
4
|
def add_search_bar(options = {}, &block)
|
5
|
+
@_search_timeout = options.delete(:timeout)
|
5
6
|
target = options.delete(:target)
|
6
7
|
|
7
8
|
@_search_bar = create_search_bar(options)
|
@@ -20,6 +21,7 @@ module MotionPrime
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def dealloc
|
24
|
+
BW::Reactor.cancel_timer(@_search_timer) if @_search_timer
|
23
25
|
@_search_bar.try(:setDelegate, nil)
|
24
26
|
@_search_bar = nil
|
25
27
|
super
|
@@ -35,10 +37,17 @@ module MotionPrime
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def searchBar(search_bar, textDidChange: text)
|
38
|
-
|
40
|
+
BW::Reactor.cancel_timer(@_search_timer) if @_search_timer
|
41
|
+
if @_search_timeout
|
42
|
+
@_search_timer = BW::Reactor.add_timer(@_search_timeout.to_f/1000, proc{ @search_callback.call(text) }.weak!)
|
43
|
+
else
|
44
|
+
@search_callback.call(text)
|
45
|
+
end
|
39
46
|
end
|
40
47
|
|
41
48
|
def searchBarSearchButtonClicked(search_bar)
|
49
|
+
BW::Reactor.cancel_timer(@_search_timer) if @_search_timer
|
50
|
+
@search_callback.call(search_bar.text)
|
42
51
|
search_bar.resignFirstResponder
|
43
52
|
end
|
44
53
|
end
|
@@ -12,7 +12,7 @@ module MotionPrime
|
|
12
12
|
include MotionPrime::ScreenNavigationMixin
|
13
13
|
include MotionPrime::ScreenSectionsMixin
|
14
14
|
|
15
|
-
attr_accessor :parent_screen, :modal, :params, :
|
15
|
+
attr_accessor :parent_screen, :modal, :params, :options, :tab_bar
|
16
16
|
class_attribute :current_screen
|
17
17
|
|
18
18
|
def app_delegate
|
@@ -14,6 +14,10 @@ module MotionPrime
|
|
14
14
|
render_sections
|
15
15
|
end
|
16
16
|
|
17
|
+
def all_sections
|
18
|
+
@sections.values
|
19
|
+
end
|
20
|
+
|
17
21
|
def create_sections
|
18
22
|
section_options = self.class._section_options
|
19
23
|
return unless section_options
|
@@ -31,16 +35,16 @@ module MotionPrime
|
|
31
35
|
|
32
36
|
def render_sections
|
33
37
|
return unless @sections
|
34
|
-
if
|
35
|
-
@main_section = MotionPrime::TableSection.new(model:
|
38
|
+
if all_sections.count > 1
|
39
|
+
@main_section = MotionPrime::TableSection.new(model: all_sections, screen: self)
|
36
40
|
@main_section.render
|
37
41
|
else
|
38
|
-
|
42
|
+
all_sections.first.render
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
42
46
|
def main_section
|
43
|
-
@main_section ||
|
47
|
+
@main_section || all_sections.first
|
44
48
|
end
|
45
49
|
|
46
50
|
module ClassMethods
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module MotionPrime
|
2
|
+
module SectionWithContainerMixin
|
3
|
+
extend ::MotionSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_attribute :container_element_options
|
7
|
+
end
|
8
|
+
|
9
|
+
def container_view
|
10
|
+
container_element.try(:view)
|
11
|
+
end
|
12
|
+
|
13
|
+
def init_container_element(options = {})
|
14
|
+
@container_element ||= begin
|
15
|
+
options.merge!({
|
16
|
+
screen: screen,
|
17
|
+
section: self.weak_ref,
|
18
|
+
has_drawn_content: true
|
19
|
+
})
|
20
|
+
container_element_options = self.class.container_element_options.clone
|
21
|
+
type = container_element_options.delete(:type)
|
22
|
+
options.merge!(container_element_options)
|
23
|
+
MotionPrime::BaseElement.factory(type, options)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def load_container_with_elements(options = {})
|
28
|
+
init_container_element(options[:container] || {})
|
29
|
+
@container_element.compute_options! unless @container_element.computed_options
|
30
|
+
compute_element_options(options[:elements] || {})
|
31
|
+
|
32
|
+
if respond_to?(:prerender_elements_for_state) && prerender_enabled?
|
33
|
+
prerender_elements_for_state(:normal)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def compute_element_options(options = {})
|
39
|
+
self.elements.values.each do |element|
|
40
|
+
element.size_to_fit_if_needed if element.is_a?(LabelDrawElement)
|
41
|
+
element.compute_options! if element.respond_to?(:computed_options) && !element.computed_options
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
module ClassMethods
|
47
|
+
def container_element(options)
|
48
|
+
self.container_element_options = options
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -3,11 +3,14 @@ module MotionPrime
|
|
3
3
|
module CellSectionMixin
|
4
4
|
extend ::MotionSupport::Concern
|
5
5
|
|
6
|
+
include SectionWithContainerMixin
|
7
|
+
|
6
8
|
attr_writer :table
|
7
9
|
attr_reader :pending_display
|
8
10
|
|
9
11
|
included do
|
10
12
|
class_attribute :custom_cell_name
|
13
|
+
container_element type: :table_view_cell
|
11
14
|
end
|
12
15
|
|
13
16
|
def table
|
@@ -42,27 +45,10 @@ module MotionPrime
|
|
42
45
|
end
|
43
46
|
|
44
47
|
def init_container_element(options = {})
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
has_drawn_content: true
|
50
|
-
})
|
51
|
-
options[:styles] ||= []
|
52
|
-
options[:styles] = [:"#{table.name}_first_cell"] if table.data.first == self
|
53
|
-
options[:styles] = [:"#{table.name}_last_cell"] if table.data.last == self
|
54
|
-
MotionPrime::BaseElement.factory(:table_view_cell, options)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# FIXME: Why this duplicates functionality from other parts, e.g. draw_in?
|
59
|
-
def load_container_element(options = {})
|
60
|
-
init_container_element(options)
|
61
|
-
load_elements
|
62
|
-
@container_element.compute_options! unless @container_element.computed_options
|
63
|
-
if respond_to?(:prerender_elements_for_state) && prerender_enabled?
|
64
|
-
prerender_elements_for_state(:normal)
|
65
|
-
end
|
48
|
+
options[:styles] ||= []
|
49
|
+
options[:styles] = [:"#{table.name}_first_cell"] if table.data.first == self
|
50
|
+
options[:styles] = [:"#{table.name}_last_cell"] if table.data.last == self
|
51
|
+
super(options)
|
66
52
|
end
|
67
53
|
|
68
54
|
def pending_display!
|
@@ -4,30 +4,13 @@ module MotionPrime
|
|
4
4
|
|
5
5
|
include HasStyles
|
6
6
|
include FrameCalculatorMixin
|
7
|
+
include SectionWithContainerMixin
|
8
|
+
|
7
9
|
attr_accessor :container_element, :container_gesture_recognizers, :cached_draw_image
|
10
|
+
|
8
11
|
included do
|
9
12
|
class_attribute :prerender_enabled
|
10
|
-
|
11
|
-
|
12
|
-
def container_view
|
13
|
-
container_element.try(:view)
|
14
|
-
end
|
15
|
-
|
16
|
-
def init_container_element(options = {})
|
17
|
-
@container_element ||= begin
|
18
|
-
options.merge!({
|
19
|
-
screen: screen,
|
20
|
-
section: self.weak_ref,
|
21
|
-
has_drawn_content: true
|
22
|
-
})
|
23
|
-
options[:styles] ||= []
|
24
|
-
MotionPrime::BaseElement.factory(:view_with_section, options)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def load_container_element(options = {})
|
29
|
-
init_container_element(options)
|
30
|
-
@container_element.compute_options! unless @container_element.computed_options
|
13
|
+
container_element type: :view_with_section
|
31
14
|
end
|
32
15
|
|
33
16
|
def draw_in(rect, state = :normal)
|
@@ -19,6 +19,7 @@ module MotionPrime
|
|
19
19
|
include HasNormalizer
|
20
20
|
include HasClassFactory
|
21
21
|
include DrawSectionMixin
|
22
|
+
include DelegateMixin
|
22
23
|
|
23
24
|
attr_accessor :screen, :model, :name, :options, :elements, :section_styles
|
24
25
|
class_attribute :elements_options, :container_options, :keyboard_close_bindings
|
@@ -145,13 +146,6 @@ module MotionPrime
|
|
145
146
|
self.instance_eval(&@options_block) if @options_block.is_a?(Proc)
|
146
147
|
end
|
147
148
|
|
148
|
-
def load_elements
|
149
|
-
self.elements.values.each do |element|
|
150
|
-
element.size_to_fit_if_needed if element.is_a?(LabelDrawElement)
|
151
|
-
element.compute_options! if element.respond_to?(:computed_options) && !element.computed_options
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
149
|
def add_element(key, options = {})
|
156
150
|
return unless render_element?(key)
|
157
151
|
opts = options.clone
|
@@ -334,6 +328,12 @@ module MotionPrime
|
|
334
328
|
end
|
335
329
|
|
336
330
|
class << self
|
331
|
+
def inherited(subclass)
|
332
|
+
subclass.elements_options = self.elements_options.try(:clone)
|
333
|
+
subclass.container_options = self.container_options.try(:clone)
|
334
|
+
subclass.keyboard_close_bindings = self.keyboard_close_bindings.try(:clone)
|
335
|
+
end
|
336
|
+
|
337
337
|
def element(name, options = {}, &block)
|
338
338
|
options[:name] ||= name
|
339
339
|
options[:type] ||= :label
|
@@ -210,6 +210,13 @@ module MotionPrime
|
|
210
210
|
end
|
211
211
|
|
212
212
|
class << self
|
213
|
+
def inherited(subclass)
|
214
|
+
super
|
215
|
+
subclass.fields_options = self.fields_options.try(:clone)
|
216
|
+
subclass.text_field_limits = self.text_field_limits.try(:clone)
|
217
|
+
subclass.text_view_limits = self.text_view_limits.try(:clone)
|
218
|
+
end
|
219
|
+
|
213
220
|
def field(name, options = {}, &block)
|
214
221
|
options[:name] = name
|
215
222
|
options[:type] ||= :string
|
@@ -103,6 +103,15 @@ module MotionPrime
|
|
103
103
|
NSLog("can't blur on element #{self.class_name_without_kvo}")
|
104
104
|
end
|
105
105
|
|
106
|
+
def default_label_options
|
107
|
+
label_options = options[:label]
|
108
|
+
if label_options.has_key?(:text)
|
109
|
+
label_options
|
110
|
+
else
|
111
|
+
{text: options[:name].to_s.titleize}.merge(label_options)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
106
115
|
def bind_text_input
|
107
116
|
view(:input).on :change do |view|
|
108
117
|
focus
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class PasswordFieldSection < BaseFieldSection
|
3
3
|
element :label, type: :label do
|
4
|
-
|
4
|
+
default_label_options
|
5
5
|
end
|
6
6
|
element :input, type: :text_field, delegate: proc { form.table_delegate } do
|
7
7
|
{secure_text_entry: true}.merge(options[:input] || {})
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class SubmitFieldSection < BaseFieldSection
|
3
3
|
element :submit, type: :button do
|
4
|
-
{title: options[:
|
4
|
+
{title: options[:name].to_s.titleize}.merge(options[:button] || {})
|
5
5
|
end
|
6
6
|
element :error_message, type: :error_message, text: proc { all_errors.join("\n") if observing_errors? }
|
7
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class TextFieldSection < BaseFieldSection
|
3
3
|
element :label, type: :label do
|
4
|
-
|
4
|
+
default_label_options
|
5
5
|
end
|
6
6
|
element :input, type: :text_view, delegate: proc { form.table_delegate } do
|
7
7
|
{editable: true}.merge(options[:input] || {})
|
@@ -85,6 +85,13 @@ module MotionPrime
|
|
85
85
|
end
|
86
86
|
|
87
87
|
class << self
|
88
|
+
def inherited(subclass)
|
89
|
+
super
|
90
|
+
subclass.tabs_options = self.tabs_options.try(:clone)
|
91
|
+
subclass.tabs_default = self.tabs_default.try(:clone)
|
92
|
+
subclass.tabs_indexes = self.tabs_indexes.try(:clone)
|
93
|
+
end
|
94
|
+
|
88
95
|
def tab(id, options = {})
|
89
96
|
options[:name] ||= id.to_s.titleize
|
90
97
|
options[:id] = id
|
@@ -58,6 +58,13 @@ module MotionPrime
|
|
58
58
|
@preloader_queue[-1] = :cancelled if @preloader_queue.present?
|
59
59
|
end
|
60
60
|
|
61
|
+
def add_cells(cells)
|
62
|
+
prepare_table_cells(cells)
|
63
|
+
@data ||= []
|
64
|
+
@data += cells
|
65
|
+
reload_table_data
|
66
|
+
end
|
67
|
+
|
61
68
|
def reload_cell(section)
|
62
69
|
section.elements.values.each(&:compute_options!)
|
63
70
|
section.cached_draw_image = nil
|
@@ -307,7 +314,7 @@ module MotionPrime
|
|
307
314
|
def load_cell_by_index(index, options = {})
|
308
315
|
section = rows_for_section(index.section)[index.row]
|
309
316
|
if section.load_section && options[:preload] && !section.container_element && async_data? # perform only if just loaded
|
310
|
-
section.
|
317
|
+
section.load_container_with_elements(container: container_element_options_for(index))
|
311
318
|
end
|
312
319
|
section
|
313
320
|
end
|
@@ -387,17 +394,17 @@ module MotionPrime
|
|
387
394
|
@preloader_queue ||= []
|
388
395
|
@strong_refs ||= []
|
389
396
|
|
390
|
-
# TODO: do
|
391
|
-
|
392
|
-
|
393
|
-
|
397
|
+
# TODO: we do we need to keep screen ref too?
|
398
|
+
queue_id = @preloader_queue.count
|
399
|
+
@strong_refs[queue_id] = [screen.strong_ref, screen.main_controller.strong_ref]
|
400
|
+
@preloader_queue[queue_id] = :in_progress
|
401
|
+
BW::Reactor.schedule(queue_id) do |queue_id|
|
394
402
|
result = load_count.times do |offset|
|
395
403
|
if @preloader_queue[queue_id] == :cancelled
|
396
404
|
@strong_refs[queue_id] = nil
|
397
405
|
break
|
398
406
|
end
|
399
|
-
|
400
|
-
if screen.retainCount == 1
|
407
|
+
if screen.main_controller.retainCount == 1
|
401
408
|
@strong_refs[queue_id] = nil
|
402
409
|
@preloader_queue[queue_id] = :dealloc
|
403
410
|
break
|
@@ -423,6 +430,12 @@ module MotionPrime
|
|
423
430
|
end
|
424
431
|
|
425
432
|
class << self
|
433
|
+
def inherited(subclass)
|
434
|
+
super
|
435
|
+
subclass.async_data_options = self.async_data_options.try(:clone)
|
436
|
+
subclass.section_header_options = self.section_header_options.try(:clone)
|
437
|
+
end
|
438
|
+
|
426
439
|
def async_table_data(options = {})
|
427
440
|
self.async_data_options = options
|
428
441
|
end
|