Text stuff: Bugfixes in Insert and Remove methods

Still not well tested. Also some way to trigger the layouts to adopt to
the changed document paragraphs. Not yet via the new TextListener.
This commit is contained in:
Stephan Aßmus 2014-01-19 16:33:36 +01:00
parent 315dee6f22
commit 2c906df217
5 changed files with 54 additions and 9 deletions

View File

@ -92,6 +92,7 @@ Paragraph::Insert(int32 offset, const TextSpan& newSpan)
if (offset - span.CharCount() < 0)
break;
offset -= span.CharCount();
index++;
}
if (fTextSpans.CountItems() == index)
@ -139,25 +140,28 @@ Paragraph::Remove(int32 offset, int32 length)
if (offset - span.CharCount() < 0)
break;
offset -= span.CharCount();
index++;
}
if (index >= fTextSpans.CountItems())
return false;
TextSpan span = fTextSpans.ItemAtFast(index).SubSpan(0, offset);
TextSpan span(fTextSpans.ItemAtFast(index));
int32 removeLength = std::min(span.CharCount() - offset, length);
span.Remove(offset, removeLength);
fTextSpans.Replace(index, span);
length -= removeLength;
index += 1;
if (index >= fTextSpans.CountItems())
return true;
while (length > 0) {
// Remove more spans if necessary
while (length > 0 && index < fTextSpans.CountItems()) {
int32 spanLength = fTextSpans.ItemAtFast(index).CharCount();
if (spanLength <= length) {
fTextSpans.Remove(index);
length -= spanLength;
} else {
// Reached last span
int32 removeLength = std::min(length, spanLength);
removeLength = std::min(length, spanLength);
TextSpan lastSpan = fTextSpans.ItemAtFast(index).SubSpan(
removeLength, spanLength - removeLength);
// Try to merge with first span, otherwise replace span at index
@ -172,6 +176,10 @@ Paragraph::Remove(int32 offset, int32 length)
}
}
// See if anything from the TextSpan at offset remained
if (span.CharCount() == 0)
fTextSpans.Remove(index - 1);
return true;
}

View File

@ -125,7 +125,7 @@ TextDocument::Remove(int32 textOffset, int32 length)
textOffset = 0;
while (length > 0) {
while (length > 0 && index + 1 < fParagraphs.CountItems()) {
const Paragraph& paragraph = ParagraphAt(index + 1);
paragraphLength = paragraph.Length();
// Remove paragraph in any case. If some of it remains, the last
@ -238,10 +238,10 @@ TextDocument::ParagraphIndexFor(int32 textOffset, int32& paragraphOffset) const
int32 count = fParagraphs.CountItems();
for (int32 i = 0; i < count; i++) {
const Paragraph& paragraph = fParagraphs.ItemAtFast(i);
paragraphOffset = textOffset - textLength;
int32 paragraphLength = paragraph.Length();
if (textLength + paragraphLength > textOffset)
return i;
paragraphOffset += paragraphLength;
textLength += paragraphLength;
}
return -1;

View File

@ -61,6 +61,34 @@ TextDocumentLayout::SetTextDocument(const TextDocumentRef& document)
}
void
TextDocumentLayout::Invalidate()
{
InvalidateParagraphs(0, fParagraphLayouts.CountItems());
}
void
TextDocumentLayout::InvalidateParagraphs(int32 start, int32 count)
{
if (start < 0 || fDocument.Get() == NULL)
return;
const ParagraphList& paragraphs = fDocument->Paragraphs();
while (count > 0) {
if (start >= fParagraphLayouts.CountItems())
break;
const Paragraph& paragraph = paragraphs.ItemAtFast(start);
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(start);
info.layout->SetParagraph(paragraph);
start++;
}
}
void
TextDocumentLayout::SetWidth(float width)
{

View File

@ -78,6 +78,9 @@ public:
void SetTextDocument(
const TextDocumentRef& document);
void Invalidate();
void InvalidateParagraphs(int32 start, int32 count);
void SetWidth(float width);
float Width() const
{ return fWidth; }

View File

@ -243,6 +243,9 @@ TextEditor::Insert(int32 offset, const BString& string)
if (!fEditingEnabled || fDocument.Get() == NULL)
return B_ERROR;
// TODO: Via listener, and only affected paragraphs
fLayout->Invalidate();
return fDocument->Insert(offset, string, fStyleAtCaret);
}
@ -253,6 +256,9 @@ TextEditor::Remove(int32 offset, int32 length)
if (!fEditingEnabled || fDocument.Get() == NULL)
return B_ERROR;
// TODO: Via listener, and only affected paragraphs
fLayout->Invalidate();
return fDocument->Remove(offset, length);
}