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
@@ -6,47 +6,23 @@ class PMCursorAdapter < PMBaseAdapter
6
6
  super()
7
7
  @cursor = opts.fetch(:cursor)
8
8
  @cell_options = opts.fetch(:cell, 1)
9
+ @cell_options[:cursor] = @cursor # slip the cursor inside so callbacks have it
9
10
  end
10
11
 
11
12
  def count
12
13
  cursor.count
13
14
  end
14
15
 
15
- def item(position)
16
+ def item_data(position)
16
17
  cursor.moveToPosition(position)
17
- cursor
18
+ cell_options # return the one & only one cell_options
18
19
  end
19
20
 
20
- def view(position, convert_view, parent)
21
- data = item(position)
22
- out = convert_view || rmq.create!(cell_options[:cell_class] || Potion::TextView)
23
- update_view(out, data)
24
- if cell_options[:action]
25
- find(out).on(:tap) do
26
- find.screen.send(cell_options[:action], item(position), position)
27
- end
28
- end
29
- out
21
+ # slighty different arguments to send when tapping
22
+ def action_arguments(data, position)
23
+ item_data(position) # move the cursor into position
24
+ @cursor
30
25
  end
31
26
 
32
- def update_view(out, data)
33
- if cell_options[:update].is_a?(Proc)
34
- cell_options[:update].call(out, data)
35
- elsif cell_options[:update].is_a?(Symbol) || cell_options[:update].is_a?(String)
36
- find.screen.send(cell_options[:update], out, data)
37
- else
38
- out.text = data.getString(cell_options[:title_column].to_i)
39
- end
40
- end
41
-
42
- end
43
-
44
- __END__
45
-
46
- def table_data
47
- {
48
- cursor: my_cursor,
49
- title_column: 0,
50
- }
51
27
  end
52
28
 
@@ -12,15 +12,9 @@
12
12
  end
13
13
 
14
14
  def load_view
15
- # Potion::LinearLayout.new(self.activity)
16
- self.view = create!(Potion::ListView, :list)
17
- # find(self.view).style do |st|
18
- # st.layout_width = :match_parent
19
- # st.layout_height = :match_parent
20
- # st.layout_weight = 1
21
- # st.view.drawSelectorOnTop = false
22
- # end
23
- # self.view
15
+ v = Potion::View.new(app.context) # TODO, fix this horrible hack
16
+ lv = rmq(v).create(Potion::ListView).tag(:list)
17
+ self.view = lv.get
24
18
  end
25
19
 
26
20
  def screen_setup
@@ -55,7 +49,8 @@
55
49
  @adapter ||= begin
56
50
  td = table_data
57
51
  if td.is_a?(Array)
58
- PMBaseAdapter.new(data: td)
52
+ cells = td.first[:cells]
53
+ PMBaseAdapter.new(data: cells)
59
54
  elsif td.is_a?(Hash)
60
55
  mp "Please supply a cursor in #{self.inspect}#table_data." unless td[:cursor]
61
56
  PMCursorAdapter.new(td)
@@ -64,6 +59,13 @@
64
59
  end
65
60
 
66
61
  def update_table_data
62
+ # base adapters must reacquire their data from the PMListScreen "delegate"
63
+ if adapter.instance_of?(PMCursorAdapter)
64
+ # TODO: Reload for PMCursorAdapter
65
+ elsif adapter.is_a?(PMBaseAdapter)
66
+ td = table_data
67
+ adapter.data = td && td.first && td.first[:cells]
68
+ end
67
69
  adapter.notifyDataSetChanged
68
70
  end
69
71
 
@@ -86,8 +88,9 @@
86
88
  @view = inflater.inflate(r(:layout, @xml_resource), parent, false)
87
89
  else
88
90
  v = load_view
91
+ mp v
89
92
  @view ||= v
90
- @view.setId Potion::ViewIdGenerator.generate
93
+ @view.id = Potion::ViewIdGenerator.generate
91
94
  end
92
95
 
