Permalink
Browse files

Trying to get an example of full screen animations. Driving me NUTS. …

…Favourite star is now broken on iPad.
  • Loading branch information...
0 parents commit 269070118a5f1b08c12e6198cee4ea51940d53cd Jeremy Gale committed Mar 20, 2012
Showing with 4,836 additions and 0 deletions.
  1. +15 −0 .gitignore
  2. +393 −0 Animations.xcodeproj/project.pbxproj
  3. +7 −0 Animations.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  4. +45 −0 Animations/Animations-Info.plist
  5. +14 −0 Animations/Animations-Prefix.pch
  6. +36 −0 Animations/AppDelegate.h
  7. +107 −0 Animations/AppDelegate.m
  8. +13 −0 Animations/BasicViewController.h
  9. +43 −0 Animations/BasicViewController.m
  10. +52 −0 Animations/FavouriteAnimationViewController.h
  11. +183 −0 Animations/FavouriteAnimationViewController.m
  12. +35 −0 Animations/FirstViewController.h
  13. +124 −0 Animations/FirstViewController.m
  14. BIN Animations/Images/Default-Landscape.png
  15. BIN Animations/Images/Default-Portrait.png
  16. BIN Animations/Images/Default.png
  17. BIN Animations/Images/Favourite.png
  18. BIN Animations/Images/FavouriteGlow.png
  19. BIN Animations/Images/NavBarFavouriteActive.png
  20. BIN Animations/Images/NavBarFavouriteNonActive.png
  21. +34 −0 Animations/MGSplitViewController/DetailViewController.h
  22. +186 −0 Animations/MGSplitViewController/DetailViewController.m
  23. +31 −0 Animations/MGSplitViewController/MGSplitCornersView.h
  24. +244 −0 Animations/MGSplitViewController/MGSplitCornersView.m
  25. +22 −0 Animations/MGSplitViewController/MGSplitDividerView.h
  26. +216 −0 Animations/MGSplitViewController/MGSplitDividerView.m
  27. +28 −0 Animations/MGSplitViewController/MGSplitViewAppDelegate.h
  28. +48 −0 Animations/MGSplitViewController/MGSplitViewAppDelegate.m
  29. +116 −0 Animations/MGSplitViewController/MGSplitViewController.h
  30. +1,135 −0 Animations/MGSplitViewController/MGSplitViewController.m
  31. +21 −0 Animations/MGSplitViewController/RootViewController.h
  32. +105 −0 Animations/MGSplitViewController/RootViewController.m
  33. +33 −0 Animations/SplashViewController.h
  34. +149 −0 Animations/SplashViewController.m
  35. +2 −0 Animations/en.lproj/InfoPlist.strings
  36. +99 −0 Animations/en.lproj/MainWindow.xib
  37. +650 −0 Animations/en.lproj/MainWindowiPad.xib
  38. +18 −0 Animations/main.m
  39. +348 −0 FavouriteAnimationViewController.xib
  40. +284 −0 FavouriteAnimationViewController~iphone.xib
