[Libreoffice-commits] core.git: 3 commits - ios/iosremote

Siqi LIU me at siqi.fr
Mon Sep 9 05:36:49 PDT 2013


 dev/null                                                                       |binary
 ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsViewController.h     |   84 +
 ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m     |  796 ++++++++++
 ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.h  |   30 
 ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.m  |  144 +
 ios/iosremote/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.h |   36 
 ios/iosremote/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m |  202 ++
 ios/iosremote/InAppSettingsKit/Controllers/IASKViewController.h                |   26 
 ios/iosremote/InAppSettingsKit/Models/IASKSettingsReader.h                     |  144 +
 ios/iosremote/InAppSettingsKit/Models/IASKSettingsReader.m                     |  266 +++
 ios/iosremote/InAppSettingsKit/Models/IASKSettingsStore.h                      |   39 
 ios/iosremote/InAppSettingsKit/Models/IASKSettingsStore.m                      |   68 
 ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreFile.h                  |   28 
 ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreFile.m                  |   53 
 ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.h          |   25 
 ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.m          |   67 
 ios/iosremote/InAppSettingsKit/Models/IASKSpecifier.h                          |   59 
 ios/iosremote/InAppSettingsKit/Models/IASKSpecifier.m                          |  239 +++
 ios/iosremote/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h           |   31 
 ios/iosremote/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m           |   71 
 ios/iosremote/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h        |   29 
 ios/iosremote/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.m        |   49 
 ios/iosremote/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.h       |   22 
 ios/iosremote/InAppSettingsKit/Views/IASKPSTitleValueSpecifierViewCell.m       |   57 
 ios/iosremote/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.h     |   29 
 ios/iosremote/InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.m     |   59 
 ios/iosremote/InAppSettingsKit/Views/IASKSlider.h                              |   26 
 ios/iosremote/InAppSettingsKit/Views/IASKSlider.m                              |   29 
 ios/iosremote/InAppSettingsKit/Views/IASKSwitch.h                              |   26 
 ios/iosremote/InAppSettingsKit/Views/IASKSwitch.m                              |   30 
 ios/iosremote/InAppSettingsKit/Views/IASKTextField.h                           |   26 
 ios/iosremote/InAppSettingsKit/Views/IASKTextField.m                           |   29 
 ios/iosremote/InAppSettingsKit/Xibs/IASKAppSettingsView.xib                    |  222 ++
 ios/iosremote/InAppSettingsKit/Xibs/IASKAppSettingsWebView.xib                 |  378 ++++
 ios/iosremote/InAppSettingsKit/Xibs/IASKPSSliderSpecifierViewCell.xib          |  251 +++
 ios/iosremote/InAppSettingsKit/Xibs/IASKPSTextFieldSpecifierViewCell.xib       |  254 +++
 ios/iosremote/InAppSettingsKit/Xibs/IASKPSToggleSwitchSpecifierViewCell.xib    |  237 ++
 ios/iosremote/InAppSettingsKit/Xibs/IASKSpecifierValuesView.xib                |  255 +++
 ios/iosremote/Settings.bundle/Root.plist                                       |  109 +
 ios/iosremote/Settings.bundle/en.lproj/Root.strings                            |binary
 ios/iosremote/UIView+Shadowing.h                                               |    1 
 ios/iosremote/UIView+Shadowing.m                                               |   10 
 ios/iosremote/UserDefaults.plist                                               |    4 
 ios/iosremote/en.lproj/iPad_autosize.storyboard                                |  451 +++--
 ios/iosremote/en.lproj/iPad_autosize.strings                                   |binary
 ios/iosremote/en.lproj/iPad_autosize_old.storyboard                            |  451 +++--
 ios/iosremote/fr.lproj/iPad_autosize.storyboard                                |  447 +++--
 ios/iosremote/fr.lproj/iPad_autosize.strings                                   |binary
 ios/iosremote/fr.lproj/iPad_autosize_old.storyboard                            |  447 +++--
 ios/iosremote/iosremote.xcodeproj/project.pbxproj                              |  190 ++
 ios/iosremote/iosremote/AppDelegate.h                                          |    3 
 ios/iosremote/iosremote/AppDelegate.m                                          |   13 
 ios/iosremote/iosremote/BasePresentationViewController.h                       |   18 
 ios/iosremote/iosremote/BasePresentationViewController.m                       |   95 -
 ios/iosremote/iosremote/Communication/Client.m                                 |    2 
 ios/iosremote/iosremote/Communication/CommunicationManager.m                   |    3 
 ios/iosremote/iosremote/ControlVariables.h                                     |    3 
 ios/iosremote/iosremote/HorizontalSlideCell.m                                  |    1 
 ios/iosremote/iosremote/Timer.h                                                |    4 
 ios/iosremote/iosremote/Timer.m                                                |   47 
 ios/iosremote/iosremote/UIViewController+LibOStyling.m                         |    1 
 ios/iosremote/iosremote/en.lproj/iPhone_autoSize.storyboard                    |  226 +-
 ios/iosremote/iosremote/en.lproj/iPhone_autoSize.strings                       |binary
 ios/iosremote/iosremote/en.lproj/iPhone_autoSize_old.storyboard                |  226 +-
 ios/iosremote/iosremote/fr.lproj/iPhone_autoSize.storyboard                    |  226 +-
 ios/iosremote/iosremote/fr.lproj/iPhone_autoSize.strings                       |binary
 ios/iosremote/iosremote/fr.lproj/iPhone_autoSize_old.storyboard                |  226 +-
 ios/iosremote/iosremote/iosremote-Prefix.pch                                   |    1 
 ios/iosremote/iosremote/serverList_vc.m                                        |    1 
 ios/iosremote/iosremote/slideShowPreviewTable_vc.h                             |   16 
 ios/iosremote/iosremote/slideShowPreviewTable_vc.m                             |  119 -
 ios/iosremote/iosremote/slideShowPreviewTable_vc_ipad.h                        |    1 
 ios/iosremote/iosremote/slideShowPreviewTable_vc_ipad.m                        |    7 
 ios/iosremote/iosremote/slideShowPreviewTable_vc_iphone.h                      |    1 
 ios/iosremote/iosremote/slideShowPreviewTable_vc_iphone.m                      |    1 
 ios/iosremote/iosremote/slideShowSwipeInList_ipad.m                            |    8 
 ios/iosremote/iosremote/slideShowSwipeInList_iphone.m                          |   18 
 ios/iosremote/iosremote/slideShow_vc_iphone.h                                  |    1 
 ios/iosremote/iosremote/slideShow_vc_iphone.m                                  |  143 -
 ios/iosremote/iosremote/stopWatch.m                                            |   46 
 ios/iosremote/iosremote/timer_clear_btn_dark.png                               |binary
 ios/iosremote/iosremote/timer_pause_btn_dark.png                               |binary
 ios/iosremote/iosremote/timer_pause_btn_dark at 2x.png                            |binary
 ios/iosremote/iosremote/timer_settime_btn_dark.png                             |binary
 ios/iosremote/iosremote/timer_settime_btn_dark at 2x.png                          |binary
 ios/iosremote/iosremote/timer_start_btn_dark.png                               |binary
 ios/iosremote/iosremote/timer_start_btn_dark at 2x.png                            |binary
 ios/iosremote/iosremote/zh-Hans.lproj/iPhone_autoSize.storyboard               |  226 +-
 ios/iosremote/iosremote/zh-Hans.lproj/iPhone_autoSize.strings                  |binary
 ios/iosremote/iosremote/zh-Hans.lproj/iPhone_autoSize_old.storyboard           |  226 +-
 ios/iosremote/zh-Hans.lproj/iPad_autosize.storyboard                           |  443 +++--
 ios/iosremote/zh-Hans.lproj/iPad_autosize.strings                              |binary
 ios/iosremote/zh-Hans.lproj/iPad_autosize_old.storyboard                       |  443 +++--
 93 files changed, 7699 insertions(+), 1622 deletions(-)

New commits:
commit 8a1f535c3dbc624b70ba85078ab058f4b4f97f1f
Author: Siqi LIU <me at siqi.fr>
Date:   Mon Sep 9 14:34:37 2013 +0200

    concentrate all config into one place
    
    Make use of InAppSettingKit, which allows both in-app setting and system-wide setting pane.
    Introduced more customization like default count-down timer duration & vibration & auto_start & default timing widget options
    
    Change-Id: Ida60b3b3f87a674795ee3ebddf14c71265196264

