Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian William Wolter committed Aug 17, 2011
2 parents a85f698 + 95bd784 commit 2cd3630
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 33 deletions.
16 changes: 16 additions & 0 deletions TwUI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@
886EBA8313D64393006DE018 /* TUIControl+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 886EBA7E13D64393006DE018 /* TUIControl+Private.m */; };
886EBA8413D64393006DE018 /* TUIControl+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 886EBA7E13D64393006DE018 /* TUIControl+Private.m */; };
886EBA8513D64393006DE018 /* TUIControl+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 886EBA7E13D64393006DE018 /* TUIControl+Private.m */; };
887F272C13F9969800D75DE6 /* TUITableViewSectionHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 887F272A13F9969800D75DE6 /* TUITableViewSectionHeader.h */; settings = {ATTRIBUTES = (Public, ); }; };
887F272D13F9969800D75DE6 /* TUITableViewSectionHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 887F272A13F9969800D75DE6 /* TUITableViewSectionHeader.h */; };
887F272E13F9969800D75DE6 /* TUITableViewSectionHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 887F272A13F9969800D75DE6 /* TUITableViewSectionHeader.h */; };
887F272F13F9969800D75DE6 /* TUITableViewSectionHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 887F272B13F9969800D75DE6 /* TUITableViewSectionHeader.m */; };
887F273013F9969800D75DE6 /* TUITableViewSectionHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 887F272B13F9969800D75DE6 /* TUITableViewSectionHeader.m */; };
887F273113F9969800D75DE6 /* TUITableViewSectionHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 887F272B13F9969800D75DE6 /* TUITableViewSectionHeader.m */; };
88CC1F2F13E365B600827793 /* TUIControl+Accessibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 88CC1F2D13E365B500827793 /* TUIControl+Accessibility.h */; };
88CC1F3013E365B600827793 /* TUIControl+Accessibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 88CC1F2D13E365B500827793 /* TUIControl+Accessibility.h */; };
88CC1F3113E365B600827793 /* TUIControl+Accessibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 88CC1F2D13E365B500827793 /* TUIControl+Accessibility.h */; };
Expand Down Expand Up @@ -266,6 +272,8 @@
8819794B13E26E5800AA39EB /* TUINSView+Accessibility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TUINSView+Accessibility.m"; sourceTree = "<group>"; };
886EBA7D13D64393006DE018 /* TUIControl+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TUIControl+Private.h"; sourceTree = "<group>"; };
886EBA7E13D64393006DE018 /* TUIControl+Private.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TUIControl+Private.m"; sourceTree = "<group>"; };
887F272A13F9969800D75DE6 /* TUITableViewSectionHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUITableViewSectionHeader.h; sourceTree = "<group>"; };
887F272B13F9969800D75DE6 /* TUITableViewSectionHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUITableViewSectionHeader.m; sourceTree = "<group>"; };
88CC1F2D13E365B500827793 /* TUIControl+Accessibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TUIControl+Accessibility.h"; sourceTree = "<group>"; };
88CC1F2E13E365B500827793 /* TUIControl+Accessibility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TUIControl+Accessibility.m"; sourceTree = "<group>"; };
88CC1F3513E3684400827793 /* TUIButton+Accessibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TUIButton+Accessibility.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -593,6 +601,8 @@
CBB74C7413BE6E1900C85CB5 /* TUITableViewCell.m */,
88D25F5313F5D96500CFAAA9 /* TUITableView+Cell.h */,
88D25F5413F5D96500CFAAA9 /* TUITableView+Cell.m */,
887F272A13F9969800D75DE6 /* TUITableViewSectionHeader.h */,
887F272B13F9969800D75DE6 /* TUITableViewSectionHeader.m */,
CBB74C7513BE6E1900C85CB5 /* TUITextEditor.h */,
CBB74C7613BE6E1900C85CB5 /* TUITextEditor.m */,
CBB74C7713BE6E1900C85CB5 /* TUITextField.h */,
Expand Down Expand Up @@ -644,6 +654,7 @@
88CC1F3913E3684700827793 /* TUIButton+Accessibility.h in Headers */,
88EFFB5313F417E200CF91A9 /* TUITextViewEditor.h in Headers */,
88D25F5713F5D96500CFAAA9 /* TUITableView+Cell.h in Headers */,
887F272E13F9969800D75DE6 /* TUITableViewSectionHeader.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -692,6 +703,7 @@
CBB74CE213BE6E1900C85CB5 /* TUIView.h in Headers */,
CBB74CE413BE6E1900C85CB5 /* TUIViewController.h in Headers */,
CBB74CE613BE6E1900C85CB5 /* TUIViewNSViewContainer.h in Headers */,
887F272C13F9969800D75DE6 /* TUITableViewSectionHeader.h in Headers */,
886EBA7F13D64393006DE018 /* TUIControl+Private.h in Headers */,
8819794413E26E0200AA39EB /* TUIView+Accessibility.h in Headers */,
8819794C13E26E5800AA39EB /* TUINSView+Accessibility.h in Headers */,
Expand All @@ -713,6 +725,7 @@
88CC1F3813E3684700827793 /* TUIButton+Accessibility.h in Headers */,
88EFFB5213F417E200CF91A9 /* TUITextViewEditor.h in Headers */,
88D25F5613F5D96500CFAAA9 /* TUITableView+Cell.h in Headers */,
887F272D13F9969800D75DE6 /* TUITableViewSectionHeader.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -912,6 +925,7 @@
88CC1F3C13E3684700827793 /* TUIButton+Accessibility.m in Sources */,
88EFFB5613F417E200CF91A9 /* TUITextViewEditor.m in Sources */,
88D25F5A13F5D96500CFAAA9 /* TUITableView+Cell.m in Sources */,
887F273113F9969800D75DE6 /* TUITableViewSectionHeader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -972,6 +986,7 @@
88CC1F3A13E3684700827793 /* TUIButton+Accessibility.m in Sources */,
88EFFB5413F417E200CF91A9 /* TUITextViewEditor.m in Sources */,
88D25F5813F5D96500CFAAA9 /* TUITableView+Cell.m in Sources */,
887F272F13F9969800D75DE6 /* TUITableViewSectionHeader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1041,6 +1056,7 @@
88CC1F3B13E3684700827793 /* TUIButton+Accessibility.m in Sources */,
88EFFB5513F417E200CF91A9 /* TUITextViewEditor.m in Sources */,
88D25F5913F5D96500CFAAA9 /* TUITableView+Cell.m in Sources */,
887F273013F9969800D75DE6 /* TUITableViewSectionHeader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
21 changes: 1 addition & 20 deletions lib/UIKit/TUIButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,7 @@ - (void)drawRect:(CGRect)r
- (void)mouseDown:(NSEvent *)event
{
[super mouseDown:event];
if([event clickCount] < 2) {
[self sendActionsForControlEvents:TUIControlEventTouchDown];
} else {
[self sendActionsForControlEvents:TUIControlEventTouchDownRepeat];
}


if(popUpMenu) { // happens even if clickCount is big
NSMenu *menu = popUpMenu;
NSPoint p = [self frameInNSView].origin;
Expand All @@ -240,20 +235,6 @@ - (void)mouseDown:(NSEvent *)event
}
}

- (void)mouseUp:(NSEvent *)event
{
[super mouseUp:event];
// if([event clickCount] < 2) {
if([self eventInside:event]) {
if(![self didDrag]) {
[self sendActionsForControlEvents:TUIControlEventTouchUpInside];
}
} else {
[self sendActionsForControlEvents:TUIControlEventTouchUpOutside];
}
// }
}

- (void)_update {
_titleView.text = self.currentTitle;
_titleView.textColor = self.currentTitleColor;
Expand Down
29 changes: 16 additions & 13 deletions lib/UIKit/TUIControl.m
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ -(BOOL)selected {
*/
-(void)setSelected:(BOOL)selected {
[self _stateWillChange];
_controlFlags.selected = selected;
_controlFlags.selected = selected;
[self _stateDidChange];
[self setNeedsDisplay];
[self setNeedsDisplay];
}

