HaikuDepot: Work-in-progress on a TextDocument class.
* This is mostly still targeted at the use-case of parsing some mark up text and building a static representation of the styled document which can be layouted and rendered. * Lots of TODOs and almost nothing is tested.
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "TextDocument.h"
|
||||
|
||||
|
||||
TextDocument::TextDocument()
|
||||
:
|
||||
fParagraphs(),
|
||||
fEmptyLastParagraph(),
|
||||
fDefaultTextStyle()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TextDocument::TextDocument(const TextStyle& textStyle,
|
||||
const ParagraphStyle& paragraphStyle)
|
||||
:
|
||||
fParagraphs(),
|
||||
fEmptyLastParagraph(paragraphStyle),
|
||||
fDefaultTextStyle(textStyle)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TextDocument::TextDocument(const TextDocument& other)
|
||||
:
|
||||
fParagraphs(other.fParagraphs),
|
||||
fEmptyLastParagraph(other.fEmptyLastParagraph),
|
||||
fDefaultTextStyle(other.fDefaultTextStyle)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TextDocument&
|
||||
TextDocument::operator=(const TextDocument& other)
|
||||
{
|
||||
fParagraphs = other.fParagraphs;
|
||||
fEmptyLastParagraph = other.fEmptyLastParagraph;
|
||||
fDefaultTextStyle = other.fDefaultTextStyle;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TextDocument::operator==(const TextDocument& other) const
|
||||
{
|
||||
if (this == &other)
|
||||
return true;
|
||||
|
||||
return fEmptyLastParagraph == other.fEmptyLastParagraph
|
||||
&& fDefaultTextStyle == other.fDefaultTextStyle
|
||||
&& fParagraphs == other.fParagraphs;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TextDocument::operator!=(const TextDocument& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
TextDocument::Insert(int32 offset, const BString& text)
|
||||
{
|
||||
return Insert(offset, text, TextStyleAt(offset));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TextDocument::Insert(int32 offset, const BString& text, const TextStyle& style)
|
||||
{
|
||||
return Insert(offset, text, style, ParagraphStyleAt(offset));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TextDocument::Insert(int32 offset, const BString& text,
|
||||
const TextStyle& textStyle, const ParagraphStyle& paragraphStyle)
|
||||
{
|
||||
return Replace(offset, 0, text, textStyle, paragraphStyle);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
TextDocument::Remove(int32 offset, int32 length)
|
||||
{
|
||||
// TODO: Implement
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
TextDocument::Replace(int32 offset, int32 length, const BString& text)
|
||||
{
|
||||
return Replace(offset, length, text, TextStyleAt(offset));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TextDocument::Replace(int32 offset, int32 length, const BString& text,
|
||||
const TextStyle& style)
|
||||
{
|
||||
return Replace(offset, length, text, style, ParagraphStyleAt(offset));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TextDocument::Replace(int32 offset, int32 length, const BString& text,
|
||||
const TextStyle& textStyle, const ParagraphStyle& paragraphStyle)
|
||||
{
|
||||
// TODO: Implement
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
const TextStyle&
|
||||
TextDocument::TextStyleAt(int32 textOffset) const
|
||||
{
|
||||
int32 paragraphOffset;
|
||||
const Paragraph& paragraph = ParagraphAt(textOffset, paragraphOffset);
|
||||
|
||||
textOffset -= paragraphOffset;
|
||||
const TextSpanList& spans = paragraph.TextSpans();
|
||||
|
||||
int32 index = 0;
|
||||
while (index < spans.CountItems()) {
|
||||
const TextSpan& span = spans.ItemAtFast(index);
|
||||
if (textOffset - span.CharCount() < 0)
|
||||
return span.Style();
|
||||
textOffset -= span.CharCount();
|
||||
}
|
||||
|
||||
// TODO: Document should have a default TextStyle?
|
||||
return fDefaultTextStyle;
|
||||
}
|
||||
|
||||
|
||||
const ParagraphStyle&
|
||||
TextDocument::ParagraphStyleAt(int32 textOffset) const
|
||||
{
|
||||
int32 paragraphOffset;
|
||||
return ParagraphAt(textOffset, paragraphOffset).Style();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
const Paragraph&
|
||||
TextDocument::ParagraphAt(int32 textOffset, int32& paragraphOffset) const
|
||||
{
|
||||
int32 textLength = 0;
|
||||
paragraphOffset = 0;
|
||||
int32 count = fParagraphs.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
const Paragraph& paragraph = fParagraphs.ItemAtFast(i);
|
||||
paragraphOffset = textLength;
|
||||
if (textLength + paragraph.Length() > textOffset)
|
||||
return paragraph;
|
||||
}
|
||||
return fEmptyLastParagraph;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TextDocument::Append(const Paragraph& paragraph)
|
||||
{
|
||||
return fParagraphs.Add(paragraph);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TEXT_DOCUMENT_H
|
||||
#define TEXT_DOCUMENT_H
|
||||
|
||||
#include "List.h"
|
||||
#include "Paragraph.h"
|
||||
|
||||
|
||||
typedef List<Paragraph, false> ParagraphList;
|
||||
|
||||
|
||||
class TextDocument {
|
||||
public:
|
||||
TextDocument();
|
||||
TextDocument(const TextStyle& textStyle,
|
||||
const ParagraphStyle& paragraphStyle);
|
||||
TextDocument(const TextDocument& other);
|
||||
|
||||
TextDocument& operator=(const TextDocument& other);
|
||||
bool operator==(const TextDocument& other) const;
|
||||
bool operator!=(const TextDocument& other) const;
|
||||
|
||||
// Text insertion and removing
|
||||
status_t Insert(int32 offset, const BString& text);
|
||||
status_t Insert(int32 offset, const BString& text,
|
||||
const TextStyle& style);
|
||||
status_t Insert(int32 offset, const BString& text,
|
||||
const TextStyle& textStyle,
|
||||
const ParagraphStyle& paragraphStyle);
|
||||
|
||||
status_t Remove(int32 offset, int32 length);
|
||||
|
||||
status_t Replace(int32 offset, int32 length,
|
||||
const BString& text);
|
||||
status_t Replace(int32 offset, int32 length,
|
||||
const BString& text,
|
||||
const TextStyle& style);
|
||||
status_t Replace(int32 offset, int32 length,
|
||||
const BString& text,
|
||||
const TextStyle& textStyle,
|
||||
const ParagraphStyle& paragraphStyle);
|
||||
|
||||
// Style access
|
||||
const TextStyle& TextStyleAt(int32 textOffset) const;
|
||||
const ParagraphStyle& ParagraphStyleAt(int32 textOffset) const;
|
||||
|
||||
// Paragraph access
|
||||
const ParagraphList& Paragraphs() const
|
||||
{ return fParagraphs; }
|
||||
|
||||
const Paragraph& ParagraphAt(int32 textOffset,
|
||||
int32& paragraphOffset) const;
|
||||
|
||||
bool Append(const Paragraph& paragraph);
|
||||
|
||||
private:
|
||||
ParagraphList fParagraphs;
|
||||
Paragraph fEmptyLastParagraph;
|
||||
TextStyle fDefaultTextStyle;
|
||||
};
|
||||
|
||||
|
||||
#endif // TEXT_DOCUMENT_H
|
||||
Reference in New Issue
Block a user