Permalink
Browse files

text renderer : it is now possible to use the keyboard up/down arrows…

… to navigate in multiline text
  • Loading branch information...
michaelvillar committed Mar 11, 2012
1 parent 1669fe3 commit 9b90041ad3635b4a9486fbd080f3d62791570da4
@@ -30,5 +30,7 @@ extern CGSize AB_CTFrameGetSize(CTFrameRef frame, BOOL shouldAddOneLine);
extern CGFloat AB_CTFrameGetHeight(CTFrameRef frame);
extern CFIndex AB_CTFrameGetStringIndexForPosition(CTFrameRef frame, CGPoint p);
+extern void AB_CTFrameGetIndexForPositionInLine(NSString *string, CTFrameRef frame, CFIndex lineIndex, float xPosition, CFIndex *index);
+extern void AB_CTFrameGetLinePositionOfIndex(NSString *string, CTFrameRef frame, int index, CFIndex *lineIndex, float *xPosition);
extern void AB_CTFrameGetRectsForRange(NSString *string, CTFrameRef frame, CFRange range, CGRect rects[], CFIndex *rectCount);
extern void AB_CTFrameGetRectsForRangeWithAggregationType(NSString *string, CTFrameRef frame, CFRange range, AB_CTLineRectAggregationType aggregationType, CGRect rects[], CFIndex *rectCount);
@@ -142,6 +142,42 @@ static inline BOOL RangeContainsIndex(CFRange range, CFIndex index)
return (a && b);
}
+void AB_CTFrameGetIndexForPositionInLine(NSString *string, CTFrameRef frame, CFIndex lineIndex, float xPosition, CFIndex *index)
+{
+ NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
+ CFIndex linesCount = [lines count];
+ if(lineIndex < linesCount)
+ {
+ CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:lineIndex];
+ *index = CTLineGetStringIndexForPosition(line, CGPointMake(xPosition, 0));
+ }
+ else
+ *index = 0;
+}
+
+void AB_CTFrameGetLinePositionOfIndex(NSString *string, CTFrameRef frame, int index, CFIndex *lineIndex, float *xPosition)
+{
+ NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
+ CFIndex linesCount = [lines count];
+ CFIndex charCount = 0;
+ CFIndex count = 0;
+
+ for(CFIndex i = 0; i < linesCount; ++i) {
+ CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:i];
+ count = CTLineGetGlyphCount(line);
+ if((index >= charCount && index < charCount + count) || i == linesCount - 1)
+ {
+ CGFloat offset = CTLineGetOffsetForStringIndex(line, index, NULL);
+ *lineIndex = i;
+ *xPosition = offset;
+ return;
+ }
+ charCount += count;
+ }
+ *lineIndex = -1;
+ *xPosition = 0;
+}
+
void AB_CTFrameGetRectsForRange(NSString *string, CTFrameRef frame, CFRange range, CGRect rects[], CFIndex *rectCount)
{
AB_CTFrameGetRectsForRangeWithAggregationType(string, frame, range, AB_CTLineRectAggregationTypeInline, rects, rectCount);
@@ -194,6 +194,7 @@ text with distinguishing appearance (i.e. NSTextView renders with -markedTextAtt
*/
- (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection replacementRange:(NSRange)replacementRange
{
+ NSLog(@"set selected range : %@",NSStringFromRange(newSelection));
NSRange selectedRange = [self selectedRange];
if(replacementRange.location == NSNotFound) {
@@ -17,6 +17,13 @@
#import "TUITextRenderer.h"
#import "TUITextEditor.h"
#import "TUIView.h"
+#import "CoreText+Additions.h"
+
+@interface TUITextRenderer ()
+
+- (CTFrameRef)ctFrame;
+
+@end
@interface NSString (ABTokenizerAdditions)
@end
@@ -73,6 +80,69 @@ - (TUITextEditor *)_textEditor
return nil;
}
+- (int)_indexByMovingIndex:(int)index
+ by:(int)incr
+{
+ CFIndex lineIndex;
+ float xPosition;
+ AB_CTFrameGetLinePositionOfIndex(TEXT, [self ctFrame], index, &lineIndex, &xPosition);
+ if(lineIndex >= 0)
+ {
+ NSArray *lines = (__bridge NSArray *)CTFrameGetLines([self ctFrame]);
+ CFIndex linesCount = [lines count];
+ if(incr < 0 && lineIndex == 0)
+ {
+ return 0;
+ }
+ else if(lineIndex + incr >= linesCount)
+ {
+ return (int)[TEXT length];
+ }
+ else if(lineIndex + incr >= 0) {
+ CFIndex index;
+ AB_CTFrameGetIndexForPositionInLine(TEXT, [self ctFrame], lineIndex + incr, xPosition, &index);
+ return (int)index;
+ }
+ }
+ return -1;
+}
+
+- (void)moveUp:(id)sender
+{
+ NSInteger selectionLength = abs((int)(_selectionStart - _selectionEnd));
+ if(selectionLength)
+ _selectionStart = _selectionEnd = (MIN(_selectionEnd,_selectionStart));
+ else
+ _selectionEnd = _selectionStart = [self _indexByMovingIndex:(int)MIN(_selectionStart,_selectionEnd)
+ by:-1];
+ [self.view setNeedsDisplay];
+}
+
+- (void)moveUpAndModifySelection:(id)sender
+{
+ _selectionEnd = [self _indexByMovingIndex:(int)MIN(_selectionStart,_selectionEnd)
+ by:-1];
+ [self.view setNeedsDisplay];
+}
+
+- (void)moveDown:(id)sender
+{
+ NSInteger selectionLength = abs((int)(_selectionStart - _selectionEnd));
+ if(selectionLength)
+ _selectionStart = _selectionEnd = (MAX(_selectionEnd,_selectionStart));
+ else
+ _selectionEnd = _selectionStart = [self _indexByMovingIndex:(int)MAX(_selectionStart,_selectionEnd)
+ by:1];
+ [self.view setNeedsDisplay];
+}
+
+- (void)moveDownAndModifySelection:(id)sender
+{
+ _selectionEnd = [self _indexByMovingIndex:(int)MAX(_selectionStart,_selectionEnd)
+ by:1];
+ [self.view setNeedsDisplay];
+}
+
- (void)moveRight:(id)sender
{
NSInteger selectionLength = abs((int)(_selectionStart - _selectionEnd));

0 comments on commit 9b90041

Please sign in to comment.