NSUrl CreateApplicationSupportDirectory()
        {
            NSFileManager fileManager = NSFileManager.DefaultManager;

            NSUrl[] URLs = fileManager.GetUrls(NSSearchPathDirectory.ApplicationSupportDirectory, NSSearchPathDomain.User);
            NSUrl   url  = URLs [URLs.Length - 1];

            url = url.Append(ApplicationDocumentsDirectoryName, false);
            NSError error;

            NSDictionary properties = url.GetResourceValues(new NSString[] { NSUrl.IsDirectoryKey }, out error);

            if (properties != null)
            {
                var isDirectoryNumber = (NSNumber)properties [NSUrl.IsDirectoryKey];
                if (isDirectoryNumber != null && !isDirectoryNumber.BoolValue)
                {
                    Console.WriteLine("Could not access the application data folder.");
                    return(null);
                }
            }
            else if (error.Code == (int)NSCocoaError.FileReadNoSuchFile)
            {
                bool ok = fileManager.CreateDirectory(url.Path, true, null);
                if (!ok)
                {
                    Console.WriteLine("Error occured: {0}", error.LocalizedDescription);
                    return(null);
                }
            }

            return(url);
        }
Example #2
0
        public Task <bool> Move(string newPath)
        {
            var tcs = new TaskCompletionSource <bool> ();

            NSUrl newUrl = documentsUrl.Append(newPath, false);

            Task.Factory.StartNew(() => {
                var c = new NSFileCoordinator(filePresenterOrNil: null);
                NSError coordErr;
                c.CoordinateWriteWrite(LocalUrl, NSFileCoordinatorWritingOptions.ForMoving, newUrl, NSFileCoordinatorWritingOptions.ForReplacing, out coordErr, (url1, url2) => {
                    bool r = false;
                    using (var m = new NSFileManager()) {
                        NSError remErr;
                        r = m.Move(url1, url2, out remErr);
                        if (r)
                        {
                            Path      = newPath;
                            LocalUrl  = newUrl;
                            LocalPath = LocalUrl.Path;
                        }
                    }
                    tcs.SetResult(r);
                });
            });

            return(tcs.Task);
        }
        public override void DidFinishDownloading(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location)
        {
            Console.WriteLine("Finished");
            Console.WriteLine("File downloaded in : {0}", location);
            NSFileManager fileManager = NSFileManager.DefaultManager;

            var   URLs = fileManager.GetUrls(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User);
            NSUrl documentsDictionry = URLs[0];

            NSUrl   originalURL    = downloadTask.OriginalRequest.Url;
            NSUrl   destinationURL = documentsDictionry.Append(controller.FileName, false);
            NSError removeCopy;
            NSError errorCopy;

            fileManager.Remove(destinationURL, out removeCopy);
            bool success = fileManager.Copy(location, destinationURL, out errorCopy);

            if (success)
            {
                controller.Dismiss();
            }
            else
            {
                Console.WriteLine("Error during the copy: {0}", errorCopy.LocalizedDescription);
            }
        }
        /**
         * Move the downloaded file to it's destination
         */
        public bool MoveDownloadedFile(DownloadFileImplementation file, NSUrl location, string destinationPathName)
        {
            var     fileManager = NSFileManager.DefaultManager;
            NSError removeCopy;
            NSError errorCopy;
            bool    success = false;

            string nameFile           = destinationPathName.Split('/').Last();
            var    URLs               = fileManager.GetUrls(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User);
            NSUrl  documentsDictionry = URLs.First();
            NSUrl  destinationURL     = documentsDictionry.Append(nameFile, false);

            try
            {
                fileManager.Remove(destinationURL, out removeCopy);
                success = fileManager.Copy(location, destinationURL, out errorCopy);
                if (!success)
                {
                    file.StatusDetails = errorCopy.LocalizedDescription;
                    file.Status        = DownloadFileStatus.FAILED;
                }
                else
                {
                    file.DestinationPathName = destinationURL.Path;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debugger.Break();
            }

            return(success);
        }
        private NSUrl GetContentKeyDirectory()
        {
            var documentPath = NSSearchPath.GetDirectories(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User, true).FirstOrDefault();

            if (documentPath == null)
            {
                throw new Exception("Unable to determine library URL");
            }

            var documentUrl = new NSUrl(documentPath, true);

            var contentKeyDirectory = documentUrl.Append(".keys", true);

            if (!NSFileManager.DefaultManager.FileExists(contentKeyDirectory.Path))
            {
                try
                {
                    NSFileManager.DefaultManager.CreateDirectory(contentKeyDirectory.AbsoluteString, false, null);
                }
                catch (Exception ex)
                {
                    throw new Exception($"Unable to create directory for content keys at path: {contentKeyDirectory.Path}", ex);
                }
            }

            return(contentKeyDirectory);
        }
Example #6
0
        public override void DidFinishDownloading(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location)
        {
            Console.WriteLine("Finished");
            Console.WriteLine("File downloaded in : {0}", location);
            NSFileManager fileManager = NSFileManager.DefaultManager;

            var   URLs = fileManager.GetUrls(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User);
            NSUrl documentsDictionry = URLs [0];

            NSUrl   originalURL    = downloadTask.OriginalRequest.Url;
            NSUrl   destinationURL = documentsDictionry.Append("image1.png", false);
            NSError removeCopy;
            NSError errorCopy;

            fileManager.Remove(destinationURL, out removeCopy);
            bool success = fileManager.Copy(location, destinationURL, out errorCopy);

            if (success)
            {
                // we do not need to be on the main/UI thread to load the UIImage
                UIImage image = UIImage.FromFile(destinationURL.Path);
                InvokeOnMainThread(() => {
                    controller.ImageView.Image     = image;
                    controller.ImageView.Hidden    = false;
                    controller.ProgressView.Hidden = true;
                });
            }
            else
            {
                Console.WriteLine("Error during the copy: {0}", errorCopy.LocalizedDescription);
            }
        }
Example #7
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Imagine this using https://docs.microsoft.com/en-us/xamarin/ios/app-fundamentals/backgrounding/ios-backgrounding-techniques/updating-an-application-in-the-background
            // instead of just on launch

            text      = new UITextView(new CoreGraphics.CGRect(200, 200, 200, 100));
            text.Text = "Before";
            View.AddSubview(text);

            NSUrl url = NSFileManager.DefaultManager.GetContainerUrl("group.com.xamarin.sample.TestApplication");

            url = url.Append("testAppState.json", false);
            System.IO.File.WriteAllText(url.Path, TestData.GetJson());

            var proxy = new WidgetCenterProxy();

            proxy.ReloadAllTimeLines();
            proxy.GetCurrentConfigurationsWithCompletion((widgets) => {
                foreach (var widget in widgets)
                {
                    Console.WriteLine(widget.Kind + " " + widget.Family);
                }

                InvokeOnMainThread(() => {
                    text.Text = "After widgets " + widgets.Count;
                });
            }
                                                         );
        }
