Files
phonegap-plugins/iOS/PickerView/PickerView.m
2012-04-09 17:02:17 +02:00

339 lines
13 KiB
Objective-C

//
// PickerView.m
//
// Created by Olivier Louvignes on 11/28/2011.
//
// Copyright 2011 Olivier Louvignes. All rights reserved.
// MIT Licensed
#import "PickerView.h"
// Private interface
@interface PickerView()
@property (nonatomic, retain) UIPickerView *pickerView;
@end
@implementation PickerView
@synthesize pickerView = _pickerView;
@synthesize callbackID;
@synthesize systemMajorVersion;
@synthesize actionSheet;
@synthesize popoverController;
@synthesize items;
-(void)create:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
{
//NSLog(@"PickerView::create():arguments: %@", arguments);
//NSLog(@"PickerView::create():options: %@", options);
// The first argument in the arguments parameter is the callbackID.
// We use this to send data back to the successCallback or failureCallback
// through PluginResult.
self.callbackID = [arguments pop];
self.systemMajorVersion = [[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue];
// Compiling options with defaults
NSString *title = [options objectForKey:@"title"] ?: @" ";
NSString *style = [options objectForKey:@"style"] ?: @"default";
NSString *doneButtonLabel = [options objectForKey:@"doneButtonLabel"] ?: @"Done";
NSString *cancelButtonLabel = [options objectForKey:@"cancelButtonLabel"] ?: @"Cancel";
// Hold slots items in an instance variable
self.items = [options objectForKey:@"items"];
// Initialize PickerView
self.pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 40.0f, 320.0f, 162.0f)];
self.pickerView.showsSelectionIndicator = YES;
self.pickerView.delegate = self;
// Loop through slots to define default value
for(int i = 0; i < [self.items count]; i++) {
NSDictionary *slot = [self.items objectAtIndex:i];
// Check for a default value
NSString *defaultValue = [NSString stringWithFormat:@"%@", [slot objectForKey:@"value"]];
if([slot objectForKey:@"data"] && defaultValue) {
// Loop through slot data
for(int j = 0; j < [[slot objectForKey:@"data"] count]; j++) {
NSDictionary *slotData = [[slot objectForKey:@"data"] objectAtIndex:j];
NSString *slotDataValue = [NSString stringWithFormat:@"%@", [slotData objectForKey:@"value"]];
// Check for a default value match
if([slotDataValue isEqualToString:defaultValue]) {
[self.pickerView selectRow:j inComponent:i animated:NO];
}
}
}
}
// Check if device is iPad as we won't be able to use an ActionSheet there
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
return [self createForIpad:arguments withDict:options];
}
// Create actionSheet
self.actionSheet = [[UIActionSheet alloc] initWithTitle:title
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
// Style actionSheet, defaults to UIActionSheetStyleDefault
if([style isEqualToString:@"black-opaque"]) actionSheet.actionSheetStyle = UIActionSheetStyleBlackOpaque;
else if([style isEqualToString:@"black-translucent"]) actionSheet.actionSheetStyle = UIActionSheetStyleBlackTranslucent;
else actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
// Append pickerView
[actionSheet addSubview:self.pickerView];
[self.pickerView release];
// Create segemented cancel button
UISegmentedControl *cancelButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:cancelButtonLabel]];
cancelButton.momentary = YES;
cancelButton.frame = CGRectMake(5.0f, 7.0f, 50.0f, 30.0f);
cancelButton.segmentedControlStyle = UISegmentedControlStyleBar;
cancelButton.tintColor = [UIColor blackColor];
[cancelButton addTarget:self action:@selector(segmentedControl:didDismissWithCancelButton:) forControlEvents:UIControlEventValueChanged];
// Append close button
[actionSheet addSubview:cancelButton];
[cancelButton release];
// Create segemented done button
UISegmentedControl *doneButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:doneButtonLabel]];
doneButton.momentary = YES;
doneButton.frame = CGRectMake(265.0f, 7.0f, 50.0f, 30.0f);
doneButton.segmentedControlStyle = UISegmentedControlStyleBar;
doneButton.tintColor = [UIColor colorWithRed:51.0f/255.0f green:102.0f/255.0f blue:153.0f/255.0f alpha:1.0f];
[doneButton addTarget:self action:@selector(segmentedControl:didDismissWithDoneButton:) forControlEvents:UIControlEventValueChanged];
// Append done button
[actionSheet addSubview:doneButton];
[doneButton release];
//[actionSheet sendSubviewToBack:pickerView];
// Toggle ActionSheet
[actionSheet showInView:self.webView.superview];
// Resize actionSheet was 360
float actionSheetHeight;
if(systemMajorVersion == 5) {
actionSheetHeight = 360.0f;
} else {
actionSheetHeight = 472.0f;
}
[actionSheet setBounds:CGRectMake(0, 0, 320.0f, actionSheetHeight)];
}
-(void)createForIpad:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
{
NSString *doneButtonLabel = [options objectForKey:@"doneButtonLabel"] ?: @"Done";
NSString *cancelButtonLabel = [options objectForKey:@"cancelButtonLabel"] ?: @"Cancel";
// Create a generic content view controller
UINavigationController* popoverContent = [[UINavigationController alloc] init];
// Create a generic container view
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320.0f, 162.0f)];
popoverContent.view = popoverView;
// Append pickerView
[popoverView addSubview:self.pickerView];
[self.pickerView release];
/*
UIBarButtonItem *okButton = [[UIBarButtonItem alloc] initWithTitle:@"Ok" style:UIBarButtonItemStyleBordered target:self action:@selector(okayButtonPressed)];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(cancelButtonPressed)];
[popoverContent.navigationItem setLeftBarButtonItem:cancelButton animated:NO];
[popoverContent.navigationItem setRightBarButtonItem:okButton animated:NO];
popoverContent.topViewController.navigationItem.title = @"MY TITLE!";
popoverContent.navigationItem.title = @"MY TITLE!";
*/
// Create segemented cancel button
UISegmentedControl *cancelButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:cancelButtonLabel]];
cancelButton.momentary = YES;
cancelButton.frame = CGRectMake(5.0f, 7.0f, 50.0f, 30.0f);
cancelButton.segmentedControlStyle = UISegmentedControlStyleBar;
cancelButton.tintColor = [UIColor blackColor];
[cancelButton addTarget:self action:@selector(segmentedControl:didDismissWithCancelButton:) forControlEvents:UIControlEventValueChanged];
// Append close button
[popoverView addSubview:cancelButton];
[cancelButton release];
// Create segemented done button
UISegmentedControl *doneButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:doneButtonLabel]];
doneButton.momentary = YES;
doneButton.frame = CGRectMake(265.0f, 7.0f, 50.0f, 30.0f);
doneButton.segmentedControlStyle = UISegmentedControlStyleBar;
doneButton.tintColor = [UIColor colorWithRed:51.0f/255.0f green:102.0f/255.0f blue:153.0f/255.0f alpha:1.0f];
[doneButton addTarget:self action:@selector(segmentedControl:didDismissWithDoneButton:) forControlEvents:UIControlEventValueChanged];
// Append done button
[popoverView addSubview:doneButton];
[doneButton release];
// Resize the popover view shown
// in the current view to the view's size
popoverContent.contentSizeForViewInPopover = CGSizeMake(320.0f, 162.0f);
// Create a popover controller
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
popoverController.delegate = self;
//present the popover view non-modal with a
//refrence to the button pressed within the current view
[popoverController presentPopoverFromRect:CGRectMake(374.0f, 1014.0f, 20.0f, 20.0f)
inView:self.webView.superview
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
//release the popover content
[popoverView release];
[popoverContent release];
}
//
// Dismiss methods
//
// Picker with segmentedControls dismissed with done
- (void)segmentedControl:(UISegmentedControl *)segmentedControl didDismissWithDoneButton:(NSInteger)buttonIndex
{
//NSLog(@"didDismissWithDoneButton:%d", buttonIndex);
// Check if device is iPad
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
// Emulate a new delegate method
[self popoverController:popoverController dismissWithClickedButtonIndex:1 animated:YES];
} else {
[actionSheet dismissWithClickedButtonIndex:1 animated:YES];
}
}
// Picker with segmentedControls dismissed with cancel
- (void)segmentedControl:(UISegmentedControl *)segmentedControl didDismissWithCancelButton:(NSInteger)buttonIndex
{
//NSLog(@"didDismissWithCancelButton:%d", buttonIndex);
// Check if device is iPad
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
// Emulate a new delegate method
[self popoverController:popoverController dismissWithClickedButtonIndex:0 animated:YES];
} else {
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
}
// Popover generic dismiss - iPad
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
//NSLog(@"popoverControllerDidDismissPopover");
// Retreive pickerView
NSArray *subviews = [self.popoverController.contentViewController.view subviews];
UIPickerView *pickerView = [subviews objectAtIndex:0];
// Simulate a cancel click
[self sendResultsFromPickerView:pickerView withButtonIndex:0];
}
// Popover emulated button-powered dismiss - iPad
- (void)popoverController:(UIPopoverController *)popoverController dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(Boolean)animated
{
//NSLog(@"didDismissPopoverWithButtonIndex:%d", buttonIndex);
// Manually dismiss the popover
[self.popoverController dismissPopoverAnimated:animated];
// Retreive pickerView
NSArray *subviews = [self.popoverController.contentViewController.view subviews];
UIPickerView *pickerView = [subviews objectAtIndex:0];
[self sendResultsFromPickerView:pickerView withButtonIndex:buttonIndex];
// Release objects
[self.popoverController release];
}
// ActionSheet generic dismiss - iPhone
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
//NSLog(@"didDismissWithButtonIndex:%d", buttonIndex);
// Retreive pickerView
NSArray *subviews = [self.actionSheet subviews];
UIPickerView *pickerView = [subviews objectAtIndex:1];
[self sendResultsFromPickerView:pickerView withButtonIndex:buttonIndex];
// Release objects
[self.actionSheet release];
}
//
// Results
//
- (void)sendResultsFromPickerView:(UIPickerView *)pickerView withButtonIndex:(NSInteger)buttonIndex {
// Build returned result
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
NSMutableDictionary *values = [[NSMutableDictionary alloc] init];
// Loop throught slots
for(int i = 0; i < [items count]; i++) {
NSInteger selectedRow = [pickerView selectedRowInComponent:i];
NSString *selectedValue = [[[[items objectAtIndex:i] objectForKey:@"data"] objectAtIndex:selectedRow] objectForKey:@"value"];
NSString *slotName = [[items objectAtIndex:i] objectForKey:@"name"] ?: [NSString stringWithFormat:@"%d", i];
[values setObject:selectedValue forKey:slotName];
}
[result setObject:[NSNumber numberWithInteger:buttonIndex] forKey:@"buttonIndex"];
[result setObject:values forKey:@"values"];
// Create Plugin Result
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result];
// Checking if cancel was clicked
if (buttonIndex == 0) {
//Call the Failure Javascript function
[self writeJavascript: [pluginResult toErrorCallbackString:self.callbackID]];
}else {
//Call the Success Javascript function
[self writeJavascript: [pluginResult toSuccessCallbackString:self.callbackID]];
}
}
//
// Picker delegate
//
// Listen picker selected row
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
//NSLog(@"didSelectRow %d", row);
}
// Tell the picker how many rows are available for a given component
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [[[items objectAtIndex:component] objectForKey:@"data"] count];
}
// Tell the picker how many components it will have
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return [items count];
}
// Tell the picker the title for a given component
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
//NSLog(@"%d:%d", component, row);
return [[[[items objectAtIndex:component] objectForKey:@"data"] objectAtIndex:row] objectForKey:@"text"];
}
// Tell the picker the width of each row for a given component
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return 300.0f/[items count];
}
@end