diff --git a/Chameleon.podspec b/Chameleon.podspec new file mode 100644 index 00000000..6acff5c8 --- /dev/null +++ b/Chameleon.podspec @@ -0,0 +1,46 @@ +Pod::Spec.new do |s| + s.name = "Chameleon" + s.version = "0.0.2" + s.summary = "Chameleon is a port of Apple's UIKit (and some minimal related frameworks) to Mac OS X." + s.description = "Chameleon is a port of Apple's UIKit (and some minimal related frameworks) to Mac OS X. It is meant to be as much of a drop-in replacement for the real UIKit as possible. It also adapts some iOS user interface conventions to the Mac (such as UIAlertView being represented by NSAlert) so that apps built using Chameleon have as much chance as possible of feeling at home on the desktop with relatively little porting effort." + s.homepage = "http://chameleonproject.org/" + s.author = { "Sean Heber" => "sean@iconfactory.com" } + s.source = { :git => "https://github.com/michaelmelanson/Chameleon.git" } + s.license = { :type => 'Modified BSD License' } + s.platform = :osx, '10.6' + s.frameworks = 'IOKit', 'QuartzCore', 'SystemConfiguration', 'AppKit', 'Foundation', 'QTKit', 'WebKit' + + s.requires_arc = false + s.compiler_flags = '-fno-objc-arc' + + s.subspec 'UIKit' do |sb| + sb.source_files = 'UIKit/Classes/*.{h,m}' + sb.resources = "UIKit/Resources/*.png" + sb.header_dir = 'UIKit' + end + + s.subspec 'StoreKit' do |sb| + sb.source_files = 'StoreKit/Classes/*.{h,m}' + sb.header_dir = 'StoreKit' + end + + s.subspec 'AVFoundation' do |sb| + sb.source_files = 'AVFoundation/Classes/*.{h,m}' + sb.header_dir = 'AVFoundation' + end + + s.subspec 'AssetsLibrary' do |sb| + sb.source_files = 'AssetsLibrary/Classes/*.{h,m}' + sb.header_dir = 'AssetsLibrary' + end + + s.subspec 'MediaPlayer' do |sb| + sb.source_files = 'MediaPlayer/Classes/*.{h,m}' + sb.header_dir = 'MediaPlayer' + end + + s.subspec 'MessageUI' do |sb| + sb.source_files = 'MessageUI/*.{h,m}', 'MessageUI/Classes/*.{h,m}' + sb.header_dir = 'MessageUI' + end +end diff --git a/UIKit/Classes/NSIndexPath+UITableView.h b/UIKit/Classes/NSIndexPath+UITableView.h index b39e618d..7ed0a4de 100644 --- a/UIKit/Classes/NSIndexPath+UITableView.h +++ b/UIKit/Classes/NSIndexPath+UITableView.h @@ -30,7 +30,7 @@ #import @interface NSIndexPath (UITableView) -+ (NSIndexPath *)indexPathForRow:(NSUInteger)row inSection:(NSUInteger)section; -@property (readonly) NSUInteger row; -@property (readonly) NSUInteger section; ++ (NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section; +@property (readonly) NSInteger row; +@property (readonly) NSInteger section; @end diff --git a/UIKit/Classes/NSIndexPath+UITableView.m b/UIKit/Classes/NSIndexPath+UITableView.m index b3cda59a..687d8fe2 100644 --- a/UIKit/Classes/NSIndexPath+UITableView.m +++ b/UIKit/Classes/NSIndexPath+UITableView.m @@ -31,18 +31,18 @@ @implementation NSIndexPath (UITableView) -+ (NSIndexPath *)indexPathForRow:(NSUInteger)row inSection:(NSUInteger)section ++ (NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section { - NSUInteger path[2] = {section, row}; + NSInteger path[2] = {section, row}; return [self indexPathWithIndexes:path length:2]; } -- (NSUInteger)row +- (NSInteger)row { return [self indexAtPosition:1]; } --(NSUInteger)section +-(NSInteger)section { return [self indexAtPosition:0]; } diff --git a/UIKit/Classes/UIAccessibility.h b/UIKit/Classes/UIAccessibility.h index a0aadcbf..7d62ceff 100644 --- a/UIKit/Classes/UIAccessibility.h +++ b/UIKit/Classes/UIAccessibility.h @@ -77,4 +77,5 @@ extern UIAccessibilityNotifications UIAccessibilityPageScrolledNotification; @end extern void UIAccessibilityPostNotification(UIAccessibilityNotifications notification, id argument); +extern BOOL UIAccessibilityIsGuidedAccessEnabled(void); extern BOOL UIAccessibilityIsVoiceOverRunning(void); diff --git a/UIKit/Classes/UIAccessibility.m b/UIKit/Classes/UIAccessibility.m index 4cff6f6f..8edb1676 100644 --- a/UIKit/Classes/UIAccessibility.m +++ b/UIKit/Classes/UIAccessibility.m @@ -163,6 +163,12 @@ void UIAccessibilityPostNotification(UIAccessibilityNotifications notification, { } + +BOOL UIAccessibilityIsGuidedAccessEnabled() +{ + return NO; +} + BOOL UIAccessibilityIsVoiceOverRunning() { return NO; diff --git a/UIKit/Classes/UIAction.m b/UIKit/Classes/UIAction.m index 5378ff5d..0afcf14a 100644 --- a/UIKit/Classes/UIAction.m +++ b/UIKit/Classes/UIAction.m @@ -36,7 +36,7 @@ - (BOOL)isEqual:(id)object { if (object == self) { return YES; - } else if ([object isKindOfClass:[isa class]]) { + } else if ([object isKindOfClass:[self class]]) { return ([object target] == self.target && [object action] == self.action); } else { return NO; diff --git a/UIKit/Classes/UIActivityIndicatorView.h b/UIKit/Classes/UIActivityIndicatorView.h index 71fe74b5..5f99de5e 100644 --- a/UIKit/Classes/UIActivityIndicatorView.h +++ b/UIKit/Classes/UIActivityIndicatorView.h @@ -49,5 +49,5 @@ typedef enum { @property BOOL hidesWhenStopped; @property UIActivityIndicatorViewStyle activityIndicatorViewStyle; - +@property (retain) UIColor *color; @end diff --git a/UIKit/Classes/UIActivityIndicatorView.m b/UIKit/Classes/UIActivityIndicatorView.m index af715172..f30c07de 100644 --- a/UIKit/Classes/UIActivityIndicatorView.m +++ b/UIKit/Classes/UIActivityIndicatorView.m @@ -45,15 +45,13 @@ static CGSize UIActivityIndicatorViewStyleSize(UIActivityIndicatorViewStyle styl } } -static UIImage *UIActivityIndicatorViewFrameImage(UIActivityIndicatorViewStyle style, NSInteger frame, NSInteger numberOfFrames, CGFloat scale) +static UIImage *UIActivityIndicatorViewFrameImage(UIActivityIndicatorViewStyle style, NSInteger frame, NSInteger numberOfFrames, CGFloat scale, UIColor *toothColor) { const CGSize frameSize = UIActivityIndicatorViewStyleSize(style); const CGFloat radius = frameSize.width / 2.f; const CGFloat TWOPI = M_PI * 2.f; const CGFloat numberOfTeeth = 12; const CGFloat toothWidth = (style == UIActivityIndicatorViewStyleWhiteLarge)? 3.5 : 2; - - UIColor *toothColor = (style == UIActivityIndicatorViewStyleGray)? [UIColor grayColor] : [UIColor whiteColor]; UIGraphicsBeginImageContextWithOptions(frameSize, NO, scale); CGContextRef c = UIGraphicsGetCurrentContext(); @@ -176,7 +174,7 @@ - (void)_startAnimation NSMutableArray *images = [[NSMutableArray alloc] initWithCapacity:numberOfFrames]; for (NSInteger frameNumber=0; frameNumber +#import "UITextLayer.h" +#import "UITextLayer+Private.h" +#import "UITextField.h" +#import "UITextField+Private.h" + NSString *const UIApplicationWillChangeStatusBarOrientationNotification = @"UIApplicationWillChangeStatusBarOrientationNotification"; NSString *const UIApplicationDidChangeStatusBarOrientationNotification = @"UIApplicationDidChangeStatusBarOrientationNotification"; @@ -183,6 +188,11 @@ - (BOOL)isStatusBarHidden return YES; } +- (void)setStatusBarHidden:(BOOL)statusBarHidden +{ + // do nothing +} + - (CGRect)statusBarFrame { return CGRectZero; @@ -606,6 +616,55 @@ - (BOOL)_sendGlobalKeyboardNSEvent:(NSEvent *)theNSEvent fromScreen:(UIScreen *) return [self _sendActionToFirstResponder:@selector(commit:) withSender:key fromScreen:theScreen]; } } + + if (key.type == UIKeyTypeTab) { + UIResponder *firstResponder = [self _firstResponderForScreen:theScreen]; + + // the open list for an interative depth-first traversal + NSMutableArray *open = [NSMutableArray array]; + [open addObjectsFromArray:self.keyWindow.subviews]; + + NSMutableArray *allTextFields = [NSMutableArray array]; + + while(open.count > 0) + { + UIView *view = [open objectAtIndex:0]; + [open removeObjectAtIndex:0]; + [open addObjectsFromArray:view.subviews]; + + if ([view isKindOfClass:[UITextField class]]) { + if ([[(UITextField *)view textLayer] textShouldBeginEditing:nil]) { + [allTextFields addObject:view]; + } + } + } + + if ([allTextFields count] > 0) { + [allTextFields sortUsingComparator:^NSComparisonResult(id fieldOne, id fieldTwo) { + NSRect fieldOneBounds = [(UITextField *)fieldOne bounds]; + NSRect fieldTwoBounds = [(UITextField *)fieldTwo bounds]; + + NSComparator comparator = ^(NSNumber *obj1, NSNumber *obj2) { + if ([obj1 intValue] == [obj2 intValue]) return NSOrderedSame; + else if ([obj1 intValue] < [obj2 intValue]) return NSOrderedAscending; + else return NSOrderedDescending; + }; + + NSComparisonResult horizontalComparison = comparator(@(fieldOneBounds.origin.x), @(fieldTwoBounds.origin.x)); + NSComparisonResult verticalComparison = comparator(@(fieldOneBounds.origin.y), @(fieldTwoBounds.origin.y)); + + return horizontalComparison == NSOrderedSame ? verticalComparison : horizontalComparison; + }]; + + int currentIndex = [allTextFields containsObject:firstResponder] ? (int) [allTextFields indexOfObject:firstResponder] : -1; + int nextIndex = (currentIndex + 1) % [allTextFields count]; + + UIResponder *nextResponder = [allTextFields objectAtIndex:nextIndex]; + [nextResponder becomeFirstResponder]; + } + + return YES; + } } return NO; diff --git a/UIKit/Classes/UIButton.m b/UIKit/Classes/UIButton.m index 9cbb4892..97d86874 100644 --- a/UIKit/Classes/UIButton.m +++ b/UIKit/Classes/UIButton.m @@ -78,7 +78,7 @@ - (id)initWithFrame:(CGRect)frame self.opaque = NO; _titleLabel.lineBreakMode = UILineBreakModeMiddleTruncation; _titleLabel.backgroundColor = [UIColor clearColor]; - _titleLabel.textAlignment = UITextAlignmentLeft; + _titleLabel.textAlignment = NSLeftTextAlignment; _titleLabel.shadowOffset = CGSizeZero; [self addSubview:_backgroundImageView]; [self addSubview:_imageView]; diff --git a/UIKit/Classes/UICustomNSTextView.h b/UIKit/Classes/UICustomNSTextView.h index d8f6b749..91ccd5f2 100644 --- a/UIKit/Classes/UICustomNSTextView.h +++ b/UIKit/Classes/UICustomNSTextView.h @@ -28,6 +28,7 @@ */ #import +#import "UITextInputTraits.h" @class CALayer, UICustomNSTextView; @@ -40,10 +41,12 @@ @interface UICustomNSTextView: NSTextView { BOOL secureTextEntry; BOOL isBecomingFirstResponder; + UITextAutocorrectionType autocorrectionType; } - (id)initWithFrame:(NSRect)frame secureTextEntry:(BOOL)isSecure isField:(BOOL)isField; - (void)setSecureTextEntry:(BOOL)isSecure; +- (void)setAutocorrectionType:(UITextAutocorrectionType)type; - (BOOL)reallyBecomeFirstResponder; - (BOOL)reallyResignFirstResponder; diff --git a/UIKit/Classes/UICustomNSTextView.m b/UIKit/Classes/UICustomNSTextView.m index cc3165ba..f6932e7f 100644 --- a/UIKit/Classes/UICustomNSTextView.m +++ b/UIKit/Classes/UICustomNSTextView.m @@ -29,6 +29,7 @@ #import "UICustomNSTextView.h" #import "UIBulletGlyphGenerator.h" +#import "UITextInputTraits.h" #import #import #import @@ -82,6 +83,7 @@ - (id)initWithFrame:(NSRect)frame secureTextEntry:(BOOL)isSecure isField:(BOOL)i [self setDisplaysLinkToolTips:NO]; [self setAutomaticDataDetectionEnabled:NO]; [self setSecureTextEntry:isSecure]; + [self setAutocorrectionType:UITextAutocorrectionTypeDefault]; [self setLayerContentsPlacement:NSViewLayerContentsPlacementTopLeft]; @@ -121,16 +123,29 @@ - (void)updateStyles [style setLineBreakMode:NSLineBreakByTruncatingTail]; } + // eliminate the built-in padding around the text field + [[self textContainer] setLineFragmentPadding:0]; + [self setDefaultParagraphStyle:style]; [style release]; } +// vertically centre the text +- (NSPoint)textContainerOrigin { + return NSMakePoint(0, (self.font.ascender + self.font.descender + self.font.xHeight)/2); +} + - (void)setSecureTextEntry:(BOOL)isSecure { secureTextEntry = isSecure; [self updateStyles]; } +- (void)setAutocorrectionType:(UITextAutocorrectionType)type +{ + autocorrectionType = type; +} + - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { if (secureTextEntry && ([menuItem action] == @selector(copy:) || [menuItem action] == @selector(cut:))) { @@ -267,7 +282,7 @@ - (void)keyDown:(NSEvent *)event - (void)setNeedsFakeSpellCheck { - if ([self isContinuousSpellCheckingEnabled]) { + if ([self isContinuousSpellCheckingEnabled] && self->autocorrectionType != UITextAutocorrectionTypeNo) { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(forcedSpellCheck) object:nil]; [self performSelector:@selector(forcedSpellCheck) withObject:nil afterDelay:0.5]; } @@ -326,7 +341,9 @@ - (void)drawFakeSpellingUnderlinesInRect:(NSRect)rect for (NSUInteger i=0; i #import +#import NSString *const UIDeviceOrientationDidChangeNotification = @"UIDeviceOrientationDidChangeNotification"; @@ -64,6 +65,63 @@ - (UIDeviceOrientation)orientation return UIDeviceOrientationPortrait; } + +- (NSDictionary *)primaryPowerSource +{ + CFTypeRef powerSourceInfo = IOPSCopyPowerSourcesInfo(); + CFArrayRef powerSources = IOPSCopyPowerSourcesList(powerSourceInfo); + + if (CFArrayGetCount(powerSources) == 0) return nil; + + CFDictionaryRef primarySourceRef = IOPSGetPowerSourceDescription(powerSourceInfo, CFArrayGetValueAtIndex(powerSources, 0)); + NSDictionary *primarySource = [NSDictionary dictionaryWithDictionary:[(__bridge NSDictionary *) primarySourceRef copy]]; + + CFRelease(primarySourceRef); + CFRelease(powerSourceInfo); + CFRelease(powerSources); + + return primarySource; +} + +- (UIDeviceBatteryState)batteryState +{ + UIDeviceBatteryState state = UIDeviceBatteryStateUnknown; + + NSDictionary *powerSource = [self primaryPowerSource]; + id powerSourceState = [powerSource objectForKey:(__bridge NSString *)CFSTR(kIOPSPowerSourceStateKey)]; + + if ([powerSourceState isEqualToString:(__bridge NSString *)CFSTR(kIOPSACPowerValue)]) { + id currentObj = [powerSource objectForKey:(__bridge NSString *)CFSTR(kIOPSCurrentCapacityKey)]; + id capacityObj = [powerSource objectForKey:(__bridge NSString *)CFSTR(kIOPSMaxCapacityKey)]; + + if ([currentObj isEqualToNumber:capacityObj]) { + state = UIDeviceBatteryStateFull; + } else { + state = UIDeviceBatteryStateCharging; + } + } else if ([powerSourceState isEqualToString:(__bridge NSString *)CFSTR(kIOPSBatteryPowerValue)]) { + state = UIDeviceBatteryStateUnplugged; + } + + return state; +} + +- (float)batteryLevel +{ + float batteryLevel = 1.f; + + NSDictionary *powerSource = [self primaryPowerSource]; + + if (powerSource != nil) { + id currentObj = [powerSource objectForKey:(__bridge NSString *)CFSTR(kIOPSCurrentCapacityKey)]; + id capacityObj = [powerSource objectForKey:(__bridge NSString *)CFSTR(kIOPSMaxCapacityKey)]; + + batteryLevel = [currentObj floatValue] / [capacityObj floatValue]; + } + + return batteryLevel; +} + - (BOOL)isMultitaskingSupported { return YES; diff --git a/UIKit/Classes/UIFont.m b/UIKit/Classes/UIFont.m index dcbab16e..46459c95 100644 --- a/UIKit/Classes/UIFont.m +++ b/UIKit/Classes/UIFont.m @@ -191,7 +191,7 @@ - (UIFont *)fontWithSize:(CGFloat)fontSize { CTFontRef newFont = CTFontCreateCopyWithAttributes(_font, fontSize, NULL, NULL); if (newFont) { - UIFont *theFont = [isa _fontWithCTFont:newFont]; + UIFont *theFont = [[self class] _fontWithCTFont:newFont]; CFRelease(newFont); return theFont; } else { diff --git a/UIKit/Classes/UIImage+UIPrivate.m b/UIKit/Classes/UIImage+UIPrivate.m index dfade4f5..7fcd6a9a 100644 --- a/UIKit/Classes/UIImage+UIPrivate.m +++ b/UIKit/Classes/UIImage+UIPrivate.m @@ -60,9 +60,7 @@ + (UIImage *)_frameworkImageWithName:(NSString *)name leftCapWidth:(NSUInteger)l UIImage *image = [self _cachedImageForName:name]; if (!image) { - NSBundle *frameworkBundle = [NSBundle bundleWithIdentifier:@"org.chameleonproject.UIKit"]; - NSString *frameworkFile = [[frameworkBundle resourcePath] stringByAppendingPathComponent:name]; - image = [[self imageWithContentsOfFile:frameworkFile] stretchableImageWithLeftCapWidth:leftCapWidth topCapHeight:topCapHeight]; + image = [[UIImage imageNamed:name] stretchableImageWithLeftCapWidth:leftCapWidth topCapHeight:topCapHeight]; [self _cacheImage:image forName:name]; } diff --git a/UIKit/Classes/UIImage.m b/UIKit/Classes/UIImage.m index 7948a19b..cda552d4 100644 --- a/UIKit/Classes/UIImage.m +++ b/UIKit/Classes/UIImage.m @@ -59,7 +59,7 @@ + (id)imageNamed:(NSString *)name if (!img) { // as per the iOS docs, if it fails to find a match with the bare name, it re-tries by appending a png file extension - img = [self _imageNamed:name] ?: [self _imageNamed:[name stringByAppendingPathExtension:@"png"]]; + img = [self _imageNamed:name] ?: [self _imageNamed:[name stringByAppendingPathExtension:@"png"]] ?: [self _imageNamed:[name stringByAppendingPathExtension:@"tiff"]]; [self _cacheImage:img forName:name]; } diff --git a/UIKit/Classes/UIKey.h b/UIKit/Classes/UIKey.h index 019c75e1..1311e9e3 100644 --- a/UIKit/Classes/UIKey.h +++ b/UIKit/Classes/UIKey.h @@ -41,6 +41,7 @@ typedef enum { UIKeyTypeRightArrow, UIKeyTypeReturn, UIKeyTypeEnter, + UIKeyTypeTab, UIKeyTypeHome, UIKeyTypeInsert, UIKeyTypeDelete, diff --git a/UIKit/Classes/UIKey.m b/UIKit/Classes/UIKey.m index 7dbed326..53a0013c 100644 --- a/UIKit/Classes/UIKey.m +++ b/UIKit/Classes/UIKey.m @@ -68,6 +68,7 @@ - (UIKeyType)type case NSHomeFunctionKey: return UIKeyTypeHome; case 0x000D: return UIKeyTypeReturn; case 0x0003: return UIKeyTypeEnter; + case NSTabCharacter: return UIKeyTypeTab; } } diff --git a/UIKit/Classes/UIKit.h b/UIKit/Classes/UIKit.h index 24ab4f36..b810f7fd 100644 --- a/UIKit/Classes/UIKit.h +++ b/UIKit/Classes/UIKit.h @@ -118,3 +118,10 @@ // SystemConfiguration-Helper #define kSCNetworkReachabilityFlagsIsWWAN kSCNetworkReachabilityFlagsConnectionOnDemand + + +#define NSTextAlignmentLeft NSLeftTextAlignment +#define NSTextAlignmentCenter NSCenterTextAlignment +#define NSTextAlignmentRight NSRightTextAlignment +#define NSTextAlignmentJustified NSJustifiedTextAlignment +#define NSTextAlignmentNatural NSNaturalTextAlignment \ No newline at end of file diff --git a/UIKit/Classes/UIKitView.m b/UIKit/Classes/UIKitView.m index 9e3f1b61..337469fc 100644 --- a/UIKit/Classes/UIKitView.m +++ b/UIKit/Classes/UIKitView.m @@ -308,13 +308,17 @@ - (void)launchApplicationWithDelegate:(id)appDelegate aft if (delay) { UIImage *defaultImage = [UIImage imageNamed:@"Default-Landscape.png"]; UIImageView *defaultImageView = [[[UIImageView alloc] initWithImage:defaultImage] autorelease]; - defaultImageView.contentMode = UIViewContentModeCenter; + defaultImageView.contentMode = UIViewContentModeScaleAspectFill; + defaultImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + defaultImageView.frame = _screen.bounds; UIWindow *defaultWindow = [(UIWindow *)[UIWindow alloc] initWithFrame:_screen.bounds]; defaultWindow.userInteractionEnabled = NO; defaultWindow.screen = _screen; defaultWindow.backgroundColor = [UIColor blackColor]; // dunno.. defaultWindow.opaque = YES; + defaultWindow.autoresizesSubviews = YES; + defaultWindow.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [defaultWindow addSubview:defaultImageView]; [defaultWindow makeKeyAndVisible]; [self performSelector:@selector(_launchApplicationWithDefaultWindow:) withObject:defaultWindow afterDelay:delay]; diff --git a/UIKit/Classes/UILabel.h b/UIKit/Classes/UILabel.h index 14673cf9..a9efee35 100644 --- a/UIKit/Classes/UILabel.h +++ b/UIKit/Classes/UILabel.h @@ -40,7 +40,7 @@ UIColor *_highlightedTextColor; UIColor *_shadowColor; CGSize _shadowOffset; - UITextAlignment _textAlignment; + NSTextAlignment _textAlignment; UILineBreakMode _lineBreakMode; BOOL _enabled; NSInteger _numberOfLines; @@ -56,7 +56,7 @@ @property (nonatomic, retain) UIColor *highlightedTextColor; @property (nonatomic, retain) UIColor *shadowColor; @property (nonatomic) CGSize shadowOffset; -@property (nonatomic) UITextAlignment textAlignment; +@property (nonatomic) NSTextAlignment textAlignment; @property (nonatomic) UILineBreakMode lineBreakMode; @property (nonatomic, getter=isEnabled) BOOL enabled; @property (nonatomic) NSInteger numberOfLines; // currently only supports 0 or 1 diff --git a/UIKit/Classes/UILabel.m b/UIKit/Classes/UILabel.m index e930cb1c..7a5282b1 100644 --- a/UIKit/Classes/UILabel.m +++ b/UIKit/Classes/UILabel.m @@ -43,7 +43,7 @@ - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { self.userInteractionEnabled = NO; - self.textAlignment = UITextAlignmentLeft; + self.textAlignment = NSLeftTextAlignment; self.lineBreakMode = UILineBreakModeTailTruncation; self.textColor = [UIColor blackColor]; self.backgroundColor = [UIColor whiteColor]; @@ -114,7 +114,7 @@ - (void)setShadowOffset:(CGSize)newOffset } } -- (void)setTextAlignment:(UITextAlignment)newAlignment +- (void)setTextAlignment:(NSTextAlignment)newAlignment { if (newAlignment != _textAlignment) { _textAlignment = newAlignment; diff --git a/UIKit/Classes/UILongPressGestureRecognizer.m b/UIKit/Classes/UILongPressGestureRecognizer.m index 6eabf1a4..9723ea54 100644 --- a/UIKit/Classes/UILongPressGestureRecognizer.m +++ b/UIKit/Classes/UILongPressGestureRecognizer.m @@ -83,7 +83,7 @@ - (void)_cancelWaiting { if (_waiting) { _waiting = NO; - [isa cancelPreviousPerformRequestsWithTarget:self selector:@selector(_beginGesture) object:nil]; + [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(_beginGesture) object:nil]; } } diff --git a/UIKit/Classes/UIMenuController.m b/UIKit/Classes/UIMenuController.m index d5c0637c..9a74feda 100644 --- a/UIKit/Classes/UIMenuController.m +++ b/UIKit/Classes/UIMenuController.m @@ -194,7 +194,7 @@ - (void)update { UIApplication *app = [UIApplication sharedApplication]; UIResponder *firstResponder = [app.keyWindow _firstResponder]; - NSArray *allItems = [[isa _defaultMenuItems] arrayByAddingObjectsFromArray:_menuItems]; + NSArray *allItems = [[[self class] _defaultMenuItems] arrayByAddingObjectsFromArray:_menuItems]; [_enabledMenuItems removeAllObjects]; diff --git a/UIKit/Classes/UINavigationBar.m b/UIKit/Classes/UINavigationBar.m index 226deeb4..d5add95a 100644 --- a/UIKit/Classes/UINavigationBar.m +++ b/UIKit/Classes/UINavigationBar.m @@ -201,9 +201,9 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: CGRect rightFrame = CGRectZero; if (backItem) { - _leftView = [isa _backButtonWithBarButtonItem:backItem.backBarButtonItem]; + _leftView = [[self class] _backButtonWithBarButtonItem:backItem.backBarButtonItem]; } else { - _leftView = [isa _viewWithBarButtonItem:topItem.leftBarButtonItem]; + _leftView = [[self class] _viewWithBarButtonItem:topItem.leftBarButtonItem]; } if (_leftView) { @@ -213,7 +213,7 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: [self addSubview:_leftView]; } - _rightView = [isa _viewWithBarButtonItem:topItem.rightBarButtonItem]; + _rightView = [[self class] _viewWithBarButtonItem:topItem.rightBarButtonItem]; if (_rightView) { _rightView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; @@ -229,7 +229,7 @@ - (void)_setViewsWithTransition:(_UINavigationBarTransition)transition animated: if (!_centerView) { UILabel *titleLabel = [[[UILabel alloc] init] autorelease]; titleLabel.text = topItem.title; - titleLabel.textAlignment = UITextAlignmentCenter; + titleLabel.textAlignment = NSCenterTextAlignment; titleLabel.backgroundColor = [UIColor clearColor]; titleLabel.textColor = [UIColor whiteColor]; titleLabel.font = [UIFont boldSystemFontOfSize:14]; diff --git a/UIKit/Classes/UINavigationItem.m b/UIKit/Classes/UINavigationItem.m index 13157ea2..8c799661 100644 --- a/UIKit/Classes/UINavigationItem.m +++ b/UIKit/Classes/UINavigationItem.m @@ -90,13 +90,13 @@ - (void)_setNavigationBar:(UINavigationBar *)navigationBar if (_navigationBar != nil && navigationBar == nil) { // remove observation - for (NSString * keyPath in [isa _keyPathsTriggeringUIUpdates]) { + for (NSString * keyPath in [[self class] _keyPathsTriggeringUIUpdates]) { [self removeObserver:self forKeyPath:keyPath]; } } else if (navigationBar != nil) { // observe property changes to notify UI element - for (NSString * keyPath in [isa _keyPathsTriggeringUIUpdates]) { + for (NSString * keyPath in [[self class] _keyPathsTriggeringUIUpdates]) { [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:UINavigationItemContext]; } } diff --git a/UIKit/Classes/UIPopoverView.m b/UIKit/Classes/UIPopoverView.m index c10444a7..c425acec 100644 --- a/UIKit/Classes/UIPopoverView.m +++ b/UIKit/Classes/UIPopoverView.m @@ -164,8 +164,8 @@ - (void)layoutSubviews [super layoutSubviews]; const CGRect bounds = self.bounds; - _backgroundView.frame = [isa backgroundRectForBounds:bounds]; - _contentContainerView.frame = [isa contentRectForBounds:bounds withNavigationBar:NO]; + _backgroundView.frame = [[self class] backgroundRectForBounds:bounds]; + _contentContainerView.frame = [[self class] contentRectForBounds:bounds withNavigationBar:NO]; _contentView.frame = _contentContainerView.bounds; } @@ -312,7 +312,7 @@ - (void)setContentView:(UIView *)aView - (void)setContentSize:(CGSize)aSize animated:(BOOL)animated { CGRect frame = self.frame; - frame.size = [isa frameSizeForContentSize:aSize withNavigationBar:NO]; + frame.size = [[self class] frameSizeForContentSize:aSize withNavigationBar:NO]; [UIView animateWithDuration:animated? 0.2 : 0 animations:^(void) { diff --git a/UIKit/Classes/UIProgressView.h b/UIKit/Classes/UIProgressView.h index 15f359b4..50afe7ef 100644 --- a/UIKit/Classes/UIProgressView.h +++ b/UIKit/Classes/UIProgressView.h @@ -43,5 +43,7 @@ typedef enum { @property (nonatomic) UIProgressViewStyle progressViewStyle; @property (nonatomic) float progress; +@property (nonatomic, strong) UIColor *progressTintColor; +@property (nonatomic, strong) UIColor *trackTintColor; @end diff --git a/UIKit/Classes/UIProgressView.m b/UIKit/Classes/UIProgressView.m index 514f8b74..bf593fbf 100644 --- a/UIKit/Classes/UIProgressView.m +++ b/UIKit/Classes/UIProgressView.m @@ -28,6 +28,8 @@ */ #import "UIProgressView.h" +#import "UIGraphics.h" +#import "UIColor.h" @implementation UIProgressView @synthesize progressViewStyle=_progressViewStyle, progress=_progress; @@ -56,4 +58,22 @@ - (void)setProgress:(float)p } } +- (void)drawRect:(CGRect)rect { + int totalWidth = self.frame.size.width; + int filledWidth = totalWidth * self->_progress; + + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + + // draw the background part of the bar + CGContextSetFillColorWithColor(context, self.trackTintColor.CGColor); + CGContextFillRect(context, CGRectMake(0, 0, totalWidth, self.frame.size.height)); + + // draw the filled part of the bar + CGContextSetFillColorWithColor(context, self.progressTintColor.CGColor); + CGContextFillRect(context, CGRectMake(0, 0, filledWidth, self.frame.size.height)); + + CGContextRestoreGState(context); +} + @end diff --git a/UIKit/Classes/UIResponder.m b/UIKit/Classes/UIResponder.m index 55ece95e..4e97c18e 100644 --- a/UIKit/Classes/UIResponder.m +++ b/UIKit/Classes/UIResponder.m @@ -114,7 +114,7 @@ - (BOOL)resignFirstResponder - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { - if ([isa instancesRespondToSelector:action]) { + if ([[self class] instancesRespondToSelector:action]) { return YES; } else { return [[self nextResponder] canPerformAction:action withSender:sender]; diff --git a/UIKit/Classes/UIScreen.h b/UIKit/Classes/UIScreen.h index 78a8cd79..75339d2e 100644 --- a/UIKit/Classes/UIScreen.h +++ b/UIKit/Classes/UIScreen.h @@ -34,6 +34,12 @@ extern NSString *const UIScreenDidConnectNotification; extern NSString *const UIScreenDidDisconnectNotification; extern NSString *const UIScreenModeDidChangeNotification; +typedef enum { + UIScreenOverscanCompensationScale, + UIScreenOverscanCompensationInsetBounds, + UIScreenOverscanCompensationInsetApplicationFrame, +} UIScreenOverscanCompensation; + @class UIImageView, CALayer, UIKitView, UIScreenMode, UIPopoverController; @interface UIScreen : NSObject { @@ -53,5 +59,8 @@ extern NSString *const UIScreenModeDidChangeNotification; @property (nonatomic, readonly, copy) NSArray *availableModes; // only ever returns the currentMode @property (nonatomic, retain) UIScreenMode *currentMode; // ignores any attempt to set this @property (nonatomic, readonly) CGFloat scale; +@property (nonatomic, assign) UIScreenOverscanCompensation overscanCompensation; // has no effect +@property (nonatomic, retain) UIScreen *mirroredScreen; // always returns nil +@property (nonatomic) CGFloat brightness; // has no effect; defaults to 0.0 @end diff --git a/UIKit/Classes/UIScreen.m b/UIKit/Classes/UIScreen.m index 0d1bae52..d2ff96f4 100644 --- a/UIKit/Classes/UIScreen.m +++ b/UIKit/Classes/UIScreen.m @@ -49,6 +49,7 @@ @implementation UIScreen @synthesize currentMode=_currentMode; +@synthesize overscanCompensation; + (void)initialize { @@ -242,4 +243,9 @@ - (NSString *)description return [NSString stringWithFormat:@"<%@: %p; bounds = %@; mode = %@>", [self className], self, NSStringFromCGRect(self.bounds), self.currentMode]; } +- (UIScreen *)mirroredScreen +{ + return nil; +} + @end diff --git a/UIKit/Classes/UISegmentedControl.m b/UIKit/Classes/UISegmentedControl.m index ae1cb6fd..84a83d72 100644 --- a/UIKit/Classes/UISegmentedControl.m +++ b/UIKit/Classes/UISegmentedControl.m @@ -205,13 +205,13 @@ - (void)drawRect:(CGRect)frame if (enabled) { [_textShadowColor set]; - [string drawInRect:CGRectOffset(textRect, _textShadowOffset.width, _textShadowOffset.height) withFont:_font lineBreakMode:UILineBreakModeTailTruncation alignment:UITextAlignmentCenter]; + [string drawInRect:CGRectOffset(textRect, _textShadowOffset.width, _textShadowOffset.height) withFont:_font lineBreakMode:UILineBreakModeTailTruncation alignment:NSCenterTextAlignment]; [_textColor set]; } else { [_disabledTextColor set]; } - [string drawInRect:textRect withFont:_font lineBreakMode:UILineBreakModeTailTruncation alignment:UITextAlignmentCenter]; + [string drawInRect:textRect withFont:_font lineBreakMode:UILineBreakModeTailTruncation alignment:NSCenterTextAlignment]; } // Images diff --git a/UIKit/Classes/UIStringDrawing.h b/UIKit/Classes/UIStringDrawing.h index c8b7d909..831a4e67 100644 --- a/UIKit/Classes/UIStringDrawing.h +++ b/UIKit/Classes/UIStringDrawing.h @@ -38,12 +38,6 @@ typedef enum { UILineBreakModeMiddleTruncation, } UILineBreakMode; -typedef enum { - UITextAlignmentLeft, - UITextAlignmentCenter, - UITextAlignmentRight, -} UITextAlignment; - typedef enum { UIBaselineAdjustmentAlignBaselines, UIBaselineAdjustmentAlignCenters, @@ -67,7 +61,7 @@ NSString *const UITextAttributeTextShadowOffset; - (CGSize)drawAtPoint:(CGPoint)point forWidth:(CGFloat)width withFont:(UIFont *)font fontSize:(CGFloat)fontSize lineBreakMode:(UILineBreakMode)lineBreakMode baselineAdjustment:(UIBaselineAdjustment)baselineAdjustment; - (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font; - (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode; -- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment; +- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment; // not yet implemented - (CGSize)sizeWithFont:(UIFont *)font minFontSize:(CGFloat)minFontSize actualFontSize:(CGFloat *)actualFontSize forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode; diff --git a/UIKit/Classes/UIStringDrawing.m b/UIKit/Classes/UIStringDrawing.m index 4b395981..767d9a89 100644 --- a/UIKit/Classes/UIStringDrawing.m +++ b/UIKit/Classes/UIStringDrawing.m @@ -173,7 +173,7 @@ - (CGSize)drawAtPoint:(CGPoint)point forWidth:(CGFloat)width withFont:(UIFont *) return [self drawAtPoint:point forWidth:width withFont:font fontSize:[font pointSize] lineBreakMode:lineBreakMode baselineAdjustment:UIBaselineAdjustmentNone]; } -- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode alignment:(UITextAlignment)alignment +- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment { CGSize actualSize = CGSizeZero; CFArrayRef lines = CreateCTLinesForString(self,rect.size,font,lineBreakMode,&actualSize); @@ -192,9 +192,9 @@ - (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(UILineB CTLineRef line = CFArrayGetValueAtIndex(lines, lineNumber); float flush; switch (alignment) { - case UITextAlignmentCenter: flush = 0.5; break; - case UITextAlignmentRight: flush = 1; break; - case UITextAlignmentLeft: + case NSCenterTextAlignment: flush = 0.5; break; + case NSRightTextAlignment: flush = 1; break; + case NSLeftTextAlignment: default: flush = 0; break; } @@ -217,12 +217,12 @@ - (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(UILineB - (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font { - return [self drawInRect:rect withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft]; + return [self drawInRect:rect withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:NSLeftTextAlignment]; } - (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode { - return [self drawInRect:rect withFont:font lineBreakMode:lineBreakMode alignment:UITextAlignmentLeft]; + return [self drawInRect:rect withFont:font lineBreakMode:lineBreakMode alignment:NSLeftTextAlignment]; } @end diff --git a/UIKit/Classes/UITextField+Private.h b/UIKit/Classes/UITextField+Private.h new file mode 100644 index 00000000..68330f08 --- /dev/null +++ b/UIKit/Classes/UITextField+Private.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2011, The Iconfactory. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of The Iconfactory nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@interface UITextField(Private) + +- (id)textLayer; + +@end + diff --git a/UIKit/Classes/UITextField.h b/UIKit/Classes/UITextField.h index 9c569090..a3d2634e 100644 --- a/UIKit/Classes/UITextField.h +++ b/UIKit/Classes/UITextField.h @@ -81,6 +81,7 @@ typedef enum { NSString *_placeholder; UITextBorderStyle _borderStyle; CGFloat _minimumFontSize; + UITextAutocorrectionType _autocorrectionType; UIView *_inputAccessoryView; UIView *_inputView; @@ -108,7 +109,7 @@ typedef enum { - (void)drawTextInRect:(CGRect)rect; @property (nonatomic, assign) id delegate; -@property (nonatomic, assign) UITextAlignment textAlignment; +@property (nonatomic, assign) NSTextAlignment textAlignment; @property (nonatomic, copy) NSString *placeholder; @property (nonatomic, copy) NSString *text; @property (nonatomic, retain) UIFont *font; diff --git a/UIKit/Classes/UITextField.m b/UIKit/Classes/UITextField.m index 27f24fed..1b1b32d7 100644 --- a/UIKit/Classes/UITextField.m +++ b/UIKit/Classes/UITextField.m @@ -56,13 +56,14 @@ - (id)initWithFrame:(CGRect)frame _textLayer = [[UITextLayer alloc] initWithContainer:self isField:YES]; [self.layer insertSublayer:_textLayer atIndex:0]; - self.textAlignment = UITextAlignmentLeft; + self.textAlignment = NSLeftTextAlignment; self.font = [UIFont systemFontOfSize:17]; self.borderStyle = UITextBorderStyleNone; self.textColor = [UIColor blackColor]; self.clearButtonMode = UITextFieldViewModeNever; self.leftViewMode = UITextFieldViewModeNever; self.rightViewMode = UITextFieldViewModeNever; + self.autocorrectionType = UITextAutocorrectionTypeDefault; self.opaque = NO; } return self; @@ -194,6 +195,11 @@ - (void)setFrame:(CGRect)frame } } +- (void)setHidden:(BOOL)hidden +{ + [super setHidden:hidden]; + [_textLayer setHidden:hidden]; +} - (CGRect)borderRectForBounds:(CGRect)bounds { @@ -287,6 +293,12 @@ - (CGRect)textRectForBounds:(CGRect)bounds - (void)drawPlaceholderInRect:(CGRect)rect { + // inset the rect by the offset required to vertically centre the text + CGFloat fontHeight = self.font.ascender + self.font.xHeight; + CGRect placeholderRect = CGRectInset(rect, 0, (rect.size.height - fontHeight) / 2); + + [[UIColor colorWithWhite:0.7 alpha:1.0] set]; + [self->_placeholder drawInRect:placeholderRect withFont:self.font]; } - (void)drawTextInRect:(CGRect)rect @@ -297,6 +309,10 @@ - (void)drawRect:(CGRect)rect { UIImage *background = self.enabled? _background : _disabledBackground; [background drawInRect:self.bounds]; + + if ([self.text length] == 0) { + [self drawPlaceholderInRect:[self placeholderRectForBounds:self.bounds]]; + } } @@ -311,11 +327,13 @@ - (void)setAutocapitalizationType:(UITextAutocapitalizationType)type - (UITextAutocorrectionType)autocorrectionType { - return UITextAutocorrectionTypeDefault; + return self->_autocorrectionType; } - (void)setAutocorrectionType:(UITextAutocorrectionType)type { + self->_autocorrectionType = type; + [self->_textLayer setAutocorrectionType:type]; } - (BOOL)enablesReturnKeyAutomatically @@ -408,12 +426,12 @@ - (void)setTextColor:(UIColor *)newColor _textLayer.textColor = newColor; } -- (UITextAlignment)textAlignment +- (NSTextAlignment)textAlignment { return _textLayer.textAlignment; } -- (void)setTextAlignment:(UITextAlignment)textAlignment +- (void)setTextAlignment:(NSTextAlignment)textAlignment { _textLayer.textAlignment = textAlignment; } @@ -496,13 +514,13 @@ - (NSString *)description { NSString *textAlignment = @""; switch (self.textAlignment) { - case UITextAlignmentLeft: + case NSLeftTextAlignment: textAlignment = @"Left"; break; - case UITextAlignmentCenter: + case NSCenterTextAlignment: textAlignment = @"Center"; break; - case UITextAlignmentRight: + case NSRightTextAlignment: textAlignment = @"Right"; break; } @@ -514,4 +532,6 @@ - (id)mouseCursorForEvent:(UIEvent *)event return [NSCursor IBeamCursor]; } +- (UITextLayer *)textLayer { return _textLayer; } + @end diff --git a/UIKit/Classes/UITextLayer+Private.h b/UIKit/Classes/UITextLayer+Private.h new file mode 100644 index 00000000..5a8b2a48 --- /dev/null +++ b/UIKit/Classes/UITextLayer+Private.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2011, The Iconfactory. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of The Iconfactory nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@interface UITextLayer(Private) + +- (id)containerView; + +@end + diff --git a/UIKit/Classes/UITextLayer.h b/UIKit/Classes/UITextLayer.h index c6092e0f..26b23751 100644 --- a/UIKit/Classes/UITextLayer.h +++ b/UIKit/Classes/UITextLayer.h @@ -30,6 +30,7 @@ #import #import #import "UIStringDrawing.h" +#import "UITextInputTraits.h" @class UICustomNSClipView, UICustomNSTextView, UIColor, UIFont, UIScrollView, UIWindow, UIView; @@ -66,7 +67,7 @@ @end @interface UITextLayer : CALayer { - id containerView; + UIView *containerView; BOOL containerCanScroll; UICustomNSTextView *textView; UICustomNSClipView *clipView; @@ -85,6 +86,7 @@ - (id)initWithContainer:(UIView *)aView isField:(BOOL)isField; - (void)setContentOffset:(CGPoint)contentOffset; +- (void)setAutocorrectionType:(UITextAutocorrectionType)type; - (void)scrollRangeToVisible:(NSRange)range; - (BOOL)becomeFirstResponder; - (BOOL)resignFirstResponder; @@ -95,6 +97,6 @@ @property (nonatomic, retain) UIFont *font; @property (nonatomic, assign) BOOL editable; @property (nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry; -@property (nonatomic, assign) UITextAlignment textAlignment; +@property (nonatomic, assign) NSTextAlignment textAlignment; @end diff --git a/UIKit/Classes/UITextLayer.m b/UIKit/Classes/UITextLayer.m index 638e48ab..d884ba11 100644 --- a/UIKit/Classes/UITextLayer.m +++ b/UIKit/Classes/UITextLayer.m @@ -28,6 +28,7 @@ */ #import "UITextLayer.h" +#import "UITextLayer+Private.h" #import "UIScrollView.h" #import "UICustomNSTextView.h" #import "UICustomNSClipView.h" @@ -71,7 +72,7 @@ - (id)initWithContainer:(UIView containerView; } + @end diff --git a/UIKit/Classes/UITextView.h b/UIKit/Classes/UITextView.h index 678b67b2..ab00ec2b 100644 --- a/UIKit/Classes/UITextView.h +++ b/UIKit/Classes/UITextView.h @@ -71,7 +71,7 @@ extern NSString *const UITextViewTextDidEndEditingNotification; - (void)scrollRangeToVisible:(NSRange)range; -@property (nonatomic) UITextAlignment textAlignment; // stub, not yet implemented! +@property (nonatomic) NSTextAlignment textAlignment; // stub, not yet implemented! @property (nonatomic) NSRange selectedRange; @property (nonatomic, getter=isEditable) BOOL editable; @property (nonatomic, copy) NSString *text; diff --git a/UIKit/Classes/UITextView.m b/UIKit/Classes/UITextView.m index a89563df..1d54ddfb 100644 --- a/UIKit/Classes/UITextView.m +++ b/UIKit/Classes/UITextView.m @@ -199,12 +199,12 @@ - (void)setTextColor:(UIColor *)newColor _textLayer.textColor = newColor; } -- (UITextAlignment)textAlignment +- (NSTextAlignment)textAlignment { return _textLayer.textAlignment; } -- (void)setTextAlignment:(UITextAlignment)textAlignment +- (void)setTextAlignment:(NSTextAlignment)textAlignment { _textLayer.textAlignment = textAlignment; } @@ -310,15 +310,21 @@ - (NSString *)description { NSString *textAlignment = @""; switch (self.textAlignment) { - case UITextAlignmentLeft: + case NSLeftTextAlignment: textAlignment = @"Left"; break; - case UITextAlignmentCenter: + case NSCenterTextAlignment: textAlignment = @"Center"; break; - case UITextAlignmentRight: + case NSRightTextAlignment: textAlignment = @"Right"; break; + case NSJustifiedTextAlignment: + textAlignment = @"Justified"; + break; + case NSNaturalTextAlignment: + textAlignment = @"Natural"; + break; } return [NSString stringWithFormat:@"<%@: %p; textAlignment = %@; selectedRange = %@; editable = %@; textColor = %@; font = %@; delegate = %@>", [self className], self, textAlignment, NSStringFromRange(self.selectedRange), (self.editable ? @"YES" : @"NO"), self.textColor, self.font, self.delegate]; } diff --git a/UIKit/Classes/UIView.h b/UIKit/Classes/UIView.h index 655518bc..807a6019 100644 --- a/UIKit/Classes/UIView.h +++ b/UIKit/Classes/UIView.h @@ -110,6 +110,7 @@ typedef NSUInteger UIViewAnimationOptions; BOOL _autoresizesSubviews; BOOL _userInteractionEnabled; CALayer *_layer; + CGRect _frame; NSInteger _tag; UIViewContentMode _contentMode; UIColor *_backgroundColor; @@ -206,5 +207,6 @@ typedef NSUInteger UIViewAnimationOptions; @property (nonatomic, getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled; // state is maintained, but it has no effect @property (nonatomic, getter=isExclusiveTouch) BOOL exclusiveTouch; // state is maintained, but it has no effect @property (nonatomic,copy) NSArray *gestureRecognizers; +@property (nonatomic, assign) BOOL translatesAutoresizingMaskIntoConstraints; @end diff --git a/UIKit/Classes/UIView.m b/UIKit/Classes/UIView.m index ecdc0d27..9d007f85 100644 --- a/UIKit/Classes/UIView.m +++ b/UIKit/Classes/UIView.m @@ -81,14 +81,16 @@ - (id)init - (id)initWithFrame:(CGRect)theFrame { if ((self=[super init])) { - _implementsDrawRect = [isa _instanceImplementsDrawRect]; + _implementsDrawRect = [[self class] _instanceImplementsDrawRect]; _clearsContextBeforeDrawing = YES; _autoresizesSubviews = YES; _userInteractionEnabled = YES; _subviews = [[NSMutableSet alloc] init]; _gestureRecognizers = [[NSMutableSet alloc] init]; - _layer = [[[isa layerClass] alloc] init]; + _frame = CGRectZero; + + _layer = [[[[self class] layerClass] alloc] init]; _layer.delegate = self; _layer.layoutManager = [UIViewLayoutManager layoutManager]; @@ -228,10 +230,12 @@ - (void)addSubview:(UIView *)subview UIWindow *oldWindow = subview.window; UIWindow *newWindow = self.window; - subview->_needsDidAppearOrDisappear = [self _subviewControllersNeedAppearAndDisappear]; + subview->_needsDidAppearOrDisappear = YES;//[self _subviewControllersNeedAppearAndDisappear]; if ([subview _viewController] && subview->_needsDidAppearOrDisappear) { - [[subview _viewController] viewWillAppear:NO]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[subview _viewController] viewWillAppear:NO]; + }); } [subview _willMoveFromWindow:oldWindow toWindow:newWindow]; @@ -266,7 +270,9 @@ - (void)addSubview:(UIView *)subview [self didAddSubview:subview]; if ([subview _viewController] && subview->_needsDidAppearOrDisappear) { - [[subview _viewController] viewDidAppear:NO]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[subview _viewController] viewDidAppear:NO]; + }); } } } @@ -618,41 +624,41 @@ - (void)_superviewSizeDidChangeFrom:(CGSize)oldSize to:(CGSize)newSize */ if (hasAutoresizingFor(UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin)) { - frame.origin.y = floorf(frame.origin.y + (frame.origin.y / oldSize.height * delta.height)); - frame.size.height = floorf(frame.size.height + (frame.size.height / oldSize.height * delta.height)); + frame.origin.y += frame.origin.y / oldSize.height * delta.height; + frame.size.height += frame.size.height / oldSize.height * delta.height; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight)) { const CGFloat t = frame.origin.y + frame.size.height; - frame.origin.y = floorf(frame.origin.y + (frame.origin.y / t * delta.height)); - frame.size.height = floorf(frame.size.height + (frame.size.height / t * delta.height)); + frame.origin.y += frame.origin.y / t * delta.height; + frame.size.height += frame.size.height / t * delta.height; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight)) { - frame.size.height = floorf(frame.size.height + (frame.size.height / (oldSize.height - frame.origin.y) * delta.height)); + frame.size.height += frame.size.height / (oldSize.height - frame.origin.y) * delta.height; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin)) { - frame.origin.y = floorf(frame.origin.y + (delta.height / 2.f)); + frame.origin.y += delta.height / 2.f; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleHeight)) { - frame.size.height = floorf(frame.size.height + delta.height); + frame.size.height += delta.height; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleTopMargin)) { - frame.origin.y = floorf(frame.origin.y + delta.height); + frame.origin.y += delta.height; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleBottomMargin)) { - frame.origin.y = floorf(frame.origin.y); + // nothing required } if (hasAutoresizingFor(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin)) { - frame.origin.x = floorf(frame.origin.x + (frame.origin.x / oldSize.width * delta.width)); - frame.size.width = floorf(frame.size.width + (frame.size.width / oldSize.width * delta.width)); + frame.origin.x += frame.origin.x / oldSize.width * delta.width; + frame.size.width += frame.size.width / oldSize.width * delta.width; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth)) { const CGFloat t = frame.origin.x + frame.size.width; - frame.origin.x = floorf(frame.origin.x + (frame.origin.x / t * delta.width)); - frame.size.width = floorf(frame.size.width + (frame.size.width / t * delta.width)); + frame.origin.x += frame.origin.x / t * delta.width; + frame.size.width += frame.size.width / t * delta.width; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth)) { - frame.size.width = floorf(frame.size.width + (frame.size.width / (oldSize.width - frame.origin.x) * delta.width)); + frame.size.width += frame.size.width / (oldSize.width - frame.origin.x) * delta.width; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin)) { - frame.origin.x = floorf(frame.origin.x + (delta.width / 2.f)); + frame.origin.x += delta.width / 2.f; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleWidth)) { - frame.size.width = floorf(frame.size.width + delta.width); + frame.size.width += delta.width; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleLeftMargin)) { - frame.origin.x = floorf(frame.origin.x + delta.width); + frame.origin.x += delta.width; } else if (hasAutoresizingFor(UIViewAutoresizingFlexibleRightMargin)) { - frame.origin.x = floorf(frame.origin.x); + // nothing required } self.frame = frame; @@ -684,14 +690,17 @@ + (NSSet *)keyPathsForValuesAffectingFrame - (CGRect)frame { - return _layer.frame; + return _frame; } - (void)setFrame:(CGRect)newFrame { - if (!CGRectEqualToRect(newFrame,_layer.frame)) { + _frame = newFrame; + + if (!CGRectEqualToRect(CGRectIntegral(newFrame),CGRectIntegral(_layer.frame))) { CGRect oldBounds = _layer.bounds; - _layer.frame = newFrame; + CGRect roundedFrame = CGRectIntegral(_frame); + _layer.frame = roundedFrame; [self _boundsDidChangeFrom:oldBounds to:_layer.bounds]; [[NSNotificationCenter defaultCenter] postNotificationName:UIViewFrameDidChangeNotification object:self]; } diff --git a/UIKit/Classes/UIViewAdapter.m b/UIKit/Classes/UIViewAdapter.m index 6e05ce87..242a6872 100644 --- a/UIKit/Classes/UIViewAdapter.m +++ b/UIKit/Classes/UIViewAdapter.m @@ -113,7 +113,7 @@ - (void)_updateLayers CALayer *clipLayer = [_clipView layer]; // setting these here because I've had bad experiences with NSView changing some layer properties out from under me. - clipLayer.geometryFlipped = YES; + clipLayer.geometryFlipped = NO; // always make sure it's at the very bottom [layer insertSublayer:clipLayer atIndex:0]; diff --git a/UIKit/Classes/UIViewController.h b/UIKit/Classes/UIViewController.h index 87796790..2f77a390 100644 --- a/UIKit/Classes/UIViewController.h +++ b/UIKit/Classes/UIViewController.h @@ -89,6 +89,9 @@ typedef enum { - (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated; // works, but not exactly correctly. - (void)dismissModalViewControllerAnimated:(BOOL)animated; // see comments in dismissModalViewController +- (void)presentViewController:(UIViewController *)modalViewController animated:(BOOL)animated completion:(void(^)(void))completion; +- (void)dismissViewControllerAnimated:(BOOL)animated completion:(void(^)(void))completion; + - (void)didReceiveMemoryWarning; // doesn't do anything and is never called... - (void)setToolbarItems:(NSArray *)toolbarItems animated:(BOOL)animated; @@ -105,6 +108,8 @@ typedef enum { @property (nonatomic, readonly, retain) NSBundle *nibBundle; // always returns nil @property (nonatomic, retain) UIView *view; @property (nonatomic, assign) BOOL wantsFullScreenLayout; // doesn't do anything right now +@property (nonatomic, assign) BOOL shouldAutorotate; // always returns NO +@property (nonatomic, assign) NSUInteger supportedInterfaceOrientations; // always returns UIInterfaceOrientationLandscapeLeft @property (nonatomic, copy) NSString *title; @property (nonatomic, readonly) UIInterfaceOrientation interfaceOrientation; // always returns UIInterfaceOrientationLandscapeLeft @property (nonatomic, readonly, retain) UINavigationItem *navigationItem; @@ -119,6 +124,8 @@ typedef enum { @property (nonatomic, assign) UIModalPresentationStyle modalPresentationStyle; @property (nonatomic, assign) UIModalTransitionStyle modalTransitionStyle; // not used right now +@property (nonatomic, readonly) UIViewController *presentedViewController; + @property (nonatomic, readonly) UIViewController *parentViewController; @property (nonatomic, readonly, retain) UINavigationController *navigationController; @property (nonatomic, readonly, retain) UISplitViewController *splitViewController; diff --git a/UIKit/Classes/UIViewController.m b/UIKit/Classes/UIViewController.m index 6d0ec441..1a090c0a 100644 --- a/UIKit/Classes/UIViewController.m +++ b/UIKit/Classes/UIViewController.m @@ -255,6 +255,32 @@ - (void)dismissModalViewControllerAnimated:(BOOL)animated } } +- (void)presentViewController:(UIViewController *)modalViewController animated:(BOOL)animated completion:(void(^)(void))completion +{ + // this isn't exactly right either, but close enough + [self presentModalViewController:modalViewController animated:animated]; + + if (completion != NULL) { + completion(); + } +} + +- (void)dismissViewControllerAnimated:(BOOL)animated completion:(void(^)(void))completion +{ + // this isn't exactly right either, but close enough + [self dismissModalViewControllerAnimated:animated]; + + if (completion != NULL) { + completion(); + } +} + +- (UIViewController *)presentedViewController +{ + return self.modalViewController; +} + + - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); @@ -298,4 +324,14 @@ - (NSString *)description return [NSString stringWithFormat:@"<%@: %p; title = %@; view = %@>", [self className], self, self.title, self.view]; } +- (BOOL)shouldAutorotate +{ + return NO; +} + +- (NSUInteger)supportedInterfaceOrientations +{ + return UIInterfaceOrientationLandscapeLeft; +} + @end diff --git a/UIKit/Classes/UIWebView.h b/UIKit/Classes/UIWebView.h index 768934f7..cc10cc6d 100644 --- a/UIKit/Classes/UIWebView.h +++ b/UIKit/Classes/UIWebView.h @@ -82,4 +82,12 @@ typedef NSUInteger UIWebViewNavigationType; @property (nonatomic, readonly, retain) NSURLRequest *request; @property (nonatomic) UIDataDetectorTypes dataDetectorTypes; +@property (nonatomic, assign) BOOL allowsInlineMediaPlayback; +@property (nonatomic, assign) BOOL mediaPlaybackRequiresUserAction; +@property (nonatomic, assign) BOOL mediaPlaybackAllowsAirPlay; +@property (nonatomic, assign) BOOL keyboardDisplayRequiresUserAction; + +// Chameleon specific +@property (nonatomic, assign) BOOL chameleonAllowContextMenu; + @end diff --git a/UIKit/Classes/UIWebView.m b/UIKit/Classes/UIWebView.m index df9da91c..166b8123 100644 --- a/UIKit/Classes/UIWebView.m +++ b/UIKit/Classes/UIWebView.m @@ -31,13 +31,35 @@ #import "UIViewAdapter.h" #import +@interface WebPreferences (WebPreferencesPrivate) +- (void)_setLocalStorageDatabasePath:(NSString *)path; +- (void) setLocalStorageEnabled: (BOOL) localStorageEnabled; +- (void) setDatabasesEnabled:(BOOL)databasesEnabled; +- (void) setDeveloperExtrasEnabled:(BOOL)developerExtrasEnabled; +- (void) setWebGLEnabled:(BOOL)webGLEnabled; +- (void) setOfflineWebApplicationCacheEnabled:(BOOL)offlineWebApplicationCacheEnabled; + +- (NSString *)_localStorageDatabasePath; +- (void)_setLocalStorageDatabasePath:(NSString *)path; +@end + @implementation UIWebView @synthesize request=_request, delegate=_delegate, dataDetectorTypes=_dataDetectorTypes, scalesPageToFit=_scalesPageToFit; +@synthesize chameleonAllowContextMenu; + +- (NSString *)_localStorageDatabasePath +{ + NSString *appName = [[NSRunningApplication currentApplication] localizedName]; + NSURL *applicationSupport = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] firstObject]; + NSString *databasePath = [NSString stringWithFormat:@"%@/%@/WebKit/LocalStorage", [applicationSupport path], appName]; + return databasePath; +} - (id)initWithFrame:(CGRect)frame { if ((self=[super initWithFrame:frame])) { _scalesPageToFit = NO; + self.chameleonAllowContextMenu = NO; _webView = [(WebView *)[WebView alloc] initWithFrame:NSRectFromCGRect(self.bounds)]; [_webView setAutoresizingMask:(NSViewWidthSizable|NSViewHeightSizable)]; @@ -45,6 +67,14 @@ - (id)initWithFrame:(CGRect)frame [_webView setFrameLoadDelegate:self]; [_webView setUIDelegate:self]; [_webView setDrawsBackground:NO]; + + WebPreferences *preferences = [WebPreferences standardPreferences]; + [preferences setOfflineWebApplicationCacheEnabled:YES]; + [preferences setDeveloperExtrasEnabled:YES]; + [preferences _setLocalStorageDatabasePath:[self _localStorageDatabasePath]]; + [preferences setLocalStorageEnabled:YES]; + + [_webView setPreferences:preferences]; _webViewAdapter = [[UIViewAdapter alloc] initWithFrame:self.bounds]; _webViewAdapter.NSView = _webView; @@ -211,7 +241,11 @@ - (void)webView:(WebView *)sender makeFirstResponder:(NSResponder *)responder - (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems { - return [NSArray array]; + if (self.chameleonAllowContextMenu == YES) { + return defaultMenuItems; + } else { + return [NSArray array]; + } } - (BOOL)webViewIsResizable:(WebView *)sender diff --git a/UIKit/Classes/UIWindow.m b/UIKit/Classes/UIWindow.m index af5f20d4..22c03009 100644 --- a/UIKit/Classes/UIWindow.m +++ b/UIKit/Classes/UIWindow.m @@ -370,7 +370,10 @@ - (void)sendEvent:(UIEvent *)event NSCursor *newCursor = [view mouseCursorForEvent:event] ?: [NSCursor arrowCursor]; if ([NSCursor currentCursor] != newCursor) { - [newCursor set]; + // Hack: Disabled by Michael Melanson + // because it was interfering with our use case. + + //[newCursor set]; } [view release];