15 .gitignore
@@ -0,0 +1,15 @@
+.DS_Store
+*.swp
+*~.nib
+
+build/
+xcuserdata
+
+
+*.pbxuser
+*.perspective
+*.perspectivev3
+*.mode1v3
+*.mode2v3
+.LSOverride
+
393 Animations.xcodeproj/project.pbxproj
@@ -0,0 +1,393 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 0C7A2E441518F59600BCD43A /* BasicViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7A2E431518F59600BCD43A /* BasicViewController.m */; };
+ 0C7A2E521518F62D00BCD43A /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7A2E471518F62D00BCD43A /* DetailViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+ 0C7A2E531518F62D00BCD43A /* MGSplitCornersView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7A2E491518F62D00BCD43A /* MGSplitCornersView.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+ 0C7A2E541518F62D00BCD43A /* MGSplitDividerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7A2E4B1518F62D00BCD43A /* MGSplitDividerView.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+ 0C7A2E551518F62D00BCD43A /* MGSplitViewAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7A2E4D1518F62D00BCD43A /* MGSplitViewAppDelegate.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+ 0C7A2E561518F62D00BCD43A /* MGSplitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7A2E4F1518F62D00BCD43A /* MGSplitViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+ 0C7A2E571518F62D00BCD43A /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7A2E511518F62D00BCD43A /* RootViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+ 0C9E5039151802DF00A599AA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9E5038151802DF00A599AA /* UIKit.framework */; };
+ 0C9E503B151802DF00A599AA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9E503A151802DF00A599AA /* Foundation.framework */; };
+ 0C9E503D151802DF00A599AA /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9E503C151802DF00A599AA /* CoreGraphics.framework */; };
+ 0C9E5043151802DF00A599AA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E5041151802DF00A599AA /* InfoPlist.strings */; };
+ 0C9E5045151802DF00A599AA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9E5044151802DF00A599AA /* main.m */; };
+ 0C9E5049151802DF00A599AA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9E5048151802DF00A599AA /* AppDelegate.m */; };
+ 0C9E50691518035100A599AA /* FavouriteAnimationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9E50661518035100A599AA /* FavouriteAnimationViewController.m */; };
+ 0C9E506A1518035100A599AA /* SplashViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9E50681518035100A599AA /* SplashViewController.m */; };
+ 0C9E506E1518037C00A599AA /* FavouriteAnimationViewController~iphone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E506D1518037C00A599AA /* FavouriteAnimationViewController~iphone.xib */; };
+ 0C9E50701518038900A599AA /* FavouriteAnimationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E506F1518038900A599AA /* FavouriteAnimationViewController.xib */; };
+ 0C9E50751518048600A599AA /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C9E50741518048600A599AA /* QuartzCore.framework */; };
+ 0C9E507D1518D7E300A599AA /* Default-Landscape.png in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E50771518D7E300A599AA /* Default-Landscape.png */; };
+ 0C9E507F1518D7E300A599AA /* Default-Portrait.png in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E50791518D7E300A599AA /* Default-Portrait.png */; };
+ 0C9E50811518D7E300A599AA /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E507B1518D7E300A599AA /* Default.png */; };
+ 0C9E508A1518DA6300A599AA /* Favourite.png in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E50861518DA6300A599AA /* Favourite.png */; };
+ 0C9E508C1518DA6300A599AA /* FavouriteGlow.png in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E50881518DA6300A599AA /* FavouriteGlow.png */; };
+ 0C9E50931518DBF800A599AA /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C9E50921518DBF800A599AA /* FirstViewController.m */; };
+ 0C9E50981518DC3B00A599AA /* NavBarFavouriteActive.png in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E50941518DC3B00A599AA /* NavBarFavouriteActive.png */; };
+ 0C9E509A1518DC3B00A599AA /* NavBarFavouriteNonActive.png in Resources */ = {isa = PBXBuildFile; fileRef = 0C9E50961518DC3B00A599AA /* NavBarFavouriteNonActive.png */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 0C7A2E421518F59600BCD43A /* BasicViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BasicViewController.h; sourceTree = "<group>"; };
+ 0C7A2E431518F59600BCD43A /* BasicViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BasicViewController.m; sourceTree = "<group>"; };
+ 0C7A2E461518F62D00BCD43A /* DetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = "<group>"; };
+ 0C7A2E471518F62D00BCD43A /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = "<group>"; };
+ 0C7A2E481518F62D00BCD43A /* MGSplitCornersView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGSplitCornersView.h; sourceTree = "<group>"; };
+ 0C7A2E491518F62D00BCD43A /* MGSplitCornersView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGSplitCornersView.m; sourceTree = "<group>"; };
+ 0C7A2E4A1518F62D00BCD43A /* MGSplitDividerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGSplitDividerView.h; sourceTree = "<group>"; };
+ 0C7A2E4B1518F62D00BCD43A /* MGSplitDividerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGSplitDividerView.m; sourceTree = "<group>"; };
+ 0C7A2E4C1518F62D00BCD43A /* MGSplitViewAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGSplitViewAppDelegate.h; sourceTree = "<group>"; };
+ 0C7A2E4D1518F62D00BCD43A /* MGSplitViewAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGSplitViewAppDelegate.m; sourceTree = "<group>"; };
+ 0C7A2E4E1518F62D00BCD43A /* MGSplitViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGSplitViewController.h; sourceTree = "<group>"; };
+ 0C7A2E4F1518F62D00BCD43A /* MGSplitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGSplitViewController.m; sourceTree = "<group>"; };
+ 0C7A2E501518F62D00BCD43A /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = "<group>"; };
+ 0C7A2E511518F62D00BCD43A /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = "<group>"; };
+ 0C9E5034151802DF00A599AA /* Animations.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Animations.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 0C9E5038151802DF00A599AA /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 0C9E503A151802DF00A599AA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 0C9E503C151802DF00A599AA /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 0C9E5040151802DF00A599AA /* Animations-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Animations-Info.plist"; sourceTree = "<group>"; };
+ 0C9E5042151802DF00A599AA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 0C9E5044151802DF00A599AA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 0C9E5046151802DF00A599AA /* Animations-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Animations-Prefix.pch"; sourceTree = "<group>"; };
+ 0C9E5047151802DF00A599AA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+ 0C9E5048151802DF00A599AA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+ 0C9E50651518035100A599AA /* FavouriteAnimationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FavouriteAnimationViewController.h; sourceTree = "<group>"; };
+ 0C9E50661518035100A599AA /* FavouriteAnimationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FavouriteAnimationViewController.m; sourceTree = "<group>"; };
+ 0C9E50671518035100A599AA /* SplashViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SplashViewController.h; sourceTree = "<group>"; };
+ 0C9E50681518035100A599AA /* SplashViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SplashViewController.m; sourceTree = "<group>"; };
+ 0C9E506D1518037C00A599AA /* FavouriteAnimationViewController~iphone.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "FavouriteAnimationViewController~iphone.xib"; sourceTree = "<group>"; };
+ 0C9E506F1518038900A599AA /* FavouriteAnimationViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FavouriteAnimationViewController.xib; sourceTree = "<group>"; };
+ 0C9E50741518048600A599AA /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ 0C9E50771518D7E300A599AA /* Default-Landscape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape.png"; sourceTree = "<group>"; };
+ 0C9E50791518D7E300A599AA /* Default-Portrait.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait.png"; sourceTree = "<group>"; };
+ 0C9E507B1518D7E300A599AA /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
+ 0C9E50861518DA6300A599AA /* Favourite.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Favourite.png; sourceTree = "<group>"; };
+ 0C9E50881518DA6300A599AA /* FavouriteGlow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = FavouriteGlow.png; sourceTree = "<group>"; };
+ 0C9E50911518DBF800A599AA /* FirstViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FirstViewController.h; sourceTree = "<group>"; };
+ 0C9E50921518DBF800A599AA /* FirstViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FirstViewController.m; sourceTree = "<group>"; };
+ 0C9E50941518DC3B00A599AA /* NavBarFavouriteActive.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = NavBarFavouriteActive.png; sourceTree = "<group>"; };
+ 0C9E50961518DC3B00A599AA /* NavBarFavouriteNonActive.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = NavBarFavouriteNonActive.png; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 0C9E5031151802DF00A599AA /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 0C9E50751518048600A599AA /* QuartzCore.framework in Frameworks */,
+ 0C9E5039151802DF00A599AA /* UIKit.framework in Frameworks */,
+ 0C9E503B151802DF00A599AA /* Foundation.framework in Frameworks */,
+ 0C9E503D151802DF00A599AA /* CoreGraphics.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 0C7A2E451518F62D00BCD43A /* MGSplitViewController */ = {
+ isa = PBXGroup;
+ children = (
+ 0C7A2E461518F62D00BCD43A /* DetailViewController.h */,
+ 0C7A2E471518F62D00BCD43A /* DetailViewController.m */,
+ 0C7A2E481518F62D00BCD43A /* MGSplitCornersView.h */,
+ 0C7A2E491518F62D00BCD43A /* MGSplitCornersView.m */,
+ 0C7A2E4A1518F62D00BCD43A /* MGSplitDividerView.h */,
+ 0C7A2E4B1518F62D00BCD43A /* MGSplitDividerView.m */,
+ 0C7A2E4C1518F62D00BCD43A /* MGSplitViewAppDelegate.h */,
+ 0C7A2E4D1518F62D00BCD43A /* MGSplitViewAppDelegate.m */,
+ 0C7A2E4E1518F62D00BCD43A /* MGSplitViewController.h */,
+ 0C7A2E4F1518F62D00BCD43A /* MGSplitViewController.m */,
+ 0C7A2E501518F62D00BCD43A /* RootViewController.h */,
+ 0C7A2E511518F62D00BCD43A /* RootViewController.m */,
+ );
+ name = MGSplitViewController;
+ path = Animations/MGSplitViewController;
+ sourceTree = "<group>";
+ };
+ 0C9E5029151802DF00A599AA = {
+ isa = PBXGroup;
+ children = (
+ 0C7A2E451518F62D00BCD43A /* MGSplitViewController */,
+ 0C9E503E151802DF00A599AA /* Animations */,
+ 0C9E506C1518036400A599AA /* Xibs */,
+ 0C9E50761518D7E300A599AA /* Images */,
+ 0C9E5037151802DF00A599AA /* Frameworks */,
+ 0C9E5035151802DF00A599AA /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 0C9E5035151802DF00A599AA /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 0C9E5034151802DF00A599AA /* Animations.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0C9E5037151802DF00A599AA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 0C9E50741518048600A599AA /* QuartzCore.framework */,
+ 0C9E5038151802DF00A599AA /* UIKit.framework */,
+ 0C9E503A151802DF00A599AA /* Foundation.framework */,
+ 0C9E503C151802DF00A599AA /* CoreGraphics.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 0C9E503E151802DF00A599AA /* Animations */ = {
+ isa = PBXGroup;
+ children = (
+ 0C9E5047151802DF00A599AA /* AppDelegate.h */,
+ 0C9E5048151802DF00A599AA /* AppDelegate.m */,
+ 0C9E50651518035100A599AA /* FavouriteAnimationViewController.h */,
+ 0C9E50661518035100A599AA /* FavouriteAnimationViewController.m */,
+ 0C9E50671518035100A599AA /* SplashViewController.h */,
+ 0C9E50681518035100A599AA /* SplashViewController.m */,
+ 0C9E50911518DBF800A599AA /* FirstViewController.h */,
+ 0C9E50921518DBF800A599AA /* FirstViewController.m */,
+ 0C7A2E421518F59600BCD43A /* BasicViewController.h */,
+ 0C7A2E431518F59600BCD43A /* BasicViewController.m */,
+ 0C9E503F151802DF00A599AA /* Supporting Files */,
+ );
+ path = Animations;
+ sourceTree = "<group>";
+ };
+ 0C9E503F151802DF00A599AA /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 0C9E5040151802DF00A599AA /* Animations-Info.plist */,
+ 0C9E5041151802DF00A599AA /* InfoPlist.strings */,
+ 0C9E5044151802DF00A599AA /* main.m */,
+ 0C9E5046151802DF00A599AA /* Animations-Prefix.pch */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ 0C9E506C1518036400A599AA /* Xibs */ = {
+ isa = PBXGroup;
+ children = (
+ 0C9E506F1518038900A599AA /* FavouriteAnimationViewController.xib */,
+ 0C9E506D1518037C00A599AA /* FavouriteAnimationViewController~iphone.xib */,
+ );
+ name = Xibs;
+ sourceTree = "<group>";
+ };
+ 0C9E50761518D7E300A599AA /* Images */ = {
+ isa = PBXGroup;
+ children = (
+ 0C9E50941518DC3B00A599AA /* NavBarFavouriteActive.png */,
+ 0C9E50961518DC3B00A599AA /* NavBarFavouriteNonActive.png */,
+ 0C9E50861518DA6300A599AA /* Favourite.png */,
+ 0C9E50881518DA6300A599AA /* FavouriteGlow.png */,
+ 0C9E50771518D7E300A599AA /* Default-Landscape.png */,
+ 0C9E50791518D7E300A599AA /* Default-Portrait.png */,
+ 0C9E507B1518D7E300A599AA /* Default.png */,
+ );
+ name = Images;
+ path = Animations/Images;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 0C9E5033151802DF00A599AA /* Animations */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 0C9E505E151802DF00A599AA /* Build configuration list for PBXNativeTarget "Animations" */;
+ buildPhases = (
+ 0C9E5030151802DF00A599AA /* Sources */,
+ 0C9E5031151802DF00A599AA /* Frameworks */,
+ 0C9E5032151802DF00A599AA /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Animations;
+ productName = Animations;
+ productReference = 0C9E5034151802DF00A599AA /* Animations.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0C9E502B151802DF00A599AA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0430;
+ ORGANIZATIONNAME = "Force Grind Inc.";
+ };
+ buildConfigurationList = 0C9E502E151802DF00A599AA /* Build configuration list for PBXProject "Animations" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 0C9E5029151802DF00A599AA;
+ productRefGroup = 0C9E5035151802DF00A599AA /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 0C9E5033151802DF00A599AA /* Animations */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 0C9E5032151802DF00A599AA /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 0C9E5043151802DF00A599AA /* InfoPlist.strings in Resources */,
+ 0C9E506E1518037C00A599AA /* FavouriteAnimationViewController~iphone.xib in Resources */,
+ 0C9E50701518038900A599AA /* FavouriteAnimationViewController.xib in Resources */,
+ 0C9E507D1518D7E300A599AA /* Default-Landscape.png in Resources */,
+ 0C9E507F1518D7E300A599AA /* Default-Portrait.png in Resources */,
+ 0C9E50811518D7E300A599AA /* Default.png in Resources */,
+ 0C9E508A1518DA6300A599AA /* Favourite.png in Resources */,
+ 0C9E508C1518DA6300A599AA /* FavouriteGlow.png in Resources */,
+ 0C9E50981518DC3B00A599AA /* NavBarFavouriteActive.png in Resources */,
+ 0C9E509A1518DC3B00A599AA /* NavBarFavouriteNonActive.png in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 0C9E5030151802DF00A599AA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 0C9E5045151802DF00A599AA /* main.m in Sources */,
+ 0C9E5049151802DF00A599AA /* AppDelegate.m in Sources */,
+ 0C9E50691518035100A599AA /* FavouriteAnimationViewController.m in Sources */,
+ 0C9E506A1518035100A599AA /* SplashViewController.m in Sources */,
+ 0C9E50931518DBF800A599AA /* FirstViewController.m in Sources */,
+ 0C7A2E441518F59600BCD43A /* BasicViewController.m in Sources */,
+ 0C7A2E521518F62D00BCD43A /* DetailViewController.m in Sources */,
+ 0C7A2E531518F62D00BCD43A /* MGSplitCornersView.m in Sources */,
+ 0C7A2E541518F62D00BCD43A /* MGSplitDividerView.m in Sources */,
+ 0C7A2E551518F62D00BCD43A /* MGSplitViewAppDelegate.m in Sources */,
+ 0C7A2E561518F62D00BCD43A /* MGSplitViewController.m in Sources */,
+ 0C7A2E571518F62D00BCD43A /* RootViewController.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 0C9E5041151802DF00A599AA /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 0C9E5042151802DF00A599AA /* en */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 0C9E505C151802DF00A599AA /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.1;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 0C9E505D151802DF00A599AA /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.1;
+ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 0C9E505F151802DF00A599AA /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "Animations/Animations-Prefix.pch";
+ INFOPLIST_FILE = "Animations/Animations-Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 0C9E5060151802DF00A599AA /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "Animations/Animations-Prefix.pch";
+ INFOPLIST_FILE = "Animations/Animations-Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 0C9E502E151802DF00A599AA /* Build configuration list for PBXProject "Animations" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 0C9E505C151802DF00A599AA /* Debug */,
+ 0C9E505D151802DF00A599AA /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 0C9E505E151802DF00A599AA /* Build configuration list for PBXNativeTarget "Animations" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 0C9E505F151802DF00A599AA /* Debug */,
+ 0C9E5060151802DF00A599AA /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0C9E502B151802DF00A599AA /* Project object */;
+}
7 Animations.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:Animations.xcodeproj">
+ </FileRef>
+</Workspace>
45 Animations/Animations-Info.plist
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.forcegrind.fullscreenanimation.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
14 Animations/Animations-Prefix.pch
@@ -0,0 +1,14 @@
+//
+// Prefix header for all source files of the 'Animations' target in the 'Animations' project
+//
+
+#import <Availability.h>
+
+#ifndef __IPHONE_4_0
+#warning "This project uses features only available in iOS SDK 4.0 and later."
+#endif
+
+#ifdef __OBJC__
+ #import <UIKit/UIKit.h>
+ #import <Foundation/Foundation.h>
+#endif
36 Animations/AppDelegate.h
@@ -0,0 +1,36 @@
+//
+// AppDelegate.h
+// Animations
+//
+// Created by Jeremy Gale on 2012-03-19.
+// Copyright (c) 2012 Force Grind Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE
+
+#import <UIKit/UIKit.h>
+
+@class MGSplitViewController;
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) IBOutlet UIWindow *window;
+@property (strong, nonatomic) IBOutlet MGSplitViewController *splitViewController;
+@property (strong, nonatomic) IBOutlet UITabBarController *tabBarController;
+
+@end
107 Animations/AppDelegate.m
@@ -0,0 +1,107 @@
+//
+// AppDelegate.m
+// Animations
+//
+// Created by Jeremy Gale on 2012-03-19.
+// Copyright (c) 2012 Force Grind Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE
+
+#import "AppDelegate.h"
+#import "FirstViewController.h"
+#import "BasicViewController.h"
+#import "MGSplitViewController.h"
+
+@implementation AppDelegate
+
+@synthesize window = _window;
+@synthesize splitViewController = _splitViewController;
+@synthesize tabBarController = _tabBarController;
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+
+ FirstViewController *firstVC = [[FirstViewController alloc] initWithNibName:nil bundle:nil];
+ firstVC.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemDownloads tag:0];
+ UINavigationController *firstNav = [[UINavigationController alloc] initWithRootViewController:firstVC];
+
+ BasicViewController *secondVC = [[BasicViewController alloc] init];
+ secondVC.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemContacts tag:1];
+ BasicViewController *thirdVC = [[BasicViewController alloc] init];
+ thirdVC.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemBookmarks tag:2];
+ BasicViewController *fourthVC = [[BasicViewController alloc] init];
+ fourthVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Favourites"
+ image:[UIImage imageNamed:@"Favourite.png"]
+ tag:3];
+ self.tabBarController = [[UITabBarController alloc] init];
+
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
+ {
+ self.tabBarController.viewControllers = [NSArray arrayWithObjects:firstNav, secondVC, thirdVC, fourthVC, nil];
+ self.window.rootViewController = self.tabBarController;
+ }
+ else
+ {
+ BasicViewController *replacementFirstVC = [[BasicViewController alloc] init];
+ replacementFirstVC.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemDownloads tag:0];
+ UINavigationController *replacementNavFirstVC = [[UINavigationController alloc] initWithRootViewController:replacementFirstVC];
+
+ self.tabBarController.viewControllers = [NSArray arrayWithObjects:replacementNavFirstVC, secondVC, thirdVC, fourthVC, nil];
+
+ self.splitViewController = [[MGSplitViewController alloc] init];
+ self.splitViewController.delegate = firstVC;
+ self.splitViewController.viewControllers = [NSArray arrayWithObjects:self.tabBarController, firstNav, nil];
+
+ self.window.rootViewController = self.splitViewController;
+ }
+
+ [self.window makeKeyAndVisible];
+
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application
+{
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application
+{
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application
+{
+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application
+{
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application
+{
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end
13 Animations/BasicViewController.h
@@ -0,0 +1,13 @@
+//
+// BasicViewController.h
+// Animations
+//
+// Created by Jeremy Gale on 2012-03-20.
+// Copyright (c) 2012 Force Grind Inc. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface BasicViewController : UIViewController
+
+@end
43 Animations/BasicViewController.m
@@ -0,0 +1,43 @@
+//
+// BasicViewController.m
+// Animations
+//
+// Created by Jeremy Gale on 2012-03-20.
+// Copyright (c) 2012 Force Grind Inc. All rights reserved.
+//
+
+#import "BasicViewController.h"
+
+@interface BasicViewController ()
+
+@end
+
+@implementation BasicViewController
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ if (self) {
+ // Custom initialization
+ }
+ return self;
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+}
+
+- (void)viewDidUnload
+{
+ [super viewDidUnload];
+ // Release any retained subviews of the main view.
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+@end
52 Animations/FavouriteAnimationViewController.h
@@ -0,0 +1,52 @@
+//
+// FavouriteAnimationViewController.h
+// O2PriorityMoments
+//
+// Created by Jeremy Gale on 2011-11-25
+// Copyright 2011 Force Grind Inc. All rights reserved.
+//
+// Shamelessly inspried by Ryan Harrison's code
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE
+
+
+#import <UIKit/UIKit.h>
+
+
+@interface FavouriteAnimationViewController : UIViewController
+{
+ UIImageView *starImageView;
+ UIView *otherTabsFadeBlackView;
+ UIView *favTabBlueStarGlowView;
+ UIView *bottomView;
+}
+
+@property (nonatomic, retain) IBOutlet UIImageView *starImageView;
+@property (nonatomic, retain) IBOutlet UIView *otherTabsFadeBlackView;
+@property (nonatomic, retain) IBOutlet UIView *favTabBlueStarGlowView;
+@property (nonatomic, retain) IBOutlet UIView *bottomView;
+
+- (id)init;
+
+- (void)startFavouriteAnimation;
+
+- (void)makeFavTabGlow;
+- (void)fadeOutTabAndGlow;
+
+@end
183 Animations/FavouriteAnimationViewController.m
@@ -0,0 +1,183 @@
+//
+// FavouriteAnimationViewController.m
+// O2PriorityMoments
+//
+// Created by Jeremy Gale on 2011-11-25
+// Copyright 2011 Force Grind Inc. All rights reserved.
+//
+// Shamelessly inspried by Ryan Harrison's code
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE
+
+
+#import "FavouriteAnimationViewController.h"
+#import <QuartzCore/QuartzCore.h>
+#import "AppDelegate.h"
+
+#define animationDuration 3.0
+#define kFadeInTabDuration 1.5
+#define kFadeOutTabDuration 1.5
+#define kFavouritesTabIndex 3
+
+@implementation FavouriteAnimationViewController
+
+@synthesize starImageView;
+@synthesize bottomView;
+@synthesize otherTabsFadeBlackView;
+@synthesize favTabBlueStarGlowView;
+
+- (id)init
+{
+ if ((self = [super initWithNibName:@"FavouriteAnimationViewController" bundle:nil]))
+ {
+ }
+ return self;
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ // Do any additional setup after loading the view from its nib.
+
+ otherTabsFadeBlackView.alpha = 0;
+ favTabBlueStarGlowView.alpha = 0;
+}
+
+- (void)viewDidAppear:(BOOL)animated
+{
+ [super viewDidAppear:animated];
+
+ // Need to wait until viewDidAppear to make sure the view has been resized properly
+ [self startFavouriteAnimation];
+}
+
+- (void)startFavouriteAnimation
+{
+ //Animate the image shrinking. Include this in the CAAnimationGroup below to get both things to work
+// CABasicAnimation *shrink;
+// shrink = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+// shrink.fromValue = [NSNumber numberWithDouble:1.0];
+// shrink.toValue = [NSNumber numberWithDouble:0.3];
+
+ CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
+ pathAnimation.calculationMode = kCAAnimationPaced;
+
+ CGPoint fromPoint = starImageView.center;
+ // This assumes there is always a UITabBarController 320 pixels wide at the left side of the screen,
+ // and we are going to the third out of 4 view controllers
+
+ AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
+
+ CGPoint toPoint = CGPointMake(320.0 * kFavouritesTabIndex / appDelegate.tabBarController.viewControllers.count + 40, // +40 because each tab bar is currently 80 pixels wide
+ self.view.frame.size.height - 24); // - 24 because want it to be in the middle of the tab bar which has height of 49
+ CGMutablePathRef curvedPath = CGPathCreateMutable();
+ CGPathMoveToPoint(curvedPath, NULL, fromPoint.x, fromPoint.y);
+ CGPathAddCurveToPoint(curvedPath, NULL, toPoint.x, fromPoint.y, toPoint.x, fromPoint.y, toPoint.x, toPoint.y);
+ pathAnimation.path = curvedPath;
+ CGPathRelease(curvedPath);
+
+ CAAnimationGroup *group = [CAAnimationGroup animation];
+ // kCAFillModeForwards The receiver remains visible in
+ // its final state when the animation is completed.
+ group.fillMode = kCAFillModeForwards;
+ group.removedOnCompletion = NO;
+ [group setAnimations:[NSArray arrayWithObjects:/*shrink,*/ pathAnimation, nil]];
+ group.duration = animationDuration;
+ group.delegate = self;
+
+ [starImageView.layer addAnimation:group forKey:@"savingAnimation"];
+
+ //Animate the tab bar getting dark
+ CABasicAnimation *fadeIn = [CABasicAnimation animationWithKeyPath:@"opacity"];
+ fadeIn.toValue = [NSNumber numberWithDouble:1.0];
+ fadeIn.fillMode = kCAFillModeForwards;
+ fadeIn.removedOnCompletion = NO;
+ fadeIn.duration = animationDuration;
+
+ [otherTabsFadeBlackView.layer addAnimation:fadeIn forKey:@"tabBarFadeBlack"];
+}
+
+// Make the blue star image go from an alpha of 0 to 1.0 making it glow
+- (void)makeFavTabGlow
+{
+ //Hide the yellow star now
+ starImageView.hidden = YES;
+
+ //Animate the tab bar getting dark
+ CABasicAnimation *fadeIn = [CABasicAnimation animationWithKeyPath:@"opacity"];
+ fadeIn.toValue = [NSNumber numberWithDouble:1.0];
+ fadeIn.fillMode = kCAFillModeForwards;
+ fadeIn.removedOnCompletion = NO;
+ fadeIn.duration = kFadeInTabDuration;
+ fadeIn.delegate = self;
+
+ [favTabBlueStarGlowView.layer addAnimation:fadeIn forKey:@"favBlueStarGlowFadeIn"];
+}
+
+// Makes the entire bottom view (overlays tab bar) go to alpha 0.0,
+// i.e. have it go back to normal.
+- (void)fadeOutTabAndGlow
+{
+ //Animate the meGlow getting dark
+ CABasicAnimation *fadeOut = [CABasicAnimation animationWithKeyPath:@"opacity"];
+ fadeOut.toValue = [NSNumber numberWithDouble:0.0];
+ fadeOut.fillMode = kCAFillModeForwards;
+ fadeOut.removedOnCompletion = NO;
+ fadeOut.duration = kFadeOutTabDuration;
+ fadeOut.delegate = self;
+
+ [bottomView.layer addAnimation:fadeOut forKey:@"allFadeOut"];
+}
+
+- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
+{
+ if(anim == [starImageView.layer animationForKey:@"savingAnimation"])
+ {
+ [self makeFavTabGlow];
+ }
+ else if(anim == [favTabBlueStarGlowView.layer animationForKey:@"favBlueStarGlowFadeIn"])
+ {
+ [self fadeOutTabAndGlow];
+ }
+ else if(anim == [bottomView.layer animationForKey:@"allFadeOut"])
+ {
+ [self.view removeFromSuperview];
+ }
+}
+
+#pragma mark - Rotation Handling
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ // Return YES for supported orientations
+ return (interfaceOrientation == UIInterfaceOrientationPortrait);
+}
+
+#pragma mark - Memory Management
+
+- (void)viewDidUnload
+{
+ [super viewDidUnload];
+ // Release any retained subviews of the main view.
+ self.starImageView = nil;
+ self.otherTabsFadeBlackView = nil;
+ self.favTabBlueStarGlowView = nil;
+ self.bottomView = nil;
+}
+
+@end
35 Animations/FirstViewController.h
@@ -0,0 +1,35 @@
+//
+// FirstViewController.h
+// Animations
+//
+// Created by Jeremy Gale on 2012-03-20.
+// Copyright (c) 2012 Force Grind Inc. All rights reserved.
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE
+
+#import <UIKit/UIKit.h>
+#import "MGSplitViewController.h"
+
+@interface FirstViewController : UIViewController <MGSplitViewControllerDelegate>
+{
+ UIButton *_favButton;
+}
+
+@end
124 Animations/FirstViewController.m
@@ -0,0 +1,124 @@
+//
+// FirstViewController.m
+// Animations
+//
+// Created by Jeremy Gale on 2012-03-20.
+// Copyright (c) 2012 Force Grind Inc. All rights reserved.
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE
+
+#import "FirstViewController.h"
+#import "AppDelegate.h"
+#import "FavouriteAnimationViewController.h"
+#import "SplashViewController.h"
+
+@interface FirstViewController ()
+@property (strong, nonatomic) UIPopoverController *masterPopoverController;
+@end
+
+@implementation FirstViewController
+
+@synthesize masterPopoverController = _masterPopoverController;
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ if (self) {
+ // Custom initialization
+ }
+ return self;
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+
+ _favButton = [UIButton buttonWithType:UIButtonTypeCustom];
+ [_favButton setImage:[UIImage imageNamed:@"NavBarFavouriteNonActive.png"] forState:UIControlStateNormal];
+ [_favButton setImage:[UIImage imageNamed:@"NavBarFavouriteActive.png"] forState:UIControlStateSelected];
+ _favButton.frame = CGRectMake(0.0, 0.0, 35.0, 35.0);
+ [_favButton addTarget:self action:@selector(favouriteTapped:) forControlEvents:UIControlEventTouchUpInside];
+
+ UIBarButtonItem *star = [[UIBarButtonItem alloc] initWithCustomView:_favButton];
+ self.navigationItem.rightBarButtonItem = star;
+
+ SplashViewController *splashScreen = [[SplashViewController alloc] init];
+ AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
+
+ // This will never let me see the view underneath :(
+ //[appDelegate.window.rootViewController presentModalViewController:splashScreen animated:NO];
+ [appDelegate.window addSubview:splashScreen.view];
+}
+
+- (void)viewDidUnload
+{
+ [super viewDidUnload];
+ // Release any retained subviews of the main view.
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+
+#pragma mark - Actions
+
+- (IBAction)favouriteTapped:(id)sender
+{
+ _favButton.selected = !_favButton.selected;
+
+ if (_favButton.selected)
+ {
+ AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
+ FavouriteAnimationViewController *favAnimationView = [[FavouriteAnimationViewController alloc] init];
+
+ if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
+ {
+ // For some reason, it seems like using window's rootViewController.view doesn't work for iPhone :(
+ [appDelegate.window addSubview:favAnimationView.view];
+ }
+ else
+ {
+ // Need to add it to the top-most view controller's view, or else it won't properly rotate to landscape
+ [appDelegate.splitViewController.view addSubview:favAnimationView.view];
+ }
+ }
+}
+
+
+#pragma mark - Split view
+
+- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
+{
+ barButtonItem.title = NSLocalizedString(@"Master", @"Master");
+ [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
+ self.masterPopoverController = popoverController;
+}
+
+- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
+{
+ // Called when the view is shown again in the split view, invalidating the button and popover controller.
+ [self.navigationItem setLeftBarButtonItem:nil animated:YES];
+ self.masterPopoverController = nil;
+}
+
+@end
BIN Animations/Images/Default-Landscape.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN Animations/Images/Default-Portrait.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN Animations/Images/Default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN Animations/Images/Favourite.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN Animations/Images/FavouriteGlow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN Animations/Images/NavBarFavouriteActive.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN Animations/Images/NavBarFavouriteNonActive.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 Animations/MGSplitViewController/DetailViewController.h
@@ -0,0 +1,34 @@
+//
+// DetailViewController.h
+// MGSplitView
+//
+// Created by Matt Gemmell on 26/07/2010.
+// Copyright Instinctive Code 2010.
+//
+
+#import <UIKit/UIKit.h>
+#import "MGSplitViewController.h"
+
+@interface DetailViewController : UIViewController <UIPopoverControllerDelegate, MGSplitViewControllerDelegate> {
+ IBOutlet MGSplitViewController *splitController;
+ IBOutlet UIBarButtonItem *toggleItem;
+ IBOutlet UIBarButtonItem *verticalItem;
+ IBOutlet UIBarButtonItem *dividerStyleItem;
+ IBOutlet UIBarButtonItem *masterBeforeDetailItem;
+ UIPopoverController *popoverController;
+ UIToolbar *toolbar;
+
+ id detailItem;
+ UILabel *detailDescriptionLabel;
+}
+
+@property (nonatomic, retain) IBOutlet UIToolbar *toolbar;
+@property (nonatomic, retain) id detailItem;
+@property (nonatomic, retain) IBOutlet UILabel *detailDescriptionLabel;
+
+- (IBAction)toggleMasterView:(id)sender;
+- (IBAction)toggleVertical:(id)sender;
+- (IBAction)toggleDividerStyle:(id)sender;
+- (IBAction)toggleMasterBeforeDetail:(id)sender;
+
+@end
186 Animations/MGSplitViewController/DetailViewController.m
@@ -0,0 +1,186 @@
+//
+// DetailViewController.m
+// MGSplitView
+//
+// Created by Matt Gemmell on 26/07/2010.
+// Copyright Instinctive Code 2010.
+//
+
+#import "DetailViewController.h"
+#import "RootViewController.h"
+
+
+@interface DetailViewController ()
+
+@property (nonatomic, retain) UIPopoverController *popoverController;
+- (void)configureView;
+
+@end
+
+
+@implementation DetailViewController
+
+
+@synthesize toolbar, popoverController, detailItem, detailDescriptionLabel;
+
+
+#pragma mark -
+#pragma mark Managing the detail item
+
+
+// When setting the detail item, update the view and dismiss the popover controller if it's showing.
+- (void)setDetailItem:(id)newDetailItem
+{
+ if (detailItem != newDetailItem) {
+ [detailItem release];
+ detailItem = [newDetailItem retain];
+
+ // Update the view.
+ [self configureView];
+ }
+
+ if (popoverController != nil) {
+ [popoverController dismissPopoverAnimated:YES];
+ }
+}
+
+
+- (void)configureView
+{
+ // Update the user interface for the detail item.
+ detailDescriptionLabel.text = [detailItem description];
+ toggleItem.title = ([splitController isShowingMaster]) ? @"Hide Master" : @"Show Master"; // "I... AM... THE MASTER!" Derek Jacobi. Gave me chills.
+ verticalItem.title = (splitController.vertical) ? @"Horizontal Split" : @"Vertical Split";
+ dividerStyleItem.title = (splitController.dividerStyle == MGSplitViewDividerStyleThin) ? @"Enable Dragging" : @"Disable Dragging";
+ masterBeforeDetailItem.title = (splitController.masterBeforeDetail) ? @"Detail First" : @"Master First";
+}
+
+
+#pragma mark -
+#pragma mark Split view support
+
+
+- (void)splitViewController:(MGSplitViewController*)svc
+ willHideViewController:(UIViewController *)aViewController
+ withBarButtonItem:(UIBarButtonItem*)barButtonItem
+ forPopoverController: (UIPopoverController*)pc
+{
+ //NSLog(@"%@", NSStringFromSelector(_cmd));
+
+ if (barButtonItem) {
+ barButtonItem.title = @"Popover";
+ NSMutableArray *items = [[toolbar items] mutableCopy];
+ [items insertObject:barButtonItem atIndex:0];
+ [toolbar setItems:items animated:YES];
+ [items release];
+ }
+ self.popoverController = pc;
+}
+
+
+// Called when the view is shown again in the split view, invalidating the button and popover controller.
+- (void)splitViewController:(MGSplitViewController*)svc
+ willShowViewController:(UIViewController *)aViewController
+ invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
+{
+ //NSLog(@"%@", NSStringFromSelector(_cmd));
+
+ if (barButtonItem) {
+ NSMutableArray *items = [[toolbar items] mutableCopy];
+ [items removeObject:barButtonItem];
+ [toolbar setItems:items animated:YES];
+ [items release];
+ }
+ self.popoverController = nil;
+}
+
+
+- (void)splitViewController:(MGSplitViewController*)svc
+ popoverController:(UIPopoverController*)pc
+ willPresentViewController:(UIViewController *)aViewController
+{
+ //NSLog(@"%@", NSStringFromSelector(_cmd));
+}
+
+
+- (void)splitViewController:(MGSplitViewController*)svc willChangeSplitOrientationToVertical:(BOOL)isVertical
+{
+ //NSLog(@"%@", NSStringFromSelector(_cmd));
+}
+
+
+- (void)splitViewController:(MGSplitViewController*)svc willMoveSplitToPosition:(float)position
+{
+ //NSLog(@"%@", NSStringFromSelector(_cmd));
+}
+
+
+- (float)splitViewController:(MGSplitViewController *)svc constrainSplitPosition:(float)proposedPosition splitViewSize:(CGSize)viewSize
+{
+ //NSLog(@"%@", NSStringFromSelector(_cmd));
+ return proposedPosition;
+}
+
+
+#pragma mark -
+#pragma mark Actions
+
+
+- (IBAction)toggleMasterView:(id)sender
+{
+ [splitController toggleMasterView:sender];
+ [self configureView];
+}
+
+
+- (IBAction)toggleVertical:(id)sender
+{
+ [splitController toggleSplitOrientation:self];
+ [self configureView];
+}
+
+
+- (IBAction)toggleDividerStyle:(id)sender
+{
+ MGSplitViewDividerStyle newStyle = ((splitController.dividerStyle == MGSplitViewDividerStyleThin) ? MGSplitViewDividerStylePaneSplitter : MGSplitViewDividerStyleThin);
+ [splitController setDividerStyle:newStyle animated:YES];
+ [self configureView];
+}
+
+
+- (IBAction)toggleMasterBeforeDetail:(id)sender
+{
+ [splitController toggleMasterBeforeDetail:sender];
+ [self configureView];
+}
+
+
+#pragma mark -
+#pragma mark Rotation support
+
+
+// Ensure that the view controller supports rotation and that the split view can therefore show in both portrait and landscape.
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+
+- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
+{
+ [self configureView];
+}
+
+
+- (void)dealloc
+{
+ [popoverController release];
+ [toolbar release];
+
+ [detailItem release];
+ [detailDescriptionLabel release];
+ [super dealloc];
+}
+
+
+@end
31 Animations/MGSplitViewController/MGSplitCornersView.h
@@ -0,0 +1,31 @@
+//
+// MGSplitCornersView.h
+// MGSplitView
+//
+// Created by Matt Gemmell on 28/07/2010.
+// Copyright 2010 Instinctive Code.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef enum _MGCornersPosition {
+ MGCornersPositionLeadingVertical = 0, // top of screen for a left/right split.
+ MGCornersPositionTrailingVertical = 1, // bottom of screen for a left/right split.
+ MGCornersPositionLeadingHorizontal = 2, // left of screen for a top/bottom split.
+ MGCornersPositionTrailingHorizontal = 3 // right of screen for a top/bottom split.
+} MGCornersPosition;
+
+@class MGSplitViewController;
+@interface MGSplitCornersView : UIView {
+ float cornerRadius;
+ MGSplitViewController *splitViewController;
+ MGCornersPosition cornersPosition;
+ UIColor *cornerBackgroundColor;
+}
+
+@property (nonatomic, assign) float cornerRadius;
+@property (nonatomic, assign) MGSplitViewController *splitViewController; // weak ref.
+@property (nonatomic, assign) MGCornersPosition cornersPosition; // don't change this manually; let the splitViewController manage it.
+@property (nonatomic, retain) UIColor *cornerBackgroundColor;
+
+@end
244 Animations/MGSplitViewController/MGSplitCornersView.m
@@ -0,0 +1,244 @@
+//
+// MGSplitCornersView.m
+// MGSplitView
+//
+// Created by Matt Gemmell on 28/07/2010.
+// Copyright 2010 Instinctive Code.
+//
+
+#import "MGSplitCornersView.h"
+
+
+double deg2Rad(double degrees);
+double rad2Deg(double radians);
+
+@implementation MGSplitCornersView
+
+
+#pragma mark -
+#pragma mark Setup and teardown
+
+
+- (id)initWithFrame:(CGRect)frame
+{
+ if ((self = [super initWithFrame:frame])) {
+ self.contentMode = UIViewContentModeRedraw;
+ self.userInteractionEnabled = NO;
+ self.opaque = NO;
+ self.backgroundColor = [UIColor clearColor];
+ cornerRadius = 0.0; // actual value is set by the splitViewController.
+ cornersPosition = MGCornersPositionLeadingVertical;
+ }
+
+ return self;
+}
+
+
+- (void)dealloc
+{
+ self.cornerBackgroundColor = nil;
+
+ [super dealloc];
+}
+
+
+#pragma mark -
+#pragma mark Geometry helpers
+
+
+double deg2Rad(double degrees)
+{
+ // Converts degrees to radians.
+ return degrees * (M_PI / 180.0);
+}
+
+
+double rad2Deg(double radians)
+{
+ // Converts radians to degrees.
+ return radians * (180 / M_PI);
+}
+
+
+#pragma mark -
+#pragma mark Drawing
+
+
+- (void)drawRect:(CGRect)rect
+{
+ // Draw two appropriate corners, with cornerBackgroundColor behind them.
+ if (cornerRadius > 0) {
+ if (NO) { // just for debugging.
+ [[UIColor redColor] set];
+ UIRectFill(self.bounds);
+ }
+
+ float maxX = CGRectGetMaxX(self.bounds);
+ float maxY = CGRectGetMaxY(self.bounds);
+ UIBezierPath *path = [UIBezierPath bezierPath];
+ CGPoint pt = CGPointZero;
+ switch (cornersPosition) {
+ case MGCornersPositionLeadingVertical: // top of screen for a left/right split
+ [path moveToPoint:pt];
+ pt.y += cornerRadius;
+ [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(90) endAngle:0 clockwise:YES]];
+ pt.x += cornerRadius;
+ pt.y -= cornerRadius;
+ [path addLineToPoint:pt];
+ [path addLineToPoint:CGPointZero];
+ [path closePath];
+
+ pt.x = maxX - cornerRadius;
+ pt.y = 0;
+ [path moveToPoint:pt];
+ pt.y = maxY;
+ [path addLineToPoint:pt];
+ pt.x += cornerRadius;
+ [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(180) endAngle:deg2Rad(90) clockwise:YES]];
+ pt.y -= cornerRadius;
+ [path addLineToPoint:pt];
+ pt.x -= cornerRadius;
+ [path addLineToPoint:pt];
+ [path closePath];
+
+ break;
+
+ case MGCornersPositionTrailingVertical: // bottom of screen for a left/right split
+ pt.y = maxY;
+ [path moveToPoint:pt];
+ pt.y -= cornerRadius;
+ [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(270) endAngle:deg2Rad(360) clockwise:NO]];
+ pt.x += cornerRadius;
+ pt.y += cornerRadius;
+ [path addLineToPoint:pt];
+ pt.x -= cornerRadius;
+ [path addLineToPoint:pt];
+ [path closePath];
+
+ pt.x = maxX - cornerRadius;
+ pt.y = maxY;
+ [path moveToPoint:pt];
+ pt.y -= cornerRadius;
+ [path addLineToPoint:pt];
+ pt.x += cornerRadius;
+ [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(180) endAngle:deg2Rad(270) clockwise:NO]];
+ pt.y += cornerRadius;
+ [path addLineToPoint:pt];
+ pt.x -= cornerRadius;
+ [path addLineToPoint:pt];
+ [path closePath];
+
+ break;
+
+ case MGCornersPositionLeadingHorizontal: // left of screen for a top/bottom split
+ pt.x = 0;
+ pt.y = cornerRadius;
+ [path moveToPoint:pt];
+ pt.y -= cornerRadius;
+ [path addLineToPoint:pt];
+ pt.x += cornerRadius;
+ [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(180) endAngle:deg2Rad(270) clockwise:NO]];
+ pt.y += cornerRadius;
+ [path addLineToPoint:pt];
+ pt.x -= cornerRadius;
+ [path addLineToPoint:pt];
+ [path closePath];
+
+ pt.x = 0;
+ pt.y = maxY - cornerRadius;
+ [path moveToPoint:pt];
+ pt.y = maxY;
+ [path addLineToPoint:pt];
+ pt.x += cornerRadius;
+ [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(180) endAngle:deg2Rad(90) clockwise:YES]];
+ pt.y -= cornerRadius;
+ [path addLineToPoint:pt];
+ pt.x -= cornerRadius;
+ [path addLineToPoint:pt];
+ [path closePath];
+
+ break;
+
+ case MGCornersPositionTrailingHorizontal: // right of screen for a top/bottom split
+ pt.y = cornerRadius;
+ [path moveToPoint:pt];
+ pt.y -= cornerRadius;
+ [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(270) endAngle:deg2Rad(360) clockwise:NO]];
+ pt.x += cornerRadius;
+ pt.y += cornerRadius;
+ [path addLineToPoint:pt];
+ pt.x -= cornerRadius;
+ [path addLineToPoint:pt];
+ [path closePath];
+
+ pt.y = maxY - cornerRadius;
+ [path moveToPoint:pt];
+ pt.y += cornerRadius;
+ [path appendPath:[UIBezierPath bezierPathWithArcCenter:pt radius:cornerRadius startAngle:deg2Rad(90) endAngle:0 clockwise:YES]];
+ pt.x += cornerRadius;
+ pt.y -= cornerRadius;
+ [path addLineToPoint:pt];
+ pt.x -= cornerRadius;
+ [path addLineToPoint:pt];
+ [path closePath];
+
+ break;
+
+ default:
+ break;
+ }
+
+ [self.cornerBackgroundColor set];
+ [path fill];
+ }
+}
+
+
+#pragma mark -
+#pragma mark Accessors and properties
+
+
+- (void)setCornerRadius:(float)newRadius
+{
+ if (newRadius != cornerRadius) {
+ cornerRadius = newRadius;
+ [self setNeedsDisplay];
+ }
+}
+
+
+- (void)setSplitViewController:(MGSplitViewController *)theController
+{
+ if (theController != splitViewController) {
+ splitViewController = theController;
+ [self setNeedsDisplay];
+ }
+}
+
+
+- (void)setCornersPosition:(MGCornersPosition)posn
+{
+ if (cornersPosition != posn) {
+ cornersPosition = posn;
+ [self setNeedsDisplay];
+ }
+}
+
+
+- (void)setCornerBackgroundColor:(UIColor *)color
+{
+ if (color != cornerBackgroundColor) {
+ [cornerBackgroundColor release];
+ cornerBackgroundColor = [color retain];
+ [self setNeedsDisplay];
+ }
+}
+
+
+@synthesize cornerRadius;
+@synthesize splitViewController;
+@synthesize cornersPosition;
+@synthesize cornerBackgroundColor;
+
+
+@end
22 Animations/MGSplitViewController/MGSplitDividerView.h
@@ -0,0 +1,22 @@
+//
+// MGSplitDividerView.h
+// MGSplitView
+//
+// Created by Matt Gemmell on 26/07/2010.
+// Copyright 2010 Instinctive Code.
+//
+
+#import <UIKit/UIKit.h>
+
+@class MGSplitViewController;
+@interface MGSplitDividerView : UIView {
+ MGSplitViewController *splitViewController;
+ BOOL allowsDragging;
+}
+
+@property (nonatomic, assign) MGSplitViewController *splitViewController; // weak ref.
+@property (nonatomic, assign) BOOL allowsDragging;
+
+- (void)drawGripThumbInRect:(CGRect)rect;
+
+@end
216 Animations/MGSplitViewController/MGSplitDividerView.m
@@ -0,0 +1,216 @@
+//
+// MGSplitDividerView.m
+// MGSplitView
+//
+// Created by Matt Gemmell on 26/07/2010.
+// Copyright 2010 Instinctive Code.
+//
+
+#import "MGSplitDividerView.h"
+#import "MGSplitViewController.h"
+
+
+@implementation MGSplitDividerView
+
+
+#pragma mark -
+#pragma mark Setup and teardown
+
+
+- (id)initWithFrame:(CGRect)frame
+{
+ if ((self = [super initWithFrame:frame])) {
+ self.userInteractionEnabled = NO;
+ self.allowsDragging = NO;
+ self.contentMode = UIViewContentModeRedraw;
+ }
+ return self;
+}
+
+
+- (void)dealloc
+{
+ self.splitViewController = nil;
+ [super dealloc];
+}
+
+
+#pragma mark -
+#pragma mark Drawing
+
+
+- (void)drawRect:(CGRect)rect
+{
+ if (splitViewController.dividerStyle == MGSplitViewDividerStyleThin) {
+ [super drawRect:rect];
+
+ } else if (splitViewController.dividerStyle == MGSplitViewDividerStylePaneSplitter) {
+ // Draw gradient background.
+ CGRect bounds = self.bounds;
+ CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
+ CGFloat locations[2] = {0, 1};
+ CGFloat components[8] = { 0.988, 0.988, 0.988, 1.0, // light
+ 0.875, 0.875, 0.875, 1.0 };// dark
+ CGGradientRef gradient = CGGradientCreateWithColorComponents (rgb, components, locations, 2);
+ CGContextRef context = UIGraphicsGetCurrentContext();
+ CGPoint start, end;
+ if (splitViewController.vertical) {
+ // Light left to dark right.
+ start = CGPointMake(CGRectGetMinX(bounds), CGRectGetMidY(bounds));
+ end = CGPointMake(CGRectGetMaxX(bounds), CGRectGetMidY(bounds));
+ } else {
+ // Light top to dark bottom.
+ start = CGPointMake(CGRectGetMidX(bounds), CGRectGetMinY(bounds));
+ end = CGPointMake(CGRectGetMidX(bounds), CGRectGetMaxY(bounds));
+ }
+ CGContextDrawLinearGradient(context, gradient, start, end, 0);
+ CGColorSpaceRelease(rgb);
+ CGGradientRelease(gradient);
+
+ // Draw borders.
+ float borderThickness = 1.0;
+ [[UIColor colorWithWhite:0.7 alpha:1.0] set];
+ CGRect borderRect = bounds;
+ if (splitViewController.vertical) {
+ borderRect.size.width = borderThickness;
+ UIRectFill(borderRect);
+ borderRect.origin.x = CGRectGetMaxX(bounds) - borderThickness;
+ UIRectFill(borderRect);
+
+ } else {
+ borderRect.size.height = borderThickness;
+ UIRectFill(borderRect);
+ borderRect.origin.y = CGRectGetMaxY(bounds) - borderThickness;
+ UIRectFill(borderRect);
+ }
+
+ // Draw grip.
+ [self drawGripThumbInRect:bounds];
+ }
+}
+
+
+- (void)drawGripThumbInRect:(CGRect)rect
+{
+ float width = 9.0;
+ float height;
+ if (splitViewController.vertical) {
+ height = 30.0;
+ } else {
+ height = width;
+ width = 30.0;
+ }
+
+ // Draw grip in centred in rect.
+ CGRect gripRect = CGRectMake(0, 0, width, height);
+ gripRect.origin.x = ((rect.size.width - gripRect.size.width) / 2.0);
+ gripRect.origin.y = ((rect.size.height - gripRect.size.height) / 2.0);
+
+ float stripThickness = 1.0;
+ UIColor *stripColor = [UIColor colorWithWhite:0.35 alpha:1.0];
+ UIColor *lightColor = [UIColor colorWithWhite:1.0 alpha:1.0];
+ float space = 3.0;
+ if (splitViewController.vertical) {
+ gripRect.size.width = stripThickness;
+ [stripColor set];
+ UIRectFill(gripRect);
+
+ gripRect.origin.x += stripThickness;
+ gripRect.origin.y += 1;
+ [lightColor set];
+ UIRectFill(gripRect);
+ gripRect.origin.x -= stripThickness;
+ gripRect.origin.y -= 1;
+
+ gripRect.origin.x += space + stripThickness;
+ [stripColor set];
+ UIRectFill(gripRect);
+
+ gripRect.origin.x += stripThickness;
+ gripRect.origin.y += 1;
+ [lightColor set];
+ UIRectFill(gripRect);
+ gripRect.origin.x -= stripThickness;
+ gripRect.origin.y -= 1;
+
+ gripRect.origin.x += space + stripThickness;
+ [stripColor set];
+ UIRectFill(gripRect);
+
+ gripRect.origin.x += stripThickness;
+ gripRect.origin.y += 1;
+ [lightColor set];
+ UIRectFill(gripRect);
+
+ } else {
+ gripRect.size.height = stripThickness;
+ [stripColor set];
+ UIRectFill(gripRect);
+
+ gripRect.origin.y += stripThickness;
+ gripRect.origin.x -= 1;
+ [lightColor set];
+ UIRectFill(gripRect);
+ gripRect.origin.y -= stripThickness;
+ gripRect.origin.x += 1;
+
+ gripRect.origin.y += space + stripThickness;
+ [stripColor set];
+ UIRectFill(gripRect);
+
+ gripRect.origin.y += stripThickness;
+ gripRect.origin.x -= 1;
+ [lightColor set];
+ UIRectFill(gripRect);
+ gripRect.origin.y -= stripThickness;
+ gripRect.origin.x += 1;
+
+ gripRect.origin.y += space + stripThickness;
+ [stripColor set];
+ UIRectFill(gripRect);
+
+ gripRect.origin.y += stripThickness;
+ gripRect.origin.x -= 1;
+ [lightColor set];
+ UIRectFill(gripRect);
+ }
+}
+
+
+#pragma mark -
+#pragma mark Interaction
+
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ UITouch *touch = [touches anyObject];
+ if (touch) {
+ CGPoint lastPt = [touch previousLocationInView:self];
+ CGPoint pt = [touch locationInView:self];
+ float offset = (splitViewController.vertical) ? pt.x - lastPt.x : pt.y - lastPt.y;
+ if (!splitViewController.masterBeforeDetail) {
+ offset = -offset;
+ }
+ splitViewController.splitPosition = splitViewController.splitPosition + offset;
+ }
+}
+
+
+#pragma mark -
+#pragma mark Accessors and properties
+
+
+- (void)setAllowsDragging:(BOOL)flag
+{
+ if (flag != allowsDragging) {
+ allowsDragging = flag;
+ self.userInteractionEnabled = allowsDragging;
+ }
+}
+
+
+@synthesize splitViewController;
+@synthesize allowsDragging;
+
+
+@end
28 Animations/MGSplitViewController/MGSplitViewAppDelegate.h
@@ -0,0 +1,28 @@
+//
+// MGSplitViewAppDelegate.h
+// MGSplitView
+//
+// Created by Matt Gemmell on 26/07/2010.
+// Copyright Instinctive Code 2010.
+//
+
+#import <UIKit/UIKit.h>
+
+@class RootViewController;
+@class DetailViewController;
+@class MGSplitViewController;
+
+@interface MGSplitViewAppDelegate : NSObject <UIApplicationDelegate> {
+ UIWindow *window;
+ MGSplitViewController *splitViewController;
+ RootViewController *rootViewController;
+ DetailViewController *detailViewController;
+}
+
+@property (nonatomic, retain) IBOutlet UIWindow *window;
+
+@property (nonatomic, retain) IBOutlet MGSplitViewController *splitViewController;
+@property (nonatomic, retain) IBOutlet RootViewController *rootViewController;
+@property (nonatomic, retain) IBOutlet DetailViewController *detailViewController;
+
+@end
48 Animations/MGSplitViewController/MGSplitViewAppDelegate.m
@@ -0,0 +1,48 @@
+//
+// MGSplitViewAppDelegate.m
+// MGSplitView
+//
+// Created by Matt Gemmell on 26/07/2010.
+// Copyright Instinctive Code 2010.
+//
+
+#import "MGSplitViewAppDelegate.h"
+#import "RootViewController.h"
+#import "DetailViewController.h"
+#import "MGSplitViewController.h"
+
+@implementation MGSplitViewAppDelegate
+
+
+@synthesize window, splitViewController, rootViewController, detailViewController;
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ // Add the split view controller's view to the window and display.
+ [window addSubview:splitViewController.view];
+ [window makeKeyAndVisible];
+
+ [rootViewController performSelector:@selector(selectFirstRow) withObject:nil afterDelay:0];
+ [detailViewController performSelector:@selector(configureView) withObject:nil afterDelay:0];
+
+ if (NO) { // whether to allow dragging the divider to move the split.
+ splitViewController.splitWidth = 15.0; // make it wide enough to actually drag!
+ splitViewController.allowsDraggingDivider = YES;
+ }
+
+ return YES;
+}
+
+
+- (void)dealloc
+{
+ [splitViewController release];
+ [window release];
+
+ [super dealloc];
+}
+
+
+@end
+
116 Animations/MGSplitViewController/MGSplitViewController.h
@@ -0,0 +1,116 @@
+//
+// MGSplitViewController.h
+// MGSplitView
+//
+// Created by Matt Gemmell on 26/07/2010.
+// Copyright 2010 Instinctive Code.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef enum _MGSplitViewDividerStyle {
+ // These names have been chosen to be conceptually similar to those of NSSplitView on Mac OS X.
+ MGSplitViewDividerStyleThin = 0, // Thin divider, like UISplitViewController (default).
+ MGSplitViewDividerStylePaneSplitter = 1 // Thick divider, drawn with a grey gradient and a grab-strip.
+} MGSplitViewDividerStyle;
+
+@class MGSplitDividerView;
+@protocol MGSplitViewControllerDelegate;
+@interface MGSplitViewController : UIViewController <UIPopoverControllerDelegate> {
+ BOOL _showsMasterInPortrait;
+ BOOL _showsMasterInLandscape;
+ float _splitWidth;
+ id _delegate;
+ BOOL _vertical;
+ BOOL _masterBeforeDetail;
+ NSMutableArray *_viewControllers;
+ UIBarButtonItem *_barButtonItem; // To be compliant with wacky UISplitViewController behaviour.
+ UIPopoverController *_hiddenPopoverController; // Popover used to hold the master view if it's not always visible.
+ MGSplitDividerView *_dividerView; // View that draws the divider between the master and detail views.
+ NSArray *_cornerViews; // Views to draw the inner rounded corners between master and detail views.
+ float _splitPosition;
+ BOOL _reconfigurePopup;
+ MGSplitViewDividerStyle _dividerStyle; // Meta-setting which configures several aspects of appearance and behaviour.
+}
+
+@property (nonatomic, assign) IBOutlet id <MGSplitViewControllerDelegate> delegate;
+@property (nonatomic, assign) BOOL showsMasterInPortrait; // applies to both portrait orientations (default NO)
+@property (nonatomic, assign) BOOL showsMasterInLandscape; // applies to both landscape orientations (default YES)
+@property (nonatomic, assign, getter=isVertical) BOOL vertical; // if NO, split is horizontal, i.e. master above detail (default YES)
+@property (nonatomic, assign, getter=isMasterBeforeDetail) BOOL masterBeforeDetail; // if NO, master view is below/right of detail (default YES)
+@property (nonatomic, assign) float splitPosition; // starting position of split in pixels, relative to top/left (depending on .isVertical setting) if masterBeforeDetail is YES, else relative to bottom/right.
+@property (nonatomic, assign) float splitWidth; // width of split in pixels.
+@property (nonatomic, assign) BOOL allowsDraggingDivider; // whether to let the user drag the divider to alter the split position (default NO).
+
+@property (nonatomic, copy) NSArray *viewControllers; // array of UIViewControllers; master is at index 0, detail is at index 1.
+@property (nonatomic, retain) IBOutlet UIViewController *masterViewController; // convenience.
+@property (nonatomic, retain) IBOutlet UIViewController *detailViewController; // convenience.
+@property (nonatomic, retain) MGSplitDividerView *dividerView; // the view which draws the divider/split between master and detail.
+@property (nonatomic, assign) MGSplitViewDividerStyle dividerStyle; // style (and behaviour) of the divider between master and detail.
+
+@property (nonatomic, readonly, getter=isLandscape) BOOL landscape; // returns YES if this view controller is in either of the two Landscape orientations, else NO.
+
+// Actions
+- (IBAction)toggleSplitOrientation:(id)sender; // toggles split axis between vertical (left/right; default) and horizontal (top/bottom).
+- (IBAction)toggleMasterBeforeDetail:(id)sender; // toggles position of master view relative to detail view.
+- (IBAction)toggleMasterView:(id)sender; // toggles display of the master view in the current orientation.
+- (IBAction)showMasterPopover:(id)sender; // shows the master view in a popover spawned from the provided barButtonItem, if it's currently hidden.
+- (void)notePopoverDismissed; // should rarely be needed, because you should not change the popover's delegate. If you must, then call this when it's dismissed.
+
+// Conveniences for you, because I care.
+- (BOOL)isShowingMaster;
+- (void)setSplitPosition:(float)posn animated:(BOOL)animate; // Allows for animation of splitPosition changes. The property's regular setter is not animated.
+/* Note: splitPosition is the width (in a left/right split, or height in a top/bottom split) of the master view.
+ It is relative to the appropriate side of the splitView, which can be any of the four sides depending on the values in isMasterBeforeDetail and isVertical:
+ isVertical = YES, isMasterBeforeDetail = YES: splitPosition is relative to the LEFT edge. (Default)
+ isVertical = YES, isMasterBeforeDetail = NO: splitPosition is relative to the RIGHT edge.
+ isVertical = NO, isMasterBeforeDetail = YES: splitPosition is relative to the TOP edge.
+ isVertical = NO, isMasterBeforeDetail = NO: splitPosition is relative to the BOTTOM edge.
+
+ This implementation was chosen so you don't need to recalculate equivalent splitPositions if the user toggles masterBeforeDetail themselves.
+ */
+- (void)setDividerStyle:(MGSplitViewDividerStyle)newStyle animated:(BOOL)animate; // Allows for animation of dividerStyle changes. The property's regular setter is not animated.
+- (NSArray *)cornerViews;
+/*
+ -cornerViews returns an NSArray of two MGSplitCornersView objects, used to draw the inner corners.
+ The first view is the "leading" corners (top edge of screen for left/right split, left edge of screen for top/bottom split).
+ The second view is the "trailing" corners (bottom edge of screen for left/right split, right edge of screen for top/bottom split).
+ Do NOT modify them, except to:
+ 1. Change their .cornerBackgroundColor
+ 2. Change their .cornerRadius
+ */
+
+@end
+
+
+@protocol MGSplitViewControllerDelegate
+
+@optional
+
+// Called when a button should be added to a toolbar for a hidden view controller.
+- (void)splitViewController:(MGSplitViewController*)svc
+ willHideViewController:(UIViewController *)aViewController
+ withBarButtonItem:(UIBarButtonItem*)barButtonItem
+ forPopoverController: (UIPopoverController*)pc;
+
+// Called when the master view is shown again in the split view, invalidating the button and popover controller.
+- (void)splitViewController:(MGSplitViewController*)svc
+ willShowViewController:(UIViewController *)aViewController
+ invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem;
+
+// Called when the master view is shown in a popover, so the delegate can take action like hiding other popovers.
+- (void)splitViewController:(MGSplitViewController*)svc
+ popoverController:(UIPopoverController*)pc
+ willPresentViewController:(UIViewController *)aViewController;
+
+// Called when the split orientation will change (from vertical to horizontal, or vice versa).
+- (void)splitViewController:(MGSplitViewController*)svc willChangeSplitOrientationToVertical:(BOOL)isVertical;
+
+// Called when split position will change to the given pixel value (relative to left if split is vertical, or to top if horizontal).
+- (void)splitViewController:(MGSplitViewController*)svc willMoveSplitToPosition:(float)position;
+
+// Called before split position is changed to the given pixel value (relative to left if split is vertical, or to top if horizontal).
+// Note that viewSize is the current size of the entire split-view; i.e. the area enclosing the master, divider and detail views.
+- (float)splitViewController:(MGSplitViewController *)svc constrainSplitPosition:(float)proposedPosition splitViewSize:(CGSize)viewSize;
+
+@end
1,135 Animations/MGSplitViewController/MGSplitViewController.m
@@ -0,0 +1,1135 @@
+//
+// MGSplitViewController.m
+// MGSplitView
+//
+// Created by Matt Gemmell on 26/07/2010.
+// Copyright 2010 Instinctive Code.
+//
+
+#import "MGSplitViewController.h"
+#import "MGSplitDividerView.h"
+#import "MGSplitCornersView.h"
+
+#define MG_DEFAULT_SPLIT_POSITION 320.0 // default width of master view in UISplitViewController.
+#define MG_DEFAULT_SPLIT_WIDTH 1.0 // default width of split-gutter in UISplitViewController.
+#define MG_DEFAULT_CORNER_RADIUS 5.0 // default corner-radius of overlapping split-inner corners on the master and detail views.
+#define MG_DEFAULT_CORNER_COLOR [UIColor blackColor] // default color of intruding inner corners (and divider background).
+
+#define MG_PANESPLITTER_CORNER_RADIUS 0.0 // corner-radius of split-inner corners for MGSplitViewDividerStylePaneSplitter style.
+#define MG_PANESPLITTER_SPLIT_WIDTH 25.0 // width of split-gutter for MGSplitViewDividerStylePaneSplitter style.
+
+#define MG_MIN_VIEW_WIDTH 200.0 // minimum width a view is allowed to become as a result of changing the splitPosition.
+
+#define MG_ANIMATION_CHANGE_SPLIT_ORIENTATION @"ChangeSplitOrientation" // Animation ID for internal use.
+#define MG_ANIMATION_CHANGE_SUBVIEWS_ORDER @"ChangeSubviewsOrder" // Animation ID for internal use.
+
+
+@interface MGSplitViewController (MGPrivateMethods)
+
+- (void)setup;
+- (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation;
+- (void)layoutSubviews;
+- (void)layoutSubviewsWithAnimation:(BOOL)animate;
+- (void)layoutSubviewsForInterfaceOrientation:(UIInterfaceOrientation)theOrientation withAnimation:(BOOL)animate;
+- (BOOL)shouldShowMasterForInterfaceOrientation:(UIInterfaceOrientation)theOrientation;
+- (BOOL)shouldShowMaster;
+- (NSString *)nameOfInterfaceOrientation:(UIInterfaceOrientation)theOrientation;
+- (void)reconfigureForMasterInPopover:(BOOL)inPopover;
+
+@end
+
+
+@implementation MGSplitViewController
+
+
+#pragma mark -
+#pragma mark Orientation helpers
+
+
+- (NSString *)nameOfInterfaceOrientation:(UIInterfaceOrientation)theOrientation
+{
+ NSString *orientationName = nil;
+ switch (theOrientation) {
+ case UIInterfaceOrientationPortrait:
+ orientationName = @"Portrait"; // Home button at bottom
+ break;
+ case UIInterfaceOrientationPortraitUpsideDown:
+ orientationName = @"Portrait (Upside Down)"; // Home button at top
+ break;
+ case UIInterfaceOrientationLandscapeLeft:
+ orientationName = @"Landscape (Left)"; // Home button on left
+ break;
+ case UIInterfaceOrientationLandscapeRight:
+ orientationName = @"Landscape (Right)"; // Home button on right
+ break;
+ default:
+ break;
+ }
+
+ return orientationName;
+}
+
+
+- (BOOL)isLandscape
+{
+ return UIInterfaceOrientationIsLandscape(self.interfaceOrientation);
+}
+
+
+- (BOOL)shouldShowMasterForInterfaceOrientation:(UIInterfaceOrientation)theOrientation
+{
+ // Returns YES if master view should be shown directly embedded in the splitview, instead of hidden in a popover.
+ return ((UIInterfaceOrientationIsLandscape(theOrientation)) ? _showsMasterInLandscape : _showsMasterInPortrait);
+}
+
+
+- (BOOL)shouldShowMaster
+{
+ return [self shouldShowMasterForInterfaceOrientation:self.interfaceOrientation];
+}
+
+
+- (BOOL)isShowingMaster
+{
+ return [self shouldShowMaster] && self.masterViewController && self.masterViewController.view && ([self.masterViewController.view superview] == self.view);
+}
+
+
+#pragma mark -
+#pragma mark Setup and Teardown
+
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
+ [self setup];
+ }
+
+ return self;
+}
+
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+ if ((self = [super initWithCoder:aDecoder])) {
+ [self setup];
+ }
+
+ return self;
+}
+
+
+- (void)setup
+{
+ // Configure default behaviour.
+ _viewControllers = [[NSMutableArray alloc] initWithObjects:[NSNull null], [NSNull null], nil];
+ _splitWidth = MG_DEFAULT_SPLIT_WIDTH;
+ _showsMasterInPortrait = NO;
+ _showsMasterInLandscape = YES;
+ _reconfigurePopup = NO;
+ _vertical = YES;
+ _masterBeforeDetail = YES;
+ _splitPosition = MG_DEFAULT_SPLIT_POSITION;
+ CGRect divRect = self.view.bounds;
+ if ([self isVertical]) {
+ divRect.origin.y = _splitPosition;
+ divRect.size.height = _splitWidth;
+ } else {
+ divRect.origin.x = _splitPosition;
+ divRect.size.width = _splitWidth;
+ }
+ _dividerView = [[MGSplitDividerView alloc] initWithFrame:divRect];
+ _dividerView.splitViewController = self;
+ _dividerView.backgroundColor = MG_DEFAULT_CORNER_COLOR;
+ _dividerStyle = MGSplitViewDividerStyleThin;
+}
+
+
+- (void)dealloc
+{
+ _delegate = nil;
+ [self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
+ [_viewControllers release];
+ [_barButtonItem release];
+ [_hiddenPopoverController release];
+ [_dividerView release];
+ [_cornerViews release];
+
+ [super dealloc];
+}
+
+
+#pragma mark -
+#pragma mark View management
+
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+
+- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
+{
+ [self.masterViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
+ [self.detailViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
+}
+
+
+- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
+{
+ [self.masterViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
+ [self.detailViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
+}
+
+
+- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
+ duration:(NSTimeInterval)duration
+{
+ // Hide popover.
+ if (_hiddenPopoverController && _hiddenPopoverController.popoverVisible) {
+ [_hiddenPopoverController dismissPopoverAnimated:NO];
+ }
+
+ // Re-tile views.
+ _reconfigurePopup = YES;
+ [self layoutSubviewsForInterfaceOrientation:toInterfaceOrientation withAnimation:YES];
+
+ // JBG: Moving these to after to fix this bug, as suggested by:
+ // https://github.com/mattgemmell/MGSplitViewController/issues/35
+ [self.masterViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
+ [self.detailViewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
+}
+
+
+- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
+{
+ [self.masterViewController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
+ [self.detailViewController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
+}
+
+
+- (void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
+{
+ [self.masterViewController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
+ [self.detailViewController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
+}
+
+
+- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration
+{
+ [self.masterViewController willAnimateSecondHalfOfRotationFromInterfaceOrientation:fromInterfaceOrientation duration:duration];
+ [self.detailViewController willAnimateSecondHalfOfRotationFromInterfaceOrientation:fromInterfaceOrientation duration:duration];
+}
+
+
+- (CGSize)splitViewSizeForOrientation:(UIInterfaceOrientation)theOrientation
+{
+ UIScreen *screen = [UIScreen mainScreen];
+ CGRect fullScreenRect = screen.bounds; // always implicitly in Portrait orientation.
+ CGRect appFrame = screen.applicationFrame;
+
+ // Find status bar height by checking which dimension of the applicationFrame is narrower than screen bounds.
+ // Little bit ugly looking, but it'll still work even if they change the status bar height in future.
+ float statusBarHeight = MAX((fullScreenRect.size.width - appFrame.size.width), (fullScreenRect.size.height - appFrame.size.height));
+
+ // Initially assume portrait orientation.
+ float width = fullScreenRect.size.width;
+ float height = fullScreenRect.size.height;
+
+ // Correct for orientation.
+ if (UIInterfaceOrientationIsLandscape(theOrientation)) {
+ width = height;
+ height = fullScreenRect.size.width;
+ }
+
+ // Account for status bar, which always subtracts from the height (since it's always at the top of the screen).
+ height -= statusBarHeight;
+
+ return CGSizeMake(width, height);
+}
+
+
+- (void)layoutSubviewsForInterfaceOrientation:(UIInterfaceOrientation)theOrientation withAnimation:(BOOL)animate
+{
+ if (_reconfigurePopup) {
+ [self reconfigureForMasterInPopover:![self shouldShowMasterForInterfaceOrientation:theOrientation]];
+ }
+
+ // Layout the master, detail and divider views appropriately, adding/removing subviews as needed.
+ // First obtain relevant geometry.
+ CGSize fullSize = [self splitViewSizeForOrientation:theOrientation];
+ float width = fullSize.width;
+ float height = fullSize.height;
+
+ if (NO) { // Just for debugging.
+ NSLog(@"Target orientation is %@, dimensions will be %.0f x %.0f",
+ [self nameOfInterfaceOrientation:theOrientation], width, height);
+ }
+
+ // Layout the master, divider and detail views.
+ CGRect newFrame = CGRectMake(0, 0, width, height);
+ UIViewController *controller;
+ UIView *theView;
+ BOOL shouldShowMaster = [self shouldShowMasterForInterfaceOrientation:theOrientation];
+ BOOL masterFirst = [self isMasterBeforeDetail];
+ if ([self isVertical]) {
+ // Master on left, detail on right (or vice versa).
+ CGRect masterRect, dividerRect, detailRect;
+ if (masterFirst) {
+ if (!shouldShowMaster) {
+ // Move off-screen.
+ newFrame.origin.x -= (_splitPosition + _splitWidth);
+ }
+
+ newFrame.size.width = _splitPosition;
+ masterRect = newFrame;
+
+ newFrame.origin.x += newFrame.size.width;
+ newFrame.size.width = _splitWidth;
+ dividerRect = newFrame;
+
+ newFrame.origin.x += newFrame.size.width;
+ newFrame.size.width = width - newFrame.origin.x;
+ detailRect = newFrame;
+
+ } else {
+ if (!shouldShowMaster) {
+ // Move off-screen.
+ newFrame.size.width += (_splitPosition + _splitWidth);
+ }
+
+ newFrame.size.width -= (_splitPosition + _splitWidth);
+ detailRect = newFrame;
+
+ newFrame.origin.x += newFrame.size.width;
+ newFrame.size.width = _splitWidth;
+ dividerRect = newFrame;
+
+ newFrame.origin.x += newFrame.size.width;
+ newFrame.size.width = _splitPosition;
+ masterRect = newFrame;
+ }
+
+ // Position master.
+ controller = self.masterViewController;
+ if (controller && [controller isKindOfClass:[UIViewController class]]) {
+ theView = controller.view;
+ if (theView) {
+ theView.frame = masterRect;
+ if (!theView.superview) {
+ [controller viewWillAppear:NO];
+ [self.view addSubview:theView];
+ [controller viewDidAppear:NO];
+ }
+ }
+ }
+
+ // Position divider.
+ theView = _dividerView;
+ theView.frame = dividerRect;
+ if (!theView.superview) {
+ [self.view addSubview:theView];
+ }
+
+ // Position detail.
+ controller = self.detailViewController;
+ if (controller && [controller isKindOfClass:[UIViewController class]]) {
+ theView = controller.view;
+ if (theView) {
+ theView.frame = detailRect;
+ if (!theView.superview) {
+ [self.view insertSubview:theView aboveSubview:self.masterViewController.view];
+ } else {
+ [self.view bringSubviewToFront:theView];
+ }
+ }
+ }
+
+ } else {
+ // Master above, detail below (or vice versa).
+ CGRect masterRect, dividerRect, detailRect;
+ if (masterFirst) {
+ if (!shouldShowMaster) {