1 module fluid.size_lock;
2 
3 import std.algorithm;
4 
5 import fluid.node;
6 import fluid.utils;
7 import fluid.style;
8 import fluid.backend;
9 
10 
11 
12 @safe:
13 
14 
15 SizeLimit sizeLimit(size_t x, size_t y) {
16 
17     return SizeLimit(x, y);
18 
19 }
20 
21 SizeLimit sizeLimitX(size_t x) {
22 
23     return SizeLimit(x, 0);
24 
25 }
26 
27 SizeLimit sizeLimitY(size_t y) {
28 
29     return SizeLimit(0, y);
30 
31 }
32 
33 struct SizeLimit {
34 
35     size_t x;
36     size_t y;
37 
38 }
39 
40 /// `sizeLock` "locks" a node, restricting space avilable to it, and making it fill the space, if possible.
41 ///
42 /// Size-locks are extremely useful for responsible applications, making sure the content doesn't span too much space on
43 /// large screens, for example on wide-screen, where the content can be applied a sizeLimitX, so it never spreads to
44 /// more than the set value.
45 alias sizeLock(alias T) = simpleConstructor!(SizeLock, T);
46 
47 /// ditto
48 class SizeLock(T : Node) : T {
49 
50     /// The maximum size of this node.
51     /// If a value on either axis is `0`, limit will not be applied on the axis.
52     SizeLimit limit;
53 
54     this(T...)(SizeLimit limit, T args) {
55 
56         super(args);
57         this.limit = limit;
58 
59     }
60 
61     override void resizeImpl(Vector2 space) {
62 
63         // Virtually limit the available space
64         if (limit.x != 0) space.x = min(space.x, limit.x);
65         if (limit.y != 0) space.y = min(space.y, limit.y);
66 
67         // Resize the child
68         super.resizeImpl(space);
69 
70         // Apply the limit to the resulting value; fill in remaining space if available
71         if (limit.x != 0) minSize.x = max(space.x, min(limit.x, minSize.x));
72         if (limit.y != 0) minSize.y = max(space.y, min(limit.y, minSize.y));
73 
74     }
75 
76 }
77 
78 ///
79 unittest {
80 
81     import fluid;
82 
83     // The frame will appear horizontally-centered in the parent node, while filling it vertically
84     sizeLock!vframe(
85         layout!(1, "center", "fill"),
86         sizeLimitX(400),
87 
88         label("Hello, World!")
89     );
90 
91 }
92 
93 unittest {
94 
95     import fluid.space;
96     import fluid.label;
97     import fluid.frame;
98     import fluid.structs;
99 
100     auto io = new HeadlessBackend;
101     auto root = sizeLock!vframe(
102         layout!("center", "fill"),
103         sizeLimitX(400),
104         label("Hello, World!"),
105     );
106 
107     root.io = io;
108 
109     with (Rule)
110     root.theme = nullTheme.derive(
111         rule!Frame(backgroundColor = color!"1c1c1c"),
112         rule!Label(textColor = color!"eee"),
113     );
114 
115     {
116         root.draw();
117 
118         // The rectangle should display neatly in the middle of the display, limited to 400px
119         io.assertRectangle(Rectangle(200, 0, 400, 600), color!"1c1c1c");
120     }
121 
122     {
123         io.nextFrame;
124         root.layout = layout!("start", "fill");
125         root.updateSize();
126         root.draw();
127 
128         io.assertRectangle(Rectangle(0, 0, 400, 600), color!"1c1c1c");
129     }
130 
131     {
132         io.nextFrame;
133         root.layout = layout!"center";
134         root.limit = sizeLimit(200, 200);
135         root.updateSize();
136         root.draw();
137 
138         io.assertRectangle(Rectangle(300, 200, 200, 200), color!"1c1c1c");
139     }
140 
141 }