         }
     }
     
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        
-        self.scrollView.frame = self.view.bounds
-        self.gradientView.frame = self.scrollView.bounds;
-        self.view.addSubview(self.scrollView)
-        
-        self.scrollView.delegate = self
-        
-        let rotate = UIRotationGestureRecognizer(target: self, action: "handleRotation:")
-        rotate.delegate = self
-        self.view.addGestureRecognizer(rotate)
-        
-        let tap = UITapGestureRecognizer(target: self, action: "handleTap:")
-        self.view.addGestureRecognizer(tap)
-        
-        let longPress = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
-        self.view.addGestureRecognizer(longPress)
-        
-    }
-    
-    func saveGradient () {
-        self.saveState = .Saving
-        UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, true, 0.0)
-        self.view.drawViewHierarchyInRect(self.view.bounds, afterScreenUpdates: false)
+    // MARK: Saving gradients
+    
+    private func imageFromCurrentGradient() -> UIImage {
+        UIGraphicsBeginImageContextWithOptions(self.scrollView.frame.size, true, 0.0)
+        self.scrollView.drawViewHierarchyInRect(self.scrollView.frame, afterScreenUpdates: false)
         let screenshot = UIGraphicsGetImageFromCurrentImageContext()
         UIGraphicsEndImageContext()
-        // convert to PNG so that it doesn't save a JPEG
+        // convert to PNG so that it doesn't save a JPEG (default)
         let pngData = UIImagePNGRepresentation(screenshot)
-        let gradient = UIImage(data: pngData)
+        return UIImage(data: pngData)!
+    }
+    
+    private func saveGradient () {
+        self.saveState = .Saving
+        let gradient = self.imageFromCurrentGradient()
+        
         UIImageWriteToSavedPhotosAlbum(gradient, self, "image:didFinishSavingWithError:contextInfo:", nil)
     }
     
     func image(image : UIImage, didFinishSavingWithError error : NSError!, contextInfo : UnsafePointer<Void>) {
         if error != nil {
-            var alertController : UIAlertController?
-            
-            if error.code == ALAssetsLibraryAccessUserDeniedError || error.code == ALAssetsLibraryAccessGloballyDeniedError {
-                alertController = UIAlertController(title: NSLocalizedString("unable_to_save", comment: ""), message: NSLocalizedString("cannot_access_photos", comment: ""), preferredStyle: .Alert)
-                
-            } else {
-                alertController = UIAlertController(title: NSLocalizedString("unable_to_save", comment: ""), message: error.localizedDescription, preferredStyle: .Alert)
-            }
-            
-            alertController!.addAction(UIAlertAction(title: NSLocalizedString("close", comment: ""), style: .Cancel, handler: nil))
-            self.presentViewController(alertController!, animated: true, completion: { () -> Void in
-                self.saveState = .Idle
-            })
-            
+            // there was a problem saving the gradient
+            // just display the activity controller instead
+            self.showActivityControllerForImage(image)
+            self.saveState = .Idle
         } else {
             self.saveState = .Saved
             self.showSaveIndicator()
-        }
-    }
-    
-    func showSaveIndicator () {
+            self.showInfoButton()
+        }
+    }
+    
+    private func showInfoButton () {
+        let btn = self.infoButton
+        btn.frame = CGRectMake(CGRectGetWidth(self.view.bounds) - CGRectGetWidth(btn.bounds), 0, CGRectGetWidth(btn.bounds), CGRectGetHeight(btn.bounds))
+        btn.alpha = 0.0
+        self.view.addSubview(btn)
+        btn.fadeIn(nil)
+    }
+    
+    private func hideInfoButton () {
+        self.infoButton.fadeOut { (finished : Bool) -> () in
+            self.infoButton.removeFromSuperview()
+        }
+    }
+    
+    private func showSaveIndicator () {
         let btn = self.saveIndicator
         btn.center = self.view.center
         btn.transform = CGAffineTransformMakeScale(0.01, 0.01)
         self.view.addSubview(btn)
-        btn.grow(nil)
-    }
-    
-    func hideSaveIndicator () {
+        btn.grow { (finished : Bool) -> () in
+            UIView.transitionWithView(btn, duration: 0.5, options: .TransitionCrossDissolve, animations: { () -> Void in
+                btn.setTitle(nil, forState: .Normal)
+                btn.setImage(UIImage(named: "Action")?.imageWithRenderingMode(.AlwaysTemplate), forState: .Normal)
+            }, completion: nil)
+        }
+    }
+    
+    private func hideSaveIndicator () {
         let btn = self.saveIndicator
         btn.shrink { (finished : Bool) -> () in
             btn.removeFromSuperview()
+            btn.setTitle(NSLocalizedString("saved", comment: "").uppercaseStringWithLocale(NSLocale.autoupdatingCurrentLocale()), forState: .Normal)
+            btn.setImage(nil, forState: .Normal)
             self.saveState = .Idle
         }
     }
     
     func sharePressed (button : UIButton) {
-        
-    }
-    
-    func viewForZoomingInScrollView(scrollView: UIScrollView!) -> UIView! {
-        return self.gradientView
-    }
-
-    override func didReceiveMemoryWarning() {
-        super.didReceiveMemoryWarning()
-        // Dispose of any resources that can be recreated.
-    }
-    
-    override func prefersStatusBarHidden() -> Bool {
-        return true;
-    }
-    
-    override func viewDidAppear(animated: Bool) {
-        super.viewDidAppear(animated)
-        self.becomeFirstResponder()
-    }
-    
-    override func viewWillDisappear(animated: Bool) {
-        self.resignFirstResponder()
-        super.viewWillDisappear(animated)
-    }
-
-    override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent) {
-        if motion == .MotionShake {
-            self.gradientView.changeGradient(true)
-            AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
-        }
-        super.motionBegan(motion, withEvent: event)
-    }
-    
+        let gradient = self.imageFromCurrentGradient()
+        self.showActivityControllerForImage(gradient)
+    }
+    
+    func infoPressed (button : UIButton) {
+        NSLog("Show some info")
+    }
+    
+    private func showActivityControllerForImage(image : UIImage) {
+        let activityController = UIActivityViewController(activityItems: [image], applicationActivities: nil)
+        if activityController.respondsToSelector("popoverPresentationController") {
+            activityController.popoverPresentationController?.sourceView = self.saveIndicator
+            activityController.popoverPresentationController?.sourceRect = CGRectInset(self.saveIndicator.bounds, 0, -10)
+            activityController.popoverPresentationController?.permittedArrowDirections = .Up
+        }
+        self.presentViewController(activityController, animated: true, completion: nil)
+    }
 }
 

        btn.titleLabel?.lineBreakMode = .ByWordWrapping
        
        btn.contentVerticalAlignment = .Center
        btn.setTitle(NSLocalizedString("saved", comment: "").uppercaseString, forState: .Normal)
        btn.addTarget(self, action: "sharePressed:", forControlEvents: .TouchUpInside)
        return btn
    }()
    
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer!, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer!) -> Bool {
        return true

        self.transform = CGAffineTransformMakeScale(0.01, 0.01)
        }, completion: completion)
    }
    
    func fadeIn(completion : ((Bool) -> ())?) {
        UIView.animateWithDuration(fadeAnimationDuration(), delay: 0.0, options: .BeginFromCurrentState, animations: { () -> Void in
            self.alpha = 1.0
            }, completion: completion)
    }
    
    func fadeOut(completion : ((Bool) -> ())?) {
        UIView.animateWithDuration(fadeAnimationDuration(), delay: 0.0, options: .BeginFromCurrentState, animations: { () -> Void in
            self.alpha = 0.0
            }, completion: completion)
    }
}

class ViewController: UIViewController, UIScrollViewDelegate, UIGestureRecognizerDelegate {
    
    lazy private var scrollView : UIScrollView = {
        var scrollView = UIScrollView(frame: CGRectZero)
        scrollView.maximumZoomScale = CGFloat.max
        scrollView.bouncesZoom = false
        scrollView.bounces = false
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        scrollView.delegate = self
        return scrollView
    }()
    
    lazy private var gradientView : GradientView = {
        return GradientView(frame: CGRectZero)
    }()
    
    lazy private var saveIndicator : UIButton = {
        let btn = UIButton(frame: CGRectMake(0, 0, 100.0, 100.0))
        btn.layer.cornerRadius = 50.0
        btn.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.6)
        btn.tintColor = UIColor.whiteColor()
        
        btn.titleLabel?.numberOfLines = 0
        btn.titleLabel?.textAlignment = .Center
