ruby_motion_query 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
data/README.md ADDED
@@ -0,0 +1,964 @@
1
+ ![RQM logo](http://ir_wp.s3.amazonaws.com/wp-content/uploads/sites/9/2013/07/rmq_logo.png)
2
+
3
+ RubyMotionQuery - RMQ - A small, light, muggle, nonpolluting, jQuery-like library for [RubyMotion](http://rubymotion.com).
4
+
5
+ #### The [RMQ Introductory Guide and other info][1] is a great place to start.
6
+
7
+
8
+ ----------
9
+
10
+
11
+ #### Some of the very cool features:
12
+ - **selecting** (*querying*) views
13
+ - **traversal** through view hierarchy (moving around the tree)
14
+ - tagging
15
+ - **events and gestures**
16
+ - animations
17
+ - **stylers and stylesheets**
18
+ - colors
19
+ - fonts
20
+ - image utilities
21
+ - app
22
+ - device
23
+
24
+ #### Other wrapper libraries
25
+ 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.
26
+
27
+ RMQ **doesn't require any** other wrapper or gem.
28
+
29
+ > If you preferred jQuery over Prototype, you'll love RMQ.
30
+
31
+ 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.
32
+
33
+ ----------
34
+
35
+ ### * Alpha * Warning *
36
+
37
+ 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.
38
+
39
+ 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.
40
+
41
+ Nothing is optimized for speed yet. Well, that isn't true, somethings are.
42
+
43
+ Memory leaks may exist.
44
+
45
+ Tested only on iOS, not OS X (nor is there any OS X specific code)
46
+
47
+ ----------
48
+
49
+ ## Installation
50
+
51
+ RMQ **requires no other gems**. If you use stuff like **scale** and certain animations it will require some frameworks (like QuartzCore or CoreGraphics)
52
+
53
+ - `gem install ruby_motion_query`
54
+ - `require 'ruby_motion_query'`
55
+
56
+ or add it to your `Gemfile`:
57
+
58
+ - `gem 'ruby_motion_query'`
59
+
60
+
61
+
62
+ ## Usage
63
+
64
+ ### Example App
65
+ *Clone this repo and run the example app to see an example of use.*
66
+
67
+ git clone git@github.com:infinitered/rmq.git
68
+ cd rmq
69
+ rake retina=4
70
+
71
+ 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.
72
+
73
+ ### What's an rmq instance?
74
+
75
+ - an rmq instance is an array-like object containing UIViews
76
+ - rmq() never returns nil. If nothing is selected, it's an empty [ ] array-like
77
+ object
78
+ - an rmq object always (almost always) returns either itself or a new
79
+ rmq object. This is how chaining works. You do not need to worry if
80
+ an rmq is blank or not, everything always works without throwing a
81
+ nil exception
82
+ - jQuery uses the DOM, what is rmq using for the "DOM"? It uses the
83
+ controller it was called in. The "DOM" is the controller's subview
84
+ tree. If you call rmq inside a view, it will attach to the
85
+ controller that the view is currently in or to the current screen's
86
+ controller
87
+
88
+ ### Basic syntax
89
+
90
+ The main command is `rmq` and you use it everywhere. You can rename this by aliasing the methods in `ext.rb`.
91
+
92
+ ```ruby
93
+ # Like jQuery you wrap your objects or selectors in a rmq(), here are some examples
94
+ rmq(my_view).show
95
+ rmq(UILabel).hide
96
+
97
+ # You can use zero or more selectors, all these are valid
98
+ rmq(my_view, UILabel).hide
99
+ rmq(:a_tag, :a_style_name, UIImageView).hide
100
+ rmq(hidden: true).show
101
+
102
+ # If you use a set of selectors, they are an "or", to do an "and" use .and
103
+ rmq(:UIImageView).and(hidden: true).show
104
+ ```
105
+
106
+ **rmq by itself is the rmq instance of the current UIViewController if you're inside a UIViewController**.
107
+
108
+ If you're inside a UIView you've created, `rmq.closest(UIControl)` is the same as `rmq(self).closest(UIControl)`.
109
+
110
+ #### rmq is always an array-like object (enumerablish), never nil, etc:
111
+
112
+ Because of this, you **never have to check** if your selectors return anything before calling actions or other methods on your rmq object.
113
+
114
+ ```ruby
115
+ # This will hide any UILabel in the controller, if any exist. If not, nothing happens
116
+ rmq(UILabel).hide
117
+
118
+ # Because of this, you can create chains without worry of exceptions
119
+ rmq(:this_tag_does_not_exist).show.apply_style(:my_style_name).on(:touch_down){puts 'score!'}
120
+ ```
121
+
122
+ #### Almost all methods of an rmq object return either itself or another rmq object, so you can chain:
123
+ ```ruby
124
+ rmq.append(UILabel, :label_style).on(:tap){|sender,event| sender.hide}
125
+
126
+ # or
127
+
128
+ rmq.closest(AddEntry).find(:delete_button).hide
129
+ rmq(AddEntry).find(UILabel).blink
130
+
131
+ ```
132
+
133
+ If you want the actual inner object(s), use **.get**
134
+
135
+ ```ruby
136
+ # returns my_view
137
+ rmq(my_view).get
138
+
139
+ # returns an array
140
+ rmq(UILabel).get
141
+ ```
142
+
143
+ ### Selectors
144
+
145
+ - Constant
146
+ - :a_tag
147
+ - :a_style_name
148
+ - my_view_instance
149
+ - text: 'you can select via attributes also'
150
+ - :another_tag, UILabel, text: 'an array' <- this is an "or", use .and for and
151
+
152
+ ### Traversing
153
+
154
+ - all
155
+ - and
156
+ - not
157
+ - and_self
158
+ - end
159
+ - find
160
+ - children
161
+ - siblings
162
+ - closest
163
+ - parent
164
+ - parents
165
+ - filter
166
+ - view_controller
167
+ - root_view
168
+
169
+ ### Enumerablish
170
+ A rmq object is like an enumerable, but each method returns a rmq object instead of a enumerable. For example, these methods:
171
+
172
+ - each
173
+ - map
174
+ - select
175
+ - grep
176
+ - detect
177
+ - inject
178
+ - first
179
+ - last
180
+ - []
181
+ - <<
182
+ - *etc*
183
+
184
+ all return another rmq instance, so you can chain.
185
+
186
+ You can also do **rmq.length** and **rmq[0]** like an array
187
+
188
+ **.to_a** gives you an actual array, so will **.get** (this is preferred)
189
+
190
+ ### Events and Gestures
191
+
192
+ #### On / Off
193
+
194
+ To add an event, use .on, to remove it it, use .off
195
+
196
+ ```ruby
197
+ # Simple example
198
+ rmq(UIView).on(:tap){|sender| rmq(sender).hide}
199
+
200
+ # Adding an Event during creation
201
+ view_q = rmq.append(UIView).on(:tap) do |sender, event|
202
+ # do something here
203
+ end
204
+
205
+ # removing an Event
206
+ view_q.off(:tap)
207
+
208
+ # or you remove them all
209
+ view_q.off
210
+
211
+ # like everything in RMQ, this works on all items selected
212
+ rmq(UIView).off(:tap)
213
+ ```
214
+
215
+ #### RubyMotionQuery::Event
216
+
217
+ 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.
218
+
219
+ If you see Event, just remember that's either an event or gesture. I decided to call them Events
220
+
221
+ ##### Type of events and gestures
222
+ ```ruby
223
+ # Events on controls
224
+ :touch
225
+ :touch_up
226
+ :touch_down
227
+ :touch_start
228
+ :touch_stop
229
+ :change
230
+
231
+ :touch_down_repeat
232
+ :touch_drag_inside
233
+ :touch_drag_outside
234
+ :touch_drag_enter
235
+ :touch_drag_exit
236
+ :touch_up_inside
237
+ :touch_up_outside
238
+ :touch_cancel
239
+
240
+ :value_changed
241
+
242
+ :editing_did_begin
243
+ :editing_changed
244
+ :editing_did_change
245
+ :editing_did_end
246
+ :editing_did_endonexit
247
+
248
+ :all_touch
249
+ :all_editing
250
+
251
+ :application
252
+ :system
253
+ :all
254
+
255
+ # Gestures
256
+ :tap
257
+ :pinch
258
+ :rotate
259
+ :swipe
260
+ :pan
261
+ :long_press
262
+ ```
263
+
264
+ ##### Interesting methods of an RubyMotionQuery::Event:
265
+ ```ruby
266
+ foo.sender
267
+ foo.event
268
+
269
+ foo.gesture?
270
+ foo.recognizer
271
+ foo.gesture
272
+
273
+ foo.location
274
+ foo.location_in
275
+
276
+ foo.sdk_event_or_recognizer
277
+ ```
278
+
279
+ TODO, need many examples here
280
+
281
+ #### RubyMotionQuery::Events
282
+
283
+ The internal store of events in a UIView. It's rmq.events, you won't use it too often
284
+
285
+ ### Tags
286
+
287
+ ```ruby
288
+ # Add tags
289
+ rmq(my_view).tag(:your_tag)
290
+
291
+ rmq(my_view).find(UILabel).tag(:selected, :customer)
292
+
293
+ # You can use a tag or tags as selecors
294
+ rmq(:selected).hide
295
+ rmq(:your_tag).and(:selected).hide
296
+ ```
297
+
298
+ ### Actions
299
+ ```ruby
300
+ rmq(UILabel).attr(text: 'Foo bar')
301
+ rmq(UILabel).send(:some_method, args)
302
+ rmq(my_view).hide
303
+ rmq(my_view).show
304
+ rmq(my_view).toggle
305
+ rmq(my_view).toggle_enabled
306
+ ```
307
+
308
+ ### Subviews
309
+
310
+ ```ruby
311
+ rmq.append(UILabel) # Creates a UILabel in the current controller
312
+ rmq.append(UILabel, :my_label_style)
313
+ rmq.append(UILabel.alloc.initWithFrame([[0,0],[10,10]]), :my_label_style)
314
+ rmq(my_view).append(UIButton) # A custom button
315
+ rmq(my_view).remove
316
+ rmq(my_vuew).children.remove
317
+ rmq(UIView).append(UIButton, :delete_me)
318
+
319
+ rmq(my_view).parent # .superview works too
320
+ rmq(my_view).parents # all parents up the tree, up to the root
321
+ rmq(my_view).children
322
+ rmq(my_view).find # children, grandchildren, etc
323
+ rmq.root_view
324
+ rmq.view_controller
325
+ ```
326
+
327
+ ### Animate
328
+
329
+ ```ruby
330
+ rmq(my_view).animate(
331
+ duration: 0.3,
332
+ animations: lambda{|q|
333
+ q.move left: 20
334
+ }
335
+ )
336
+ ```
337
+
338
+ ```ruby
339
+ # As an example, this is the implementation of .animations.throb
340
+ rmq(selectors).animate(
341
+ duration: 0.1,
342
+ animations: -> (q) {
343
+ q.style {|st| st.scale = 1.1}
344
+ },
345
+ completion: -> (did_finish, q) {
346
+ q.animate(
347
+ duration: 0.4,
348
+ animations: -> (cq) {
349
+ cq.style {|st| st.scale = 1.0}
350
+ }
351
+ )
352
+ }
353
+ )
354
+
355
+ # You can pass any options that animateWithDuration allows: options: YOUR_OPTIONS
356
+ ```
357
+
358
+ ### Animations
359
+
360
+ #### Current animations included:
361
+
362
+ ```ruby
363
+ rmq(my_view).animations.fade_in
364
+ rmq(my_view).animations.fade_in(duration: 0.8)
365
+ rmq(my_view).animations.fade_out
366
+ rmq(my_view).animations.fade_out(duration: 0.8)
367
+
368
+ rmq(my_view).animations.blink
369
+ rmq(my_view).animations.throb
370
+
371
+ rmq.animations.start_spinner
372
+ rmq.animations.stop_spinner
373
+ ```
374
+
375
+ ### Color
376
+
377
+ ```ruby
378
+ rmq.color.red
379
+ rmq.color.from_hex('#ffffff')
380
+ rmq.color.from_hex('ffffff')
381
+ rmq.color.from_rgba(128, 128, 128, 0.5)
382
+
383
+ # Add a new standard color
384
+ rmq.color.add_named :pitch_black, '#000000'
385
+ # Or
386
+ rmq.color.add_named :pitch_black, rmq.color.black
387
+
388
+ # In a stylesheet you don't need the rmq
389
+ color.pitch_black
390
+ color.red
391
+ ```
392
+
393
+ ### Font
394
+
395
+ ```ruby
396
+ rmq.font.system(12)
397
+ rmq.font_with_name('Helvetica', 18)
398
+ rmq.font.family_list # useful in console
399
+ rmq.font.for_family('Helvetica') # useful in console
400
+
401
+ # Add a new standard font
402
+ font_family = 'Helvetica Neue'
403
+ font.add_named :large, font_family, 36
404
+ font.add_named :medium, font_family, 24
405
+ font.add_named :small, font_family, 18
406
+
407
+ # then use them like so
408
+ rmq.font.large
409
+ rmq.font.small
410
+
411
+ # In a stylesheet you don't need the rmq
412
+ font.medium
413
+ font.system(14)
414
+ ```
415
+
416
+ ### Position (moving, sizing, and nudging)
417
+
418
+ ```ruby
419
+ # Move/Size changes size and origin of selected view(s)
420
+ rmq(your_view).move(l: 20)
421
+ rmq(your_view).move(left: 20)
422
+ rmq(your_view).move(l: 20, t: 20, w: 100, h: 50)
423
+ rmq(your_view).move(left: 20, top: 20, width: 100, height: 50)
424
+ rmq(your_view).size(left: 20, top: 20, width: 100, height: 50) # alias
425
+
426
+ # Nudge pushes them in a direction
427
+ rmq(your_view).nudge(d: 20)
428
+ rmq(your_view).nudge(down: 20)
429
+ rmq(your_view).nudge(l: 20, r: 20, u: 100, d: 50)
430
+ rmq(your_view).nudge(left: 20, right: 20, up: 100, down: 50)
431
+ ```
432
+
433
+ ### Images
434
+
435
+ ```ruby
436
+ RubyMotionQuery::ImageUtils.resource('logo')
437
+ rmq.image.resource('logo')
438
+ rmq.image.resource('subfolder/foo')
439
+ rmq.image.resource_for_device('logo') # will look for 4inch or 3.5inch
440
+ rmq.image.resource('logo', cached: false)
441
+
442
+ rmq.image.resource_resizable('foo', left: 10, top: 10, right: 10, bottom: 10)
443
+
444
+ rmq.image.from_view(my_view)
445
+
446
+ # In a stylesheet you don't need the rmq
447
+ image.resource('logo')
448
+ ```
449
+
450
+ ### App
451
+ ```ruby
452
+ RubyMotionQuery::App.window
453
+ rmq.app.window
454
+ rmq.app.delegate
455
+ rmq.app.environment
456
+ rmq.app.release? # .production? also
457
+ rmq.app.test?
458
+ rmq.app.development?
459
+ rmq.app.version
460
+ rmq.app.name
461
+ rmq.app.identifier
462
+ rmq.app.resource_path
463
+ rmq.app.document_path
464
+ ```
465
+
466
+ ### Device
467
+
468
+ ```ruby
469
+ RubyMotionQuery::Device.screen
470
+ rmq.device.screen
471
+ rmq.device.width # screen width
472
+ rmq.device.height # screen height
473
+ rmq.device.ipad?
474
+ rmq.device.iphone?
475
+ rmq.device.four_inch?
476
+ rmq.device.retina?
477
+
478
+ # return values are :unkown, :portrait, :portrait_upside_down, :landscape_Left,
479
+ # :landscape_right, :face_up, :face_down
480
+ rmq.device.orientation
481
+ rmq.device.landscape?
482
+ rmq.device.portrait?
483
+ ```
484
+
485
+ ### Format
486
+ A performant way to format numbers and dates.
487
+
488
+ ```ruby
489
+ rmq.format.number(1232, '#,##0.##')
490
+ rmq.format.date(Time.now, 'EEE, MMM d, ''yy')
491
+ rmq.format.numeric_formatter(your_format_here) # returns cached numeric formatter
492
+ rmq.format.date_formatter(your_format_here) # returns cached date formatter
493
+ ```
494
+ See <http://www.unicode.org/reports/tr35/tr35-19.html#Date_Format_Patterns> for more information about date format strings.
495
+
496
+ ### Utils
497
+
498
+ These are mostly used internally by rmq.
499
+
500
+ ```ruby
501
+ RubyMotionQuery::RMQ.is_class?(foo)
502
+ RubyMotionQuery::RMQ.is_blank?(foo)
503
+ RubyMotionQuery::RMQ.controller_for_view(view)
504
+ RubyMotionQuery::RMQ.view_to_s(view)
505
+ ```
506
+
507
+ ### Pollution
508
+
509
+ The following are the only pollution in RMQ
510
+
511
+ - UIView
512
+ - rmq
513
+ - rmq_data
514
+ - UIViewController
515
+ - rmq
516
+ - rmq_data
517
+ - TopLevel *(Only in development, used for console)*
518
+ - rmq
519
+
520
+ ### Console Fun
521
+
522
+ rmq.all.log
523
+ rmq.all.log :wide
524
+ rmq(UIView).show
525
+ rmq(UILabel).animations.blink
526
+ rmq(UIButton).nudge l: 10
527
+
528
+ ### A recommended project structure
529
+
530
+ - app
531
+ - controllers
532
+ - your_controller.rb
533
+ - your_other_controller.rb
534
+ - models
535
+ - stylers
536
+ - ui_view_styler.rb
537
+ - ui_button_styler.rb
538
+ - etc
539
+ - stylesheets
540
+ - application_stylesheet.rb (inherit from RubyMotionQuery::Stylesheet)
541
+ - your_stylesheet.rb (inherit from ApplicationStylesheet)
542
+ - your_other_stylesheet.rb (inherit from ApplicationStylesheet)
543
+ - views
544
+
545
+ ----------
546
+
547
+ ### Styles and stylesheets
548
+
549
+ 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.
550
+
551
+ **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.
552
+
553
+ #### Example controller
554
+
555
+ ```ruby
556
+ class MainController < UIViewController
557
+
558
+ def viewDidLoad
559
+ super
560
+
561
+ rmq.stylesheet = MainControllerStyleSheet
562
+ view.rmq.apply_style :root_view
563
+
564
+ @title_label = rmq.append(UILabel, :title_label).get
565
+ rmq.append UIImageView, :logo
566
+
567
+ rmq.append(UIButton, :make_labels_blink).on(:tap) do |sender|
568
+ rmq(UILabel).animations.blink
569
+ end
570
+
571
+ rmq.append(UIButton.buttonWithType(UIButtonTypeRoundedRect), :make_buttons_throb).on(:tap) do |sender|
572
+ rmq(UIButton).animations.throb
573
+ end
574
+
575
+ rmq.append(UIView, :section).tap do |section|
576
+ section.append(UILabel, :section_title)
577
+
578
+ section.append(UILabel, :section_enabled_title)
579
+
580
+ section.append(UISwitch, :section_enabled).on(:change) do |sender|
581
+ style = sender.isOn ? :section_button_enabled : :section_button_disabled
582
+ buttons = sender.rmq.parent.find(UIButton).apply_style(style)
583
+ end
584
+
585
+ section.append(UIButton, :start_spinner).on(:tap) do |sender|
586
+ rmq.animations.start_spinner
587
+ end
588
+
589
+ section.append(UIButton, :stop_spinner).on(:tap) do |sender|
590
+ rmq.animations.stop_spinner
591
+ end
592
+ end
593
+
594
+ end
595
+ end
596
+ ```
597
+
598
+ #### Example stylesheet
599
+
600
+ ```ruby
601
+ class ApplicationStylesheet < RubyMotionQuery::Stylesheet
602
+ PADDING = 10
603
+
604
+ def application_setup
605
+ font_family = 'Helvetica Neue'
606
+ font.add_named :large, font_family, 36
607
+ font.add_named :medium, font_family, 24
608
+ font.add_named :small, font_family, 18
609
+
610
+ color.add_named :translucent_black, color.from_rgba(0, 0, 0, 0.4)
611
+ color.add_named :battleship_gray, '#7F7F7F'
612
+ end
613
+
614
+ def label(st)
615
+ st.background_color = color.clear
616
+ end
617
+
618
+ end
619
+
620
+ class MainStylesheet < ApplicationStylesheet
621
+ def setup
622
+ # Add sytlesheet specific setup stuff here.
623
+ # Add application specific setup stuff in application_stylesheet.rb
624
+ end
625
+
626
+ def root_view(st)
627
+ st.background_color = color.white
628
+ end
629
+
630
+ def logo(st)
631
+ st.frame = {t: 10, w: 200, h: 96}
632
+ st.centered = :horizontal
633
+ st.image = image.resource('logo')
634
+ end
635
+
636
+ def title_label(st)
637
+ label st # stack styles
638
+ st.frame = {l: PADDING, t: 120, w: 200, h: 20}
639
+ st.text = 'Test label'
640
+ st.color = color.from_rgba(34, 132, 198, 1.0)
641
+ st.font = font.medium
642
+ end
643
+
644
+ def make_labels_blink(st)
645
+ st.frame = {t: 120, w: 150, h: 20}
646
+ st.from_right = PADDING
647
+
648
+ # ipad? (and landscape?, etc) is just a convenience methods for
649
+ # rmq.device.ipad?
650
+
651
+ # Here is a complete example of different formatting for orientatinos
652
+ # and devices
653
+ # if ipad?
654
+ # if landscape?
655
+ # st.frame = {l: 20, t: 120, w: 150, h: four_inch? ? 20 : 30}
656
+ # else
657
+ # st.frame = {l: 90, t: 120, w: 150, h: four_inch? ? 25 : 35}
658
+ # end
659
+ # else
660
+ # if landscape?
661
+ # st.frame = {l: 20, t: 20, w: 150, h: four_inch? ? 22 : 32}
662
+ # else
663
+ # st.frame = {l: 90, t: 20, w: 150, h: four_inch? ? 30 : 40}
664
+ # end
665
+ # end
666
+
667
+ # If you don't want something to be reapplied during orientation
668
+ # changes (assuming you're reapplying durring orientation changes
669
+ # in your controller, it's not automatic)
670
+ unless st.view_has_been_styled?
671
+ st.text = 'Blink labels'
672
+ st.font = font.system(10)
673
+ st.color = color.white
674
+ st.background_color = color.from_hex('ed1160')
675
+ end
676
+ end
677
+
678
+ def make_buttons_throb(st)
679
+ st.frame = {t: 150, w: 150, h: 20}
680
+ st.from_right = PADDING
681
+ st.text = 'Throb buttons'
682
+ st.color = color.black
683
+ end
684
+
685
+ def section(st)
686
+ st.frame = {w: 270, h: 110}
687
+
688
+ if landscape? && iphone?
689
+ st.left = PADDING
690
+ else
691
+ st.centered = :horizontal
692
+ end
693
+
694
+ st.from_bottom = PADDING
695
+
696
+ st.z_position = 1
697
+ st.background_color = color.battleship_gray
698
+ end
699
+
700
+ def section_label(st)
701
+ label st
702
+ st.color = color.white
703
+ end
704
+
705
+ def section_title(st)
706
+ section_label st
707
+ st.frame = {l: PADDING, t: PADDING, w: 150, h: 20}
708
+ st.text = 'Section title'
709
+ end
710
+
711
+ def section_enabled(st)
712
+ label st
713
+ st.frame = {l: PADDING, t: 30}
714
+ st.on = true
715
+ end
716
+
717
+ def section_enabled_title(st)
718
+ section_label st
719
+ st.frame = {l: 93, t: 34, w: 150, h: 20}
720
+ st.text = 'Enabled'
721
+ end
722
+
723
+ def section_buttons(st)
724
+ st.frame = {l: PADDING, t: 64, w: 120, h: 40}
725
+ st.background_color = color.black
726
+ section_button_enabled st
727
+ end
728
+
729
+ def start_spinner(st)
730
+ section_buttons st
731
+ st.text = 'Start spinner'
732
+ end
733
+
734
+ def stop_spinner(st)
735
+ section_buttons st
736
+ st.from_right = PADDING
737
+ st.text = 'Stop spinner'
738
+ end
739
+
740
+ def section_button_disabled(st)
741
+ st.enabled = false
742
+ st.color = color.dark_gray
743
+ end
744
+
745
+ def section_button_enabled(st)
746
+ st.enabled = true
747
+ st.color = color.white
748
+ end
749
+
750
+ def animate_move(st)
751
+ st.scale = 1.0
752
+ st.frame = {t: 180, w: 150, h: 20}
753
+ st.from_right = PADDING
754
+ st.text = 'Animate move and scale'
755
+ st.font = font.system(10)
756
+ st.color = color.white
757
+ st.background_color = color.from_hex('ed1160')
758
+ st.z_position = 99
759
+ st.color = color.white
760
+ end
761
+
762
+ def overlay(st)
763
+ st.frame = :full
764
+ st.background_color = color.translucent_black
765
+ st.hidden = true
766
+ st.z_position = 99
767
+ end
768
+
769
+ def benchmarks_results_wrapper(st)
770
+ st.hidden = true
771
+ st.frame = {w: app_width - 20, h: 120}
772
+ st.centered = :both
773
+ st.background_color = color.white
774
+ st.z_position = 100
775
+ end
776
+
777
+ def benchmarks_results_label(st)
778
+ label st
779
+ st.padded = {l: 10, t: 10, b:10, r: 10}
780
+ st.text_alignment = :left
781
+ st.color = color.black
782
+ st.font = font.system(10)
783
+
784
+ # If the styler doesn't have the method, you can add it or
785
+ # just use st.view to get the actual object
786
+ st.view.numberOfLines = 0
787
+ st.view.lineBreakMode = NSLineBreakByWordWrapping
788
+ end
789
+
790
+ def run_benchmarks(st)
791
+ st.frame = {l: PADDING, t: 150, w: 130, h: 20}
792
+ st.text = 'Run benchmarks'
793
+ st.font = font.system(11)
794
+ st.color = color.white
795
+ st.enabled = true
796
+ st.background_color = color.from_hex('faa619')
797
+ end
798
+
799
+ def run_benchmarks_disabled(st)
800
+ st.enabled = false
801
+ st.color = color.from_hex('de8714')
802
+ end
803
+
804
+ def benchmark(st)
805
+ st.hidden = false
806
+ st.text = 'foo'
807
+ st.color = color.white
808
+ st.left = 10
809
+ end
810
+
811
+ end
812
+ ```
813
+
814
+ #### Stylers
815
+
816
+ A styler wraps around a view, augmenting it with styling power and sugar.
817
+
818
+ 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.
819
+
820
+ When you create a "style method", it will be passed the view, wrapped in a styler. You can get the view using st.view.
821
+
822
+ ##### UIViewStyler
823
+ Here is a silly example, showing you a bunch of methods the UIViewStyler gives you:
824
+
825
+ ```ruby
826
+ def ui_view_kitchen_sink(st)
827
+ st.frame = {l: 1, t: 2, w: 3, h: 4}
828
+ st.frame = {left: 1, top: 2, width: 3, height: 4}
829
+ st.frame = {left: 10}
830
+ st.left = 20
831
+ st.top = 30
832
+ st.width = 40
833
+ st.height = 50
834
+ st.right = 100
835
+ st.bottom = 110
836
+ st.from_right = 10
837
+ st.from_bottom = 12
838
+ st.padded = {l: 1, t: 2, r: 3, b: 4}
839
+ st.padded = {left: 1, top: 2, right: 3, bottom: 4}
840
+ st.center = st.superview.center
841
+ st.center_x = 50
842
+ st.center_y = 60
843
+ st.centered = :horizontal
844
+ st.centered = :vertical
845
+ st.centered = :both
846
+
847
+ st.enabled = true
848
+ st.hidden = false
849
+ st.z_position = 66
850
+ st.opaque = false
851
+
852
+ st.background_color = color.red
853
+
854
+ st.scale = 1.5
855
+ end
856
+ ```
857
+
858
+ ##### UIControlStyler
859
+ Nothing yet
860
+
861
+ ##### UILabelStyler
862
+
863
+ ```ruby
864
+ def ui_label_kitchen_sink(st)
865
+ st.text = 'rmq is awesome'
866
+ st.font = font.system(12)
867
+ st.color = color.black
868
+ st.text_alignment = :center
869
+
870
+ st.resize_to_fit_text
871
+ st.size_to_fit
872
+ end
873
+ ```
874
+
875
+ ##### UIButtonStyler
876
+
877
+ ```ruby
878
+ def ui_button_kitchen_sink(st)
879
+ st.text = 'foo'
880
+ st.font = font.system(12)
881
+ st.color = color.red
882
+ st.image_normal = image.resource('logo')
883
+ st.image_highlighted = image.resource('logo')
884
+ end
885
+ ```
886
+
887
+ ##### UIImageViewStyler
888
+
889
+ ```ruby
890
+ def u_image_view_kitchen_sink(st)
891
+ st.image = image.resource('logo')
892
+ end
893
+ ```
894
+
895
+ ##### UIScrollViewStyler
896
+
897
+ ```ruby
898
+ def ui_scroll_view_kitchen_sink(st)
899
+ st.paging = true
900
+ end
901
+ ```
902
+
903
+ ##### UISwitchStyler
904
+
905
+ ```ruby
906
+ def ui_switch_kitchen_sink(st)
907
+ st.on = true
908
+ end
909
+ ```
910
+
911
+ **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**
912
+
913
+ #### Add your own stylers
914
+
915
+ In the example app, look in **/app/stylers**, you can just copy that whole folder to start. Then add methods to the appropriate class.
916
+
917
+ Here is an example of adding a method to all stylers:
918
+ ```ruby
919
+ module RubyMotionQuery
920
+ module Stylers
921
+ class UIViewStyler
922
+
923
+ def border_width=(value)
924
+ @view.layer.borderWidth = value
925
+ end
926
+ def border_width
927
+ @view.layer.borderWidth
928
+ end
929
+
930
+ end
931
+ end
932
+ end
933
+ ```
934
+
935
+ You can also include all of your custom stylers in one file, which works well if you don't have a lot.
936
+
937
+
938
+ ## Contact
939
+
940
+ created by **Todd Werth** ([http://toddwerth.com](http://toddwerth.com))
941
+
942
+ - [@twerth](http://twitter.com/twerth)
943
+ - [todd@infinitered.com](mailto:todd@infinitered.com)
944
+ - [github](https://github.com/twerth)
945
+
946
+ with help from the team at **InfiniteRed** ([http://infinitered.com](http://infinitered.com))
947
+
948
+ - [@infinite_red](http://twitter.com/infinite_red)
949
+ - [github](https://github.com/infinitered)
950
+
951
+
952
+ ## License
953
+
954
+ RMQ is available under the MIT license. See the LICENSE file for more info.
955
+
956
+ ## Contributing
957
+
958
+ 1. Fork it
959
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
960
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
961
+ 4. Push to the branch (`git push origin my-new-feature`)
962
+ 5. Create new Pull Request
963
+
964
+ [1]: http://infinitered.com/rmq