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:
committed by
waddlesplash
parent
22e03e588e
commit
800e6fe412
@@ -79,6 +79,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BSize _ValidatePreferredSize();
|
BSize _ValidatePreferredSize();
|
||||||
|
float _StringWidth(const char* text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* fText;
|
char* fText;
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user