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 }