Started to add yard docs. Updated readme, I removed alpha warning because I think we're all good now

This commit is contained in:
Todd Werth
2013-08-04 09:08:35 -07:00
parent a037806df7
commit 8cc1680c5b
9 changed files with 214 additions and 65 deletions

1
.yardopts Normal file
View File

@@ -0,0 +1 @@
motion/**/*.rb

View File

@@ -1,17 +1,17 @@
![RQM logo](http://ir_wp.s3.amazonaws.com/wp-content/uploads/sites/9/2013/07/rmq_logo.png)
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.**
[![Dependency Status](https://gemnasium.com/infinitered/rmq.png)](https://gemnasium.com/infinitered/rmq)
[![Build Status](https://travis-ci.org/infinitered/rmq.png?branch=master)](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

View File

@@ -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,6 +71,12 @@ module RubyMotionQuery
# Normally used to get the only view in selected.
#
# @example
# # 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
@@ -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

View File

@@ -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

View File

@@ -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`.
#

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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