BStringView: add support for multiline strings

* Actually draw the string at the bottom of the frame.
* Unfortunately BStringList cannot be cached because there is no
  space left in the class.
* Change SGI and PNG translators to use it in place of BTextView.

Change-Id: I07e12bf1a8dc956d18c9624604c7b63453ad15a2
Reviewed-on: https://review.haiku-os.org/620
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Kacper Kasper
2018-11-03 16:44:10 +00:00
committed by waddlesplash
parent 22e03e588e
commit 800e6fe412
5 changed files with 73 additions and 68 deletions
+1
View File
@@ -79,6 +79,7 @@ private:
private: private:
BSize _ValidatePreferredSize(); BSize _ValidatePreferredSize();
float _StringWidth(const char* text);
private: private:
char* fText; char* fText;
+5 -17
View File
@@ -18,7 +18,6 @@
#include <MenuItem.h> #include <MenuItem.h>
#include <PopUpMenu.h> #include <PopUpMenu.h>
#include <StringView.h> #include <StringView.h>
#include <TextView.h>
#include <stdio.h> #include <stdio.h>
#define PNG_NO_PEDANTIC_WARNINGS #define PNG_NO_PEDANTIC_WARNINGS
@@ -69,13 +68,10 @@ PNGView::PNGView(const BRect &frame, const char *name, uint32 resizeMode,
menuField->SetDivider(menuField->StringWidth(menuField->Label()) + 7.0f); menuField->SetDivider(menuField->StringWidth(menuField->Label()) + 7.0f);
menuField->ResizeToPreferred(); menuField->ResizeToPreferred();
fCopyrightView = new BTextView("PNG copyright"); BString pngCopyright = png_get_copyright(NULL);
fCopyrightView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); pngCopyright.ReplaceLast("\n", "");
fCopyrightView->SetLowColor(fCopyrightView->ViewColor()); BStringView* pngCopyrightView = new BStringView(
fCopyrightView->MakeEditable(false); "PNG copyright", pngCopyright);
fCopyrightView->SetWordWrap(false);
fCopyrightView->MakeResizable(true);
fCopyrightView->SetText(png_get_copyright(NULL));
BLayoutBuilder::Group<>(this, B_VERTICAL, 0) BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
.SetInsets(B_USE_DEFAULT_SPACING) .SetInsets(B_USE_DEFAULT_SPACING)
@@ -88,7 +84,7 @@ PNGView::PNGView(const BRect &frame, const char *name, uint32 resizeMode,
.AddGlue() .AddGlue()
.End() .End()
.AddGlue() .AddGlue()
.Add(fCopyrightView); .Add(pngCopyrightView);
} }
@@ -118,14 +114,6 @@ PNGView::AttachedToWindow()
} }
void
PNGView::FrameResized(float width, float height)
{
// This works around a flaw of BTextView
fCopyrightView->SetTextRect(fCopyrightView->Bounds());
}
void void
PNGView::MessageReceived(BMessage *message) PNGView::MessageReceived(BMessage *message)
{ {
-3
View File
@@ -15,7 +15,6 @@
#include <View.h> #include <View.h>
class BPopUpMenu; class BPopUpMenu;
class BTextView;
// Config panel messages // Config panel messages
@@ -33,7 +32,6 @@ class PNGView : public BView {
~PNGView(); ~PNGView();
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void FrameResized(float width, float height);
virtual void MessageReceived(BMessage *message); virtual void MessageReceived(BMessage *message);
private: private:
@@ -41,7 +39,6 @@ class PNGView : public BView {
private: private:
BPopUpMenu* fInterlaceMenu; BPopUpMenu* fInterlaceMenu;
BTextView* fCopyrightView;
TranslatorSettings* fSettings; TranslatorSettings* fSettings;
// the actual settings for the translator, // the actual settings for the translator,
// shared with the translator // shared with the translator
+2 -14
View File
@@ -44,7 +44,6 @@
#include <PopUpMenu.h> #include <PopUpMenu.h>
#include <String.h> #include <String.h>
#include <StringView.h> #include <StringView.h>
#include <TextView.h>
#include <Window.h> #include <Window.h>
#include "SGIImage.h" #include "SGIImage.h"
@@ -114,16 +113,11 @@ SGIView::SGIView(const char* name, uint32 flags, TranslatorSettings* settings)
BStringView* detailView = new BStringView("details", detail); BStringView* detailView = new BStringView("details", detail);
detailView->SetExplicitAlignment(labelAlignment); detailView->SetExplicitAlignment(labelAlignment);
BTextView* infoView = new BTextView("info"); BStringView* infoView = new BStringView("info",
infoView->SetText(BString(B_TRANSLATE("written by:\n")) BString(B_TRANSLATE("written by:\n"))
.Append(author) .Append(author)
.Append(B_TRANSLATE("\nbased on GIMP SGI plugin v1.5:\n")) .Append(B_TRANSLATE("\nbased on GIMP SGI plugin v1.5:\n"))
.Append(kSGICopyright).String()); .Append(kSGICopyright).String());
infoView->SetExplicitAlignment(labelAlignment);
infoView->SetWordWrap(false);
infoView->MakeEditable(false);
infoView->MakeResizable(true);
infoView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
BLayoutBuilder::Group<>(this, B_VERTICAL, 0) BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
.SetInsets(B_USE_DEFAULT_SPACING) .SetInsets(B_USE_DEFAULT_SPACING)
@@ -141,12 +135,6 @@ SGIView::SGIView(const char* name, uint32 flags, TranslatorSettings* settings)
GetFont(&font); GetFont(&font);
SetExplicitPreferredSize(BSize((font.Size() * 390) / 12, SetExplicitPreferredSize(BSize((font.Size() * 390) / 12,
(font.Size() * 180) / 12)); (font.Size() * 180) / 12));
// TODO: remove this workaround for ticket #4217
infoView->SetExplicitPreferredSize(
BSize(infoView->LineWidth(3), infoView->TextHeight(0, 80)));
infoView->SetExplicitMaxSize(infoView->ExplicitPreferredSize());
infoView->SetExplicitMinSize(infoView->ExplicitPreferredSize());
} }
+65 -34
View File
@@ -22,6 +22,7 @@
#include <LayoutUtils.h> #include <LayoutUtils.h>
#include <Message.h> #include <Message.h>
#include <PropertyInfo.h> #include <PropertyInfo.h>
#include <StringList.h>
#include <View.h> #include <View.h>
#include <Window.h> #include <Window.h>
@@ -55,7 +56,7 @@ BStringView::BStringView(BRect frame, const char* name, const char* text,
fText(text ? strdup(text) : NULL), fText(text ? strdup(text) : NULL),
fTruncation(B_NO_TRUNCATION), fTruncation(B_NO_TRUNCATION),
fAlign(B_ALIGN_LEFT), fAlign(B_ALIGN_LEFT),
fPreferredSize(text ? StringWidth(text) : 0.0, -1) fPreferredSize(text ? _StringWidth(text) : 0.0, -1)
{ {
} }
@@ -66,7 +67,7 @@ BStringView::BStringView(const char* name, const char* text, uint32 flags)
fText(text ? strdup(text) : NULL), fText(text ? strdup(text) : NULL),
fTruncation(B_NO_TRUNCATION), fTruncation(B_NO_TRUNCATION),
fAlign(B_ALIGN_LEFT), fAlign(B_ALIGN_LEFT),
fPreferredSize(text ? StringWidth(text) : 0.0, -1) fPreferredSize(text ? _StringWidth(text) : 0.0, -1)
{ {
} }
@@ -273,36 +274,41 @@ BStringView::Draw(BRect updateRect)
BRect bounds = Bounds(); BRect bounds = Bounds();
const char* text = fText; BStringList lines;
float width = fPreferredSize.width; BString(fText).Split("\n", false, lines);
BString truncated; for (int i = 0; i < lines.CountStrings(); i++) {
if (fTruncation != B_NO_TRUNCATION && width > bounds.Width()) { const char* text = lines.StringAt(i).String();
// The string needs to be truncated float width = StringWidth(text);
// TODO: we should cache this BString truncated;
truncated = fText; if (fTruncation != B_NO_TRUNCATION && width > bounds.Width()) {
TruncateString(&truncated, fTruncation, bounds.Width()); // The string needs to be truncated
text = truncated.String(); // TODO: we should cache this
width = StringWidth(text); truncated = lines.StringAt(i);
TruncateString(&truncated, fTruncation, bounds.Width());
text = truncated.String();
width = StringWidth(text);
}
float y = (bounds.top + bounds.bottom - ceilf(fontHeight.descent))
- ceilf(fontHeight.ascent + fontHeight.descent + fontHeight.leading)
* (lines.CountStrings() - i - 1);
float x;
switch (fAlign) {
case B_ALIGN_RIGHT:
x = bounds.Width() - width;
break;
case B_ALIGN_CENTER:
x = (bounds.Width() - width) / 2.0;
break;
default:
x = 0.0;
break;
}
DrawString(text, BPoint(x, y));
} }
float y = (bounds.top + bounds.bottom - ceilf(fontHeight.ascent)
- ceilf(fontHeight.descent)) / 2.0 + ceilf(fontHeight.ascent);
float x;
switch (fAlign) {
case B_ALIGN_RIGHT:
x = bounds.Width() - width;
break;
case B_ALIGN_CENTER:
x = (bounds.Width() - width) / 2.0;
break;
default:
x = 0.0;
break;
}
DrawString(text, BPoint(x, y));
} }
@@ -391,7 +397,7 @@ BStringView::SetText(const char* text)
free(fText); free(fText);
fText = text ? strdup(text) : NULL; fText = text ? strdup(text) : NULL;
float newStringWidth = StringWidth(fText); float newStringWidth = _StringWidth(fText);
if (fPreferredSize.width != newStringWidth) { if (fPreferredSize.width != newStringWidth) {
fPreferredSize.width = newStringWidth; fPreferredSize.width = newStringWidth;
InvalidateLayout(); InvalidateLayout();
@@ -476,7 +482,7 @@ BStringView::SetFont(const BFont* font, uint32 mask)
{ {
BView::SetFont(font, mask); BView::SetFont(font, mask);
fPreferredSize.width = StringWidth(fText); fPreferredSize.width = _StringWidth(fText);
Invalidate(); Invalidate();
InvalidateLayout(); InvalidateLayout();
@@ -585,8 +591,15 @@ BStringView::_ValidatePreferredSize()
font_height fontHeight; font_height fontHeight;
GetFontHeight(&fontHeight); GetFontHeight(&fontHeight);
int32 lines = 0;
char* temp = fText;
do {
temp = strchr(temp + 1, '\n');
lines++;
} while (temp != NULL);
fPreferredSize.height = ceilf(fontHeight.ascent + fontHeight.descent fPreferredSize.height = ceilf(fontHeight.ascent + fontHeight.descent
+ fontHeight.leading); + fontHeight.leading) * lines;
ResetLayoutInvalidation(); ResetLayoutInvalidation();
} }
@@ -595,6 +608,24 @@ BStringView::_ValidatePreferredSize()
} }
float
BStringView::_StringWidth(const char* text)
{
if(text == NULL)
return 0.0f;
float maxWidth = 0.0f;
BStringList lines;
BString(fText).Split("\n", false, lines);
for (int i = 0; i < lines.CountStrings(); i++) {
float width = StringWidth(lines.StringAt(i));
if (maxWidth < width)
maxWidth = width;
}
return maxWidth;
}
extern "C" void extern "C" void
B_IF_GCC_2(InvalidateLayout__11BStringViewb, B_IF_GCC_2(InvalidateLayout__11BStringViewb,
_ZN11BStringView16InvalidateLayoutEb)(BView* view, bool descendants) _ZN11BStringView16InvalidateLayoutEb)(BView* view, bool descendants)