Example #8
0
            public override async Task <StorageFile> CreateFileAsync(string desiredName, CreationCollisionOption options, CancellationToken cancellationToken)
            {
                using var _ = _nsUrl.BeginSecurityScopedAccess();
                var path       = IOPath.Combine(Path, desiredName);
                var actualName = desiredName;

                switch (options)
                {
                case CreationCollisionOption.FailIfExists:
                    if (Directory.Exists(path) || File.Exists(path))
                    {
                        throw new UnauthorizedAccessException("There is already an item with the same name.");
                    }
                    break;

                case CreationCollisionOption.GenerateUniqueName:
                    actualName = await FindAvailableNumberedFileNameAsync(desiredName);

                    break;

                case CreationCollisionOption.OpenIfExists:
                    if (Directory.Exists(path))
                    {
                        throw new UnauthorizedAccessException("There is already a folder with the same name.");
                    }
                    break;

                case CreationCollisionOption.ReplaceExisting:
                    if (Directory.Exists(path))
                    {
                        throw new UnauthorizedAccessException("There is already a folder with the same name.");
                    }

                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(options));
                }

                var actualPath = IOPath.Combine(Path, actualName);

                if (!File.Exists(actualPath))
                {
                    File.Create(actualPath).Close();
                }

                return(StorageFile.GetFromSecurityScopedUrl(_nsUrl.Append(actualName, false), Owner));
            }
        static NSUrl GetCloudUrlFor(NSUrl localUrl)
        {
            string destinationFileName = localUrl.LastPathComponent;
            NSUrl  cloudDirectory      = NSFileManager.DefaultManager.GetUrlForUbiquityContainer(null);
            NSUrl  destinationURL      = cloudDirectory.Append(destinationFileName, false);

            return(destinationURL);
        }
Example #10
0
 public CloudFile(string path, NSUrl documentsUrl)
 {
     this.documentsUrl = documentsUrl;
     Path             = path;
     LocalUrl         = documentsUrl.Append(Path, false);
     LocalPath        = LocalUrl.Path;
     ModifiedTime     = DateTime.UtcNow;
     IsDownloaded     = true;
     DownloadProgress = 1;
 }
        void PresentAuthenticationController()
        {
            var authenticationController = new AuthenticationController()
            {
                Title                = "Sign in",
                Delegate             = this,
                WebViewConfiguration = _webViewConfiguration,
                Url = URL.Append("sign-in", false)
            };

            var authNavigationController = new UINavigationController(authenticationController);

            PresentViewController(authNavigationController, true, null);
        }
Example #12
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Imagine this using https://docs.microsoft.com/en-us/xamarin/ios/app-fundamentals/backgrounding/ios-backgrounding-techniques/updating-an-application-in-the-background
            // instead of just on launch

            text      = new UITextView(new CoreGraphics.CGRect(200, 200, 200, 100));
            text.Text = "Before";
            View.AddSubview(text);

            NSUrl url = NSFileManager.DefaultManager.GetContainerUrl("group.com.xamarin.sample.TestApplication");

            url = url.Append("testAppState.json", false);
            System.IO.File.WriteAllText(url.Path, TestData.GetJson());

            text.Text = "After";
        }
    public string CreateGif(string frame1Path, string frame2Path, string frame3Path, string frame4Path, string webId, string path = "")
    {
        List <UIImage> listOfFrame = new List <UIImage>();
        UIImage        image1      = new UIImage(frame1Path);

        listOfFrame.Add(image1);
        UIImage image2 = new UIImage(frame2Path);

        listOfFrame.Add(image2);
        UIImage image3 = new UIImage(frame3Path);

        listOfFrame.Add(image3);
        UIImage image4 = new UIImage(frame4Path);

        listOfFrame.Add(image4);
        NSMutableDictionary fileProperties = new NSMutableDictionary
        {
            { CGImageProperties.GIFLoopCount, new NSNumber(1) }
        };
        NSUrl documentsDirectoryUrl = NSFileManager.DefaultManager.GetUrl(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User, null, true, out _);
        NSUrl fileUrl = documentsDirectoryUrl.Append(webId + ".gif", false);

        var destination = CGImageDestination.Create(fileUrl, MobileCoreServices.UTType.GIF, 4);

        destination.SetProperties(fileProperties);
        foreach (var frame in listOfFrame)
        {
            //difference is here, i create a var option and i set the
            //GifDictionary
            var options = new CGImageDestinationOptions();
            options.GifDictionary = new NSMutableDictionary();
            options.GifDictionary[CGImageProperties.GIFDelayTime] = new NSNumber(1f);
            var cgImage = frame.CGImage;
            if (cgImage != null)
            {
                destination.AddImage(cgImage, options);
            }
        }
        if (!destination.Close())
        {
            Console.WriteLine("Failed to finalize the image destination");
        }
        return(fileUrl.Path);
    }
    void Done (object sender, EventArgs args)
    {
      var syncPoint = UrlField.Text;
      if (String.IsNullOrWhiteSpace (syncPoint)) {
        Pop ();
        return;
      }

      var remoteUrl = new NSUrl (syncPoint);

      // If user just enters the server URL, fill in a default database name:
      if (String.IsNullOrWhiteSpace (remoteUrl.Path) || remoteUrl.Path == "/") {
        remoteUrl = remoteUrl.Append ("grocery-sync", false);
        syncPoint = remoteUrl.AbsoluteString;
      }

      NSUserDefaults.StandardUserDefaults.SetString (syncPoint, SyncUrlKey);

      Pop ();
    }
Example #15
0
        private bool FileExistenceCheck(IDownloadFile i)
        {
            var downloadFile        = (DownloadFileImplementation)i;
            var fileManager         = NSFileManager.DefaultManager;
            var destinationPathName = downloadFile.DestinationPathName;

            string nameFile           = destinationPathName.Split('/').Last();
            var    URLs               = fileManager.GetUrls(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User);
            NSUrl  documentsDictionry = URLs.First();
            NSUrl  destinationURL     = documentsDictionry.Append(nameFile, false);

            if (fileManager.FileExists(destinationURL.Path))
            {
                downloadFile.DestinationPathName = destinationURL.Path;
                downloadFile.StatusDetails       = default(string);
                downloadFile.Status = DownloadFileStatus.COMPLETED;
                return(true);
            }
            return(false);
        }
