mirror of
https://github.com/zhigang1992/rmq.git
synced 2026-01-12 09:33:43 +08:00
Started to add yard docs. Updated readme, I removed alpha warning because I think we're all good now
This commit is contained in:
34
README.md
34
README.md
@@ -1,17 +1,17 @@
|
||||

|
||||
|
||||
RubyMotionQuery - RMQ - A small, light, muggle, nonpolluting, jQuery-like library for [RubyMotion](http://rubymotion.com).
|
||||
# RubyMotionQuery - RMQ
|
||||
A light, muggle, nonpolluting, jQuery-like library for [RubyMotion](http://rubymotion.com).
|
||||
|
||||
#### The [RMQ Introductory Guide and other info][1] is a great place to start.
|
||||
|
||||
----------
|
||||
**The [RMQ Introductory Guide and other info][1] is a great place to start.**
|
||||
|
||||
[](https://gemnasium.com/infinitered/rmq)
|
||||
[](https://travis-ci.org/infinitered/rmq)
|
||||
|
||||
----------
|
||||
|
||||
#### Some of the very cool features:
|
||||
## General
|
||||
|
||||
### Some of the very cool features:
|
||||
- **selecting** (*querying*) views
|
||||
- **traversal** through view hierarchy (moving around the tree)
|
||||
- tagging
|
||||
@@ -24,7 +24,13 @@ RubyMotionQuery - RMQ - A small, light, muggle, nonpolluting, jQuery-like librar
|
||||
- app
|
||||
- device
|
||||
|
||||
#### Other wrapper libraries
|
||||
----------
|
||||
|
||||
**Tested only on iOS only, not OS X (nor is there any OS X specific code)**
|
||||
|
||||
----------
|
||||
|
||||
### Other wrapper libraries
|
||||
There are a lot of great wrappers out there such as Teacup and Sugarcube. I've used these and I enjoy them. However, many of the wrappers heavily pollute the standard classes, which is great if you like that sort of thing. RMQ is designed to have minimal pollution, to be very simple and high performance (it will be when it's done). RMQ shouldn't conflict with anything.
|
||||
|
||||
RMQ **doesn't require any** other wrapper or gem.
|
||||
@@ -33,19 +39,6 @@ RMQ **doesn't require any** other wrapper or gem.
|
||||
|
||||
Some of the code in RMQ came from BubbleWrap and Sugarcube. Not too much but some did. I thank you BubbleWrap and Sugarcube teams for your work.
|
||||
|
||||
----------
|
||||
|
||||
### * Alpha * Warning *
|
||||
|
||||
This is in the **alpha** stage right now, it works well and we've used some of RMQ in production apps, but it **needs** more **testing**, **performance** optimizations, **documentation**, and the **TODOs** to be finished.
|
||||
|
||||
RDocs are not done. I'd appreciate help on these. This readme isn't up to the quality I'd like either. I figure it's better to get it out to the community sooner rather than wait for it to be more finished. My ideal is jQuery quality docs in addition to basic RDoc reference.
|
||||
|
||||
Somethings still need to be optimized for speed
|
||||
|
||||
Tested only on iOS, not OS X (nor is there any OS X specific code)
|
||||
|
||||
----------
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -59,7 +52,6 @@ or add it to your `Gemfile`:
|
||||
- `gem 'ruby_motion_query'`
|
||||
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### Example App
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
module RubyMotionQuery
|
||||
|
||||
# The main class for RubyMotionQuery
|
||||
#
|
||||
# What's an rmq instance?
|
||||
# - an rmq instance is an array-like object containing UIViews
|
||||
# - rmq() never returns nil. If nothing is selected, it's an empty [ ] array-like
|
||||
# object
|
||||
# - an rmq object always (almost always) returns either itself or a new
|
||||
# rmq object. This is how chaining works. You do not need to worry if
|
||||
# an rmq is blank or not, everything always works without throwing a
|
||||
# nil exception
|
||||
# - jQuery uses the DOM, what is rmq using for the "DOM"? It uses the
|
||||
# controller it was called in. The "DOM" is the controller's subview
|
||||
# tree. If you call rmq inside a view, it will attach to the
|
||||
# controller that the view is currently in or to the current screen's
|
||||
# controller
|
||||
class RMQ
|
||||
attr_accessor :context, :parent_rmq
|
||||
|
||||
@@ -6,10 +22,14 @@ module RubyMotionQuery
|
||||
@selected_dirty = true
|
||||
end
|
||||
|
||||
# Do not use
|
||||
def selected=(value)
|
||||
@_selected = value
|
||||
@selected_dirty = false
|
||||
end
|
||||
|
||||
# The UIViews currently selected
|
||||
# Use {#get} instead to get the actual UIView objects
|
||||
def selected
|
||||
if @selected_dirty
|
||||
@_selected = []
|
||||
@@ -51,7 +71,13 @@ module RubyMotionQuery
|
||||
# Normally used to get the only view in selected.
|
||||
#
|
||||
# @example
|
||||
# rmq(foo).parent.get.some_method_on_parent
|
||||
# # returns my_view
|
||||
# rmq(my_view).get
|
||||
#
|
||||
# # returns an array
|
||||
# rmq(UILabel).get
|
||||
#
|
||||
# rmq(foo).parent.get.some_method_on_parent
|
||||
def get
|
||||
sel = self.selected
|
||||
if sel.length == 1
|
||||
@@ -61,10 +87,17 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# Is this rmq a root instance? Which means it only has 1 selected view, and that view
|
||||
# is the view you called rmq in. Which is a tad confusing, but if you call *just* rmq inside a
|
||||
# view, then only that view will be *selected* and this rmq will be *root*. If you call rmq
|
||||
# inside a controller, only controller.view will be selected and the rma instance will be a root.
|
||||
def root?
|
||||
(selected.length == 1) && (selected.first == @context)
|
||||
end
|
||||
|
||||
# The context is where rmq was created (not the selectors).
|
||||
# Normally you are inside a controller or a UIView when you execute the rmq method.
|
||||
# @return the controller's view or the view you are in when calling rmq
|
||||
def context_or_context_view
|
||||
if @context.is_a?(UIViewController)
|
||||
@context.view
|
||||
@@ -73,45 +106,43 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
def extract_views_from_selectors(view_container, working_selectors)
|
||||
unless RMQ.is_blank?(working_selectors)
|
||||
working_selectors.each do |selector|
|
||||
if selector.is_a?(UIView)
|
||||
view_container << working_selectors.delete(selector)
|
||||
end
|
||||
end
|
||||
end
|
||||
[view_container, working_selectors]
|
||||
end
|
||||
|
||||
def all_subviews_for(view)
|
||||
# TODO maybe cache this, and invalidate cache properly
|
||||
out = []
|
||||
if view.subviews
|
||||
view.subviews.each do |subview|
|
||||
out << subview
|
||||
out << all_subviews_for(subview)
|
||||
end
|
||||
out.flatten!
|
||||
end
|
||||
|
||||
out
|
||||
end
|
||||
|
||||
def all_superviews_for(view, out = [])
|
||||
if (nr = view.nextResponder) && nr.is_a?(UIView)
|
||||
out << nr
|
||||
all_superviews_for(nr, out)
|
||||
end
|
||||
out
|
||||
end
|
||||
|
||||
# Changed inspect to be useful
|
||||
# @example
|
||||
# (main)> rmq.all
|
||||
# => RMQ 172658240. 26 selected. selectors: []. .log for more info
|
||||
def inspect
|
||||
out = "RMQ #{self.object_id}. #{self.count} selected. selectors: #{self.selectors.to_s}. .log for more info"
|
||||
out << "\n[#{selected.first}]" if self.count == 1
|
||||
out
|
||||
end
|
||||
|
||||
# Super useful in the console. log outputs to the console a table of the selected views
|
||||
# @param :wide outputs wide format (really wide, but awesome: rmq.all.log :wide)
|
||||
# @example
|
||||
# (main)> rmq(UIImageView).log
|
||||
#
|
||||
# object_id | class | style_name | frame |
|
||||
# sv id | superview | subviews count | tags |
|
||||
# - - - - - - | - - - - - - - - - - - | - - - - - - - - - - - - | - - - - - - - - - - - - - - - - |
|
||||
# 168150976 | UIImageView | logo | {l: 60, t: 10, w: 200, h: 95.5} |
|
||||
# 168128784 | UIView | 0 | |
|
||||
# - - - - - - | - - - - - - - - - - - | - - - - - - - - - - - - | - - - - - - - - - - - - - - - - |
|
||||
# 168180640 | UIImageView | | {l: 1, t: 1, w: 148, h: 19} |
|
||||
# 168173616 | UIRoundedRectButton | 0 | |
|
||||
# - - - - - - | - - - - - - - - - - - | - - - - - - - - - - - - | - - - - - - - - - - - - - - - - |
|
||||
# 168204336 | UIImageView | | {l: 1, t: 0, w: 77, h: 27} |
|
||||
# 168201952 | _UISwitchInternalView | 0 | |
|
||||
# - - - - - - | - - - - - - - - - - - | - - - - - - - - - - - - | - - - - - - - - - - - - - - - - |
|
||||
# 172600352 | UIImageView | | {l: -2, t: 0, w: 79, h: 27} |
|
||||
# 168204512 | UIView | 0 | |
|
||||
# - - - - - - | - - - - - - - - - - - | - - - - - - - - - - - - | - - - - - - - - - - - - - - - - |
|
||||
# 168205504 | UIImageView | | {l: -2, t: 0, w: 131, h: 27} |
|
||||
# 168204512 | UIView | 0 | |
|
||||
# - - - - - - | - - - - - - - - - - - | - - - - - - - - - - - - | - - - - - - - - - - - - - - - - |
|
||||
# 168205600 | UIImageView | | {l: 49, t: 0, w: 29, h: 27} |
|
||||
# 168204512 | UIView | 0 | |
|
||||
# - - - - - - | - - - - - - - - - - - | - - - - - - - - - - - - | - - - - - - - - - - - - - - - - |
|
||||
# RMQ 278442176. 6 selected. selectors: [UIImageView]#
|
||||
def log(opt = nil)
|
||||
wide = (opt == :wide)
|
||||
out = "\n object_id | class | style_name | frame |"
|
||||
@@ -157,5 +188,40 @@ module RubyMotionQuery
|
||||
attr_accessor :cache_controller_rmqs
|
||||
@cache_controller_rmqs = true
|
||||
end
|
||||
|
||||
protected
|
||||
def extract_views_from_selectors(view_container, working_selectors)
|
||||
unless RMQ.is_blank?(working_selectors)
|
||||
working_selectors.each do |selector|
|
||||
if selector.is_a?(UIView)
|
||||
view_container << working_selectors.delete(selector)
|
||||
end
|
||||
end
|
||||
end
|
||||
[view_container, working_selectors]
|
||||
end
|
||||
|
||||
def all_subviews_for(view)
|
||||
# TODO maybe cache this, and invalidate cache properly
|
||||
out = []
|
||||
if view.subviews
|
||||
view.subviews.each do |subview|
|
||||
out << subview
|
||||
out << all_subviews_for(subview)
|
||||
end
|
||||
out.flatten!
|
||||
end
|
||||
|
||||
out
|
||||
end
|
||||
|
||||
def all_superviews_for(view, out = [])
|
||||
if (nr = view.nextResponder) && nr.is_a?(UIView)
|
||||
out << nr
|
||||
all_superviews_for(nr, out)
|
||||
end
|
||||
out
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,32 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# @example
|
||||
# # Standard colors:
|
||||
#
|
||||
# color.clear
|
||||
# color.white
|
||||
# color.light_gray
|
||||
# color.gray
|
||||
# color.dark_gray
|
||||
# color.black
|
||||
#
|
||||
# color.red
|
||||
# color.green
|
||||
# color.blue
|
||||
# color.yellow
|
||||
# color.orange
|
||||
# color.purple
|
||||
# color.brown
|
||||
# color.cyan
|
||||
# color.magenta
|
||||
#
|
||||
# color.table_view
|
||||
# color.scroll_view
|
||||
# color.flipside
|
||||
# color.under_page
|
||||
# color.light_text
|
||||
# color.dark_text
|
||||
class Color < UIColor
|
||||
|
||||
class << self
|
||||
@@ -36,6 +62,7 @@ module RubyMotionQuery
|
||||
alias :light_text :lightTextColor
|
||||
alias :dark_text :darkTextColor
|
||||
|
||||
# Add your own standard color
|
||||
def add_named(key, hex_or_color)
|
||||
color = if hex_or_color.is_a?(String)
|
||||
Color.from_hex(hex_or_color)
|
||||
@@ -49,6 +76,12 @@ module RubyMotionQuery
|
||||
end
|
||||
|
||||
# Thanks bubblewrap for this method
|
||||
#
|
||||
# @param hex with or without the #
|
||||
# @return UIColor
|
||||
# @example
|
||||
# color.from_hex('#ffffff')
|
||||
# color.from_hex('ffffff')
|
||||
def from_hex(hex_color)
|
||||
hex_color.gsub!("#", "")
|
||||
case hex_color.size
|
||||
|
||||
@@ -37,7 +37,7 @@ module RubyMotionQuery
|
||||
image.resizableImageWithCapInsets([opts[:top], opts[:left], opts[:bottom], opts[:right]], resizingMode: UIImageResizingModeStretch)
|
||||
end
|
||||
|
||||
# [FROM Sugarcube, thanks Sugarcube]
|
||||
# Note: FROM Sugarcube, thanks Sugarcube
|
||||
#
|
||||
# Easily take a snapshot of a `UIView`.
|
||||
#
|
||||
|
||||
@@ -20,11 +20,11 @@ module RubyMotionQuery
|
||||
end
|
||||
alias :resize :move
|
||||
|
||||
def align(direction)
|
||||
# TODO
|
||||
# rmq(UILabel).align(:left)
|
||||
# rmq(UILabel).align(:left, :top)
|
||||
end
|
||||
#def align(direction)
|
||||
## TODO
|
||||
## rmq(UILabel).align(:left)
|
||||
## rmq(UILabel).align(:left, :top)
|
||||
#end
|
||||
|
||||
def nudge(opts)
|
||||
left = opts[:left] || opts[:l] || 0
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
module RubyMotionQuery
|
||||
class RMQ
|
||||
|
||||
# Do not use
|
||||
def selectors=(value)
|
||||
@selected_dirty = true
|
||||
normalize_selectors(value)
|
||||
@_selectors = value
|
||||
end
|
||||
|
||||
# @return the selectors, which is what you used for the query
|
||||
# @example
|
||||
# (main)> rmq(UILabel, UIImageView).selectors
|
||||
# => [UILabel, UIImageView]
|
||||
def selectors
|
||||
@_selectors
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
|
||||
def match_context(new_selectors)
|
||||
match(context_or_context_view, new_selectors)
|
||||
end
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
module RubyMotionQuery
|
||||
class RMQ
|
||||
|
||||
# Most everthing uses filter to do its work
|
||||
# Most everything uses filter to do its work. This is mostly used internally
|
||||
# but you can use it too. Just pass a block that returns views, it will be
|
||||
# called for every view that is *selected*
|
||||
#
|
||||
# @param return_array returns array not rmq: return_array: true
|
||||
# @param uniq removes duplicate views: uniq: true
|
||||
# @param limit limits the number of views *per selected view*: limit: true
|
||||
def filter(opts = {}, &block)
|
||||
out = []
|
||||
limit = opts[:limit]
|
||||
@@ -25,10 +31,14 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# @return all selected views
|
||||
def all
|
||||
self.view_controller.rmq.find
|
||||
end
|
||||
|
||||
# @return a new rmq instance reducing selected views to those that match selectors provided
|
||||
#
|
||||
# @param selectors
|
||||
def and(*working_selectors)
|
||||
return self unless working_selectors
|
||||
normalize_selectors(working_selectors)
|
||||
@@ -38,6 +48,9 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# @return a new rmq instance removing selected views that match selectors provided
|
||||
#
|
||||
# @param selectors
|
||||
def not(*working_selectors)
|
||||
return self unless working_selectors
|
||||
normalize_selectors(working_selectors)
|
||||
@@ -47,6 +60,7 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# @return a new rmq instance adding the context to the selected views
|
||||
def and_self
|
||||
if @parent_rmq
|
||||
out = @parent_rmq.selected.dup
|
||||
@@ -59,15 +73,23 @@ module RubyMotionQuery
|
||||
end
|
||||
alias :add_self :and_self
|
||||
|
||||
# @return the parent rmq instance
|
||||
#
|
||||
# @example
|
||||
# rmq(test_view).find(UIImageView).tag(:foo).end.find(UILabel).tag(:bar)
|
||||
def end
|
||||
@parent_rmq || self
|
||||
end
|
||||
|
||||
# @return rmq instance selecting the parent of the selected view(s)
|
||||
def parent
|
||||
closest(UIView)
|
||||
end
|
||||
alias :superview :parent
|
||||
|
||||
# @return rmq instance selecting the parents, grandparents, etc of the selected view(s)
|
||||
#
|
||||
# @param selectors
|
||||
def parents(*working_selectors)
|
||||
normalize_selectors(working_selectors)
|
||||
|
||||
@@ -86,6 +108,11 @@ module RubyMotionQuery
|
||||
end
|
||||
alias :superviews :parents
|
||||
|
||||
# Get the descendants of each view in the current set of selected views, filtered by a selector(s)
|
||||
#
|
||||
# @return rmq instance selecting the children, grandchildren, etc of the selected view(s)
|
||||
#
|
||||
# @param selectors
|
||||
def find(*working_selectors)
|
||||
normalize_selectors(working_selectors)
|
||||
|
||||
@@ -103,6 +130,9 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# @return rmq instance selecting the children of the selected view(s)
|
||||
#
|
||||
# @param selectors
|
||||
def children(*working_selectors)
|
||||
normalize_selectors(working_selectors)
|
||||
|
||||
@@ -121,12 +151,20 @@ module RubyMotionQuery
|
||||
end
|
||||
alias :subviews :children
|
||||
|
||||
|
||||
# @return rmq instance selecting the siblings of the selected view(s)
|
||||
#
|
||||
# @param selectors
|
||||
def siblings(*working_selectors)
|
||||
normalize_selectors(working_selectors)
|
||||
|
||||
self.parent.children.not(selected)
|
||||
end
|
||||
|
||||
|
||||
# @return rmq instance selecting the sibling above to the selected view(s)
|
||||
#
|
||||
# @param selectors
|
||||
def next(*working_selectors)
|
||||
normalize_selectors(working_selectors)
|
||||
|
||||
@@ -139,6 +177,9 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# @return rmq instance selecting the sibling below to the selected view(s)
|
||||
#
|
||||
# @param selectors
|
||||
def prev(*working_selectors)
|
||||
normalize_selectors(working_selectors)
|
||||
|
||||
@@ -151,6 +192,12 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# For each view in the set, get the first view that matches the selector by testing the view itself and
|
||||
# traversing up through its ancestors in the tree
|
||||
#
|
||||
# @return rmq instance selecting the first parent or grandparent or ancestor up the tree of the selected view(s)
|
||||
#
|
||||
# @param selectors
|
||||
def closest(*working_selectors)
|
||||
normalize_selectors(working_selectors)
|
||||
|
||||
@@ -159,6 +206,7 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# @return UIViewController of this rmq instance
|
||||
def view_controller
|
||||
@_view_controller ||= begin
|
||||
if @context.is_a?(UIViewController)
|
||||
@@ -169,6 +217,7 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
# @return UIView of this rmq instance's controller
|
||||
def root_view
|
||||
vc = self.view_controller
|
||||
if RMQ.is_blank?(vc)
|
||||
|
||||
@@ -20,9 +20,8 @@ module RubyMotionQuery
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Given a UIView, returns the UIViewController it is sitting in, or nil if it's not
|
||||
# sitting anywhere in particular
|
||||
# @param view
|
||||
# @returns the UIViewController it is sitting in, or nil if it's not sitting anywhere in particular
|
||||
def controller_for_view(view)
|
||||
# Non-recursive for speed
|
||||
while view
|
||||
|
||||
Reference in New Issue
Block a user