bluepotion 0.1.6 → 0.1.7

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -0
  3. data/lib/project/alert_dialog/alert_dialog.rb +26 -4
  4. data/lib/project/benchmark.rb +34 -0
  5. data/lib/project/delayed_execution.rb +16 -0
  6. data/lib/project/ext/object.rb +16 -15
  7. data/lib/project/ext/time.rb +42 -0
  8. data/lib/project/ext/view.rb +26 -5
  9. data/lib/project/potion.rb +9 -0
  10. data/lib/project/pro_motion/activities/pm_activity.rb +15 -0
  11. data/lib/project/pro_motion/activities/pm_navigation_activity.rb +8 -1
  12. data/lib/project/pro_motion/activities/pm_single_fragment_activity.rb +1 -1
  13. data/lib/project/pro_motion/adapters/pm_base_adapter.rb +79 -15
  14. data/lib/project/pro_motion/adapters/pm_cursor_adapter.rb +7 -31
  15. data/lib/project/pro_motion/fragments/pm_list_screen.rb +14 -11
  16. data/lib/project/pro_motion/fragments/pm_screen.rb +3 -0
  17. data/lib/project/pro_motion/fragments/pm_screen_module.rb +41 -2
  18. data/lib/project/pro_motion/pm_application.rb +63 -0
  19. data/lib/project/ruby_motion_query/rmq/actions.rb +10 -0
  20. data/lib/project/ruby_motion_query/rmq/base.rb +79 -25
  21. data/lib/project/ruby_motion_query/rmq/config.rb +9 -0
  22. data/lib/project/ruby_motion_query/rmq/event_wrappers/rmq_keyboard_action.rb +12 -0
  23. data/lib/project/ruby_motion_query/rmq/event_wrappers/rmq_number_picker_change.rb +12 -0
  24. data/lib/project/ruby_motion_query/rmq/events.rb +14 -3
  25. data/lib/project/ruby_motion_query/rmq/factory.rb +10 -5
  26. data/lib/project/ruby_motion_query/rmq/selectors.rb +7 -6
  27. data/lib/project/ruby_motion_query/rmq/styles.rb +33 -10
  28. data/lib/project/ruby_motion_query/rmq/subviews.rb +2 -3
  29. data/lib/project/ruby_motion_query/rmq/traverse.rb +44 -6
  30. data/lib/project/ruby_motion_query/rmq_color.rb +2 -1
  31. data/lib/project/ruby_motion_query/rmq_device.rb +6 -0
  32. data/lib/project/ruby_motion_query/rmq_resource.rb +8 -0
  33. data/lib/project/ruby_motion_query/rmq_screen_data.rb +5 -0
  34. data/lib/project/ruby_motion_query/rmq_stylesheet.rb +30 -4
  35. data/lib/project/ruby_motion_query/rmq_validation.rb +3 -3
  36. data/lib/project/ruby_motion_query/rmq_view_data.rb +33 -1
  37. data/lib/project/ruby_motion_query/stylers/rmq_text_view_styler.rb +11 -3
  38. data/lib/project/ruby_motion_query/stylers/rmq_view_styler.rb +37 -3
  39. data/lib/project/version.rb +1 -1
  40. metadata +10 -4
  41. data/lib/project/compatibility/motion_keychain.rb +0 -14
@@ -0,0 +1,9 @@
1
+ class RMQ
2
+ def self.caching_enabled?
3
+ !!@caching_enabled
4
+ end
5
+
6
+ def self.caching_enabled=(value)
7
+ @caching_enabled = value
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ class RMQKeyboardAction
2
+ def initialize(&block)
3
+ @done_callback = block
4
+ end
5
+
6
+ def onEditorAction(view, action_id, key_event)
7
+ if action_id == Potion::EditorInfo::IME_ACTION_DONE
8
+ @done_callback.call if @done_callback
9
+ end
10
+ false
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class RMQNumberPickerChange
2
+ attr_accessor :change_block
3
+
4
+ def initialize(&block)
5
+ @change_block = block
6
+ end
7
+
8
+ def onValueChange(picker, old_val, new_val)
9
+ @change_block.call(picker, old_val, new_val)
10
+ end
11
+
12
+ end
@@ -5,7 +5,9 @@ class RMQ
5
5
  when :click, :tap, :touch
