BsDropDownAreaPlacement.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "GUI/BsDropDownAreaPlacement.h"
  4. #include "Debug/BsDebug.h"
  5. namespace bs
  6. {
  7. DropDownAreaPlacement DropDownAreaPlacement::aroundPosition(const Vector2I& position)
  8. {
  9. DropDownAreaPlacement instance;
  10. instance.mType = Type::Position;
  11. instance.mPosition = position;
  12. return instance;
  13. }
  14. DropDownAreaPlacement DropDownAreaPlacement::aroundBoundsVert(const Rect2I& bounds)
  15. {
  16. DropDownAreaPlacement instance;
  17. instance.mType = Type::BoundsVert;
  18. instance.mBounds = bounds;
  19. return instance;
  20. }
  21. DropDownAreaPlacement DropDownAreaPlacement::aroundBoundsHorz(const Rect2I& bounds)
  22. {
  23. DropDownAreaPlacement instance;
  24. instance.mType = Type::BoundsHorz;
  25. instance.mBounds = bounds;
  26. return instance;
  27. }
  28. DropDownAreaPlacement DropDownAreaPlacement::aroundBounds(const Rect2I& bounds)
  29. {
  30. DropDownAreaPlacement instance;
  31. instance.mType = Type::BoundsAll;
  32. instance.mBounds = bounds;
  33. return instance;
  34. }
  35. Rect2I DropDownAreaPlacement::getOptimalBounds(UINT32 width, UINT32 height, const Rect2I& availableArea, HorzDir& horzDir, VertDir& vertDir) const
  36. {
  37. Rect2I output;
  38. int potentialLeftStart = 0;
  39. int potentialRightStart = 0;
  40. int potentialTopStart = 0;
  41. int potentialBottomStart = 0;
  42. switch (getType())
  43. {
  44. case DropDownAreaPlacement::Type::Position:
  45. potentialLeftStart = potentialRightStart = getPosition().x;
  46. potentialTopStart = potentialBottomStart = getPosition().y;
  47. break;
  48. case DropDownAreaPlacement::Type::BoundsHorz:
  49. potentialRightStart = getBounds().x;
  50. potentialLeftStart = getBounds().x + getBounds().width;
  51. potentialBottomStart = getBounds().y + getBounds().height;
  52. potentialTopStart = getBounds().y;
  53. break;
  54. case DropDownAreaPlacement::Type::BoundsVert:
  55. potentialRightStart = getBounds().x + getBounds().width;
  56. potentialLeftStart = getBounds().x;
  57. potentialBottomStart = getBounds().y;
  58. potentialTopStart = getBounds().y + getBounds().height;
  59. break;
  60. case DropDownAreaPlacement::Type::BoundsAll:
  61. potentialRightStart = getBounds().x + getBounds().width;
  62. potentialLeftStart = getBounds().x;
  63. potentialBottomStart = getBounds().y + getBounds().height;
  64. potentialTopStart = getBounds().y;
  65. break;
  66. }
  67. // Determine x position and whether to align to left or right side of the drop down list
  68. UINT32 availableRightwardWidth = (UINT32)std::max(0, (availableArea.x + (INT32)availableArea.width) - potentialRightStart);
  69. UINT32 availableLeftwardWidth = (UINT32)std::max(0, potentialLeftStart - availableArea.x);
  70. //// Prefer right if possible
  71. if (width <= availableRightwardWidth)
  72. {
  73. output.x = potentialRightStart;
  74. output.width = width;
  75. horzDir = HorzDir::Right;
  76. }
  77. else
  78. {
  79. if (availableRightwardWidth >= availableLeftwardWidth)
  80. {
  81. output.x = potentialRightStart;
  82. output.width = std::min(width, availableRightwardWidth);
  83. horzDir = HorzDir::Right;
  84. }
  85. else
  86. {
  87. output.x = potentialLeftStart - std::min(width, availableLeftwardWidth);
  88. output.width = std::min(width, availableLeftwardWidth);
  89. horzDir = HorzDir::Left;
  90. }
  91. }
  92. // Determine y position and whether to open upward or downward
  93. UINT32 availableDownwardHeight = (UINT32)std::max(0, (availableArea.y + (INT32)availableArea.height) - potentialBottomStart);
  94. UINT32 availableUpwardHeight = (UINT32)std::max(0, potentialTopStart - availableArea.y);
  95. //// Prefer down if possible
  96. if (height <= availableDownwardHeight)
  97. {
  98. output.y = potentialBottomStart;
  99. output.height = height;
  100. vertDir = VertDir::Down;
  101. }
  102. else
  103. {
  104. if (availableDownwardHeight >= availableUpwardHeight)
  105. {
  106. output.y = potentialBottomStart;
  107. output.height = std::min(height, availableDownwardHeight);;
  108. vertDir = VertDir::Down;
  109. }
  110. else
  111. {
  112. output.y = potentialTopStart - (INT32)std::min(height, availableUpwardHeight);
  113. output.height = std::min(height, availableUpwardHeight);
  114. vertDir = VertDir::Up;
  115. }
  116. }
  117. return output;
  118. }
  119. }