diff --git a/src/dlangui/dialogs/msgbox.d b/src/dlangui/dialogs/msgbox.d
index fd4c11c0..13bda396 100644
--- a/src/dlangui/dialogs/msgbox.d
+++ b/src/dlangui/dialogs/msgbox.d
@@ -55,7 +55,7 @@ class MessageBox : Dialog {
}
/// override to implement creation of dialog controls
override void init() {
- TextWidget msg = new TextWidget("msg", _message);
+ TextWidget msg = new MultilineTextWidget("msg", _message);
padding(Rect(10, 10, 10, 10));
msg.padding(Rect(10, 10, 10, 10));
addChild(msg);
diff --git a/src/dlangui/graphics/fonts.d b/src/dlangui/graphics/fonts.d
index 992c53e0..9ea85c10 100644
--- a/src/dlangui/graphics/fonts.d
+++ b/src/dlangui/graphics/fonts.d
@@ -209,6 +209,8 @@ class Font : RefCountedObject {
return 0;
const dchar * pstr = text.ptr;
uint len = cast(uint)text.length;
+ if (widths.length < len)
+ widths.length = len + 1;
int x = 0;
int charsMeasured = 0;
int * pwidths = widths.ptr;
@@ -475,7 +477,7 @@ struct SimpleTextFormatter {
int lastWordEndX = 0;
dchar prevChar = 0;
for (int i = 0; i <= charsMeasured; i++) {
- dchar ch = text[i];
+ dchar ch = i < charsMeasured ? text[i] : 0;
if (ch == '\n' || i == charsMeasured) {
// split by EOL char or at end of text
dstring line = cast(dstring)text[lineStart .. i];
@@ -506,7 +508,7 @@ struct SimpleTextFormatter {
prevChar = ch;
continue;
}
- if (maxWidth > 0 && x > maxWidth && x - lineStartX > maxWidth && i > lineStart) {
+ if (maxWidth > 0 && maxWidth != MAX_WIDTH_UNSPECIFIED && x > maxWidth && x - lineStartX > maxWidth && i > lineStart) {
// need splitting
int lineEnd = i;
int lineEndX = widths[i - 1];
diff --git a/src/dlangui/widgets/controls.d b/src/dlangui/widgets/controls.d
index 0e8973a4..82968d80 100644
--- a/src/dlangui/widgets/controls.d
+++ b/src/dlangui/widgets/controls.d
@@ -70,6 +70,17 @@ class TextWidget : Widget {
styleId = STYLE_TEXT;
_text = rawText;
}
+ this(string ID, UIString uitext) {
+ super(ID);
+ styleId = STYLE_TEXT;
+ _text = uitext;
+ }
+
+ /// max lines to show
+ @property int maxLines() { return style.maxLines; }
+ /// set max lines to show
+ @property void maxLines(int n) { ownStyle.maxLines = n; }
+
protected UIString _text;
/// get widget text
override @property dstring text() { return _text; }
@@ -95,7 +106,12 @@ class TextWidget : Widget {
override void measure(int parentWidth, int parentHeight) {
FontRef font = font();
//auto measureStart = std.datetime.Clock.currAppTick;
- Point sz = font.textSize(text, MAX_WIDTH_UNSPECIFIED, 4, 0, textFlags);
+ Point sz;
+ if (maxLines == 1) {
+ sz = font.textSize(text, MAX_WIDTH_UNSPECIFIED, 4, 0, textFlags);
+ } else {
+ sz = font.measureMultilineText(text, maxLines, MAX_WIDTH_UNSPECIFIED, 4, 0, textFlags);
+ }
//auto measureEnd = std.datetime.Clock.currAppTick;
//auto duration = measureEnd - measureStart;
//if (duration.length > 10)
@@ -113,9 +129,33 @@ class TextWidget : Widget {
applyPadding(rc);
FontRef font = font();
- Point sz = font.textSize(text);
- applyAlign(rc, sz);
- font.drawText(buf, rc.left, rc.top, text, textColor, 4, 0, textFlags);
+ if (maxLines == 1) {
+ Point sz = font.textSize(text);
+ applyAlign(rc, sz);
+ font.drawText(buf, rc.left, rc.top, text, textColor, 4, 0, textFlags);
+ } else {
+ SimpleTextFormatter fmt;
+ Point sz = fmt.format(text, font, maxLines, rc.width, 4, 0, textFlags);
+ applyAlign(rc, sz);
+ // TODO: apply align to alignment lines
+ fmt.draw(buf, rc.left, rc.top, font, textColor);
+ }
+ }
+}
+
+/// static text widget with multiline text
+class MultilineTextWidget : TextWidget {
+ this(string ID = null, string textResourceId = null) {
+ super(ID, textResourceId);
+ styleId = STYLE_MULTILINE_TEXT;
+ }
+ this(string ID, dstring rawText) {
+ super(ID, rawText);
+ styleId = STYLE_MULTILINE_TEXT;
+ }
+ this(string ID, UIString uitext) {
+ super(ID, uitext);
+ styleId = STYLE_MULTILINE_TEXT;
}
}
diff --git a/src/dlangui/widgets/styles.d b/src/dlangui/widgets/styles.d
index d0246c82..9ce7f172 100644
--- a/src/dlangui/widgets/styles.d
+++ b/src/dlangui/widgets/styles.d
@@ -34,6 +34,8 @@ import dlangui.graphics.resources;
// Themes should define all of these styles in order to support all controls
/// standard style id for TextWidget
immutable string STYLE_TEXT = "TEXT";
+/// standard style id for MultilineTextWidget
+immutable string STYLE_MULTILINE_TEXT = "MULTILINE_TEXT";
/// standard style id for Button
immutable string STYLE_BUTTON = "BUTTON";
/// standard style id for Button label
@@ -277,6 +279,7 @@ class Style {
protected int _layoutWidth = SIZE_UNSPECIFIED;
protected int _layoutHeight = SIZE_UNSPECIFIED;
protected int _layoutWeight = WEIGHT_UNSPECIFIED;
+ protected int _maxLines = SIZE_UNSPECIFIED;
protected uint[] _focusRectColors;
@@ -484,6 +487,14 @@ class Style {
return parentStyle.textColor;
}
+ /// text color
+ @property int maxLines() const {
+ if (_maxLines != SIZE_UNSPECIFIED)
+ return _maxLines;
+ else
+ return parentStyle.maxLines;
+ }
+
/// text flags
@property uint textFlags() const {
if (_textFlags != TEXT_FLAGS_UNSPECIFIED)
@@ -660,6 +671,11 @@ class Style {
return this;
}
+ @property Style maxLines(int lines) {
+ _maxLines = lines;
+ return this;
+ }
+
@property Style alpha(uint alpha) {
_alpha = alpha;
return this;
@@ -814,6 +830,7 @@ class Theme : Style {
_parentStyle = null;
_backgroundColor = COLOR_TRANSPARENT; // transparent
_textColor = 0x000000; // black
+ _maxLines = 1;
_align = Align.TopLeft;
_fontSize = 14; // TODO: from settings or screen properties / DPI
_fontStyle = FONT_STYLE_NORMAL;
@@ -1218,6 +1235,8 @@ bool loadStyleAttributes(Style style, Element elem, bool allowStates) {
style.minHeight = decodeDimension(elem.tag.attr["minHeight"]);
if ("maxHeight" in elem.tag.attr)
style.maxHeight = decodeDimension(elem.tag.attr["maxHeight"]);
+ if ("maxLines" in elem.tag.attr)
+ style.maxLines = decodeDimension(elem.tag.attr["maxLines"]);
if ("fontFace" in elem.tag.attr)
style.fontFace = elem.tag.attr["fontFace"];
if ("fontFamily" in elem.tag.attr)
diff --git a/views/res/theme_dark.xml b/views/res/theme_dark.xml
index b9eb9ad3..bb977764 100644
--- a/views/res/theme_dark.xml
+++ b/views/res/theme_dark.xml
@@ -98,6 +98,14 @@
>
+
+