1 ///
2 module fluid.label;
3 
4 import fluid.node;
5 import fluid.text;
6 import fluid.utils;
7 import fluid.style;
8 import fluid.backend;
9 
10 @safe:
11 
12 /// A label can be used to display text on the screen.
13 alias label = simpleConstructor!Label;
14 
15 /// ditto
16 class Label : Node {
17 
18     public {
19 
20         /// Text of this label.
21         Text text;
22 
23         alias value = text;
24 
25         /// If true, the content of the label should not be wrapped into new lines if it's too long to fit into one.
26         bool isWrapDisabled;
27 
28     }
29 
30     this(Rope text) {
31 
32         this.text = Text(this, text);
33 
34     }
35 
36     this(const(char)[] text) {
37 
38         this.text = Text(this, text);
39 
40     }
41 
42     /// Set wrap on for this node.
43     This disableWrap(this This = Label)() return {
44 
45         isWrapDisabled = true;
46         return cast(This) this;
47 
48     }
49 
50     /// Set wrap off for this node
51     This enableWrap(this This = Label)() return {
52 
53         isWrapDisabled = false;
54         return cast(This) this;
55 
56     }
57 
58     bool isEmpty() const {
59 
60         return text.length == 0;
61 
62     }
63 
64     protected override void resizeImpl(Vector2 available) {
65 
66         import std.math;
67 
68         text.resize(available, !isWrapDisabled);
69         minSize = text.size;
70 
71     }
72 
73     protected override void drawImpl(Rectangle outer, Rectangle inner) {
74 
75         const style = pickStyle();
76         style.drawBackground(tree.io, outer);
77         text.draw(style, inner.start);
78 
79     }
80 
81     unittest {
82 
83         auto io = new HeadlessBackend;
84         auto root = label("Hello, World!");
85 
86         with (Rule)
87         root.theme = nullTheme.derive(
88             rule!Label(textColor = color!"000"),
89         );
90         root.io = io;
91         root.draw();
92 
93         const initialTextArea = root.text.size.x * root.text.size.y;
94 
95         io.assertTexture(root.text.texture.chunks[0], Vector2(0, 0), color!"fff");
96         io.nextFrame;
97 
98         root.text ~= " It's a nice day today!";
99         root.draw();
100 
101         io.assertTexture(root.text.texture.chunks[0], Vector2(0, 0), color!"fff");
102 
103         const newTextArea = root.text.size.x * root.text.size.y;
104 
105         assert(newTextArea > initialTextArea);
106 
107     }
108 
109     override string toString() const {
110 
111         import std.range;
112         import std.format;
113 
114         return format!"Label(%(%s%))"(only(text.toString));
115 
116     }
117 
118 }
119 
120 ///
121 unittest {
122 
123     // Label takes just a single argument: the text to display
124     auto myLabel = label("Hello, World!");
125 
126     // You can access and change label text
127     myLabel.text ~= " It's a nice day today!";
128 
129     // Text will automatically wrap if it's too long to fit, but you can toggle it off
130     myLabel.isWrapDisabled = true;
131 
132 }