ProMotion 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -10,6 +10,6 @@ pom.xml
10
10
  /build
11
11
  .DS_Store
12
12
  *.clj
13
- .repl_histroy
14
13
  .rvmrc
15
14
  *.gem
15
+ .repl_history
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ promotion
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p392
data/Gemfile CHANGED
@@ -3,3 +3,5 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in ProMotion.gemspec
4
4
  gemspec
5
5
 
6
+ # Use this in development
7
+ gem "motion-stump"
data/Gemfile.lock CHANGED
@@ -1,14 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ProMotion (0.4.0)
4
+ ProMotion (0.5.2)
5
5
 
6
6
  GEM
7
- remote: http://rubygems.org/
7
+ remote: https://rubygems.org/
8
8
  specs:
9
+ motion-stump (0.2.1)
9
10
 
10
11
  PLATFORMS
11
12
  ruby
12
13
 
13
14
  DEPENDENCIES
14
15
  ProMotion!
16
+ motion-stump
data/README.md CHANGED
@@ -8,6 +8,7 @@ with your app's designed screens.
8
8
  1. [Tutorials](#tutorials)
9
9
  * [Screencasts](#screencasts)
10
10
  * [Sample Apps](#sample-apps)
11
+ * [Apps Built With ProMotion](#apps-built-with-promotion)
11
12
  1. **[Getting Started](#getting-started)**
12
13
  * [Setup](#setup)
13
14
  1. [What's New?](#whats-new)
@@ -36,13 +37,20 @@ Video tutorial with 0.4.
36
37
 
37
38
  http://www.clearsightstudio.com/insights/tutorial-make-youtube-video-app-rubymotion-promotion/
38
39
 
39
- ### Sample apps
40
+ ### Sample Apps
40
41
 
41
- Sample app here: https://github.com/jamonholmgren/promotion-tutorial
42
+ #### ProMotion Tutorial
43
+ Sample app here: [https://github.com/jamonholmgren/promotion-tutorial](https://github.com/jamonholmgren/promotion-tutorial)
42
44
 
43
- Also, check out the free [BigDay! Reminder app](https://itunes.apple.com/us/app/bigday!/id571756685?ls=1&mt=8) on the
45
+ ### Apps Built With ProMotion
46
+
47
+ #### BigDay! Reminder App
48
+ Check out the free [BigDay! Reminder app](https://itunes.apple.com/us/app/bigday!/id571756685?ls=1&mt=8) on the
44
49
  App Store to see what's possible. ClearSight Studio built the app for Kijome Software, a small app investment company.
45
50
 
51
+ #### TipCounter App
52
+ [TipCounter](http://www.tipcounterapp.com) was built by [Matt Brewer](https://github.com/macfanatic/) for bartenders and servers to easily track their tips. Used ProMotion and the development was a lot of fun!
53
+
46
54
  ## Getting Started
47
55
 
48
56
  ProMotion is designed to be as intuitive and Ruby-like as possible. For example, here is a
@@ -85,7 +93,7 @@ Create a Gemfile and add the following lines:
85
93
 
86
94
  ```ruby
87
95
  source 'https://rubygems.org'
88
- gem "ProMotion", "~> 0.4.1"
96
+ gem "ProMotion", "~> 0.5.0"
89
97
  ```
90
98
 
91
99
  Run `bundle install` in Terminal to install ProMotion.
@@ -122,11 +130,13 @@ Run `rake`. You should now see the simulator open with your home screen and a na
122
130
 
123
131
  ## What's New?
124
132
 
125
- ### Version 0.5.0
133
+ ### Version 0.5
126
134
 
127
- Version 0.5.0 is mostly a documentation and consistency release. It should be backwards-compatible
128
- with 0.4.0.
135
+ Version 0.5 is mostly a documentation and consistency release. It should be backwards-compatible
136
+ with 0.4.
129
137
 
138
+ * `on_return` fires after animation complete on modals now
139
+ * Added tests ... run with `rake spec` (thanks [@macfanatic](http://twitter.com/macfanatic))
130
140
  * Rearranged internal folders to make a lot more sense
131
141
  * More complete API documentation
132
142
  * Refactored camelCase methods and configs to under_score
@@ -135,7 +145,7 @@ with 0.4.0.
135
145
  * `add_element` is now `add` (and `remove_element` is `remove`)
136
146
  * Removed built-in app (will release some sample apps soon, including a "Kitchen Sink" one)
137
147
 
138
- ### Version 0.4.0
148
+ ### Version 0.4
139
149
 
140
150
  * Screens are now UIViewControllers (they used to contain UIViewControllers, but that got too funky) so you can do normal UIViewController stuff with them
141
151
  * Screen functionality can also be inherited as a module in your own UIViewController, but you need to provide your own methods for viewDidLoad and whatnot.
@@ -164,8 +174,8 @@ class HomeScreen < ProMotion::Screen
164
174
  end
165
175
 
166
176
  def will_appear
167
- # Set up the elements in your view with add_view
168
- @label = add_view UILabel.alloc.initWithFrame(CGRectMake(5, 5, 20, 20))
177
+ # Set up the elements in your view with add
178
+ @label ||= add UILabel.alloc.initWithFrame(CGRectMake(5, 5, 20, 20))
169
179
  end
170
180
 
171
181
  def on_appear
@@ -306,22 +316,22 @@ end
306
316
 
307
317
  ### Adding view elements
308
318
 
309
- Any view item (UIView, UIButton, custom UIView subclasses, etc) can be added to the current view with `add_view`.
310
- `add_view` accepts a second argument which is a hash of attributes that get applied to the element before it is
319
+ Any view item (UIView, UIButton, custom UIView subclasses, etc) can be added to the current view with `add`.
320
+ `add` accepts a second argument which is a hash of attributes that get applied to the element before it is
311
321
  dropped into the view.
312
322
 
313
323
  ```ruby
314
- @label = add_view UILabel.alloc.initWithFrame(CGRectMake(5, 5, 20, 20)), {
324
+ @label = add UILabel.alloc.initWithFrame(CGRectMake(5, 5, 20, 20)), {
315
325
  text: "This is awesome!",
316
326
  font: UIFont.systemFontOfSize(18)
317
327
  }
318
328
 
319
- @element = add_view UIView.alloc.initWithFrame(CGRectMake(0, 0, 20, 20)), {
329
+ @element = add UIView.alloc.initWithFrame(CGRectMake(0, 0, 20, 20)), {
320
330
  backgroundColor: UIColor.whiteColor
321
331
  }
322
332
  ```
323
333
 
324
- The `set_attributes` method is identical to add_view except that it does not add it to the current view.
334
+ The `set_attributes` method is identical to add except that it does not add it to the current view.
325
335
 
326
336
  ```ruby
327
337
  @element = set_attributes UIView.alloc.initWithFrame(CGRectMake(0, 0, 20, 20)), {
@@ -448,29 +458,26 @@ end
448
458
 
449
459
  ## Reference
450
460
 
461
+ ### Screen
462
+
451
463
  <table>
452
464
  <tr>
453
- <th>Class or Module</th>
454
465
  <th>Method</th>
455
466
  <th>Description</th>
456
467
  </tr>
457
468
  <tr>
458
- <td>Screen</td>
459
469
  <td>is_modal?</td>
460
470
  <td>Returns if the screen was opened in a modal window.</td>
461
471
  </tr>
462
472
  <tr>
463
- <td>&nbsp;</td>
464
473
  <td>self</td>
465
474
  <td>Returns the Screen which is a subclass of UIViewController or UITableViewController</td>
466
475
  </tr>
467
476
  <tr>
468
- <td>&nbsp;</td>
469
477
  <td>has_nav_bar?</td>
470
478
  <td>Returns if the screen is contained in a navigation controller.</td>
471
479
  </tr>
472
480
  <tr>
473
- <td>&nbsp;</td>
474
481
  <td>set_tab_bar_item(args)</td>
475
482
  <td>
476
483
  Creates the tab that is shown in a tab bar item.<br />
@@ -478,14 +485,12 @@ end
478
485
  </td>
479
486
  </tr>
480
487
  <tr>
481
- <td>&nbsp;</td>
482
488
  <td>on_appear</td>
483
489
  <td>
484
490
  Callback for when the screen appears.<br />
485
491
  </td>
486
492
  </tr>
487
493
  <tr>
488
- <td>&nbsp;</td>
489
494
  <td>will_appear</td>
490
495
  <td>
491
496
  Callback for before the screen appears.<br />
@@ -494,21 +499,18 @@ end
494
499
  </td>
495
500
  </tr>
496
501
  <tr>
497
- <td>&nbsp;</td>
498
502
  <td>will_disappear</td>
499
503
  <td>
500
504
  Callback for before the screen disappears.<br />
501
505
  </td>
502
506
  </tr>
503
507
  <tr>
504
- <td>&nbsp;</td>
505
508
  <td>will_rotate(orientation, duration)</td>
506
509
  <td>
507
510
  Callback for before the screen rotates.<br />
508
511
  </td>
509
512
  </tr>
510
513
  <tr>
511
- <td>&nbsp;</td>
512
514
  <td>on_opened **Deprecated**</td>
513
515
  <td>
514
516
  Callback when screen is opened via a tab bar. Please don't use this, as it will be removed in the future<br />
@@ -516,14 +518,12 @@ end
516
518
  </td>
517
519
  </tr>
518
520
  <tr>
519
- <td>&nbsp;</td>
520
521
  <td>set_nav_bar_left_button(title, args = {})</td>
521
522
  <td>
522
523
  Set a left nav bar button.<br />
523
524
  </td>
524
525
  </tr>
525
526
  <tr>
526
- <td>&nbsp;</td>
527
527
  <td>set_nav_bar_right_button(title, args = {})</td>
528
528
  <td>
529
529
  Set a right nav bar button.<br />
@@ -531,7 +531,6 @@ end
531
531
  </td>
532
532
  </tr>
533
533
  <tr>
534
- <td>&nbsp;</td>
535
534
  <td>should_autorotate</td>
536
535
  <td>
537
536
  (iOS 6) return true/false if screen should rotate.<br />
@@ -539,21 +538,18 @@ end
539
538
  </td>
540
539
  </tr>
541
540
  <tr>
542
- <td>&nbsp;</td>
543
541
  <td>should_rotate(orientation)</td>
544
542
  <td>
545
543
  (iOS 5) Return true/false for rotation to orientation.<br />
546
544
  </td>
547
545
  </tr>
548
546
  <tr>
549
- <td>&nbsp;</td>
550
547
  <td>title</td>
551
548
  <td>
552
549
  Returns title of current screen.<br />
553
550
  </td>
554
551
  </tr>
555
552
  <tr>
556
- <td>&nbsp;</td>
557
553
  <td>title=(title)</td>
558
554
  <td>
559
555
  Sets title of current screen.<br />
@@ -570,24 +566,19 @@ end
570
566
  </td>
571
567
  </tr>
572
568
  <tr>
573
- <td>
574
- ScreenElements<br />
575
- Included in Screen by default
576
- </td>
577
569
  <td>add(view, attrs = {})</td>
578
570
  <td>
579
571
  Adds the view to the screen after applying the attributes.<br />
580
572
  (alias: `add_element`, `add_view`)<br />
581
573
  Example:
582
574
  <code>
583
- add_view UIInputView.alloc.initWithFrame(CGRectMake(10, 10, 300, 40)), {
575
+ add UIInputView.alloc.initWithFrame(CGRectMake(10, 10, 300, 40)), {
584
576
  backgroundColor: UIColor.grayColor
585
577
  }
586
578
  </code>
587
579
  </td>
588
580
  </tr>
589
581
  <tr>
590
- <td>&nbsp;</td>
591
582
  <td>remove(view)</td>
592
583
  <td>
593
584
  Removes the view from the superview and sets it to nil<br />
@@ -595,96 +586,78 @@ end
595
586
  </td>
596
587
  </tr>
597
588
  <tr>
598
- <td>&nbsp;</td>
599
589
  <td>bounds</td>
600
590
  <td>
601
591
  Accessor for self.view.bounds<br />
602
592
  </td>
603
593
  </tr>
604
594
  <tr>
605
- <td>&nbsp;</td>
606
595
  <td>frame</td>
607
596
  <td>
608
597
  Accessor for self.view.frame<br />
609
598
  </td>
610
599
  </tr>
611
600
  <tr>
612
- <td>&nbsp;</td>
613
601
  <td>view</td>
614
602
  <td>
615
603
  The main view for this screen.<br />
616
604
  </td>
617
605
  </tr>
618
606
  <tr>
619
- <td>
620
- SystemHelper<br />
621
- Included in Screen by default
622
- </td>
623
607
  <td>ios_version</td>
624
608
  <td>
625
609
  Returns the iOS version that is running on the device<br />
626
610
  </td>
627
611
  </tr>
628
612
  <tr>
629
- <td>&nbsp;</td>
630
613
  <td>ios_version_greater?(version)</td>
631
614
  <td>
632
615
  Returns true if 'ios_version' is greater than the version passed in, false otherwise<br />
633
616
  </td>
634
617
  </tr>
635
618
  <tr>
636
- <td>&nbsp;</td>
637
619
  <td>ios_version_greater_eq?(version)</td>
638
620
  <td>
639
621
  Returns true if 'ios_version' is greater than or equal to the version passed in, false otherwise<br />
640
622
  </td>
641
623
  </tr>
642
624
  <tr>
643
- <td>&nbsp;</td>
644
625
  <td>ios_version_is?(version)</td>
645
626
  <td>
646
627
  Returns true if 'ios_version' is equal to the version passed in, false otherwise<br />
647
628
  </td>
648
629
  </tr>
649
630
  <tr>
650
- <td>&nbsp;</td>
651
631
  <td>ios_version_less?(version)</td>
652
632
  <td>
653
633
  Returns true if 'ios_version' is less than the version passed in, false otherwise<br />
654
634
  </td>
655
635
  </tr>
656
636
  <tr>
657
- <td>&nbsp;</td>
658
637
  <td>ios_version_less_eq?(version)</td>
659
638
  <td>
660
639
  Returns true if 'ios_version' is less than or equal to the version passed in, false otherwise<br />
661
640
  </td>
662
641
  </tr>
663
642
  <tr>
664
- <td>ScreenNavigation<br />
665
- included in Screen
666
- </td>
667
643
  <td>app_delegate</td>
668
644
  <td>
669
645
  Returns the AppDelegate<br />
670
646
  </td>
671
647
  </tr>
672
648
  <tr>
673
- <td>&nbsp;</td>
674
649
  <td>close(args = {})</td>
675
650
  <td>
676
651
  Closes the current screen, passes args back to the previous screen's <code>on_return</code> method<br />
677
652
  </td>
678
653
  </tr>
679
654
  <tr>
680
- <td>&nbsp;</td>
681
655
  <td>open_root_screen(screen)</td>
682
656
  <td>
683
657
  Closes all other open screens and opens <code>screen</code> as the root view controller.<br />
684
658
  </td>
685
659
  </tr>
686
660
  <tr>
687
- <td>&nbsp;</td>
688
661
  <td>open(screen, args = {})</td>
689
662
  <td>
690
663
  Pushes the screen onto the navigation stack or opens in a modal<br />
@@ -699,37 +672,37 @@ end
699
672
  </td>
700
673
  </tr>
701
674
  <tr>
702
- <td>&nbsp;</td>
703
675
  <td>open_tab_bar(*screens)</td>
704
676
  <td>
705
677
  Open a UITabBarController with the specified screens as the root view controller of the current app<br />
706
678
  </td>
707
679
  </tr>
708
680
  <tr>
709
- <td>&nbsp;</td>
710
681
  <td>open_tab(tab)</td>
711
682
  <td>
712
683
  Opens the tab where the "string" title matches the passed in tab<br />
713
684
  </td>
714
685
  </tr>
715
-
686
+ </table>
687
+
688
+ ### TableScreen
689
+
690
+ *Has all the methods of Screen*
691
+
692
+ <table>
716
693
  <tr>
717
- <td>TableScreen</td>
718
- <td>&nbsp;</td>
719
- <td>*Has all the methods of Screen*</td>
694
+ <th>Method</th>
695
+ <th>Description</th>
720
696
  </tr>
721
697
  <tr>
722
- <td>&nbsp;</td>
723
698
  <td>self</td>
724
699
  <td>Returns the current UITableViewController (not UITableView)</td>
725
700
  </tr>
726
701
  <tr>
727
- <td>&nbsp;</td>
728
702
  <td>searchable(placeholder: "placeholder text")</td>
729
703
  <td>Class method to make the current table searchable.</td>
730
704
  </tr>
731
705
  <tr>
732
- <td>&nbsp;</td>
733
706
  <td colspan="2">
734
707
  <h3>table_data</h3>
735
708
  Method that is called to get the table's cell data and build the table.<br />
@@ -788,16 +761,22 @@ end
788
761
  </td>
789
762
  </tr>
790
763
  <tr>
791
- <td>&nbsp;</td>
792
764
  <td>update_table_data</td>
793
765
  <td>
794
766
  Causes the table data to be refreshed, such as when a remote data source has
795
767
  been downloaded and processed.<br />
796
768
  </td>
797
769
  </tr>
770
+ </table>
798
771
 
772
+ ### Console
773
+
774
+ <table>
775
+ <tr>
776
+ <th>Method</th>
777
+ <th>Description</th>
778
+ </tr>
799
779
  <tr>
800
- <td>Console</td>
801
780
  <td>log(log, with_color:color)</td>
802
781
  <td>
803
782
  Class method to output a colored console message.<br />
@@ -813,3 +792,20 @@ If you need help, feel free to ping me on twitter @jamonholmgren or email jamon@
813
792
  ## Contributing
814
793
 
815
794
  I'm really looking for feedback. Tweet me with your ideas or open a ticket (I don't mind!) and let's discuss.
795
+
796
+ ### Submitting a Pull Request
797
+
798
+ 1. Fork the project
799
+ 2. Create a feature branch
800
+ 3. Code
801
+ 4. Update or create new specs
802
+ 5. Make sure tests are passing by running `rake spec`
803
+ 6. Submit pull request
804
+
805
+ ### Primary Contributors
806
+
807
+ * Jamon Holmgren: [@jamonholmgren](https://twitter.com/jamonholmgren)
808
+ * Silas Matson: [@silasjmatson](https://twitter.com/silasjmatson)
809
+ * Matt Brewer: [@macfanatic](https://twitter.com/macfanatic)
810
+
811
+
@@ -0,0 +1,2 @@
1
+ class AppDelegate
2
+ end
@@ -8,15 +8,18 @@ module ProMotion
8
8
 
9
9
  class << self
10
10
  def log(log, with_color:color)
11
+ return if RUBYMOTION_ENV == "test"
11
12
  puts color[0] + NAME + log + color[1]
12
13
  end
13
14
 
14
15
  def log(log, withColor:color)
16
+ return if RUBYMOTION_ENV == "test"
15
17
  warn "[DEPRECATION] `log(log, withColor:color)` is deprecated. Use `log(log, with_color:color)`"
16
18
  self.log(log, with_color:color)
17
19
  end
18
20
 
19
21
  def log(log)
22
+ return if RUBYMOTION_ENV == "test"
20
23
  log(log, with_color: DEFAULT_COLOR)
21
24
  end
22
25
  end
@@ -19,7 +19,7 @@ module ProMotion
19
19
 
20
20
  def frame_from_array(array)
21
21
  return CGRectMake(array[0], array[1], array[2], array[3]) if array.length == 4
22
- Console.log(" - frame_from_array expects an array with four elements: [x, y, width, height]", withColor: Console::RED_COLOR)
22
+ Console.log(" - frame_from_array expects an array with four elements: [x, y, width, height]", with_color: Console::RED_COLOR)
23
23
  CGRectZero
24
24
  end
25
25
 
@@ -27,17 +27,5 @@ module ProMotion
27
27
  return self.view.frame
28
28
  end
29
29
 
30
- def content_height(view)
31
- height = 0
32
- view.subviews.each do |subview|
33
- next if subview.isHidden
34
- y = subview.frame.origin.y
35
- h = subview.frame.size.height
36
- if (y + h) > height
37
- height = y + h
38
- end
39
- end
40
- height
41
- end
42
30
  end
43
31
  end
@@ -1,55 +1,35 @@
1
1
  module ProMotion
2
2
  module ScreenNavigation
3
- # TODO: De-uglify this method.
4
- def open_screen(screen, args = {})
5
- # Instantiate screen if given a class
6
- screen = screen.new if screen.respond_to?(:new)
7
-
8
- screen.parent_screen = self if screen.respond_to?("parent_screen=")
9
-
10
- screen.title = args[:title] if args[:title] && screen.respond_to?("title=")
11
3
 
12
- screen.modal = args[:modal] if args[:modal] && screen.respond_to?("modal=")
4
+ def open_screen(screen, args = {})
13
5
 
14
- screen.hidesBottomBarWhenPushed = args[:hide_tab_bar] unless args[:hide_tab_bar].nil?
6
+ # Apply properties to instance
7
+ screen = setup_screen_for_open(screen, args)
8
+ ensure_wrapper_controller_in_place(screen, args)
15
9
 
16
- screen.add_nav_bar if args[:nav_bar] && screen.respond_to?(:add_nav_bar)
17
-
18
- unless args[:close_all] || args[:modal]
19
- screen.navigation_controller ||= self.navigation_controller if screen.respond_to?("navigation_controller=")
20
- screen.tab_bar ||= self.tab_bar if screen.respond_to?("tab_bar=")
21
- end
22
-
23
- screen.send(:on_load) if screen.respond_to?(:on_load)
24
-
25
- animated = args[:animated]
26
- animated ||= true
10
+ screen.send(:on_load) if screen.respond_to?(:on_load)
11
+ animated = args[:animated] || true
27
12
 
28
13
  if args[:close_all]
29
- open_root_screen(screen)
14
+ open_root_screen screen
15
+
30
16
  elsif args[:modal]
31
- vc = screen
32
- vc = screen.main_controller if screen.respond_to?("main_controller=")
33
- self.presentModalViewController(vc, animated:animated)
17
+ present_modal_view_controller screen, animated
18
+
34
19
  elsif args[:in_tab] && self.tab_bar
35
- vc = open_tab(args[:in_tab])
36
- if vc
37
- if vc.is_a?(UINavigationController)
38
- screen.navigation_controller = vc if screen.respond_to?("navigation_controller=")
39
- push_view_controller(screen, vc)
40
- else
41
- self.tab_bar.selectedIndex = vc.tabBarItem.tag
42
- end
43
- else
44
- Console.log("No tab bar item '#{args[:in_tab]}'", with_color: Console::RED_COLOR)
45
- end
20
+ present_view_controller_in_tab_bar_controller screen, args[:in_tab]
21
+
46
22
  elsif self.navigation_controller
47
23
  push_view_controller screen
24
+
48
25
  elsif screen.respond_to?(:main_controller)
49
26
  open_view_controller screen.main_controller
27
+
50
28
  else
51
29
  open_view_controller screen
30
+
52
31
  end
32
+
53
33
  end
54
34
  alias :open :open_screen
55
35
 
@@ -65,36 +45,36 @@ module ProMotion
65
45
  # TODO: De-uglify this method.
66
46
  def close_screen(args = {})
67
47
  args ||= {}
68
- args[:animated] = true
48
+ args[:animated] ||= true
69
49
 
70
50
  # Pop current view, maybe with arguments, if in navigation controller
71
- previous_screen = self.parent_screen
72
51
  if self.is_modal?
73
- self.parent_screen.dismissModalViewControllerAnimated(args[:animated])
52
+ close_modal_screen args
53
+
74
54
  elsif self.navigation_controller
75
- if args[:to_screen] && args[:to_screen].is_a?(UIViewController)
76
- self.navigation_controller.popToViewController(args[:to_screen], animated: args[:animated])
77
- previous_screen = args[:to_screen]
78
- else
79
- self.navigation_controller.popViewControllerAnimated(args[:animated])
80
- end
55
+ close_nav_screen args
56
+ send_on_return(args) # TODO: this would be better implemented in a callback or view_did_disappear.
57
+
81
58
  else
82
59
  Console.log("Tried to close #{self.to_s}; however, this screen isn't modal or in a nav bar.", withColor: Console::PURPLE_COLOR)
60
+
83
61
  end
84
-
85
- if previous_screen && previous_screen.respond_to?(:on_return)
62
+ end
63
+ alias :close :close_screen
64
+
65
+ def send_on_return(args = {})
66
+ if self.parent_screen && self.parent_screen.respond_to?(:on_return)
86
67
  if args
87
- previous_screen.send(:on_return, args)
68
+ self.parent_screen.send(:on_return, args)
88
69
  else
89
- previous_screen.send(:on_return)
70
+ self.parent_screen.send(:on_return)
90
71
  end
91
- ProMotion::Screen.current_screen = previous_screen
72
+ ProMotion::Screen.current_screen = self.parent_screen
92
73
  end
93
74
  end
94
- alias :close :close_screen
95
75
 
96
76
  def open_view_controller(vc)
97
- UIApplication.sharedApplication.delegate.load_root_view vc
77
+ app_delegate.load_root_view vc
98
78
  end
99
79
 
100
80
  def push_view_controller(vc, nav_controller=nil)
@@ -102,5 +82,78 @@ module ProMotion
102
82
  nav_controller ||= self.navigation_controller
103
83
  nav_controller.pushViewController(vc, animated: true)
104
84
  end
85
+
86
+
87
+
88
+
89
+ protected
90
+
91
+ def setup_screen_for_open(screen, args={})
92
+
93
+ # Instantiate screen if given a class
94
+ screen = screen.new if screen.respond_to?(:new)
95
+
96
+ # Set parent, title & modal properties
97
+ screen.parent_screen = self if screen.respond_to?("parent_screen=")
98
+ screen.title = args[:title] if args[:title] && screen.respond_to?("title=")
99
+ screen.modal = args[:modal] if args[:modal] && screen.respond_to?("modal=")
100
+
101
+ # Hide bottom bar?
102
+ screen.hidesBottomBarWhenPushed = args[:hide_tab_bar] == true
103
+
104
+ # Wrap in a PM::NavigationController?
105
+ screen.add_nav_bar if args[:nav_bar] && screen.respond_to?(:add_nav_bar)
106
+
107
+ # Return modified screen instance
108
+ screen
109
+
110
+ end
111
+
112
+ def ensure_wrapper_controller_in_place(screen, args={})
113
+ unless args[:close_all] || args[:modal]
114
+ screen.navigation_controller ||= self.navigation_controller if screen.respond_to?("navigation_controller=")
115
+ screen.tab_bar ||= self.tab_bar if screen.respond_to?("tab_bar=")
116
+ end
117
+ end
118
+
119
+ def present_modal_view_controller(screen, animated)
120
+ vc = screen
121
+ vc = screen.main_controller if screen.respond_to?(:main_controller)
122
+ self.presentModalViewController(vc, animated:animated)
123
+ end
124
+
125
+ def present_view_controller_in_tab_bar_controller(screen, tab_name)
126
+ vc = open_tab tab_name
127
+ if vc
128
+
129
+ if vc.is_a?(UINavigationController)
130
+ screen.navigation_controller = vc if screen.respond_to?("navigation_controller=")
131
+ push_view_controller(screen, vc)
132
+ else
133
+ self.tab_bar.selectedIndex = vc.tabBarItem.tag
134
+ end
135
+
136
+ else
137
+ Console.log("No tab bar item '#{tab_name}'", with_color: Console::RED_COLOR)
138
+ end
139
+ end
140
+
141
+ def close_modal_screen(args={})
142
+ args[:animated] ||= true
143
+ self.parent_screen.dismissViewControllerAnimated(args[:animated], completion: lambda {
144
+ send_on_return(args)
145
+ })
146
+ end
147
+
148
+ def close_nav_screen(args={})
149
+ args[:animated] ||= true
150
+ if args[:to_screen] && args[:to_screen].is_a?(UIViewController)
151
+ self.parent_screen = args[:to_screen]
152
+ self.navigation_controller.popToViewController(args[:to_screen], animated: args[:animated])
153
+ else
154
+ self.navigation_controller.popViewControllerAnimated(args[:animated])
155
+ end
156
+ end
157
+
105
158
  end
106
159
  end
@@ -131,7 +131,7 @@ module ProMotion
131
131
  end
132
132
 
133
133
  def main_controller
134
- return self.navigationController if self.navigationController
134
+ return self.navigation_controller if self.navigation_controller
135
135
  self
136
136
  end
137
137
 
@@ -1,3 +1,3 @@
1
1
  module ProMotion
2
- VERSION = "0.5.0" unless defined?(ProMotion::VERSION)
2
+ VERSION = "0.5.2" unless defined?(ProMotion::VERSION)
3
3
  end
File without changes
@@ -0,0 +1,2 @@
1
+ class BasicScreen < ProMotion::Screen
2
+ end
@@ -0,0 +1,3 @@
1
+ class DummyClass
2
+ # will dynamically do things with this thing
3
+ end
@@ -0,0 +1,13 @@
1
+ class HomeScreen < ProMotion::Screen
2
+
3
+ title "Home"
4
+
5
+ def on_load
6
+ set_nav_bar_right_button "Save", action: :save_something, type: UIBarButtonItemStyleDone
7
+ set_nav_bar_left_button "Cancel", action: :return_to_some_other_screen, type: UIBarButtonItemStylePlain
8
+ end
9
+
10
+ def on_return(args={})
11
+ end
12
+
13
+ end
@@ -0,0 +1,28 @@
1
+ describe "ios version" do
2
+
3
+ before do
4
+ @dummy = DummyClass.new
5
+ @dummy.extend ProMotion::SystemHelper
6
+ end
7
+
8
+ it "#ios_version_is?" do
9
+ @dummy.ios_version_is?(@dummy.ios_version).should == true
10
+ end
11
+
12
+ it "#ios_version_greater?" do
13
+ @dummy.ios_version_greater?('1.0').should == true
14
+ end
15
+
16
+ it "#ios_version_greater_eq?" do
17
+ @dummy.ios_version_greater_eq?(@dummy.ios_version).should == true
18
+ end
19
+
20
+ it "#ios_version_less?" do
21
+ @dummy.ios_version_less?('9.0').should == true
22
+ end
23
+
24
+ it "#ios_version_less_eq?" do
25
+ @dummy.ios_version_less_eq?(@dummy.ios_version).should == true
26
+ end
27
+
28
+ end
data/spec/main_spec.rb ADDED
@@ -0,0 +1,13 @@
1
+ describe "pro motion module" do
2
+
3
+ it "should have 'PM' module" do
4
+ should.not.raise(NameError) { PM }
5
+ end
6
+
7
+ it "should not allow screen inclusion into just any class" do
8
+ dummy = DummyClass.new
9
+ dummy.extend ProMotion::ScreenModule
10
+ should.raise(StandardError) { dummy.on_create }
11
+ end
12
+
13
+ end
@@ -0,0 +1,191 @@
1
+ describe "screen helpers" do
2
+
3
+ describe "screen elements" do
4
+
5
+ before do
6
+ @screen = HomeScreen.new
7
+ @screen.on_load
8
+ @subview = UIView.alloc.initWithFrame CGRectZero
9
+ end
10
+
11
+ it "should add a subview" do
12
+ @screen.add @subview
13
+ @screen.view.subviews.count.should == 1
14
+ end
15
+
16
+ it "should set attributes before adding a subview" do
17
+ @screen.add @subview, backgroundColor: UIColor.redColor
18
+ @screen.view.subviews.first.backgroundColor.should == UIColor.redColor
19
+ end
20
+
21
+ it "should let you remove a view" do
22
+ @screen.view.addSubview @subview
23
+ @screen.remove @subview
24
+ @screen.view.subviews.count.should == 0
25
+ end
26
+
27
+ end
28
+
29
+
30
+ describe "screen navigation" do
31
+
32
+ before do
33
+ @screen = HomeScreen.new nav_bar: true
34
+ @screen.on_load
35
+ @second_vc = UIViewController.alloc.initWithNibName(nil, bundle:nil)
36
+ end
37
+
38
+ it "#push_view_controller should use the default navigation controller if not provided" do
39
+ vcs = @screen.navigation_controller.viewControllers
40
+ @screen.push_view_controller @second_vc
41
+ @screen.navigation_controller.viewControllers.count.should == vcs.count + 1
42
+ end
43
+
44
+ it "#push_view_controller should use a provided navigation controller" do
45
+ second_nav_controller = UINavigationController.alloc.initWithRootViewController @screen
46
+ @screen.push_view_controller @second_vc, second_nav_controller
47
+ second_nav_controller.viewControllers.count.should == 2
48
+ end
49
+
50
+ it "should return the application delegate" do
51
+ @screen.app_delegate.should == UIApplication.sharedApplication.delegate
52
+ end
53
+
54
+
55
+
56
+ describe "opening a screen" do
57
+
58
+ it "should create an instance from class when opening a new screen" do
59
+ @screen.send(:setup_screen_for_open, BasicScreen).should.be.instance_of BasicScreen
60
+ end
61
+
62
+ it "should apply properties when opening a new screen" do
63
+ new_screen = @screen.send(:setup_screen_for_open, BasicScreen, title: 'Some Title', modal: true, hide_tab_bar: true, nav_bar: true)
64
+
65
+ new_screen.parent_screen.should == @screen
66
+ new_screen.title.should == 'Some Title'
67
+ new_screen.is_modal?.should == true
68
+ new_screen.hidesBottomBarWhenPushed.should == true
69
+ new_screen.has_nav_bar?.should == true
70
+ end
71
+
72
+ it "should present the #main_controller when showing a modal screen" do
73
+ new_screen = @screen.send(:setup_screen_for_open, BasicScreen, modal: true)
74
+
75
+ @screen.mock!('presentModalViewController:animated:') do |vc, animated|
76
+ vc.should == new_screen.main_controller
77
+ animated.should == true
78
+ end
79
+ @screen.send(:present_modal_view_controller, new_screen, true)
80
+ end
81
+
82
+ it "should push screen onto nav controller stack inside a tab bar" do
83
+ # TODO: Implement this test
84
+ end
85
+
86
+ it "should set the tab bar selectedIndex when opening a screen inside a tab bar" do
87
+ # TODO: Implement this test
88
+ end
89
+
90
+ it "should open a root screen if :close_all is provided" do
91
+ @screen.mock!(:open_root_screen) { |screen| screen.should.be.instance_of BasicScreen }
92
+ @screen.open_screen BasicScreen, close_all: true
93
+ end
94
+
95
+ it "should present a modal screen if :modal is provided" do
96
+ @screen.mock!(:present_modal_view_controller) do |screen, animated|
97
+ screen.should.be.instance_of BasicScreen
98
+ animated.should == true
99
+ end
100
+ @screen.open_screen BasicScreen, modal: true
101
+ end
102
+
103
+ it "should open screen in tab bar if :in_tab is provided" do
104
+ @screen.stub!(:tab_bar, return: true)
105
+ @screen.mock!(:present_view_controller_in_tab_bar_controller) do |screen, tab_name|
106
+ screen.should.be.instance_of BasicScreen
107
+ tab_name.should == 'my_tab'
108
+ end
109
+ @screen.open_screen BasicScreen, in_tab: 'my_tab'
110
+ end
111
+
112
+ it "should pop onto navigation controller if current screen is on nav stack already" do
113
+ @screen.mock!(:push_view_controller) { |vc| vc.should.be.instance_of BasicScreen }
114
+ @screen.open_screen BasicScreen
115
+ end
116
+
117
+ it "should open the main controller if no options are provided" do
118
+ parent_screen = HomeScreen.new
119
+ nav_controller = ProMotion::NavigationController.new
120
+ new_screen = BasicScreen.new
121
+ new_screen.stub! :main_controller, return: nav_controller
122
+
123
+ parent_screen.mock!(:open_view_controller) { |vc| vc.should.be == nav_controller }
124
+ parent_screen.open_screen new_screen
125
+ end
126
+
127
+ it "should open the provided view controller if no other conditions are met" do
128
+ parent_screen = HomeScreen.new
129
+ new_screen = BasicScreen.new
130
+ parent_screen.mock!(:open_view_controller) { |vc| vc.should.be == new_screen }
131
+ parent_screen.open_screen new_screen
132
+ end
133
+
134
+ end
135
+
136
+
137
+ describe "closing a screen" do
138
+
139
+ before do
140
+ @second_screen = BasicScreen.new
141
+ end
142
+
143
+ it "should close a modal screen" do
144
+ parent_screen = HomeScreen.new
145
+ @screen.parent_screen = parent_screen
146
+ @screen.modal = true
147
+
148
+ @screen.mock!(:close_modal_screen) { |args| args.should.be.instance_of Hash }
149
+ @screen.close
150
+ end
151
+
152
+ it "#close_modal_screen should call #send_on_return" do
153
+ parent_screen = HomeScreen.new
154
+ @screen.parent_screen = parent_screen
155
+ @screen.modal = true
156
+
157
+ @screen.mock!(:send_on_return) { |args| args.should.be.instance_of Hash }
158
+ parent_screen.mock!('dismissViewControllerAnimated:completion:') do |animated, completion|
159
+ animated.should == true
160
+ completion.should.be.instance_of Proc
161
+ completion.call
162
+ end
163
+ @screen.close
164
+ end
165
+
166
+ it "#close should pop from the navigation controller" do
167
+ @screen.navigation_controller.mock!(:popViewControllerAnimated) { |animated| animated.should == true }
168
+ @screen.close
169
+ end
170
+
171
+ it "#send_on_return shouldn't pass args to parent screen if there are none" do
172
+ parent_screen = HomeScreen.new
173
+ @screen.parent_screen = parent_screen
174
+
175
+ parent_screen.mock!(:on_return) { |args| args.count.should == 0 }
176
+ @screen.send_on_return
177
+ end
178
+
179
+ it "#send_on_return should pass args to parent screen" do
180
+ parent_screen = HomeScreen.new
181
+ @screen.parent_screen = parent_screen
182
+
183
+ parent_screen.mock!(:on_return) { |args| args[:key].should == :value }
184
+ @screen.send_on_return key: :value
185
+ end
186
+
187
+ end
188
+
189
+ end
190
+
191
+ end
@@ -0,0 +1,111 @@
1
+ describe "screen properties" do
2
+
3
+ before do
4
+
5
+ # Simulate AppDelegate setup of main screen
6
+ @screen = HomeScreen.new modal: true, nav_bar: true
7
+ @screen.on_load
8
+
9
+ end
10
+
11
+ it "should store title" do
12
+ HomeScreen.get_title.should == 'Home'
13
+ end
14
+
15
+ it "should let the instance reset the title" do
16
+ @screen.title = "instance method"
17
+ HomeScreen.get_title.should == 'instance method'
18
+ end
19
+
20
+ it "should store debug mode" do
21
+ HomeScreen.debug_mode = true
22
+ HomeScreen.debug_mode.should == true
23
+ end
24
+
25
+ it "#is_modal? should be true" do
26
+ @screen.is_modal?.should == true
27
+ end
28
+
29
+ it "should know it is the first screen" do
30
+ @screen.first_screen?.should == true
31
+ end
32
+
33
+ it "#should_autorotate should default to 'true'" do
34
+ @screen.should_autorotate.should == true
35
+ end
36
+
37
+
38
+ describe "iOS lifecycle methods" do
39
+
40
+ it "-viewDidLoad" do
41
+ @screen.mock!(:view_did_load) { true }
42
+ @screen.viewDidLoad.should == true
43
+ end
44
+
45
+ it "-viewWillAppear" do
46
+ @screen.mock!(:view_will_appear) { |animated| animated.should == true }
47
+ @screen.viewWillAppear(true)
48
+ end
49
+
50
+ it "-viewDidAppear" do
51
+ @screen.mock!(:view_did_appear) { |animated| animated.should == true }
52
+ @screen.viewDidAppear(true)
53
+ end
54
+
55
+ it "-viewWillDisappear" do
56
+ @screen.mock!(:view_will_disappear) { |animated| animated.should == true }
57
+ @screen.viewWillDisappear(true)
58
+ end
59
+
60
+ it "-viewDidDisappear" do
61
+ @screen.mock!(:view_did_disappear) { |animated| animated.should == true }
62
+ @screen.viewDidDisappear(true)
63
+ end
64
+
65
+ it "-shouldAutorotateToInterfaceOrientation" do
66
+ @screen.mock!(:should_rotate) { |o| o.should == UIInterfaceOrientationPortrait }
67
+ @screen.shouldAutorotateToInterfaceOrientation(UIInterfaceOrientationPortrait)
68
+ end
69
+
70
+ it "-shouldAutorotate" do
71
+ @screen.mock!(:should_autorotate) { true }
72
+ @screen.shouldAutorotate.should == true
73
+ end
74
+
75
+ it "-willRotateToInterfaceOrientation" do
76
+ @screen.mock! :will_rotate do |orientation, duration|
77
+ orientation.should == UIInterfaceOrientationPortrait
78
+ duration.should == 0.5
79
+ end
80
+ @screen.willRotateToInterfaceOrientation(UIInterfaceOrientationPortrait, duration: 0.5)
81
+ end
82
+
83
+ it "-didRotateFromInterfaceOrientation" do
84
+ @screen.mock!(:on_rotate) { true }
85
+ @screen.didRotateFromInterfaceOrientation(UIInterfaceOrientationPortrait).should == true
86
+ end
87
+
88
+ end
89
+
90
+
91
+ describe "navigation controller behavior" do
92
+
93
+ it "should have a nav bar" do
94
+ @screen.has_nav_bar?.should == true
95
+ end
96
+
97
+ it "#main_controller should return a navigation controller" do
98
+ @screen.main_controller.should.be.instance_of ProMotion::NavigationController
99
+ end
100
+
101
+ it "have a right bar button item" do
102
+ @screen.navigationItem.rightBarButtonItem.should.not == nil
103
+ end
104
+
105
+ it "should have a left bar button item" do
106
+ @screen.navigationItem.leftBarButtonItem.should.not == nil
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -0,0 +1,43 @@
1
+ describe "view helpers" do
2
+
3
+ def equal_rect(rect)
4
+ ->(obj) { CGRectEqualToRect obj, rect }
5
+ end
6
+
7
+ before do
8
+ @dummy = UIView.alloc.initWithFrame CGRectZero
9
+ @dummy.extend ProMotion::ViewHelper
10
+ end
11
+
12
+ it "#frame_from_array should return zero rect for bad input" do
13
+ @dummy.frame_from_array([]).should equal_rect(CGRectZero)
14
+ end
15
+
16
+ it "#frame_from_array should return a valid CGRect" do
17
+ @dummy.frame_from_array([0,0,320,480]).should equal_rect(CGRectMake(0,0,320,480))
18
+ end
19
+
20
+ it "should allow you to set attributes" do
21
+ @dummy.set_attributes @dummy, backgroundColor: UIColor.redColor
22
+ @dummy.backgroundColor.should == UIColor.redColor
23
+ end
24
+
25
+ describe "content height" do
26
+
27
+ before do
28
+ @child = UIView.alloc.initWithFrame([[20,100],[300,380]])
29
+ @dummy.addSubview @child
30
+ end
31
+
32
+ it "should return content height" do
33
+ @dummy.content_height(@dummy).should == 480
34
+ end
35
+
36
+ it "should ignore hidden subviews" do
37
+ @child.hidden = true
38
+ @dummy.content_height(@dummy).should == 0
39
+ end
40
+
41
+ end
42
+
43
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ProMotion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-03-04 00:00:00.000000000 Z
14
+ date: 2013-03-28 00:00:00.000000000 Z
15
15
  dependencies: []
16
16
  description: ProMotion is a new way to easily build RubyMotion iOS apps.
17
17
  email:
@@ -23,13 +23,15 @@ extensions: []
23
23
  extra_rdoc_files: []
24
24
  files:
25
25
  - .gitignore
26
- - .repl_history
26
+ - .ruby-gemset
27
+ - .ruby-version
27
28
  - Gemfile
28
29
  - Gemfile.lock
29
30
  - LICENSE
30
31
  - ProMotion.gemspec
31
32
  - README.md
32
33
  - Rakefile
34
+ - app/app_delegate.rb
33
35
  - lib/ProMotion.rb
34
36
  - lib/ProMotion/.DS_Store
35
37
  - lib/ProMotion/app_delegate.rb
@@ -55,6 +57,15 @@ files:
55
57
  - lib/ProMotion/screens/screen.rb
56
58
  - lib/ProMotion/screens/table_screen.rb
57
59
  - lib/ProMotion/version.rb
60
+ - spec/helpers/.gitkeep
61
+ - spec/helpers/basic_screen.rb
62
+ - spec/helpers/dummy_class.rb
63
+ - spec/helpers/home_screen.rb
64
+ - spec/ios_version_spec.rb
65
+ - spec/main_spec.rb
66
+ - spec/screen_helpers_spec.rb
67
+ - spec/view_controller_spec.rb
68
+ - spec/view_helper_spec.rb
58
69
  homepage: https://github.com/clearsightstudio/ProMotion
59
70
  licenses: []
60
71
  post_install_message:
@@ -82,4 +93,13 @@ summary: ProMotion is a new way to organize RubyMotion apps. Instead of dealing
82
93
  UIViewControllers, you work with Screens. Screens are a logical way to think of
83
94
  your app and include a ton of great utilities to make iOS development more like
84
95
  Ruby and less like Objective-C.
85
- test_files: []
96
+ test_files:
97
+ - spec/helpers/.gitkeep
98
+ - spec/helpers/basic_screen.rb
99
+ - spec/helpers/dummy_class.rb
100
+ - spec/helpers/home_screen.rb
101
+ - spec/ios_version_spec.rb
102
+ - spec/main_spec.rb
103
+ - spec/screen_helpers_spec.rb
104
+ - spec/view_controller_spec.rb
105
+ - spec/view_helper_spec.rb