Skip to content

Instantly share code, notes, and snippets.

@danielpunkass
Forked from anonymous/gist:219916
Created October 27, 2009 21:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielpunkass/219994 to your computer and use it in GitHub Desktop.
Save danielpunkass/219994 to your computer and use it in GitHub Desktop.
//
// TextView.m
// TextDidChange
//
// Created by Timothy J. Wood on 10/27/09.
// Copyright 2009 The Omni Group. All rights reserved.
//
/*
A button hooked up to -insertFoo: yields:
2009-10-27 13:22:37.971 TextDidChange[1897:a0b] insert range:{0, 0}
2009-10-27 13:22:37.974 TextDidChange[1897:a0b] in processEditing editedMask:2 editedRange:{0, 3} changeInLength:3
2009-10-27 13:22:37.975 TextDidChange[1897:a0b] in didChangeText: rangeForUserTextChange = {3, 0}
2009-10-27 13:22:37.975 TextDidChange[1897:a0b] in didChangeText: editedMask:0 editedRange:{9223372036854775807, 3} changeInLength:0
copying & pasting that "foo" right after yields:
2009-10-27 13:22:40.132 TextDidChange[1897:a0b] in processEditing editedMask:3 editedRange:{3, 3} changeInLength:3
2009-10-27 13:22:40.134 TextDidChange[1897:a0b] in didChangeText: rangeForUserTextChange = {6, 0}
2009-10-27 13:22:40.134 TextDidChange[1897:a0b] in didChangeText: editedMask:0 editedRange:{9223372036854775807, 3} changeInLength:0
then, selecting and deleting the first foo:
2009-10-27 13:22:42.243 TextDidChange[1897:a0b] in processEditing editedMask:2 editedRange:{0, 0} changeInLength:-3
2009-10-27 13:22:42.244 TextDidChange[1897:a0b] in didChangeText: rangeForUserTextChange = {0, 0}
2009-10-27 13:22:42.245 TextDidChange[1897:a0b] in didChangeText: editedMask:0 editedRange:{9223372036854775807, 0} changeInLength:0
*/
#import "TextView.h"
@interface TextStorage : NSTextStorage
{
NSMutableAttributedString *_contents;
}
@end
@implementation TextStorage
// NSTextStorage is abstract; minimal concrete subclass
- init;
{
if (!(self = [super init]))
return nil;
_contents = [[NSMutableAttributedString alloc] initWithString:@"" attributes:nil];
return self;
}
- (void)dealloc;
{
[_contents release];
[super dealloc];
}
#pragma mark -
#pragma NSAttributedString subclass
- (NSUInteger)length;
{
return [_contents length];
}
- (NSString *)string;
{
return [_contents string];
}
- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range;
{
return [_contents attributesAtIndex:location effectiveRange:range];
}
#pragma mark -
#pragma NSMutableAttributedString subclass
- (void)beginEditing;
{
[super beginEditing];
[_contents beginEditing];
}
- (void)endEditing;
{
[_contents endEditing];
[super endEditing];
}
- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str;
{
[_contents replaceCharactersInRange:range withString:str];
[self edited:NSTextStorageEditedCharacters range:range changeInLength:[str length] - range.length];
}
- (void)replaceCharactersInRange:(NSRange)range withAttributedString:(NSAttributedString *)attributedString;
{
[_contents replaceCharactersInRange:range withAttributedString:attributedString];
[self edited:NSTextStorageEditedAttributes|NSTextStorageEditedCharacters range:range changeInLength:[attributedString length] - range.length];
}
- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range;
{
[_contents setAttributes:attrs range:range];
[self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
}
#pragma mark -
#pragma mark NSTextStorage subclass
- (void)processEditing;
{
NSLog(@"in processEditing editedMask:%ld editedRange:%@ changeInLength:%ld", [self editedMask], NSStringFromRange([self editedRange]), [self changeInLength]);
[super processEditing];
}
@end
@implementation TextView
- (void)awakeFromNib;
{
// Terrible
TextStorage *textStorage = [[TextStorage alloc] init];
[[self layoutManager] replaceTextStorage:textStorage];
[textStorage release];
}
- (void)didChangeText;
{
NSLog(@"in didChangeText: rangeForUserTextChange = %@", NSStringFromRange([self rangeForUserTextChange]));
NSTextStorage *textStorage = [self textStorage];
NSLog(@"in didChangeText: editedMask:%ld editedRange:%@ changeInLength:%ld", [textStorage editedMask], NSStringFromRange([textStorage editedRange]), [textStorage changeInLength]);
[super didChangeText];
}
- (IBAction)insertFoo:(id)sender;
{
// ... not bothering with multi-range for test ...
NSRange range = [self selectionRangeForProposedRange:[self selectedRange] granularity:[self selectionGranularity]];
NSLog(@"insert range:%@", NSStringFromRange(range));
if ([self shouldChangeTextInRange:range replacementString:@"foo"]) {
NSTextStorage *textStorage = [self textStorage];
[textStorage beginEditing];
[textStorage replaceCharactersInRange:range withString:@"foo"];
[textStorage endEditing];
[self didChangeText];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment