[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