mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-19 08:53:30 +00:00
Fixed: Make sure the delegate methods and notifications are handled in the same way as in the Cooca frameworks.
CPTextViewDidChangeSelectionNotification should not be send if the text view is empty. CPTextDidBeginEditingNotification is send when an edit is started. CPTextDidEndEditingNotification is send when an edit is ending. textShouldBeginEditing: delegate method is called to allow control if edit should start. textShouldEndEditing: delegate method is called to allow control if edit should end.
This commit is contained in:
@@ -156,6 +156,8 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
CPTimer _scrollingTimer;
|
||||
|
||||
CPString _placeholderString;
|
||||
|
||||
BOOL _firstResponderButNotEditingYet;
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||
@@ -409,7 +411,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
- (void)_windowDidResignKey:(CPNotification)aNotification
|
||||
{
|
||||
if (![[self window] isKeyWindow])
|
||||
[self resignFirstResponder];
|
||||
[self _resignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)_windowDidBecomeKey:(CPNotification)aNotification
|
||||
@@ -503,17 +505,33 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
[super becomeFirstResponder];
|
||||
_firstResponderButNotEditingYet = YES;
|
||||
[self _becomeFirstResponder];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)resignFirstResponder
|
||||
- (void)_resignFirstResponder
|
||||
{
|
||||
[self _reverseSetBinding];
|
||||
[_caret stopBlinking];
|
||||
[self setNeedsDisplay:YES];
|
||||
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
||||
}
|
||||
|
||||
- (BOOL)resignFirstResponder
|
||||
{
|
||||
if (_firstResponderButNotEditingYet)
|
||||
_firstResponderButNotEditingYet = NO;
|
||||
else
|
||||
{
|
||||
if ([self _sendDelegateTextShouldEndEditing])
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextDidEndEditingNotification object:self];
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
[self _resignFirstResponder];
|
||||
|
||||
return YES;
|
||||
}
|
||||
@@ -708,7 +726,21 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
- (void)didChangeText
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextDidChangeNotification object:self];
|
||||
}
|
||||
|
||||
- (BOOL)_didBeginEditing
|
||||
{
|
||||
if (_firstResponderButNotEditingYet)
|
||||
{
|
||||
if ([self _sendDelegateTextShouldBeginEditing])
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextDidBeginEditingNotification object:self];
|
||||
_firstResponderButNotEditingYet = NO;
|
||||
} else
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)shouldChangeTextInRange:(CPRange)aRange replacementString:(CPString)aString
|
||||
@@ -716,7 +748,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
if (![self isEditable])
|
||||
return NO;
|
||||
|
||||
return [self _sendDelegateTextShouldBeginEditing] && [self _sendDelegateShouldChangeTextInRange:aRange replacementString:aString];
|
||||
return [self _sendDelegateShouldChangeTextInRange:aRange replacementString:aString];
|
||||
}
|
||||
|
||||
|
||||
@@ -748,7 +780,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
var isAttributed = [aString isKindOfClass:CPAttributedString],
|
||||
string = isAttributed ? [aString string]:aString;
|
||||
|
||||
if (![self shouldChangeTextInRange:CPMakeRangeCopy(_selectionRange) replacementString:string])
|
||||
if (![self _didBeginEditing] || ![self shouldChangeTextInRange:CPMakeRangeCopy(_selectionRange) replacementString:string])
|
||||
return;
|
||||
|
||||
if (!isAttributed)
|
||||
@@ -863,38 +895,45 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
- (void)_setSelectedRange:(CPRange)range affinity:(CPSelectionAffinity)affinity stillSelecting:(BOOL)selecting overwriteTypingAttributes:(BOOL)doOverwrite
|
||||
{
|
||||
var maxRange = CPMakeRange(0, [_layoutManager numberOfCharacters]);
|
||||
var maxRange = CPMakeRange(0, [_layoutManager numberOfCharacters]),
|
||||
newSelectionRange;
|
||||
|
||||
range = CPIntersectionRange(maxRange, range);
|
||||
|
||||
if (!selecting && [self _delegateRespondsToWillChangeSelectionFromCharacterRangeToCharacterRange])
|
||||
{
|
||||
_selectionRange = [self _sendDelegateWillChangeSelectionFromCharacterRange:_selectionRange toCharacterRange:range];
|
||||
newSelectionRange = [self _sendDelegateWillChangeSelectionFromCharacterRange:_selectionRange toCharacterRange:range];
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectionRange = CPMakeRangeCopy(range);
|
||||
_selectionRange = [self selectionRangeForProposedRange:_selectionRange granularity:[self selectionGranularity]];
|
||||
newSelectionRange = [self selectionRangeForProposedRange:range granularity:[self selectionGranularity]];
|
||||
}
|
||||
|
||||
if (_selectionRange.length)
|
||||
[_layoutManager invalidateDisplayForGlyphRange:_selectionRange];
|
||||
var isNewSelection = !CPEqualRanges(newSelectionRange, _selectionRange);
|
||||
|
||||
if (isNewSelection)
|
||||
_selectionRange = newSelectionRange;
|
||||
|
||||
if (newSelectionRange.length)
|
||||
{
|
||||
if (isNewSelection)
|
||||
[_layoutManager invalidateDisplayForGlyphRange:newSelectionRange];
|
||||
}
|
||||
else
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
if (!selecting)
|
||||
{
|
||||
if ([self _isFirstResponder])
|
||||
[self updateInsertionPointStateAndRestartTimer:((_selectionRange.length === 0) && ![_caret isBlinking])];
|
||||
[self updateInsertionPointStateAndRestartTimer:((newSelectionRange.length === 0) && ![_caret isBlinking])];
|
||||
|
||||
if (doOverwrite && _placeholderString === nil)
|
||||
if (doOverwrite && _placeholderString === nil && isNewSelection)
|
||||
[self setTypingAttributes:[_textStorage attributesAtIndex:CPMaxRange(range) effectiveRange:nil]];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextViewDidChangeSelectionNotification object:self];
|
||||
|
||||
}
|
||||
|
||||
if (!selecting && _selectionRange.length > 0)
|
||||
if (!selecting && newSelectionRange.length > 0)
|
||||
[_CPNativeInputManager focusForClipboardOfTextView:self];
|
||||
}
|
||||
|
||||
@@ -978,18 +1017,18 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
{
|
||||
var fraction = [],
|
||||
point = [self convertPoint:point fromView:nil];
|
||||
|
||||
|
||||
// convert to container coordinate
|
||||
point.x -= _textContainerOrigin.x;
|
||||
point.y -= _textContainerOrigin.y;
|
||||
|
||||
|
||||
var index = [_layoutManager glyphIndexForPoint:point inTextContainer:_textContainer fractionOfDistanceThroughGlyph:fraction];
|
||||
|
||||
|
||||
if (index === CPNotFound)
|
||||
index = [_layoutManager numberOfCharacters];
|
||||
else if (fraction[0] > 0.5)
|
||||
index++;
|
||||
|
||||
|
||||
return index;
|
||||
}
|
||||
- (CGPoint)_characterIndexFromEvent:(CPEvent)event
|
||||
@@ -1012,9 +1051,9 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
[_CPNativeInputManager cancelCurrentInputSessionIfNeeded];
|
||||
[_caret setVisibility:NO];
|
||||
|
||||
|
||||
_startTrackingLocation = [self _characterIndexFromEvent:event];
|
||||
|
||||
|
||||
var granularities = [CPNotFound, CPSelectByCharacter, CPSelectByWord, CPSelectByParagraph];
|
||||
[self setSelectionGranularity:granularities[[event clickCount]]];
|
||||
|
||||
@@ -1027,20 +1066,20 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
placeholderFrame = CGRectIntersection([_layoutManager boundingRectForGlyphRange:placeholderRange inTextContainer:_textContainer], _frame),
|
||||
rangeToHide = CPMakeRange(0, _selectionRange.location - lineBeginningIndex),
|
||||
dragPlaceholder;
|
||||
|
||||
|
||||
// hide the left part of the first line of the selection that is not included
|
||||
[placeholderString addAttribute:CPForegroundColorAttributeName
|
||||
value:[CPColor colorWithRed:1 green:1 blue:1 alpha:0]
|
||||
range:rangeToHide];
|
||||
|
||||
|
||||
_movingSelection = CPMakeRange(_startTrackingLocation, 0);
|
||||
|
||||
|
||||
dragPlaceholder = [[CPTextView alloc] initWithFrame:placeholderFrame];
|
||||
[dragPlaceholder._textStorage replaceCharactersInRange:CPMakeRange(0, 0) withAttributedString:placeholderString];
|
||||
|
||||
[dragPlaceholder setBackgroundColor:[CPColor colorWithRed:1 green:1 blue:1 alpha:0]];
|
||||
[dragPlaceholder setAlphaValue:0.5];
|
||||
|
||||
|
||||
var stringForPasting = [_textStorage attributedSubstringFromRange:CPMakeRangeCopy(_selectionRange)],
|
||||
richData = [_CPRTFProducer produceRTF:stringForPasting documentAttributes:@{}],
|
||||
draggingPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];
|
||||
@@ -1055,12 +1094,12 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
pasteboard:draggingPasteboard
|
||||
source:self
|
||||
slideBack:YES];
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var setRange = CPMakeRange(_startTrackingLocation, 0);
|
||||
|
||||
|
||||
if ([event modifierFlags] & CPShiftKeyMask)
|
||||
setRange = _MakeRangeFromAbs(_startTrackingLocation < _MidRange(_selectionRange) ? CPMaxRange(_selectionRange) : _selectionRange.location, _startTrackingLocation);
|
||||
else
|
||||
@@ -1081,7 +1120,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
if (_movingSelection)
|
||||
return;
|
||||
|
||||
|
||||
var oldRange = [self selectedRange],
|
||||
index = [self _characterIndexFromEvent:event];
|
||||
|
||||
@@ -1531,7 +1570,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
- (void)_deleteForRange:(CPRange)changedRange
|
||||
{
|
||||
if (![self shouldChangeTextInRange:changedRange replacementString:@""])
|
||||
if (![self _didBeginEditing] || ![self shouldChangeTextInRange:changedRange replacementString:@""])
|
||||
return;
|
||||
|
||||
changedRange = CPIntersectionRange(CPMakeRange(0, [_layoutManager numberOfCharacters]), changedRange);
|
||||
@@ -1655,7 +1694,6 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTextViewDidChangeTypingAttributesNotification
|
||||
object:self];
|
||||
|
||||
}
|
||||
|
||||
- (CPDictionary)_attributesForFontPanel
|
||||
@@ -1798,7 +1836,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
|
||||
- (void)underline:(id)sender
|
||||
{
|
||||
if (![self shouldChangeTextInRange:_selectionRange replacementString:nil])
|
||||
if (![self _didBeginEditing] || ![self shouldChangeTextInRange:_selectionRange replacementString:nil])
|
||||
return;
|
||||
|
||||
if (!CPEmptyRange(_selectionRange))
|
||||
@@ -2099,7 +2137,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
{
|
||||
var point = [info draggingLocation],
|
||||
location = [self _characterIndexFromRawPoint:CGPointCreateCopy(point)];
|
||||
|
||||
|
||||
_movingSelection = CPMakeRange(location, 0);
|
||||
[_caret _drawCaretAtLocation:_movingSelection.location];
|
||||
[_caret setVisibility:YES];
|
||||
@@ -2112,11 +2150,11 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
{
|
||||
var location = [self convertPoint:[aSender draggingLocation] fromView:nil],
|
||||
pasteboard = [aSender draggingPasteboard];
|
||||
|
||||
|
||||
if ([pasteboard availableTypeFromArray:[CPRTFPboardType, CPStringPboardType]])
|
||||
{
|
||||
[_caret setVisibility:NO];
|
||||
|
||||
|
||||
if (CPLocationInRange(_movingSelection.location, _selectionRange))
|
||||
{
|
||||
[self setSelectedRange:_movingSelection];
|
||||
@@ -2141,7 +2179,7 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
[self insertText:dataForPasting];
|
||||
}, 0);
|
||||
}
|
||||
|
||||
|
||||
if ([pasteboard availableTypeFromArray:[CPColorDragType]])
|
||||
[self setTextColor:[CPKeyedUnarchiver unarchiveObjectWithData:[pasteboard dataForType:CPColorDragType]] range:_selectionRange];
|
||||
}
|
||||
@@ -2215,6 +2253,14 @@ var kDelegateRespondsTo_textShouldBeginEditing
|
||||
return [_delegate textShouldBeginEditing:self];
|
||||
}
|
||||
|
||||
- (BOOL)_sendDelegateTextShouldEndEditing
|
||||
{
|
||||
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textShouldEndEditing))
|
||||
return YES;
|
||||
|
||||
return [_delegate textShouldEndEditing:self];
|
||||
}
|
||||
|
||||
- (BOOL)_sendDelegateShouldChangeTextInRange:(CPRange)aRange replacementString:(CPString)aString
|
||||
{
|
||||
if (!(_delegateRespondsToSelectorMask & kDelegateRespondsTo_textView_shouldChangeTextInRange_replacementString))
|
||||
@@ -2458,7 +2504,7 @@ var CPTextViewAllowsUndoKey = @"CPTextViewAllowsUndoKey",
|
||||
_caretTimer = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)_drawCaretAtLocation:(int)aLoc
|
||||
{
|
||||
var rect = [_textView._layoutManager boundingRectForGlyphRange:CPMakeRange(aLoc, 1) inTextContainer:_textView._textContainer];
|
||||
@@ -2791,6 +2837,3 @@ var _CPCopyPlaceholder = '-';
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user