more work concerning navigation within BTextView:
* pressing HOME on last line works again * made public versions of LineAt() do what is required to pass back the correct value even for the last line of the buffer (original implementation has been moved to private _LineAt()) * PAGE_UP/PAGE_DOWN now moves the view by the bounds-height, making the behaviour somewhat less confusing (IMHO, please shout if that's not acceptable for you) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30458 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2002f6f626
commit
588b46eacd
|
@ -510,8 +510,8 @@ void
|
|||
BTextView::Draw(BRect updateRect)
|
||||
{
|
||||
// what lines need to be drawn?
|
||||
int32 startLine = LineAt(BPoint(0.0, updateRect.top));
|
||||
int32 endLine = LineAt(BPoint(0.0, updateRect.bottom));
|
||||
int32 startLine = _LineAt(BPoint(0.0, updateRect.top));
|
||||
int32 endLine = _LineAt(BPoint(0.0, updateRect.bottom));
|
||||
|
||||
_DrawLines(startLine, endLine);
|
||||
}
|
||||
|
@ -1157,7 +1157,7 @@ BTextView::SetText(BFile *inFile, int32 inOffset, int32 inLength,
|
|||
fText->InsertText(inFile, inOffset, inLength, 0);
|
||||
|
||||
// update the start offsets of each line below offset
|
||||
fLines->BumpOffset(inLength, LineAt(inOffset) + 1);
|
||||
fLines->BumpOffset(inLength, _LineAt(inOffset) + 1);
|
||||
|
||||
// update the style runs
|
||||
fStyles->BumpOffset(inLength, fStyles->OffsetToRun(inOffset - 1) + 1);
|
||||
|
@ -1630,7 +1630,7 @@ BTextView::SetFontAndColor(int32 startOffset, int32 endOffset,
|
|||
_Refresh(startOffset, endOffset, startOffset != endOffset, false);
|
||||
} else {
|
||||
// the line breaks wont change, simply redraw
|
||||
_RequestDrawLines(LineAt(startOffset), LineAt(endOffset), startOffset,
|
||||
_RequestDrawLines(_LineAt(startOffset), _LineAt(endOffset), startOffset,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
@ -1724,7 +1724,10 @@ BTextView::RunArray(int32 startOffset, int32 endOffset, int32 *outSize) const
|
|||
int32
|
||||
BTextView::LineAt(int32 offset) const
|
||||
{
|
||||
return fLines->OffsetToLine(offset);
|
||||
int32 lineNum = _LineAt(offset);
|
||||
if (_IsOnEmptyLastLine(offset))
|
||||
lineNum++;
|
||||
return lineNum;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1735,7 +1738,10 @@ BTextView::LineAt(int32 offset) const
|
|||
int32
|
||||
BTextView::LineAt(BPoint point) const
|
||||
{
|
||||
return fLines->PixelToLine(point.y - fTextRect.top);
|
||||
int32 lineNum = _LineAt(point);
|
||||
if ((*fLines)[lineNum + 1]->origin <= point.y - fTextRect.top)
|
||||
lineNum++;
|
||||
return lineNum;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1749,7 +1755,7 @@ BPoint
|
|||
BTextView::PointAt(int32 inOffset, float *outHeight) const
|
||||
{
|
||||
// TODO: Cleanup.
|
||||
int32 lineNum = LineAt(inOffset);
|
||||
int32 lineNum = _LineAt(inOffset);
|
||||
STELine* line = (*fLines)[lineNum];
|
||||
float height = 0;
|
||||
|
||||
|
@ -1757,9 +1763,9 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
|
|||
result.x = 0.0;
|
||||
result.y = line->origin + fTextRect.top;
|
||||
|
||||
// Handle the case where we are on the last (always empty) line
|
||||
// Handle the case where there is only one line (no text inserted)
|
||||
// TODO: See if we can do this better
|
||||
if (fStyles->NumRuns() == 0 || lineNum == fLines->NumLines()) {
|
||||
if (fStyles->NumRuns() == 0) {
|
||||
const rgb_color *color = NULL;
|
||||
const BFont *font = NULL;
|
||||
fStyles->GetNullStyle(&font, &color);
|
||||
|
@ -1767,16 +1773,13 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
|
|||
font_height fontHeight;
|
||||
font->GetHeight(&fontHeight);
|
||||
height = fontHeight.ascent + fontHeight.descent;
|
||||
|
||||
} else {
|
||||
height = (line + 1)->origin - line->origin;
|
||||
|
||||
// special case: go down one line if inOffset is a newline
|
||||
if (inOffset == TextLength() && inOffset > 0
|
||||
&& fText->RealCharAt(inOffset - 1) == B_ENTER) {
|
||||
if (_IsOnEmptyLastLine(inOffset)) {
|
||||
// special case: go down one line if inOffset is the newline
|
||||
// at the end of the buffer
|
||||
result.y += height;
|
||||
height = LineHeight(CountLines() - 1);
|
||||
|
||||
} else {
|
||||
int32 offset = line->offset;
|
||||
int32 length = inOffset - line->offset;
|
||||
|
@ -1831,26 +1834,16 @@ BTextView::OffsetAt(BPoint point) const
|
|||
const int32 textLength = fText->Length();
|
||||
|
||||
// should we even bother?
|
||||
if (point.y >= fTextRect.bottom && point.x >= fTextRect.right)
|
||||
if (point.y >= fTextRect.bottom)
|
||||
return textLength;
|
||||
else if (point.y < fTextRect.top && point.x <= fTextRect.left)
|
||||
else if (point.y < fTextRect.top)
|
||||
return 0;
|
||||
|
||||
#define COMPILE_PROBABLY_BAD_CODE 1
|
||||
|
||||
#if COMPILE_PROBABLY_BAD_CODE
|
||||
// NOTE: I have not been able to test what happens if all this is removed.
|
||||
// For one-line text views (BTextControl), it works just fine. But I would
|
||||
// need to check StyledEdit or something in various situations (new lines
|
||||
// at end and other stuff)...
|
||||
// special case one line text views
|
||||
if (CountLines() <= 1)
|
||||
point.y = fTextRect.top;
|
||||
#endif
|
||||
|
||||
int32 lineNum = LineAt(point);
|
||||
int32 lineNum = _LineAt(point);
|
||||
STELine* line = (*fLines)[lineNum];
|
||||
|
||||
#define COMPILE_PROBABLY_BAD_CODE 1
|
||||
|
||||
#if COMPILE_PROBABLY_BAD_CODE
|
||||
// special case: if point is within the text rect and PixelToLine()
|
||||
// tells us that it's on the last line, but if point is actually
|
||||
|
@ -2999,7 +2992,7 @@ BTextView::InsertText(const char *inText, int32 inLength, int32 inOffset,
|
|||
fText->InsertText(inText, inLength, inOffset);
|
||||
|
||||
// update the start offsets of each line below offset
|
||||
fLines->BumpOffset(inLength, LineAt(inOffset) + 1);
|
||||
fLines->BumpOffset(inLength, _LineAt(inOffset) + 1);
|
||||
|
||||
// update the style runs
|
||||
fStyles->BumpOffset(inLength, fStyles->OffsetToRun(inOffset - 1) + 1);
|
||||
|
@ -3415,11 +3408,13 @@ BTextView::_HandlePageKey(uint32 inPageKey)
|
|||
int32 lastClickOffset = fClickOffset;
|
||||
switch (inPageKey) {
|
||||
case B_HOME:
|
||||
line = (*fLines)[LineAt(lastClickOffset)];
|
||||
if (ctrlDown)
|
||||
fClickOffset = 0;
|
||||
else
|
||||
else {
|
||||
// get the start of the last line if caret is on it
|
||||
line = (*fLines)[_LineAt(lastClickOffset)];
|
||||
fClickOffset = line->offset;
|
||||
}
|
||||
|
||||
if (!shiftDown)
|
||||
selStart = selEnd = fClickOffset;
|
||||
|
@ -3446,7 +3441,7 @@ BTextView::_HandlePageKey(uint32 inPageKey)
|
|||
// If we are on the last line, just go to the last
|
||||
// character in the buffer, otherwise get the starting
|
||||
// offset of the next line, and go to the previous character
|
||||
int32 currentLine = LineAt(lastClickOffset);
|
||||
int32 currentLine = _LineAt(lastClickOffset);
|
||||
if (currentLine + 1 < fLines->NumLines()) {
|
||||
line = (*fLines)[currentLine + 1];
|
||||
fClickOffset = _PreviousInitialByte(line->offset);
|
||||
|
@ -3486,6 +3481,7 @@ BTextView::_HandlePageKey(uint32 inPageKey)
|
|||
|
||||
currentPos.y -= Bounds().Height();
|
||||
fClickOffset = OffsetAt(LineAt(currentPos));
|
||||
ScrollBy(0, -1 * Bounds().Height());
|
||||
|
||||
if (!shiftDown)
|
||||
selStart = selEnd = fClickOffset;
|
||||
|
@ -3502,6 +3498,7 @@ BTextView::_HandlePageKey(uint32 inPageKey)
|
|||
selEnd = fClickOffset;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3511,6 +3508,7 @@ BTextView::_HandlePageKey(uint32 inPageKey)
|
|||
|
||||
currentPos.y += Bounds().Height();
|
||||
fClickOffset = OffsetAt(LineAt(currentPos));
|
||||
ScrollBy(0, Bounds().Height());
|
||||
|
||||
if (!shiftDown)
|
||||
selStart = selEnd = fClickOffset;
|
||||
|
@ -3568,7 +3566,7 @@ BTextView::_HandleAlphaKey(const char *bytes, int32 numBytes)
|
|||
|
||||
if (fAutoindent && numBytes == 1 && *bytes == B_ENTER) {
|
||||
int32 start, offset;
|
||||
start = offset = OffsetAt(LineAt(fSelStart));
|
||||
start = offset = OffsetAt(_LineAt(fSelStart));
|
||||
|
||||
while (ByteAt(offset) != '\0' &&
|
||||
(ByteAt(offset) == B_TAB || ByteAt(offset) == B_SPACE))
|
||||
|
@ -3601,8 +3599,8 @@ BTextView::_Refresh(int32 fromOffset, int32 toOffset, bool erase, bool scroll)
|
|||
{
|
||||
// TODO: Cleanup
|
||||
float saveHeight = fTextRect.Height();
|
||||
int32 fromLine = LineAt(fromOffset);
|
||||
int32 toLine = LineAt(toOffset);
|
||||
int32 fromLine = _LineAt(fromOffset);
|
||||
int32 toLine = _LineAt(toOffset);
|
||||
int32 saveFromLine = fromLine;
|
||||
int32 saveToLine = toLine;
|
||||
float saveLineHeight = LineHeight(fromLine);
|
||||
|
@ -3626,14 +3624,14 @@ BTextView::_Refresh(int32 fromOffset, int32 toOffset, bool erase, bool scroll)
|
|||
if (newHeight != saveHeight) {
|
||||
// the text area has changed
|
||||
if (newHeight < saveHeight)
|
||||
toLine = LineAt(BPoint(0.0f, saveHeight + fTextRect.top));
|
||||
toLine = _LineAt(BPoint(0.0f, saveHeight + fTextRect.top));
|
||||
else
|
||||
toLine = LineAt(BPoint(0.0f, newHeight + fTextRect.top));
|
||||
toLine = _LineAt(BPoint(0.0f, newHeight + fTextRect.top));
|
||||
}
|
||||
|
||||
// draw only those lines that are visible
|
||||
int32 fromVisible = LineAt(BPoint(0.0f, bounds.top));
|
||||
int32 toVisible = LineAt(BPoint(0.0f, bounds.bottom));
|
||||
int32 fromVisible = _LineAt(BPoint(0.0f, bounds.top));
|
||||
int32 toVisible = _LineAt(BPoint(0.0f, bounds.bottom));
|
||||
fromLine = max_c(fromVisible, fromLine);
|
||||
toLine = min_c(toLine, toVisible);
|
||||
|
||||
|
@ -3932,6 +3930,9 @@ BTextView::_FindLineBreak(int32 fromOffset, float *outAscent, float *outDescent,
|
|||
int32
|
||||
BTextView::_PreviousWordBoundary(int32 offset)
|
||||
{
|
||||
if (offset <= 0)
|
||||
return 0;
|
||||
|
||||
uint32 charType = _CharClassification(offset);
|
||||
int32 previous;
|
||||
while (offset > 0) {
|
||||
|
@ -3948,8 +3949,11 @@ BTextView::_PreviousWordBoundary(int32 offset)
|
|||
int32
|
||||
BTextView::_NextWordBoundary(int32 offset)
|
||||
{
|
||||
uint32 charType = _CharClassification(offset);
|
||||
int32 textLen = TextLength();
|
||||
if (offset >= textLen)
|
||||
return textLen;
|
||||
|
||||
uint32 charType = _CharClassification(offset);
|
||||
while (offset < textLen) {
|
||||
offset = _NextInitialByte(offset);
|
||||
if (_CharClassification(offset) != charType)
|
||||
|
@ -4449,18 +4453,18 @@ BTextView::_PerformMouseMoved(BPoint where, uint32 code)
|
|||
// triple click, extend selection linewise
|
||||
if (currentOffset <= fTrackingMouse->anchor) {
|
||||
fTrackingMouse->selStart
|
||||
= (*fLines)[LineAt(currentOffset)]->offset;
|
||||
= (*fLines)[_LineAt(currentOffset)]->offset;
|
||||
fTrackingMouse->selEnd
|
||||
= fTrackingMouse->shiftDown
|
||||
? fSelEnd
|
||||
: (*fLines)[LineAt(fTrackingMouse->anchor) + 1]->offset;
|
||||
: (*fLines)[_LineAt(fTrackingMouse->anchor) + 1]->offset;
|
||||
} else {
|
||||
fTrackingMouse->selStart
|
||||
= fTrackingMouse->shiftDown
|
||||
? fSelStart
|
||||
: (*fLines)[LineAt(fTrackingMouse->anchor)]->offset;
|
||||
: (*fLines)[_LineAt(fTrackingMouse->anchor)]->offset;
|
||||
fTrackingMouse->selEnd
|
||||
= (*fLines)[LineAt(currentOffset) + 1]->offset;
|
||||
= (*fLines)[_LineAt(currentOffset) + 1]->offset;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -4664,10 +4668,10 @@ BTextView::_PerformAutoScrolling()
|
|||
float lineHeight = 0;
|
||||
float vertDiff = 0;
|
||||
if (fWhere.y > bounds.bottom) {
|
||||
lineHeight = LineHeight(LineAt(bounds.LeftBottom()));
|
||||
lineHeight = LineHeight(_LineAt(bounds.LeftBottom()));
|
||||
vertDiff = fWhere.y - bounds.bottom;
|
||||
} else if (fWhere.y < bounds.top) {
|
||||
lineHeight = LineHeight(LineAt(bounds.LeftTop()));
|
||||
lineHeight = LineHeight(_LineAt(bounds.LeftTop()));
|
||||
vertDiff = fWhere.y - bounds.top; // negative value
|
||||
}
|
||||
// Always scroll vertically line by line or by multiples of that
|
||||
|
@ -5230,6 +5234,44 @@ BTextView::_CancelInputMethod()
|
|||
}
|
||||
|
||||
|
||||
/*! \brief Returns the line number for the character at the given offset.
|
||||
N.B.: this will never return the last line (use LineAt() if you
|
||||
need to be correct about that)
|
||||
\param offset The offset of the wanted character.
|
||||
\return A line number.
|
||||
*/
|
||||
int32
|
||||
BTextView::_LineAt(int32 offset) const
|
||||
{
|
||||
return fLines->OffsetToLine(offset);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Returns the line number for the given point.
|
||||
N.B.: this will never return the last line (use LineAt() if you
|
||||
need to be correct about that)
|
||||
\param point A point.
|
||||
\return A line number.
|
||||
*/
|
||||
int32
|
||||
BTextView::_LineAt(const BPoint& point) const
|
||||
{
|
||||
return fLines->PixelToLine(point.y - fTextRect.top);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Determines if the given offset is on the empty line at the end of
|
||||
the buffer.
|
||||
\param offset The offset that shall be checked.
|
||||
*/
|
||||
bool
|
||||
BTextView::_IsOnEmptyLastLine(int32 offset) const
|
||||
{
|
||||
return (offset == TextLength() && offset > 0
|
||||
&& fText->RealCharAt(offset - 1) == B_ENTER);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BTextView::TextTrackState
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue