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