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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user