VBWidget.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #include "VBWidget.h"
  2. #include "VBForm.h"
  3. #include "VBProperty.h"
  4. #include "VBWidgetPropertyModel.h"
  5. #include "VBWidgetRegistry.h"
  6. #include <LibGUI/GButton.h>
  7. #include <LibGUI/GCheckBox.h>
  8. #include <LibGUI/GGroupBox.h>
  9. #include <LibGUI/GLabel.h>
  10. #include <LibGUI/GPainter.h>
  11. #include <LibGUI/GProgressBar.h>
  12. #include <LibGUI/GRadioButton.h>
  13. #include <LibGUI/GScrollBar.h>
  14. #include <LibGUI/GSlider.h>
  15. #include <LibGUI/GSpinBox.h>
  16. #include <LibGUI/GTextEditor.h>
  17. VBWidget::VBWidget(VBWidgetType type, VBForm& form, VBWidget* parent)
  18. : m_type(type)
  19. , m_form(form)
  20. , m_property_model(VBWidgetPropertyModel::create(*this))
  21. {
  22. auto* widget_parent = parent ? parent->gwidget() : &form;
  23. m_gwidget = VBWidgetRegistry::build_gwidget(*this, type, widget_parent, m_properties);
  24. m_form.m_gwidget_map.set(m_gwidget, this);
  25. setup_properties();
  26. }
  27. VBWidget::~VBWidget()
  28. {
  29. m_form.m_gwidget_map.remove(m_gwidget);
  30. m_form.m_selected_widgets.remove(this);
  31. m_gwidget->parent()->remove_child(*m_gwidget);
  32. }
  33. Rect VBWidget::rect() const
  34. {
  35. return m_gwidget->window_relative_rect();
  36. }
  37. void VBWidget::set_rect(const Rect& rect)
  38. {
  39. if (rect == m_gwidget->window_relative_rect())
  40. return;
  41. auto new_window_relative_rect = rect;
  42. if (m_gwidget->parent())
  43. new_window_relative_rect.move_by(-m_gwidget->parent_widget()->window_relative_rect().location());
  44. m_gwidget->set_relative_rect(new_window_relative_rect);
  45. synchronize_properties();
  46. }
  47. bool VBWidget::is_selected() const
  48. {
  49. return m_form.is_selected(*this);
  50. }
  51. Rect VBWidget::grabber_rect(Direction direction) const
  52. {
  53. int grabber_size = 5;
  54. int half_grabber_size = grabber_size / 2;
  55. switch (direction) {
  56. case Direction::Left:
  57. return { rect().x() - half_grabber_size, rect().center().y() - half_grabber_size, grabber_size, grabber_size };
  58. case Direction::UpLeft:
  59. return { rect().x() - half_grabber_size, rect().y() - half_grabber_size, grabber_size, grabber_size };
  60. case Direction::Up:
  61. return { rect().center().x() - half_grabber_size, rect().y() - half_grabber_size, grabber_size, grabber_size };
  62. case Direction::UpRight:
  63. return { rect().right() - half_grabber_size, rect().y() - half_grabber_size, grabber_size, grabber_size };
  64. case Direction::Right:
  65. return { rect().right() - half_grabber_size, rect().center().y() - half_grabber_size, grabber_size, grabber_size };
  66. case Direction::DownLeft:
  67. return { rect().x() - half_grabber_size, rect().bottom() - half_grabber_size, grabber_size, grabber_size };
  68. case Direction::Down:
  69. return { rect().center().x() - half_grabber_size, rect().bottom() - half_grabber_size, grabber_size, grabber_size };
  70. case Direction::DownRight:
  71. return { rect().right() - half_grabber_size, rect().bottom() - half_grabber_size, grabber_size, grabber_size };
  72. default:
  73. ASSERT_NOT_REACHED();
  74. }
  75. }
  76. Direction VBWidget::grabber_at(const Point& position) const
  77. {
  78. Direction found_grabber = Direction::None;
  79. for_each_direction([&](Direction direction) {
  80. if (grabber_rect(direction).contains(position))
  81. found_grabber = direction;
  82. });
  83. return found_grabber;
  84. }
  85. void VBWidget::for_each_property(Function<void(VBProperty&)> callback)
  86. {
  87. for (auto& it : m_properties) {
  88. callback(it);
  89. }
  90. }
  91. void VBWidget::add_property(const String& name, Function<GVariant(const GWidget&)>&& getter, Function<void(GWidget&, const GVariant&)>&& setter)
  92. {
  93. auto& prop = property(name);
  94. prop.m_getter = move(getter);
  95. prop.m_setter = move(setter);
  96. }
  97. #define VB_ADD_PROPERTY(gclass, name, getter, setter, variant_type) \
  98. add_property( \
  99. name, \
  100. [](auto& widget) -> GVariant { return ((const gclass&)widget).getter(); }, \
  101. [](auto& widget, auto& value) { ((gclass&)widget).setter(value.to_##variant_type()); })
  102. void VBWidget::setup_properties()
  103. {
  104. VB_ADD_PROPERTY(CObject, "name", name, set_name, string);
  105. VB_ADD_PROPERTY(GWidget, "width", width, set_width, int);
  106. VB_ADD_PROPERTY(GWidget, "height", height, set_height, int);
  107. VB_ADD_PROPERTY(GWidget, "x", x, set_x, int);
  108. VB_ADD_PROPERTY(GWidget, "y", y, set_y, int);
  109. VB_ADD_PROPERTY(GWidget, "visible", is_visible, set_visible, bool);
  110. VB_ADD_PROPERTY(GWidget, "enabled", is_enabled, set_enabled, bool);
  111. VB_ADD_PROPERTY(GWidget, "tooltip", tooltip, set_tooltip, string);
  112. VB_ADD_PROPERTY(GWidget, "backcolor", background_color, set_background_color, color);
  113. VB_ADD_PROPERTY(GWidget, "forecolor", foreground_color, set_foreground_color, color);
  114. VB_ADD_PROPERTY(GWidget, "autofill", fill_with_background_color, set_fill_with_background_color, bool);
  115. if (m_type == VBWidgetType::GLabel) {
  116. VB_ADD_PROPERTY(GLabel, "text", text, set_text, string);
  117. }
  118. if (m_type == VBWidgetType::GButton) {
  119. VB_ADD_PROPERTY(GButton, "text", text, set_text, string);
  120. }
  121. if (m_type == VBWidgetType::GGroupBox) {
  122. VB_ADD_PROPERTY(GGroupBox, "title", title, set_title, string);
  123. }
  124. if (m_type == VBWidgetType::GScrollBar) {
  125. VB_ADD_PROPERTY(GScrollBar, "min", min, set_min, int);
  126. VB_ADD_PROPERTY(GScrollBar, "max", max, set_max, int);
  127. VB_ADD_PROPERTY(GScrollBar, "value", value, set_value, int);
  128. VB_ADD_PROPERTY(GScrollBar, "step", step, set_step, int);
  129. }
  130. if (m_type == VBWidgetType::GSpinBox) {
  131. VB_ADD_PROPERTY(GSpinBox, "min", min, set_min, int);
  132. VB_ADD_PROPERTY(GSpinBox, "max", max, set_max, int);
  133. VB_ADD_PROPERTY(GSpinBox, "value", value, set_value, int);
  134. }
  135. if (m_type == VBWidgetType::GProgressBar) {
  136. VB_ADD_PROPERTY(GProgressBar, "min", min, set_min, int);
  137. VB_ADD_PROPERTY(GProgressBar, "max", max, set_max, int);
  138. VB_ADD_PROPERTY(GProgressBar, "value", value, set_value, int);
  139. }
  140. if (m_type == VBWidgetType::GSlider) {
  141. VB_ADD_PROPERTY(GSlider, "min", min, set_min, int);
  142. VB_ADD_PROPERTY(GSlider, "max", max, set_max, int);
  143. VB_ADD_PROPERTY(GSlider, "value", value, set_value, int);
  144. }
  145. if (m_type == VBWidgetType::GTextEditor) {
  146. VB_ADD_PROPERTY(GTextEditor, "text", text, set_text, string);
  147. VB_ADD_PROPERTY(GTextEditor, "ruler_visible", is_ruler_visible, set_ruler_visible, bool);
  148. }
  149. if (m_type == VBWidgetType::GCheckBox) {
  150. VB_ADD_PROPERTY(GCheckBox, "text", text, set_text, string);
  151. VB_ADD_PROPERTY(GCheckBox, "checked", is_checked, set_checked, bool);
  152. }
  153. if (m_type == VBWidgetType::GRadioButton) {
  154. VB_ADD_PROPERTY(GRadioButton, "text", text, set_text, string);
  155. VB_ADD_PROPERTY(GRadioButton, "checked", is_checked, set_checked, bool);
  156. }
  157. }
  158. void VBWidget::synchronize_properties()
  159. {
  160. for (auto& prop : m_properties) {
  161. if (prop.m_getter)
  162. prop.m_value = prop.m_getter(*gwidget());
  163. }
  164. m_property_model->update();
  165. }
  166. VBProperty& VBWidget::property(const String& name)
  167. {
  168. for (auto& prop : m_properties) {
  169. if (prop.name() == name)
  170. return prop;
  171. }
  172. m_properties.append(make<VBProperty>(*this, name, GVariant()));
  173. return m_properties.last();
  174. }
  175. void VBWidget::property_did_change()
  176. {
  177. m_form.update();
  178. }
  179. void VBWidget::capture_transform_origin_rect()
  180. {
  181. m_transform_origin_rect = rect();
  182. }
  183. bool VBWidget::is_in_layout() const
  184. {
  185. if (auto* parent_widget = m_gwidget->parent_widget()) {
  186. if (parent_widget->layout())
  187. return true;
  188. }
  189. return false;
  190. }