6
6
  handle_click(view, &block)
7
7
  when :change
8
- handle_change(view, &block)
8
+ handle_change(view, args, &block)
9
+ when :done
10
+ handle_done(view, &block)
9
11
  else
10
12
  raise "[RMQ ERROR] Unrecognized event: #{event}"
11
13
  end
@@ -25,13 +27,22 @@ class RMQ
25
27
  end
26
28
  end
27
29
 
28
- def handle_change(view, &block)
30
+ def handle_change(view, args, &block)
29
31
  # Seek bar change
30
32
  if view.respond_to? :setOnSeekBarChangeListener
31
33
  view.onSeekBarChangeListener = RMQSeekChange.new(args, &block)
32
34
  # Text change
33
- elsif view.respond_to? :addTextChangeListener
35
+ elsif view.respond_to? :addTextChangedListener
34
36
  view.addTextChangedListener(RMQTextChange.new(&block))
37
+ elsif view.respond_to? :setOnValueChangedListener
38
+ view.onValueChangedListener = RMQNumberPickerChange.new(&block)
39
+ end
40
+ end
41
+
42
+ def handle_done(view, &block)
43
+ # Keyboard done button pressed
44
+ if view.respond_to? :setOnEditorActionListener
45
+ view.onEditorActionListener = RMQKeyboardAction.new(&block)
35
46
  end
36
47
  end
37
48
 
@@ -22,11 +22,16 @@ class RMQ
22
22
  #
23
23
  # @return [RMQ]
24
24
  def create_with_selectors(working_selectors, originated_from, working_parent_rmq = nil)
25
- q = RMQ.new
26
- q.originated_from = originated_from
27
- q.parent_rmq = working_parent_rmq
28
- q.selectors = working_selectors
29
- q
25
+ #if working_parent_rmq && (working_parent_rmq.selectors.length == 1)
26
+ #working_parent_rmq.selectors[0].rmq(working_selectors)
27
+ #else
28
+ q = RMQ.new
29
+ q.originated_from = originated_from
30
+
31
+ q.parent_rmq = working_parent_rmq
32
+ q.selectors = working_selectors
33
+ q
34
+ #end
30
35
  end
31
36
 
32
37
  # This is used internally, to get a new rmq instance, just call "rmq" in your view or controller or
@@ -18,18 +18,19 @@ class RMQ
18
18
  # return true unless view.rmq_data.has_tag?
19
19
 
20
20
  new_selectors.each do |selector|
21
- if selector.is_a?(Java::Lang::Integer)
22
- if view.id == selector
21
+ if selector.is_a?(Symbol)
22
+ rd = view.rmq_data
23
+ if (rd.has_style?(selector)) || rd.has_tag?(selector)
23
24
  out = true
24
25
  break
25
26
  end
26
- elsif selector == :tagged
27
- if view.rmq_data.has_tag?
27
+ elsif selector.is_a?(Java::Lang::Integer)
28
+ if view.id == selector
28
29
  out = true
29
30
  break
30
31
  end
31
- elsif selector.is_a?(Symbol)
32
- if (view.rmq_data.has_style?(selector)) || view.rmq_data.has_tag?(selector)
32
+ elsif selector == :tagged
33
+ if view.rmq_data.has_tag?
33
34
  out = true
34
35
  break
35
36
  end
@@ -37,11 +37,24 @@ class RMQ
37
37
 
38
38
  def apply_style(*style_names)
39
39
  if style_names