93
96
  set_up_action_bar(self.class.action_bar_options)
@@ -17,8 +17,11 @@
17
17
  def on_create(bundle); end
18
18
 
19
19
  def onCreateView(inflater, parent, saved_instance_state)
20
+ mp "PMScreen onCreateView #{self.class}" if RMQ.debugging?
20
21
  super
21
22
 
23
+ self.cleanup
24
+
22
25
  if @xml_resource = self.class.xml_resource
23
26
  @view = inflater.inflate(r(:layout, @xml_resource), parent, false)
24
27
  else
@@ -55,6 +55,25 @@
55
55
  @_rmq_data ||= RMQScreenData.new
56
56
  end
57
57
 
58
+ def dummy_workaround_for_kind_of
59
+ end
60
+
61
+ def onDestroy
62
+ #return super # disable rmq cleaning while debugging, but still super
63
+ mp "onDestroy screen: #{self.class}", debugging_only: true
64
+ self.cleanup
65
+ super
66
+ end
67
+
68
+ def cleanup
69
+ find.all.cleanup
70
+ find.children.remove
71
+ if @_rmq_data
72
+ @_rmq_data.cleanup
73
+ @_rmq_data = nil
74
+ end
75
+ end
76
+
58
77
  def stylesheet
59
78
  self.rmq.stylesheet
60
79
  end
@@ -63,6 +82,16 @@
63
82
  self.rmq.stylesheet = value
64
83
  end
65
84
 
85
+ def find(*working_selectors) # I do not call rmq below for performance reasons
86
+ crmq = (rmq_data.cached_rmq ||= RMQ.create_with_selectors([], self))
87
+
88
+ if working_selectors.length == 0
89
+ crmq
90
+ else
91
+ RMQ.create_with_selectors(working_selectors, self, crmq)
92
+ end
93
+ end
94
+
66
95
  def rmq(*working_selectors)
67
96
  crmq = (rmq_data.cached_rmq ||= RMQ.create_with_selectors([], self))
68
97
 
@@ -117,13 +146,17 @@
117
146
  self.rmq.build(view_or_class, style, opts).get
118
147
  end
119
148
 
120
- # temporary stand-in for Java's R class
149
+ def log_tree
150
+ rmq.log_tree
151
+ end
152
+
153
+ # temporary stand-in for Java's R class, TODO remove this
121
154
  def r(resource_type, resource_name)
122
155
  resources.getIdentifier(resource_name.to_s, resource_type.to_s,
123
156
  activity.getApplicationInfo.packageName)
124
157
  end
125
158
 
126
- def show_toast(message)
159
+ def show_toast(message) # TODO, remove this, use app.toast
127
160
  Android::Widget::Toast.makeText(activity, message, Android::Widget::Toast::LENGTH_SHORT).show
128
161
  end
129
162
 
@@ -213,6 +246,12 @@
213
246
  input_manager.hideSoftInputFromWindow(view.getWindowToken(), 0)
214
247
  end
215
248
 
249
+ def show_keyboard
250
+ field = activity.getCurrentFocus()
251
+ input_manager = activity.getSystemService(Android::Content::Context::INPUT_METHOD_SERVICE)
252
+ input_manager.showSoftInput(field, Android::View::InputMethod::InputMethodManager::SHOW_FORCED)
253
+ end
254
+
216
255
  def action_bar
217
256
  activity && activity.getActionBar
218
257
  end
@@ -29,6 +29,10 @@
29
29
  context.getPackageManager
30
30
  end
31
31
 
32
+ def content_resolver
33
+ context.contentResolver
34
+ end
35
+
32
36
  def name
33
37
  application_info.loadLabel(package_manager)
34
38
  end
@@ -115,6 +119,65 @@
115
119
  AlertDialog.new(options, &block)
116
120
  end
117
121
 
