bluepotion 0.0.1

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