From 25df172b722bb7e9c703dcdc31370499255f88c6 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Thu, 4 Jan 2007 10:44:29 +0000 Subject: [PATCH] Implemented auto horizontal scrolling (by fixed steps for now), moved auto scrolling to its own method, introduced a new private StyledWidthUTF8Safe method. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19694 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/interface/TextView.h | 8 ++- src/kits/interface/TextView.cpp | 97 ++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 38 deletions(-) diff --git a/headers/os/interface/TextView.h b/headers/os/interface/TextView.h index 020bc52d6f..50caf69b5a 100644 --- a/headers/os/interface/TextView.h +++ b/headers/os/interface/TextView.h @@ -311,6 +311,11 @@ virtual void _ReservedTextView12(); int32 length, float *outAscent = NULL, float *outDescent = NULL) const; + float StyledWidthUTF8Safe(int32 fromOffset, + int32 numChars, + float *outAscent = NULL, + float *outDescent = NULL) const; + float ActualTabWidth(float location) const; void DoInsertText(const char *inText, @@ -343,7 +348,8 @@ virtual void _ReservedTextView12(); bool MessageDropped(BMessage *inMessage, BPoint where, BPoint offset); - + + void PerformAutoScrolling(); void UpdateScrollbars(); void AutoResize(bool doredraw=true); diff --git a/src/kits/interface/TextView.cpp b/src/kits/interface/TextView.cpp index 3e57e48bb8..fa264a1cf8 100644 --- a/src/kits/interface/TextView.cpp +++ b/src/kits/interface/TextView.cpp @@ -911,35 +911,8 @@ BTextView::MessageReceived(BMessage *message) delete fClickRunner; fClickRunner = NULL; } - } else { - // Scroll the view a bit if mouse is outside the view bounds - - BRect bounds = Bounds(); - - // TODO: Horizontal scrolling - /*if (fWhere.x > bounds.right) - scrollBy.x = fWhere.x - bounds.right; - else if (fWhere.x < bounds.left) - scrollBy.x = fWhere.x - bounds.left; - */ - float lineHeight = 0; - float diff = 0; - if (fWhere.y > bounds.bottom) { - lineHeight = LineHeight(LineAt(bounds.LeftBottom())); - diff = fWhere.y - bounds.bottom; - } else if (fWhere.y < bounds.top) { - lineHeight = LineHeight(LineAt(bounds.LeftTop())); - diff = fWhere.y - bounds.top; // negative value - } - - // Always scroll vertically by multiples of line height, - // based on the distance of the cursor from the border of the view - // TODO: Refine this, I can't even remember how beos works here - BPoint scrollBy; - scrollBy.y = lineHeight > 0 ? lineHeight * (int32)(floorf(diff) / lineHeight) : 0; - if (scrollBy != B_ORIGIN) - ScrollBy(scrollBy.x, scrollBy.y); - } + } else + PerformAutoScrolling(); break; } @@ -1690,7 +1663,7 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const // special case: go down one line if inOffset is a newline if (inOffset == textLength && (*fText)[inOffset - 1] == B_ENTER) { float ascent, descent; - StyledWidth(inOffset, 1, &ascent, &descent); + StyledWidthUTF8Safe(inOffset, 1, &ascent, &descent); result.y += height; height = ascent + descent; @@ -1698,23 +1671,23 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const } else { int32 offset = line->offset; int32 length = inOffset - line->offset; - int32 numChars = length; + int32 numBytes = length; bool foundTab = false; do { - foundTab = fText->FindChar(B_TAB, offset, &numChars); + foundTab = fText->FindChar(B_TAB, offset, &numBytes); - float width = StyledWidth(offset, numChars); + float width = StyledWidth(offset, numBytes); result.x += width; if (foundTab) { result.x += ActualTabWidth(result.x); - numChars++; + numBytes++; } - offset += numChars; - length -= numChars; - numChars = length; + offset += numBytes; + length -= numBytes; + numBytes = length; } while (foundTab && length > 0); } } @@ -3497,6 +3470,21 @@ BTextView::StyledWidth(int32 fromOffset, int32 length, float *outAscent, } +// Unlike the StyledWidth method, this one takes as parameter +// the number of chars, not the number of bytes. +float +BTextView::StyledWidthUTF8Safe(int32 fromOffset, int32 numChars, + float *outAscent, float *outDescent) const +{ + int32 toOffset = fromOffset; + while (numChars--) + toOffset = NextInitialByte(toOffset); + + const int32 length = toOffset - fromOffset; + return StyledWidth(fromOffset, length, outAscent, outDescent); +} + + /*! \brief Calculate the actual tab width for the given location. \param location The location to calculate the tab width of. \return The actual tab width for the given location @@ -4007,6 +3995,41 @@ BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset) } +void +BTextView::PerformAutoScrolling() +{ + // Scroll the view a bit if mouse is outside the view bounds + BRect bounds = Bounds(); + BPoint scrollBy; + + // TODO: refine horizontal scrolling, for example by + // scrolling char by char and not using fixed values + if (fWhere.x > bounds.right) { + scrollBy.x = floorf((fWhere.x - bounds.right) / 10); + } else if (fWhere.x < bounds.left) { + scrollBy.x = floorf((fWhere.x - bounds.left) / 10); // negative value + } + + float lineHeight = 0; + float vertDiff = 0; + if (fWhere.y > bounds.bottom) { + lineHeight = LineHeight(LineAt(bounds.LeftBottom())); + vertDiff = fWhere.y - bounds.bottom; + } else if (fWhere.y < bounds.top) { + lineHeight = LineHeight(LineAt(bounds.LeftTop())); + vertDiff = fWhere.y - bounds.top; // negative value + } + + // Always scroll vertically line by line or by multiples of that + // based on the distance of the cursor from the border of the view + // TODO: Refine this, I can't even remember how beos works here + scrollBy.y = lineHeight > 0 ? lineHeight * (int32)(floorf(vertDiff) / lineHeight) : 0; + + if (scrollBy != B_ORIGIN) + ScrollBy(scrollBy.x, scrollBy.y); +} + + /*! \brief Updates the scrollbars associated with the object (if any). */ void