1 module nodes.map_frame;
2 
3 import fluid;
4 
5 @safe:
6 
7 @("MapFrame lays nodes out differently based on their drop vectors")
8 unittest {
9 
10     import fluid.space;
11     import fluid.structs : layout;
12 
13     class RectangleSpace : Space {
14 
15         CanvasIO canvasIO;
16         Color color;
17 
18         this(Color color) @safe {
19             this.color = color;
20         }
21 
22         override void resizeImpl(Vector2) @safe {
23             use(canvasIO);
24             minSize = Vector2(10, 10);
25         }
26 
27         override void drawImpl(Rectangle outer, Rectangle inner) @safe {
28             canvasIO.drawRectangle(inner, color);
29         }
30 
31     }
32 
33     RectangleSpace[9] spaces;
34 
35     auto root = mapFrame(
36         layout!(1, "fill"),
37 
38         // Rectangles with same X and Y
39 
40         Vector2(50, 50),
41         .dropVector!"start",
42         spaces[0] = new RectangleSpace(color!"f00"),
43 
44         Vector2(50, 50),
45         .dropVector!"center",
46         spaces[1] = new RectangleSpace(color!"0f0"),
47 
48         Vector2(50, 50),
49         .dropVector!"end",
50         spaces[2] = new RectangleSpace(color!"00f"),
51 
52         // Rectangles with different Xs
53 
54         Vector2(50, 100),
55         .dropVector!("start", "start"),
56         spaces[3] = new RectangleSpace(color!"e00"),
57 
58         Vector2(50, 100),
59         .dropVector!("center", "start"),
60         spaces[4] = new RectangleSpace(color!"0e0"),
61 
62         Vector2(50, 100),
63         .dropVector!("end", "start"),
64         spaces[5] = new RectangleSpace(color!"00e"),
65 
66         // Overflowing rectangles
67         Vector2(-10, -10),
68         spaces[6] = new RectangleSpace(color!"f0f"),
69 
70         Vector2(20, -5),
71         spaces[7] = new RectangleSpace(color!"0ff"),
72 
73         Vector2(-5, 20),
74         spaces[8] = new RectangleSpace(color!"ff0"),
75     );
76     auto test = testSpace(.layout!"fill", nullTheme, root);
77 
78     foreach (preventOverflow; [false, true, false]) {
79 
80         root.preventOverflow = preventOverflow;
81         test.drawAndAssert(
82 
83             // Every rectangle is attached to (50, 50) but using a different origin point
84             // The first red rectangle is attached by its start corner, the green by center corner, and the blue by end
85             // corner
86             spaces[0].drawsRectangle(50, 50, 10, 10).ofColor("f00"),
87             spaces[1].drawsRectangle(45, 45, 10, 10).ofColor("0f0"),
88             spaces[2].drawsRectangle(40, 40, 10, 10).ofColor("00f"),
89 
90             // This is similar for the second triple of rectangles, but the Y axis is the same for every one of them
91             spaces[3].drawsRectangle(50, 100, 10, 10).ofColor("e00"),
92             spaces[4].drawsRectangle(45, 100, 10, 10).ofColor("0e0"),
93             spaces[5].drawsRectangle(40, 100, 10, 10).ofColor("00e"));
94 
95         // Two rectangles overflow: one is completely outside the view, and one is only peeking in
96         // With overflow disabled, they should both be moved strictly inside the mapFrame
97         if (preventOverflow) {
98             test.drawAndAssert(
99                 spaces[6].drawsRectangle(0, 0, 10, 10).ofColor("f0f"),
100                 spaces[7].drawsRectangle(20, 0, 10, 10).ofColor("0ff"),
101                 spaces[8].drawsRectangle(0, 20, 10, 10).ofColor("ff0"));
102         }
103 
104         // With overflow enabled, these two overflows should now be allowed to stay outside
105         else {
106             test.drawAndAssert(
107                 spaces[6].drawsRectangle(-10, -10, 10, 10).ofColor("f0f"),
108                 spaces[7].drawsRectangle(20, -5, 10, 10).ofColor("0ff"),
109                 spaces[8].drawsRectangle(-5, 20, 10, 10).ofColor("ff0"));
110         }
111 
112     }
113 
114 }