From d31130dde96954637825a20e6e1a675e354c9579 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Wed, 18 Mar 2015 11:26:08 +0300 Subject: [PATCH] implement issue #39 - MultilineTextWidget --- src/dlangui/dialogs/msgbox.d | 2 +- src/dlangui/graphics/fonts.d | 6 +++-- src/dlangui/widgets/controls.d | 48 +++++++++++++++++++++++++++++++--- src/dlangui/widgets/styles.d | 19 ++++++++++++++ views/res/theme_dark.xml | 8 ++++++ views/res/theme_default.xml | 8 ++++++ 6 files changed, 84 insertions(+), 7 deletions(-) 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 @@ > + +