+/* Role Controller {{{ */
+@interface RoleController : CYViewController <
+ UITableViewDataSource,
+ UITableViewDelegate
+> {
+ _transient Database *database_;
+ id roledelegate_;
+ UITableView *table_;
+ UISegmentedControl *segment_;
+ UIView *container_;
+}
+
+- (void) showDoneButton;
+- (void) resizeSegmentedControl;
+
+@end
+
+@implementation RoleController
+- (void) dealloc {
+ [table_ release];
+ [segment_ release];
+ [container_ release];
+
+ [super dealloc];
+}
+
+- (id) initWithDatabase:(Database *)database delegate:(id)delegate {
+ if ((self = [super init])) {
+ database_ = database;
+ roledelegate_ = delegate;
+
+ [[self navigationItem] setTitle:UCLocalize("WHO_ARE_YOU")];
+
+ NSArray *items = [NSArray arrayWithObjects:
+ UCLocalize("USER"),
+ UCLocalize("HACKER"),
+ UCLocalize("DEVELOPER"),
+ nil];
+ segment_ = [[UISegmentedControl alloc] initWithItems:items];
+ container_ = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[self view] frame].size.width, 44.0f)];
+ [container_ addSubview:segment_];
+
+ int index = -1;
+ if ([Role_ isEqualToString:@"User"]) index = 0;
+ if ([Role_ isEqualToString:@"Hacker"]) index = 1;
+ if ([Role_ isEqualToString:@"Developer"]) index = 2;
+ if (index != -1) {
+ [segment_ setSelectedSegmentIndex:index];
+ [self showDoneButton];
+ }
+
+ [segment_ addTarget:self action:@selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];
+ [self resizeSegmentedControl];
+
+ table_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped];
+ [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+ [table_ setDelegate:self];
+ [table_ setDataSource:self];
+ [[self view] addSubview:table_];
+ [table_ reloadData];
+ } return self;
+}
+
+- (void) resizeSegmentedControl {
+ CGFloat width = [[self view] frame].size.width;
+ [segment_ setFrame:CGRectMake(width / 32.0f, 0, width - (width / 32.0f * 2.0f), 44.0f)];
+}
+
+- (void) viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+
+ [self resizeSegmentedControl];
+}
+
+- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
+ [self resizeSegmentedControl];
+}
+
+- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
+ [self resizeSegmentedControl];
+}
+
+- (void) save {
+ NSString *role = nil;
+
+ switch ([segment_ selectedSegmentIndex]) {
+ case 0: role = @"User"; break;
+ case 1: role = @"Hacker"; break;
+ case 2: role = @"Developer"; break;
+
+ _nodefault
+ }
+
+ if (![role isEqualToString:Role_]) {
+ Role_ = role;
+
+ Settings_ = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ Role_, @"Role",
+ nil];
+
+ [Metadata_ setObject:Settings_ forKey:@"Settings"];
+
+ Changed_ = true;
+
+ [roledelegate_ updateData];
+ }
+}
+
+- (void) segmentChanged:(UISegmentedControl *)control {
+ [self showDoneButton];
+}
+
+- (void) doneButtonClicked {
+ [self save];
+ [[self navigationController] dismissModalViewControllerAnimated:YES];
+}
+
+- (void) showDoneButton {
+ UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]
+ initWithTitle:UCLocalize("DONE")
+ style:UIBarButtonItemStyleDone
+ target:self
+ action:@selector(doneButtonClicked)
+ ];
+ [[self navigationItem] setRightBarButtonItem:rightItem animated:[[self navigationItem] rightBarButtonItem] == nil];
+ [rightItem release];
+}
+
+- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
+ // XXX: For not having a single cell in the table, this sure is a lot of sections.
+ return 6;
+}
+
+- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return 0; // :(
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ return nil; // This method is required by the protocol.
+}
+
+- (NSString *) tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
+ if (section == 1)
+ return UCLocalize("ROLE_EX");
+ if (section == 4)
+ return [NSString stringWithFormat:
+ @"%@: %@\n%@: %@\n%@: %@",
+ UCLocalize("USER"), UCLocalize("USER_EX"),
+ UCLocalize("HACKER"), UCLocalize("HACKER_EX"),
+ UCLocalize("DEVELOPER"), UCLocalize("DEVELOPER_EX")
+ ];
+ else return nil;
+}
+
+- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
+ if (section == 3) return 44.0f;
+ else return 0;
+}
+
+- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
+ if (section == 3) return container_;
+ else return nil;
+}
+
+@end
+/* }}} */
+
+/* Cydia Container {{{ */
+@interface CYContainer : UIViewController <ProgressDelegate> {
+ _transient Database *database_;
+ RefreshBar *refreshbar_;
+
+ bool dropped_;
+ bool updating_;
+ id updatedelegate_;
+ UITabBarController *root_;
+}
+
+- (void) setTabBarController:(UITabBarController *)controller;
+
+- (void) dropBar:(BOOL)animated;
+- (void) beginUpdate;
+- (void) raiseBar:(BOOL)animated;
+
+@end
+
+@implementation CYContainer
+
+// NOTE: UIWindow only sends the top controller these messages,
+// So we have to forward them on.
+
+- (void) viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ [root_ viewDidAppear:animated];
+}
+
+- (void) viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+ [root_ viewWillAppear:animated];
+}
+
+- (void) viewDidDisappear:(BOOL)animated {
+ [super viewDidDisappear:animated];
+ [root_ viewDidDisappear:animated];
+}
+
+- (void) viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ [root_ viewWillDisappear:animated];
+}
+
+- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
+ return YES; /* XXX: return YES; */
+}
+
+- (void) setTabBarController:(UITabBarController *)controller {
+ root_ = controller;
+ [[self view] addSubview:[root_ view]];
+}
+
+- (void) setUpdate:(NSDate *)date {
+ [self beginUpdate];
+}
+
+- (void) beginUpdate {
+ [self dropBar:YES];
+ [refreshbar_ start];
+
+ updating_ = true;
+
+ [NSThread
+ detachNewThreadSelector:@selector(performUpdate)
+ toTarget:self
+ withObject:nil
+ ];
+}
+
+- (void) performUpdate { _pooled
+ Status status;
+ status.setDelegate(self);
+ [database_ updateWithStatus:status];
+
+ [self
+ performSelectorOnMainThread:@selector(completeUpdate)
+ withObject:nil
+ waitUntilDone:NO
+ ];
+}
+
+- (void) completeUpdate {
+ updating_ = false;
+
+ [self raiseBar:YES];
+ [refreshbar_ stop];
+ [updatedelegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0];
+}
+
+- (void) cancelUpdate {
+ [refreshbar_ cancel];
+ [self completeUpdate];
+}
+
+- (void) cancelPressed {
+ [self cancelUpdate];
+}
+
+- (BOOL) updating {
+ return updating_;
+}
+
+- (void) setProgressError:(NSString *)error withTitle:(NSString *)title {
+ [refreshbar_ setPrompt:[NSString stringWithFormat:UCLocalize("COLON_DELIMITED"), UCLocalize("ERROR"), error]];
+}
+
+- (void) startProgress {
+}
+
+- (void) setProgressTitle:(NSString *)title {
+ [self
+ performSelectorOnMainThread:@selector(_setProgressTitle:)
+ withObject:title
+ waitUntilDone:YES
+ ];
+}
+
+- (bool) isCancelling:(size_t)received {
+ return !updating_;
+}
+
+- (void) setProgressPercent:(float)percent {
+ [self
+ performSelectorOnMainThread:@selector(_setProgressPercent:)
+ withObject:[NSNumber numberWithFloat:percent]
+ waitUntilDone:YES
+ ];
+}
+
+- (void) addProgressOutput:(NSString *)output {
+ [self
+ performSelectorOnMainThread:@selector(_addProgressOutput:)
+ withObject:output
+ waitUntilDone:YES
+ ];
+}
+
+- (void) _setProgressTitle:(NSString *)title {
+ [refreshbar_ setPrompt:title];
+}
+
+- (void) _setProgressPercent:(NSNumber *)percent {
+ [refreshbar_ setProgress:[percent floatValue]];
+}
+
+- (void) _addProgressOutput:(NSString *)output {
+}
+
+- (void) setUpdateDelegate:(id)delegate {
+ updatedelegate_ = delegate;
+}
+
+- (void) dropBar:(BOOL)animated {
+ if (dropped_) return;
+ dropped_ = true;
+
+ [[self view] addSubview:refreshbar_];
+
+ if (animated) [UIView beginAnimations:nil context:NULL];
+ CGRect barframe = [refreshbar_ frame];
+ CGRect viewframe = [[root_ view] frame];
+ viewframe.origin.y += barframe.size.height + 20.0f;
+ viewframe.size.height -= barframe.size.height + 20.0f;
+ [[root_ view] setFrame:viewframe];
+ if (animated) [UIView commitAnimations];
+
+ // Ensure bar has the proper width for our view, it might have changed
+ barframe.size.width = viewframe.size.width;
+ [refreshbar_ setFrame:barframe];
+
+ // XXX: fix Apple's layout bug
+ [[root_ selectedViewController] _updateLayoutForStatusBarAndInterfaceOrientation];
+}
+
+- (void) raiseBar:(BOOL)animated {
+ if (!dropped_) return;
+ dropped_ = false;
+
+ [refreshbar_ removeFromSuperview];
+
+ if (animated) [UIView beginAnimations:nil context:NULL];
+ CGRect barframe = [refreshbar_ frame];
+ CGRect viewframe = [[root_ view] frame];
+ viewframe.origin.y -= barframe.size.height + 20.0f;
+ viewframe.size.height += barframe.size.height + 20.0f;
+ [[root_ view] setFrame:viewframe];
+ if (animated) [UIView commitAnimations];
+
+ // XXX: fix Apple's layout bug
+ [[root_ selectedViewController] _updateLayoutForStatusBarAndInterfaceOrientation];
+}
+
+- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
+ // XXX: fix Apple's layout bug
+ [[root_ selectedViewController] _updateLayoutForStatusBarAndInterfaceOrientation];
+}
+
+- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
+ if (dropped_) {
+ [self raiseBar:NO];
+ [self dropBar:NO];
+ }
+
+ // XXX: fix Apple's layout bug
+ [[root_ selectedViewController] _updateLayoutForStatusBarAndInterfaceOrientation];
+}
+
+- (void) dealloc {
+ [refreshbar_ release];
+ [super dealloc];
+}
+
+- (id) initWithDatabase: (Database *)database {
+ if ((self = [super init]) != nil) {
+ database_ = database;
+
+ [[self view] setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+
+ refreshbar_ = [[RefreshBar alloc] initWithFrame:CGRectMake(0, 0, [[self view] frame].size.width, [UINavigationBar defaultSize].height) delegate:self];
+ } return self;
+}
+
+@end
+/* }}} */
+
+typedef enum {
+ kCydiaTag = 0,
+ kSectionsTag = 1,
+ kChangesTag = 2,
+ kManageTag = 3,
+ kInstalledTag = 4,
+ kSourcesTag = 5,
+ kSearchTag = 6
+} CYTabTag;