1 /** 2 * Copyright: Enalye 3 * License: Zlib 4 * Authors: Enalye 5 */ 6 module atelier.ui.label; 7 8 import std.algorithm.comparison : min; 9 import std..string, std.conv; 10 import bindbc.sdl, bindbc.sdl.ttf; 11 import atelier.core, atelier.common, atelier.render; 12 import atelier.ui.gui_element; 13 14 /// A single line of text. 15 final class Label : GuiElement { 16 private { 17 dstring _text; 18 Font _font; 19 int _charSpacing, _charScale = 1; 20 } 21 22 @property { 23 /// Text 24 string text() const { 25 return to!string(_text); 26 } 27 /// Ditto 28 string text(string text_) { 29 _text = to!dstring(text_); 30 reload(); 31 return text_; 32 } 33 34 /// Font 35 Font font() const { 36 return cast(Font) _font; 37 } 38 /// Ditto 39 Font font(Font font_) { 40 _font = font_; 41 reload(); 42 return _font; 43 } 44 45 /// Additionnal spacing between each character 46 int charSpacing() const { 47 return _charSpacing; 48 } 49 /// Ditto 50 int charSpacing(int charSpacing_) { 51 return _charSpacing = charSpacing_; 52 } 53 54 /// Characters scaling 55 int charScale() const { 56 return _charScale; 57 } 58 /// Ditto 59 int charScale(int charScale_) { 60 return _charScale = charScale_; 61 } 62 } 63 64 /// Build label 65 this(string text_ = "", Font font = getDefaultFont()) { 66 setInitFlags(Init.notInteractable); 67 _font = font; 68 _text = to!dstring(text_); 69 reload(); 70 } 71 72 private void reload() { 73 Vec2f totalSize_ = Vec2f(0f, _font.ascent - _font.descent) * _charScale; 74 float lineWidth = 0f; 75 dchar prevChar; 76 foreach (dchar ch; _text) { 77 if (ch == '\n') { 78 lineWidth = 0f; 79 totalSize_.y += _font.lineSkip * _charScale; 80 } 81 else { 82 const Glyph metrics = _font.getMetrics(ch); 83 lineWidth += _font.getKerning(prevChar, ch) * _charScale; 84 lineWidth += metrics.advance * _charScale; 85 if (lineWidth > totalSize_.x) 86 totalSize_.x = lineWidth; 87 prevChar = ch; 88 } 89 } 90 size = totalSize_; 91 } 92 93 override void draw() { 94 Vec2f pos = origin; 95 dchar prevChar; 96 foreach (dchar ch; _text) { 97 if (ch == '\n') { 98 pos.x = origin.x; 99 pos.y += _font.lineSkip * _charScale; 100 prevChar = 0; 101 } 102 else { 103 Glyph metrics = _font.getMetrics(ch); 104 pos.x += _font.getKerning(prevChar, ch) * _charScale; 105 Vec2f drawPos = Vec2f(pos.x + metrics.offsetX * _charScale, 106 pos.y - metrics.offsetY * _charScale); 107 metrics.draw(drawPos, _charScale, color, alpha); 108 pos.x += (metrics.advance + _charSpacing) * _charScale; 109 prevChar = ch; 110 } 111 } 112 } 113 }