bluepotion 0.0.1

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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +10 -0
  3. data/lib/bluepotion.rb +16 -0
  4. data/lib/project/ext/activity.rb +62 -0
  5. data/lib/project/ext/array_list.rb +25 -0
  6. data/lib/project/ext/fragment.rb +2 -0
  7. data/lib/project/ext/object.rb +105 -0
  8. data/lib/project/ext/string.rb +23 -0
  9. data/lib/project/ext/view.rb +81 -0
  10. data/lib/project/potion.rb +50 -0
  11. data/lib/project/pro_motion/pm_activity.rb +38 -0
  12. data/lib/project/pro_motion/pm_application.rb +71 -0
  13. data/lib/project/pro_motion/pm_home_activity.rb +14 -0
  14. data/lib/project/pro_motion/pm_screen.rb +67 -0
  15. data/lib/project/pro_motion/pm_screen_module.rb +165 -0
  16. data/lib/project/pro_motion/pm_single_fragment_activity.rb +31 -0
  17. data/lib/project/ruby_motion_query/rmq/actions.rb +48 -0
  18. data/lib/project/ruby_motion_query/rmq/base.rb +260 -0
  19. data/lib/project/ruby_motion_query/rmq/data.rb +64 -0
  20. data/lib/project/ruby_motion_query/rmq/debug.rb +9 -0
  21. data/lib/project/ruby_motion_query/rmq/enumerablish.rb +99 -0
  22. data/lib/project/ruby_motion_query/rmq/events.rb +28 -0
  23. data/lib/project/ruby_motion_query/rmq/factory.rb +47 -0
  24. data/lib/project/ruby_motion_query/rmq/position.rb +2 -0
  25. data/lib/project/ruby_motion_query/rmq/selectors.rb +72 -0
  26. data/lib/project/ruby_motion_query/rmq/styles.rb +108 -0
  27. data/lib/project/ruby_motion_query/rmq/subviews.rb +95 -0
  28. data/lib/project/ruby_motion_query/rmq/tags.rb +58 -0
  29. data/lib/project/ruby_motion_query/rmq/traverse.rb +287 -0
  30. data/lib/project/ruby_motion_query/rmq/utils.rb +36 -0
  31. data/lib/project/ruby_motion_query/rmq/version.rb +6 -0
  32. data/lib/project/ruby_motion_query/rmq_activity_data.rb +3 -0
  33. data/lib/project/ruby_motion_query/rmq_app.rb +9 -0
  34. data/lib/project/ruby_motion_query/rmq_color.rb +121 -0
  35. data/lib/project/ruby_motion_query/rmq_device.rb +47 -0
  36. data/lib/project/ruby_motion_query/rmq_event.rb +1 -0
  37. data/lib/project/ruby_motion_query/rmq_font.rb +61 -0
  38. data/lib/project/ruby_motion_query/rmq_image.rb +55 -0
  39. data/lib/project/ruby_motion_query/rmq_rect.rb +576 -0
  40. data/lib/project/ruby_motion_query/rmq_screen_data.rb +3 -0
  41. data/lib/project/ruby_motion_query/rmq_stylesheet.rb +39 -0
  42. data/lib/project/ruby_motion_query/rmq_view_data.rb +88 -0
  43. data/lib/project/ruby_motion_query/stylers/rmq_button_styler.rb +3 -0
  44. data/lib/project/ruby_motion_query/stylers/rmq_image_button_styler.rb +3 -0
  45. data/lib/project/ruby_motion_query/stylers/rmq_image_view_styler.rb +24 -0
  46. data/lib/project/ruby_motion_query/stylers/rmq_linear_layout_styler.rb +32 -0
  47. data/lib/project/ruby_motion_query/stylers/rmq_relative_layout_styler.rb +7 -0
  48. data/lib/project/ruby_motion_query/stylers/rmq_styler_helper.rb +3 -0
  49. data/lib/project/ruby_motion_query/stylers/rmq_text_view_styler.rb +50 -0
  50. data/lib/project/ruby_motion_query/stylers/rmq_view_styler.rb +201 -0
  51. data/lib/project/version.rb +3 -0
  52. data/templates/screen/app/screens/name_screen.rb +20 -0
  53. data/templates/screen/app/stylesheets/name_screen_stylesheet.rb +24 -0
  54. data/templates/screen/spec/screens/name_screen_spec.rb +8 -0
  55. metadata +119 -0
