ruby_motion_query 0.1.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 (46) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE +21 -0
  3. data/README.md +964 -0
  4. data/lib/ruby_motion_query.rb +8 -0
  5. data/motion/ext.rb +34 -0
  6. data/motion/ruby_motion_query/actions.rb +44 -0
  7. data/motion/ruby_motion_query/animations.rb +125 -0
  8. data/motion/ruby_motion_query/app.rb +71 -0
  9. data/motion/ruby_motion_query/base.rb +161 -0
  10. data/motion/ruby_motion_query/color.rb +80 -0
  11. data/motion/ruby_motion_query/data.rb +32 -0
  12. data/motion/ruby_motion_query/device.rb +73 -0
  13. data/motion/ruby_motion_query/enumerablish.rb +74 -0
  14. data/motion/ruby_motion_query/event.rb +125 -0
  15. data/motion/ruby_motion_query/events.rb +65 -0
  16. data/motion/ruby_motion_query/factory.rb +32 -0
  17. data/motion/ruby_motion_query/font.rb +66 -0
  18. data/motion/ruby_motion_query/format.rb +54 -0
  19. data/motion/ruby_motion_query/image.rb +79 -0
  20. data/motion/ruby_motion_query/position.rb +45 -0
  21. data/motion/ruby_motion_query/selectors.rb +56 -0
  22. data/motion/ruby_motion_query/stylers/ui_button_styler.rb +32 -0
  23. data/motion/ruby_motion_query/stylers/ui_control_styler.rb +8 -0
  24. data/motion/ruby_motion_query/stylers/ui_date_picker_styler.rb +8 -0
  25. data/motion/ruby_motion_query/stylers/ui_image_view_styler.rb +14 -0
  26. data/motion/ruby_motion_query/stylers/ui_label_styler.rb +36 -0
  27. data/motion/ruby_motion_query/stylers/ui_navigation_bar_styler.rb +8 -0
  28. data/motion/ruby_motion_query/stylers/ui_page_control_styler.rb +8 -0
  29. data/motion/ruby_motion_query/stylers/ui_refresh_control_styler.rb +8 -0
  30. data/motion/ruby_motion_query/stylers/ui_scroll_view_styler.rb +10 -0
  31. data/motion/ruby_motion_query/stylers/ui_segmented_control_styler.rb +8 -0
  32. data/motion/ruby_motion_query/stylers/ui_slider_styler.rb +8 -0
  33. data/motion/ruby_motion_query/stylers/ui_stepper_styler.rb +8 -0
  34. data/motion/ruby_motion_query/stylers/ui_switch_styler.rb +10 -0
  35. data/motion/ruby_motion_query/stylers/ui_tab_bar_styler.rb +8 -0
  36. data/motion/ruby_motion_query/stylers/ui_table_view_cell_styler.rb +8 -0
  37. data/motion/ruby_motion_query/stylers/ui_table_view_styler.rb +8 -0
  38. data/motion/ruby_motion_query/stylers/ui_text_field_styler.rb +8 -0
  39. data/motion/ruby_motion_query/stylers/ui_text_view_styler.rb +8 -0
  40. data/motion/ruby_motion_query/stylers/ui_view_styler.rb +243 -0
  41. data/motion/ruby_motion_query/stylesheet.rb +185 -0
  42. data/motion/ruby_motion_query/subviews.rb +52 -0
  43. data/motion/ruby_motion_query/tags.rb +14 -0
  44. data/motion/ruby_motion_query/traverse.rb +183 -0
  45. data/motion/ruby_motion_query/utils.rb +53 -0
  46. metadata +89 -0
@@ -0,0 +1,8 @@
1
+ unless defined?(Motion::Project::App)
2
+ raise "This must be required from within a RubyMotion Rakefile"
3
+ end
4
+
5
+ Motion::Project::App.setup do |app|
6
+ parent = File.join(File.dirname(__FILE__), '..')
7
+ app.files.unshift(Dir.glob(File.join(parent, "motion/**/*.rb")))
8
+ end
data/motion/ext.rb ADDED
@@ -0,0 +1,34 @@
1
+ class UIView
2
+ def rmq_data
3
+ @_rmq_data ||= RubyMotionQuery::ViewData.new
4
+ end
5
+
6
+ protected
7
+
8
+ def rmq(*selectors)
9
+ RubyMotionQuery::RMQ.create_with_selectors(selectors, RubyMotionQuery::RMQ.controller_for_view(self))
10
+ end
11
+ end
12
+
13
+ class UIViewController
14
+ def rmq(*selectors)
15
+ if RubyMotionQuery::RMQ.cache_controller_rmqs && selectors.length == 0
16
+ rmq_data.rmq ||= RubyMotionQuery::RMQ.create_with_selectors(selectors, self)
17
+ else
18
+ RubyMotionQuery::RMQ.create_with_selectors(selectors, self)
19
+ end
20
+ end
21
+
22
+ def rmq_data
23
+ @_rmq_data ||= RubyMotionQuery::ControllerData.new
24
+ end
25
+ end
26
+
27
+ # Used in console, so that you can just call rmq with an view or controller as self
28
+ class TopLevel
29
+ def rmq(*selectors)
30
+ if window = RubyMotionQuery::RMQ.app.window
31
+ RubyMotionQuery::RMQ.create_with_selectors(selectors, window.subviews.first)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,44 @@
1
+ module RubyMotionQuery
2
+ class RMQ
3
+ def attr(new_settings)
4
+ selected.each do |view|
5
+ new_settings.each do |k,v|
6
+ view.send "#{k}=", v
7
+ end
8
+ end
9
+ self
10
+ end
11
+
12
+ def send(method, args = nil)
13
+ selected.each do |view|
14
+ if args
15
+ view.__send__ method, args
16
+ else
17
+ view.__send__ method
18
+ end
19
+ end
20
+ self
21
+ end
22
+
23
+ def hide
24
+ selected.each { |view| view.hidden = true }
25
+ self
26
+ end
27
+
28
+ def show
29
+ selected.each { |view| view.hidden = false }
30
+ self
31
+ end
32
+
33
+ def toggle
34
+ selected.each { |view| view.hidden = !view.hidden? }
35
+ self
36
+ end
37
+
38
+ def toggle_enabled
39
+ selected.each { |view| view.enabled = !view.enabled? }
40
+ self
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,125 @@
1
+ module RubyMotionQuery
2
+ class RMQ
3
+ def animate(opts = {})
4
+ working_selected = self.selected
5
+ @_rmq = self # @ for rm bug
6
+
7
+ animations_lambda = if (animations_callback = (opts.delete(:animations) || opts.delete(:changes)))
8
+ -> do
9
+ working_selected.each do |view|
10
+ animations_callback.call(@_rmq.create_rmq_in_context(view))
11
+ end
12
+ end
13
+ else
14
+ nil
15
+ end
16
+
17
+ return self unless animations_lambda
18
+
19
+ after_lambda = if (after_callback = (opts.delete(:completion) || opts.delete(:after)))
20
+ -> (did_finish) {
21
+ after_callback.call(did_finish, @_rmq)
22
+ }
23
+ else
24
+ nil
25
+ end
26
+
27
+ UIView.animateWithDuration(
28
+ opts.delete(:duration) || 0.3,
29
+ delay: opts.delete(:delay) || 0,
30
+ options: (opts.delete(:options) || UIViewAnimationOptionCurveEaseInOut),
31
+ animations: animations_lambda,
32
+ completion: after_lambda
33
+ )
34
+
35
+ self
36
+ end
37
+
38
+ def animations
39
+ @_animations ||= Animations.new(self)
40
+ end
41
+ end
42
+
43
+ class Animations
44
+ def initialize(rmq)
45
+ @rmq = rmq
46
+ end
47
+
48
+ def fade_in(opts = {})
49
+ @rmq.each do |view|
50
+ view.layer.opacity = 0.0
51
+ view.hidden = false
52
+ end
53
+
54
+ opts[:animations] = lambda do |rmq|
55
+ rmq.get.layer.opacity = 1.0
56
+ end
57
+
58
+ @rmq.animate(opts)
59
+ end
60
+
61
+ def fade_out(opts = {})
62
+ opts[:animations] = lambda do |rmq|
63
+ rmq.get.layer.opacity = 0.0
64
+ end
65
+
66
+ @completion_block = opts[:completion] || opts[:after]
67
+
68
+ opts[:completion] = lambda do |did_finish, rmq|
69
+ rmq.each do |view|
70
+ view.hidden = true
71
+ view.layer.opacity = 1.0
72
+ end
73
+
74
+ @completion_block.call(did_finish, rmq) if @completion_block
75
+ end
76
+
77
+ @rmq.animate(opts)
78
+ end
79
+
80
+ def throb
81
+ @rmq.animate(
82
+ duration: 0.1,
83
+ animations: -> (q) {
84
+ q.style {|st| st.scale = 1.1}
85
+ },
86
+ completion: -> (did_finish, q) {
87
+ q.animate(
88
+ duration: 0.4,
89
+ animations: -> (cq) {
90
+ cq.style {|st| st.scale = 1.0}
91
+ }
92
+ )
93
+ }
94
+ )
95
+ end
96
+
97
+ def blink
98
+ self.fade_out(duration: 0.2, after: lambda {|did_finish, rmq| rmq.animations.fade_in(duration: 0.2)})
99
+ end
100
+
101
+ def start_spinner(style = UIActivityIndicatorViewStyleGray)
102
+ spinner = Animations.window_spinner(style)
103
+ spinner.startAnimating
104
+ @rmq.create_rmq_in_context(spinner)
105
+ end
106
+
107
+ def stop_spinner
108
+ spinner = Animations.window_spinner
109
+ spinner.stopAnimating
110
+ @rmq.create_rmq_in_context(spinner)
111
+ end
112
+
113
+ def self.window_spinner(style = UIActivityIndicatorViewStyleGray)
114
+ @_window_spinner ||= begin
115
+ window = RMQ.app.window
116
+ UIActivityIndicatorView.alloc.initWithActivityIndicatorStyle(style).tap do |o|
117
+ o.center = window.center
118
+ o.hidesWhenStopped = true
119
+ o.layer.zPosition = NSIntegerMax
120
+ window.addSubview(o)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,71 @@
1
+ module RubyMotionQuery
2
+ class RMQ
3
+ def app
4
+ App
5
+ end
6
+
7
+ def self.app
8
+ App
9
+ end
10
+
11
+ # TODO This is a bit wierd and may not work, need to think on this
12
+ # It's also confusing use of rmq which assumes a controller and subviews
13
+ #def window_rmq
14
+ #RMQ.create_with_selectors([App.window], self.context)
15
+ #end
16
+
17
+ #def self.window_rmq
18
+ #RMQ.create_with_selectors([App.window], App.window)
19
+ #end
20
+ end
21
+
22
+ class App
23
+ class << self
24
+
25
+ def window
26
+ UIApplication.sharedApplication.keyWindow || UIApplication.sharedApplication.windows[0]
27
+ end
28
+
29
+ def delegate
30
+ UIApplication.sharedApplication.delegate
31
+ end
32
+
33
+ def environment
34
+ RUBYMOTION_ENV.to_sym
35
+ end
36
+
37
+ def release?
38
+ environment == :release
39
+ end
40
+ alias :production? :release?
41
+
42
+ def test?
43
+ environment == :test
44
+ end
45
+
46
+ def development?
47
+ environment == :development
48
+ end
49
+
50
+ def version
51
+ NSBundle.mainBundle.infoDictionary['CFBundleVersion']
52
+ end
53
+
54
+ def name
55
+ NSBundle.mainBundle.objectForInfoDictionaryKey 'CFBundleDisplayName'
56
+ end
57
+
58
+ def identifier
59
+ NSBundle.mainBundle.bundleIdentifier
60
+ end
61
+
62
+ def resource_path
63
+ NSBundle.mainBundle.resourcePath
64
+ end
65
+
66
+ def document_path
67
+ NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true)[0]
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,161 @@
1
+ module RubyMotionQuery
2
+ class RMQ
3
+ attr_accessor :context, :parent_rmq
4
+
5
+ def initialize
6
+ @selected_dirty = true
7
+ end
8
+
9
+ def selected=(value)
10
+ @_selected = value
11
+ @selected_dirty = false
12
+ end
13
+ def selected
14
+ if @selected_dirty
15
+ @_selected = []
16
+
17
+ if RMQ.is_blank?(self.selectors)
18
+ @_selected << context_or_context_view
19
+ else
20
+ working_selectors = self.selectors.dup
21
+ extract_views_from_selectors(@_selected, working_selectors)
22
+
23
+ unless RMQ.is_blank?(working_selectors)
24
+ subviews = all_subviews_for(root_view)
25
+ subviews.each do |subview|
26
+ @_selected << subview if match(subview, working_selectors)
27
+ end
28
+ end
29
+
30
+ @_selected.uniq!
31
+ end
32
+
33
+ @selected_dirty = false
34
+ else
35
+ @_selected ||= []
36
+ end
37
+
38
+ @_selected
39
+ end
40
+
41
+ # The view(s) this rmq was derived from
42
+ def origin_views
43
+ if @parent_rmq
44
+ @parent_rmq.selected
45
+ else
46
+ [self.view_controller.view]
47
+ end
48
+ end
49
+
50
+ # Returns a view or array of views.
51
+ # Normally used to get the only view in selected.
52
+ #
53
+ # @example
54
+ # rmq(foo).parent.get.some_method_on_parent
55
+ def get
56
+ sel = self.selected
57
+ if sel.length == 1
58
+ sel.first
59
+ else
60
+ sel
61
+ end
62
+ end
63
+
64
+ def root?
65
+ (selected.length == 1) && (selected.first == @context)
66
+ end
67
+
68
+ def context_or_context_view
69
+ if @context.is_a?(UIViewController)
70
+ @context.view
71
+ else
72
+ @context
73
+ end
74
+ end
75
+
76
+ def extract_views_from_selectors(view_container, working_selectors)
77
+ unless RMQ.is_blank?(working_selectors)
78
+ working_selectors.each do |selector|
79
+ if selector.is_a?(UIView)
80
+ view_container << working_selectors.delete(selector)
81
+ end
82
+ end
83
+ end
84
+ [view_container, working_selectors]
85
+ end
86
+
87
+ def all_subviews_for(view)
88
+ # TODO maybe cache this, and invalidate cache properly
89
+ out = []
90
+ if view.subviews
91
+ view.subviews.each do |subview|
92
+ out << subview
93
+ out << all_subviews_for(subview)
94
+ end
95
+ out.flatten!
96
+ end
97
+
98
+ out
99
+ end
100
+
101
+ def all_superviews_for(view, out = [])
102
+ if (nr = view.nextResponder) && nr.is_a?(UIView)
103
+ out << nr
104
+ all_superviews_for(nr, out)
105
+ end
106
+ out
107
+ end
108
+
109
+ def inspect
110
+ out = "RMQ #{self.object_id}. #{self.count} selected. selectors: #{self.selectors.to_s}. .log for more info"
111
+ out << "\n[#{selected.first}]" if self.count == 1
112
+ out
113
+ end
114
+
115
+ def log(opt = nil)
116
+ wide = (opt == :wide)
117
+ out = "\n object_id | class | style_name | frame |"
118
+ out << "\n" unless wide
119
+ out << " sv id | superview | subviews count | tags |"
120
+ line = " - - - - - - | - - - - - - - - - - - | - - - - - - - - - - - - | - - - - - - - - - - - - - - - - |\n"
121
+ out << "\n"
122
+ out << line.chop if wide
123
+ out << line
124
+
125
+ selected.each do |view|
126
+ out << " #{view.object_id.to_s.ljust(12)}|"
127
+ out << " #{view.class.name[0..21].ljust(22)}|"
128
+ out << " #{(view.rmq_data.style_name || '')[0..23].ljust(24)}|"
129
+
130
+ s = ""
131
+ if view.origin
132
+ format = '#0.#'
133
+ s = " {l: #{RMQ.format.numeric(view.origin.x, format)}"
134
+ s << ", t: #{RMQ.format.numeric(view.origin.y, format)}"
135
+ s << ", w: #{RMQ.format.numeric(view.size.width, format)}"
136
+ s << ", h: #{RMQ.format.numeric(view.size.height, format)}}"
137
+ end
138
+ out << s.ljust(33)
139
+ out << '|'
140
+
141
+ out << "\n" unless wide
142
+ out << " #{view.superview.object_id.to_s.ljust(12)}|"
143
+ out << " #{(view.superview ? view.superview.class.name : '')[0..21].ljust(22)}|"
144
+ out << " #{view.subviews.length.to_s.ljust(23)} |"
145
+ #out << " #{view.subviews.length.to_s.rjust(8)} #{view.superview.class.name.ljust(20)} #{view.superview.object_id.to_s.rjust(10)}"
146
+ out << " #{view.rmq_data.tag_names.join(',').ljust(32)}|"
147
+ out << "\n"
148
+ out << line unless wide
149
+ end
150
+
151
+ out << "RMQ #{self.object_id}. #{self.count} selected. selectors: #{self.selectors.to_s}"
152
+
153
+ puts out
154
+ end
155
+
156
+ class << self
157
+ attr_accessor :cache_controller_rmqs
158
+ @cache_controller_rmqs = true
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,80 @@
1
+ module RubyMotionQuery
2
+ class RMQ
3
+ def self.color
4
+ Color
5
+ end
6
+
7
+ def color
8
+ Color
9
+ end
10
+ end
11
+
12
+ class Color < UIColor
13
+
14
+ class << self
15
+ alias :clear :clearColor
16
+ alias :white :whiteColor
17
+ alias :light_gray :lightGrayColor
18
+ alias :gray :grayColor
19
+ alias :dark_gray :darkGrayColor
20
+ alias :black :blackColor
21
+
22
+ alias :red :redColor
23
+ alias :green :greenColor
24
+ alias :blue :blueColor
25
+ alias :yellow :yellowColor
26
+ alias :orange :orangeColor
27
+ alias :purple :purpleColor
28
+ alias :brown :brownColor
29
+ alias :cyan :cyanColor
30
+ alias :magenta :magentaColor
31
+
32
+ alias :table_view :groupTableViewBackgroundColor
33
+ alias :scroll_view :scrollViewTexturedBackgroundColor
34
+ alias :flipside :viewFlipsideBackgroundColor
35
+ alias :under_page :underPageBackgroundColor
36
+ alias :light_text :lightTextColor
37
+ alias :dark_text :darkTextColor
38
+
39
+ def add_named(key, hex_or_color)
40
+ color = if hex_or_color.is_a?(String)
41
+ Color.from_hex(hex_or_color)
42
+ else
43
+ hex_or_color
44
+ end
45
+
46
+ Color.define_singleton_method(key) do
47
+ color
48
+ end
49
+ end
50
+
51
+ # Thanks bubblewrap for this method
52
+ def from_hex(hex_color)
53
+ hex_color.gsub!("#", "")
54
+ case hex_color.size
55
+ when 3
56
+ colors = hex_color.scan(%r{[0-9A-Fa-f]}).map{ |el| (el * 2).to_i(16) }
57
+ when 6
58
+ colors = hex_color.scan(%r<[0-9A-Fa-f]{2}>).map{ |el| el.to_i(16) }
59
+ else
60
+ raise ArgumentError
61
+ end
62
+ if colors.size == 3
63
+ from_rgba(colors[0], colors[1], colors[2], 1.0)
64
+ else
65
+ raise ArgumentError
66
+ end
67
+ end
68
+
69
+ def from_rgba(r,g,b,a)
70
+ UIColor.colorWithRed((r/255.0), green: (g/255.0), blue: (b/255.0), alpha: a)
71
+ end
72
+
73
+ def from_hsva(h,s,v,a)
74
+ UIColor.alloc.initWithHue(h, saturation: s, brightness: v, alpha: a)
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,32 @@
1
+ module RubyMotionQuery
2
+ class ViewData
3
+ attr_accessor :events, :style_name
4
+
5
+ def tags
6
+ @_tags ||= {}
7
+ end
8
+
9
+ def tag_names
10
+ tags.keys
11
+ end
12
+
13
+ def tag(*tag_or_tags)
14
+ tag_or_tags.flatten!
15
+ tag_or_tags.each do |tag_name|
16
+ tags[tag_name] = 1
17
+ end
18
+ end
19
+
20
+ def has_tag?(tag_name = nil)
21
+ if tag_name
22
+ tags.include?(tag_name)
23
+ else
24
+ RMQ.is_blank?(@_tags)
25
+ end
26
+ end
27
+ end
28
+
29
+ class ControllerData
30
+ attr_accessor :stylesheet, :rmq
31
+ end
32
+ end
@@ -0,0 +1,73 @@
1
+ module RubyMotionQuery
2
+ class RMQ
3
+ def device
4
+ Device
5
+ end
6
+ def self.device
7
+ Device
8
+ end
9
+ end
10
+
11
+ class Device
12
+ class << self
13
+ def screen
14
+ UIScreen.mainScreen
15
+ end
16
+
17
+ def width
18
+ @_width ||= Device.screen.bounds.size.width
19
+ end
20
+
21
+ def height
22
+ @_height ||= Device.screen.bounds.size.height
23
+ end
24
+
25
+ def ipad?
26
+ @_ipad = (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) if @_ipad.nil?
27
+ @_ipad
28
+ end
29
+
30
+ def iphone?
31
+ @_iphone = (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPhone) if @_iphone.nil?
32
+ @_iphone
33
+ end
34
+
35
+ def four_inch?
36
+ @_four_inch = (Device.height == 568.0) if @_four_inch.nil?
37
+ @_four_inch
38
+ end
39
+
40
+ def retina?()
41
+ if @_retina.nil?
42
+ main_screen = Device.screen
43
+ @_retina = !!(main_screen.respondsToSelector('displayLinkWithTarget:selector:') && main_screen.scale == 2.0)
44
+ end
45
+
46
+ @_retina
47
+ end
48
+
49
+ def orientation
50
+ ORIENTATIONS[UIDevice.currentDevice.orientation] || :unknown
51
+ end
52
+
53
+ def landscape?
54
+ Device.orientation == :landscape_Left || Device.orientation == :landscape_right
55
+ end
56
+
57
+ def portrait?
58
+ Device.orientation == :portrait || Device.orientation == :unknown
59
+ end
60
+
61
+ ORIENTATIONS = {
62
+ UIDeviceOrientationUnknown => :unkown,
63
+ UIDeviceOrientationPortrait => :portrait,
64
+ UIDeviceOrientationPortraitUpsideDown => :portrait_upside_down,
65
+ UIDeviceOrientationLandscapeLeft => :landscape_Left,
66
+ UIDeviceOrientationLandscapeRight => :landscape_right,
67
+ UIDeviceOrientationFaceUp => :face_up,
68
+ UIDeviceOrientationFaceDown => :face_down
69
+ }
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,74 @@
1
+ module RubyMotionQuery
2
+ class RMQ
3
+ # I'm purposly not including Enumerable,
4
+ # please use to_a if you want one
5
+
6
+ def <<(value)
7
+ selected << value if value.is_a?(UIView)
8
+ self
9
+ end
10
+
11
+ # @example
12
+ # rmq(UILabel)[3]
13
+ # or
14
+ # rmq(UILabel)[1..5]
15
+ def [](i)
16
+ RMQ.create_with_array_and_selectors([selected[i]], @selectors, @context)
17
+ end
18
+ alias :eq :[]
19
+
20
+ def each(&block)
21
+ return self unless block
22
+ RMQ.create_with_array_and_selectors(selected.each(&block), @selectors, @context)
23
+ end
24
+
25
+ def map(&block)
26
+ return self unless block
27
+ RMQ.create_with_array_and_selectors(selected.map(&block), @selectors, @context)
28
+ end
29
+ alias :collect :map
30
+
31
+ def select(&block)
32
+ return self unless block
33
+ RMQ.create_with_array_and_selectors(selected.select(&block), @selectors, @context)
34
+ end
35
+
36
+ def detect(&block) # Unlike enumerable, detect and find are not the same. See find in transverse
37
+ return self unless block
38
+ RMQ.create_with_array_and_selectors(selected.select(&block), @selectors, @context)
39
+ end
40
+
41
+ def grep(&block)
42
+ return self unless block
43
+ RMQ.create_with_array_and_selectors(selected.grep(&block), @selectors, @context)
44
+ end
45
+
46
+ def reject(&block)
47
+ return self unless block
48
+ RMQ.create_with_array_and_selectors(selected.reject(&block), @selectors, @context)
49
+ end
50
+
51
+ def inject(o, &block)
52
+ return self unless block
53
+ RMQ.create_with_array_and_selectors(selected.inject(o, &block), @selectors, @context)
54
+ end
55
+ alias :reduce :inject
56
+
57
+ def first
58
+ RMQ.create_with_array_and_selectors([selected.first], @selectors, @context)
59
+ end
60
+ def last
61
+ RMQ.create_with_array_and_selectors([selected.last], @selectors, @context)
62
+ end
63
+
64
+ def to_a
65
+ selected
66
+ end
67
+
68
+ def length
69
+ selected.length
70
+ end
71
+ alias :size :length
72
+ alias :count :length
73
+ end
74
+ end