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 ///
14 /// Styles: $(UL
15 ///     $(LI `style` = Default style for this node.)
16 /// )
17 alias label = simpleConstructor!Label;
18 
19 /// ditto
20 class Label : Node {
21 
22     mixin DefineStyles;
23     mixin ImplHoveredRect;
24 
25     public {
26 
27         /// Text of this label.
28         Text!Label text;
29 
30         /// If true, the content of the label should not be wrapped into new lines if it's too long to fit into one.
31         bool isWrapDisabled;
32 
33     }
34 
35     deprecated("Use this(NodeParams, string text) instead.") {
36 
37         static foreach (index; 0 .. BasicNodeParamLength) {
38 
39             /// Initialize the label with given text.
40             this(BasicNodeParam!index sup, string text = "") {
41 
42                 super(sup);
43                 this.text = Text!Label(this, text);
44 
45             }
46 
47         }
48 
49     }
50 
51     this(NodeParams params, string text) {
52 
53         super(params);
54         this.text = Text!Label(this, text);
55 
56     }
57 
58     deprecated("`text` is now a required parameter for label — please adjust before 0.7.0.")
59     this(NodeParams params) {
60 
61         super(params);
62         this.text = Text!Label(this, text);
63 
64     }
65 
66     /// Set wrap on for this node.
67     This disableWrap(this This = Label)() return {
68 
69         isWrapDisabled = true;
70         return cast(This) this;
71 
72     }
73 
74     /// Set wrap off for this node
75     This enableWrap(this This = Label)() return {
76 
77         isWrapDisabled = false;
78         return cast(This) this;
79 
80     }
81 
82     protected override void resizeImpl(Vector2 available) {
83 
84         import std.math;
85 
86         text.resize(available, !isWrapDisabled);
87         minSize = text.size;
88 
89     }
90 
91     protected override void drawImpl(Rectangle outer, Rectangle inner) {
92 
93         const style = pickStyle();
94         style.drawBackground(tree.io, outer);
95         text.draw(style, inner);
96 
97     }
98 
99     override inout(Style) pickStyle() inout {
100 
101         return style;
102 
103     }
104 
105     unittest {
106 
107         auto io = new HeadlessBackend;
108         auto root = label("Hello, World!");
109 
110         root.theme = nullTheme.makeTheme!q{
111             Label.styleAdd.textColor = color!"000";
112         };
113         root.io = io;
114         root.draw();
115 
116         const initialTextArea = root.text.size.x * root.text.size.y;
117 
118         io.assertTexture(root.text.texture, Vector2(0, 0), color!"000");
119         io.nextFrame;
120 
121         root.text ~= " It's a nice day today!";
122         root.draw();
123 
124         io.assertTexture(root.text.texture, Vector2(0, 0), color!"000");
125 
126         const newTextArea = root.text.size.x * root.text.size.y;
127 
128         assert(newTextArea > initialTextArea);
129 
130     }
131 
132 }
133 
134 ///
135 unittest {
136 
137     // Label takes just a single argument: the text to display
138     auto myLabel = label("Hello, World!");
139 
140     // You can access and change label text
141     myLabel.text ~= " It's a nice day today!";
142 
143     // Text will automatically wrap if it's too long to fit, but you can toggle it off
144     myLabel.isWrapDisabled = true;
145 
146 }