diff --git a/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsViewController.h b/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsViewController.h
new file mode 100755
index 0000000..e2d5b99
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsViewController.h
@@ -0,0 +1,84 @@
+//
+//  IASKAppSettingsViewController.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+#import <MessageUI/MessageUI.h>
+
+#import "IASKSettingsStore.h"
+#import "IASKViewController.h"
+
+ at class IASKSettingsReader;
+ at class IASKAppSettingsViewController;
+ at class IASKSpecifier;
+
+ at protocol IASKSettingsDelegate
+- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender;
+
+ at optional
+#pragma mark - UITableView header customization
+- (CGFloat) settingsViewController:(id<IASKViewController>)settingsViewController
+                         tableView:(UITableView *)tableView
+         heightForHeaderForSection:(NSInteger)section;
+- (UIView *) settingsViewController:(id<IASKViewController>)settingsViewController
+                          tableView:(UITableView *)tableView
+            viewForHeaderForSection:(NSInteger)section;
+
+#pragma mark - UITableView cell customization
+- (CGFloat)tableView:(UITableView*)tableView heightForSpecifier:(IASKSpecifier*)specifier;
+- (UITableViewCell*)tableView:(UITableView*)tableView cellForSpecifier:(IASKSpecifier*)specifier;
+
+#pragma mark - mail composing customization
+- (NSString*) settingsViewController:(id<IASKViewController>)settingsViewController
+         mailComposeBodyForSpecifier:(IASKSpecifier*) specifier;
+
+- (UIViewController<MFMailComposeViewControllerDelegate>*) settingsViewController:(id<IASKViewController>)settingsViewController
+                                     viewControllerForMailComposeViewForSpecifier:(IASKSpecifier*) specifier;
+
+- (void) settingsViewController:(id<IASKViewController>) settingsViewController
+          mailComposeController:(MFMailComposeViewController*)controller
+            didFinishWithResult:(MFMailComposeResult)result
+                          error:(NSError*)error;
+
+#pragma mark - respond to button taps
+- (void)settingsViewController:(IASKAppSettingsViewController*)sender buttonTappedForKey:(NSString*)key;
+- (void)settingsViewController:(IASKAppSettingsViewController*)sender tableView:(UITableView *)tableView didSelectCustomViewSpecifier:(IASKSpecifier*)specifier;
+ at end
+
+
+ at interface IASKAppSettingsViewController : UITableViewController <IASKViewController, UITextFieldDelegate, UINavigationControllerDelegate, MFMailComposeViewControllerDelegate> {
+  id<IASKSettingsDelegate>  __unsafe_unretained _delegate;
+
+    NSMutableArray          *_viewList;
+
+  IASKSettingsReader    *_settingsReader;
+    id<IASKSettingsStore>  _settingsStore;
+  NSString        *_file;
+
+  id                      _currentFirstResponder;
+
+    BOOL                    _showCreditsFooter;
+    BOOL                    _showDoneButton;
+}
+
+ at property (nonatomic, unsafe_unretained) IBOutlet id delegate;
+ at property (nonatomic, copy) NSString *file;
+ at property (nonatomic, assign) BOOL showCreditsFooter;
+ at property (nonatomic, assign) BOOL showDoneButton;
+
+- (void)synchronizeSettings;
+- (IBAction)dismiss:(id)sender;
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m b/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m
new file mode 100755
index 0000000..afaa28e
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m
@@ -0,0 +1,796 @@
+//
+//  IASKAppSettingsViewController.m
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009-2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+
+#import "IASKAppSettingsViewController.h"
+#import "IASKSettingsReader.h"
+#import "IASKSettingsStoreUserDefaults.h"
+#import "IASKPSToggleSwitchSpecifierViewCell.h"
+#import "IASKPSSliderSpecifierViewCell.h"
+#import "IASKPSTextFieldSpecifierViewCell.h"
+#import "IASKPSTitleValueSpecifierViewCell.h"
+#import "IASKSwitch.h"
+#import "IASKSlider.h"
+#import "IASKSpecifier.h"
+#import "IASKSpecifierValuesViewController.h"
+#import "IASKTextField.h"
+
+static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
+static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
+static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
+
+static NSString *kIASKCredits = @"Powered by InAppSettingsKit"; // Leave this as-is!!!
+
+#define kIASKSpecifierValuesViewControllerIndex       0
+#define kIASKSpecifierChildViewControllerIndex        1
+
+#define kIASKCreditsViewWidth                         285
+
+CGRect IASKCGRectSwap(CGRect rect);
+
+ at interface IASKAppSettingsViewController ()
+ at property (nonatomic, strong) NSMutableArray *viewList;
+ at property (nonatomic, strong) id currentFirstResponder;
+
+- (void) setup;
+
+- (void)_textChanged:(id)sender;
+- (void)synchronizeSettings;
+- (void)userDefaultsDidChange;
+- (void)reload;
+ at end
+
+ at implementation IASKAppSettingsViewController
+
+ at synthesize delegate = _delegate;
+ at synthesize viewList = _viewList;
+ at synthesize settingsReader = _settingsReader;
+ at synthesize file = _file;
+ at synthesize currentFirstResponder = _currentFirstResponder;
+ at synthesize showCreditsFooter = _showCreditsFooter;
+ at synthesize showDoneButton = _showDoneButton;
+ at synthesize settingsStore = _settingsStore;
+
+#pragma mark accessors
+- (IASKSettingsReader*)settingsReader {
+	if (!_settingsReader) {
+		_settingsReader = [[IASKSettingsReader alloc] initWithFile:self.file];
+	}
+	return _settingsReader;
+}
+
+- (id<IASKSettingsStore>)settingsStore {
+	if (!_settingsStore) {
+		_settingsStore = [[IASKSettingsStoreUserDefaults alloc] init];
+	}
+	return _settingsStore;
+}
+
+- (NSString*)file {
+	if (!_file) {
+		return @"Root";
+	}
+	return _file;
+}
+
+- (void)setFile:(NSString *)file {
+	if (file != _file) {
+
+		_file = [file copy];
+	}
+
+    self.tableView.contentOffset = CGPointMake(0, 0);
+	self.settingsReader = nil; // automatically initializes itself
+	[self.tableView reloadData];
+}
+
+- (BOOL)isPad {
+	BOOL isPad = NO;
+#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)
+	isPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
+#endif
+	return isPad;
+}
+
+#pragma mark standard view controller methods
+- (id)init {
+    return [self initWithNibName:@"IASKAppSettingsView" bundle:nil];
+}
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
+        // If set to YES, will add a DONE button at the right of the navigation bar
+      _showDoneButton = YES;
+
+      [self setup];
+    }
+    return self;
+}
+
+- (void)awakeFromNib {
+	// If set to YES, will add a DONE button at the right of the navigation bar
+	// if loaded via NIB, it's likely we sit in a TabBar- or NavigationController
+	// and thus don't need the Done button
+	_showDoneButton = NO;
+
+  [self setup];
+}
+
+//common (NIB & code based) initialization
+- (void) setup {
+  // If set to YES, will display credits for InAppSettingsKit creators
+  _showCreditsFooter = YES;
+}
+
+- (NSMutableArray *)viewList {
+    if (!_viewList) {
+		_viewList = [[NSMutableArray alloc] init];
+		[_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKSpecifierValuesView", @"ViewName",nil]];
+		[_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKAppSettingsView", @"ViewName",nil]];
+	}
+	return _viewList;
+}
+
+- (void) viewDidLoad {
+  [super viewDidLoad];
+  if ([self isPad]) {
+    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLineEtched;
+  }
+
+    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Done", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(handleBack)];
+    [backButton setBackgroundImage:[UIImage imageNamed:@"backButton"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
+    self.navigationItem.leftBarButtonItem = backButton;
+}
+
+- (void)viewDidUnload {
+  [super viewDidUnload];
+
+	// Release any retained subviews of the main view.
+	// e.g. self.myOutlet = nil;
+	self.view = nil;
+	self.viewList = nil;
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+	// if there's something selected, the value might have changed
+	// so reload that row
+	NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
+	if(selectedIndexPath) {
+		[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:selectedIndexPath]
+							  withRowAnimation:UITableViewRowAnimationNone];
+		// and reselect it, so we get the nice default deselect animation from UITableViewController
+		[self.tableView selectRowAtIndexPath:selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
+	}
+
+	self.navigationItem.rightBarButtonItem = nil;
+	self.navigationController.delegate = self;
+	if (_showDoneButton) {
+		UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
+																					target:self
+																					action:@selector(dismiss:)];
+		self.navigationItem.rightBarButtonItem = buttonItem;
+	}
+	if (!self.title) {
+		self.title = NSLocalizedString(@"Settings", @"");
+	}
+
+	if ([self.settingsStore isKindOfClass:[IASKSettingsStoreUserDefaults class]]) {
+		[[NSNotificationCenter defaultCenter] addObserver:self
+												 selector:@selector(userDefaultsDidChange)
+													 name:NSUserDefaultsDidChangeNotification
+												   object:[NSUserDefaults standardUserDefaults]];
+		[self userDefaultsDidChange]; // force update in case of changes while we were hidden
+	}
+	[super viewWillAppear:animated];
+}
+
+- (CGSize)contentSizeForViewInPopover {
+    return [[self view] sizeThatFits:CGSizeMake(320, 2000)];
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+	[super viewDidAppear:animated];
+
+	NSNotificationCenter *dc = [NSNotificationCenter defaultCenter];
+	IASK_IF_IOS4_OR_GREATER([dc addObserver:self selector:@selector(synchronizeSettings) name:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication]];);
+	IASK_IF_IOS4_OR_GREATER([dc addObserver:self selector:@selector(reload) name:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication]];);
+	[dc addObserver:self selector:@selector(synchronizeSettings) name:UIApplicationWillTerminateNotification object:[UIApplication sharedApplication]];
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+	[NSObject cancelPreviousPerformRequestsWithTarget:self];
+	[super viewWillDisappear:animated];
+}
+
+- (void)viewDidDisappear:(BOOL)animated {
+	[[NSNotificationCenter defaultCenter] removeObserver:self];
+
+	if (!self.navigationController.delegate) {
+		// hide the keyboard when we're popping from the navigation controller
+		[self.currentFirstResponder resignFirstResponder];
+	}
+
+	[super viewDidDisappear:animated];
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+    return YES;
+}
+
+- (void)didReceiveMemoryWarning {
+	// Releases the view if it doesn't have a superview.
+    [super didReceiveMemoryWarning];
+
+	// Release any cached data, images, etc that aren't in use.
+}
+
+- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
+	if (![viewController isKindOfClass:[IASKAppSettingsViewController class]] && ![viewController isKindOfClass:[IASKSpecifierValuesViewController class]]) {
+		[self dismiss:nil];
+	}
+}
+
+- (void)dealloc {
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+    _viewList = nil;
+	_file = nil;
+	_currentFirstResponder = nil;
+	_settingsReader = nil;
+    _settingsStore = nil;
+
+	_delegate = nil;
+
+}
+
+
+#pragma mark -
+#pragma mark Actions
+
+- (IBAction)dismiss:(id)sender {
+	[self.settingsStore synchronize];
+	self.navigationController.delegate = nil;
+
+	if (self.delegate && [self.delegate conformsToProtocol:@protocol(IASKSettingsDelegate)]) {
+		[self.delegate settingsViewControllerDidEnd:self];
+	}
+}
+
+- (void)toggledValue:(id)sender {
+    IASKSwitch *toggle    = (IASKSwitch*)sender;
+    IASKSpecifier *spec   = [_settingsReader specifierForKey:[toggle key]];
+
+    if ([toggle isOn]) {
+        if ([spec trueValue] != nil) {
+            [self.settingsStore setObject:[spec trueValue] forKey:[toggle key]];
+        }
+        else {
+            [self.settingsStore setBool:YES forKey:[toggle key]];
+        }
+    }
+    else {
+        if ([spec falseValue] != nil) {
+            [self.settingsStore setObject:[spec falseValue] forKey:[toggle key]];
+        }
+        else {
+            [self.settingsStore setBool:NO forKey:[toggle key]];
+        }
+    }
+    [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged
+                                                        object:[toggle key]
+                                                      userInfo:[NSDictionary dictionaryWithObject:[self.settingsStore objectForKey:[toggle key]]
+                                                                                           forKey:[toggle key]]];
+}
+
+- (void)sliderChangedValue:(id)sender {
+    IASKSlider *slider = (IASKSlider*)sender;
+    [self.settingsStore setFloat:[slider value] forKey:[slider key]];
+    [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged
+                                                        object:[slider key]
+                                                      userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:[slider value]]
+                                                                                           forKey:[slider key]]];
+}
+
+
+#pragma mark -
+#pragma mark UITableView Functions
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+	return [self.settingsReader numberOfSections];
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    return [self.settingsReader numberOfRowsForSection:section];
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
+    IASKSpecifier *specifier  = [self.settingsReader specifierForIndexPath:indexPath];
+    if ([[specifier type] isEqualToString:kIASKCustomViewSpecifier]) {
+		if ([self.delegate respondsToSelector:@selector(tableView:heightForSpecifier:)]) {
+			return [self.delegate tableView:tableView heightForSpecifier:specifier];
+		} else {
+			return 0;
+		}
+	}
+	return tableView.rowHeight;
+}
+
+- (NSString *)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section {
+    NSString *header = [self.settingsReader titleForSection:section];
+	if (0 == header.length) {
+		return nil;
+	}
+	return header;
+}
+
+- (UIView *)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section {
+	if ([self.delegate respondsToSelector:@selector(settingsViewController:tableView:viewForHeaderForSection:)]) {
+		return [self.delegate settingsViewController:self tableView:tableView viewForHeaderForSection:section];
+	} else {
+		return nil;
+	}
+}
+
+- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section {
+	if ([self tableView:tableView viewForHeaderInSection:section] && [self.delegate respondsToSelector:@selector(settingsViewController:tableView:heightForHeaderForSection:)]) {
+		CGFloat result;
+		if ((result = [self.delegate settingsViewController:self tableView:tableView heightForHeaderForSection:section])) {
+			return result;
+		}
+
+	}
+	NSString *title;
+	if ((title = [self tableView:tableView titleForHeaderInSection:section])) {
+		CGSize size = [title sizeWithFont:[UIFont boldSystemFontOfSize:[UIFont labelFontSize]]
+						constrainedToSize:CGSizeMake(tableView.frame.size.width - 2*kIASKHorizontalPaddingGroupTitles, INFINITY)
+							lineBreakMode:UILineBreakModeWordWrap];
+		return size.height+kIASKVerticalPaddingGroupTitles;
+	}
+	return 0;
+}
+
+- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
+{
+	NSString *footerText = [self.settingsReader footerTextForSection:section];
+	if (_showCreditsFooter && (section == [self.settingsReader numberOfSections]-1)) {
+		// show credits since this is the last section
+		if ((footerText == nil) || ([footerText length] == 0)) {
+			// show the credits on their own
+			return kIASKCredits;
+		} else {
+			// show the credits below the app's FooterText
+			return [NSString stringWithFormat:@"%@\n\n%@", footerText, kIASKCredits];
+		}
+	} else {
+		if ([footerText length] == 0) {
+			return nil;
+		}
+		return [self.settingsReader footerTextForSection:section];
+	}
+}
+
+- (UITableViewCell*)dequeueReusableCellWithIdentifier:(NSString*)identifier {
+	UITableViewCell *cell = nil;
+	if ([identifier isEqualToString:kIASKPSToggleSwitchSpecifier]) {
+		cell = [[[NSBundle mainBundle] loadNibNamed:@"IASKPSToggleSwitchSpecifierViewCell"
+											  owner:self
+											options:nil] objectAtIndex:0];
+	}
+	else if ([identifier isEqualToString:kIASKPSMultiValueSpecifier] || [identifier isEqualToString:kIASKPSTitleValueSpecifier]) {
+		cell = [[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
+		cell.accessoryType = [identifier isEqualToString:kIASKPSMultiValueSpecifier] ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
+	}
+	else if ([identifier isEqualToString:kIASKPSTextFieldSpecifier]) {
+		cell = (IASKPSTextFieldSpecifierViewCell*) [[[NSBundle mainBundle] loadNibNamed:@"IASKPSTextFieldSpecifierViewCell"
+																				  owner:self
+																				options:nil] objectAtIndex:0];
+	}
+	else if ([identifier isEqualToString:kIASKPSSliderSpecifier]) {
+		cell = (IASKPSSliderSpecifierViewCell*) [[[NSBundle mainBundle] loadNibNamed:@"IASKPSSliderSpecifierViewCell"
+																			   owner:self
+																			 options:nil] objectAtIndex:0];
+	} else if ([identifier isEqualToString:kIASKPSChildPaneSpecifier]) {
+		cell = [[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
+		cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+	} else if ([identifier isEqualToString:kIASKButtonSpecifier]) {
+		cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
+	} else if ([identifier isEqualToString:kIASKMailComposeSpecifier]) {
+		cell = [[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
+		[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
+	} else {
+		cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
+	}
+	return cell;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+	IASKSpecifier *specifier  = [self.settingsReader specifierForIndexPath:indexPath];
+	if ([specifier.type isEqualToString:kIASKCustomViewSpecifier] && [self.delegate respondsToSelector:@selector(tableView:cellForSpecifier:)]) {
+		UITableViewCell* cell = [self.delegate tableView:tableView cellForSpecifier:specifier];
+		assert(nil != cell && "delegate must return a UITableViewCell for custom cell types");
+		return cell;
+	}
+
+	UITableViewCell *cell = [self dequeueReusableCellWithIdentifier:specifier.type];
+
+	if ([specifier.type isEqualToString:kIASKPSToggleSwitchSpecifier]) {
+		((IASKPSToggleSwitchSpecifierViewCell*)cell).label.text = specifier.title;
+
+		id currentValue = [self.settingsStore objectForKey:specifier.key];
+		BOOL toggleState;
+		if (currentValue) {
+			if ([currentValue isEqual:specifier.trueValue]) {
+				toggleState = YES;
+			} else if ([currentValue isEqual:specifier.falseValue]) {
+				toggleState = NO;
+			} else {
+				toggleState = [currentValue boolValue];
+			}
+		} else {
+			toggleState = specifier.defaultBoolValue;
+		}
+		((IASKPSToggleSwitchSpecifierViewCell*)cell).toggle.on = toggleState;
+
+		[((IASKPSToggleSwitchSpecifierViewCell*)cell).toggle addTarget:self action:@selector(toggledValue:) forControlEvents:UIControlEventValueChanged];
+		((IASKPSToggleSwitchSpecifierViewCell*)cell).toggle.key = specifier.key;
+	}
+	else if ([specifier.type isEqualToString:kIASKPSMultiValueSpecifier]) {
+		cell.textLabel.text = specifier.title;
+		cell.detailTextLabel.text = [[specifier titleForCurrentValue:[self.settingsStore objectForKey:specifier.key] != nil ?
+									  [self.settingsStore objectForKey:specifier.key] : specifier.defaultValue] description];
+	}
+	else if ([specifier.type isEqualToString:kIASKPSTitleValueSpecifier]) {
+		cell.textLabel.text = specifier.title;
+		id value = [self.settingsStore objectForKey:specifier.key] ? : specifier.defaultValue;
+
+		NSString *stringValue;
+		if (specifier.multipleValues || specifier.multipleTitles) {
+			stringValue = [specifier titleForCurrentValue:value];
+		} else {
+			stringValue = [value description];
+		}
+
+		cell.detailTextLabel.text = stringValue;
+		cell.userInteractionEnabled = NO;
+	}
+	else if ([specifier.type isEqualToString:kIASKPSTextFieldSpecifier]) {
+		((IASKPSTextFieldSpecifierViewCell*)cell).label.text = specifier.title;
+
+		NSString *textValue = [self.settingsStore objectForKey:specifier.key] != nil ? [self.settingsStore objectForKey:specifier.key] : specifier.defaultStringValue;
+		if (textValue && ![textValue isMemberOfClass:[NSString class]]) {
+			textValue = [NSString stringWithFormat:@"%@", textValue];
+		}
+		IASKTextField *textField = ((IASKPSTextFieldSpecifierViewCell*)cell).textField;
+		textField.text = textValue;
+		textField.key = specifier.key;
+		textField.delegate = self;
+		textField.secureTextEntry = [specifier isSecure];
+		textField.keyboardType = specifier.keyboardType;
+		textField.autocapitalizationType = specifier.autocapitalizationType;
+		[textField addTarget:self action:@selector(_textChanged:) forControlEvents:UIControlEventEditingChanged];
+		if([specifier isSecure]){
+			textField.autocorrectionType = UITextAutocorrectionTypeNo;
+		} else {
+			textField.autocorrectionType = specifier.autoCorrectionType;
+		}
+		[cell setNeedsLayout];
+	}
+	else if ([specifier.type isEqualToString:kIASKPSSliderSpecifier]) {
+		if (specifier.minimumValueImage.length > 0) {
+			((IASKPSSliderSpecifierViewCell*)cell).minImage.image = [UIImage imageWithContentsOfFile:[_settingsReader pathForImageNamed:specifier.minimumValueImage]];
+		}
+
+		if (specifier.maximumValueImage.length > 0) {
+			((IASKPSSliderSpecifierViewCell*)cell).maxImage.image = [UIImage imageWithContentsOfFile:[_settingsReader pathForImageNamed:specifier.maximumValueImage]];
+		}
+
+		IASKSlider *slider = ((IASKPSSliderSpecifierViewCell*)cell).slider;
+		slider.minimumValue = specifier.minimumValue;
+		slider.maximumValue = specifier.maximumValue;
+		slider.value =	[self.settingsStore objectForKey:specifier.key] != nil ? [[self.settingsStore objectForKey:specifier.key] floatValue] : [specifier.defaultValue floatValue];
+		[slider addTarget:self action:@selector(sliderChangedValue:) forControlEvents:UIControlEventValueChanged];
+		slider.key = specifier.key;
+		[cell setNeedsLayout];
+	}
+	else if ([specifier.type isEqualToString:kIASKPSChildPaneSpecifier]) {
+		cell.textLabel.text = specifier.title;
+	} else if ([specifier.type isEqualToString:kIASKOpenURLSpecifier] || [specifier.type isEqualToString:kIASKMailComposeSpecifier]) {
+		cell.textLabel.text = specifier.title;
+		cell.detailTextLabel.text = [specifier.defaultValue description];
+	} else if ([specifier.type isEqualToString:kIASKButtonSpecifier]) {
+		NSString *value = [self.settingsStore objectForKey:specifier.key];
+		cell.textLabel.text = [value isKindOfClass:[NSString class]] ? [self.settingsReader titleForStringId:value] : specifier.title;
+		cell.textLabel.textAlignment = UITextAlignmentCenter;
+	} else {
+		cell.textLabel.text = specifier.title;
+	}
+	return cell;
+}
+
+- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+	//create a set of specifier types that can't be selected
+	static NSSet* noSelectionTypes = nil;
+	if(nil == noSelectionTypes) {
+		noSelectionTypes = [NSSet setWithObjects:kIASKPSToggleSwitchSpecifier, kIASKPSSliderSpecifier, nil];
+	}
+
+	IASKSpecifier *specifier  = [self.settingsReader specifierForIndexPath:indexPath];
+	if([noSelectionTypes containsObject:specifier.type]) {
+		return nil;
+	} else {
+		return indexPath;
+	}
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+    IASKSpecifier *specifier  = [self.settingsReader specifierForIndexPath:indexPath];
+
+    //switches and sliders can't be selected (should be captured by tableView:willSelectRowAtIndexPath: delegate method)
+    assert(![[specifier type] isEqualToString:kIASKPSToggleSwitchSpecifier]);
+    assert(![[specifier type] isEqualToString:kIASKPSSliderSpecifier]);
+
+    if ([[specifier type] isEqualToString:kIASKPSMultiValueSpecifier]) {
+        IASKSpecifierValuesViewController *targetViewController = [[self.viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex] objectForKey:@"viewController"];
+
+        if (targetViewController == nil) {
+            // the view controller has not been created yet, create it and set it to our viewList array
+            // create a new dictionary with the new view controller
+            NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3];
+            [newItemDict addEntriesFromDictionary: [self.viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex]];	// copy the title and explain strings
+
+            targetViewController = [[IASKSpecifierValuesViewController alloc] initWithNibName:@"IASKSpecifierValuesView" bundle:nil];
+            // add the new view controller to the dictionary and then to the 'viewList' array
+            [newItemDict setObject:targetViewController forKey:@"viewController"];
+            [self.viewList replaceObjectAtIndex:kIASKSpecifierValuesViewControllerIndex withObject:newItemDict];
+
+            // load the view controll back in to push it
+            targetViewController = [[self.viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex] objectForKey:@"viewController"];
+        }
+        [targetViewController setCurrentSpecifier:specifier];
+        targetViewController.settingsReader = self.settingsReader;
+        targetViewController.settingsStore = self.settingsStore;
+        [[self navigationController] pushViewController:targetViewController animated:YES];
+    }
+    else if ([[specifier type] isEqualToString:kIASKPSTextFieldSpecifier]) {
+		IASKPSTextFieldSpecifierViewCell *textFieldCell = (id)[tableView cellForRowAtIndexPath:indexPath];
+		[textFieldCell.textField becomeFirstResponder];
+    }
+    else if ([[specifier type] isEqualToString:kIASKPSChildPaneSpecifier]) {
+
+
+        Class vcClass = [specifier viewControllerClass];
+        if (vcClass) {
+            SEL initSelector = [specifier viewControllerSelector];
+            if (!initSelector) {
+                initSelector = @selector(init);
+            }
+            UIViewController * vc = [vcClass alloc];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+            [vc performSelector:initSelector withObject:[specifier file] withObject:[specifier key]];
+#pragma clang diagnostic pop
+			if ([vc respondsToSelector:@selector(setDelegate:)]) {
+				[vc performSelector:@selector(setDelegate:) withObject:self.delegate];
+			}
+			if ([vc respondsToSelector:@selector(setSettingsStore:)]) {
+				[vc performSelector:@selector(setSettingsStore:) withObject:self.settingsStore];
+			}
+			self.navigationController.delegate = nil;
+            [self.navigationController pushViewController:vc animated:YES];
+
+            return;
+        }
+
+        if (nil == [specifier file]) {
+            [tableView deselectRowAtIndexPath:indexPath animated:YES];
+            return;
+        }
+
+        IASKAppSettingsViewController *targetViewController = [[self.viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex] objectForKey:@"viewController"];
+
+        if (targetViewController == nil) {
+            // the view controller has not been created yet, create it and set it to our viewList array
+            // create a new dictionary with the new view controller
+            NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3];
+            [newItemDict addEntriesFromDictionary: [self.viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex]];	// copy the title and explain strings
+
+            targetViewController = [[[self class] alloc] initWithNibName:@"IASKAppSettingsView" bundle:nil];
+			targetViewController.showDoneButton = NO;
+			targetViewController.settingsStore = self.settingsStore;
+			targetViewController.delegate = self.delegate;
+
+            // add the new view controller to the dictionary and then to the 'viewList' array
+            [newItemDict setObject:targetViewController forKey:@"viewController"];
+            [self.viewList replaceObjectAtIndex:kIASKSpecifierChildViewControllerIndex withObject:newItemDict];
+
+            // load the view controll back in to push it
+            targetViewController = [[self.viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex] objectForKey:@"viewController"];
+        }
+		targetViewController.file = specifier.file;
+		targetViewController.title = specifier.title;
+        targetViewController.showCreditsFooter = NO;
+        [[self navigationController] pushViewController:targetViewController animated:YES];
+    } else if ([[specifier type] isEqualToString:kIASKOpenURLSpecifier]) {
+        [tableView deselectRowAtIndexPath:indexPath animated:YES];
+		[[UIApplication sharedApplication] openURL:[NSURL URLWithString:specifier.file]];
+    } else if ([[specifier type] isEqualToString:kIASKButtonSpecifier]) {
+        [tableView deselectRowAtIndexPath:indexPath animated:YES];
+		if ([self.delegate respondsToSelector:@selector(settingsViewController:buttonTappedForKey:)]) {
+			[self.delegate settingsViewController:self buttonTappedForKey:[specifier key]];
+		} else {
+			// legacy code, provided for backward compatibility
+			// the delegate mechanism above is much cleaner and doesn't leak
+			Class buttonClass = [specifier buttonClass];
+			SEL buttonAction = [specifier buttonAction];
+			if ([buttonClass respondsToSelector:buttonAction]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+                [buttonClass performSelector:buttonAction withObject:self withObject:[specifier key]];
+#pragma clang diagnostic pop
+				NSLog(@"InAppSettingsKit Warning: Using IASKButtonSpecifier without implementing the delegate method is deprecated");
+			}
+		}
+    } else if ([[specifier type] isEqualToString:kIASKMailComposeSpecifier]) {
+        [tableView deselectRowAtIndexPath:indexPath animated:YES];
+        if ([MFMailComposeViewController canSendMail]) {
+            MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
+            mailViewController.navigationBar.barStyle = self.navigationController.navigationBar.barStyle;
+			mailViewController.navigationBar.tintColor = self.navigationController.navigationBar.tintColor;
+
+            if ([specifier localizedObjectForKey:kIASKMailComposeSubject]) {
+                [mailViewController setSubject:[specifier localizedObjectForKey:kIASKMailComposeSubject]];
+            }
+            if ([[specifier specifierDict] objectForKey:kIASKMailComposeToRecipents]) {
+                [mailViewController setToRecipients:[[specifier specifierDict] objectForKey:kIASKMailComposeToRecipents]];
+            }
+            if ([[specifier specifierDict] objectForKey:kIASKMailComposeCcRecipents]) {
+                [mailViewController setCcRecipients:[[specifier specifierDict] objectForKey:kIASKMailComposeCcRecipents]];
+            }
+            if ([[specifier specifierDict] objectForKey:kIASKMailComposeBccRecipents]) {
+                [mailViewController setBccRecipients:[[specifier specifierDict] objectForKey:kIASKMailComposeBccRecipents]];
+            }
+            if ([specifier localizedObjectForKey:kIASKMailComposeBody]) {
+                BOOL isHTML = NO;
+                if ([[specifier specifierDict] objectForKey:kIASKMailComposeBodyIsHTML]) {
+                    isHTML = [[[specifier specifierDict] objectForKey:kIASKMailComposeBodyIsHTML] boolValue];
+                }
+
+              if ([self.delegate respondsToSelector:@selector(settingsViewController:mailComposeBodyForSpecifier:)]) {
+                    [mailViewController setMessageBody:[self.delegate settingsViewController:self
+                                                                 mailComposeBodyForSpecifier:specifier] isHTML:isHTML];
+                }
+                else {
+                    [mailViewController setMessageBody:[specifier localizedObjectForKey:kIASKMailComposeBody] isHTML:isHTML];
+                }
+            }
+
+            UIViewController<MFMailComposeViewControllerDelegate> *vc = nil;
+
+          if ([self.delegate respondsToSelector:@selector(settingsViewController:viewControllerForMailComposeViewForSpecifier:)]) {
+            vc = [self.delegate settingsViewController:self viewControllerForMailComposeViewForSpecifier:specifier];
+            }
+
+            if (vc == nil) {
+                vc = self;
+            }
+
+            mailViewController.mailComposeDelegate = vc;
+            [vc presentModalViewController:mailViewController animated:YES];
+        } else {
+            UIAlertView *alert = [[UIAlertView alloc]
+                                  initWithTitle:NSLocalizedString(@"Mail not configured", @"InAppSettingsKit")
+                                  message:NSLocalizedString(@"This device is not configured for sending Email. Please configure the Mail settings in the Settings app.", @"InAppSettingsKit")
+                                  delegate: nil
+                                  cancelButtonTitle:NSLocalizedString(@"OK", @"InAppSettingsKit")
+                                  otherButtonTitles:nil];
+            [alert show];
+        }
+
+	} else if ([[specifier type] isEqualToString:kIASKCustomViewSpecifier] && [self.delegate respondsToSelector:@selector(settingsViewController:tableView:didSelectCustomViewSpecifier:)]) {
+        [self.delegate settingsViewController:self tableView:tableView didSelectCustomViewSpecifier:specifier];
+    } else {
+        [tableView deselectRowAtIndexPath:indexPath animated:NO];
+    }
+}
+
+
+#pragma mark -
+#pragma mark MFMailComposeViewControllerDelegate Function
+
+-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
+
+    // Forward the mail compose delegate
+    if ([self.delegate respondsToSelector:@selector(settingsViewController:mailComposeController:didFinishWithResult:error:)]) {
+         [self.delegate settingsViewController:self
+                         mailComposeController:controller
+                           didFinishWithResult:result
+                                         error:error];
+     }
+
+    // NOTE: No error handling is done here
+    [self dismissModalViewControllerAnimated:YES];
+}
+
+#pragma mark -
+#pragma mark UITextFieldDelegate Functions
+
+- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
+	self.currentFirstResponder = textField;
+	return YES;
+}
+
+- (void)_textChanged:(id)sender {
+    IASKTextField *text = (IASKTextField*)sender;
+    [_settingsStore setObject:[text text] forKey:[text key]];
+    [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged
+                                                        object:[text key]
+                                                      userInfo:[NSDictionary dictionaryWithObject:[text text]
+                                                                                           forKey:[text key]]];
+}
+
+- (BOOL)textFieldShouldReturn:(UITextField *)textField{
+	[textField resignFirstResponder];
+	self.currentFirstResponder = nil;
+	return YES;
+}
+
+
+#pragma mark Notifications
+
+- (void)synchronizeSettings {
+    [_settingsStore synchronize];
+}
+
+static NSDictionary *oldUserDefaults = nil;
+- (void)userDefaultsDidChange {
+	NSDictionary *currentDict = [NSUserDefaults standardUserDefaults].dictionaryRepresentation;
+	NSMutableArray *indexPathsToUpdate = [NSMutableArray array];
+	for (NSString *key in currentDict.allKeys) {
+		if (![[oldUserDefaults valueForKey:key] isEqual:[currentDict valueForKey:key]]) {
+			NSIndexPath *path = [self.settingsReader indexPathForKey:key];
+			if (path && ![[self.settingsReader specifierForKey:key].type isEqualToString:kIASKCustomViewSpecifier]) {
+				[indexPathsToUpdate addObject:path];
+			}
+		}
+	}
+	oldUserDefaults = currentDict;
+
+
+	for (UITableViewCell *cell in self.tableView.visibleCells) {
+		if ([cell isKindOfClass:[IASKPSTextFieldSpecifierViewCell class]] && [((IASKPSTextFieldSpecifierViewCell*)cell).textField isFirstResponder]) {
+			[indexPathsToUpdate removeObject:[self.tableView indexPathForCell:cell]];
+		}
+	}
+	if (indexPathsToUpdate.count) {
+		[self.tableView reloadRowsAtIndexPaths:indexPathsToUpdate withRowAnimation:UITableViewRowAnimationNone];
+	}
+}
+
+- (void)reload {
+	// wait 0.5 sec until UI is available after applicationWillEnterForeground
+	[self.tableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.5];
+}
+
+#pragma mark CGRect Utility function
+CGRect IASKCGRectSwap(CGRect rect) {
+	CGRect newRect;
+	newRect.origin.x = rect.origin.y;
+	newRect.origin.y = rect.origin.x;
+	newRect.size.width = rect.size.height;
+	newRect.size.height = rect.size.width;
+	return newRect;
+}
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.h b/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.h
new file mode 100755
index 0000000..c13c30ed
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.h
@@ -0,0 +1,30 @@
+//
+//  IASKAppSettingsWebViewController.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+#import <MessageUI/MessageUI.h>
+
+ at interface IASKAppSettingsWebViewController : UIViewController <UIWebViewDelegate, MFMailComposeViewControllerDelegate> {
+  UIWebView *webView;
+  NSURL *url;
+}
+
+- (id)initWithFile:(NSString*)htmlFileName key:(NSString*)key;
+
+ at property (nonatomic, strong) IBOutlet UIWebView *webView;
+ at property (nonatomic, strong) NSURL *url;
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.m b/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.m
new file mode 100755
index 0000000..99ecd44
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.m
@@ -0,0 +1,144 @@
+//
+//  IASKAppSettingsWebViewController.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKAppSettingsWebViewController.h"
+
+ at implementation IASKAppSettingsWebViewController
+
+ at synthesize url;
+ at synthesize webView;
+
+- (id)initWithFile:(NSString*)urlString key:(NSString*)key {
+	if (!(self = [super initWithNibName:nil bundle:nil])) {
+		return nil;
+	}
+
+	self.url = [NSURL URLWithString:urlString];
+	if (!self.url || ![self.url scheme]) {
+		NSString *path = [[NSBundle mainBundle] pathForResource:[urlString stringByDeletingPathExtension] ofType:[urlString pathExtension]];
+		if(path)
+			self.url = [NSURL fileURLWithPath:path];
+		else
+			self.url = nil;
+	}
+	return self;
+}
+
+
+- (void)dealloc {
+	webView = nil;
+	url = nil;
+
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+	[webView loadRequest:[NSURLRequest requestWithURL:self.url]];
+}
+
+- (void)viewDidUnload {
+	[super viewDidUnload];
+	self.webView = nil;
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+    return YES;
+}
+
+- (void)webViewDidFinishLoad:(UIWebView *)webView {
+	self.navigationItem.title = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];
+}
+
+- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
+	NSURL *newURL = [request URL];
+
+	// intercept mailto URL and send it to an in-app Mail compose view instead
+	if ([[newURL scheme] isEqualToString:@"mailto"]) {
+
+		NSArray *rawURLparts = [[newURL resourceSpecifier] componentsSeparatedByString:@"?"];
+		if (rawURLparts.count > 2) {
+			return NO; // invalid URL
+		}
+
+		MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
+		mailViewController.mailComposeDelegate = self;
+
+		NSMutableArray *toRecipients = [NSMutableArray array];
+		NSString *defaultRecipient = [rawURLparts objectAtIndex:0];
+		if (defaultRecipient.length) {
+			[toRecipients addObject:defaultRecipient];
+		}
+
+		if (rawURLparts.count == 2) {
+			NSString *queryString = [rawURLparts objectAtIndex:1];
+
+			NSArray *params = [queryString componentsSeparatedByString:@"&"];
+			for (NSString *param in params) {
+				NSArray *keyValue = [param componentsSeparatedByString:@"="];
+				if (keyValue.count != 2) {
+					continue;
+				}
+				NSString *key = [[keyValue objectAtIndex:0] lowercaseString];
+				NSString *value = [keyValue objectAtIndex:1];
+
+				value =  (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
+																							 (__bridge CFStringRef)value,
+																							 CFSTR(""),
+																							 kCFStringEncodingUTF8);
+				if ([key isEqualToString:@"subject"]) {
+					[mailViewController setSubject:value];
+				}
+
+				if ([key isEqualToString:@"body"]) {
+					[mailViewController setMessageBody:value isHTML:NO];
+				}
+
+				if ([key isEqualToString:@"to"]) {
+					[toRecipients addObjectsFromArray:[value componentsSeparatedByString:@","]];
+				}
+
+				if ([key isEqualToString:@"cc"]) {
+					NSArray *recipients = [value componentsSeparatedByString:@","];
+					[mailViewController setCcRecipients:recipients];
+				}
+
+				if ([key isEqualToString:@"bcc"]) {
+					NSArray *recipients = [value componentsSeparatedByString:@","];
+					[mailViewController setBccRecipients:recipients];
+				}
+			}
+		}
+
+		[mailViewController setToRecipients:toRecipients];
+
+		[self presentModalViewController:mailViewController animated:YES];
+		return NO;
+	}
+
+	// open inline if host is the same, otherwise, pass to the system
+	if (![newURL host] || [[newURL host] isEqualToString:[self.url host]]) {
+		return YES;
+	}
+	[[UIApplication sharedApplication] openURL:newURL];
+	return NO;
+}
+
+- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
+	[self dismissModalViewControllerAnimated:YES];
+}
+
+
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.h b/ios/iosremote/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.h
new file mode 100755
index 0000000..d733d4d
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.h
@@ -0,0 +1,36 @@
+//
+//  IASKSpecifierValuesViewController.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+#import "IASKSettingsStore.h"
+#import "IASKViewController.h"
+ at class IASKSpecifier;
+ at class IASKSettingsReader;
+
+ at interface IASKSpecifierValuesViewController : UIViewController<IASKViewController> {
+    UITableView             *_tableView;
+
+    IASKSpecifier           *_currentSpecifier;
+    NSIndexPath             *_checkedItem;
+    IASKSettingsReader      *_settingsReader;
+    id<IASKSettingsStore>   _settingsStore;
+}
+
+ at property (nonatomic, strong) IBOutlet UITableView *tableView;
+ at property (nonatomic, strong) NSIndexPath *checkedItem;
+ at property (nonatomic, strong) IASKSpecifier *currentSpecifier;
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m b/ios/iosremote/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m
new file mode 100755
index 0000000..52531c0
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m
@@ -0,0 +1,202 @@
+//
+//  IASKSpecifierValuesViewController.m
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSpecifierValuesViewController.h"
+#import "IASKSpecifier.h"
+#import "IASKSettingsReader.h"
+#import "IASKSettingsStoreUserDefaults.h"
+
+#define kCellValue      @"kCellValue"
+
+ at interface IASKSpecifierValuesViewController()
+- (void)userDefaultsDidChange;
+ at end
+
+ at implementation IASKSpecifierValuesViewController
+
+ at synthesize tableView=_tableView;
+ at synthesize currentSpecifier=_currentSpecifier;
+ at synthesize checkedItem=_checkedItem;
+ at synthesize settingsReader = _settingsReader;
+ at synthesize settingsStore = _settingsStore;
+
+- (void) updateCheckedItem {
+    NSInteger index;
+
+	// Find the currently checked item
+    if([self.settingsStore objectForKey:[_currentSpecifier key]]) {
+      index = [[_currentSpecifier multipleValues] indexOfObject:[self.settingsStore objectForKey:[_currentSpecifier key]]];
+    } else {
+      index = [[_currentSpecifier multipleValues] indexOfObject:[_currentSpecifier defaultValue]];
+    }
+	[self setCheckedItem:[NSIndexPath indexPathForRow:index inSection:0]];
+}
+
+- (id<IASKSettingsStore>)settingsStore {
+    if(_settingsStore == nil) {
+        _settingsStore = [[IASKSettingsStoreUserDefaults alloc] init];
+    }
+    return _settingsStore;
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Done", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(handleBack)];
+    [backButton setBackgroundImage:[UIImage imageNamed:@"backButton"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
+    self.navigationItem.leftBarButtonItem = backButton;
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+    if (_currentSpecifier) {
+        [self setTitle:[_currentSpecifier title]];
+        [self updateCheckedItem];
+    }
+
+    if (_tableView) {
+        [_tableView reloadData];
+
+		// Make sure the currently checked item is visible
+        [_tableView scrollToRowAtIndexPath:[self checkedItem] atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
+    }
+	[super viewWillAppear:animated];
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+	[_tableView flashScrollIndicators];
+	[super viewDidAppear:animated];
+	[[NSNotificationCenter defaultCenter] addObserver:self
+											 selector:@selector(userDefaultsDidChange)
+												 name:NSUserDefaultsDidChangeNotification
+											   object:[NSUserDefaults standardUserDefaults]];
+}
+
+- (void)viewDidDisappear:(BOOL)animated {
+	[[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:nil];
+	[super viewDidDisappear:animated];
+}
+
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+	return YES;
+}
+
+- (void)didReceiveMemoryWarning {
+	// Releases the view if it doesn't have a superview.
+    [super didReceiveMemoryWarning];
+
+	// Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+	// Release any retained subviews of the main view.
+	// e.g. self.myOutlet = nil;
+	self.tableView = nil;
+}
+
+
+- (void)dealloc {
+    _currentSpecifier = nil;
+	_checkedItem = nil;
+	_settingsReader = nil;
+    _settingsStore = nil;
+	_tableView = nil;
+}
+
+
+#pragma mark -
+#pragma mark UITableView delegates
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+	return 1;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    return [_currentSpecifier multipleValuesCount];
+}
+
+- (void)selectCell:(UITableViewCell *)cell {
+	[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
+	[[cell textLabel] setTextColor:kIASKgrayBlueColor];
+}
+
+- (void)deselectCell:(UITableViewCell *)cell {
+	[cell setAccessoryType:UITableViewCellAccessoryNone];
+	[[cell textLabel] setTextColor:[UIColor darkTextColor]];
+}
+
+- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
+    return [_currentSpecifier footerText];
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    UITableViewCell *cell   = [tableView dequeueReusableCellWithIdentifier:kCellValue];
+    NSArray *titles         = [_currentSpecifier multipleTitles];
+
+    if (!cell) {
+        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellValue];
+    }
+
+	if ([indexPath isEqual:[self checkedItem]]) {
+		[self selectCell:cell];
+    } else {
+        [self deselectCell:cell];
+    }
+
+	@try {
+		[[cell textLabel] setText:[self.settingsReader titleForStringId:[titles objectAtIndex:indexPath.row]]];
+	}
+	@catch (NSException * e) {}
+    return cell;
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+
+    if (indexPath == [self checkedItem]) {
+        [tableView deselectRowAtIndexPath:indexPath animated:YES];
+        return;
+    }
+
+    NSArray *values         = [_currentSpecifier multipleValues];
+
+    [tableView deselectRowAtIndexPath:indexPath animated:YES];
+    [self deselectCell:[tableView cellForRowAtIndexPath:[self checkedItem]]];
+    [self selectCell:[tableView cellForRowAtIndexPath:indexPath]];
+    [self setCheckedItem:indexPath];
+
+    [self.settingsStore setObject:[values objectAtIndex:indexPath.row] forKey:[_currentSpecifier key]];
+	[self.settingsStore synchronize];
+    [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged
+                                                        object:[_currentSpecifier key]
+                                                      userInfo:[NSDictionary dictionaryWithObject:[values objectAtIndex:indexPath.row]
+                                                                                           forKey:[_currentSpecifier key]]];
+}
+
+#pragma mark Notifications
+
+- (void)userDefaultsDidChange {
+	NSIndexPath *oldCheckedItem = self.checkedItem;
+	if(_currentSpecifier) {
+		[self updateCheckedItem];
+	}
+
+	// only reload the table if it had changed; prevents animation cancellation
+	if (![self.checkedItem isEqual:oldCheckedItem]) {
+		[_tableView reloadData];
+	}
+}
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Controllers/IASKViewController.h b/ios/iosremote/InAppSettingsKit/Controllers/IASKViewController.h
new file mode 100755
index 0000000..2ab89a6
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Controllers/IASKViewController.h
@@ -0,0 +1,26 @@
+//
+//  IASKAppSettingsViewController.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+ at class IASKSettingsReader;
+ at protocol IASKSettingsStore;
+
+// protocol all IASK view controllers implement
+ at protocol IASKViewController <NSObject>
+
+ at property (nonatomic, retain) IASKSettingsReader* settingsReader;
+ at property (nonatomic, retain) id<IASKSettingsStore> settingsStore;
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSettingsReader.h b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsReader.h
new file mode 100755
index 0000000..2af1fc9
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsReader.h
@@ -0,0 +1,144 @@
+//
+//  IASKSettingsReader.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <Foundation/Foundation.h>
+
+#define kIASKPreferenceSpecifiers             @"PreferenceSpecifiers"
+#define kIASKType                             @"Type"
+#define kIASKTitle                            @"Title"
+#define kIASKFooterText                       @"FooterText"
+#define kIASKKey                              @"Key"
+#define kIASKFile                             @"File"
+#define kIASKDefaultValue                     @"DefaultValue"
+#define kIASKMinimumValue                     @"MinimumValue"
+#define kIASKMaximumValue                     @"MaximumValue"
+#define kIASKTrueValue                        @"TrueValue"
+#define kIASKFalseValue                       @"FalseValue"
+#define kIASKIsSecure                         @"IsSecure"
+#define KIASKKeyboardType                     @"KeyboardType"
+#define kIASKAutocapitalizationType           @"AutocapitalizationType"
+#define kIASKAutoCorrectionType               @"AutocorrectionType"
+#define kIASKValues                           @"Values"
+#define kIASKTitles                           @"Titles"
+#define kIASKViewControllerClass              @"IASKViewControllerClass"
+#define kIASKViewControllerSelector           @"IASKViewControllerSelector"
+#define kIASKButtonClass                      @"IASKButtonClass"
+#define kIASKButtonAction                     @"IASKButtonAction"
+#define kIASKMailComposeToRecipents           @"IASKMailComposeToRecipents"
+#define kIASKMailComposeCcRecipents           @"IASKMailComposeCcRecipents"
+#define kIASKMailComposeBccRecipents          @"IASKMailComposeBccRecipents"
+#define kIASKMailComposeSubject               @"IASKMailComposeSubject"
+#define kIASKMailComposeBody                  @"IASKMailComposeBody"
+#define kIASKMailComposeBodyIsHTML            @"IASKMailComposeBodyIsHTML"
+#define kIASKKeyboardAlphabet                 @"Alphabet"
+#define kIASKKeyboardNumbersAndPunctuation    @"NumbersAndPunctuation"
+#define kIASKKeyboardNumberPad                @"NumberPad"
+#define kIASKKeyboardDecimalPad               @"DecimalPad"
+
+#define KIASKKeyboardURL                      @"URL"
+#define kIASKKeyboardEmailAddress             @"EmailAddress"
+#define kIASKAutoCapNone                      @"None"
+#define kIASKAutoCapSentences                 @"Sentences"
+#define kIASKAutoCapWords                     @"Words"
+#define kIASKAutoCapAllCharacters             @"AllCharacters"
+#define kIASKAutoCorrDefault                  @"Default"
+#define kIASKAutoCorrNo                       @"No"
+#define kIASKAutoCorrYes                      @"Yes"
+#define kIASKMinimumValueImage                @"MinimumValueImage"
+#define kIASKMaximumValueImage                @"MaximumValueImage"
+
+#define kIASKPSGroupSpecifier                 @"PSGroupSpecifier"
+#define kIASKPSToggleSwitchSpecifier          @"PSToggleSwitchSpecifier"
+#define kIASKPSMultiValueSpecifier            @"PSMultiValueSpecifier"
+#define kIASKPSSliderSpecifier                @"PSSliderSpecifier"
+#define kIASKPSTitleValueSpecifier            @"PSTitleValueSpecifier"
+#define kIASKPSTextFieldSpecifier             @"PSTextFieldSpecifier"
+#define kIASKPSChildPaneSpecifier             @"PSChildPaneSpecifier"
+#define kIASKOpenURLSpecifier                 @"IASKOpenURLSpecifier"
+#define kIASKButtonSpecifier                  @"IASKButtonSpecifier"
+#define kIASKMailComposeSpecifier             @"IASKMailComposeSpecifier"
+#define kIASKCustomViewSpecifier              @"IASKCustomViewSpecifier"
+
+#define kIASKBundleFolder                     @"Settings.bundle"
+#define kIASKBundleFolderAlt                  @"InAppSettings.bundle"
+#define kIASKBundleFilename                   @"Root.plist"
+#define KIASKBundleLocaleFolderExtension      @".lproj"
+
+#define kIASKAppSettingChanged                @"kAppSettingChanged"
+
+#define kIASKSectionHeaderIndex               0
+
+#define kIASKSliderNoImagesPadding            11
+#define kIASKSliderImagesPadding              43
+
+
+#define kIASKTableWidth                       320
+#define kIASKSpacing                          5
+#define kIASKMinLabelWidth                    97
+#define kIASKMinValueWidth                    35
+#define kIASKPaddingLeft                      9
+#define kIASKPaddingRight                     10
+#define kIASKHorizontalPaddingGroupTitles     19
+#define kIASKVerticalPaddingGroupTitles       15
+
+#define kIASKLabelFontSize                    17
+#define kIASKgrayBlueColor                    [UIColor colorWithRed:0.318 green:0.4 blue:0.569 alpha:1.0]
+
+#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_0
+#define kCFCoreFoundationVersionNumber_iPhoneOS_4_0 550.32
+#endif
+
+#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_1
+#define kCFCoreFoundationVersionNumber_iPhoneOS_4_1 550.38
+#endif
+
+
+#define IASK_IF_IOS4_OR_GREATER(...) \
+if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_0) \
+{ \
+__VA_ARGS__ \
+}
+
+ at class IASKSpecifier;
+
+ at interface IASKSettingsReader : NSObject {
+    NSString        *_path;
+    NSString        *_localizationTable;
+    NSString        *_bundlePath;
+    NSDictionary    *_settingsBundle;
+    NSArray         *_dataSource;
+    NSBundle        *_bundle;
+}
+
+- (id)initWithFile:(NSString*)file;
+- (NSInteger)numberOfSections;
+- (NSInteger)numberOfRowsForSection:(NSInteger)section;
+- (IASKSpecifier*)specifierForIndexPath:(NSIndexPath*)indexPath;
+- (NSIndexPath*)indexPathForKey:(NSString*)key;
+- (IASKSpecifier*)specifierForKey:(NSString*)key;
+- (NSString*)titleForSection:(NSInteger)section;
+- (NSString*)keyForSection:(NSInteger)section;
+- (NSString*)footerTextForSection:(NSInteger)section;
+- (NSString*)titleForStringId:(NSString*)stringId;
+- (NSString*)pathForImageNamed:(NSString*)image;
+
+ at property (nonatomic, strong) NSString      *path;
+ at property (nonatomic, strong) NSString      *localizationTable;
+ at property (nonatomic, strong) NSString      *bundlePath;
+ at property (nonatomic, strong) NSDictionary  *settingsBundle;
+ at property (nonatomic, strong) NSArray       *dataSource;
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSettingsReader.m b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsReader.m
new file mode 100755
index 0000000..3f73091
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsReader.m
@@ -0,0 +1,266 @@
+//
+//	IASKSettingsReader.m
+//	http://www.inappsettingskit.com
+//
+//	Copyright (c) 2009:
+//	Luc Vandal, Edovia Inc., http://www.edovia.com
+//	Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//	All rights reserved.
+//
+//	It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//	as the original authors of this code. You can give credit in a blog post, a tweet or on
+//	a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//	This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSettingsReader.h"
+#import "IASKSpecifier.h"
+
+ at interface IASKSettingsReader (private)
+- (void)_reinterpretBundle:(NSDictionary*)settingsBundle;
+- (BOOL)_sectionHasHeading:(NSInteger)section;
+- (NSString *)platformSuffix;
+- (NSString *)locateSettingsFile:(NSString *)file;
+
+ at end
+
+ at implementation IASKSettingsReader
+
+ at synthesize path=_path,
+localizationTable=_localizationTable,
+bundlePath=_bundlePath,
+settingsBundle=_settingsBundle,
+dataSource=_dataSource;
+
+- (id)init {
+	return [self initWithFile:@"Root"];
+}
+
+- (id)initWithFile:(NSString*)file {
+	if ((self=[super init])) {
+
+
+		self.path = [self locateSettingsFile: file];
+		[self setSettingsBundle:[NSDictionary dictionaryWithContentsOfFile:self.path]];
+		self.bundlePath = [self.path stringByDeletingLastPathComponent];
+		_bundle = [NSBundle bundleWithPath:[self bundlePath]];
+
+		// Look for localization file
+		self.localizationTable = [self.settingsBundle objectForKey:@"StringsTable"];
+		if (!self.localizationTable)
+		{
+			// Look for localization file using filename
+			self.localizationTable = [[[[self.path stringByDeletingPathExtension] // removes '.plist'
+										stringByDeletingPathExtension] // removes potential '.inApp'
+									   lastPathComponent] // strip absolute path
+									  stringByReplacingOccurrencesOfString:[self platformSuffix] withString:@""]; // removes potential '~device' (~ipad, ~iphone)
+			if([_bundle pathForResource:self.localizationTable ofType:@"strings"] == nil){
+				// Could not find the specified localization: use default
+				self.localizationTable = @"Root";
+			}
+		}
+
+		if (_settingsBundle) {
+			[self _reinterpretBundle:_settingsBundle];
+		}
+	}
+	return self;
+}
+
+- (void)dealloc {
+	_path = nil;
+	_localizationTable = nil;
+	_bundlePath = nil;
+	_settingsBundle = nil;
+	_dataSource = nil;
+	_bundle = nil;
+
+}
+
+- (void)_reinterpretBundle:(NSDictionary*)settingsBundle {
+	NSArray *preferenceSpecifiers	= [settingsBundle objectForKey:kIASKPreferenceSpecifiers];
+	NSInteger sectionCount			= -1;
+	NSMutableArray *dataSource		= [[NSMutableArray alloc] init];
+
+	for (NSDictionary *specifier in preferenceSpecifiers) {
+		if ([(NSString*)[specifier objectForKey:kIASKType] isEqualToString:kIASKPSGroupSpecifier]) {
+			NSMutableArray *newArray = [[NSMutableArray alloc] init];
+
+			[newArray addObject:specifier];
+			[dataSource addObject:newArray];
+			sectionCount++;
+		}
+		else {
+			if (sectionCount == -1) {
+				NSMutableArray *newArray = [[NSMutableArray alloc] init];
+				[dataSource addObject:newArray];
+				sectionCount++;
+			}
+
+			IASKSpecifier *newSpecifier = [[IASKSpecifier alloc] initWithSpecifier:specifier];
+			[(NSMutableArray*)[dataSource objectAtIndex:sectionCount] addObject:newSpecifier];
+		}
+	}
+	[self setDataSource:dataSource];
+}
+
+- (BOOL)_sectionHasHeading:(NSInteger)section {
+	return [[[[self dataSource] objectAtIndex:section] objectAtIndex:0] isKindOfClass:[NSDictionary class]];
+}
+
+- (NSInteger)numberOfSections {
+	return [[self dataSource] count];
+}
+
+- (NSInteger)numberOfRowsForSection:(NSInteger)section {
+	int headingCorrection = [self _sectionHasHeading:section] ? 1 : 0;
+	return [(NSArray*)[[self dataSource] objectAtIndex:section] count] - headingCorrection;
+}
+
+- (IASKSpecifier*)specifierForIndexPath:(NSIndexPath*)indexPath {
+	int headingCorrection = [self _sectionHasHeading:indexPath.section] ? 1 : 0;
+
+	IASKSpecifier *specifier = [[[self dataSource] objectAtIndex:indexPath.section] objectAtIndex:(indexPath.row+headingCorrection)];
+	specifier.settingsReader = self;
+	return specifier;
+}
+
+- (NSIndexPath*)indexPathForKey:(NSString *)key {
+	for (NSUInteger sectionIndex = 0; sectionIndex < self.dataSource.count; sectionIndex++) {
+		NSArray *section = [self.dataSource objectAtIndex:sectionIndex];
+		for (NSUInteger rowIndex = 0; rowIndex < section.count; rowIndex++) {
+			IASKSpecifier *specifier = (IASKSpecifier*)[section objectAtIndex:rowIndex];
+			if ([specifier isKindOfClass:[IASKSpecifier class]] && [specifier.key isEqualToString:key]) {
+				NSUInteger correctedRowIndex = rowIndex - [self _sectionHasHeading:sectionIndex];
+				return [NSIndexPath indexPathForRow:correctedRowIndex inSection:sectionIndex];
+			}
+		}
+	}
+	return nil;
+}
+
+- (IASKSpecifier*)specifierForKey:(NSString*)key {
+	for (NSArray *specifiers in _dataSource) {
+		for (id sp in specifiers) {
+			if ([sp isKindOfClass:[IASKSpecifier class]]) {
+				if ([[sp key] isEqualToString:key]) {
+					return sp;
+				}
+			}
+		}
+	}
+	return nil;
+}
+
+- (NSString*)titleForSection:(NSInteger)section {
+	if ([self _sectionHasHeading:section]) {
+		NSDictionary *dict = [[[self dataSource] objectAtIndex:section] objectAtIndex:kIASKSectionHeaderIndex];
+		return [self titleForStringId:[dict objectForKey:kIASKTitle]];
+	}
+	return nil;
+}
+
+- (NSString*)keyForSection:(NSInteger)section {
+	if ([self _sectionHasHeading:section]) {
+		return [[[[self dataSource] objectAtIndex:section] objectAtIndex:kIASKSectionHeaderIndex] objectForKey:kIASKKey];
+	}
+	return nil;
+}
+
+- (NSString*)footerTextForSection:(NSInteger)section {
+	if ([self _sectionHasHeading:section]) {
+		NSDictionary *dict = [[[self dataSource] objectAtIndex:section] objectAtIndex:kIASKSectionHeaderIndex];
+		return [self titleForStringId:[dict objectForKey:kIASKFooterText]];
+	}
+	return nil;
+}
+
+- (NSString*)titleForStringId:(NSString*)stringId {
+	return [_bundle localizedStringForKey:stringId value:stringId table:self.localizationTable];
+}
+
+- (NSString*)pathForImageNamed:(NSString*)image {
+	return [[self bundlePath] stringByAppendingPathComponent:image];
+}
+
+- (NSString *)platformSuffix {
+	BOOL isPad = NO;
+#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)
+	isPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
+#endif
+	return isPad ? @"~ipad" : @"~iphone";
+}
+
+- (NSString *)file:(NSString *)file
+		withBundle:(NSString *)bundle
+			suffix:(NSString *)suffix
+		 extension:(NSString *)extension {
+
+	NSString *appBundle = [[NSBundle mainBundle] bundlePath];
+	bundle = [appBundle stringByAppendingPathComponent:bundle];
+	file = [file stringByAppendingFormat:@"%@%@", suffix, extension];
+	return [bundle stringByAppendingPathComponent:file];
+
+}
+
+- (NSString *)locateSettingsFile: (NSString *)file {
+
+	// The file is searched in the following order:
+	//
+	// InAppSettings.bundle/FILE~DEVICE.inApp.plist
+	// InAppSettings.bundle/FILE.inApp.plist
+	// InAppSettings.bundle/FILE~DEVICE.plist
+	// InAppSettings.bundle/FILE.plist
+	// Settings.bundle/FILE~DEVICE.inApp.plist
+	// Settings.bundle/FILE.inApp.plist
+	// Settings.bundle/FILE~DEVICE.plist
+	// Settings.bundle/FILE.plist
+	//
+	// where DEVICE is either "iphone" or "ipad" depending on the current
+	// interface idiom.
+	//
+	// Settings.app uses the ~DEVICE suffixes since iOS 4.0.  There are some
+	// differences from this implementation:
+	// - For an iPhone-only app running on iPad, Settings.app will not use the
+	//	 ~iphone suffix.  There is no point in using these suffixes outside
+	//	 of universal apps anyway.
+	// - This implementation uses the device suffixes on iOS 3.x as well.
+	// - also check current locale (short only)
+
+	NSArray *bundles =
+	[NSArray arrayWithObjects:kIASKBundleFolderAlt, kIASKBundleFolder, nil];
+
+	NSArray *extensions =
+	[NSArray arrayWithObjects:@".inApp.plist", @".plist", nil];
+
+	NSArray *suffixes =
+	[NSArray arrayWithObjects:[self platformSuffix], @"", nil];
+
+	NSArray *languages =
+	[NSArray arrayWithObjects:[[[NSLocale preferredLanguages] objectAtIndex:0] stringByAppendingString:KIASKBundleLocaleFolderExtension], @"", nil];
+
+	NSString *path = nil;
+	NSFileManager *fileManager = [NSFileManager defaultManager];
+
+	for (NSString *bundle in bundles) {
+		for (NSString *extension in extensions) {
+			for (NSString *suffix in suffixes) {
+				for (NSString *language in languages) {
+					path = [self file:file
+						   withBundle:[bundle stringByAppendingPathComponent:language]
+							   suffix:suffix
+							extension:extension];
+					if ([fileManager fileExistsAtPath:path]) {
+						goto exitFromNestedLoop;
+					}
+				}
+			}
+		}
+	}
+
+exitFromNestedLoop:
+	return path;
+}
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStore.h b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStore.h
new file mode 100755
index 0000000..79639ac
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStore.h
@@ -0,0 +1,39 @@
+//
+//  IASKSettingsStore.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <Foundation/Foundation.h>
+
+ at protocol IASKSettingsStore <NSObject>
+ at required
+- (void)setBool:(BOOL)value      forKey:(NSString*)key;
+- (void)setFloat:(float)value    forKey:(NSString*)key;
+- (void)setDouble:(double)value  forKey:(NSString*)key;
+- (void)setInteger:(int)value    forKey:(NSString*)key;
+- (void)setObject:(id)value      forKey:(NSString*)key;
+- (BOOL)boolForKey:(NSString*)key;
+- (float)floatForKey:(NSString*)key;
+- (double)doubleForKey:(NSString*)key;
+- (int)integerForKey:(NSString*)key;
+- (id)objectForKey:(NSString*)key;
+- (BOOL)synchronize; // Write settings to a permanant storage. Returns YES on success, NO otherwise
+ at end
+
+
+ at interface IASKAbstractSettingsStore : NSObject <IASKSettingsStore> {
+}
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStore.m b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStore.m
new file mode 100755
index 0000000..8948459
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStore.m
@@ -0,0 +1,68 @@
+//
+//  IASKSettingsStore.m
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSettingsStore.h"
+
+ at implementation IASKAbstractSettingsStore
+
+- (void)setObject:(id)value forKey:(NSString*)key {
+    [NSException raise:@"Unimplemented"
+                format:@"setObject:forKey: must be implemented in subclasses of IASKAbstractSettingsStore"];
+}
+
+- (id)objectForKey:(NSString*)key {
+    [NSException raise:@"Unimplemented"
+                format:@"objectForKey: must be implemented in subclasses of IASKAbstractSettingsStore"];
+    return nil;
+}
+
+- (void)setBool:(BOOL)value forKey:(NSString*)key {
+    [self setObject:[NSNumber numberWithBool:value] forKey:key];
+}
+
+- (void)setFloat:(float)value forKey:(NSString*)key {
+    [self setObject:[NSNumber numberWithFloat:value] forKey:key];
+}
+
+- (void)setInteger:(int)value forKey:(NSString*)key {
+    [self setObject:[NSNumber numberWithInt:value] forKey:key];
+}
+
+- (void)setDouble:(double)value forKey:(NSString*)key {
+    [self setObject:[NSNumber numberWithDouble:value] forKey:key];
+}
+
+- (BOOL)boolForKey:(NSString*)key {
+    return [[self objectForKey:key] boolValue];
+}
+
+- (float)floatForKey:(NSString*)key {
+    return [[self objectForKey:key] floatValue];
+}
+- (int)integerForKey:(NSString*)key {
+    return [[self objectForKey:key] intValue];
+}
+
+- (double)doubleForKey:(NSString*)key {
+    return [[self objectForKey:key] doubleValue];
+}
+
+- (BOOL)synchronize {
+    return NO;
+}
+
+ at end
\ No newline at end of file
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreFile.h b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreFile.h
new file mode 100755
index 0000000..54331ed
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreFile.h
@@ -0,0 +1,28 @@
+//
+//  IASKSettingsStoreFile.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <Foundation/Foundation.h>
+#import "IASKSettingsStore.h"
+
+ at interface IASKSettingsStoreFile : IASKAbstractSettingsStore {
+    NSString * _filePath;
+    NSMutableDictionary * _dict;
+}
+
+- (id)initWithPath:(NSString*)path;
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreFile.m b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreFile.m
new file mode 100755
index 0000000..3192650
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreFile.m
@@ -0,0 +1,53 @@
+//
+//  IASKSettingsStoreFile.m
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSettingsStoreFile.h"
+
+
+ at implementation IASKSettingsStoreFile
+
+- (id)initWithPath:(NSString*)path {
+    if((self = [super init])) {
+        _filePath = path;
+        _dict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
+        if(_dict == nil) {
+            _dict = [[NSMutableDictionary alloc] init];
+        }
+    }
+    return self;
+}
+
+- (void)dealloc {
+    _dict = nil;
+    _filePath = nil;
+
+}
+
+
+- (void)setObject:(id)value forKey:(NSString *)key {
+    [_dict setObject:value forKey:key];
+}
+
+- (id)objectForKey:(NSString *)key {
+    return [_dict objectForKey:key];
+}
+
+- (BOOL)synchronize {
+    return [_dict writeToFile:_filePath atomically:YES];
+}
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.h b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.h
new file mode 100755
index 0000000..c1d2fce
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.h
@@ -0,0 +1,25 @@
+//
+//  IASKSettingsStoreUserDefaults.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <Foundation/Foundation.h>
+#import "IASKSettingsStore.h"
+
+ at interface IASKSettingsStoreUserDefaults : IASKAbstractSettingsStore {
+
+}
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.m b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.m
new file mode 100755
index 0000000..c5979f8
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.m
@@ -0,0 +1,67 @@
+//
+//  IASKSettingsStoreUserDefaults.m
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  Marc-Etienne M.Léveillé, Edovia Inc., http://www.edovia.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSettingsStoreUserDefaults.h"
+
+
+ at implementation IASKSettingsStoreUserDefaults
+
+- (void)setBool:(BOOL)value forKey:(NSString*)key {
+    [[NSUserDefaults standardUserDefaults] setBool:value forKey:key];
+}
+
+- (void)setFloat:(float)value forKey:(NSString*)key {
+    [[NSUserDefaults standardUserDefaults] setFloat:value forKey:key];
+}
+
+- (void)setDouble:(double)value forKey:(NSString*)key {
+    [[NSUserDefaults standardUserDefaults] setDouble:value forKey:key];
+}
+
+- (void)setInteger:(int)value forKey:(NSString*)key {
+    [[NSUserDefaults standardUserDefaults] setInteger:value forKey:key];
+}
+
+- (void)setObject:(id)value forKey:(NSString*)key {
+    [[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
+}
+
+- (BOOL)boolForKey:(NSString*)key {
+    return [[NSUserDefaults standardUserDefaults] boolForKey:key];
+}
+
+- (float)floatForKey:(NSString*)key {
+    return [[NSUserDefaults standardUserDefaults] floatForKey:key];
+}
+
+- (double)doubleForKey:(NSString*)key {
+    return [[NSUserDefaults standardUserDefaults] doubleForKey:key];
+}
+
+- (int)integerForKey:(NSString*)key {
+    return [[NSUserDefaults standardUserDefaults] integerForKey:key];
+}
+
+- (id)objectForKey:(NSString*)key {
+    return [[NSUserDefaults standardUserDefaults] objectForKey:key];
+}
+
+- (BOOL)synchronize {
+    return [[NSUserDefaults standardUserDefaults] synchronize];
+}
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSpecifier.h b/ios/iosremote/InAppSettingsKit/Models/IASKSpecifier.h
new file mode 100755
index 0000000..5053c40
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSpecifier.h
@@ -0,0 +1,59 @@
+//
+//  IASKSpecifier.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+ at class IASKSettingsReader;
+
+ at interface IASKSpecifier : NSObject {
+    NSDictionary    *_specifierDict;
+    NSDictionary    *_multipleValuesDict;
+    IASKSettingsReader *__unsafe_unretained _settingsReader;
+}
+ at property (nonatomic, strong) NSDictionary  *specifierDict;
+ at property (nonatomic, unsafe_unretained) IASKSettingsReader *settingsReader;
+
+- (id)initWithSpecifier:(NSDictionary*)specifier;
+- (NSString*)localizedObjectForKey:(NSString*)key;
+- (NSString*)title;
+- (NSString*)key;
+- (NSString*)type;
+- (NSString*)titleForCurrentValue:(id)currentValue;
+- (NSInteger)multipleValuesCount;
+- (NSArray*)multipleValues;
+- (NSArray*)multipleTitles;
+- (NSString*)file;
+- (id)defaultValue;
+- (id)defaultStringValue;
+- (BOOL)defaultBoolValue;
+- (id)trueValue;
+- (id)falseValue;
+- (float)minimumValue;
+- (float)maximumValue;
+- (NSString*)minimumValueImage;
+- (NSString*)maximumValueImage;
+- (BOOL)isSecure;
+- (UIKeyboardType)keyboardType;
+- (UITextAutocapitalizationType)autocapitalizationType;
+- (UITextAutocorrectionType)autoCorrectionType;
+- (NSString*)footerText;
+- (Class)viewControllerClass;
+- (SEL)viewControllerSelector;
+-(Class)buttonClass;
+-(SEL)buttonAction;
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Models/IASKSpecifier.m b/ios/iosremote/InAppSettingsKit/Models/IASKSpecifier.m
new file mode 100755
index 0000000..2ca65b2
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Models/IASKSpecifier.m
@@ -0,0 +1,239 @@
+//
+//  IASKSpecifier.m
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSpecifier.h"
+#import "IASKSettingsReader.h"
+
+ at interface IASKSpecifier ()
+ at property (nonatomic, strong) NSDictionary  *multipleValuesDict;
+- (void)_reinterpretValues:(NSDictionary*)specifierDict;
+ at end
+
+ at implementation IASKSpecifier
+
+ at synthesize specifierDict=_specifierDict;
+ at synthesize multipleValuesDict=_multipleValuesDict;
+ at synthesize settingsReader = _settingsReader;
+
+- (id)initWithSpecifier:(NSDictionary*)specifier {
+    if ((self = [super init])) {
+        [self setSpecifierDict:specifier];
+
+        if ([[self type] isEqualToString:kIASKPSMultiValueSpecifier] ||
+			[[self type] isEqualToString:kIASKPSTitleValueSpecifier]) {
+            [self _reinterpretValues:[self specifierDict]];
+        }
+    }
+    return self;
+}
+
+- (void)dealloc {
+    _specifierDict = nil;
+    _multipleValuesDict = nil;
+
+	_settingsReader = nil;
+
+}
+
+- (void)_reinterpretValues:(NSDictionary*)specifierDict {
+    NSArray *values = [_specifierDict objectForKey:kIASKValues];
+    NSArray *titles = [_specifierDict objectForKey:kIASKTitles];
+
+    NSMutableDictionary *multipleValuesDict = [[NSMutableDictionary alloc] init];
+
+    if (values) {
+		[multipleValuesDict setObject:values forKey:kIASKValues];
+	}
+
+    if (titles) {
+		[multipleValuesDict setObject:titles forKey:kIASKTitles];
+	}
+
+    [self setMultipleValuesDict:multipleValuesDict];
+}
+- (NSString*)localizedObjectForKey:(NSString*)key {
+	return [self.settingsReader titleForStringId:[_specifierDict objectForKey:key]];
+}
+
+- (NSString*)title {
+    return [self localizedObjectForKey:kIASKTitle];
+}
+
+- (NSString*)footerText {
+    return [self localizedObjectForKey:kIASKFooterText];
+}
+
+-(Class) viewControllerClass {
+    return NSClassFromString([_specifierDict objectForKey:kIASKViewControllerClass]);
+}
+
+-(SEL) viewControllerSelector {
+    return NSSelectorFromString([_specifierDict objectForKey:kIASKViewControllerSelector]);
+}
+
+-(Class)buttonClass {
+    return NSClassFromString([_specifierDict objectForKey:kIASKButtonClass]);
+}
+
+-(SEL)buttonAction {
+    return NSSelectorFromString([_specifierDict objectForKey:kIASKButtonAction]);
+}
+
+- (NSString*)key {
+    return [_specifierDict objectForKey:kIASKKey];
+}
+
+- (NSString*)type {
+    return [_specifierDict objectForKey:kIASKType];
+}
+
+- (NSString*)titleForCurrentValue:(id)currentValue {
+	NSArray *values = [self multipleValues];
+	NSArray *titles = [self multipleTitles];
+	if (values.count != titles.count) {
+		return nil;
+	}
+    NSInteger keyIndex = [values indexOfObject:currentValue];
+	if (keyIndex == NSNotFound) {
+		return nil;
+	}
+	@try {
+		return [self.settingsReader titleForStringId:[titles objectAtIndex:keyIndex]];
+	}
+	@catch (NSException * e) {}
+	return nil;
+}
+
+- (NSInteger)multipleValuesCount {
+    return [[_multipleValuesDict objectForKey:kIASKValues] count];
+}
+
+- (NSArray*)multipleValues {
+    return [_multipleValuesDict objectForKey:kIASKValues];
+}
+
+- (NSArray*)multipleTitles {
+    return [_multipleValuesDict objectForKey:kIASKTitles];
+}
+
+- (NSString*)file {
+    return [_specifierDict objectForKey:kIASKFile];
+}
+
+- (id)defaultValue {
+    return [_specifierDict objectForKey:kIASKDefaultValue];
+}
+
+- (id)defaultStringValue {
+    return [[_specifierDict objectForKey:kIASKDefaultValue] description];
+}
+
+- (BOOL)defaultBoolValue {
+	id defaultValue = [self defaultValue];
+	if ([defaultValue isEqual:[self trueValue]]) {
+		return YES;
+	}
+	if ([defaultValue isEqual:[self falseValue]]) {
+		return NO;
+	}
+	return [defaultValue boolValue];
+}
+
+- (id)trueValue {
+    return [_specifierDict objectForKey:kIASKTrueValue];
+}
+
+- (id)falseValue {
+    return [_specifierDict objectForKey:kIASKFalseValue];
+}
+
+- (float)minimumValue {
+    return [[_specifierDict objectForKey:kIASKMinimumValue] floatValue];
+}
+
+- (float)maximumValue {
+    return [[_specifierDict objectForKey:kIASKMaximumValue] floatValue];
+}
+
+- (NSString*)minimumValueImage {
+    return [_specifierDict objectForKey:kIASKMinimumValueImage];
+}
+
+- (NSString*)maximumValueImage {
+    return [_specifierDict objectForKey:kIASKMaximumValueImage];
+}
+
+- (BOOL)isSecure {
+    return [[_specifierDict objectForKey:kIASKIsSecure] boolValue];
+}
+
+- (UIKeyboardType)keyboardType {
+    if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardAlphabet]) {
+        return UIKeyboardTypeDefault;
+    }
+    else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumbersAndPunctuation]) {
+        return UIKeyboardTypeNumbersAndPunctuation;
+    }
+    else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumberPad]) {
+        return UIKeyboardTypeNumberPad;
+    }
+    else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardDecimalPad]) {
+		if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_1) {
+			return UIKeyboardTypeDecimalPad;
+		}
+		else {
+			return UIKeyboardTypeNumbersAndPunctuation;
+		}
+    }
+    else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:KIASKKeyboardURL]) {
+        return UIKeyboardTypeURL;
+    }
+    else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardEmailAddress]) {
+        return UIKeyboardTypeEmailAddress;
+    }
+    return UIKeyboardTypeDefault;
+}
+
+- (UITextAutocapitalizationType)autocapitalizationType {
+    if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapNone]) {
+        return UITextAutocapitalizationTypeNone;
+    }
+    else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapSentences]) {
+        return UITextAutocapitalizationTypeSentences;
+    }
+    else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapWords]) {
+        return UITextAutocapitalizationTypeWords;
+    }
+    else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapAllCharacters]) {
+        return UITextAutocapitalizationTypeAllCharacters;
+    }
+    return UITextAutocapitalizationTypeNone;
+}
+
+- (UITextAutocorrectionType)autoCorrectionType {
+    if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrDefault]) {
+        return UITextAutocorrectionTypeDefault;
+    }
+    else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrNo]) {
+        return UITextAutocorrectionTypeNo;
+    }
+    else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrYes]) {
+        return UITextAutocorrectionTypeYes;
+    }
+    return UITextAutocorrectionTypeDefault;
+}
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h b/ios/iosremote/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h
new file mode 100755
index 0000000..9a1f0f2
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h
@@ -0,0 +1,31 @@
+//
+//  IASKPSSliderSpecifierViewCell.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+ at class IASKSlider;
+
+ at interface IASKPSSliderSpecifierViewCell : UITableViewCell {
+    IASKSlider *__unsafe_unretained _slider;
+    UIImageView *__unsafe_unretained _minImage;
+    UIImageView *__unsafe_unretained _maxImage;
+}
+
+ at property (nonatomic, unsafe_unretained) IBOutlet IASKSlider *slider;
+ at property (nonatomic, unsafe_unretained) IBOutlet UIImageView *minImage;
+ at property (nonatomic, unsafe_unretained) IBOutlet UIImageView *maxImage;
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m b/ios/iosremote/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m
new file mode 100755
index 0000000..69187e9
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m
@@ -0,0 +1,71 @@
+//
+//  IASKPSSliderSpecifierViewCell.m
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009-2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKPSSliderSpecifierViewCell.h"
+#import "IASKSlider.h"
+#import "IASKSettingsReader.h"
+
+ at implementation IASKPSSliderSpecifierViewCell
+
+ at synthesize slider=_slider,
+            minImage=_minImage,
+            maxImage=_maxImage;
+
+- (void)layoutSubviews {
+    [super layoutSubviews];
+	CGRect  sliderBounds    = _slider.bounds;
+    CGPoint sliderCenter    = _slider.center;
+    const double superViewWidth = _slider.superview.frame.size.width;
+
+    sliderCenter.x = superViewWidth / 2;
+    sliderBounds.size.width = superViewWidth - kIASKSliderNoImagesPadding * 2;
+	_minImage.hidden = YES;
+	_maxImage.hidden = YES;
+
+	// Check if there are min and max images. If so, change the layout accordingly.
+	if (_minImage.image && _maxImage.image) {
+		// Both images
+		_minImage.hidden = NO;
+		_maxImage.hidden = NO;
+        sliderBounds.size.width  = superViewWidth - kIASKSliderImagesPadding * 2;
+	}
+	else if (_minImage.image) {
+		// Min image
+		_minImage.hidden = NO;
+		sliderCenter.x    += (kIASKSliderImagesPadding - kIASKSliderNoImagesPadding) / 2;
+		sliderBounds.size.width  = superViewWidth - kIASKSliderNoImagesPadding - kIASKSliderImagesPadding;
+	}
+	else if (_maxImage.image) {
+		// Max image
+		_maxImage.hidden = NO;
+		sliderCenter.x    -= (kIASKSliderImagesPadding - kIASKSliderNoImagesPadding) / 2;
+		sliderBounds.size.width  = superViewWidth - kIASKSliderNoImagesPadding - kIASKSliderImagesPadding;
+	}
+
+	_slider.bounds = sliderBounds;
+    _slider.center = sliderCenter;
+}
+
+- (void)dealloc {
+	_minImage.image = nil;
+	_maxImage.image = nil;
+}
+
+- (void)prepareForReuse {
+	_minImage.image = nil;
+	_maxImage.image = nil;
+}
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h b/ios/iosremote/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h
new file mode 100755
index 0000000..2d6be58
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h
@@ -0,0 +1,29 @@
+//
+//  IASKPSTextFieldSpecifierViewCell.h
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+ at class IASKTextField;
+
+ at interface IASKPSTextFieldSpecifierViewCell : UITableViewCell {
+    UILabel *__unsafe_unretained _label;
+    IASKTextField *__unsafe_unretained _textField;
+}
+
+ at property (nonatomic, unsafe_unretained) IBOutlet UILabel *label;
+ at property (nonatomic, unsafe_unretained) IBOutlet IASKTextField *textField;
+
+ at end
diff --git a/ios/iosremote/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.m b/ios/iosremote/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.m
new file mode 100755
index 0000000..39648c2
--- /dev/null
+++ b/ios/iosremote/InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.m
@@ -0,0 +1,49 @@
+//
+//  IASKPSTextFieldSpecifierViewCell.m
+//  http://www.inappsettingskit.com
+//
+//  Copyright (c) 2009-2010:
+//  Luc Vandal, Edovia Inc., http://www.edovia.com
+//  Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+//  All rights reserved.
+//
+//  It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+//  as the original authors of this code. You can give credit in a blog post, a tweet or on
+//  a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+//  This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKPSTextFieldSpecifierViewCell.h"

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list