122
+ # Send user to native Texting
123
+ # app.sms("555-555-5555")
124
+ def sms(phone_number)
125
+ mp "[BP Deprecated] use app.launch(sms: #{phone_number}) over app.sms"
126
+ launch(sms: phone_number)
127
+ end
128
+
129
+ # Launch native services via intent
130
+ # app.launch(sms: '5045558008')
131
+ # app.launch(tel: '5045558008')
132
+ # app.launch(web: 'http://giphy.com')
133
+ # app.launch(email: 'your@mom.com')
134
+ # app.launch(email: 'your@mom.com', subject: "Hey Chica", message: "Howdy")
135
+ # app.launch(chooser: 'I hope you have a nice day!')
136
+ def launch(command={})
137
+ action_view = "android.intent.action.VIEW"
138
+ action_send = "android.intent.action.SEND"
139
+ action_dial = "android.intent.action.DIAL"
140
+ key_list = command.keys
141
+ launch_intent = case
142
+ when key_list.include?(:sms)
143
+ sms_intent = Android::Content::Intent.new(action_view)
144
+ sms_intent.setData(Android::Net::Uri.fromParts("sms", command[:sms].to_s, nil))
145
+ when key_list.include?(:email)
146
+ email_intent = Android::Content::Intent.new(action_view)
147
+ email_string = "mailto:#{command[:email]}"
148
+ email_string += "?subject=#{command[:subject].to_s}"
149
+ email_string += "&body=#{command[:message].to_s}"
150
+ email_intent.setData(Android::Net::Uri.parse(email_string))
151
+ when key_list.include?(:web)
152
+ web_intent = Android::Content::Intent.new(action_view)
153
+ web_intent.setData(Android::Net::Uri.parse(command[:web]))
154
+ when key_list.include?(:tel)
155
+ tel_intent = Android::Content::Intent.new(action_dial)
156
+ tel_intent.setData(Android::Net::Uri.fromParts("tel", command[:tel], nil))
157
+ when key_list.include?(:chooser)
158
+ message_intent = Android::Content::Intent.new(action_send)
159
+ message_intent.type = "text/plain"
160
+ message_intent.putExtra("android.intent.extra.TEXT", command[:chooser].to_s) if command[:chooser]
161
+ Android::Content::Intent.createChooser(message_intent, nil)
162
+ else
163
+ mp "[BP Warning] Launch type unknown - '#{command.keys.inspect}'"
164
+ nil
165
+ end
166
+
167
+ find.activity.startActivity(launch_intent) if launch_intent
168
+ end
169
+
170
+ # Execute the given block after the given number of seconds
171
+ #
172
+ # @example
173
+ # app.after(10) do
174
+ # p "This will print in 10 seconds"
175
+ # end
176
+ #
177
+ def after(delay, &block)
178
+ DelayedExecution.after(delay, &block)
179
+ end
180
+
118
181
  class << self
119
182
  attr_accessor :current_application, :home_screen_class
120
183
 
@@ -40,6 +40,16 @@ class RMQ
40
40
  self
41
41
  end
42
42
 
43
+ def cleanup
44
+ selected.each { |view| view.cleanup }
45
+ self
46
+ end
47
+
48
+ def clear_cache
49
+ selected.each { |view| view.rmq_data.clear_query_cache }
50
+ self
51
+ end
52
+
43
53
  #def toggle
44
54
  #selected.each { |view| view.hidden = !view.hidden? }
45
55
  #self
@@ -1,8 +1,18 @@
1
1
  class RMQ
2
2
  def initialize
3
3
  @selected_dirty = true
4
+ $rmq_initialized ||= 0
5
+ $rmq_initialized += 1
6
+ #mp $rmq_initialized
4
7
  end
5
8
 
9
+ #def finalize
10
+ #mp 'finalize' # Never called
11
+ #$rmq_initialized -= 1
12
+ #mp $rmq_initialized
13
+ #super
14
+ #end
15
+
6
16
  def originated_from=(value)
7
17
  if value
8
18
  if value.is_a?(Potion::Activity)
@@ -15,8 +25,9 @@ class RMQ
15
25
  elsif value.is_a?(RMQStylesheet)
