From ccfedbc4fae6e29a262f848b18383d2aa1810d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Thu, 5 Sep 2013 18:07:14 +0200 Subject: [PATCH] HaikuDepot: text stuff: Layout all document paragraphs. * Use TextDocumentLayout in TextDocumentView. * Extend test case demonstrating paragraphs with different alignments, something unsupported in BTextView. --- src/apps/haiku-depot/Jamfile | 1 + .../textview/TextDocumentLayout.cpp | 155 ++++++++++++++++++ .../haiku-depot/textview/TextDocumentLayout.h | 107 ++++++++++++ .../haiku-depot/textview/TextDocumentTest.cpp | 12 +- .../haiku-depot/textview/TextDocumentView.cpp | 12 +- .../haiku-depot/textview/TextDocumentView.h | 4 +- 6 files changed, 282 insertions(+), 9 deletions(-) create mode 100644 src/apps/haiku-depot/textview/TextDocumentLayout.cpp create mode 100644 src/apps/haiku-depot/textview/TextDocumentLayout.h diff --git a/src/apps/haiku-depot/Jamfile b/src/apps/haiku-depot/Jamfile index 13b48f1db4..ecd1902bc5 100644 --- a/src/apps/haiku-depot/Jamfile +++ b/src/apps/haiku-depot/Jamfile @@ -20,6 +20,7 @@ local textDocumentSources = ParagraphStyle.cpp ParagraphStyleData.cpp TextDocument.cpp + TextDocumentLayout.cpp TextDocumentView.cpp TextLayout.cpp TextSpan.cpp diff --git a/src/apps/haiku-depot/textview/TextDocumentLayout.cpp b/src/apps/haiku-depot/textview/TextDocumentLayout.cpp new file mode 100644 index 0000000000..b728b7bcf3 --- /dev/null +++ b/src/apps/haiku-depot/textview/TextDocumentLayout.cpp @@ -0,0 +1,155 @@ +/* + * Copyright 2013, Stephan Aßmus . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "TextDocumentLayout.h" + +#include +#include + +#include + + +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(); + } +} diff --git a/src/apps/haiku-depot/textview/TextDocumentLayout.h b/src/apps/haiku-depot/textview/TextDocumentLayout.h new file mode 100644 index 0000000000..2cf1dbf937 --- /dev/null +++ b/src/apps/haiku-depot/textview/TextDocumentLayout.h @@ -0,0 +1,107 @@ +/* + * Copyright 2013, Stephan Aßmus . + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef TEXT_DOCUMENT_LAYOUT_H +#define TEXT_DOCUMENT_LAYOUT_H + +#include + +#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 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 TextDocumentLayoutRef; + +#endif // TEXT_DOCUMENT_LAYOUT_H diff --git a/src/apps/haiku-depot/textview/TextDocumentTest.cpp b/src/apps/haiku-depot/textview/TextDocumentTest.cpp index 7d804b4ef7..41d7658463 100644 --- a/src/apps/haiku-depot/textview/TextDocumentTest.cpp +++ b/src/apps/haiku-depot/textview/TextDocumentTest.cpp @@ -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); diff --git a/src/apps/haiku-depot/textview/TextDocumentView.cpp b/src/apps/haiku-depot/textview/TextDocumentView.cpp index c344f10efe..9baddafb4c 100644 --- a/src/apps/haiku-depot/textview/TextDocumentView.cpp +++ b/src/apps/haiku-depot/textview/TextDocumentView.cpp @@ -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(); } diff --git a/src/apps/haiku-depot/textview/TextDocumentView.h b/src/apps/haiku-depot/textview/TextDocumentView.h index 0e7f57c4d6..14e1f2f80a 100644 --- a/src/apps/haiku-depot/textview/TextDocumentView.h +++ b/src/apps/haiku-depot/textview/TextDocumentView.h @@ -8,8 +8,8 @@ #include #include -#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