Example #16
0
        void UpdateDocumentStorageContainerURL(object sender, EventArgs e)
        {
            NSUrl oldDocumentsDirectory = DocumentsDirectory;

            NSFileManager        fileManager   = NSFileManager.DefaultManager;
            NSNotificationCenter defaultCenter = NSNotificationCenter.DefaultCenter;

            if (AppConfig.SharedAppConfiguration.StorageOption != StorageType.Cloud)
            {
                DocumentsDirectory = GetFirstDocumentDirectoryUrlForUserDomain();
                RaiseStorageChoiceChanged();
            }
            else
            {
                ThreadPool.QueueUserWorkItem(_ => {
                    // The call to GetUrlForUbiquityContainer should be on a background thread.
                    // You can pass null to retrieve the URL for the first container in the list
                    // For more information visit https://developer.apple.com/library/ios/documentation/General/Conceptual/iCloudDesignGuide/Chapters/iCloudFundametals.html#//apple_ref/doc/uid/TP40012094-CH6-SW1
                    NSUrl cloudDirectory = fileManager.GetUrlForUbiquityContainer(null);

                    InvokeOnMainThread(() => {
                        DocumentsDirectory = cloudDirectory.Append("Documents", true);

                        NSError error;
                        NSUrl[] localDocuments = fileManager.GetDirectoryContent(oldDocumentsDirectory,
                                                                                 null, NSDirectoryEnumerationOptions.SkipsPackageDescendants, out error);

                        foreach (NSUrl url in localDocuments)
                        {
                            string ext = Path.GetExtension(url.AbsoluteString).Replace(".", string.Empty);
                            if (ext == AppConfig.ListerFileExtension)
                            {
                                MakeItemUbiquitousAtURL(url);
                            }
                        }

                        RaiseStorageChoiceChanged();
                    });
                });
            }
        }
        public void DidFinishDownloading(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location)
        {
            Console.WriteLine("Finished");
            Console.WriteLine("File downloaded in : {0}", location);
            NSFileManager fileManager = NSFileManager.DefaultManager;

            var   URLs = fileManager.GetUrls(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User);
            NSUrl documentsDictionry = URLs[0];

            NSUrl   originalURL    = downloadTask.OriginalRequest.Url;
            NSUrl   destinationURL = documentsDictionry.Append("image1.png", false);
            NSError removeCopy;
            NSError errorCopy;

            fileManager.Remove(destinationURL, out removeCopy);
            bool success = fileManager.Copy(location, destinationURL, out errorCopy);

            if (success)
            {
                // we do not need to be on the main/UI thread to load the UIImage
                UIImage image = UIImage.FromFile(destinationURL.Path);
                InvokeOnMainThread(() => {
                    Console.WriteLine("Image downloaded successfully.");

                    var screen = UIScreen.MainScreen.Bounds;

                    UIImageView imageView = new UIImageView();
                    imageView.Image       = image;
                    imageView.Frame       = new CGRect(0, 0, screen.Size.Width, screen.Size.Height);

                    controller.Add(imageView);

                    Console.WriteLine("Added image to ImageView");
                });
            }
            else
            {
                Console.WriteLine("Error during the copy: {0}", errorCopy.LocalizedDescription);
            }
        }
        static Task <NSUrl> CopyToDocumentsDirectoryAsync(NSUrl fromUrl)
        {
            var tcs = new TaskCompletionSource <NSUrl>();

            NSUrl localDocDir = GetDocumentDirectoryUrl();
            NSUrl toURL       = localDocDir.Append(fromUrl.LastPathComponent, false);

            bool              success = false;
            NSError           coordinationError, copyError = null;
            NSFileCoordinator fileCoordinator = new NSFileCoordinator();

            ThreadPool.QueueUserWorkItem(_ => {
                fileCoordinator.CoordinateReadWrite(fromUrl, 0, toURL, NSFileCoordinatorWritingOptions.ForReplacing, out coordinationError, (src, dst) => {
                    NSFileManager fileManager = new NSFileManager();
                    success = fileManager.Copy(src, dst, out copyError);

                    if (success)
                    {
                        var attributes = new NSFileAttributes {
                            FileExtensionHidden = true
                        };
                        fileManager.SetAttributes(attributes, dst.Path);
                        Console.WriteLine("Copied file: {0} to: {1}.", src.AbsoluteString, dst.AbsoluteString);
                    }
                });

                // In your app, handle this gracefully.
                if (!success)
                {
                    Console.WriteLine("Couldn't copy file: {0} to: {1}. Error: {2}.", fromUrl.AbsoluteString,
                                      toURL.AbsoluteString, (coordinationError ?? copyError).Description);
                }

                tcs.SetResult(toURL);
            });

            return(tcs.Task);
        }
Example #19
0
        void Done(object sender, EventArgs args)
        {
            var syncPoint = UrlField.Text;

            if (String.IsNullOrWhiteSpace(syncPoint))
            {
                Pop();
                return;
            }

            var remoteUrl = new NSUrl(syncPoint);

            // If user just enters the server URL, fill in a default database name:
            if (String.IsNullOrWhiteSpace(remoteUrl.Path) || remoteUrl.Path == "/")
            {
                remoteUrl = remoteUrl.Append("grocery-sync", false);
                syncPoint = remoteUrl.AbsoluteString;
            }

            NSUserDefaults.StandardUserDefaults.SetString(syncPoint, SyncUrlKey);

            Pop();
        }
Example #20
0
 public string GetLocalPath(string path)
 {
     return(documentsUrl.Append(path, false).Path);
 }
Example #21
0
		public CloudFile (string path, NSUrl documentsUrl)
		{
			this.documentsUrl = documentsUrl;
			Path = path;
			LocalUrl = documentsUrl.Append (Path, false);
			LocalPath = LocalUrl.Path;
			ModifiedTime = DateTime.UtcNow;
			IsDownloaded = true;
			DownloadProgress = 1;
		}
Example #22
0
        public Task <MediaResult> OpenMediaPickerAsync(MediaType fileType)
        {
            var task = new TaskCompletionSource <MediaResult>();

            try
            {
                if (fileType == MediaType.Image)
                {
                    var picker = new ImagePickerController();
                    picker.OpenImagePickerAsync(GetController(), (nsdict) =>
                    {
                        if (nsdict == null)
                        {
                            task.SetResult(new MediaResult(false)
                            {
                                Message = "Cancelled."
                            });
                            return;
                        }
                        try
                        {
                            var photoUrl   = nsdict.ValueForKey(new NSString("UIImagePickerControllerReferenceURL")) as NSUrl;
                            var imageName  = photoUrl.LastPathComponent;
                            var dir        = NSSearchPath.GetDirectories(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User, true).FirstOrDefault();
                            var picUrl     = new NSUrl(dir, true);
                            var localPath  = picUrl.Append(imageName, false);
                            var localPath1 = picUrl.Append(imageName, true);
                            //task.SetResult(new MediaResult(true) { FilePath = localPath.ToString()});
                            var photo = nsdict.ValueForKey(new NSString("UIImagePickerControllerOriginalImage")) as UIImage;
                            if (photo != null)
                            {
                                string fileName = System.IO.Path.Combine(GetPublicDirectoryPath(), imageName);
                                NSError err     = null;
                                if (photo.AsJPEG().Save(fileName, false, out err))
                                {
                                    task.SetResult(new MediaResult(true)
                                    {
                                        FilePath = fileName
                                    });
                                }
                                else
                                {
                                    task.SetResult(null);
                                }
                            }
                            else
                            {
                                task.SetResult(null);
                            }
                        }

                        catch (Exception ex)
                        {
                            task.SetResult(new MediaResult(false)
                            {
                                FilePath = ex.Message
                            });
                        }
                    });
                }
                else if (fileType == MediaType.Video)
                {
                    var picker = new ImagePickerController();
                    picker.OpenVideoPickerAsync(GetController(), (nsdict) =>
                    {
                        if (nsdict == null)
                        {
                            task.SetResult(new MediaResult(false)
                            {
                                Message = "Cancelled."
                            });
                            return;
                        }
                        try
                        {
                            var mediaUrl = nsdict.ValueForKey(new NSString("UIImagePickerControllerMediaURL")) as NSUrl;
                            task.SetResult(new MediaResult(true)
                            {
                                FilePath = mediaUrl.ToString()
                            });
                        }
                        catch (Exception ex)
                        {
                            task.SetResult(new MediaResult(false)
                            {
                                FilePath = ex.Message
                            });
                        }
                    });
                }
                else if (fileType == MediaType.Documents)
                {
                    var picker = new ImagePickerController();
                    picker.OpenDoc(GetController(), (obj) =>
                    {
                        if (obj == null)
                        {
                            task.SetResult(new MediaResult(false)
                            {
                                Message = "Cancelled."
                            });
                            return;
                        }
                        try
                        {
                            var aa      = obj.AbsoluteUrl;
                            var isExist = System.IO.File.Exists(aa.AbsoluteString);
                            task.SetResult(new MediaResult(true)
                            {
                                FilePath = aa.Path
                            });
                        }
                        catch (Exception ex)
                        {
                            task.SetResult(new MediaResult(false)
                            {
                                FilePath = ex.Message
                            });
                        }
                    });
                }

                else
                {
                    var picker = new AudioPickerController();
                    picker.OpenAudioPickerAsync(GetController(), (nsurl) =>
                    {
                        if (nsurl == null)
                        {
                            task.SetResult(new MediaResult(false)
                            {
                                Message = "Cancelled."
                            });
                            return;
                        }
                        task.SetResult(new MediaResult(true)
                        {
                            FilePath = nsurl.ToString()
                        });
                    });
                }
            }
            catch (Exception ex)
            {
                task.SetResult(new MediaResult(false)
                {
                    Message = ex.Message
                });
            }
            return(task.Task);
        }
