ruby_motion_query 0.5.8 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -1478
- data/motion/ext.rb +1 -1
- data/motion/ruby_motion_query/actions.rb +68 -4
- data/motion/ruby_motion_query/animations.rb +3 -0
- data/motion/ruby_motion_query/debug.rb +1 -0
- data/motion/ruby_motion_query/device.rb +8 -0
- data/motion/ruby_motion_query/grid.rb +370 -0
- data/motion/ruby_motion_query/image.rb +2 -0
- data/motion/ruby_motion_query/inspector.rb +354 -0
- data/motion/ruby_motion_query/inspector_stylesheet.rb +106 -0
- data/motion/ruby_motion_query/position.rb +39 -20
- data/motion/ruby_motion_query/rect.rb +557 -0
- data/motion/ruby_motion_query/stylers/ui_button_styler.rb +16 -3
- data/motion/ruby_motion_query/stylers/ui_view_styler.rb +71 -43
- data/motion/ruby_motion_query/stylesheet.rb +11 -0
- data/motion/ruby_motion_query/subviews.rb +2 -0
- data/motion/ruby_motion_query/tags.rb +14 -0
- data/motion/ruby_motion_query/utils.rb +8 -5
- data/motion/ruby_motion_query/version.rb +1 -1
- data/templates/view/app/views/name.rb +2 -1
- metadata +8 -4
data/README.md
CHANGED
@@ -1,79 +1,41 @@
|
|
1
1
|
![RMQ logo](https://raw.github.com/infinitered/rmq/master/resources/logo@2x.png?raw=true)
|
2
2
|
|
3
|
-
#
|
3
|
+
# RMQ - RubyMotion Front-end Library
|
4
4
|
|
5
5
|
[![Dependency Status](https://gemnasium.com/infinitered/rmq.png)](https://gemnasium.com/infinitered/rmq)
|
6
6
|
[![Build Status](https://travis-ci.org/infinitered/rmq.png?branch=master)](https://travis-ci.org/infinitered/rmq)
|
7
7
|
[![Gem Version](https://badge.fury.io/rb/ruby_motion_query.png)](http://badge.fury.io/rb/ruby_motion_query)
|
8
8
|
[![Crusher.io optimized](http://www.crusher.io/repo/infinitered/rmq/badge)](http://www.crusher.io/repo/infinitered/rmq)
|
9
9
|
|
10
|
-
A fast, non-polluting, chaining, front-end library. It’s like jQuery for [RubyMotion](http://rubymotion.com)
|
10
|
+
A fast, non-polluting, chaining, front-end library. It’s like jQuery for [RubyMotion](http://rubymotion.com) plus templates, stylesheets, events, animations, etc.
|
11
11
|
|
12
|
-
|
12
|
+
One of RMQ's goal is to have the best [documentation][1] of any RubyMotion UI library.
|
13
13
|
|
14
|
-
|
14
|
+
## v0.6.0
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
----------
|
19
|
-
|
20
|
-
## General
|
21
|
-
|
22
|
-
### Some of the very cool features:
|
23
|
-
- events and gestures
|
24
|
-
- view factory
|
25
|
-
- stylesheets
|
26
|
-
- actions
|
27
|
-
- position
|
28
|
-
- selecting (_querying views_)
|
29
|
-
- templates
|
30
|
-
- traversal through view hierarchy (moving around the tree)
|
31
|
-
- animations
|
32
|
-
- tagging
|
33
|
-
- colors
|
34
|
-
- fonts
|
35
|
-
- image utilities
|
36
|
-
- app
|
37
|
-
- device
|
38
|
-
|
39
|
-
[![features](https://ir_wp.s3.amazonaws.com/wp-content/uploads/sites/11/2014/03/rmq_parts-300x231.png)](https://ir_wp.s3.amazonaws.com/wp-content/uploads/sites/11/2014/03/rmq_parts.png)
|
16
|
+
<br />
|
40
17
|
|
41
18
|
----------
|
42
19
|
|
43
|
-
|
20
|
+
## Read the [RMQ Documentation][1] here
|
44
21
|
|
45
22
|
----------
|
46
23
|
|
47
|
-
|
48
|
-
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.
|
49
|
-
|
50
|
-
RMQ **doesn't require any** other wrapper or gem.
|
51
|
-
|
52
|
-
> If you preferred jQuery over Prototype, you'll love RMQ.
|
53
|
-
|
54
|
-
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.
|
24
|
+
<br />
|
55
25
|
|
56
26
|
## Quick Start
|
57
27
|
|
58
28
|
```
|
59
29
|
gem install ruby_motion_query
|
60
|
-
|
61
|
-
|
30
|
+
# Update your gem file to use RMQ-Edge
|
31
|
+
gem 'ruby_motion_query', :git => 'git@github.com:infinitered/rmq.git'
|
62
32
|
bundle
|
63
33
|
rake
|
64
34
|
```
|
65
35
|
|
66
|
-
|
67
|
-
|
68
|
-
```
|
69
|
-
gem install ruby_motion_query
|
70
|
-
rbenv rehash
|
71
|
-
rmq create my_app
|
72
|
-
cd my_app
|
73
|
-
bundle
|
74
|
-
rake
|
75
|
-
```
|
36
|
+
rbenv rehash after gem install if you use rbenv
|
76
37
|
|
38
|
+
<br />
|
77
39
|
|
78
40
|
## Installation
|
79
41
|
|
@@ -98,1458 +60,42 @@ for **bleeding edge**, add this to your `Gemfile`:
|
|
98
60
|
- `gem 'ruby_motion_query', :git => 'git@github.com:infinitered/rmq.git'`
|
99
61
|
|
100
62
|
|
101
|
-
## Deprecation
|
102
|
-
|
103
|
-
- **UIView#rmq_did_create(self_in_rmq)** - *Use rmq_build instead*
|
104
|
-
|
105
|
-
<br />
|
106
|
-
|
107
|
-
## Usage
|
108
|
-
|
109
|
-
----
|
110
|
-
|
111
|
-
|
112
|
-
<br />
|
113
|
-
|
114
|
-
### Example App
|
115
|
-
|
116
|
-
----
|
117
|
-
|
118
|
-
*Clone this repo and run the example app to see an example of use.*
|
119
|
-
|
120
|
-
git clone git@github.com:infinitered/rmq.git
|
121
|
-
cd rmq
|
122
|
-
rake
|
123
|
-
|
124
|
-
The example app works in any orientation, on both iPhone and iPad. Notice how the benchmark popup is done with RMQ, then think about how you'd do that without it.
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
<br />
|
129
|
-
|
130
|
-
### What's an rmq instance?
|
131
|
-
|
132
|
-
----
|
133
|
-
|
134
|
-
- an rmq instance is an array-like object containing UIViews
|
135
|
-
- rmq() never returns nil. If nothing is selected, it's an empty [ ] array-like
|
136
|
-
object
|
137
|
-
- an rmq object always (almost always) returns either itself or a new
|
138
|
-
rmq object. This is how chaining works. You do not need to worry if
|
139
|
-
an rmq is blank or not, everything always works without throwing a
|
140
|
-
nil exception
|
141
|
-
- jQuery uses the DOM, what is rmq using for the "DOM"? It uses the
|
142
|
-
controller it was called in. The "DOM" is the controller's subview
|
143
|
-
tree. If you call rmq inside a view, it will attach to the
|
144
|
-
controller that the view is currently in or to the current screen's
|
145
|
-
controller
|
146
|
-
|
147
|
-
|
148
|
-
<br />
|
149
|
-
|
150
|
-
### Basic syntax
|
151
|
-
|
152
|
-
----
|
153
|
-
|
154
|
-
The main command is `rmq` and you use it everywhere. You can rename this by aliasing the methods in `ext.rb`.
|
155
|
-
|
156
|
-
```ruby
|
157
|
-
# Like jQuery you wrap your objects or selectors in a rmq(), here are some examples
|
158
|
-
rmq(my_view).show
|
159
|
-
rmq(UILabel).hide
|
160
|
-
|
161
|
-
# You can use zero or more selectors, all these are valid
|
162
|
-
rmq(my_view, UILabel).hide
|
163
|
-
rmq(:a_tag, :a_style_name, UIImageView).hide
|
164
|
-
rmq(hidden: true).show
|
165
|
-
|
166
|
-
# If you use a set of selectors, they are an "or", to do an "and" use .and
|
167
|
-
rmq(UIImageView).and(hidden: true).show
|
168
|
-
```
|
169
|
-
|
170
|
-
**rmq by itself is the rmq instance of the current UIViewController if you're inside a UIViewController**.
|
171
|
-
|
172
|
-
If you're inside a UIView you've created, `rmq.closest(UIControl)` is the same as `rmq(self).closest(UIControl)`.
|
173
|
-
|
174
|
-
#### rmq is always an array-like object (enumerablish), never nil, etc:
|
175
|
-
|
176
|
-
Because of this, you **never have to check** if your selectors return anything before calling actions or other methods on your rmq object.
|
177
|
-
|
178
|
-
```ruby
|
179
|
-
# This will hide any UILabel in the controller, if any exist. If not, nothing happens
|
180
|
-
rmq(UILabel).hide
|
181
|
-
|
182
|
-
# Because of this, you can create chains without worry of exceptions
|
183
|
-
rmq(:this_tag_does_not_exist).show.apply_style(:my_style_name).on(:touch_down){puts 'score!'}
|
184
|
-
```
|
185
|
-
|
186
|
-
#### Almost all methods of an rmq object return either itself or another rmq object, so you can chain:
|
187
|
-
```ruby
|
188
|
-
rmq.append(UILabel, :label_style).on(:tap){|sender,event| sender.hide}
|
189
|
-
|
190
|
-
# or
|
191
|
-
|
192
|
-
rmq.closest(AddEntry).find(:delete_button).hide
|
193
|
-
rmq(AddEntry).find(UILabel).blink
|
194
|
-
|
195
|
-
```
|
196
|
-
|
197
|
-
If you want the actual inner object(s), use **.get**
|
198
|
-
|
199
|
-
```ruby
|
200
|
-
# returns my_view
|
201
|
-
rmq(my_view).get
|
202
|
-
|
203
|
-
# returns an array
|
204
|
-
rmq(UILabel).get
|
205
|
-
```
|
206
|
-
|
207
|
-
|
208
|
-
<br />
|
209
|
-
|
210
|
-
### Command-line Tool and Generators
|
211
|
-
|
212
|
-
----
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
Like Rails, RMQ provides a command-line tool, mostly for generating files. **Create a new app**:
|
217
|
-
|
218
|
-
```
|
219
|
-
> rmq create my_app
|
220
|
-
```
|
221
|
-
|
222
|
-
To get all the commands available just do:
|
223
|
-
|
224
|
-
```
|
225
|
-
> rmq
|
226
|
-
```
|
227
|
-
|
228
|
-
To generate **controllers, models, views**, etc, do the following:
|
229
|
-
|
230
|
-
```
|
231
|
-
> rmq create model foo
|
232
|
-
> rmq create controller bar
|
233
|
-
> rmq create view foo_bar
|
234
|
-
> rmq create shared some_class_used_app_wide
|
235
|
-
> rmq create lib some_class_used_by_multiple_apps
|
236
|
-
|
237
|
-
> rmq create collection_view_controller foos
|
238
|
-
> rmq create table_view_controller bars
|
239
|
-
|
240
|
-
> rmq create view my_view dry_run
|
241
|
-
```
|
242
|
-
|
243
|
-
I recomend you play around with it, do this:
|
244
|
-
|
245
|
-
```
|
246
|
-
> cd
|
247
|
-
> cd Desktop
|
248
|
-
> rmq create test_rmq_app
|
249
|
-
> cd test_rmq_app
|
250
|
-
> rmq create table_view_controller people
|
251
|
-
> rmq create view group
|
252
|
-
> bundle
|
253
|
-
> rake
|
254
|
-
```
|
255
|
-
|
256
|
-
|
257
|
-
<br />
|
258
|
-
|
259
|
-
### Selectors
|
260
|
-
|
261
|
-
----
|
262
|
-
|
263
|
-
- Constant
|
264
|
-
- :a_tag
|
265
|
-
- :a_style_name
|
266
|
-
- my_view_instance
|
267
|
-
- text: 'you can select via attributes also'
|
268
|
-
- :another_tag, UILabel, text: 'an array' <- this is an "or", use .and for and
|
269
|
-
|
270
|
-
The more common use is to select any view or views you have assigned to variables, then perform actions on them. For example:
|
271
|
-
|
272
|
-
```ruby
|
273
|
-
view_1 = UIView.alloc.initWithFrame([[10,10],[100, 10]])
|
274
|
-
view_2 = UIView.alloc.initWithFrame([[10,20],[100, 10]])
|
275
|
-
@view_3 = rmq.append(UIView, :some_style).get
|
276
|
-
|
277
|
-
rmq(view_1).layout(l: 20, t: 40, w: 80, h: 20)
|
278
|
-
|
279
|
-
rmq(view_1, view_2, @view_3).hide
|
280
|
-
a = [view_1, view_2, @view_3]
|
281
|
-
|
282
|
-
rmq(a).distribute(:vertical, margin: 10)
|
283
|
-
|
284
|
-
rmq(a).on(:tap) do |sender|
|
285
|
-
puts 'Tapped'
|
286
|
-
end
|
287
|
-
```
|
288
|
-
|
289
|
-
|
290
|
-
<br />
|
291
|
-
|
292
|
-
### Subviews - appending, creating, etc
|
293
|
-
|
294
|
-
----
|
295
|
-
|
296
|
-
* **build**: takes an existing view, applies the style if it exists, then calls rmq_build method
|
297
|
-
* **create**: creates the view when given the class, or uses an existing view you pass it, then does a [build]
|
298
|
-
* **append**: [create] + appends the view to the end of the subview tree or to then end of the children of a view (if called on an rmq object with that view in it)
|
299
|
-
* **prepend**: Same as [append], but inserts the view to beginning of the subview tree (overall or view's children)
|
300
|
-
* **insert**: Same as [append], but inserts the view at the index of the subview tree (overall or view's children)
|
301
|
-
|
302
|
-
```ruby
|
303
|
-
rmq.append(UILabel) # Creates a UILabel in the current controller
|
304
|
-
rmq.append(UILabel, :my_label_style)
|
305
|
-
rmq.append(UILabel.alloc.initWithFrame([[0,0],[10,10]]), :my_label_style)
|
306
|
-
|
307
|
-
rmq(my_view).append(UIButton)
|
308
|
-
rmq(my_view).remove
|
309
|
-
rmq(my_vuew).children.remove
|
310
|
-
|
311
|
-
rmq(UIView).append(UIButton, :delete_me) # A custom button for all views
|
312
|
-
|
313
|
-
rmq.unshift(UILabel) # Adds to index 0 of the subviews
|
314
|
-
rmq.unshift(UILabel, :my_style)
|
315
|
-
rmq.insert(UILabel, at_index: 2)
|
316
|
-
rmq.insert(UILabel, at_index: 2, style: :my_style)
|
317
|
-
rmq.insert(UILabel, below_view: some_view_of_mine)
|
318
|
-
rmq.insert(UILabel, below_view: some_view_of_mine, style: :my_style)
|
319
|
-
|
320
|
-
rmq(my_view).parent # .superview works too
|
321
|
-
rmq(my_view).parents # all parents up the tree, up to the root
|
322
|
-
rmq(my_view).children
|
323
|
-
rmq(my_view).find # children, grandchildren, etc
|
324
|
-
rmq.root_view
|
325
|
-
rmq.view_controller
|
326
|
-
```
|
327
|
-
|
328
|
-
Often when appending a subview, you assign the view to a instance variable, like so:
|
329
|
-
|
330
|
-
```ruby
|
331
|
-
@name = rmq.append(UILabel, :name).get
|
332
|
-
```
|
333
|
-
|
334
|
-
The **.get** returns the actual view. Without it you'll get a reference to an rmq instance, which is how
|
335
|
-
chaining works.
|
336
|
-
|
337
|
-
This is such a common pattern, an RMQ user (https://github.com/shreeve) created append!, which I've included into RMQ.
|
338
|
-
The ! version of append or create returns the view directly:
|
339
|
-
|
340
|
-
```ruby
|
341
|
-
@name = rmq.append!(UILabel, :name)
|
342
|
-
# Or the even shorter:
|
343
|
-
@name = rmq.append! UILabel, :name
|
344
|
-
```
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
#### Create a view
|
350
|
-
If you want to create a view but not add it to the subviews of any other view, you can
|
351
|
-
use #create. It's basically #append without the actual appending.
|
352
|
-
This is very handy for stuff like table cells:
|
353
|
-
|
354
|
-
```ruby
|
355
|
-
# In your controller that is a delegate for a UITableView
|
356
|
-
def tableView(table_view, cellForRowAtIndexPath: index_path)
|
357
|
-
cell = table_view.dequeueReusableCellWithIdentifier(CELL_IDENTIFIER) || begin
|
358
|
-
rmq.create(StoreCell, :store_cell, reuse_identifier: CELL_IDENTIFIER).get
|
359
|
-
|
360
|
-
# If you want to change the style of the cell, you can do something like this:
|
361
|
-
# rmq.create(StoreCell, :store_cell, reuse_identifier: CELL_IDENTIFIER, cell_style: UITableViewCellStyleSubtitle).get
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
# Your cell
|
366
|
-
class StoreCell < UITableViewCell
|
367
|
-
def rmq_build
|
368
|
-
q = rmq(self.contentView)
|
369
|
-
q.append(UILabel, :title_label) # <- this works even though this object isn't in a controller
|
370
|
-
|
371
|
-
# Use built in views, this assumes you're using the UITableViewCellStyleSubtitle style for the cell
|
372
|
-
q.build(self.textLabel, :cell_label)
|
373
|
-
q.build(self.imageView, :cell_image)
|
374
|
-
q.build(self.detailTextLabel, :cell_label_detail)
|
375
|
-
end
|
376
|
-
end
|
377
|
-
```
|
378
|
-
|
379
|
-
|
380
|
-
<br />
|
381
|
-
|
382
|
-
### Traversing
|
383
|
-
|
384
|
-
----
|
385
|
-
|
386
|
-
Moving around the subview tree.
|
387
|
-
|
388
|
-
Used often:
|
389
|
-
|
390
|
-
- view_controller
|
391
|
-
- root_view # View of the view_controller
|
392
|
-
|
393
|
-
The rest of traversing isn't used too often, but when you need it, it's super handy. The most common methods used are:
|
394
|
-
|
395
|
-
- window # Window of the root_view
|
396
|
-
- all
|
397
|
-
- closest
|
398
|
-
- find
|
399
|
-
|
400
|
-
These are less common:
|
401
|
-
|
402
|
-
- and
|
403
|
-
- not
|
404
|
-
- and_self
|
405
|
-
- back - _rmq(test_view).find(UIImageView).tag(:foo).back.find(UILabel).tag(:bar)_
|
406
|
-
- children
|
407
|
-
- siblings
|
408
|
-
- next
|
409
|
-
- prev
|
410
|
-
- parent
|
411
|
-
- parents
|
412
|
-
- filter
|
413
|
-
|
414
|
-
|
415
|
-
<br />
|
416
|
-
|
417
|
-
### Enumerablish
|
418
|
-
|
419
|
-
----
|
420
|
-
|
421
|
-
A rmq object is like an enumerable, but each method returns a rmq object instead of a enumerable. For example, these methods:
|
422
|
-
|
423
|
-
- each
|
424
|
-
- map
|
425
|
-
- select
|
426
|
-
- grep
|
427
|
-
- detect
|
428
|
-
- inject
|
429
|
-
- first
|
430
|
-
- last
|
431
|
-
- []
|
432
|
-
- <<
|
433
|
-
- *etc*
|
434
|
-
|
435
|
-
all return another rmq instance, so you can chain.
|
436
|
-
|
437
|
-
You can also do **rmq.length** and **rmq[0]** like an array
|
438
|
-
|
439
|
-
**.to_a** gives you an actual array, so will **.get** (this is preferred)
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
<br />
|
444
|
-
|
445
|
-
### Layout/Frame System & Position
|
446
|
-
|
447
|
-
----
|
448
|
-
|
449
|
-
|
450
|
-
```
|
451
|
-
Options for layout, move, and frame:
|
452
|
-
|
453
|
-
:full
|
454
|
-
:left :l :from_right :fr
|
455
|
-
:top :t :from_right :fb
|
456
|
-
:width :w
|
457
|
-
:height :h
|
458
|
-
|
459
|
-
Options for nudge:
|
460
|
-
|
461
|
-
:left :l
|
462
|
-
:right :r
|
463
|
-
:up :u
|
464
|
-
:down :d
|
465
|
-
|
466
|
-
Values for each option can be:
|
467
|
-
|
468
|
-
signed int
|
469
|
-
float
|
470
|
-
```
|
471
|
-
|
472
|
-
```ruby
|
473
|
-
# In a style
|
474
|
-
def some_style(st)
|
475
|
-
st.frame = {l: 20, t: 20, w: 100, h: 50}
|
476
|
-
end
|
477
|
-
|
478
|
-
|
479
|
-
# Layout, move, or resize selected views
|
480
|
-
rmq(your_view).layout(left: 20, top: 20, width: 100, height: 50)
|
481
|
-
rmq(your_view).layout(l: 20)
|
482
|
-
rmq(your_view).layout(left: 20)
|
483
|
-
rmq(your_view).layout(l: 20, t: 20, w: 100, h: 50)
|
484
|
-
rmq(your_view).layout(left: 20, top: 20, width: 100, height: 50)
|
485
|
-
|
486
|
-
rmq(your_view).move(left: 20) # alias for layout
|
487
|
-
rmq(your_view).move(l: 30, t: 50) # alias for layout
|
488
|
-
rmq(your_view).resize(width: 100, height: 50) # alias for layout
|
489
|
-
|
490
|
-
# Nudge pushes them in a direction
|
491
|
-
rmq(your_view).nudge(d: 20)
|
492
|
-
rmq(your_view).nudge(down: 20)
|
493
|
-
rmq(your_view).nudge(l: 20, r: 20, u: 100, d: 50)
|
494
|
-
rmq(your_view).nudge(left: 20, right: 20, up: 100, down: 50)
|
495
|
-
|
496
|
-
# Distribute
|
497
|
-
rmq(UIButton).distribute
|
498
|
-
rmq(UIButton).distribute(:vertical)
|
499
|
-
rmq(UIButton).distribute(:horizontal)
|
500
|
-
rmq(UIButton).distribute(:vertical, margin: 20)
|
501
|
-
rmq(my_view, my_other_view, third_view).distribute(:vertical, margin: 10)
|
502
|
-
rmq(UIButton).distribute(:vertical, margins: [5,5,10,5,10,5,10,20])
|
503
|
-
```
|
504
|
-
|
505
|
-
|
506
|
-
<br />
|
507
|
-
|
508
|
-
### Events and Gestures
|
509
|
-
|
510
|
-
----
|
511
|
-
|
512
|
-
#### On / Off
|
513
|
-
|
514
|
-
To add an event, use .on, to remove it it, use .off
|
515
|
-
|
516
|
-
```ruby
|
517
|
-
# Simple example
|
518
|
-
rmq(UIView).on(:tap){|sender| rmq(sender).hide}
|
519
|
-
|
520
|
-
# Adding an Event during creation
|
521
|
-
view_q = rmq.append(UIView).on(:tap) do |sender, event|
|
522
|
-
# do something here
|
523
|
-
end
|
524
|
-
|
525
|
-
# removing an Event
|
526
|
-
view_q.off(:tap)
|
527
|
-
|
528
|
-
# or you remove them all
|
529
|
-
view_q.off
|
530
|
-
|
531
|
-
# like everything in RMQ, this works on all items selected
|
532
|
-
rmq(UIView).off(:tap)
|
533
|
-
```
|
534
|
-
|
535
|
-
#### RubyMotionQuery::Event
|
536
|
-
|
537
|
-
In RMQ events and gestures are normalized with the same API. For example removing events or gestures is foo.off, and the appropriate thing happens.
|
538
|
-
|
539
|
-
If you see Event, just remember that's either an event or gesture. I decided to call them Events
|
540
|
-
|
541
|
-
##### Type of events and gestures
|
542
|
-
|
543
|
-
```ruby
|
544
|
-
# Events on controls
|
545
|
-
:touch
|
546
|
-
:touch_up
|
547
|
-
:touch_down
|
548
|
-
:touch_start
|
549
|
-
:touch_stop
|
550
|
-
:change
|
551
|
-
|
552
|
-
:touch_down_repeat
|
553
|
-
:touch_drag_inside
|
554
|
-
:touch_drag_outside
|
555
|
-
:touch_drag_enter
|
556
|
-
:touch_drag_exit
|
557
|
-
:touch_up_inside
|
558
|
-
:touch_up_outside
|
559
|
-
:touch_cancel
|
560
|
-
|
561
|
-
:value_changed
|
562
|
-
|
563
|
-
:editing_did_begin
|
564
|
-
:editing_changed
|
565
|
-
:editing_did_change
|
566
|
-
:editing_did_end
|
567
|
-
:editing_did_endonexit
|
568
|
-
|
569
|
-
:all_touch
|
570
|
-
:all_editing
|
571
|
-
|
572
|
-
:application
|
573
|
-
:system
|
574
|
-
:all
|
575
|
-
|
576
|
-
# Gestures
|
577
|
-
:tap
|
578
|
-
:pinch
|
579
|
-
:rotate
|
580
|
-
:swipe
|
581
|
-
:swipe_up
|
582
|
-
:swipe_down
|
583
|
-
:swipe_left
|
584
|
-
:swipe_right
|
585
|
-
:pan
|
586
|
-
:long_press
|
587
|
-
```
|
588
|
-
|
589
|
-
##### Interesting methods of an RubyMotionQuery::Event:
|
590
|
-
```ruby
|
591
|
-
foo.sender
|
592
|
-
foo.event
|
593
|
-
|
594
|
-
foo.gesture?
|
595
|
-
foo.recognizer
|
596
|
-
foo.gesture
|
597
|
-
|
598
|
-
foo.location
|
599
|
-
foo.location_in
|
600
|
-
|
601
|
-
foo.sdk_event_or_recognizer
|
602
|
-
```
|
603
|
-
|
604
|
-
TODO, need many examples here
|
605
|
-
|
606
|
-
#### RubyMotionQuery::Events
|
607
|
-
|
608
|
-
The internal store of events in a UIView. It's rmq.events, you won't use it too often
|
609
|
-
|
610
|
-
|
611
|
-
<br />
|
612
|
-
|
613
|
-
### Tags
|
614
|
-
|
615
|
-
----
|
616
|
-
|
617
|
-
```ruby
|
618
|
-
# Add tags
|
619
|
-
rmq(my_view).tag(:your_tag)
|
620
|
-
rmq(my_view).clear_tags.tag(:your_new_tag)
|
621
|
-
|
622
|
-
rmq(my_view).find(UILabel).tag(:selected, :customer)
|
623
|
-
|
624
|
-
# You can optionally store a value in the tag, which can be super useful in some rare situations
|
625
|
-
rmq(my_view).tag(your_tag: 22)
|
626
|
-
rmq(my_view).tag(your_tag: 22, your_other_tag: 'Hello world')
|
627
|
-
|
628
|
-
|
629
|
-
# You can use a tag or tags as selecors
|
630
|
-
rmq(:selected).hide
|
631
|
-
rmq(:your_tag).and(:selected).hide
|
632
|
-
|
633
|
-
# Get tags for a view
|
634
|
-
your_view.rmq_data.tags
|
635
|
-
# Also
|
636
|
-
your_view.rmq_data.has_tag?(:foo)
|
637
|
-
your_view.rmq_data.tag_names
|
638
|
-
```
|
639
|
-
|
640
|
-
|
641
|
-
<br />
|
642
|
-
|
643
|
-
### Actions
|
644
|
-
|
645
|
-
----
|
646
|
-
|
647
|
-
```ruby
|
648
|
-
rmq(UILabel).attr(text: 'Foo bar')
|
649
|
-
rmq(UILabel).send(:some_method, args)
|
650
|
-
rmq(my_view).hide
|
651
|
-
rmq(my_view).show
|
652
|
-
rmq(my_view).toggle
|
653
|
-
rmq(my_view).toggle_enabled
|
654
|
-
rmq(my_text_field).focus # or .become_first_responder
|
655
|
-
```
|
656
|
-
|
657
|
-
|
658
|
-
<br />
|
659
|
-
|
660
|
-
### Animate
|
661
|
-
|
662
|
-
----
|
663
|
-
|
664
|
-
The most basic:
|
665
|
-
|
666
|
-
```ruby
|
667
|
-
rmq.animate do |q|
|
668
|
-
rmq(UIButton).nudge r: 40
|
669
|
-
end
|
670
|
-
```
|
671
|
-
|
672
|
-
Some more options, this time it is animating a selected view:
|
673
|
-
|
674
|
-
```ruby
|
675
|
-
rmq(my_view).animate(
|
676
|
-
duration: 0.3,
|
677
|
-
animations: lambda{|q|
|
678
|
-
q.move left: 20
|
679
|
-
}
|
680
|
-
)
|
681
|
-
```
|
682
|
-
|
683
|
-
```ruby
|
684
|
-
# As an example, this is the implementation of .animations.throb
|
685
|
-
rmq(selectors).animate(
|
686
|
-
duration: 0.1,
|
687
|
-
animations: -> (q) {
|
688
|
-
q.style {|st| st.scale = 1.1}
|
689
|
-
},
|
690
|
-
completion: -> (did_finish, q) {
|
691
|
-
q.animate(
|
692
|
-
duration: 0.4,
|
693
|
-
animations: -> (cq) {
|
694
|
-
cq.style {|st| st.scale = 1.0}
|
695
|
-
}
|
696
|
-
)
|
697
|
-
}
|
698
|
-
)
|
699
|
-
|
700
|
-
# You can pass any options that animateWithDuration allows: options: YOUR_OPTIONS
|
701
|
-
```
|
702
|
-
|
703
|
-
|
704
|
-
<br />
|
705
|
-
|
706
|
-
### Animations
|
707
|
-
|
708
|
-
----
|
709
|
-
|
710
|
-
See animate above.
|
711
|
-
|
712
|
-
#### Current animations included:
|
713
|
-
|
714
|
-
```ruby
|
715
|
-
rmq(my_view).animations.fade_in
|
716
|
-
rmq(my_view).animations.fade_in(duration: 0.8)
|
717
|
-
rmq(my_view).animations.fade_out
|
718
|
-
rmq(my_view).animations.fade_out(duration: 0.8)
|
719
|
-
|
720
|
-
rmq(my_view).animations.blink
|
721
|
-
rmq(my_view).animations.throb
|
722
|
-
rmq(my_view).animations.sink_and_throb
|
723
|
-
rmq(my_view).animations.land_and_sink_and_throb
|
724
|
-
rmq(my_view).animations.drop_and_spin
|
725
|
-
|
726
|
-
rmq.animations.start_spinner
|
727
|
-
rmq.animations.stop_spinner
|
728
|
-
```
|
729
|
-
|
730
|
-
|
731
|
-
<br />
|
732
|
-
|
733
|
-
### Color
|
734
|
-
|
735
|
-
----
|
736
|
-
|
737
|
-
```ruby
|
738
|
-
rmq.color.red
|
739
|
-
rmq.color.from_hex('#ffffff')
|
740
|
-
rmq.color.from_hex('ffffff')
|
741
|
-
rmq.color.from_rgba(128, 128, 128, 0.5)
|
742
|
-
|
743
|
-
# Add a new standard color
|
744
|
-
rmq.color.add_named :pitch_black, '#000000'
|
745
|
-
# Or
|
746
|
-
rmq.color.add_named :pitch_black, rmq.color.black
|
747
|
-
|
748
|
-
# In a stylesheet you don't need the rmq
|
749
|
-
color.pitch_black
|
750
|
-
color.red
|
751
|
-
```
|
752
|
-
|
753
|
-
<br />
|
754
|
-
|
755
|
-
### Font
|
756
|
-
|
757
|
-
----
|
758
|
-
|
759
|
-
```ruby
|
760
|
-
rmq.font.system(12)
|
761
|
-
rmq.font_with_name('Helvetica', 18)
|
762
|
-
rmq.font.family_list # useful in console
|
763
|
-
rmq.font.for_family('Helvetica') # useful in console
|
764
|
-
|
765
|
-
# Add a new standard font
|
766
|
-
font_family = 'Helvetica Neue'
|
767
|
-
font.add_named :large, font_family, 36
|
768
|
-
font.add_named :medium, font_family, 24
|
769
|
-
font.add_named :small, font_family, 18
|
770
|
-
|
771
|
-
# then use them like so
|
772
|
-
rmq.font.large
|
773
|
-
rmq.font.small
|
774
|
-
|
775
|
-
# In a stylesheet you don't need the rmq
|
776
|
-
font.medium
|
777
|
-
font.system(14)
|
778
|
-
```
|
779
|
-
|
780
|
-
|
781
63
|
<br />
|
782
64
|
|
783
|
-
###
|
784
|
-
|
785
|
-
----
|
786
|
-
|
787
|
-
|
788
|
-
RMQ provides various features for dealing with images.
|
789
|
-
|
790
|
-
If you want to load an image from your **/resources** folder (_which is where they should be_), you can either load it and cache it (**imageNamed**) or load it and not cache it (**NSBundle.mainBundle.pathForResource**):
|
791
|
-
|
792
|
-
```ruby
|
793
|
-
rmq.image.resource('foo') # /resources/foo@2x.png
|
794
|
-
rmq.image.resource('foo', cached: false)
|
795
|
-
# In a stylesheet
|
796
|
-
st.background_image = image.resource('foo')
|
797
|
-
```
|
798
|
-
|
799
|
-
**Capped images**
|
800
|
-
|
801
|
-
Sometimes when you apply a background_image to a view you want the image to stretch to the size of the view without stretching the corners of the image, for example if you're making a rounded button. The SDK has a nice feature for this, called UIImage#resizableImageWithCapInsets. It stretches the center of your image, but not the corners.
|
802
|
-
|
803
|
-
Let's say you want to create this, like we did in [Temple](http://app.temple.cx/):
|
804
|
-
|
805
|
-
![Bar](https://ir_wp.s3.amazonaws.com/wp-content/uploads/sites/18/2014/03/bar.png)
|
806
|
-
|
807
|
-
The red bar grows horizontally. But it has rounded caps. So we created this image ![Cap image](https://ir_wp.s3.amazonaws.com/wp-content/uploads/sites/18/2014/03/bar_poor@2x.png), which is the caps, plus one pixel to stretch. Here it is blown up and I dimmed the 4 caps:
|
808
|
-
|
809
|
-
![Cap image](https://ir_wp.s3.amazonaws.com/wp-content/uploads/sites/18/2014/03/blown_up.png)
|
810
|
-
|
811
|
-
Basically just the center line of it stretches, the other 4 quadrants do not. RMQ makes this very easy. You create a UIImageView, then in the style (or anywhere) you set the image like so:
|
812
|
-
|
813
|
-
```ruby
|
814
|
-
rmq.append(UIImageView, :your_style)
|
815
|
-
# Then in your style
|
816
|
-
st.image = image.resource_resizable('your_image', top: 4, left: 4, right: 4, bottom: 4)
|
817
|
-
```
|
818
|
-
|
819
|
-
The top, left, etc, tell which parts of the image not to stretch. You can now resize your view and it will look great.
|
820
|
-
|
821
|
-
**Snapshot of a view**
|
822
|
-
|
823
|
-
Lastly you can get an image of a view, meaning a "screenshot" of it:
|
824
|
-
|
825
|
-
```ruby
|
826
|
-
my_image_view.image = rmq.image.from_view(some_view)
|
827
|
-
```
|
828
|
-
|
829
|
-
**Other examples**
|
830
|
-
|
831
|
-
```ruby
|
832
|
-
RubyMotionQuery::ImageUtils.resource('logo')
|
833
|
-
rmq.image.resource('logo')
|
834
|
-
rmq.image.resource('subfolder/foo')
|
835
|
-
rmq.image.resource_for_device('logo') # will look for 4inch or 3.5inch
|
836
|
-
rmq.image.resource('logo', cached: false)
|
837
|
-
|
838
|
-
rmq.image.resource_resizable('foo', left: 10, top: 10, right: 10, bottom: 10)
|
839
|
-
|
840
|
-
rmq.image.from_view(my_view)
|
841
|
-
|
842
|
-
# In a stylesheet you don't need the rmq
|
843
|
-
image.resource('logo')
|
844
|
-
```
|
845
|
-
|
846
|
-
|
847
|
-
<br />
|
848
|
-
|
849
|
-
### App
|
850
|
-
|
851
|
-
----
|
852
|
-
|
853
|
-
```ruby
|
854
|
-
RubyMotionQuery::App.window
|
855
|
-
rmq.app.window
|
856
|
-
rmq.app.delegate
|
857
|
-
rmq.app.environment
|
858
|
-
rmq.app.release? # .production? also
|
859
|
-
rmq.app.test?
|
860
|
-
rmq.app.development?
|
861
|
-
rmq.app.version
|
862
|
-
rmq.app.name
|
863
|
-
rmq.app.identifier
|
864
|
-
rmq.app.resource_path
|
865
|
-
rmq.app.document_path
|
866
|
-
```
|
867
|
-
|
868
|
-
|
869
|
-
<br />
|
870
|
-
|
871
|
-
### Device
|
872
|
-
|
873
|
-
----
|
874
|
-
|
875
|
-
```ruby
|
876
|
-
RubyMotionQuery::Device.screen
|
877
|
-
rmq.device.screen
|
878
|
-
rmq.device.width # screen width
|
879
|
-
rmq.device.height # screen height
|
880
|
-
rmq.device.ipad?
|
881
|
-
rmq.device.iphone?
|
882
|
-
rmq.device.four_inch?
|
883
|
-
rmq.device.retina?
|
884
|
-
|
885
|
-
# return values are :unknown, :portrait, :portrait_upside_down, :landscape_left,
|
886
|
-
# :landscape_right, :face_up, :face_down
|
887
|
-
rmq.device.orientation
|
888
|
-
rmq.device.landscape?
|
889
|
-
rmq.device.portrait?
|
890
|
-
```
|
891
|
-
|
892
|
-
|
893
|
-
<br />
|
894
|
-
|
895
|
-
### Format
|
896
|
-
|
897
|
-
----
|
898
|
-
|
899
|
-
A performant way to format numbers and dates.
|
900
|
-
|
901
|
-
```ruby
|
902
|
-
rmq.format.number(1232, '#,##0.##')
|
903
|
-
rmq.format.date(Time.now, 'EEE, MMM d, ''yy')
|
904
|
-
rmq.format.numeric_formatter(your_format_here) # returns cached numeric formatter
|
905
|
-
rmq.format.date_formatter(your_format_here) # returns cached date formatter
|
906
|
-
```
|
907
|
-
See <http://www.unicode.org/reports/tr35/tr35-19.html#Date_Format_Patterns> for more information about date format strings.
|
908
|
-
|
909
|
-
|
910
|
-
<br />
|
911
|
-
|
912
|
-
### Utils
|
913
|
-
|
914
|
-
----
|
915
|
-
|
916
|
-
These are mostly used internally by rmq.
|
917
|
-
|
918
|
-
```ruby
|
919
|
-
RubyMotionQuery::RMQ.is_class?(foo)
|
920
|
-
RubyMotionQuery::RMQ.is_blank?(foo)
|
921
|
-
RubyMotionQuery::RMQ.controller_for_view(view)
|
922
|
-
RubyMotionQuery::RMQ.view_to_s(view)
|
923
|
-
RubyMotionQuery::RMQ.weak_ref(foo)
|
924
|
-
```
|
925
|
-
|
926
|
-
|
927
|
-
<br />
|
928
|
-
|
929
|
-
### Pollution
|
930
|
-
|
931
|
-
----
|
932
|
-
|
933
|
-
The following are the only pollution in RMQ
|
934
|
-
|
935
|
-
- UIView
|
936
|
-
- rmq
|
937
|
-
- rmq_data
|
938
|
-
- UIViewController
|
939
|
-
- rmq
|
940
|
-
- rmq_data
|
941
|
-
- Object
|
942
|
-
- rmq
|
943
|
-
|
944
|
-
|
945
|
-
<br />
|
946
|
-
|
947
|
-
### Console Fun
|
948
|
-
|
949
|
-
----
|
950
|
-
|
951
|
-
```ruby
|
952
|
-
rmq.log :tree
|
953
|
-
rmq.all.log
|
954
|
-
rmq.all.log :wide
|
955
|
-
rmq(UIView).show
|
956
|
-
rmq(UILabel).animations.blink
|
957
|
-
rmq(UIButton).nudge l: 10
|
958
|
-
```
|
959
|
-
|
960
|
-
|
961
|
-
<br />
|
962
|
-
|
963
|
-
### A recommended project structure
|
964
|
-
|
965
|
-
----
|
966
|
-
|
967
|
-
- app
|
968
|
-
- controllers
|
969
|
-
- your_controller.rb
|
970
|
-
- your_other_controller.rb
|
971
|
-
- models
|
972
|
-
- shared
|
973
|
-
- stylers
|
974
|
-
- ui_view_styler.rb
|
975
|
-
- ui_button_styler.rb
|
976
|
-
- etc
|
977
|
-
- stylesheets
|
978
|
-
- application_stylesheet.rb (inherit from RubyMotionQuery::Stylesheet)
|
979
|
-
- your_stylesheet.rb (inherit from ApplicationStylesheet)
|
980
|
-
- your_other_stylesheet.rb (inherit from ApplicationStylesheet)
|
981
|
-
- your_view_stylesheet.rb (module, included an any controller's stylesheet that needs it)
|
982
|
-
- views
|
983
|
-
- lib
|
984
|
-
- resource
|
985
|
-
- spec
|
986
|
-
- controllers
|
987
|
-
- lib
|
988
|
-
- models
|
989
|
-
- shared
|
990
|
-
- stylers
|
991
|
-
- views
|
992
|
-
|
993
|
-
|
994
|
-
<br />
|
995
|
-
|
996
|
-
### Debugging
|
997
|
-
|
998
|
-
----
|
999
|
-
|
1000
|
-
Adding rmq_debug=true to rake turns on some debugging features that are too slow or verbose to include in a normal build. It's great for normal use in the simulator, but you'll want to leave it off if you're measuring performance.
|
1001
|
-
```
|
1002
|
-
rake rmq_debug=true
|
1003
|
-
```
|
1004
|
-
|
1005
|
-
Use this to add your optional debugging code
|
1006
|
-
```ruby
|
1007
|
-
rmq.debugging?
|
1008
|
-
=> true
|
1009
|
-
```
|
1010
|
-
|
1011
|
-
```ruby
|
1012
|
-
rmq.log :tree
|
1013
|
-
rmq.all.log
|
1014
|
-
rmq.all.log :wide
|
1015
|
-
|
1016
|
-
rmq(Section).log :tree
|
1017
|
-
# 163792144 is the ID a button
|
1018
|
-
rmq(163792144).style{|st| st.background_color = rmq.color.blue}
|
1019
|
-
|
1020
|
-
rmq(Section).children.and_self.log :wide
|
1021
|
-
|
1022
|
-
rmq(UILabel).animations.blink
|
1023
|
-
|
1024
|
-
# Show subview index and thus zorder of Section within Section's parent
|
1025
|
-
rmq(Section).parent.children.log
|
1026
|
-
```
|
1027
|
-
|
1028
|
-
|
1029
|
-
<br />
|
1030
|
-
|
1031
|
-
### Styles and stylesheets
|
1032
|
-
|
1033
|
-
----
|
1034
|
-
|
1035
|
-
A very lightweight style system, designed for a low memory footprint, fast startup, and fast operation. Most everything is done at compile-time, as it's all just ruby code. Low magic.
|
1036
|
-
|
1037
|
-
**You don't have to use this system, you can use Teacup instead**, or whatever you like. RMQ works great without using the style system.
|
1038
|
-
|
1039
|
-
#### Example controller
|
1040
|
-
|
1041
|
-
```ruby
|
1042
|
-
class MainController < UIViewController
|
1043
|
-
|
1044
|
-
def viewDidLoad
|
1045
|
-
super
|
1046
|
-
|
1047
|
-
rmq.stylesheet = MainStyleSheet # Each controller has its own stylesheet
|
1048
|
-
view.rmq.apply_style :root_view
|
1049
|
-
|
1050
|
-
@title_label = rmq.append(UILabel, :title_label).get
|
1051
|
-
|
1052
|
-
image_view = rmq.append(UIImageView).get
|
1053
|
-
# Apply style anywhere
|
1054
|
-
image_view.apply_style(:logo)
|
1055
|
-
|
1056
|
-
rmq.append(UIButton, :make_labels_blink).on(:tap) do |sender|
|
1057
|
-
rmq(UILabel).animations.blink
|
1058
|
-
end
|
1059
|
-
|
1060
|
-
rmq.append(UIButton.buttonWithType(UIButtonTypeRoundedRect), :make_buttons_throb).on(:tap) do |sender|
|
1061
|
-
rmq(UIButton).animations.throb
|
1062
|
-
end
|
1063
|
-
|
1064
|
-
rmq.append(UIView, :section).tap do |section|
|
1065
|
-
section.append(UILabel, :section_title)
|
1066
|
-
|
1067
|
-
section.append(UILabel, :section_enabled_title)
|
1068
|
-
|
1069
|
-
section.append(UISwitch, :section_enabled).on(:change) do |sender|
|
1070
|
-
style = sender.isOn ? :section_button_enabled : :section_button_disabled
|
1071
|
-
buttons = sender.rmq.parent.find(UIButton).apply_style(style)
|
1072
|
-
end
|
1073
|
-
|
1074
|
-
section.append(UIButton, :start_spinner).on(:tap) do |sender|
|
1075
|
-
rmq.animations.start_spinner
|
1076
|
-
end
|
1077
|
-
|
1078
|
-
section.append(UIButton, :stop_spinner).on(:tap) do |sender|
|
1079
|
-
rmq.animations.stop_spinner
|
1080
|
-
end
|
1081
|
-
end
|
1082
|
-
|
1083
|
-
end
|
1084
|
-
end
|
1085
|
-
```
|
1086
|
-
|
1087
|
-
#### Example stylesheet
|
1088
|
-
|
1089
|
-
```ruby
|
1090
|
-
class ApplicationStylesheet < RubyMotionQuery::Stylesheet
|
1091
|
-
PADDING = 10
|
1092
|
-
|
1093
|
-
def application_setup
|
1094
|
-
font_family = 'Helvetica Neue'
|
1095
|
-
font.add_named :large, font_family, 36
|
1096
|
-
font.add_named :medium, font_family, 24
|
1097
|
-
font.add_named :small, font_family, 18
|
1098
|
-
|
1099
|
-
color.add_named :translucent_black, color.from_rgba(0, 0, 0, 0.4)
|
1100
|
-
color.add_named :battleship_gray, '#7F7F7F'
|
1101
|
-
end
|
1102
|
-
|
1103
|
-
def label(st)
|
1104
|
-
st.background_color = color.clear
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
end
|
1108
|
-
|
1109
|
-
class MainStylesheet < ApplicationStylesheet
|
1110
|
-
def setup
|
1111
|
-
# Add stylesheet specific setup stuff here.
|
1112
|
-
# Add application specific setup stuff in application_stylesheet.rb
|
1113
|
-
end
|
1114
|
-
|
1115
|
-
def root_view(st)
|
1116
|
-
st.background_color = color.white
|
1117
|
-
end
|
1118
|
-
|
1119
|
-
def logo(st)
|
1120
|
-
st.frame = {t: 10, w: 200, h: 96}
|
1121
|
-
st.centered = :horizontal
|
1122
|
-
st.image = image.resource('logo')
|
1123
|
-
end
|
1124
|
-
|
1125
|
-
def title_label(st)
|
1126
|
-
label st # stack styles
|
1127
|
-
st.frame = {l: PADDING, t: 120, w: 200, h: 20}
|
1128
|
-
st.text = 'Test label'
|
1129
|
-
st.color = color.from_rgba(34, 132, 198, 1.0)
|
1130
|
-
st.font = font.medium
|
1131
|
-
end
|
1132
|
-
|
1133
|
-
def make_labels_blink(st)
|
1134
|
-
st.frame = {t: 120, w: 150, h: 20}
|
1135
|
-
st.from_right = PADDING
|
1136
|
-
|
1137
|
-
# ipad? (and landscape?, etc) is just a convenience methods for
|
1138
|
-
# rmq.device.ipad?
|
1139
|
-
|
1140
|
-
# Here is a complete example of different formatting for orientations
|
1141
|
-
# and devices
|
1142
|
-
# if ipad?
|
1143
|
-
# if landscape?
|
1144
|
-
# st.frame = {l: 20, t: 120, w: 150, h: four_inch? ? 20 : 30}
|
1145
|
-
# else
|
1146
|
-
# st.frame = {l: 90, t: 120, w: 150, h: four_inch? ? 25 : 35}
|
1147
|
-
# end
|
1148
|
-
# else
|
1149
|
-
# if landscape?
|
1150
|
-
# st.frame = {l: 20, t: 20, w: 150, h: four_inch? ? 22 : 32}
|
1151
|
-
# else
|
1152
|
-
# st.frame = {l: 90, t: 20, w: 150, h: four_inch? ? 30 : 40}
|
1153
|
-
# end
|
1154
|
-
# end
|
1155
|
-
|
1156
|
-
# If you don't want something to be reapplied during orientation
|
1157
|
-
# changes (assuming you're reapplying during orientation changes
|
1158
|
-
# in your controller, it's not automatic)
|
1159
|
-
unless st.view_has_been_styled?
|
1160
|
-
st.text = 'Blink labels'
|
1161
|
-
st.font = font.system(10)
|
1162
|
-
st.color = color.white
|
1163
|
-
st.background_color = color.from_hex('ed1160')
|
1164
|
-
end
|
1165
|
-
end
|
1166
|
-
|
1167
|
-
def make_buttons_throb(st)
|
1168
|
-
st.frame = {t: 150, w: 150, h: 20}
|
1169
|
-
st.from_right = PADDING
|
1170
|
-
st.text = 'Throb buttons'
|
1171
|
-
st.color = color.black
|
1172
|
-
end
|
1173
|
-
|
1174
|
-
def section(st)
|
1175
|
-
st.frame = {from_bottom: PADDING, w: 270, h: 110}
|
1176
|
-
|
1177
|
-
if landscape? && iphone?
|
1178
|
-
st.left = PADDING
|
1179
|
-
else
|
1180
|
-
st.centered = :horizontal
|
1181
|
-
end
|
1182
|
-
|
1183
|
-
st.z_position = 1
|
1184
|
-
st.background_color = color.battleship_gray
|
1185
|
-
end
|
1186
|
-
|
1187
|
-
def section_label(st)
|
1188
|
-
label st
|
1189
|
-
st.color = color.white
|
1190
|
-
end
|
1191
|
-
|
1192
|
-
def section_title(st)
|
1193
|
-
section_label st
|
1194
|
-
st.frame = {l: PADDING, t: PADDING, w: 150, h: 20}
|
1195
|
-
st.text = 'Section title'
|
1196
|
-
end
|
1197
|
-
|
1198
|
-
def section_enabled(st)
|
1199
|
-
label st
|
1200
|
-
st.frame = {l: PADDING, t: 30}
|
1201
|
-
st.on = true
|
1202
|
-
end
|
1203
|
-
|
1204
|
-
def section_enabled_title(st)
|
1205
|
-
section_label st
|
1206
|
-
st.frame = {l: 93, t: 34, w: 150, h: 20}
|
1207
|
-
st.text = 'Enabled'
|
1208
|
-
end
|
1209
|
-
|
1210
|
-
def section_buttons(st)
|
1211
|
-
st.frame = {l: PADDING, t: 64, w: 120, h: 40}
|
1212
|
-
st.background_color = color.black
|
1213
|
-
section_button_enabled st
|
1214
|
-
end
|
1215
|
-
|
1216
|
-
def start_spinner(st)
|
1217
|
-
section_buttons st
|
1218
|
-
st.text = 'Start spinner'
|
1219
|
-
end
|
1220
|
-
|
1221
|
-
def stop_spinner(st)
|
1222
|
-
section_buttons st
|
1223
|
-
st.from_right = PADDING
|
1224
|
-
st.text = 'Stop spinner'
|
1225
|
-
end
|
1226
|
-
|
1227
|
-
def section_button_disabled(st)
|
1228
|
-
st.enabled = false
|
1229
|
-
st.color = color.dark_gray
|
1230
|
-
end
|
1231
|
-
|
1232
|
-
def section_button_enabled(st)
|
1233
|
-
st.enabled = true
|
1234
|
-
st.color = color.white
|
1235
|
-
end
|
1236
|
-
|
1237
|
-
def animate_move(st)
|
1238
|
-
st.scale = 1.0
|
1239
|
-
st.frame = {t: 180, w: 150, h: 20}
|
1240
|
-
st.from_right = PADDING
|
1241
|
-
st.text = 'Animate move and scale'
|
1242
|
-
st.font = font.system(10)
|
1243
|
-
st.color = color.white
|
1244
|
-
st.background_color = color.from_hex('ed1160')
|
1245
|
-
st.z_position = 99
|
1246
|
-
st.color = color.white
|
1247
|
-
end
|
1248
|
-
|
1249
|
-
def overlay(st)
|
1250
|
-
st.frame = :full
|
1251
|
-
st.background_color = color.translucent_black
|
1252
|
-
st.hidden = true
|
1253
|
-
st.z_position = 99
|
1254
|
-
end
|
1255
|
-
|
1256
|
-
def benchmarks_results_wrapper(st)
|
1257
|
-
st.hidden = true
|
1258
|
-
st.frame = {w: app_width - 20, h: 120}
|
1259
|
-
st.centered = :both
|
1260
|
-
st.background_color = color.white
|
1261
|
-
st.z_position = 100
|
1262
|
-
end
|
1263
|
-
|
1264
|
-
def benchmarks_results_label(st)
|
1265
|
-
label st
|
1266
|
-
st.padded = {l: 10, t: 10, b:10, r: 10}
|
1267
|
-
st.text_alignment = :left
|
1268
|
-
st.color = color.black
|
1269
|
-
st.font = font.system(10)
|
1270
|
-
|
1271
|
-
# If the styler doesn't have the method, you can add it or
|
1272
|
-
# just use st.view to get the actual object
|
1273
|
-
st.view.numberOfLines = 0
|
1274
|
-
st.view.lineBreakMode = NSLineBreakByWordWrapping
|
1275
|
-
end
|
1276
|
-
|
1277
|
-
def run_benchmarks(st)
|
1278
|
-
st.frame = {l: PADDING, t: 150, w: 130, h: 20}
|
1279
|
-
st.text = 'Run benchmarks'
|
1280
|
-
st.font = font.system(11)
|
1281
|
-
st.color = color.white
|
1282
|
-
st.enabled = true
|
1283
|
-
st.background_color = color.from_hex('faa619')
|
1284
|
-
end
|
1285
|
-
|
1286
|
-
def run_benchmarks_disabled(st)
|
1287
|
-
st.enabled = false
|
1288
|
-
st.color = color.from_hex('de8714')
|
1289
|
-
end
|
1290
|
-
|
1291
|
-
def benchmark(st)
|
1292
|
-
st.hidden = false
|
1293
|
-
st.text = 'foo'
|
1294
|
-
st.color = color.white
|
1295
|
-
st.left = 10
|
1296
|
-
end
|
1297
|
-
|
1298
|
-
end
|
1299
|
-
```
|
1300
|
-
|
1301
|
-
#### Stylers
|
1302
|
-
|
1303
|
-
A styler wraps around a view, augmenting it with styling power and sugar.
|
1304
|
-
|
1305
|
-
Each UIView subclass can have its own styler (many exist in RMQ, but not all *yet*). There is a UIViewStyler class they all inherit from, and a UIControlStyler controls inherit from. Much of the code is in UIViewStyler.
|
1306
|
-
|
1307
|
-
When you create a "style method", it will be passed the view, wrapped in a styler. You can get the view using st.view.
|
1308
|
-
|
1309
|
-
##### UIViewStyler
|
1310
|
-
Here is a silly example, showing you a bunch of methods the UIViewStyler gives you:
|
1311
|
-
|
1312
|
-
```ruby
|
1313
|
-
def ui_view_kitchen_sink(st)
|
1314
|
-
st.frame = {l: 1, t: 2, w: 3, h: 4}
|
1315
|
-
st.frame = {left: 1, top: 2, width: 3, height: 4}
|
1316
|
-
st.frame = {from_right: 1, from_bottom: 2, width: 3, height: 4}
|
1317
|
-
st.frame = {fr: 1, fb: 2, w: 3, h: 4}
|
1318
|
-
st.left = 20
|
1319
|
-
st.top = 30
|
1320
|
-
st.width = 40
|
1321
|
-
st.height = 50
|
1322
|
-
st.right = 100
|
1323
|
-
st.bottom = 110
|
1324
|
-
st.from_right = 10
|
1325
|
-
st.from_bottom = 12
|
1326
|
-
st.padded = {l: 1, t: 2, r: 3, b: 4}
|
1327
|
-
st.padded = {left: 1, top: 2, right: 3, bottom: 4}
|
1328
|
-
st.center = st.superview.center
|
1329
|
-
st.center_x = 50
|
1330
|
-
st.center_y = 60
|
1331
|
-
st.centered = :horizontal
|
1332
|
-
st.centered = :vertical
|
1333
|
-
st.centered = :both
|
1334
|
-
|
1335
|
-
st.enabled = true
|
1336
|
-
st.hidden = false
|
1337
|
-
st.z_position = 66
|
1338
|
-
st.opaque = false
|
1339
|
-
st.clips_to_bounds = false
|
1340
|
-
st.hidden = true
|
1341
|
-
st.content_mode = UIViewContentModeBottomLeft
|
1342
|
-
|
1343
|
-
st.background_color = color.red
|
1344
|
-
# TODO test background_image
|
1345
|
-
|
1346
|
-
st.scale = 1.5
|
1347
|
-
st.rotation = 45
|
1348
|
-
st.tint_color = color.blue
|
1349
|
-
st.layer.cornerRadius = 5
|
1350
|
-
end
|
1351
|
-
```
|
1352
|
-
|
1353
|
-
##### UIControlStyler
|
1354
|
-
Nothing yet
|
1355
|
-
|
1356
|
-
##### UILabelStyler
|
1357
|
-
|
1358
|
-
```ruby
|
1359
|
-
def ui_label_kitchen_sink(st)
|
1360
|
-
st.text = 'rmq is awesome'
|
1361
|
-
st.font = font.system(12)
|
1362
|
-
st.color = color.black
|
1363
|
-
st.text_alignment = :center
|
1364
|
-
|
1365
|
-
st.resize_to_fit_text
|
1366
|
-
st.size_to_fit
|
1367
|
-
end
|
1368
|
-
```
|
1369
|
-
|
1370
|
-
##### UIButtonStyler
|
1371
|
-
|
1372
|
-
```ruby
|
1373
|
-
def ui_button_kitchen_sink(st)
|
1374
|
-
st.text = 'foo'
|
1375
|
-
st.font = font.system(12)
|
1376
|
-
st.color = color.red
|
1377
|
-
st.image_normal = image.resource('logo')
|
1378
|
-
st.image_highlighted = image.resource('logo')
|
1379
|
-
end
|
1380
|
-
```
|
1381
|
-
|
1382
|
-
##### UIImageViewStyler
|
1383
|
-
|
1384
|
-
```ruby
|
1385
|
-
def u_image_view_kitchen_sink(st)
|
1386
|
-
st.image = image.resource('logo')
|
1387
|
-
end
|
1388
|
-
```
|
1389
|
-
|
1390
|
-
##### UIScrollViewStyler
|
1391
|
-
|
1392
|
-
```ruby
|
1393
|
-
def ui_scroll_view_kitchen_sink(st)
|
1394
|
-
st.paging = true
|
1395
|
-
end
|
1396
|
-
```
|
1397
|
-
|
1398
|
-
##### UISwitchStyler
|
1399
|
-
|
1400
|
-
```ruby
|
1401
|
-
def ui_switch_kitchen_sink(st)
|
1402
|
-
st.on = true
|
1403
|
-
end
|
1404
|
-
```
|
1405
|
-
|
1406
|
-
**There should be a styler for each UIView type. And each one should wrap all common methods and attributes, plus add functionality for common operations. This will come in future versions**
|
1407
|
-
|
1408
|
-
#### Add your own stylers
|
1409
|
-
|
1410
|
-
In the example app, look in **/app/stylers**, you can just copy that whole folder to start. Then add methods to the appropriate class.
|
1411
|
-
|
1412
|
-
Here is an example of adding a method to all stylers:
|
1413
|
-
```ruby
|
1414
|
-
module RubyMotionQuery
|
1415
|
-
module Stylers
|
1416
|
-
class UIViewStyler
|
1417
|
-
|
1418
|
-
def border_width=(value)
|
1419
|
-
@view.layer.borderWidth = value
|
1420
|
-
end
|
1421
|
-
def border_width
|
1422
|
-
@view.layer.borderWidth
|
1423
|
-
end
|
1424
|
-
|
1425
|
-
end
|
1426
|
-
end
|
1427
|
-
end
|
1428
|
-
```
|
1429
|
-
|
1430
|
-
You can also include all of your custom stylers in one file, which works well if you don't have a lot.
|
1431
|
-
|
1432
|
-
|
1433
|
-
<br />
|
1434
|
-
|
1435
|
-
### Creating your own views
|
1436
|
-
|
1437
|
-
----
|
1438
|
-
|
1439
|
-
RMQ calls 3 methods when you create, append, or build a view using rmq. rmq_build is the one you most want to use
|
1440
|
-
```ruby
|
1441
|
-
def rmq_build
|
1442
|
-
end
|
1443
|
-
|
1444
|
-
def rmq_created
|
1445
|
-
end
|
1446
|
-
|
1447
|
-
def rmq_appended
|
1448
|
-
end
|
1449
|
-
```
|
1450
|
-
If you append a view like so:
|
1451
|
-
```ruby
|
1452
|
-
rmq.append(UILabel)
|
1453
|
-
```
|
1454
|
-
The 3 methods will be called in this order:
|
1455
|
-
- rmq_created
|
1456
|
-
- rmq_appended
|
1457
|
-
- rmq_build
|
1458
|
-
|
1459
|
-
In the following example an instance of YourView is created, :your_style is applied
|
1460
|
-
then rmq_build is called on the instance that was just created. In that
|
1461
|
-
order.
|
1462
|
-
|
1463
|
-
```ruby
|
1464
|
-
# Your view
|
1465
|
-
class YourView < UIView
|
1466
|
-
def rmq_build
|
1467
|
-
rmq(self).tap do |q|
|
1468
|
-
q.append(UILabel, :section_title)
|
1469
|
-
q.append(UIButton, :buy_button).on(:tap) do |sender|
|
1470
|
-
# do something
|
1471
|
-
end
|
1472
|
-
end
|
1473
|
-
end
|
1474
|
-
end
|
1475
|
-
|
1476
|
-
# In your controller
|
1477
|
-
rmq.append(YourView, :your_style)
|
1478
|
-
```
|
1479
|
-
|
1480
|
-
|
1481
|
-
<br />
|
1482
|
-
|
1483
|
-
### Future features
|
1484
|
-
|
1485
|
-
----
|
1486
|
-
|
1487
|
-
Current roadmap:
|
1488
|
-
|
1489
|
-
- v0.6 new frame system: I’ve already designed this, I just have to implement it and use it in the real world and tweak. This is going to be very cool. It adds to the existing frame system. It doesn’t replace constraints, but rather gives you almost all the features you need without the complexity of constraints.
|
1490
|
-
- v0.6.5 templates and stylers all finished
|
1491
|
-
- v0.6.7 performance improvements
|
1492
|
-
- v0.7 first rmq plugin and any base features needed to support plugins (I don’t think there will be any base features needed)
|
1493
|
-
- v0.8 binding system
|
1494
|
-
- ?
|
1495
|
-
- ?
|
1496
|
-
- v1.0
|
1497
|
-
|
1498
|
-
Random future features that I plan on adding
|
1499
|
-
|
1500
|
-
- rmq.push_sub_controller(my_controller) and rmq.pop_sub_controller and rmq.pop_this_controller
|
1501
|
-
- add borders to UIView styler: st.borders = {l: {w: 2, color: color.black}, r: {w: 2, color: color.black}}
|
1502
|
-
- add templates for: nav controller, tab controller, table controller, collection controller
|
1503
|
-
- add from_right, from_bottom, and centered to both st.frame and to move
|
1504
|
-
- add binding that combines KVO and events to bind an attribute of one object to the attribute of selected view(s), keeping both in sync, like so: rmq.append(UITextField).bind(@person, attr: :name, to: :text)
|
1505
|
-
- rmq.log to wrap nslog to allow you to turn off logging (or does NSLog already have this feature?)
|
1506
|
-
- add selectors for UITextField
|
1507
|
-
- add string to height utility, given the font and the width
|
1508
|
-
- add block to wrap useful for a variety of things, but here is solid example: rmq.append(UIButton).tag(:foo).wrap{|view| view.titleLabel}.tag(:foo_title)
|
1509
|
-
- add def rmq_build_with_properties(props = {}). Perhaps remove rmq_created and rmq_appended, not sure if those are useful or not
|
1510
|
-
- add easy way to do alerts and actionsheets
|
1511
|
-
- add rmq.help with basic help for when you're in repl
|
65
|
+
### License
|
1512
66
|
|
67
|
+
RMQ is available under the MIT license. See the [LICENSE](https://github.com/infinitered/rmq/blob/master/LICENSE) file for more info.
|
1513
68
|
|
1514
69
|
|
1515
70
|
<br />
|
1516
71
|
|
1517
|
-
###
|
1518
|
-
|
1519
|
-
----
|
1520
|
-
|
1521
|
-
created by **Todd Werth** ([http://toddwerth.com](http://toddwerth.com))
|
72
|
+
### Created by Todd Werth ([http://toddwerth.com](http://toddwerth.com))
|
1522
73
|
|
1523
74
|
- [@twerth](http://twitter.com/twerth)
|
1524
75
|
- [todd@infinitered.com](mailto:todd@infinitered.com)
|
1525
76
|
- [github](https://github.com/twerth)
|
1526
77
|
|
1527
|
-
with help from the team at **InfiniteRed** ([http://infinitered.com](http://infinitered.com))
|
1528
|
-
|
1529
|
-
- [@infinite_red](http://twitter.com/infinite_red)
|
1530
|
-
- [github](https://github.com/infinitered)
|
1531
|
-
|
1532
|
-
|
1533
78
|
|
1534
79
|
<br />
|
1535
80
|
|
1536
|
-
###
|
1537
|
-
|
1538
|
-
----
|
1539
|
-
|
1540
|
-
RMQ is available under the MIT license. See the LICENSE file for more info.
|
1541
|
-
|
81
|
+
### [Contributors](https://github.com/infinitered/rmq/graphs/contributors)
|
1542
82
|
|
1543
83
|
<br />
|
1544
84
|
|
1545
85
|
### Contributing
|
1546
86
|
|
1547
|
-
----
|
1548
|
-
|
1549
87
|
1. Fork it
|
1550
88
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
1551
89
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
1552
90
|
4. Push to the branch (`git push origin my-new-feature`)
|
1553
91
|
5. Create new Pull Request
|
1554
92
|
|
1555
|
-
|
93
|
+
<br />
|
94
|
+
|
95
|
+
----------
|
96
|
+
|
97
|
+
## Read the [RMQ Documentation][1] here
|
98
|
+
|
99
|
+
----------
|
100
|
+
|
101
|
+
[1]: http://rubymotionquery.com
|