16
26
  @originated_from = value.controller
17
27
  else
28
+ @originated_from = nil
18
29
  #debug.log_detailed('Invalid originated_from', objects: {value: value})
19
- mp "Invalid originated_from: #{value.inspect}"
30
+ #mp "Invalid originated_from: #{value.inspect}"
20
31
  end
21
32
  else
22
33
  @originated_from = nil
@@ -44,9 +55,15 @@ class RMQ
44
55
  def originated_from_or_its_view
45
56
  if @originated_from.is_a?(Potion::Activity) || @originated_from.is_a?(PMScreen)
46
57
  @originated_from.root_view
47
- else
58
+ elsif @originated_from.is_a?(Potion::View)
48
59
  @originated_from
49
60
  end
61
+
62
+ #if @originated_from.is_a?(Potion::Activity) || @originated_from.is_a?(PMScreen)
63
+ #@originated_from.root_view
64
+ #else
65
+ #@originated_from
66
+ #end
50
67
  end
51
68
 
52
69
  def get
@@ -82,16 +99,17 @@ class RMQ
82
99
  end
83
100
 
84
101
  wide = (opt == :wide)
85
- out = "\n id |scr| class | style_name | frame |"
102
+ out = "\n id |object id |scr| class | style_name | frame |"
86
103
  out << "\n" unless wide
87
- out << " sv id |een| superview | subviews count | tags |"
88
- line = " ––––––––––––|–––|–––––––––––––––––––––––|–––––––––––––––––––––––––|–––––––––––––––––––––––––––––––––––––––|\n"
104
+ out << " sv id |object id |een| superview | subviews count | tags |"
105
+ line = " ––––––––––––|------------|–––|–––––––––––––––––––––––|–––––––––––––––––––––––––|–––––––––––––––––––––––––––––––––––––––|\n"
89
106
  out << "\n"
90
107
  out << line.chop if wide
91
108
  out << line
92
109
 
93
110
  selected.each do |view|
94
111
  out << " #{view.id.to_s.ljust(12)}|"
112
+ out << " #{view.object_id.to_s.ljust(12)}|"
95
113
  out << (view.rmq_data.screen_root_view? ? " √ |" : " |")
96
114
 
97
115
  name = view.short_class_name
@@ -111,9 +129,12 @@ class RMQ
111
129
  out << s.ljust(36)
112
130
  out << " |"
113
131
  out << "\n" unless wide
114
- out << " #{view.superview.id.to_s.ljust(12)}|"
115
- out << " |"
116
- out << " #{(view.superview ? view.superview.short_class_name : '')[0..21].ljust(22)}|"
132
+ if view.superview
133
+ out << " #{view.superview.id.to_s.ljust(12)}|"
134
+ out << " |"
135
+ out << " |"
136
+ out << " #{(view.superview ? view.superview.short_class_name : '')[0..21].ljust(22)}|"
137
+ end
117
138
  out << " #{view.subviews.length.to_s.ljust(23)} |"
118
139
  #out << " #{view.subviews.length.to_s.rjust(8)} #{view.superview.short_class_name.ljust(20)} #{view.superview.object_id.to_s.rjust(10)}"
119
140
  out << " #{view.rmq_data.tag_names.join(',').ljust(38)}|"
@@ -132,22 +153,33 @@ class RMQ
132
153
  def tree_to_s(selected_views, depth = 0)
133
154
  out = ""
134
155
 
156
+ mp 1
157
+
135
158
  selected_views.each do |view|
159
+ mp 2
160
+ mp view.rmq_data.tags
136
161
  if depth == 0
137
162
  out << "\n"
138
163
  else
164
+ mp 3
139
165
  0.upto(depth - 1) do |i|
166
+ mp 4
140
167
  out << (i == (depth - 1) ? " ├" : " │")
141
168
  end
142
169
  end
143
170
 
144
171
  out << '───'
145
172
 