- (BOOL)acceptsFirstMouse
Expand All @@ -124,12 +124,15 @@ - (void)mouseDown:(NSEvent *)event
_controlFlags.tracking = 1;
[self _stateDidChange];

// handle touch down
[self sendActionsForControlEvents:TUIControlEventTouchDown];
// handle touch down
if([event clickCount] < 2) {
[self sendActionsForControlEvents:TUIControlEventTouchDown];
} else {
[self sendActionsForControlEvents:TUIControlEventTouchDownRepeat];
}

// needs display
[self setNeedsDisplay];

}

- (void)mouseUp:(NSEvent *)event
Expand All @@ -141,16 +144,16 @@ - (void)mouseUp:(NSEvent *)event
_controlFlags.tracking = 0;
[self _stateDidChange];

// handle touch up
if([self pointInside:[self localPointForEvent:event] withEvent:event]){
[self sendActionsForControlEvents:TUIControlEventTouchUpInside];
}else{
[self sendActionsForControlEvents:TUIControlEventTouchUpOutside];
}
if([self eventInside:event]) {
if(![self didDrag]) {
[self sendActionsForControlEvents:TUIControlEventTouchUpInside];
}
} else {
[self sendActionsForControlEvents:TUIControlEventTouchUpOutside];
}

// needs display
// needs display
[self setNeedsDisplay];

}

@end
1 change: 1 addition & 0 deletions lib/UIKit/TUITextRenderer+Event.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
@interface TUITextRenderer (Event)

- (CFIndex)stringIndexForPoint:(CGPoint)p;
- (CFIndex)stringIndexForEvent:(NSEvent *)event;
- (void)resetSelection;
- (CGRect)rectForCurrentSelection;

Expand Down
8 changes: 8 additions & 0 deletions lib/UIKit/TUITextView.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@
TUIColor *textColor;
TUITextAlignment textAlignment;
BOOL editable;

BOOL spellCheckingEnabled;
NSInteger lastCheckToken;
NSArray *lastCheckResults;
NSTextCheckingResult *selectedTextCheckingResult;
BOOL autocorrectionEnabled;

TUIEdgeInsets contentInset;

Expand Down Expand Up @@ -62,6 +68,8 @@

@property (nonatomic, assign) NSRange selectedRange;
@property (nonatomic, assign, getter=isEditable) BOOL editable;
@property (nonatomic, assign, getter=isSpellCheckingEnabled) BOOL spellCheckingEnabled;
@property (nonatomic, assign, getter=isAutocorrectionEnabled) BOOL autocorrectionEnabled;

@property (nonatomic, copy) TUIViewDrawRect drawFrame;

Expand Down
99 changes: 99 additions & 0 deletions lib/UIKit/TUITextView.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@
#import "TUIKit.h"
#import "TUITextView.h"
#import "TUITextViewEditor.h"
#import "TUITextRenderer+Event.h"

@interface TUITextView ()
- (void)_checkSpelling;
- (void)_replaceMisspelledWord:(NSMenuItem *)menuItem;

@property (nonatomic, retain) NSArray *lastCheckResults;
@property (nonatomic, retain) NSTextCheckingResult *selectedTextCheckingResult;
@end

@implementation TUITextView

Expand All @@ -28,6 +37,10 @@ @implementation TUITextView
@synthesize editable;
@synthesize contentInset;
@synthesize placeholder;
@synthesize spellCheckingEnabled;
@synthesize lastCheckResults;
@synthesize selectedTextCheckingResult;
@synthesize autocorrectionEnabled;

- (void)_updateDefaultAttributes
{
Expand Down Expand Up @@ -76,6 +89,8 @@ - (void)dealloc
[font release];
[textColor release];
[placeholder release];
[lastCheckResults release];
[selectedTextCheckingResult release];
[super dealloc];
}

