Text stuff: Support extracting sub-paragraphs and documents

* Also some WIP towards integrating TextListener.
 * Everything untested.
 * Fixed a bug where copying to the clipboard had an extra line-break
   after each paragraph since the recent changes that made sure each
   paragraph ends in a line-break.
This commit is contained in:
Stephan Aßmus
2014-01-27 23:21:02 +01:00
parent fef8b2637d
commit be2f98062c
5 changed files with 160 additions and 21 deletions
+31 -10
View File
@@ -261,12 +261,36 @@ Paragraph::IsEmpty() const
BString
Paragraph::GetText(int32 start, int32 length) const
Paragraph::Text() const
{
BString result;
int32 count = fTextSpans.CountItems();
for (int32 i = 0; i < count; i++)
result << fTextSpans.ItemAtFast(i).Text();
return result;
}
BString
Paragraph::Text(int32 start, int32 length) const
{
Paragraph subParagraph = SubParagraph(start, length);
return subParagraph.Text();
}
Paragraph
Paragraph::SubParagraph(int32 start, int32 length) const
{
if (start < 0)
start = 0;
BString text;
if (start == 0 && length == Length())
return *this;
Paragraph result(fStyle);
int32 count = fTextSpans.CountItems();
for (int32 i = 0; i < count; i++) {
@@ -284,13 +308,10 @@ Paragraph::GetText(int32 start, int32 length) const
spanLength -= start;
int32 copyLength = std::min(spanLength, length);
if (start == 0 && length == spanLength) {
text << span.Text();
} else {
BString subString;
span.Text().CopyCharsInto(subString, start, copyLength);
text << subString;
}
if (start == 0 && length == spanLength)
result.Append(span);
else
result.Append(span.SubSpan(start, copyLength));
length -= copyLength;
if (length == 0)
@@ -300,7 +321,7 @@ Paragraph::GetText(int32 start, int32 length) const
start = 0;
}
return text;
return result;
}
+3 -1
View File
@@ -39,7 +39,9 @@ public:
int32 Length() const;
bool IsEmpty() const;
BString GetText(int32 start, int32 length) const;
BString Text() const;
BString Text(int32 start, int32 length) const;
Paragraph SubParagraph(int32 start, int32 length) const;
void PrintToStream() const;
+103 -4
View File
@@ -394,7 +394,14 @@ TextDocument::Length() const
BString
TextDocument::GetText(int32 start, int32 length) const
TextDocument::Text() const
{
return Text(0, Length());
}
BString
TextDocument::Text(int32 start, int32 length) const
{
if (start < 0)
start = 0;
@@ -417,13 +424,11 @@ TextDocument::GetText(int32 start, int32 length) const
paragraphLength -= start;
int32 copyLength = std::min(paragraphLength, length);
text << paragraph.GetText(start, copyLength);
text << paragraph.Text(start, copyLength);
length -= copyLength;
if (length == 0)
break;
else if (i < count - 1)
text << '\n';
// Next paragraph is copied from its beginning
start = 0;
@@ -433,6 +438,48 @@ TextDocument::GetText(int32 start, int32 length) const
}
TextDocumentRef
TextDocument::SubDocument(int32 start, int32 length) const
{
TextDocumentRef result(new(std::nothrow) TextDocument(
fDefaultCharacterStyle, fEmptyLastParagraph.Style()), true);
if (result.Get() == NULL)
return result;
if (start < 0)
start = 0;
int32 count = fParagraphs.CountItems();
for (int32 i = 0; i < count; i++) {
const Paragraph& paragraph = fParagraphs.ItemAtFast(i);
int32 paragraphLength = paragraph.Length();
if (paragraphLength == 0)
continue;
if (start > paragraphLength) {
// Skip paragraph if its before start
start -= paragraphLength;
continue;
}
// Remaining paragraph length after start
paragraphLength -= start;
int32 copyLength = std::min(paragraphLength, length);
result->Append(paragraph.SubParagraph(start, copyLength));
length -= copyLength;
if (length == 0)
break;
// Next paragraph is copied from its beginning
start = 0;
}
return result;
}
// #pragma mark -
@@ -450,3 +497,55 @@ TextDocument::PrintToStream() const
}
printf("</document>\n");
}
// #pragma mark -
bool
TextDocument::AddListener(const TextListenerRef& listener)
{
return fTextListeners.Add(listener);
}
bool
TextDocument::RemoveListener(const TextListenerRef& listener)
{
return fTextListeners.Remove(listener);
}
void
TextDocument::_NotifyTextChanging(TextChangingEvent& event) const
{
// Copy listener list to have a stable list in case listeners
// are added/removed from within the notification hook.
TextListenerList listeners(fTextListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
const TextListenerRef& listener = listeners.ItemAtFast(i);
if (listener.Get() == NULL)
continue;
listener->TextChanging(event);
if (event.IsCanceled())
break;
}
}
void
TextDocument::_NotifyTextChanged(const TextChangedEvent& event) const
{
// Copy listener list to have a stable list in case listeners
// are added/removed from within the notification hook.
TextListenerList listeners(fTextListeners);
int32 count = listeners.CountItems();
for (int32 i = 0; i < count; i++) {
const TextListenerRef& listener = listeners.ItemAtFast(i);
if (listener.Get() == NULL)
continue;
listener->TextChanged(event);
}
}
+22 -5
View File
@@ -10,9 +10,14 @@
#include "CharacterStyle.h"
#include "List.h"
#include "Paragraph.h"
#include "TextListener.h"
typedef List<Paragraph, false> ParagraphList;
typedef List<Paragraph, false> ParagraphList;
typedef List<TextListenerRef, false> TextListenerList;
class TextDocument;
typedef BReference<TextDocument> TextDocumentRef;
class TextDocument : public BReferenceable {
@@ -68,18 +73,30 @@ public:
// Query information
int32 Length() const;
BString GetText(int32 textOffset, int32 length) const;
BString Text() const;
BString Text(int32 textOffset, int32 length) const;
TextDocumentRef SubDocument(int32 textOffset,
int32 length) const;
void PrintToStream() const;
// Listener support
bool AddListener(const TextListenerRef& listener);
bool RemoveListener(const TextListenerRef& listener);
private:
void _NotifyTextChanging(
TextChangingEvent& event) const;
void _NotifyTextChanged(
const TextChangedEvent& event) const;
private:
ParagraphList fParagraphs;
Paragraph fEmptyLastParagraph;
CharacterStyle fDefaultCharacterStyle;
TextListenerList fTextListeners;
};
typedef BReference<TextDocument> TextDocumentRef;
#endif // TEXT_DOCUMENT_H
@@ -370,7 +370,7 @@ TextDocumentView::Copy(BClipboard* clipboard)
int32 end;
GetSelection(start, end);
BString text = fTextDocument->GetText(start, end - start);
BString text = fTextDocument->Text(start, end - start);
clip->AddData("text/plain", B_MIME_TYPE, text.String(),
text.Length());