@@ -0,0 +1,14 @@
1
+ # RM-733
2
+ #module ProMotion
3
+ class PMHomeActivity < PMSingleFragmentActivity
4
+ def on_create(saved_instance_state)
5
+ super
6
+
7
+ mp "PMHomeActivity on_create", debugging_only: true
8
+
9
+ home_screen_class = PMApplication.current_application.home_screen_class
10
+ set_fragment home_screen_class.new if home_screen_class
11
+ end
12
+ end
13
+
14
+ #end
@@ -0,0 +1,67 @@
1
+ # http://hipbyte.myjetbrains.com/youtrack/issue/RM-773 - can't put this in a module yet :(
2
+ #module ProMotion
3
+
4
+ class PMScreen < Android::App::Fragment
5
+ include PMScreenModule
6
+
7
+ attr_accessor :view
8
+
9
+ def onCreateView(inflater, parent, saved_instance_state)
10
+ super
11
+
12
+ if self.class.xml_resource
13
+ @view = inflater.inflate(r(:layout, self.class.xml_resource), parent, false)
14
+ else
15
+ @view = load_view
16
+ @view.setId Potion::ViewIdGenerator.generate
17
+ end
18
+
19
+ action_bar.hide if hide_action_bar?
20
+ setup_xml_widgets
21
+
22
+ # TODO: how will we pass this back if we don't use XML?
23
+ @view
24
+ end
25
+
26
+ def load_view
27
+ Potion::FrameLayout.new(self.activity)
28
+ end
29
+
30
+ def onActivityCreated(saved_instance_state)
31
+ mp "PMScreen onActivityCreated" if RMQ.debugging?
32
+
33
+ super
34
+
35
+ @view.rmq_data.is_screen_root_view = true
36
+
37
+ self.rmq.build(@view)
38
+
39
+ if self.class.rmq_style_sheet_class
40
+ self.rmq.stylesheet = self.class.rmq_style_sheet_class
41
+ @view.rmq.apply_style(:root_view) #if @view.rmq.stylesheet.respond_to?(:root_view)
42
+ end
43
+
44
+ self.action_bar.title = self.class.bars_title
45
+ self.activity.title = self.class.bars_title
46
+
47
+ on_load
48
+ end
49
+
50
+
51
+ private
52
+
53
+ def setup_xml_widgets
54
+ return unless (xml_widget_ids = self.class.xml_widget_ids)
55
+ xml_widget_ids.each do |id|
56
+ instance_variable_set("@#{id.to_s}".to_sym, find(id))
57
+ end
58
+ end
59
+
60
+ def hide_action_bar?
61
+ # RM-???: comparing nil to false causes ART crash
62
+ !self.class.show_action_bar.nil? && self.class.show_action_bar == false
63
+ end
64
+
65
+ end
66
+
67
+ #end
@@ -0,0 +1,165 @@
1
+ # http://hipbyte.myjetbrains.com/youtrack/issue/RM-773 - can't put this in a module yet :(
2
+ # module ProMotion
3
+ module PMScreenModule
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ attr_reader :xml_resource, :xml_widget_ids, :show_action_bar, :bars_title
10
+
11
+ @show_action_bar = true
12
+
13
+ def stylesheet(style_sheet_class)
14
+ @rmq_style_sheet_class = style_sheet_class
15
+ end
16
+
17
+ def rmq_style_sheet_class
18
+ @rmq_style_sheet_class
19
+ end
20
+
21
+ def uses_xml(xml_resource=nil)
22
+ @xml_resource = xml_resource ||= deduce_resource_id
23
+ end
24
+
25
+ def xml_widgets(*widget_ids)
26
+ @xml_widget_ids = widget_ids || []
27
+ @xml_widget_ids.each do |id|
28
+ attr_accessor id
29
+ end
30
+ end
31
+
32
+ def uses_action_bar(show_action_bar)
33
+ @show_action_bar = show_action_bar
34
+ end
35
+
36
+ def title(new_title)
37
+ @bars_title = new_title
38
+ #self.activity.title = new_title
39
+ #getActivity().getActionBar().setTitle("abc")
40
+ end
41
+
42
+ private
43
+
44
+ def deduce_resource_id
45
+ resource = self.name.split(".").last
46
+ resource.underscore.to_sym
47
+ end
48
+ end
49
+
50
+ def rmq_data
51
+ @_rmq_data ||= RMQScreenData.new
52
+ end
53
+
54
+ def stylesheet
55
+ self.rmq.stylesheet
56
+ end
57
+
58
+ def stylesheet=(value)
59
+ self.rmq.stylesheet = value
60
+ end
61
+
62
+ def rmq(*working_selectors)
63
+ crmq = (rmq_data.cached_rmq ||= RMQ.create_with_selectors([], self))
64
+
65
+ if working_selectors.length == 0
66
+ crmq
67
+ else
68
+ RMQ.create_with_selectors(working_selectors, self, crmq)
69
+ end
70
+ end
71
+
72
+ def root_view
73
+ self.getView
74
+ end
75
+
76
+ def on_load
77
+ # abstract
78
+ end
79
+
80
+ def color(*params)
81
+ RMQ.color(*params)
82
+ end
83
+
84
+ def font
85
+ rmq.font
86
+ end
87
+
88
+ def image
89
+ rmq.image
90
+ end
91
+
92
+ def append_view(view_or_class, style=nil, opts={})
93
+ self.rmq.append_view(view_or_class, style, opts)
94
+ end
95
+
96
+ def append_view!(view_or_class, style=nil, opts={})
97
+ self.rmq.append_view(view_or_class, style, opts).get
98
+ end
99
+
100
+ # TODO add create and build
101
+
102
+
103
+ # temporary stand-in for Java's R class
104
+ def r(resource_type, resource_name)
105
+ resources.getIdentifier(resource_name.to_s, resource_type.to_s,
106
+ activity.getApplicationInfo.packageName)
107
+ end
108
+
109
+ def show_toast(message)
110
+ Android::Widget::Toast.makeText(activity, message, Android::Widget::Toast::LENGTH_SHORT).show
111
+ end
112
+
113
+ def open(screen_class, options={})
114
+ mp "ScreenModule open", debugging_only: true
115
+ activity_class = options[:activity] || PMSingleFragmentActivity
116
+
117
+ # TODO: replace the fragment in the activity when possible
118
+ # replace the fragment if we can; otherwise launch a new activity
119
+ # we're taking a conservative approach for now - eventually we'll want to allow
120
+ # replacing fragments for any kind of activity, but I'm not sure of the best way
121
+ # to implement that yet
122
+ intent = Android::Content::Intent.new(self.activity, activity_class)
123
+ intent.putExtra PMSingleFragmentActivity::EXTRA_FRAGMENT_CLASS, screen_class.to_s
124
+
125
+ ## TODO: limited support for extras for now - should reimplement with fragment arguments
126
+ if options[:extras]
127
+ options[:extras].keys.each do |key|
128
+ intent.putExtra key.to_s, options[:extras][key].toString
129
+ end
130
+ end
131
+
132
+ self.activity.startActivity intent
133
+ end
134
+
135
+ def start_activity(activity_class)
136
+ intent = Android::Content::Intent.new(self.activity, activity_class)
137
+ #intent.putExtra("key", value); # Optional parameters
138
+ self.activity.startActivity(intent)
139
+ end
140
+
141
+ def soft_input_mode(mode)
142
+ mode_const =
143
+ case mode
144
+ when :adjust_resize
145
+ Android::View::WindowManager::LayoutParams::SOFT_INPUT_ADJUST_RESIZE
146
+ end
147
+ activity.getWindow().setSoftInputMode(mode_const)
148
+ end
149
+
150
+ def hide_keyboard
151
+ input_manager = activity.getSystemService(Android::Content::Context::INPUT_METHOD_SERVICE)
152
+ input_manager.hideSoftInputFromWindow(view.getWindowToken(), 0);
153
+ end
154
+
155
+
156
+ def activity
157
+ getActivity()
158
+ end
159
+
160
+ def action_bar
161
+ activity.getActionBar()
162
+ end
163
+
164
+ end
165
+ #end
@@ -0,0 +1,31 @@
1
+ # An abstract Activity designed to host a single fragment.
2
+ # RM-733
3
+ #module ProMotion
4
+ class PMSingleFragmentActivity < PMActivity
5
+ attr_accessor :fragment_container, :fragment
6
+
7
+ EXTRA_FRAGMENT_CLASS = "fragment_class"
8
+
9
+ def on_create(saved_instance_state)
10
+ super
11
+
12
+ mp "PMSingleFragmentActivity on_create", debugging_only: true
13
+
14
+ @fragment_container = Potion::FrameLayout.new(self)
15
+ @fragment_container.setId Potion::ViewIdGenerator.generate
16
+ self.contentView = @fragment_container
17
+
18
+ if (fragment_class = intent.getStringExtra(EXTRA_FRAGMENT_CLASS))
19
+ # TODO weird way to create this intance, look at this later
20
+ set_fragment Kernel.const_get(fragment_class.to_s).new
21
+ end
22
+ end
23
+
24
+ def set_fragment(fragment)
25
+ mp "PMSingleFragmentActivity set_fragment", debugging_only: true
26
+ @fragment = fragment # useful for the REPL
27
+ fragmentManager.beginTransaction.add(@fragment_container.getId, fragment, fragment.class.to_s).commit
28
+ end
29
+
30
+ end
31
+ #end
@@ -0,0 +1,48 @@
1
+ class RMQ
2
+
3
+ # @return [RMQ]
4
+ def attr(new_settings)
5
+ selected.each do |view|
6
+ new_settings.each do |k,v|
7
+ view.send "#{k}=", v
8
+ end
9
+ end
10
+ self
11
+ end
12
+
13
+ def send(method, args = nil)
14
+ selected.each do |view|
15
+ if view.respond_to?(method)
16
+ if args
17
+ view.__send__ method, args
18
+ else
19
+ view.__send__ method
20
+ end
21
+ end
22
+ end
23
+ self
24
+ end
25
+
26
+ def focus
27
+ unless RMQ.is_blank?(selected)
28
+ selected.last.requestFocus
29
+ end
30
+ self
31
+ end
32
+
33
+ def hide
34
+ selected.each { |view| view.setVisibility(Potion::View::INVISIBLE) }
35
+ self
36
+ end
37
+
38
+ def show
39
+ selected.each { |view| view.setVisibility(Potion::View::VISIBLE) }
40
+ self
41
+ end
42
+
43
+ #def toggle
44
+ #selected.each { |view| view.hidden = !view.hidden? }
45
+ #self
46
+ #end
47
+
48
+ end
@@ -0,0 +1,260 @@
1
+ class RMQ
2
+ def initialize
3
+ @selected_dirty = true
4
+ end
5
+
6
+ def originated_from=(value)
7
+ if value
8
+ if value.is_a?(Potion::Activity)
9
+ @originated_from = value
10
+ @activity = value
11
+ elsif value.is_a?(PMScreen)
12
+ @originated_from = value
13
+ elsif value.is_a?(Potion::View)
14
+ @originated_from = value
15
+ elsif value.is_a?(RMQStylesheet)
16
+ @originated_from = value.controller
17
+ else
18
+ #debug.log_detailed('Invalid originated_from', objects: {value: value})
19
+ mp "Invalid originated_from: #{value.inspect}"
20
+ end
21
+ else
22
+ @originated_from = nil
23
+ end
24
+ @originated_from
25
+ end
26
+
27
+ def originated_from
28
+ @originated_from
29
+ end
30
+
31
+ def parent_rmq
32
+ @_parent_rmq
33
+ end
34
+ def parent_rmq=(value)
35
+ #debug.assert(value.is_a?(RMQ) || value.nil?, 'Invalid parent_rmq', { value: value })
36
+ @_parent_rmq = value
37
+ end
38
+
39
+ def root?
40
+ # TODO broken
41
+ (selected.length == 1) && (selected.first == @originated_from)
42
+ end
43
+
44
+ def originated_from_or_its_view
45
+ if @originated_from.is_a?(Potion::Activity) || @originated_from.is_a?(PMScreen)
46
+ @originated_from.root_view
47
+ else
48
+ @originated_from
49
+ end
50
+ end
51
+
52
+ def get
53
+ sel = self.selected
54
+ if sel.length == 1
55
+ sel.first
56
+ else
57
+ sel
58
+ end
59
+ end
60
+
61
+ def origin_views
62
+ if pq = self.parent_rmq
63
+ pq.selected
64
+ else
65
+ root_view
66
+ end
67
+ end
68
+
69
+ def wrap(*views)
70
+ views = [views] unless views.is_a?(Potion::ArrayList) # TODO, WTF, RM bug?
71
+ views.flatten!
72
+
73
+ views.select!{ |v| v.is_a?(Potion::View) }
74
+ RMQ.create_with_array_and_selectors(views, views, @originated_from, self)
75
+ end
76
+
77
+ def log(opt = nil)
78
+ if opt == :tree
79
+ mp tree_to_s(selected)
80
+ sleep 0.1 # Hack, TODO, fix async problem
81
+ return
82
+ end
83
+
84
+ wide = (opt == :wide)
85
+ out = "\n id |scr| class | style_name | frame |"
86
+ out << "\n" unless wide
87
+ out << " sv id |een| superview | subviews count | tags |"
88
+ line = " ––––––––––––|–––|–––––––––––––––––––––––|–––––––––––––––––––––––––|–––––––––––––––––––––––––––––––––––––––|\n"
89
+ out << "\n"
90
+ out << line.chop if wide
91
+ out << line
92
+
93
+ selected.each do |view|
94
+ out << " #{view.id.to_s.ljust(12)}|"
95
+ out << (view.rmq_data.screen_root_view? ? " √ |" : " |")
96
+
97
+ name = view.short_class_name
98
+ name = name[(name.length - 21)..name.length] if name.length > 21
99
+ out << " #{name.ljust(22)}|"
100
+
101
+ #out << " #{""[0..23].ljust(24)}|" # TODO change to real stylname
102
+ out << " #{(view.rmq_data.style_name.to_s || '')[0..23].ljust(24)}|" # TODO change to real stylname
103
+ s = ""
104
+ #if view.origin
105
+ #format = '#0.#'
106
+ s = " {l: #{view.x}"
107
+ s << ", t: #{view.y}"
108
+ s << ", w: #{view.width}"
109
+ s << ", h: #{view.height}}"
110
+ #end
111
+ out << s.ljust(36)
112
+ out << " |"
113
+ 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)}|"
117
+ out << " #{view.subviews.length.to_s.ljust(23)} |"
118
+ #out << " #{view.subviews.length.to_s.rjust(8)} #{view.superview.short_class_name.ljust(20)} #{view.superview.object_id.to_s.rjust(10)}"
119
+ out << " #{view.rmq_data.tag_names.join(',').ljust(38)}|"
120
+ out << "\n"
121
+ out << line unless wide
122
+ end
123
+
124
+ mp out
125
+ sleep 0.1 # Hack, TODO, fix async problem
126
+ end
127
+
128
+ def log_tree
129
+ self.log :tree
130
+ end
131
+
132
+ def tree_to_s(selected_views, depth = 0)
133
+ out = ""
134
+
135
+ selected_views.each do |view|
136
+ if depth == 0
137
+ out << "\n"
138
+ else
139
+ 0.upto(depth - 1) do |i|
140
+ out << (i == (depth - 1) ? " ├" : " │")
141
+ end
142
+ end
143
+
144
+ out << '───'
145
+
146
+ out << "#{view.id} "
147
+ out << "SCREEN ROOT/" if view.rmq_data.screen_root_view?
148
+ out << "#{view.short_class_name[0..21]}"
149
+ 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
151
+
152
+ #if view.origin
153
+ #format = '#0.#'
154
+ s = " {l: #{view.x}"
155
+ s << ", t: #{view.y}"
156
+ s << ", w: #{view.width}"
157
+ s << ", h: #{view.height}}"
158
+ out << s
159
+ #end
160
+
161
+ out << "\n"
162
+ out << tree_to_s(view.subviews, depth + 1)
163
+ end
164
+
165
+ out
166
+ end
167
+
168
+ def inspect
169
+ out = "RMQ #{self.object_id}. #{self.count} selected. selectors: #{self.selectors}. .log for more info"
170
+ out << "\n[#{selected.first.inspect}]" if self.count == 1
171
+ out
172
+ end
173
+
174
+ # Do not use
175
+ def selected=(value)
176
+ @_selected = value
177
+ @selected_dirty = false
178
+ end
179
+
180
+ def selected
181
+ if @selected_dirty
182
+ @_selected = []
183
+
184
+ if RMQ.is_blank?(self.selectors)
185
+ @_selected << originated_from_or_its_view
186
+ #elsif self.selectors.length == 1 and self.selectors.first.is_a?(Java::Lang::Integer)
187
+ ### Special case where we find by id
188
+ #@_selected << self.root_view.findViewById(self.selectors.first)
189
+ else
190
+ working_selectors = self.selectors.dup
191
+ extract_views_from_selectors(@_selected, working_selectors)
192
+
193
+ unless RMQ.is_blank?(working_selectors)
194
+ subviews = all_subviews_for(root_view)
195
+ subviews.each do |subview|
196
+ @_selected << subview if match(subview, working_selectors)
197
+ end
198
+ end
199
+
200
+ end
201
+
202
+ @selected_dirty = false
203
+ else
204
+ @_selected ||= []
205
+ end
206
+
207
+ @_selected
208
+ end
209
+
210
+ def extract_views_from_selectors(view_container, working_selectors)
211
+ unless RMQ.is_blank?(working_selectors)
212
+ working_selectors.delete_if do |selector|
213
+ if selector.is_a?(Potion::View)
214
+ view_container << selector
215
+ true
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ def all_subviews_for(view)
222
+ out = []
223
+
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
235
+
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)
239
+ end
240
+ end
241
+ out
242
+ end
243
+
244
+ end # RMQ
245
+
246
+ __END__
247
+
248
+ findViewById(android.R.id.content) returns the View that hosts the content you supplied in setContentView().
249
+ Beyond that, try getRootView() (called on any View) to retrieve "the topmost view in the current view hierarchy".
250
+
251
+
252
+
253
+ we_care_about_this = getWindow.getDecorView.findViewById(Android::R::Id::Content)`
254
+ now we can traverse:
255
+ `we_care_about_this.getChildCount` and `we_care_about_this.getChildAt(0)`
256
+
257
+
258
+ Activity host = (Activity) view.getContext()
259
+
260
+ 2. view.isFocused()