Margins.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <LibGfx/Orientation.h>
  8. #include <LibGfx/Rect.h>
  9. namespace GUI {
  10. class Margins {
  11. public:
  12. Margins() = default;
  13. Margins(int all)
  14. : m_top(all)
  15. , m_right(all)
  16. , m_bottom(all)
  17. , m_left(all)
  18. {
  19. }
  20. Margins(int vertical, int horizontal)
  21. : m_top(vertical)
  22. , m_right(horizontal)
  23. , m_bottom(vertical)
  24. , m_left(horizontal)
  25. {
  26. }
  27. Margins(int top, int horizontal, int bottom)
  28. : m_top(top)
  29. , m_right(horizontal)
  30. , m_bottom(bottom)
  31. , m_left(horizontal)
  32. {
  33. }
  34. Margins(int top, int right, int bottom, int left)
  35. : m_top(top)
  36. , m_right(right)
  37. , m_bottom(bottom)
  38. , m_left(left)
  39. {
  40. }
  41. ~Margins() = default;
  42. [[nodiscard]] Gfx::IntRect applied_to(Gfx::IntRect const& input) const
  43. {
  44. Gfx::IntRect output = input;
  45. output.take_from_left(left());
  46. output.take_from_top(top());
  47. output.take_from_right(right());
  48. output.take_from_bottom(bottom());
  49. return output;
  50. }
  51. bool is_null() const { return !m_left && !m_top && !m_right && !m_bottom; }
  52. int top() const { return m_top; }
  53. int right() const { return m_right; }
  54. int bottom() const { return m_bottom; }
  55. int left() const { return m_left; }
  56. void set_top(int value) { m_top = value; }
  57. void set_right(int value) { m_right = value; }
  58. void set_bottom(int value) { m_bottom = value; }
  59. void set_left(int value) { m_left = value; }
  60. bool operator==(Margins const& other) const
  61. {
  62. return m_left == other.m_left
  63. && m_top == other.m_top
  64. && m_right == other.m_right
  65. && m_bottom == other.m_bottom;
  66. }
  67. Margins operator+(Margins const& other) const
  68. {
  69. return Margins { top() + other.top(), right() + other.right(), bottom() + other.bottom(), left() + other.left() };
  70. }
  71. [[nodiscard]] int primary_total_for_orientation(Gfx::Orientation const orientation) const
  72. {
  73. if (orientation == Gfx::Orientation::Horizontal)
  74. return m_left + m_right;
  75. else
  76. return m_top + m_bottom;
  77. }
  78. [[nodiscard]] int secondary_total_for_orientation(Gfx::Orientation const orientation) const
  79. {
  80. if (orientation == Gfx::Orientation::Vertical)
  81. return m_left + m_right;
  82. else
  83. return m_top + m_bottom;
  84. }
  85. [[nodiscard]] int horizontal_total() const
  86. {
  87. return m_left + m_right;
  88. }
  89. [[nodiscard]] int vertical_total() const
  90. {
  91. return m_top + m_bottom;
  92. }
  93. private:
  94. int m_top { 0 };
  95. int m_right { 0 };
  96. int m_bottom { 0 };
  97. int m_left { 0 };
  98. };
  99. }
  100. #define REGISTER_MARGINS_PROPERTY(property_name, getter, setter) \
  101. register_property( \
  102. property_name, [this]() { \
  103. auto m = getter(); \
  104. JsonObject margins_object; \
  105. margins_object.set("left", m.left()); \
  106. margins_object.set("right", m.right()); \
  107. margins_object.set("top", m.top()); \
  108. margins_object.set("bottom", m.bottom()); \
  109. return margins_object; }, \
  110. [this](auto& value) { \
  111. if (!value.is_array()) \
  112. return false; \
  113. auto size = value.as_array().size(); \
  114. if (size == 0 || size > 4) \
  115. return false; \
  116. int m[4]; \
  117. for (size_t i = 0; i < size; ++i) \
  118. m[i] = value.as_array().at(i).to_i32(); \
  119. if (size == 1) \
  120. setter({ m[0] }); \
  121. else if (size == 2) \
  122. setter({ m[0], m[1] }); \
  123. else if (size == 3) \
  124. setter({ m[0], m[1], m[2] }); \
  125. else \
  126. setter({ m[0], m[1], m[2], m[3] }); \
  127. return true; \
  128. });