VBWidget.cpp 6.6 KB

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