diff options
-rw-r--r-- | DevTools/HackStudio/CursorTool.cpp | 2 | ||||
-rw-r--r-- | DevTools/HackStudio/FormEditorWidget.cpp | 7 | ||||
-rw-r--r-- | DevTools/HackStudio/FormEditorWidget.h | 5 | ||||
-rw-r--r-- | DevTools/HackStudio/Makefile | 1 | ||||
-rw-r--r-- | DevTools/HackStudio/WidgetTreeModel.cpp | 77 | ||||
-rw-r--r-- | DevTools/HackStudio/WidgetTreeModel.h | 23 | ||||
-rw-r--r-- | DevTools/HackStudio/main.cpp | 7 |
7 files changed, 121 insertions, 1 deletions
diff --git a/DevTools/HackStudio/CursorTool.cpp b/DevTools/HackStudio/CursorTool.cpp index 643f9ef701..98742d448b 100644 --- a/DevTools/HackStudio/CursorTool.cpp +++ b/DevTools/HackStudio/CursorTool.cpp @@ -1,6 +1,7 @@ #include "CursorTool.h" #include "FormEditorWidget.h" #include "FormWidget.h" +#include "WidgetTreeModel.h" #include <AK/LogStream.h> void CursorTool::on_mousedown(GMouseEvent& event) @@ -78,6 +79,7 @@ void CursorTool::on_mousemove(GMouseEvent& event) widget.set_relative_rect(new_rect); return IterationDecision::Continue; }); + m_editor.model().update(); return; } } diff --git a/DevTools/HackStudio/FormEditorWidget.cpp b/DevTools/HackStudio/FormEditorWidget.cpp index 894454b2d9..c1e382566b 100644 --- a/DevTools/HackStudio/FormEditorWidget.cpp +++ b/DevTools/HackStudio/FormEditorWidget.cpp @@ -1,6 +1,7 @@ #include "FormEditorWidget.h" #include "CursorTool.h" #include "FormWidget.h" +#include "WidgetTreeModel.h" #include <LibGUI/GPainter.h> FormEditorWidget::FormEditorWidget(GWidget* parent) @@ -15,6 +16,7 @@ FormEditorWidget::FormEditorWidget(GWidget* parent) set_frame_thickness(2); m_form_widget = FormWidget::construct(*this); + m_widget_tree_model = WidgetTreeModel::create(*m_form_widget); } FormEditorWidget::~FormEditorWidget() @@ -35,3 +37,8 @@ void FormEditorWidget::set_tool(NonnullOwnPtr<Tool> tool) m_tool = move(tool); m_tool->attach(); } + +WidgetTreeModel& FormEditorWidget::model() +{ + return *m_widget_tree_model; +} diff --git a/DevTools/HackStudio/FormEditorWidget.h b/DevTools/HackStudio/FormEditorWidget.h index cc2d9e66cd..04758ab263 100644 --- a/DevTools/HackStudio/FormEditorWidget.h +++ b/DevTools/HackStudio/FormEditorWidget.h @@ -4,6 +4,7 @@ class FormWidget; class Tool; +class WidgetTreeModel; class FormEditorWidget final : public GScrollableWidget { C_OBJECT(FormEditorWidget) @@ -18,6 +19,8 @@ public: void set_tool(NonnullOwnPtr<Tool>); + WidgetTreeModel& model(); + class WidgetSelection { public: bool is_empty() const @@ -70,6 +73,7 @@ public: } WidgetSelection() {} + private: HashTable<GWidget*> m_widgets; }; @@ -82,6 +86,7 @@ private: explicit FormEditorWidget(GWidget* parent); RefPtr<FormWidget> m_form_widget; + RefPtr<WidgetTreeModel> m_widget_tree_model; NonnullOwnPtr<Tool> m_tool; WidgetSelection m_selection; }; diff --git a/DevTools/HackStudio/Makefile b/DevTools/HackStudio/Makefile index ca2c4fabec..e4bc07f538 100644 --- a/DevTools/HackStudio/Makefile +++ b/DevTools/HackStudio/Makefile @@ -15,6 +15,7 @@ OBJS = \ Tool.o \ CursorTool.o \ WidgetTool.o \ + WidgetTreeModel.o \ main.o APP = HackStudio diff --git a/DevTools/HackStudio/WidgetTreeModel.cpp b/DevTools/HackStudio/WidgetTreeModel.cpp new file mode 100644 index 0000000000..a2740da185 --- /dev/null +++ b/DevTools/HackStudio/WidgetTreeModel.cpp @@ -0,0 +1,77 @@ +#include "WidgetTreeModel.h" +#include <AK/StringBuilder.h> +#include <LibGUI/GWidget.h> +#include <stdio.h> + +WidgetTreeModel::WidgetTreeModel(GWidget& root) + : m_root(root) +{ + m_widget_icon.set_bitmap_for_size(16, GraphicsBitmap::load_from_file("/res/icons/16x16/inspector-object.png")); +} + +WidgetTreeModel::~WidgetTreeModel() +{ +} + +GModelIndex WidgetTreeModel::index(int row, int column, const GModelIndex& parent) const +{ + if (!parent.is_valid()) { + return create_index(row, column, m_root.ptr()); + } + auto& parent_node = *static_cast<GWidget*>(parent.internal_data()); + return create_index(row, column, parent_node.child_widgets().at(row)); +} + +GModelIndex WidgetTreeModel::parent_index(const GModelIndex& index) const +{ + if (!index.is_valid()) + return {}; + auto& widget = *static_cast<GWidget*>(index.internal_data()); + if (&widget == m_root.ptr()) + return {}; + + if (widget.parent_widget() == m_root.ptr()) + return create_index(0, 0, m_root.ptr()); + + // Walk the grandparent's children to find the index of widget's parent in its parent. + // (This is needed to produce the row number of the GModelIndex corresponding to widget's parent.) + int grandparent_child_index = 0; + for (auto& grandparent_child : widget.parent_widget()->parent_widget()->child_widgets()) { + if (grandparent_child == widget.parent_widget()) + return create_index(grandparent_child_index, 0, widget.parent_widget()); + ++grandparent_child_index; + } + + ASSERT_NOT_REACHED(); + return {}; +} + +int WidgetTreeModel::row_count(const GModelIndex& index) const +{ + if (!index.is_valid()) + return 1; + auto& widget = *static_cast<GWidget*>(index.internal_data()); + return widget.child_widgets().size(); +} + +int WidgetTreeModel::column_count(const GModelIndex&) const +{ + return 1; +} + +GVariant WidgetTreeModel::data(const GModelIndex& index, Role role) const +{ + auto* widget = static_cast<GWidget*>(index.internal_data()); + if (role == Role::Icon) { + return m_widget_icon; + } + if (role == Role::Display) { + return String::format("%s (%s)", widget->class_name(), widget->relative_rect().to_string().characters()); + } + return {}; +} + +void WidgetTreeModel::update() +{ + did_update(); +} diff --git a/DevTools/HackStudio/WidgetTreeModel.h b/DevTools/HackStudio/WidgetTreeModel.h new file mode 100644 index 0000000000..10a81da3fa --- /dev/null +++ b/DevTools/HackStudio/WidgetTreeModel.h @@ -0,0 +1,23 @@ +#pragma once + +#include <LibGUI/GModel.h> +#include <LibGUI/GPainter.h> + +class WidgetTreeModel final : public GModel { +public: + static NonnullRefPtr<WidgetTreeModel> create(GWidget& root) { return adopt(*new WidgetTreeModel(root)); } + virtual ~WidgetTreeModel() override; + + virtual int row_count(const GModelIndex& = GModelIndex()) const override; + virtual int column_count(const GModelIndex& = GModelIndex()) const override; + virtual GVariant data(const GModelIndex&, Role = Role::Display) const override; + virtual GModelIndex index(int row, int column, const GModelIndex& parent = GModelIndex()) const override; + virtual GModelIndex parent_index(const GModelIndex&) const override; + virtual void update() override; + +private: + explicit WidgetTreeModel(GWidget&); + + NonnullRefPtr<GWidget> m_root; + GIcon m_widget_icon; +}; diff --git a/DevTools/HackStudio/main.cpp b/DevTools/HackStudio/main.cpp index 0391ee3dc3..e3f870d7d4 100644 --- a/DevTools/HackStudio/main.cpp +++ b/DevTools/HackStudio/main.cpp @@ -9,6 +9,7 @@ #include "Project.h" #include "TerminalWrapper.h" #include "WidgetTool.h" +#include "WidgetTreeModel.h" #include <LibCore/CFile.h> #include <LibGUI/GAboutDialog.h> #include <LibGUI/GAction.h> @@ -149,6 +150,7 @@ int main(int argc, char** argv) g_form_editor_widget->set_tool(make<WidgetTool>(*g_form_editor_widget, reg)); auto widget = reg.construct(&g_form_editor_widget->form_widget()); widget->set_relative_rect(30, 30, 30, 30); + g_form_editor_widget->model().update(); }); action->set_checkable(true); action->set_checked(false); @@ -177,7 +179,10 @@ int main(int argc, char** argv) wrapper->add_child(pane_widget); }; - add_properties_pane("Form widget tree:", GTreeView::construct(nullptr)); + auto form_widget_tree_view = GTreeView::construct(nullptr); + form_widget_tree_view->set_model(g_form_editor_widget->model()); + + add_properties_pane("Form widget tree:", form_widget_tree_view); add_properties_pane("Widget properties:", GTableView::construct(nullptr)); g_text_inner_splitter = GSplitter::construct(Orientation::Vertical, g_right_hand_stack); |