From 2fea2386757ffb89e8394be785e24bfdc5bb867b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 11 Nov 2019 19:37:01 +0100 Subject: [PATCH] HackStudio: Reflect widget selections in the form widget tree view You can now manipulate the widget selection either by clicking and dragging the widgets using the cursor tool, or by interacting with the form widget tree view. :^) --- DevTools/HackStudio/FormEditorWidget.h | 14 +++++++++++++ DevTools/HackStudio/WidgetTreeModel.cpp | 11 +++++++++++ DevTools/HackStudio/WidgetTreeModel.h | 2 ++ DevTools/HackStudio/main.cpp | 26 +++++++++++++++++++++++-- 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/DevTools/HackStudio/FormEditorWidget.h b/DevTools/HackStudio/FormEditorWidget.h index 04758ab263..bfe557be33 100644 --- a/DevTools/HackStudio/FormEditorWidget.h +++ b/DevTools/HackStudio/FormEditorWidget.h @@ -23,6 +23,13 @@ public: class WidgetSelection { public: + Function on_remove; + Function on_add; + Function on_clear; + + void enable_hooks() { m_hooks_enabled = true; } + void disable_hooks() { m_hooks_enabled = false; } + bool is_empty() const { return m_widgets.is_empty(); @@ -51,16 +58,22 @@ public: { ASSERT(m_widgets.contains(&widget)); m_widgets.remove(&widget); + if (m_hooks_enabled && on_remove) + on_remove(widget); } void add(GWidget& widget) { m_widgets.set(&widget); + if (m_hooks_enabled && on_add) + on_add(widget); } void clear() { m_widgets.clear(); + if (m_hooks_enabled && on_clear) + on_clear(); } template @@ -76,6 +89,7 @@ public: private: HashTable m_widgets; + bool m_hooks_enabled { true }; }; WidgetSelection& selection() { return m_selection; } diff --git a/DevTools/HackStudio/WidgetTreeModel.cpp b/DevTools/HackStudio/WidgetTreeModel.cpp index a2740da185..130c666226 100644 --- a/DevTools/HackStudio/WidgetTreeModel.cpp +++ b/DevTools/HackStudio/WidgetTreeModel.cpp @@ -75,3 +75,14 @@ void WidgetTreeModel::update() { did_update(); } + +GModelIndex WidgetTreeModel::index_for_widget(GWidget& widget) const +{ + int parent_child_index = 0; + for (auto& parent_child : widget.parent_widget()->child_widgets()) { + if (parent_child == &widget) + return create_index(parent_child_index, 0, &widget); + ++parent_child_index; + } + return {}; +} diff --git a/DevTools/HackStudio/WidgetTreeModel.h b/DevTools/HackStudio/WidgetTreeModel.h index 10a81da3fa..f7e784b9b6 100644 --- a/DevTools/HackStudio/WidgetTreeModel.h +++ b/DevTools/HackStudio/WidgetTreeModel.h @@ -15,6 +15,8 @@ public: virtual GModelIndex parent_index(const GModelIndex&) const override; virtual void update() override; + GModelIndex index_for_widget(GWidget&) const; + private: explicit WidgetTreeModel(GWidget&); diff --git a/DevTools/HackStudio/main.cpp b/DevTools/HackStudio/main.cpp index e3f870d7d4..c18a7abcb1 100644 --- a/DevTools/HackStudio/main.cpp +++ b/DevTools/HackStudio/main.cpp @@ -100,7 +100,7 @@ int main(int argc, char** argv) Function update_actions; g_window = GWindow::construct(); - g_window->set_rect(100, 100, 800, 600); + g_window->set_rect(90, 90, 840, 600); g_window->set_title("HackStudio"); auto widget = GWidget::construct(); @@ -164,7 +164,7 @@ int main(int argc, char** argv) auto form_editing_pane_container = GSplitter::construct(Orientation::Vertical, form_editor_inner_splitter); form_editing_pane_container->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill); - form_editing_pane_container->set_preferred_size(170, 0); + form_editing_pane_container->set_preferred_size(190, 0); form_editing_pane_container->set_layout(make(Orientation::Vertical)); auto add_properties_pane = [&](auto& text, auto pane_widget) { @@ -181,6 +181,28 @@ int main(int argc, char** argv) auto form_widget_tree_view = GTreeView::construct(nullptr); form_widget_tree_view->set_model(g_form_editor_widget->model()); + form_widget_tree_view->on_selection_change = [&] { + g_form_editor_widget->selection().disable_hooks(); + g_form_editor_widget->selection().clear(); + form_widget_tree_view->selection().for_each_index([&](auto& index) { + // NOTE: Make sure we don't add the FormWidget itself to the selection, + // since that would allow you to drag-move the FormWidget. + if (index.internal_data() != &g_form_editor_widget->form_widget()) + g_form_editor_widget->selection().add(*(GWidget*)index.internal_data()); + }); + g_form_editor_widget->update(); + g_form_editor_widget->selection().enable_hooks(); + }; + + g_form_editor_widget->selection().on_add = [&](auto& widget) { + form_widget_tree_view->selection().add(g_form_editor_widget->model().index_for_widget(widget)); + }; + g_form_editor_widget->selection().on_remove = [&](auto& widget) { + form_widget_tree_view->selection().remove(g_form_editor_widget->model().index_for_widget(widget)); + }; + g_form_editor_widget->selection().on_clear = [&] { + form_widget_tree_view->selection().clear(); + }; add_properties_pane("Form widget tree:", form_widget_tree_view); add_properties_pane("Widget properties:", GTableView::construct(nullptr));