HaikuDepot: text stuff: Layout all document paragraphs.

* Use TextDocumentLayout in TextDocumentView.
 * Extend test case demonstrating paragraphs with
   different alignments, something unsupported in
   BTextView.
This commit is contained in:
Stephan Aßmus
2013-09-05 18:07:14 +02:00
parent 8e8d1b55d3
commit ccfedbc4fa
6 changed files with 282 additions and 9 deletions
+1
View File
@@ -20,6 +20,7 @@ local textDocumentSources =
ParagraphStyle.cpp
ParagraphStyleData.cpp
TextDocument.cpp
TextDocumentLayout.cpp
TextDocumentView.cpp
TextLayout.cpp
TextSpan.cpp
@@ -0,0 +1,155 @@
/*
* Copyright 2013, Stephan Aßmus <[email protected]>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "TextDocumentLayout.h"
#include <new>
#include <stdio.h>
#include <View.h>
TextDocumentLayout::TextDocumentLayout()
:
fWidth(0.0f),
fLayoutValid(false),
fDocument(),
fParagraphLayouts()
{
}
TextDocumentLayout::TextDocumentLayout(const TextDocumentRef& document)
:
fWidth(0.0f),
fLayoutValid(false),
fDocument(document),
fParagraphLayouts()
{
_Init();
}
TextDocumentLayout::TextDocumentLayout(const TextDocumentLayout& other)
:
fWidth(other.fWidth),
fLayoutValid(other.fLayoutValid),
fDocument(other.fDocument),
fParagraphLayouts(other.fParagraphLayouts)
{
}
TextDocumentLayout::~TextDocumentLayout()
{
}
void
TextDocumentLayout::SetTextDocument(const TextDocumentRef& document)
{
if (fDocument != document) {
fDocument = document;
_Init();
fLayoutValid = false;
}
}
void
TextDocumentLayout::SetWidth(float width)
{
if (fWidth != width) {
fWidth = width;
fLayoutValid = false;
}
}
float
TextDocumentLayout::Height()
{
_ValidateLayout();
float height = 0.0f;
if (fParagraphLayouts.CountItems() > 0) {
const ParagraphLayoutInfo& lastLayout = fParagraphLayouts.LastItem();
height = lastLayout.y + lastLayout.layout->Height();
}
return height;
}
void
TextDocumentLayout::Draw(BView* view, const BPoint& offset)
{
_ValidateLayout();
int layoutCount = fParagraphLayouts.CountItems();
for (int i = 0; i < layoutCount; i++) {
const ParagraphLayoutInfo& layout = fParagraphLayouts.ItemAtFast(i);
layout.layout->Draw(view, BPoint(offset.x, offset.y + layout.y));
}
}
// #pragma mark - private
void
TextDocumentLayout::_ValidateLayout()
{
if (!fLayoutValid) {
_Layout();
fLayoutValid = true;
}
}
void
TextDocumentLayout::_Init()
{
fParagraphLayouts.Clear();
const ParagraphList& paragraphs = fDocument->Paragraphs();
int paragraphCount = paragraphs.CountItems();
for (int i = 0; i < paragraphCount; i++) {
const Paragraph& paragraph = paragraphs.ItemAtFast(i);
ParagraphLayoutRef layout(new(std::nothrow) ParagraphLayout(paragraph),
true);
if (layout.Get() == NULL
|| !fParagraphLayouts.Add(ParagraphLayoutInfo(0.0f, layout))) {
fprintf(stderr, "TextDocumentLayout::_Layout() - out of memory\n");
return;
}
}
}
void
TextDocumentLayout::_Layout()
{
float y = 0.0f;
int layoutCount = fParagraphLayouts.CountItems();
for (int i = 0; i < layoutCount; i++) {
ParagraphLayoutInfo info = fParagraphLayouts.ItemAtFast(i);
const ParagraphStyle& style = info.layout->Style();
if (i > 0)
y += style.SpacingTop();
fParagraphLayouts.Replace(i, ParagraphLayoutInfo(y, info.layout));
info.layout->SetWidth(fWidth);
y += info.layout->Height() + style.SpacingBottom();
}
}
@@ -0,0 +1,107 @@
/*
* Copyright 2013, Stephan Aßmus <[email protected]>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef TEXT_DOCUMENT_LAYOUT_H
#define TEXT_DOCUMENT_LAYOUT_H
#include <Referenceable.h>
#include "List.h"
#include "TextDocument.h"
#include "ParagraphLayout.h"
class BView;
class ParagraphLayoutInfo {
public:
ParagraphLayoutInfo()
:
y(0.0f),
layout()
{
}
ParagraphLayoutInfo(float y, const ParagraphLayoutRef& layout)
:
y(y),
layout(layout)
{
}
ParagraphLayoutInfo(const ParagraphLayoutInfo& other)
:
y(other.y),
layout(other.layout)
{
}
ParagraphLayoutInfo& operator=(const ParagraphLayoutInfo& other)
{
y = other.y;
layout = other.layout;
return *this;
}
bool operator==(const ParagraphLayoutInfo& other) const
{
return y == other.y
&& layout == other.layout;
}
bool operator!=(const ParagraphLayoutInfo& other) const
{
return !(*this == other);
}
public:
float y;
ParagraphLayoutRef layout;
};
typedef List<ParagraphLayoutInfo, false> ParagraphLayoutList;
class TextDocumentLayout : public BReferenceable {
public:
TextDocumentLayout();
TextDocumentLayout(
const TextDocumentRef& document);
TextDocumentLayout(
const TextDocumentLayout& other);
virtual ~TextDocumentLayout();
void SetTextDocument(
const TextDocumentRef& document);
void SetWidth(float width);
float Width() const
{ return fWidth; }
float Height();
void Draw(BView* view, const BPoint& offset);
private:
void _Init();
void _ValidateLayout();
void _Layout();
void _DrawLayout(BView* view,
const ParagraphLayoutInfo& layout) const;
private:
float fWidth;
bool fLayoutValid;
TextDocumentRef fDocument;
ParagraphLayoutList fParagraphLayouts;
};
typedef BReference<TextDocumentLayout> TextDocumentLayoutRef;
#endif // TEXT_DOCUMENT_LAYOUT_H
@@ -50,14 +50,24 @@ TextDocumentTest::ReadyToRun()
bigStyle.SetFontSize(24);
bigStyle.SetForegroundColor(255, 50, 50);
TextDocumentRef document(new TextDocument(), true);
Paragraph paragraph(paragraphStyle);
paragraph.Append(TextSpan("This is a ", regularStyle));
paragraph.Append(TextSpan("test", bigStyle));
paragraph.Append(TextSpan(" to see if ", regularStyle));
paragraph.Append(TextSpan("different", boldStyle));
paragraph.Append(TextSpan(" character styles already work.", regularStyle));
document->Append(paragraph);
TextDocumentRef document(new TextDocument(), true);
paragraphStyle.SetSpacingTop(8.0f);
paragraphStyle.SetAlignment(ALIGN_CENTER);
paragraphStyle.SetJustify(false);
paragraph = Paragraph(paragraphStyle);
paragraph.Append(TextSpan("Different alignment styles ", regularStyle));
paragraph.Append(TextSpan("are", boldStyle));
paragraph.Append(TextSpan(" supported as of now!", regularStyle));
document->Append(paragraph);
documentView->SetTextDocument(document);
@@ -10,7 +10,7 @@ TextDocumentView::TextDocumentView(const char* name)
:
BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS)
{
fParagraphLayout.SetWidth(Bounds().Width());
fTextDocumentLayout.SetWidth(Bounds().Width());
SetViewColor(B_TRANSPARENT_COLOR);
// SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
@@ -28,8 +28,8 @@ TextDocumentView::Draw(BRect updateRect)
{
FillRect(updateRect, B_SOLID_LOW);
fParagraphLayout.SetWidth(Bounds().Width());
fParagraphLayout.Draw(this, B_ORIGIN);
fTextDocumentLayout.SetWidth(Bounds().Width());
fTextDocumentLayout.Draw(this, B_ORIGIN);
}
@@ -45,7 +45,7 @@ TextDocumentView::AttachedToWindow()
void
TextDocumentView::FrameResized(float width, float height)
{
fParagraphLayout.SetWidth(width);
fTextDocumentLayout.SetWidth(width);
}
@@ -81,7 +81,7 @@ void
TextDocumentView::GetHeightForWidth(float width, float* min, float* max,
float* preferred)
{
ParagraphLayout layout(fParagraphLayout);
TextDocumentLayout layout(fTextDocumentLayout);
layout.SetWidth(width);
float height = layout.Height() + 1;
@@ -99,7 +99,7 @@ void
TextDocumentView::SetTextDocument(const TextDocumentRef& document)
{
fTextDocument = document;
fParagraphLayout.SetParagraph(fTextDocument->ParagraphAt(0));
fTextDocumentLayout.SetTextDocument(fTextDocument);
InvalidateLayout();
}
@@ -8,8 +8,8 @@
#include <String.h>
#include <View.h>
#include "ParagraphLayout.h"
#include "TextDocument.h"
#include "TextDocumentLayout.h"
class TextDocumentView : public BView {
@@ -35,7 +35,7 @@ public:
private:
TextDocumentRef fTextDocument;
ParagraphLayout fParagraphLayout;
TextDocumentLayout fTextDocumentLayout;
};
#endif // TEXT_DOCUMENT_VIEW_H