146
- out << "#{view.id} "
173
+ mp 5
174
+ out << "#{view.id}|#{view.object_id} "
147
175
  out << "SCREEN ROOT/" if view.rmq_data.screen_root_view?
148
176
  out << "#{view.short_class_name[0..21]}"
149
177
  out << " ( :#{view.rmq_data.style_name.to_s[0..23]} )" if view.rmq_data.style_name
150
- out << " [ #{view.rmq_data.tag_names.join(',')} ]" if view.rmq_data.tag_names.length > 0
178
+ if view.rmq_data.tag_names.length > 0
179
+ mp 6
180
+ mp view.rmq_data.tag_names.inspect
181
+ out << " [ #{view.rmq_data.tag_names.join(',')} ]"
182
+ end
151
183
 
152
184
  #if view.origin
153
185
  #format = '#0.#'
@@ -182,16 +214,21 @@ class RMQ
182
214
  @_selected = []
183
215
 
184
216
  if RMQ.is_blank?(self.selectors)
185
- @_selected << originated_from_or_its_view
217
+ if orig = originated_from_or_its_view
218
+ @_selected << orig
219
+ end
186
220
  #elsif self.selectors.length == 1 and self.selectors.first.is_a?(Java::Lang::Integer)
187
221
  ### Special case where we find by id
188
222
  #@_selected << self.root_view.findViewById(self.selectors.first)
189
223
  else
190
224
  working_selectors = self.selectors.dup
225
+
191
226
  extract_views_from_selectors(@_selected, working_selectors)
192
227
 
193
228
  unless RMQ.is_blank?(working_selectors)
194
229
  subviews = all_subviews_for(root_view)
230
+
231
+ #return @_selected
195
232
  subviews.each do |subview|
196
233
  @_selected << subview if match(subview, working_selectors)
197
234
  end
@@ -199,6 +236,13 @@ class RMQ
199
236
 
200
237
  end
201
238
 
239
+ #@_selected.each do |s|
240
+ #unless s.is_a?(Potion::View)
241
+ #mp "bad selected: #{s}"
242
+ #caller
243
+ #end
244
+ #end
245
+
202
246
  @selected_dirty = false
203
247
  else
204
248
  @_selected ||= []
@@ -220,27 +264,37 @@ class RMQ
220
264
 
221
265
  def all_subviews_for(view)
222
266
  out = []
267
+ return out unless view.is_a?(Potion::ViewGroup)
223
268
 
224
- view.subviews.each do |subview|
225
- out << subview
226
- out << all_subviews_for(subview)
227
- end
228
- out.flatten!
229
- out
230
- end
231
-
232
- def all_superviews_for(view, out = [])
233
- if (sv = view.superview)
234
- out << sv
269
+ needs_flattening = false
235
270
 
236
- # Stop at root_view of screen or activity
237
- unless (sv.rmq_data.screen_root_view?) || (sv == self.activity.root_view) # TODO speed this up if needed
238
- all_superviews_for(sv, out)
271
+ (0...view.getChildCount).each_with_index do |i|
272
+ sbv = view.getChildAt(i)
273
+ if sbv && view != sbv
274
+ out << sbv
275
+ if sbv.is_a?(Potion::ViewGroup) && sbv.getChildCount > 0
276
+ needs_flattening = true
277
+ out << all_subviews_for(sbv)
278
+ end
239
279
  end
240
280
  end
281
+
282
+ out.flatten! if needs_flattening
241
283
  out
242
284
  end
243
285
 
286
+ #def all_superviews_for(view, out = [])
287
+ #if (sv = view.superview)
288
+ #out << sv
289
+
290
+ ## Stop at root_view of screen or activity
291
+ #unless (sv.rmq_data.screen_root_view?) || (sv == self.activity.root_view) # TODO speed this up if needed
292
+ #all_superviews_for(sv, out)
293
+ #end
294
+ #end
295
+ #out
296
+ #end
297
+
244
298
  end # RMQ
245
299
 
246
300
  __END__