2 // RootViewController.m
5 // Created by Mike Mayo on 9/30/10.
6 // The OpenStack project is provided under the Apache 2.0 license.
9 #import "RootViewController.h"
10 #import "ProvidersViewController.h"
11 #import "OpenStackAccount.h"
14 #import "ActivityIndicatorView.h"
15 #import "UIViewController+Conveniences.h"
16 #import "SettingsViewController.h"
18 #import "PasscodeViewController.h"
19 #import "OpenStackAppDelegate.h"
20 #import "AccountHomeViewController.h"
23 @implementation RootViewController
25 @synthesize tableView, popoverController, detailItem;
26 @synthesize restoreAccountView;
28 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
29 return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
32 - (void)restoreProviderView:(AccountDetailsViewController *)accountDetailsViewController {
33 OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
34 ProvidersViewController *vc = [[ProvidersViewController alloc] initWithNibName:@"ProvidersViewController" bundle:nil];
35 vc.rootViewController = self;
36 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
37 vc.modalPresentationStyle = UIModalPresentationFormSheet;
38 if (app.rootViewController.popoverController != nil) {
39 [app.rootViewController.popoverController dismissPopoverAnimated:YES];
42 [self presentModalViewControllerWithNavigation:vc animated:NO];
43 [vc restoreAccountDetailsViewController:accountDetailsViewController];
47 - (void)restoreAccountView:(AccountSettingsViewController *)accountSettingsViewController {
48 AccountHomeViewController *vc = [[AccountHomeViewController alloc] initWithNibName:@"AccountHomeViewController" bundle:nil];
49 vc.account = accountSettingsViewController.account;
50 vc.account.hasBeenRefreshed = NO;
51 vc.rootViewController = self;
52 [self.navigationController pushViewController:vc animated:YES];
57 #pragma mark Split view support
60 When setting the detail item, update the view and dismiss the popover controller if it's showing.
62 - (void)setDetailItem:(id)newDetailItem {
63 if (detailItem != newDetailItem) {
65 detailItem = [newDetailItem retain];
68 if (self.popoverController != nil) {
69 [self.popoverController dismissPopoverAnimated:YES];
73 - (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {
74 OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
75 app.barButtonItem = barButtonItem;
76 UIViewController *vc = [[[app.splitViewController.viewControllers objectAtIndex:1] viewControllers] lastObject];
77 barButtonItem.title = [[[self.navigationController.viewControllers lastObject] navigationItem] title];
78 vc.navigationItem.leftBarButtonItem = barButtonItem;
79 self.popoverController = pc;
82 - (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
83 OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
84 app.barButtonItem = barButtonItem;
85 UIViewController *vc = [[[app.splitViewController.viewControllers objectAtIndex:1] viewControllers] lastObject];
86 vc.navigationItem.leftBarButtonItem = nil;
87 self.popoverController = nil;
91 #pragma mark Button Handlers
93 - (void)addButtonPressed:(id)sender {
94 OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
95 ProvidersViewController *vc = [[ProvidersViewController alloc] initWithNibName:@"ProvidersViewController" bundle:nil];
96 vc.rootViewController = self;
97 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
98 vc.modalPresentationStyle = UIModalPresentationFormSheet;
99 if (app.rootViewController.popoverController != nil) {
100 [app.rootViewController.popoverController dismissPopoverAnimated:YES];
103 [self presentModalViewControllerWithNavigation:vc];
107 - (void)settingsButtonPressed:(id)sender {
109 //self.navigationController.navigationBarHidden = YES;
111 //UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 460.0)];
113 SettingsViewController *settingsViewController = [[SettingsViewController alloc] initWithNibName:@"SettingsViewController" bundle:nil];
115 UINavigationController *settingsNavigationController = [[UINavigationController alloc] initWithRootViewController:settingsViewController];
116 settingsNavigationController.view.frame = CGRectMake(0.0, 0.0, 320.0, 460.0);
118 if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
119 settingsNavigationController.navigationBar.tintColor = self.navigationController.navigationBar.tintColor;
120 settingsNavigationController.navigationBar.translucent = self.navigationController.navigationBar.translucent;
121 settingsNavigationController.navigationBar.opaque = self.navigationController.navigationBar.opaque;
122 settingsNavigationController.navigationBar.barStyle = self.navigationController.navigationBar.barStyle;
124 settingsNavigationController.navigationBar.barStyle = UIBarStyleBlack;
125 settingsNavigationController.navigationBar.opaque = NO;
128 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
129 if (self.popoverController != nil) {
130 [self.popoverController dismissPopoverAnimated:YES];
132 settingsNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
133 [self presentModalViewController:settingsNavigationController animated:YES];
135 settingsNavigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
136 [self presentModalViewController:settingsNavigationController animated:YES];
139 [settingsViewController release];
140 [settingsNavigationController release];
146 #pragma mark View lifecycle
148 - (void)setEditing:(BOOL)editing animated:(BOOL)animated {
149 [self.tableView setEditing:editing animated:animated];
150 [super setEditing:editing animated:animated];
153 - (void)presentAndRelease:(NSTimer *)timer {
154 UIViewController *vc = [timer.userInfo objectForKey:@"vc"];
155 [self presentModalViewControllerWithNavigation:vc animated:NO];
159 - (void)viewDidLoad {
161 self.navigationItem.title = @"Accounts";
163 self.navigationItem.leftBarButtonItem = self.editButtonItem;
165 UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonPressed:)];
166 self.navigationItem.rightBarButtonItem = addButton;
169 if ([[OpenStackAccount accounts] count] == 0) {
170 // if there are no accounts, go straight to the add account screen on launch
171 ProvidersViewController *vc = [[ProvidersViewController alloc] initWithNibName:@"ProvidersViewController" bundle:nil];
172 vc.rootViewController = self;
173 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
174 vc.modalPresentationStyle = UIModalPresentationFormSheet;
176 [self presentModalViewControllerWithNavigation:vc animated:NO];
179 } else if ([[OpenStackAccount accounts] count] == 1 && UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
180 // if there's only one account, go to its home screen
181 // NOTE: not doing this on iPad because it screws up the split view controller.
182 // TODO: make this work well with split view on iPad
183 AccountHomeViewController *vc = [[AccountHomeViewController alloc] initWithNibName:@"AccountHomeViewController" bundle:nil];
184 vc.account = [[OpenStackAccount accounts] objectAtIndex:0];
185 vc.rootViewController = self;
186 vc.rootViewIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
187 [self.navigationController pushViewController:vc animated:NO];
193 - (void)viewWillAppear:(BOOL)animated {
194 [super viewWillAppear:animated];
195 [self.tableView reloadData];
198 - (void)viewDidAppear:(BOOL)animated {
199 [super viewDidAppear:animated];
203 - (void)viewWillDisappear:(BOOL)animated {
204 [super viewWillDisappear:animated];
208 - (void)viewDidDisappear:(BOOL)animated {
209 [super viewDidDisappear:animated];
214 #pragma mark Table view data source
216 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
220 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
221 return [[OpenStackAccount accounts] count];
224 - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
226 static NSString *CellIdentifier = @"Cell";
228 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
230 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
231 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
234 // Configure the cell.
235 OpenStackAccount *account = [[OpenStackAccount accounts] objectAtIndex:indexPath.row];
236 cell.textLabel.text = account.username;
237 cell.detailTextLabel.text = account.provider.name;
239 if (account.provider.logoURLs && [account.provider.logoURLs objectForKey:@"provider_icon"]) {
240 cell.imageView.image = [UIImage imageNamed:[account.provider.logoURLs objectForKey:@"provider_icon"]];
242 cell.imageView.image = [UIImage imageNamed:@"pithos-solo-smallest.png"];
248 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
252 - (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
254 if (editingStyle == UITableViewCellEditingStyleDelete) {
255 NSMutableArray *accounts = [NSMutableArray arrayWithArray:[OpenStackAccount accounts]];
256 [[accounts objectAtIndex:indexPath.row] setFlaggedForDelete:YES];
257 [accounts removeObjectAtIndex:indexPath.row];
258 [OpenStackAccount persist:accounts];
260 // Delete the row from the data source.
261 [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
263 } else if (editingStyle == UITableViewCellEditingStyleInsert) {
264 // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
268 // Override to support rearranging the table view.
269 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
270 NSMutableArray *accounts = [NSMutableArray arrayWithArray:[OpenStackAccount accounts]];
271 OpenStackAccount *account = [accounts objectAtIndex:fromIndexPath.row];
272 [accounts removeObjectAtIndex:fromIndexPath.row];
273 [accounts insertObject:account atIndex:toIndexPath.row];
274 [OpenStackAccount persist:accounts];
277 // Override to support conditional rearranging of the table view.
278 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
279 // Return NO if you do not want the item to be re-orderable.
284 #pragma mark Table view delegate
286 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
287 AccountHomeViewController *vc = [[AccountHomeViewController alloc] initWithNibName:@"AccountHomeViewController" bundle:nil];
288 vc.account = [[OpenStackAccount accounts] objectAtIndex:indexPath.row];
289 vc.account.hasBeenRefreshed = NO;
290 vc.rootViewController = self;
291 vc.rootViewIndexPath = indexPath;
292 [self.navigationController pushViewController:vc animated:YES];
297 #pragma mark Memory management
299 - (void)didReceiveMemoryWarning {
300 // Releases the view if it doesn't have a superview.
301 [super didReceiveMemoryWarning];
303 // Relinquish ownership any cached data, images, etc that aren't in use.
306 - (void)viewDidUnload {
307 // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
308 // For example: self.myOutlet = nil;
314 [popoverController release];
315 [detailItem release];