ProMotion 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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