Example #23
0
        public KSCatalogViewController() : base(UITableViewStyle.Grouped, null)
        {
            PSPDFKitGlobal.LogLevel = PSPDFLogLevel.Verbose;

            // Add some custom localization to ensure the bindings work.
            PSPDFKitGlobal.Localize("en", new NameValueCollection
            {
                { "Outline", "File Content" },
                { "Bookmarks", "Remember" }
            });

            // Call cache method to ensure the bindings for the cache work.
            var oPdfCache = PSPDFCache.SharedCache;

            oPdfCache.ClearCache( );

            PSPDFKitGlobal.LogLevel = PSPDFLogLevel.Info;

            NSUrl samplesURL   = NSBundle.MainBundle.ResourceUrl.Append("Samples", true);
            NSUrl hackerMagURL = samplesURL.Append(HackerMagazineExample, false);
            NSUrl annotTestURL = samplesURL.Append(AnnotTestExample, false);


            this.Root = new RootElement("KSCatalogViewController")
            {
                new Section("Full example apps", "Can be used as a template for your own apps.")
                {
                    // PDF playground.
                    new StringElement("PSPDFViewController playground", () =>
                    {
                        var doc             = new PSPDFDocument(hackerMagURL);
                        var kioskController = new KSKioskViewController(doc);

                        kioskController.StatusBarStyleSetting = PSPDFStatusBarStyleSetting.Default;
                        this.NavigationController.PushViewController(kioskController, true);
                    }),
                },

                new Section("Customizing")
                {
                    // Combines various view controllers in a tab bar controller.
                    new StringElement("Combine search, TOC and bookmarks", () =>
                    {
                        var doc = new PSPDFDocument(hackerMagURL);

                        // Don't use PSPDFVieController directly but a subclass that allows attaching to ViewDidDisappear in order to clear
                        // the RightBarButtonItems property. Otherwise the tabBarBtn would keep a reference to the PSPDFViewController and the instances
                        // would never be freed.

                        //var controller = new PSPDFViewController(doc);
                        var controller = new KSKioskViewController(doc);
                        //controller.ViewDisappeared += (sender, args) => controller.RightBarButtonItems = new PSPDFBarButtonItem[0];

                        var tabBarController = new KSCombinedTabBarController(controller, doc);

                        var tabBarBtn = new KSBarButtonItem(controller)
                        {
                            Title = "UITabBarController",
                            Style = UIBarButtonItemStyle.Bordered
                        };
                        tabBarBtn.Clicked += (object sender, EventArgs e) => controller.PresentViewControllerModalOrPopover(tabBarController, true, false, true, tabBarBtn, null);

                        controller.RightBarButtonItems = new PSPDFBarButtonItem[] { controller.AnnotationButtonItem, controller.BookmarkButtonItem, tabBarBtn };

                        var classDic = new NSMutableDictionary();
                        classDic.LowlevelSetObject(new Class(typeof(KSInkAnnotation)).Handle, new Class(typeof(PSPDFInkAnnotation)).Handle);
                        classDic.LowlevelSetObject(new Class(typeof(KSNoteAnnotation)).Handle, new Class(typeof(PSPDFNoteAnnotation)).Handle);
                        classDic.LowlevelSetObject(new Class(typeof(KSHighlightAnnotation)).Handle, new Class(typeof(PSPDFHighlightAnnotation)).Handle);
                        doc.OverrideClassNames = classDic;

                        this.NavigationController.PushViewController(controller, true);
                    }),

                    // Shows an alert when tapping a link annotation.
                    new StringElement("Custom reaction on annotation links", () =>
                    {
                        var doc             = new PSPDFDocument(hackerMagURL);
                        var controller      = new PSPDFViewController(doc);
                        controller.Delegate = new KSCatchTappingLinkDelegate();
                        // There are link annotations on page 2.
                        controller.SetPageAnimated(1, false);
                        this.NavigationController.PushViewController(controller, true);
                    })
                },

                new Section("Subclassing")
                {
                    // Subclassing PSPDFAnnotationToolbar
                    new StringElement("Subclass annotation toolbar and drawing toolbar", () =>
                    {
                        var doc        = new PSPDFDocument(hackerMagURL);
                        var controller = new PSPDFViewController(doc);

                        var barButtons = new List <PSPDFBarButtonItem>(controller.RightBarButtonItems);
                        barButtons.Add(controller.AnnotationButtonItem);
                        controller.RightBarButtonItems = barButtons.ToArray();

                        var classDic = new NSMutableDictionary();
                        classDic.LowlevelSetObject(new Class(typeof(KSAnnotationToolbar)).Handle, new Class(typeof(PSPDFAnnotationToolbar)).Handle);
                        controller.OverrideClassNames = classDic;

                        this.NavigationController.PushViewController(controller, true);
                    }),

                    // Demonstrates always visible vertical toolbar.
                    new StringElement("Vertical always-visible annotation bar", () =>
                    {
                        var doc        = new PSPDFDocument(hackerMagURL);
                        var controller = new KSExampleAnnotationViewController(doc);

                        this.NavigationController.PushViewController(controller, true);
                    }),

                    // Tests potential binding issue when subclassing PSPDFViewController
                    new StringElement("PSPDFViewController with NULL document", () =>
                    {
                        var doc             = new PSPDFDocument(hackerMagURL);
                        var controller      = new KSNoDocumentPDFViewController();
                        controller.Document = doc;
                        this.NavigationController.PushViewController(controller, true);
                    }),

                    // Demonstrates capturing bookmark set/remove.
                    new StringElement("Capture bookmarks", () =>
                    {
                        var doc = new PSPDFDocument(hackerMagURL);

                        // Create an entry for overriding the default bookmark parser.
                        var classDic = new NSMutableDictionary();
                        classDic.LowlevelSetObject(new Class(typeof(KSBookmarkParser)).Handle, new Class(typeof(PSPDFBookmarkParser)).Handle);
                        doc.OverrideClassNames = classDic;

                        var controller = new PSPDFViewController(doc);
                        controller.RightBarButtonItems = new PSPDFBarButtonItem[]
                        {
                            controller.BookmarkButtonItem,
                            controller.SearchButtonItem,
                            controller.OutlineButtonItem,
                            controller.ViewModeButtonItem
                        };
                        this.NavigationController.PushViewController(controller, true);
                    }),

                    // Demonstrates custom annotation provider.
                    new StringElement("Custom Annotation Provider", () =>
                    {
                        var doc = new PSPDFDocument(hackerMagURL);
                        doc.SetDidCreateDocumentProviderBlock(delegate(PSPDFDocumentProvider documentProvider)
                        {
                            documentProvider.AnnotationParser.AnnotationProviders = new NSObject[]
                            {
                                new KSCustomAnnotationProvider(),
                                documentProvider.AnnotationParser.FileAnnotationProvider
                            };
                        });

                        var controller = new PSPDFViewController(doc);
                        this.NavigationController.PushViewController(controller, true);
                    }),

                    // Subclasses PDPFFileAnnotationProvider and injects additional annotations.
                    // This example demonstrates:
                    // * Make all built in annotations (those embedded in the PDF) immutable.
                    // * All annotations added by the user can be modified.
                    // * Workaround for PSPDFKit bug where the text of a non-editable annotation can still be changed.
                    // * Immediate callback if an annotation has been changed.
                    new StringElement("Subclass PSPDFFileAnnotationProvider", () =>
                    {
                        var controller = new PSPDFViewController();
                        var barButtons = new List <PSPDFBarButtonItem>(controller.RightBarButtonItems);
                        barButtons.Add(controller.AnnotationButtonItem);
                        controller.RightBarButtonItems = barButtons.ToArray();
                        controller.SetPageAnimated(2, false);

                        controller.PageMode        = PSPDFPageMode.Automatic;
                        controller.PageTransition  = PSPDFPageTransition.ScrollContinuous;
                        controller.ScrollDirection = PSPDFScrollDirection.Horizontal;

                        var classDic = new NSMutableDictionary();
                        classDic.LowlevelSetObject(new Class(typeof(KSNoteAnnotationController)).Handle, new Class(typeof(PSPDFNoteAnnotationController)).Handle);
                        controller.OverrideClassNames = classDic;

                        this.NavigationController.PushViewController(controller, true);

                        var doc = new KSPDFDocument(hackerMagURL);
                        //var doc = new PSPDFDocument();
                        //var doc = new PSPDFDocument(annotTestURL);

                        // Create an entry for overriding the file annotation provider.
                        classDic = new NSMutableDictionary();
                        classDic.LowlevelSetObject(new Class(typeof(KSFileAnnotationProvider)).Handle, new Class(typeof(PSPDFFileAnnotationProvider)).Handle);
                        classDic.LowlevelSetObject(new Class(typeof(KSInkAnnotation)).Handle, new Class(typeof(PSPDFInkAnnotation)).Handle);
                        classDic.LowlevelSetObject(new Class(typeof(KSNoteAnnotation)).Handle, new Class(typeof(PSPDFNoteAnnotation)).Handle);
                        classDic.LowlevelSetObject(new Class(typeof(KSHighlightAnnotation)).Handle, new Class(typeof(PSPDFHighlightAnnotation)).Handle);
                        doc.OverrideClassNames = classDic;

                        controller.Document = doc;
                    }),

                    // Set editable annotation types
                    new StringElement("Set editable annotation types", () =>
                    {
                        var doc        = new PSPDFDocument(hackerMagURL);
                        var controller = new PSPDFViewController(doc);
                        controller.RightBarButtonItems = new PSPDFBarButtonItem[]
                        {
                            controller.AnnotationButtonItem
                        };

                        var set = new NSMutableSet();
                        set.Add(PSPDFAnnotation.PSPDFAnnotationTypeStringInk);
                        set.Add(PSPDFAnnotation.PSPDFAnnotationTypeStringNote);
                        set.Add(PSPDFAnnotation.PSPDFAnnotationTypeStringUnderline);

                        controller.AnnotationButtonItem.AnnotationToolbar.EditableAnnotationTypes = set.ToNSOrderedSet();
                        this.NavigationController.PushViewController(controller, true);
                    })
                }
            };
        }
        void Done(object sender, EventArgs args)
        {
            var syncPoint = UrlField.Text;
            if (String.IsNullOrWhiteSpace(syncPoint)) {
                Pop ();
                return;
            }

            var remoteUrl = new NSUrl (syncPoint);

            if (remoteUrl.Scheme == "http") {
                var alert = new UIAlertView (
                    "Invalid Url",
                    "You entered an invalid URL. Do you want to fix it or revert back to what it was before?",
                    null,
                    "Fix It",
                    "Revert"
                );

                alert.Dismissed += (alertView, e) => {
                    if (e.ButtonIndex > 0) Pop();  // Go back to the main screen without saving the URL
                };

                alert.Show ();
            } else {
                // If user just enters the server URL, fill in a default database name:
                if (String.IsNullOrWhiteSpace(remoteUrl.Path) || remoteUrl.Path == "/")
                {
                    remoteUrl = remoteUrl.Append("grocery-sync", false);
                    syncPoint = remoteUrl.AbsoluteString;
                }
                NSUserDefaults.StandardUserDefaults.SetString (syncPoint, SyncUrlKey);
                Pop();
            }
        }