A game framework written with osu! in mind.
at master 898 lines 35 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using System.Linq; 6using NUnit.Framework; 7using osu.Framework.Extensions; 8using osu.Framework.Extensions.IEnumerableExtensions; 9using osu.Framework.Graphics; 10using osu.Framework.Graphics.Containers; 11using osu.Framework.Graphics.Shapes; 12using osu.Framework.Graphics.Sprites; 13using osu.Framework.Utils; 14using osuTK; 15using osuTK.Graphics; 16 17namespace osu.Framework.Tests.Visual.Layout 18{ 19 public class TestSceneGridContainer : FrameworkTestScene 20 { 21 private Container gridParent; 22 private GridContainer grid; 23 24 [SetUp] 25 public void Setup() => Schedule(() => 26 { 27 Child = gridParent = new Container 28 { 29 Anchor = Anchor.Centre, 30 Origin = Anchor.Centre, 31 RelativeSizeAxes = Axes.Both, 32 Size = new Vector2(0.5f), 33 Children = new Drawable[] 34 { 35 grid = new GridContainer { RelativeSizeAxes = Axes.Both }, 36 new Container 37 { 38 RelativeSizeAxes = Axes.Both, 39 Masking = true, 40 BorderColour = Color4.White, 41 BorderThickness = 2, 42 Child = new Box 43 { 44 RelativeSizeAxes = Axes.Both, 45 Alpha = 0, 46 AlwaysPresent = true 47 } 48 } 49 } 50 }; 51 }); 52 53 [TestCase(false)] 54 [TestCase(true)] 55 public void TestAutoSizeDoesNotConsiderRelativeSizeChildren(bool row) 56 { 57 Box relativeBox = null; 58 Box absoluteBox = null; 59 60 setSingleDimensionContent(() => new[] 61 { 62 new Drawable[] 63 { 64 relativeBox = new FillBox { RelativeSizeAxes = Axes.Both }, 65 absoluteBox = new FillBox 66 { 67 RelativeSizeAxes = Axes.None, 68 Size = new Vector2(100) 69 } 70 } 71 }, new[] { new Dimension(GridSizeMode.AutoSize) }, row); 72 73 AddStep("resize absolute box", () => absoluteBox.Size = new Vector2(50)); 74 AddAssert("relative box has length 50", () => Precision.AlmostEquals(row ? relativeBox.DrawHeight : relativeBox.DrawWidth, 50, 1)); 75 } 76 77 [Test] 78 public void TestBlankGrid() 79 { 80 } 81 82 [Test] 83 public void TestSingleCellDistributedXy() 84 { 85 FillBox box = null; 86 AddStep("set content", () => grid.Content = new[] { new Drawable[] { box = new FillBox() }, }); 87 AddAssert("box is same size as grid", () => Precision.AlmostEquals(box.DrawSize, grid.DrawSize)); 88 } 89 90 [Test] 91 public void TestSingleCellAbsoluteXy() 92 { 93 const float size = 100; 94 95 FillBox box = null; 96 AddStep("set content", () => 97 { 98 grid.Content = new[] { new Drawable[] { box = new FillBox() }, }; 99 grid.RowDimensions = grid.ColumnDimensions = new[] { new Dimension(GridSizeMode.Absolute, size) }; 100 }); 101 102 AddAssert("box has expected size", () => Precision.AlmostEquals(box.DrawSize, new Vector2(size))); 103 } 104 105 [Test] 106 public void TestSingleCellRelativeXy() 107 { 108 const float size = 0.5f; 109 110 FillBox box = null; 111 AddStep("set content", () => 112 { 113 grid.Content = new[] { new Drawable[] { box = new FillBox() }, }; 114 grid.RowDimensions = grid.ColumnDimensions = new[] { new Dimension(GridSizeMode.Relative, size) }; 115 }); 116 117 AddAssert("box has expected size", () => Precision.AlmostEquals(box.DrawSize, grid.DrawSize * new Vector2(size))); 118 } 119 120 [Test] 121 public void TestSingleCellRelativeXAbsoluteY() 122 { 123 const float absolute_height = 100; 124 const float relative_width = 0.5f; 125 126 FillBox box = null; 127 AddStep("set content", () => 128 { 129 grid.Content = new[] { new Drawable[] { box = new FillBox() }, }; 130 grid.RowDimensions = new[] { new Dimension(GridSizeMode.Absolute, absolute_height) }; 131 grid.ColumnDimensions = new[] { new Dimension(GridSizeMode.Relative, relative_width) }; 132 }); 133 134 AddAssert("box has expected width", () => Precision.AlmostEquals(box.DrawWidth, grid.DrawWidth * relative_width)); 135 AddAssert("box has expected height", () => Precision.AlmostEquals(box.DrawHeight, absolute_height)); 136 } 137 138 [Test] 139 public void TestSingleCellDistributedXRelativeY() 140 { 141 const float height = 0.5f; 142 143 FillBox box = null; 144 AddStep("set content", () => 145 { 146 grid.Content = new[] { new Drawable[] { box = new FillBox() }, }; 147 grid.RowDimensions = new[] { new Dimension(GridSizeMode.Relative, height) }; 148 }); 149 150 AddAssert("box has expected width", () => Precision.AlmostEquals(box.DrawWidth, grid.DrawWidth)); 151 AddAssert("box has expected height", () => Precision.AlmostEquals(box.DrawHeight, grid.DrawHeight * height)); 152 } 153 154 [TestCase(false)] 155 [TestCase(true)] 156 public void Test3CellRowOrColumnDistributedXy(bool row) 157 { 158 FillBox[] boxes = new FillBox[3]; 159 160 setSingleDimensionContent(() => new[] 161 { 162 new Drawable[] { boxes[0] = new FillBox(), boxes[1] = new FillBox(), boxes[2] = new FillBox() } 163 }, row: row); 164 165 for (int i = 0; i < 3; i++) 166 { 167 int local = i; 168 169 if (row) 170 AddAssert($"box {local} has correct size", () => Precision.AlmostEquals(boxes[local].DrawSize, new Vector2(grid.DrawWidth / 3f, grid.DrawHeight))); 171 else 172 AddAssert($"box {local} has correct size", () => Precision.AlmostEquals(boxes[local].DrawSize, new Vector2(grid.DrawWidth, grid.DrawHeight / 3f))); 173 } 174 } 175 176 [TestCase(false)] 177 [TestCase(true)] 178 public void Test3CellRowOrColumnDistributedXyAbsoluteYx(bool row) 179 { 180 var sizes = new[] { 50f, 100f, 75f }; 181 var boxes = new FillBox[3]; 182 183 setSingleDimensionContent(() => new[] 184 { 185 new Drawable[] { boxes[0] = new FillBox() }, 186 new Drawable[] { boxes[1] = new FillBox() }, 187 new Drawable[] { boxes[2] = new FillBox() }, 188 }, new[] 189 { 190 new Dimension(GridSizeMode.Absolute, sizes[0]), 191 new Dimension(GridSizeMode.Absolute, sizes[1]), 192 new Dimension(GridSizeMode.Absolute, sizes[2]) 193 }, row); 194 195 for (int i = 0; i < 3; i++) 196 { 197 int local = i; 198 199 if (row) 200 AddAssert($"box {local} has correct size", () => Precision.AlmostEquals(boxes[local].DrawSize, new Vector2(grid.DrawWidth, sizes[local]))); 201 else 202 AddAssert($"box {local} has correct size", () => Precision.AlmostEquals(boxes[local].DrawSize, new Vector2(sizes[local], grid.DrawHeight))); 203 } 204 } 205 206 [TestCase(false)] 207 [TestCase(true)] 208 public void Test3CellRowOrColumnDistributedXyRelativeYx(bool row) 209 { 210 var sizes = new[] { 0.2f, 0.4f, 0.2f }; 211 var boxes = new FillBox[3]; 212 213 setSingleDimensionContent(() => new[] 214 { 215 new Drawable[] { boxes[0] = new FillBox() }, 216 new Drawable[] { boxes[1] = new FillBox() }, 217 new Drawable[] { boxes[2] = new FillBox() }, 218 }, new[] 219 { 220 new Dimension(GridSizeMode.Relative, sizes[0]), 221 new Dimension(GridSizeMode.Relative, sizes[1]), 222 new Dimension(GridSizeMode.Relative, sizes[2]) 223 }, row); 224 225 for (int i = 0; i < 3; i++) 226 { 227 int local = i; 228 229 if (row) 230 AddAssert($"box {local} has correct size", () => Precision.AlmostEquals(boxes[local].DrawSize, new Vector2(grid.DrawWidth, sizes[local] * grid.DrawHeight))); 231 else 232 AddAssert($"box {local} has correct size", () => Precision.AlmostEquals(boxes[local].DrawSize, new Vector2(sizes[local] * grid.DrawWidth, grid.DrawHeight))); 233 } 234 } 235 236 [TestCase(false)] 237 [TestCase(true)] 238 public void Test3CellRowOrColumnDistributedXyMixedYx(bool row) 239 { 240 var sizes = new[] { 0.2f, 75f }; 241 var boxes = new FillBox[3]; 242 243 setSingleDimensionContent(() => new[] 244 { 245 new Drawable[] { boxes[0] = new FillBox() }, 246 new Drawable[] { boxes[1] = new FillBox() }, 247 new Drawable[] { boxes[2] = new FillBox() }, 248 }, new[] 249 { 250 new Dimension(GridSizeMode.Relative, sizes[0]), 251 new Dimension(GridSizeMode.Absolute, sizes[1]), 252 new Dimension(), 253 }, row); 254 255 if (row) 256 { 257 AddAssert("box 0 has correct size", () => Precision.AlmostEquals(boxes[0].DrawSize, new Vector2(grid.DrawWidth, sizes[0] * grid.DrawHeight))); 258 AddAssert("box 1 has correct size", () => Precision.AlmostEquals(boxes[1].DrawSize, new Vector2(grid.DrawWidth, sizes[1]))); 259 AddAssert("box 2 has correct size", () => Precision.AlmostEquals(boxes[2].DrawSize, new Vector2(grid.DrawWidth, grid.DrawHeight - boxes[0].DrawHeight - boxes[1].DrawHeight))); 260 } 261 else 262 { 263 AddAssert("box 0 has correct size", () => Precision.AlmostEquals(boxes[0].DrawSize, new Vector2(sizes[0] * grid.DrawWidth, grid.DrawHeight))); 264 AddAssert("box 1 has correct size", () => Precision.AlmostEquals(boxes[1].DrawSize, new Vector2(sizes[1], grid.DrawHeight))); 265 AddAssert("box 2 has correct size", () => Precision.AlmostEquals(boxes[2].DrawSize, new Vector2(grid.DrawWidth - boxes[0].DrawWidth - boxes[1].DrawWidth, grid.DrawHeight))); 266 } 267 } 268 269 [Test] 270 public void Test3X3GridDistributedXy() 271 { 272 var boxes = new FillBox[9]; 273 274 AddStep("set content", () => 275 { 276 grid.Content = new[] 277 { 278 new Drawable[] { boxes[0] = new FillBox(), boxes[1] = new FillBox(), boxes[2] = new FillBox() }, 279 new Drawable[] { boxes[3] = new FillBox(), boxes[4] = new FillBox(), boxes[5] = new FillBox() }, 280 new Drawable[] { boxes[6] = new FillBox(), boxes[7] = new FillBox(), boxes[8] = new FillBox() } 281 }; 282 }); 283 284 for (int i = 0; i < 9; i++) 285 { 286 int local = i; 287 AddAssert($"box {local} has correct size", () => Precision.AlmostEquals(grid.DrawSize / 3f, boxes[local].DrawSize)); 288 } 289 } 290 291 [Test] 292 public void Test3X3GridAbsoluteXy() 293 { 294 var boxes = new FillBox[9]; 295 296 var dimensions = new[] 297 { 298 new Dimension(GridSizeMode.Absolute, 50), 299 new Dimension(GridSizeMode.Absolute, 100), 300 new Dimension(GridSizeMode.Absolute, 75) 301 }; 302 303 AddStep("set content", () => 304 { 305 grid.Content = new[] 306 { 307 new Drawable[] { boxes[0] = new FillBox(), boxes[1] = new FillBox(), boxes[2] = new FillBox() }, 308 new Drawable[] { boxes[3] = new FillBox(), boxes[4] = new FillBox(), boxes[5] = new FillBox() }, 309 new Drawable[] { boxes[6] = new FillBox(), boxes[7] = new FillBox(), boxes[8] = new FillBox() } 310 }; 311 312 grid.RowDimensions = grid.ColumnDimensions = dimensions; 313 }); 314 315 for (int i = 0; i < 9; i++) 316 { 317 int local = i; 318 AddAssert($"box {local} has correct size", () => Precision.AlmostEquals(new Vector2(dimensions[local % 3].Size, dimensions[local / 3].Size), boxes[local].DrawSize)); 319 } 320 } 321 322 [Test] 323 public void Test3X3GridRelativeXy() 324 { 325 var boxes = new FillBox[9]; 326 327 var dimensions = new[] 328 { 329 new Dimension(GridSizeMode.Relative, 0.2f), 330 new Dimension(GridSizeMode.Relative, 0.4f), 331 new Dimension(GridSizeMode.Relative, 0.2f) 332 }; 333 334 AddStep("set content", () => 335 { 336 grid.Content = new[] 337 { 338 new Drawable[] { boxes[0] = new FillBox(), boxes[1] = new FillBox(), boxes[2] = new FillBox() }, 339 new Drawable[] { boxes[3] = new FillBox(), boxes[4] = new FillBox(), boxes[5] = new FillBox() }, 340 new Drawable[] { boxes[6] = new FillBox(), boxes[7] = new FillBox(), boxes[8] = new FillBox() } 341 }; 342 343 grid.RowDimensions = grid.ColumnDimensions = dimensions; 344 }); 345 346 for (int i = 0; i < 9; i++) 347 { 348 int local = i; 349 AddAssert($"box {local} has correct size", 350 () => Precision.AlmostEquals(new Vector2(dimensions[local % 3].Size * grid.DrawWidth, dimensions[local / 3].Size * grid.DrawHeight), boxes[local].DrawSize)); 351 } 352 } 353 354 [Test] 355 public void Test3X3GridMixedXy() 356 { 357 var boxes = new FillBox[9]; 358 359 var dimensions = new[] 360 { 361 new Dimension(GridSizeMode.Absolute, 50), 362 new Dimension(GridSizeMode.Relative, 0.2f) 363 }; 364 365 AddStep("set content", () => 366 { 367 grid.Content = new[] 368 { 369 new Drawable[] { boxes[0] = new FillBox(), boxes[1] = new FillBox(), boxes[2] = new FillBox() }, 370 new Drawable[] { boxes[3] = new FillBox(), boxes[4] = new FillBox(), boxes[5] = new FillBox() }, 371 new Drawable[] { boxes[6] = new FillBox(), boxes[7] = new FillBox(), boxes[8] = new FillBox() } 372 }; 373 374 grid.RowDimensions = grid.ColumnDimensions = dimensions; 375 }); 376 377 // Row 1 378 AddAssert("box 0 has correct size", () => Precision.AlmostEquals(boxes[0].DrawSize, new Vector2(dimensions[0].Size, dimensions[0].Size))); 379 AddAssert("box 1 has correct size", () => Precision.AlmostEquals(boxes[1].DrawSize, new Vector2(grid.DrawWidth * dimensions[1].Size, dimensions[0].Size))); 380 AddAssert("box 2 has correct size", () => Precision.AlmostEquals(boxes[2].DrawSize, new Vector2(grid.DrawWidth - boxes[0].DrawWidth - boxes[1].DrawWidth, dimensions[0].Size))); 381 382 // Row 2 383 AddAssert("box 3 has correct size", () => Precision.AlmostEquals(boxes[3].DrawSize, new Vector2(dimensions[0].Size, grid.DrawHeight * dimensions[1].Size))); 384 AddAssert("box 4 has correct size", () => Precision.AlmostEquals(boxes[4].DrawSize, new Vector2(grid.DrawWidth * dimensions[1].Size, grid.DrawHeight * dimensions[1].Size))); 385 AddAssert("box 5 has correct size", 386 () => Precision.AlmostEquals(boxes[5].DrawSize, new Vector2(grid.DrawWidth - boxes[0].DrawWidth - boxes[1].DrawWidth, grid.DrawHeight * dimensions[1].Size))); 387 388 // Row 3 389 AddAssert("box 6 has correct size", () => Precision.AlmostEquals(boxes[6].DrawSize, new Vector2(dimensions[0].Size, grid.DrawHeight - boxes[3].DrawHeight - boxes[0].DrawHeight))); 390 AddAssert("box 7 has correct size", 391 () => Precision.AlmostEquals(boxes[7].DrawSize, new Vector2(grid.DrawWidth * dimensions[1].Size, grid.DrawHeight - boxes[4].DrawHeight - boxes[1].DrawHeight))); 392 AddAssert("box 8 has correct size", 393 () => Precision.AlmostEquals(boxes[8].DrawSize, new Vector2(grid.DrawWidth - boxes[0].DrawWidth - boxes[1].DrawWidth, grid.DrawHeight - boxes[5].DrawHeight - boxes[2].DrawHeight))); 394 } 395 396 [Test] 397 public void TestGridWithNullRowsAndColumns() 398 { 399 var boxes = new FillBox[4]; 400 401 AddStep("set content", () => 402 { 403 grid.Content = new[] 404 { 405 new Drawable[] { boxes[0] = new FillBox(), null, boxes[1] = new FillBox(), null }, 406 null, 407 new Drawable[] { boxes[2] = new FillBox(), null, boxes[3] = new FillBox(), null }, 408 null 409 }; 410 }); 411 412 AddAssert("two extra rows and columns", () => 413 { 414 for (int i = 0; i < 4; i++) 415 { 416 if (!Precision.AlmostEquals(boxes[i].DrawSize, grid.DrawSize / 4)) 417 return false; 418 } 419 420 return true; 421 }); 422 } 423 424 [Test] 425 public void TestNestedGrids() 426 { 427 var boxes = new FillBox[4]; 428 429 AddStep("set content", () => 430 { 431 grid.Content = new[] 432 { 433 new Drawable[] 434 { 435 new GridContainer 436 { 437 RelativeSizeAxes = Axes.Both, 438 Content = new[] 439 { 440 new Drawable[] { boxes[0] = new FillBox(), new FillBox(), }, 441 new Drawable[] { new FillBox(), boxes[1] = new FillBox(), }, 442 } 443 }, 444 new FillBox(), 445 }, 446 new Drawable[] 447 { 448 new FillBox(), 449 new GridContainer 450 { 451 RelativeSizeAxes = Axes.Both, 452 Content = new[] 453 { 454 new Drawable[] { boxes[2] = new FillBox(), new FillBox(), }, 455 new Drawable[] { new FillBox(), boxes[3] = new FillBox(), }, 456 } 457 } 458 } 459 }; 460 }); 461 462 for (int i = 0; i < 4; i++) 463 { 464 int local = i; 465 AddAssert($"box {local} has correct size", () => Precision.AlmostEquals(boxes[local].DrawSize, grid.DrawSize / 4)); 466 } 467 } 468 469 [Test] 470 public void TestGridWithAutoSizingCells() 471 { 472 FillBox fillBox = null; 473 var autoSizingChildren = new Drawable[2]; 474 475 AddStep("set content", () => 476 { 477 grid.Content = new[] 478 { 479 new[] 480 { 481 autoSizingChildren[0] = new Box 482 { 483 Anchor = Anchor.Centre, 484 Origin = Anchor.Centre, 485 Size = new Vector2(50, 10) 486 }, 487 fillBox = new FillBox(), 488 }, 489 new[] 490 { 491 null, 492 autoSizingChildren[1] = new Box 493 { 494 Anchor = Anchor.Centre, 495 Origin = Anchor.Centre, 496 Size = new Vector2(50, 10) 497 }, 498 }, 499 }; 500 501 grid.ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }; 502 grid.RowDimensions = new[] 503 { 504 new Dimension(), 505 new Dimension(GridSizeMode.AutoSize), 506 }; 507 }); 508 509 AddAssert("fill box has correct size", () => Precision.AlmostEquals(fillBox.DrawSize, new Vector2(grid.DrawWidth - 50, grid.DrawHeight - 10))); 510 AddStep("rotate boxes", () => autoSizingChildren.ForEach(c => c.RotateTo(90))); 511 AddAssert("fill box has resized correctly", () => Precision.AlmostEquals(fillBox.DrawSize, new Vector2(grid.DrawWidth - 10, grid.DrawHeight - 50))); 512 } 513 514 [TestCase(false)] 515 [TestCase(true)] 516 public void TestDimensionsWithMaximumSize(bool row) 517 { 518 var boxes = new FillBox[8]; 519 520 var dimensions = new[] 521 { 522 new Dimension(), 523 new Dimension(GridSizeMode.Absolute, 100), 524 new Dimension(GridSizeMode.Distributed, maxSize: 100), 525 new Dimension(), 526 new Dimension(GridSizeMode.Distributed, maxSize: 50), 527 new Dimension(GridSizeMode.Absolute, 100), 528 new Dimension(GridSizeMode.Distributed, maxSize: 80), 529 new Dimension(GridSizeMode.Distributed, maxSize: 150) 530 }; 531 532 setSingleDimensionContent(() => new[] 533 { 534 new Drawable[] 535 { 536 boxes[0] = new FillBox(), 537 boxes[1] = new FillBox(), 538 boxes[2] = new FillBox(), 539 boxes[3] = new FillBox(), 540 boxes[4] = new FillBox(), 541 boxes[5] = new FillBox(), 542 boxes[6] = new FillBox(), 543 boxes[7] = new FillBox() 544 }, 545 }.Invert(), dimensions, row); 546 547 checkClampedSizes(row, boxes, dimensions); 548 } 549 550 [TestCase(false)] 551 [TestCase(true)] 552 public void TestDimensionsWithMinimumSize(bool row) 553 { 554 var boxes = new FillBox[8]; 555 556 var dimensions = new[] 557 { 558 new Dimension(), 559 new Dimension(GridSizeMode.Absolute, 100), 560 new Dimension(GridSizeMode.Distributed, minSize: 100), 561 new Dimension(), 562 new Dimension(GridSizeMode.Distributed, minSize: 50), 563 new Dimension(GridSizeMode.Absolute, 100), 564 new Dimension(GridSizeMode.Distributed, minSize: 80), 565 new Dimension(GridSizeMode.Distributed, minSize: 150) 566 }; 567 568 setSingleDimensionContent(() => new[] 569 { 570 new Drawable[] 571 { 572 boxes[0] = new FillBox(), 573 boxes[1] = new FillBox(), 574 boxes[2] = new FillBox(), 575 boxes[3] = new FillBox(), 576 boxes[4] = new FillBox(), 577 boxes[5] = new FillBox(), 578 boxes[6] = new FillBox(), 579 boxes[7] = new FillBox() 580 }, 581 }.Invert(), dimensions, row); 582 583 checkClampedSizes(row, boxes, dimensions); 584 } 585 586 [TestCase(false)] 587 [TestCase(true)] 588 public void TestDimensionsWithMinimumAndMaximumSize(bool row) 589 { 590 var boxes = new FillBox[8]; 591 592 var dimensions = new[] 593 { 594 new Dimension(), 595 new Dimension(GridSizeMode.Absolute, 100), 596 new Dimension(GridSizeMode.Distributed, minSize: 100), 597 new Dimension(), 598 new Dimension(GridSizeMode.Distributed, maxSize: 50), 599 new Dimension(GridSizeMode.Absolute, 100), 600 new Dimension(GridSizeMode.Distributed, minSize: 80), 601 new Dimension(GridSizeMode.Distributed, maxSize: 150) 602 }; 603 604 setSingleDimensionContent(() => new[] 605 { 606 new Drawable[] 607 { 608 boxes[0] = new FillBox(), 609 boxes[1] = new FillBox(), 610 boxes[2] = new FillBox(), 611 boxes[3] = new FillBox(), 612 boxes[4] = new FillBox(), 613 boxes[5] = new FillBox(), 614 boxes[6] = new FillBox(), 615 boxes[7] = new FillBox() 616 }, 617 }.Invert(), dimensions, row); 618 619 checkClampedSizes(row, boxes, dimensions); 620 } 621 622 [Test] 623 public void TestCombinedMinimumAndMaximumSize() 624 { 625 AddStep("set content", () => 626 { 627 gridParent.Masking = false; 628 gridParent.RelativeSizeAxes = Axes.Y; 629 gridParent.Width = 420; 630 631 grid.Content = new[] 632 { 633 new Drawable[] 634 { 635 new FillBox(), 636 new FillBox(), 637 new FillBox(), 638 }, 639 }; 640 641 grid.ColumnDimensions = new[] 642 { 643 new Dimension(GridSizeMode.Distributed, minSize: 180), 644 new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70), 645 new Dimension(GridSizeMode.Distributed, minSize: 40, maxSize: 70), 646 }; 647 }); 648 649 AddAssert("content spans grid size", () => Precision.AlmostEquals(grid.DrawWidth, grid.Content[0].Sum(d => d.DrawWidth))); 650 } 651 652 [Test] 653 public void TestCombinedMinimumAndMaximumSize2() 654 { 655 AddStep("set content", () => 656 { 657 gridParent.Masking = false; 658 gridParent.RelativeSizeAxes = Axes.Y; 659 gridParent.Width = 230; 660 661 grid.Content = new[] 662 { 663 new Drawable[] 664 { 665 new FillBox(), 666 new FillBox(), 667 }, 668 }; 669 670 grid.ColumnDimensions = new[] 671 { 672 new Dimension(GridSizeMode.Distributed, minSize: 180), 673 new Dimension(GridSizeMode.Distributed, minSize: 40, maxSize: 70), 674 }; 675 }); 676 677 AddAssert("content spans grid size", () => Precision.AlmostEquals(grid.DrawWidth, grid.Content[0].Sum(d => d.DrawWidth))); 678 } 679 680 [TestCase(true)] 681 [TestCase(false)] 682 public void TestAutoSizedCellsWithTransparentContent(bool alwaysPresent) 683 { 684 AddStep("set content", () => 685 { 686 grid.RowDimensions = new[] 687 { 688 new Dimension(), 689 new Dimension(), 690 new Dimension(GridSizeMode.AutoSize) 691 }; 692 grid.ColumnDimensions = new[] 693 { 694 new Dimension(), 695 new Dimension(GridSizeMode.AutoSize), 696 new Dimension() 697 }; 698 grid.Content = new[] 699 { 700 new Drawable[] { new FillBox(), transparentBox(alwaysPresent), new FillBox() }, 701 new Drawable[] { new FillBox(), transparentBox(alwaysPresent), new FillBox() }, 702 new Drawable[] { transparentBox(alwaysPresent), transparentBox(alwaysPresent), transparentBox(alwaysPresent) } 703 }; 704 }); 705 706 float desiredTransparentBoxSize = alwaysPresent ? 50 : 0; 707 AddAssert("non-transparent fill boxes have correct size", () => 708 grid.Content 709 .SelectMany(row => row) 710 .Where(box => box.Alpha > 0) 711 .All(box => Precision.AlmostEquals(box.DrawWidth, (grid.DrawWidth - desiredTransparentBoxSize) / 2) 712 && Precision.AlmostEquals(box.DrawHeight, (grid.DrawHeight - desiredTransparentBoxSize) / 2))); 713 } 714 715 [TestCase(true)] 716 [TestCase(false)] 717 public void TestAutoSizedRowOrColumnWithTransparentContent(bool row) 718 { 719 var boxes = new FillBox[5]; 720 721 var dimensions = new[] 722 { 723 new Dimension(GridSizeMode.Absolute, 100f), 724 new Dimension(), 725 new Dimension(GridSizeMode.AutoSize), 726 new Dimension(GridSizeMode.Relative, 0.2f), 727 new Dimension() 728 }; 729 730 setSingleDimensionContent(() => new[] 731 { 732 new Drawable[] 733 { 734 boxes[0] = new FillBox(), 735 boxes[1] = new FillBox(), 736 boxes[2] = transparentBox(false), 737 boxes[3] = new FillBox(), 738 boxes[4] = new FillBox() 739 } 740 }.Invert(), dimensions, row); 741 742 AddAssert("box 0 has correct size", () => Precision.AlmostEquals(getDimension(boxes[0], row), 100f)); 743 AddAssert("box 1 has correct size", () => 744 Precision.AlmostEquals(getDimension(boxes[1], row), (getDimension(grid, row) * 0.8f - 100f) / 2)); 745 AddAssert("box 3 has correct size", () => Precision.AlmostEquals(getDimension(boxes[3], row), getDimension(grid, row) * 0.2f)); 746 AddAssert("box 4 has correct size", () => 747 Precision.AlmostEquals(getDimension(boxes[4], row), (getDimension(grid, row) * 0.8f - 100f) / 2)); 748 } 749 750 private FillBox transparentBox(bool alwaysPresent) => new FillBox 751 { 752 Alpha = 0, 753 AlwaysPresent = alwaysPresent, 754 RelativeSizeAxes = Axes.None, 755 Size = new Vector2(50) 756 }; 757 758 [TestCase(true)] 759 [TestCase(false)] 760 public void TestAutoSizedRowOrColumnWithDelayedLifetimeContent(bool row) 761 { 762 var boxes = new FillBox[3]; 763 764 var dimensions = new[] 765 { 766 new Dimension(GridSizeMode.Absolute, 75f), 767 new Dimension(GridSizeMode.AutoSize), 768 new Dimension() 769 }; 770 771 setSingleDimensionContent(() => new[] 772 { 773 new Drawable[] 774 { 775 boxes[0] = new FillBox(), 776 boxes[1] = new FillBox 777 { 778 RelativeSizeAxes = Axes.None, 779 LifetimeStart = double.MaxValue, 780 Size = new Vector2(50) 781 }, 782 boxes[2] = new FillBox() 783 } 784 }.Invert(), dimensions, row); 785 786 AddAssert("box 0 has correct size", () => Precision.AlmostEquals(getDimension(boxes[0], row), 75f)); 787 AddAssert("box 2 has correct size", () => Precision.AlmostEquals(getDimension(boxes[2], row), getDimension(grid, row) - 75f)); 788 789 AddStep("make box 1 alive", () => boxes[1].LifetimeStart = Time.Current); 790 AddUntilStep("wait for alive", () => boxes[1].IsAlive); 791 792 AddAssert("box 0 has correct size", () => Precision.AlmostEquals(getDimension(boxes[0], row), 75f)); 793 AddAssert("box 2 has correct size", () => Precision.AlmostEquals(getDimension(boxes[2], row), getDimension(grid, row) - 125f)); 794 } 795 796 private bool gridContentChangeEventWasFired; 797 798 [Test] 799 public void TestSetContentByIndex() 800 { 801 setSingleDimensionContent(() => new[] 802 { 803 new Drawable[] 804 { 805 new FillBox(), 806 new FillBox() 807 }, 808 new Drawable[] 809 { 810 new FillBox(), 811 new FillBox() 812 } 813 }); 814 815 AddStep("Subscribe to event", () => grid.Content.ArrayElementChanged += () => gridContentChangeEventWasFired = true); 816 817 AddStep("Replace bottom right box with a SpriteText", () => 818 { 819 gridContentChangeEventWasFired = false; 820 grid.Content[1][1] = new SpriteText { Text = "test" }; 821 }); 822 assertContentChangeEventWasFired(); 823 AddAssert("[1][1] cell contains a SpriteText", () => grid.Content[1][1].GetType() == typeof(SpriteText)); 824 825 AddStep("Replace top line with [SpriteText][null]", () => 826 { 827 gridContentChangeEventWasFired = false; 828 grid.Content[0] = new Drawable[] { new SpriteText { Text = "test" }, null }; 829 }); 830 assertContentChangeEventWasFired(); 831 AddAssert("[0][0] cell contains a SpriteText", () => grid.Content[0][0].GetType() == typeof(SpriteText)); 832 AddAssert("[0][1] cell contains null", () => grid.Content[0][1] == null); 833 834 void assertContentChangeEventWasFired() => AddAssert("Content change event was fired", () => gridContentChangeEventWasFired); 835 } 836 837 /// <summary> 838 /// Returns drawable dimension along desired axis. 839 /// </summary> 840 private float getDimension(Drawable drawable, bool row) => row ? drawable.DrawHeight : drawable.DrawWidth; 841 842 private void checkClampedSizes(bool row, FillBox[] boxes, Dimension[] dimensions) 843 { 844 AddAssert("sizes not over/underflowed", () => 845 { 846 for (int i = 0; i < 8; i++) 847 { 848 if (dimensions[i].Mode != GridSizeMode.Distributed) 849 continue; 850 851 if (row && (boxes[i].DrawHeight > dimensions[i].MaxSize || boxes[i].DrawHeight < dimensions[i].MinSize)) 852 return false; 853 854 if (!row && (boxes[i].DrawWidth > dimensions[i].MaxSize || boxes[i].DrawWidth < dimensions[i].MinSize)) 855 return false; 856 } 857 858 return true; 859 }); 860 861 AddAssert("column span total length", () => 862 { 863 float expectedSize = row ? grid.DrawHeight : grid.DrawWidth; 864 float totalSize = row ? boxes.Sum(b => b.DrawHeight) : boxes.Sum(b => b.DrawWidth); 865 866 // Allowed to exceed the length of the columns due to absolute sizing 867 return totalSize >= expectedSize; 868 }); 869 } 870 871 private void setSingleDimensionContent(Func<Drawable[][]> contentFunc, Dimension[] dimensions = null, bool row = false) => AddStep("set content", () => 872 { 873 var content = contentFunc(); 874 875 if (!row) 876 content = content.Invert(); 877 878 grid.Content = content; 879 880 if (dimensions == null) 881 return; 882 883 if (row) 884 grid.RowDimensions = dimensions; 885 else 886 grid.ColumnDimensions = dimensions; 887 }); 888 889 private class FillBox : Box 890 { 891 public FillBox() 892 { 893 RelativeSizeAxes = Axes.Both; 894 Colour = new Color4(RNG.NextSingle(1), RNG.NextSingle(1), RNG.NextSingle(1), 1); 895 } 896 } 897 } 898}