Expand Down Expand Up @@ -259,6 +274,90 @@ - (void)_textDidChange
{
if(_textViewFlags.delegateTextViewDidChange)
[delegate textViewDidChange:self];

if(spellCheckingEnabled) {
[self _checkSpelling];
}
}

- (void)_checkSpelling
{
lastCheckToken = [[NSSpellChecker sharedSpellChecker] requestCheckingOfString:self.text range:NSMakeRange(0, [self.text length]) types:NSTextCheckingTypeSpelling options:nil inSpellDocumentWithTag:0 completionHandler:^(NSInteger sequenceNumber, NSArray *results, NSOrthography *orthography, NSInteger wordCount) {
// This needs to happen on the main thread so that the user doesn't enter more text while we're changing the attributed string.
dispatch_async(dispatch_get_main_queue(), ^{
// we only care about the most recent results, ignore anything older
if(sequenceNumber != lastCheckToken) return;

[[renderer backingStore] beginEditing];

NSRange wholeStringRange = NSMakeRange(0, [self.text length]);
[[renderer backingStore] removeAttribute:(id)kCTUnderlineColorAttributeName range:wholeStringRange];
[[renderer backingStore] removeAttribute:(id)kCTUnderlineStyleAttributeName range:wholeStringRange];

NSRange selectionRange = [self selectedRange];
for(NSTextCheckingResult *result in results) {
// Don't spell check the word they're typing, otherwise we're constantly marking it as misspelled and that's lame.
BOOL isActiveWord = (result.range.location + result.range.length == selectionRange.location) && selectionRange.length == 0;
if(isActiveWord) continue;

[[renderer backingStore] addAttribute:(id)kCTUnderlineColorAttributeName value:(id)[TUIColor redColor].CGColor range:result.range];
[[renderer backingStore] addAttribute:(id)kCTUnderlineStyleAttributeName value:[NSNumber numberWithInteger:kCTUnderlineStyleThick | kCTUnderlinePatternDot] range:result.range];
}

[[renderer backingStore] endEditing];
[renderer reset]; // make sure we reset so that the renderer uses our new attributes

[self setNeedsDisplay];

self.lastCheckResults = results;
});
}];
}

- (NSMenu *)menuForEvent:(NSEvent *)event
{
CFIndex stringIndex = [renderer stringIndexForEvent:event];
for(NSTextCheckingResult *result in lastCheckResults) {
if(stringIndex >= result.range.location && stringIndex <= result.range.location + result.range.length) {
self.selectedTextCheckingResult = result;
break;
}
}

if(selectedTextCheckingResult == nil) return nil;

NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
NSArray *guesses = [[NSSpellChecker sharedSpellChecker] guessesForWordRange:selectedTextCheckingResult.range inString:[self text] language:nil inSpellDocumentWithTag:0];
if(guesses.count > 0) {
for(NSString *guess in guesses) {
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:guess action:@selector(_replaceMisspelledWord:) keyEquivalent:@""];
[menuItem setTarget:self];
[menuItem setRepresentedObject:guess];
[menu addItem:menuItem];
[menuItem release];
}
} else {
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:@"No guesses" action:NULL keyEquivalent:@""];
[menu addItem:menuItem];
[menuItem release];
}

return [menu autorelease];
}

- (void)_replaceMisspelledWord:(NSMenuItem *)menuItem
{
NSString *replacement = [menuItem representedObject];
[[renderer backingStore] beginEditing];
[[renderer backingStore] removeAttribute:(id)kCTUnderlineColorAttributeName range:selectedTextCheckingResult.range];
[[renderer backingStore] removeAttribute:(id)kCTUnderlineStyleAttributeName range:selectedTextCheckingResult.range];
[[renderer backingStore] replaceCharactersInRange:self.selectedTextCheckingResult.range withString:replacement];
[[renderer backingStore] endEditing];
[renderer reset];

[self _textDidChange];

self.selectedTextCheckingResult = nil;
}

- (NSRange)selectedRange
Expand Down

0 comments on commit 2cd3630

Please sign in to comment.