40
- selected.each do |selected_view|
41
- style_names.each do |style_name|
42
- apply_style_to_view selected_view, style_name
40
+ if style_names.length == 1 && selected.length == 1
41
+ apply_style_to_view selected.first, style_names.first
42
+ else
43
+ selected.each do |selected_view|
44
+ style_names.each do |style_name|
45
+ apply_style_to_view selected_view, style_name
46
+ end
43
47
  end
44
48
  end
49
+
50
+ # TODO, remove this hack once RMA is fixed
51
+ #tproc = proc do |style_name|
52
+ #apply_style_to_view @apply_style_selected_view, style_name
53
+ #end
54
+ #selected.each do |selected_view|
55
+ #@apply_style_selected_view = selected_view
56
+ #style_names.each &tproc
57
+ #end
45
58
  end
46
59
  self
47
60
  end
@@ -49,12 +62,15 @@ class RMQ
49
62
 
50
63
  def apply_style_to_view(view, style_name)
51
64
  #begin
52
- styler = self.styler_for(view)
53
- self.stylesheet.send(style_name, styler)
54
- styler.finalize
55
-
56
- view.rmq_data.styles << style_name unless view.rmq_data.has_style?(style_name)
57
- view.rmq_style_applied
65
+ if sheet = self.stylesheet
66
+ styler = self.styler_for(view)
67
+ sheet.send(style_name, styler)
68
+ styler.finalize
69
+ styler.cleanup
70
+
71
+ view.rmq_data.styles << style_name unless view.rmq_data.has_style?(style_name)
72
+ view.rmq_style_applied
73
+ end
58
74
  #rescue NoMethodError => e
59
75
  #if e.message =~ /.*#{style_name.to_s}.*/
60
76
  #$stderr.puts "\n[RMQ ERROR] style_name :#{style_name} doesn't exist for a #{view.class.name}. Add 'def #{style_name}(st)' to #{stylesheet.class.name} class\n\n"
@@ -78,7 +94,14 @@ class RMQ
78
94
  out.flatten!.uniq
79
95
  end
80
96
 
81
-
97
+ def reapply_styles
98
+ selected.each do |selected_view|
99
+ selected_view.rmq_data.styles.each do |style_name|
100
+ apply_style_to_view selected_view, style_name
101
+ end
102
+ end
103
+ self
104
+ end
82
105
 
83
106
  end
84
107
 
@@ -30,7 +30,6 @@ class RMQ
30
30
  built = true
31
31
  end
32
32
 
33
- rmq_data.activity = self.activity
34
33
  rmq_data.screen = self.screen
35
34
 
36
35
  subviews_added << new_view
@@ -68,14 +67,14 @@ class RMQ
68
67
  alias :insert :add_subview
69
68
 
70
69
  def tag_all_from_resource_entry_name(view)
71
- view.rmq.find.each do |view|
70
+ @@tag_all_from_resource_entry_name_tproc ||= proc do |view|
72
71
  if ren = view.resource_entry_name
73
72
  view.rmq_data.tag(ren.to_sym)
74
73
  end
75
74
  end
75
+ view.rmq.find.each &@@tag_all_from_resource_entry_name_tproc
76
76
  end
77
77
 
78
-
79
78
  # Removes the selected views from their parent's (superview) subview array
80
79
  #
81
80
  # @example
@@ -28,6 +28,8 @@ class RMQ
28
28
  else
29
29
  RMQ.app.current_screen
30
30
  end
31
+ elsif @originated_from.respond_to?(:dummy_workaround_for_kind_of) # TODO, kind_of? doesn't seem to work, verify. Workaround here
32
+ @originated_from
31
33
  else
32
34
  RMQ.app.current_screen
33
35
  end
@@ -41,7 +43,8 @@ class RMQ
41
43
  if @originated_from.is_a?(Android::App::Activity)
42
44
  @originated_from.root_view
43
45
  else
44
- self.controller.root_view
46
+ c = self.controller
47
+ c.root_view if c
45
48
  end
46
49
  end
47
50
 
