summaryrefslogtreecommitdiff
path: root/CyteKit
diff options
context:
space:
mode:
Diffstat (limited to 'CyteKit')
-rw-r--r--CyteKit/CyteKit.h1
-rw-r--r--CyteKit/ListController.h40
-rw-r--r--CyteKit/ListController.mm193
-rw-r--r--CyteKit/extern.h20
4 files changed, 254 insertions, 0 deletions
diff --git a/CyteKit/CyteKit.h b/CyteKit/CyteKit.h
index 7f1df37..0d66439 100644
--- a/CyteKit/CyteKit.h
+++ b/CyteKit/CyteKit.h
@@ -24,6 +24,7 @@
#include "CyteKit/Application.h"
#include "CyteKit/CyteObject.h"
+#include "CyteKit/ListController.h"
#include "CyteKit/NavigationController.h"
#include "CyteKit/TableViewCell.h"
#include "CyteKit/TabBarController.h"
diff --git a/CyteKit/ListController.h b/CyteKit/ListController.h
new file mode 100644
index 0000000..b9b8022
--- /dev/null
+++ b/CyteKit/ListController.h
@@ -0,0 +1,40 @@
+/* Cydia - iPhone UIKit Front-End for Debian APT
+ * Copyright (C) 2008-2015 Jay Freeman (saurik)
+*/
+
+/* GNU General Public License, Version 3 {{{ */
+/*
+ * Cydia is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * Cydia is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Cydia. If not, see <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
+#ifndef CyteKit_ListController_H
+#define CyteKit_ListController_H
+
+#include <UIKit/UIKit.h>
+
+#include <CyteKit/ViewController.h>
+
+@interface CyteListController : CyteViewController
+
+- (bool) shouldYield;
+- (void) loadView;
+- (void) _reloadData;
+- (void) resetCursor;
+- (void) clearData;
+- (CGFloat) rowHeight;
+
+@end
+
+#endif//CyteKit_ListController_H
diff --git a/CyteKit/ListController.mm b/CyteKit/ListController.mm
new file mode 100644
index 0000000..d3c162e
--- /dev/null
+++ b/CyteKit/ListController.mm
@@ -0,0 +1,193 @@
+/* Cydia - iPhone UIKit Front-End for Debian APT
+ * Copyright (C) 2008-2015 Jay Freeman (saurik)
+*/
+
+/* GNU General Public License, Version 3 {{{ */
+/*
+ * Cydia is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * Cydia is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Cydia. If not, see <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
+#include "CyteKit/UCPlatform.h"
+
+#include <Foundation/Foundation.h>
+#include <UIKit/UIKit.h>
+
+#include "CyteKit/ListController.h"
+#include "CyteKit/extern.h"
+
+#include "iPhonePrivate.h"
+#include <Menes/ObjectHandle.h>
+
+static CGFloat CYStatusBarHeight() {
+ CGSize size([[UIApplication sharedApplication] statusBarFrame].size);
+ return UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]) ? size.height : size.width;
+}
+
+@implementation CyteListController {
+ _H<UITableView, 2> list_;
+}
+
+- (bool) shouldYield {
+ return false;
+}
+
+- (void) deselectWithAnimation:(BOOL)animated {
+ [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
+}
+
+- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration curve:(UIViewAnimationCurve)curve {
+ CGRect base = [[self view] bounds];
+ base.size.height -= bounds.size.height;
+ base.origin = [list_ frame].origin;
+
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationBeginsFromCurrentState:YES];
+ [UIView setAnimationCurve:curve];
+ [UIView setAnimationDuration:duration];
+ [list_ setFrame:base];
+ [UIView commitAnimations];
+}
+
+- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration {
+ [self resizeForKeyboardBounds:bounds duration:duration curve:UIViewAnimationCurveLinear];
+}
+
+- (void) resizeForKeyboardBounds:(CGRect)bounds {
+ [self resizeForKeyboardBounds:bounds duration:0];
+}
+
+- (void) getKeyboardCurve:(UIViewAnimationCurve *)curve duration:(NSTimeInterval *)duration forNotification:(NSNotification *)notification {
+ if (&UIKeyboardAnimationCurveUserInfoKey == NULL)
+ *curve = UIViewAnimationCurveEaseInOut;
+ else
+ [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:curve];
+
+ if (&UIKeyboardAnimationDurationUserInfoKey == NULL)
+ *duration = 0.3;
+ else
+ [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:duration];
+}
+
+- (void) keyboardWillShow:(NSNotification *)notification {
+ CGRect bounds;
+ CGPoint center;
+ [[[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] getValue:&bounds];
+ [[[notification userInfo] objectForKey:UIKeyboardCenterEndUserInfoKey] getValue:&center];
+
+ NSTimeInterval duration;
+ UIViewAnimationCurve curve;
+ [self getKeyboardCurve:&curve duration:&duration forNotification:notification];
+
+ CGRect kbframe = CGRectMake(Retina(center.x - bounds.size.width / 2), Retina(center.y - bounds.size.height / 2), bounds.size.width, bounds.size.height);
+ UIViewController *base([self rootViewController]);
+ CGRect viewframe = [[base view] convertRect:[list_ frame] fromView:[list_ superview]];
+ CGRect intersection = CGRectIntersection(viewframe, kbframe);
+
+ if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: _UIApplicationLinkedOnOrAfter(4)
+ intersection.size.height += CYStatusBarHeight();
+
+ [self resizeForKeyboardBounds:intersection duration:duration curve:curve];
+}
+
+- (void) keyboardWillHide:(NSNotification *)notification {
+ NSTimeInterval duration;
+ UIViewAnimationCurve curve;
+ [self getKeyboardCurve:&curve duration:&duration forNotification:notification];
+
+ [self resizeForKeyboardBounds:CGRectZero duration:duration curve:curve];
+}
+
+- (void) viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+
+ [self resizeForKeyboardBounds:CGRectZero];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
+}
+
+- (void) viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+
+ [self resizeForKeyboardBounds:CGRectZero];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
+}
+
+- (void) viewDidAppear:(BOOL)animated {
+ [super viewDidAppear:animated];
+ [self deselectWithAnimation:animated];
+}
+
+- (void) releaseSubviews {
+ list_ = nil;
+ [super releaseSubviews];
+}
+
+- (CGFloat) rowHeight {
+ return 0;
+}
+
+- (void) updateHeight {
+ [list_ setRowHeight:[self rowHeight]];
+}
+
+- (void) loadView {
+ UIView *view([[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]);
+ [view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+ [self setView:view];
+
+ list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain] autorelease];
+ [list_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+ [view addSubview:list_];
+
+ // XXX: is 20 the most optimal number here?
+ [list_ setSectionIndexMinimumDisplayRowCount:20];
+
+ [list_ setDataSource:(id)self];
+ [list_ setDelegate:(id)self];
+
+ [self updateHeight];
+}
+
+- (void) _reloadData {
+ [self updateHeight];
+
+ [list_ setDataSource:(id)self];
+ [list_ reloadData];
+}
+
+- (void) reloadData {
+ [super reloadData];
+
+ if ([self shouldYield])
+ [self performSelector:@selector(_reloadData) withObject:nil afterDelay:0];
+ else
+ [self _reloadData];
+}
+
+- (void) resetCursor {
+ [list_ scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
+}
+
+- (void) clearData {
+ [self updateHeight];
+
+ [list_ setDataSource:nil];
+ [list_ reloadData];
+
+ [self resetCursor];
+}
+
+@end
diff --git a/CyteKit/extern.h b/CyteKit/extern.h
index 670f560..562fb26 100644
--- a/CyteKit/extern.h
+++ b/CyteKit/extern.h
@@ -35,4 +35,24 @@ bool CyteIsReachable(const char *name);
void CyteInitialize(NSString *app, NSString *version);
+static inline double Retina(double value) {
+ value *= ScreenScale_;
+ value = round(value);
+ value /= ScreenScale_;
+ return value;
+}
+
+static inline CGRect Retina(CGRect value) {
+ value.origin.x *= ScreenScale_;
+ value.origin.y *= ScreenScale_;
+ value.size.width *= ScreenScale_;
+ value.size.height *= ScreenScale_;
+ value = CGRectIntegral(value);
+ value.origin.x /= ScreenScale_;
+ value.origin.y /= ScreenScale_;
+ value.size.width /= ScreenScale_;
+ value.size.height /= ScreenScale_;
+ return value;
+}
+
#endif//CyteKit_extern_H