- Fixed every Styling issue (at least the ones exposed by StyledEdit). Setting fonts works now

- Cleaned up PageUp/Down handling code
- Now setups undo in Clear()
- Alignment now partially works
- Fixed some visual artifacts which could've showed up during typing with an input method
- Added a "known bugs" section


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9096 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2004-09-29 07:18:10 +00:00
parent 9ade9e873d
commit 70751f7bfc
2 changed files with 126 additions and 100 deletions
+6 -6
View File
@@ -104,7 +104,7 @@ _BStyleRecordBuffer_::InsertRecord(const BFont *inFont,
// look for style in buffer // look for style in buffer
if (MatchRecord(inFont, inColor, &index)) if (MatchRecord(inFont, inColor, &index))
return (index); return index;
// style not found, add it // style not found, add it
font_height fh; font_height fh;
@@ -157,9 +157,7 @@ _BStyleRecordBuffer_::MatchRecord(const BFont *inFont,
const rgb_color *inColor, int32 *outIndex) const rgb_color *inColor, int32 *outIndex)
{ {
for (int32 i = 0; i < fItemCount; i++) { for (int32 i = 0; i < fItemCount; i++) {
if ( (inFont->Size() == fBuffer[i].style.font.Size()) && if ( (*inFont == fBuffer[i].style.font) &&
(inFont->Shear() == fBuffer[i].style.font.Shear()) &&
(inFont->Face() == fBuffer[i].style.font.Face()) &&
(inColor->red == fBuffer[i].style.color.red) && (inColor->red == fBuffer[i].style.color.red) &&
(inColor->green == fBuffer[i].style.color.green) && (inColor->green == fBuffer[i].style.color.green) &&
(inColor->blue == fBuffer[i].style.color.blue) && (inColor->blue == fBuffer[i].style.color.blue) &&
@@ -289,8 +287,7 @@ _BStyleBuffer_::SetStyleRange(int32 fromOffset, int32 toOffset,
fStyleRunDesc.InsertDesc(&newDesc, runIndex + 1); fStyleRunDesc.InsertDesc(&newDesc, runIndex + 1);
fStyleRecord.CommitRecord(newDesc.index); fStyleRecord.CommitRecord(newDesc.index);
runIndex++; runIndex++;
} } else {
else {
fStyleRunDesc[runIndex]->index = styleIndex; fStyleRunDesc[runIndex]->index = styleIndex;
fStyleRecord.CommitRecord(styleIndex); fStyleRecord.CommitRecord(styleIndex);
} }
@@ -348,6 +345,9 @@ _BStyleBuffer_::GetStyleRange(int32 startOffset, int32 endOffset) const
result = (STEStyleRangePtr)malloc(sizeof(int32) + result = (STEStyleRangePtr)malloc(sizeof(int32) +
(sizeof(STEStyleRun) * numStyles)); (sizeof(STEStyleRun) * numStyles));
if (!result)
return NULL;
result->count = numStyles; result->count = numStyles;
STEStyleRunPtr run = &result->runs[0]; STEStyleRunPtr run = &result->runs[0];
for (int32 index = 0; index < numStyles; index++) { for (int32 index = 0; index < numStyles; index++) {
+107 -81
View File
@@ -26,7 +26,7 @@
// Description: BTextView displays and manages styled text. // Description: BTextView displays and manages styled text.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// TODO: // TODOs:
// - Finish documenting this class // - Finish documenting this class
// - Consider using BObjectList instead of BList // - Consider using BObjectList instead of BList
// for disallowed charachters (it would remove a lot of reinterpret_casts) // for disallowed charachters (it would remove a lot of reinterpret_casts)
@@ -34,6 +34,12 @@
// - Check for correctness and possible optimizations the calls to Refresh(), // - Check for correctness and possible optimizations the calls to Refresh(),
// to refresh only changed parts of text (currently we often redraw the whole text) // to refresh only changed parts of text (currently we often redraw the whole text)
// Known Bugs:
// - PointAt(), OffsetAt(), and possibly some other functions don't work right yet
// when alignment is different than B_ALIGN_LEFT.
// - visual artifacts appears when you highlight some text which spans between
// multiple lines and with mixed sizes/styles (could be something in GetTextRegion())
// Standard Includes ----------------------------------------------------------- // Standard Includes -----------------------------------------------------------
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
@@ -1093,7 +1099,6 @@ BTextView::SetText(BFile *inFile, int32 inOffset, int32 inLength,
fStyles->BumpOffset(inLength, fStyles->OffsetToRun(inOffset - 1) + 1); fStyles->BumpOffset(inLength, fStyles->OffsetToRun(inOffset - 1) + 1);
if (inRuns != NULL) if (inRuns != NULL)
//SetStyleRange(inOffset, inOffset + inLength, inStyles, false);
SetRunArray(inOffset, inOffset + inLength, inRuns); SetRunArray(inOffset, inOffset + inLength, inRuns);
else { else {
// apply nullStyle to inserted text // apply nullStyle to inserted text
@@ -1186,37 +1191,7 @@ void
BTextView::Delete() BTextView::Delete()
{ {
CALLED(); CALLED();
Delete(fSelStart, fSelEnd);
CancelInputMethod();
// anything to delete?
if (fSelStart == fSelEnd)
return;
// hide the caret/unhilite the selection
if (fActive) {
if (fSelStart != fSelEnd)
Highlight(fSelStart, fSelEnd);
else {
if (fCaretVisible)
InvertCaret();
}
}
// remove data from buffer
DeleteText(fSelStart, fSelEnd);
// collapse the selection
fClickOffset = fSelEnd = fSelStart;
// recalc line breaks and draw what's left
Refresh(fSelStart, fSelEnd, true, true);
// draw the caret
if (fActive) {
if (!fCaretVisible)
InvertCaret();
}
} }
@@ -1446,6 +1421,9 @@ void
BTextView::Clear() BTextView::Clear()
{ {
CALLED(); CALLED();
delete fUndo;
fUndo = new _BClearUndoBuffer_(this);
Delete(); Delete();
} }
@@ -1491,6 +1469,8 @@ BTextView::Select(int32 startOffset, int32 endOffset)
if (!fSelectable) if (!fSelectable)
return; return;
CancelInputMethod();
// a negative selection? // a negative selection?
if (startOffset > endOffset) if (startOffset > endOffset)
return; return;
@@ -1802,6 +1782,10 @@ BTextView::LineAt(BPoint point) const
BPoint BPoint
BTextView::PointAt(int32 inOffset, float *outHeight) const BTextView::PointAt(int32 inOffset, float *outHeight) const
{ {
// TODO: when alignment is != than B_ALIGN_LEFT,
// this function's still a bit broken.
// Cleanup.
CALLED(); CALLED();
BPoint result; BPoint result;
int32 textLength = fText->Length(); int32 textLength = fText->Length();
@@ -1810,6 +1794,7 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
float height = 0; float height = 0;
result.x = 0.0; result.x = 0.0;
result.y = line->origin + fTextRect.top; result.y = line->origin + fTextRect.top;
// Handle the case where there is only one line // Handle the case where there is only one line
@@ -1843,7 +1828,9 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
do { do {
foundTab = fText->FindChar(B_TAB, offset, &numChars); foundTab = fText->FindChar(B_TAB, offset, &numChars);
result.x += StyledWidth(offset, numChars); float width = StyledWidth(offset, numChars);
result.x += width;
if (foundTab) { if (foundTab) {
result.x += ActualTabWidth(result.x); result.x += ActualTabWidth(result.x);
@@ -1857,6 +1844,13 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
} }
} }
if (fAlignment != B_ALIGN_LEFT) {
float modifier = fTextRect.right - StyledWidth(line->offset,
(line + 1)->offset - line->offset);
if (fAlignment == B_ALIGN_CENTER)
modifier /= 2;
result.x += modifier;
}
// convert from text rect coordinates // convert from text rect coordinates
result.x += fTextRect.left - 1.0; result.x += fTextRect.left - 1.0;
@@ -1877,6 +1871,9 @@ BTextView::PointAt(int32 inOffset, float *outHeight) const
int32 int32
BTextView::OffsetAt(BPoint point) const BTextView::OffsetAt(BPoint point) const
{ {
// TODO: When alignment is different than B_ALIGN_LEFT,
// this function is still broken.
CALLED(); CALLED();
// should we even bother? // should we even bother?
if (point.y >= fTextRect.bottom) if (point.y >= fTextRect.bottom)
@@ -1898,7 +1895,7 @@ BTextView::OffsetAt(BPoint point) const
// convert to text rect coordinates // convert to text rect coordinates
point.x -= fTextRect.left; point.x -= fTextRect.left;
point.x = (point.x < 0.0) ? 0.0 : point.x; point.x = max_c(point.x, 0.0);
// do a pseudo-binary search of the character widths on the line // do a pseudo-binary search of the character widths on the line
// that PixelToLine() gave us // that PixelToLine() gave us
@@ -2118,6 +2115,9 @@ BTextView::GetTextRegion(int32 startOffset, int32 endOffset,
BPoint startPt = PointAt(startOffset, &startLineHeight); BPoint startPt = PointAt(startOffset, &startLineHeight);
BPoint endPt = PointAt(endOffset, &endLineHeight); BPoint endPt = PointAt(endOffset, &endLineHeight);
startLineHeight = ceil(startLineHeight);
endLineHeight = ceil(endLineHeight);
BRect selRect; BRect selRect;
if (startPt.y == endPt.y) { if (startPt.y == endPt.y) {
@@ -2127,7 +2127,6 @@ BTextView::GetTextRegion(int32 startOffset, int32 endOffset,
selRect.right = endPt.x - 1.0; selRect.right = endPt.x - 1.0;
selRect.bottom = endPt.y + endLineHeight - 1.0; selRect.bottom = endPt.y + endLineHeight - 1.0;
outRegion->Include(selRect); outRegion->Include(selRect);
} else { } else {
// more than one line in the specified offset range // more than one line in the specified offset range
selRect.left = max_c(startPt.x, fTextRect.left); selRect.left = max_c(startPt.x, fTextRect.left);
@@ -2139,7 +2138,7 @@ BTextView::GetTextRegion(int32 startOffset, int32 endOffset,
if (startPt.y + startLineHeight < endPt.y) { if (startPt.y + startLineHeight < endPt.y) {
// more than two lines in the range // more than two lines in the range
selRect.left = fTextRect.left; selRect.left = fTextRect.left;
selRect.top = startPt.y + startLineHeight + 1.0; selRect.top = startPt.y + startLineHeight;
selRect.right = fTextRect.right; selRect.right = fTextRect.right;
selRect.bottom = endPt.y - 1.0; selRect.bottom = endPt.y - 1.0;
outRegion->Include(selRect); outRegion->Include(selRect);
@@ -2353,8 +2352,6 @@ BTextView::SetWordWrap(bool wrap)
if (wrap == fWrap) if (wrap == fWrap)
return; return;
fWrap = wrap;
if (Window() != NULL) { if (Window() != NULL) {
if (fActive) { if (fActive) {
// hide the caret, unhilite the selection // hide the caret, unhilite the selection
@@ -2366,6 +2363,7 @@ BTextView::SetWordWrap(bool wrap)
} }
} }
fWrap = wrap;
Refresh(0, fText->Length(), true, true); Refresh(0, fText->Length(), true, true);
if (fActive) { if (fActive) {
@@ -2447,7 +2445,10 @@ BTextView::SetAlignment(alignment flag)
CALLED(); CALLED();
// Do a reality check // Do a reality check
if (fAlignment != flag && flag >= 0 && flag <= 2) { if (fAlignment != flag &&
(flag == B_ALIGN_LEFT ||
flag == B_ALIGN_RIGHT ||
flag == B_ALIGN_CENTER)) {
fAlignment = flag; fAlignment = flag;
// After setting new alignment, update the view/window // After setting new alignment, update the view/window
@@ -3067,18 +3068,23 @@ BTextView::HandlePageKey(uint32 inPageKey)
STELinePtr line = NULL; STELinePtr line = NULL;
int32 start = fSelStart, end = fSelEnd;
switch (inPageKey) { switch (inPageKey) {
case B_HOME: case B_HOME:
line = (*fLines)[CurrentLine()]; line = (*fLines)[CurrentLine()];
fClickOffset = line->offset; fClickOffset = line->offset;
ScrollToOffset(fClickOffset);
if (shiftDown) { if (shiftDown) {
if (fClickOffset <= fSelStart) if (fClickOffset <= fSelStart) {
Select(fClickOffset, fSelEnd); start = fClickOffset;
else end = fSelEnd;
Select(fSelStart, fClickOffset); } else {
start = fSelStart;
end = fClickOffset;
}
} else } else
Select(fClickOffset, fClickOffset); start = end = fClickOffset;
break; break;
case B_END: case B_END:
@@ -3089,63 +3095,74 @@ BTextView::HandlePageKey(uint32 inPageKey)
line = (*fLines)[CurrentLine() + 1]; line = (*fLines)[CurrentLine() + 1];
fClickOffset = PreviousInitialByte(line->offset); fClickOffset = PreviousInitialByte(line->offset);
} else { } else {
fClickOffset = fText->Length(); // This check if needed to avoid moving the cursor
if (ByteAt(fClickOffset - 1) == B_ENTER) // when the cursor is on the last line, and that line
fClickOffset--; // is empty
if (fClickOffset != fText->Length()) {
fClickOffset = fText->Length();
if (ByteAt(fClickOffset - 1) == B_ENTER)
fClickOffset--;
}
} }
ScrollToOffset(fClickOffset);
if (shiftDown) { if (shiftDown) {
if (fClickOffset >= fSelEnd) if (fClickOffset >= fSelEnd) {
Select(fSelStart, fClickOffset); start = fSelStart;
else end = fClickOffset;
Select(fClickOffset, fSelEnd); } else {
start = fClickOffset;
end = fSelEnd;
}
} else } else
Select(fClickOffset, fClickOffset); start = end = fClickOffset;
break; break;
// TODO: Clean up this mess
case B_PAGE_UP: case B_PAGE_UP:
{ {
int32 currentOffset = OffsetAt(fClickOffset); BPoint currentPos = PointAt(fClickOffset);
float delta = Bounds().Height();
if (ScrollBar(B_VERTICAL) != NULL) currentPos.y -= Bounds().Height();
ScrollBar(B_VERTICAL)->SetValue(ScrollBar(B_VERTICAL)->Value() - delta); fClickOffset = OffsetAt(LineAt(currentPos));
fClickOffset = OffsetAt(LineAt(PointAt(currentOffset - delta)));
if (shiftDown) { if (shiftDown) {
if (fClickOffset <= fSelStart) if (fClickOffset <= fSelStart) {
Select(fClickOffset, fSelEnd); start = fClickOffset;
else end = fSelEnd;
Select(fSelStart, fClickOffset); } else {
start = fSelStart;
end = fClickOffset;
}
} else } else
Select(fClickOffset, fClickOffset); start = end = fClickOffset;
break; break;
} }
case B_PAGE_DOWN: case B_PAGE_DOWN:
{ {
int32 currentOffset = OffsetAt(fClickOffset); BPoint currentPos = PointAt(fClickOffset);
float delta = Bounds().Height();
if (ScrollBar(B_VERTICAL) != NULL) currentPos.y += Bounds().Height();
ScrollBar(B_VERTICAL)->SetValue(ScrollBar(B_VERTICAL)->Value() + delta); fClickOffset = OffsetAt(LineAt(currentPos) + 1);
fClickOffset = OffsetAt(LineAt(PointAt(currentOffset + delta)) + 1);
if (shiftDown) { if (shiftDown) {
if (fClickOffset >= fSelEnd) if (fClickOffset >= fSelEnd) {
Select(fSelStart, fClickOffset); start = fSelStart;
else end = fClickOffset;
Select(fClickOffset, fSelEnd); } else {
start = fClickOffset;
end = fSelEnd;
}
} else } else
Select(fClickOffset, fClickOffset); start = end = fClickOffset;
break; break;
} }
} }
ScrollToOffset(fClickOffset);
Select(start, end);
} }
@@ -3647,14 +3664,21 @@ BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset,
eraseRect = clipRect; eraseRect = clipRect;
} }
float startLeft = fTextRect.left;
for (long i = startLine; i <= endLine; i++) { for (long i = startLine; i <= endLine; i++) {
long length = (line + 1)->offset - line->offset; long length = (line + 1)->offset - line->offset;
// DrawString() chokes if you draw a newline // DrawString() chokes if you draw a newline
if ((*fText)[(line + 1)->offset - 1] == '\n') if ((*fText)[(line + 1)->offset - 1] == '\n')
length--; length--;
MovePenTo(fTextRect.left, line->origin + line->ascent + fTextRect.top); if (fAlignment != B_ALIGN_LEFT) {
// B_ALIGN_RIGHT
startLeft = (fTextRect.right - StyledWidth(line->offset, length));
if (fAlignment == B_ALIGN_CENTER)
startLeft /= 2;
}
MovePenTo(startLeft, line->origin + line->ascent + fTextRect.top);
if (erase && i >= startEraseLine) { if (erase && i >= startEraseLine) {
eraseRect.top = line->origin + fTextRect.top; eraseRect.top = line->origin + fTextRect.top;
@@ -3761,7 +3785,7 @@ BTextView::DrawCaret(int32 offset)
//STELinePtr line = (*fLines)[lineNum]; //STELinePtr line = (*fLines)[lineNum];
float lineHeight; float lineHeight;
BPoint caretPoint = PointAt(offset, &lineHeight); BPoint caretPoint = PointAt(offset, &lineHeight);
caretPoint.x = (caretPoint.x > fTextRect.right) ? fTextRect.right : caretPoint.x; caretPoint.x = min_c(caretPoint.x, fTextRect.right);
BRect caretRect; BRect caretRect;
caretRect.left = caretRect.right = caretPoint.x; caretRect.left = caretRect.right = caretPoint.x;
@@ -4417,6 +4441,8 @@ BTextView::CancelInputMethod()
delete fInline; delete fInline;
fInline = NULL; fInline = NULL;
Refresh(0, fText->Length(), true, false);
} }