@@ -66,8 +69,16 @@ class RMQ
66
69
  end
67
70
  end
68
71
 
72
+ def only_root_view_selected?
73
+ selected.length == 1 && selected[0].rmq_data.is_screen_root_view
74
+ end
75
+
69
76
  def all
70
- wrap(root_view).find
77
+ if only_root_view_selected?
78
+ self.find
79
+ else
80
+ self.wrap(self.root_view).find
81
+ end
71
82
  end
72
83
 
73
84
  def children(*working_selectors)
@@ -91,10 +102,38 @@ class RMQ
91
102
  def find(*working_selectors)
92
103
  normalize_selectors(working_selectors)
93
104
 
94
- #if working_selectors.length == 1 && self.selected.length == 1 && working_selectors.first.is_a?(Java::Lang::Integer)
95
- #return selected_first.findViewById(r(:id, working_selectors.first))
96
- #end
105
+ if RMQ.caching_enabled?
106
+ self_selected = self.selected
107
+ if working_selectors.length == 1 && self_selected.length == 1
108
+ single_selected = self_selected[0]
109
+ #if single_seleced.rmq_data.cache_queries
110
+ single_selector = working_selectors[0]
111
+ #if single_selector.is_a?(Symbol)
112
+ if cached = single_selected.rmq_data.query_cache[single_selector]
113
+ #mp "cached #{single_selector}"
114
+ return cached
115
+ else
116
+ q = filter(uniq: true) do |view|
117
+ sbvws = all_subviews_for(view)
118
+
119
+ if RMQ.is_blank?(working_selectors)
120
+ sbvws
121
+ else
122
+ sbvws.inject([]) do |out, subview|
123
+ out << subview if match(subview, working_selectors)
124
+ out
125
+ end
126
+ end
127
+ end # filter
128
+
129
+ single_selected.rmq_data.query_cache[single_selector] = q
130
+ return q
131
+ end
132
+ #end
133
+ end
134
+ end
97
135
 
136
+ # Repeating this inline for performance, TODO, measure and refactor
98
137
  filter(uniq: true) do |view|
99
138
  sbvws = all_subviews_for(view)
100
139
 
@@ -107,7 +146,6 @@ class RMQ
107
146
  end
108
147
  end
109
148
  end # filter
110
-
111
149
  end
112
150
 
113
151
  def find!(*args) # Do not alias this, strange bugs happen where classes don't have methods
@@ -114,7 +114,8 @@ class RMQColorFactory
114
114
  end
115
115
 
116
116
  def from_rgba(r, g, b, a)
117
- RMQColor.argb(a, r, b, g)
117
+ android_a = a * 255
118
+ RMQColor.argb(android_a, r, g, b)
118
119
  end
119
120
  end
120
121
 
@@ -43,5 +43,11 @@ class RMQDevice
43
43
  #TODO
44
44
  end
45
45
 
46
+ def unique_id
47
+ # This is no simple task... and can sometimes be nil based on device implementation
48
+ # This does seem, however, to be the best answer for now.
49
+ Android::Provider::Settings::Secure.getString(find.app.getContentResolver, "android_id")
50
+ end
51
+
46
52
  end
47
53
  end
@@ -22,5 +22,13 @@ class RMQResource
22
22
  def layout(name)
23
23
  self.find("layout", name)
24
24
  end
25
+
26
+ # the string value all up inside your 'res/values/strings.xml' (or nil)
27
+ def string(name=nil)
28
+ return nil unless name
29
+ resource_id = find(:string, name)
30
+ return nil if resource_id.nil? || resource_id == 0
31
+ PMApplication.current_application.resources.getString(resource_id)
32
+ end
25
33
  end
26
34
  end
@@ -1,3 +1,8 @@
1
1
  class RMQScreenData
2
2
  attr_accessor :stylesheet, :cached_rmq
3
+
4
+ def cleanup
5
+ @cached_rmq = nil
6
+ @stylesheet = nil
7
+ end
3
8
  end
@@ -1,15 +1,41 @@
1
1
  class RMQStylesheet
2
- attr_accessor :controller
3
-
4
- def initialize(controller)
2
+ def initialize(parent_screen)
5
3
  unless RMQStylesheet.application_was_setup
6
4
  RMQStylesheet.application_was_setup = true
7
5
  application_setup
8
6
  end
9
- @controller = controller
7
+ @screen = parent_screen
10
8
  setup
11
9
  end
12
10
 
11
+ # @ deprecated
12
+ def controller=(value)
13
+ @screen = value
14
+ end
15
+ # @ deprecated
16
+ def controller
17
+ @screen
18
+ end
19
+
20
+ def screen
21
+ @screen
22
+ end
23
+
24
+ def find(*working_selectors) # Not calling rmq below for performance reasons (one less method invocation)
25
+ if @screen
26
+ @screen.rmq(working_selectors)
27
+ else
28
+ super
29
+ end
30
+ end
31
+ def rmq(*working_selectors)
32
+ if @screen
33
+ @screen.rmq(working_selectors)
34
+ else
35
+ super
36
+ end
37
+ end
38
+
13
39
  def application_setup
14
40
  # Override to do your overall setup for your applications. This
15
41
  # is where you want to add your custom fonts and colors
@@ -116,8 +116,8 @@ module RubyMotionQuery
116
116
  HASUPPER = '^(?=.*[A-Z]).+$'
117
117
  # Has at least 1 lowercase letter
118
118
  HASLOWER = '^(?=.*[a-z]).+$'
119
- # Has some kind of value not just whitespace (doesn't require data to be stripped)
120
- PRESENCE = '\S+'
119
+ # is just whitespace
120
+ NOT_PRESENCE = '^\s*$' #Needed for android presence madness
121
121
 
122
122
  @@validation_methods = {
123
123
  :email => lambda { |value, opts| value.toString.matches(EMAIL)},
@@ -134,7 +134,7 @@ module RubyMotionQuery
134
134
  :strong_password => lambda { |value, opts| value.toString.matches(STRONGPW)},
135
135
  :has_upper => lambda { |value, opts| value.toString.matches(HASUPPER)},
136
136
  :has_lower => lambda { |value, opts| value.toString.matches(HASLOWER)},
137
- :presence => lambda { |value, opts| value.toString.matches(PRESENCE)},
137
+ :presence => lambda { |value, opts| !value.toString.matches(NOT_PRESENCE)},
138
138
  :length => lambda { |value, opts|
139
139
  opts = {
140
140
  exact_length: nil,
@@ -1,10 +1,42 @@
1
1
  class RMQViewData
2
- attr_accessor :events, :built, :is_screen_root_view, :activity, :screen
2
+ attr_accessor :events, :built, :is_screen_root_view, :screen, :cached_rmq #, :cache_queries
3
3
 
4
4
  def screen_root_view?
5
5
  !@is_screen_root_view.nil?
6
6
  end
7
7
 
8
+ def cleanup
9
+ clear_query_cache
10
+ if @cached_rmq
11
+ @cached_rmq.selectors = nil
12
+ @cached_rmq.parent_rmq = nil
13
+ @cached_rmq = nil
14
+ end
15
+ @events = nil
16
+ @screen = nil
17
+ @_tags = nil
18
+ @_styles = nil
19
+ @_validation_errors = nil
20
+ @validation_errors = nil
21
+ @is_screen_root_view = false
22
+ @built = false
23
+ nil
24
+ end
25
+
26
+ def query_cache
27
+ @_query_cache ||= {}
28
+ end
29
+
30
+ def clear_query_cache
31
+ @query_cache = {}
32
+ end
33
+
34
+ def activity
35
+ if @screen
36
+ @screen.getActivity
37
+ end
38
+ end
39
+
8
40
  # @return [Hash] Array of tag names assigned to to this view
9
41
  def tags
10
42
  @_tags ||= {}