bluepotion 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
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__