mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 07:07:41 +00:00
HackStudio: Remove the visual form editor
Okay we've tried this twice now, and nobody ends up working on it. Meanwhile, more and more people are using GML, and I think it's safe to say that GML is the future of GUI development here. So let's get rid of the old form editor from HackStudio and pave the way for integrating GML editing into the IDE instead. :^)
This commit is contained in:
parent
29fe4a5de5
commit
0126c81a7f
14 changed files with 0 additions and 852 deletions
|
@ -6,7 +6,6 @@ compile_gml(Dialogs/NewProjectDialog.gml Dialogs/NewProjectDialogGML.h new_proje
|
|||
set(SOURCES
|
||||
CodeDocument.cpp
|
||||
ClassViewWidget.cpp
|
||||
CursorTool.cpp
|
||||
Debugger/BacktraceModel.cpp
|
||||
Debugger/DebugInfoWidget.cpp
|
||||
Debugger/Debugger.cpp
|
||||
|
@ -23,8 +22,6 @@ set(SOURCES
|
|||
Editor.cpp
|
||||
EditorWrapper.cpp
|
||||
FindInFilesWidget.cpp
|
||||
FormEditorWidget.cpp
|
||||
FormWidget.cpp
|
||||
Git/DiffViewer.cpp
|
||||
Git/GitFilesModel.cpp
|
||||
Git/GitFilesView.cpp
|
||||
|
@ -39,8 +36,6 @@ set(SOURCES
|
|||
ProjectFile.cpp
|
||||
ProjectTemplate.cpp
|
||||
TerminalWrapper.cpp
|
||||
WidgetTool.cpp
|
||||
WidgetTreeModel.cpp
|
||||
main.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "CursorTool.h"
|
||||
#include "FormEditorWidget.h"
|
||||
#include "FormWidget.h"
|
||||
#include "WidgetTreeModel.h"
|
||||
#include <AK/Debug.h>
|
||||
#include <LibGfx/Palette.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
void CursorTool::on_mousedown(GUI::MouseEvent& event)
|
||||
{
|
||||
dbgln_if(CURSOR_TOOL_DEBUG, "CursorTool::on_mousedown");
|
||||
auto& form_widget = m_editor.form_widget();
|
||||
auto result = form_widget.hit_test(event.position(), GUI::Widget::ShouldRespectGreediness::No);
|
||||
|
||||
if (event.button() == GUI::MouseButton::Left) {
|
||||
if (result.widget && result.widget != &form_widget) {
|
||||
if (event.modifiers() & Mod_Ctrl) {
|
||||
m_editor.selection().toggle(*result.widget);
|
||||
} else if (!event.modifiers()) {
|
||||
if (!m_editor.selection().contains(*result.widget)) {
|
||||
dbgln_if(CURSOR_TOOL_DEBUG, "Selection didn't contain {}, making it the only selected one", *result.widget);
|
||||
m_editor.selection().set(*result.widget);
|
||||
}
|
||||
|
||||
m_drag_origin = event.position();
|
||||
m_positions_before_drag.clear();
|
||||
m_editor.selection().for_each([&](auto& widget) {
|
||||
m_positions_before_drag.set(&widget, widget.relative_position());
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
m_editor.selection().clear();
|
||||
m_rubber_banding = true;
|
||||
m_rubber_band_origin = event.position();
|
||||
m_rubber_band_position = event.position();
|
||||
form_widget.update();
|
||||
}
|
||||
// FIXME: Do we need to update any part of the FormEditorWidget outside the FormWidget?
|
||||
form_widget.update();
|
||||
}
|
||||
}
|
||||
|
||||
void CursorTool::on_mouseup(GUI::MouseEvent& event)
|
||||
{
|
||||
dbgln_if(CURSOR_TOOL_DEBUG, "CursorTool::on_mouseup");
|
||||
if (event.button() == GUI::MouseButton::Left) {
|
||||
auto& form_widget = m_editor.form_widget();
|
||||
auto result = form_widget.hit_test(event.position(), GUI::Widget::ShouldRespectGreediness::No);
|
||||
if (!m_dragging && !(event.modifiers() & Mod_Ctrl)) {
|
||||
if (result.widget && result.widget != &form_widget) {
|
||||
m_editor.selection().set(*result.widget);
|
||||
// FIXME: Do we need to update any part of the FormEditorWidget outside the FormWidget?
|
||||
form_widget.update();
|
||||
}
|
||||
}
|
||||
m_dragging = false;
|
||||
m_rubber_banding = false;
|
||||
form_widget.update();
|
||||
}
|
||||
}
|
||||
|
||||
void CursorTool::on_mousemove(GUI::MouseEvent& event)
|
||||
{
|
||||
dbgln_if(CURSOR_TOOL_DEBUG, "CursorTool::on_mousemove");
|
||||
auto& form_widget = m_editor.form_widget();
|
||||
|
||||
if (m_rubber_banding) {
|
||||
set_rubber_band_position(event.position());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_dragging && event.buttons() & GUI::MouseButton::Left && event.position() != m_drag_origin) {
|
||||
auto result = form_widget.hit_test(event.position(), GUI::Widget::ShouldRespectGreediness::No);
|
||||
if (result.widget && result.widget != &form_widget) {
|
||||
if (!m_editor.selection().contains(*result.widget)) {
|
||||
m_editor.selection().set(*result.widget);
|
||||
// FIXME: Do we need to update any part of the FormEditorWidget outside the FormWidget?
|
||||
form_widget.update();
|
||||
}
|
||||
}
|
||||
m_dragging = true;
|
||||
}
|
||||
|
||||
if (m_dragging) {
|
||||
auto movement_delta = event.position() - m_drag_origin;
|
||||
m_editor.selection().for_each([&](auto& widget) {
|
||||
auto new_rect = widget.relative_rect();
|
||||
new_rect.set_location(m_positions_before_drag.get(&widget).value_or({}).translated(movement_delta));
|
||||
new_rect.set_x(new_rect.x() - (new_rect.x() % m_editor.form_widget().grid_size()));
|
||||
new_rect.set_y(new_rect.y() - (new_rect.y() % m_editor.form_widget().grid_size()));
|
||||
widget.set_relative_rect(new_rect);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
m_editor.model().update();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CursorTool::on_keydown(GUI::KeyEvent& event)
|
||||
{
|
||||
dbgln_if(CURSOR_TOOL_DEBUG, "CursorTool::on_keydown");
|
||||
|
||||
auto move_selected_widgets_by = [this](int x, int y) {
|
||||
m_editor.selection().for_each([&](auto& widget) {
|
||||
widget.move_by(x, y);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
};
|
||||
|
||||
if (event.modifiers() == 0) {
|
||||
switch (event.key()) {
|
||||
case Key_Down:
|
||||
move_selected_widgets_by(0, m_editor.form_widget().grid_size());
|
||||
break;
|
||||
case Key_Up:
|
||||
move_selected_widgets_by(0, -m_editor.form_widget().grid_size());
|
||||
break;
|
||||
case Key_Left:
|
||||
move_selected_widgets_by(-m_editor.form_widget().grid_size(), 0);
|
||||
break;
|
||||
case Key_Right:
|
||||
move_selected_widgets_by(m_editor.form_widget().grid_size(), 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CursorTool::set_rubber_band_position(const Gfx::IntPoint& position)
|
||||
{
|
||||
if (m_rubber_band_position == position)
|
||||
return;
|
||||
m_rubber_band_position = position;
|
||||
|
||||
auto rubber_band_rect = this->rubber_band_rect();
|
||||
|
||||
m_editor.selection().clear();
|
||||
m_editor.form_widget().for_each_child_widget([&](auto& child) {
|
||||
if (child.relative_rect().intersects(rubber_band_rect))
|
||||
m_editor.selection().add(child);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
||||
m_editor.form_widget().update();
|
||||
}
|
||||
|
||||
Gfx::IntRect CursorTool::rubber_band_rect() const
|
||||
{
|
||||
if (!m_rubber_banding)
|
||||
return {};
|
||||
return Gfx::IntRect::from_two_points(m_rubber_band_origin, m_rubber_band_position);
|
||||
}
|
||||
|
||||
void CursorTool::on_second_paint(GUI::Painter& painter, GUI::PaintEvent&)
|
||||
{
|
||||
if (!m_rubber_banding)
|
||||
return;
|
||||
auto rect = rubber_band_rect();
|
||||
painter.fill_rect(rect, m_editor.palette().rubber_band_fill());
|
||||
painter.draw_rect(rect, m_editor.palette().rubber_band_border());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Tool.h"
|
||||
#include <AK/HashMap.h>
|
||||
#include <LibGUI/Forward.h>
|
||||
#include <LibGfx/Point.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
class CursorTool final : public Tool {
|
||||
public:
|
||||
explicit CursorTool(FormEditorWidget& editor)
|
||||
: Tool(editor)
|
||||
{
|
||||
}
|
||||
virtual ~CursorTool() override { }
|
||||
|
||||
private:
|
||||
virtual const char* class_name() const override { return "CursorTool"; }
|
||||
virtual void on_mousedown(GUI::MouseEvent&) override;
|
||||
virtual void on_mouseup(GUI::MouseEvent&) override;
|
||||
virtual void on_mousemove(GUI::MouseEvent&) override;
|
||||
virtual void on_keydown(GUI::KeyEvent&) override;
|
||||
virtual void on_second_paint(GUI::Painter&, GUI::PaintEvent&) override;
|
||||
|
||||
void set_rubber_band_position(const Gfx::IntPoint&);
|
||||
Gfx::IntRect rubber_band_rect() const;
|
||||
|
||||
Gfx::IntPoint m_drag_origin;
|
||||
HashMap<GUI::Widget*, Gfx::IntPoint> m_positions_before_drag;
|
||||
bool m_dragging { false };
|
||||
|
||||
bool m_rubber_banding { false };
|
||||
Gfx::IntPoint m_rubber_band_origin;
|
||||
Gfx::IntPoint m_rubber_band_position;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "FormEditorWidget.h"
|
||||
#include "CursorTool.h"
|
||||
#include "FormWidget.h"
|
||||
#include "WidgetTreeModel.h"
|
||||
#include <LibGUI/Painter.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
FormEditorWidget::FormEditorWidget()
|
||||
: m_tool(make<CursorTool>(*this))
|
||||
{
|
||||
set_fill_with_background_color(true);
|
||||
|
||||
m_form_widget = add<FormWidget>();
|
||||
m_widget_tree_model = WidgetTreeModel::create(*m_form_widget);
|
||||
}
|
||||
|
||||
FormEditorWidget::~FormEditorWidget()
|
||||
{
|
||||
}
|
||||
|
||||
void FormEditorWidget::paint_event(GUI::PaintEvent& event)
|
||||
{
|
||||
GUI::Frame::paint_event(event);
|
||||
|
||||
GUI::Painter painter(*this);
|
||||
painter.add_clip_rect(event.rect());
|
||||
}
|
||||
|
||||
void FormEditorWidget::set_tool(NonnullOwnPtr<Tool> tool)
|
||||
{
|
||||
m_tool->detach();
|
||||
m_tool = move(tool);
|
||||
m_tool->attach();
|
||||
}
|
||||
|
||||
WidgetTreeModel& FormEditorWidget::model()
|
||||
{
|
||||
return *m_widget_tree_model;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/HashTable.h>
|
||||
#include <LibGUI/AbstractScrollableWidget.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
class FormWidget;
|
||||
class Tool;
|
||||
class WidgetTreeModel;
|
||||
|
||||
class FormEditorWidget final : public GUI::AbstractScrollableWidget {
|
||||
C_OBJECT(FormEditorWidget)
|
||||
public:
|
||||
virtual ~FormEditorWidget() override;
|
||||
|
||||
FormWidget& form_widget() { return *m_form_widget; }
|
||||
const FormWidget& form_widget() const { return *m_form_widget; }
|
||||
|
||||
Tool& tool() { return *m_tool; }
|
||||
const Tool& tool() const { return *m_tool; }
|
||||
|
||||
void set_tool(NonnullOwnPtr<Tool>);
|
||||
|
||||
WidgetTreeModel& model();
|
||||
|
||||
class WidgetSelection {
|
||||
public:
|
||||
Function<void(GUI::Widget&)> on_remove;
|
||||
Function<void(GUI::Widget&)> on_add;
|
||||
Function<void()> 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();
|
||||
}
|
||||
|
||||
bool contains(GUI::Widget& widget) const
|
||||
{
|
||||
return m_widgets.contains(&widget);
|
||||
}
|
||||
|
||||
void toggle(GUI::Widget& widget)
|
||||
{
|
||||
if (contains(widget))
|
||||
remove(widget);
|
||||
else
|
||||
add(widget);
|
||||
}
|
||||
|
||||
void set(GUI::Widget& widget)
|
||||
{
|
||||
clear();
|
||||
add(widget);
|
||||
}
|
||||
|
||||
void remove(GUI::Widget& widget)
|
||||
{
|
||||
VERIFY(m_widgets.contains(&widget));
|
||||
m_widgets.remove(&widget);
|
||||
if (m_hooks_enabled && on_remove)
|
||||
on_remove(widget);
|
||||
}
|
||||
|
||||
void add(GUI::Widget& 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<typename Callback>
|
||||
void for_each(Callback callback)
|
||||
{
|
||||
for (auto& it : m_widgets) {
|
||||
if (callback(*it) == IterationDecision::Break)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WidgetSelection() { }
|
||||
|
||||
private:
|
||||
HashTable<GUI::Widget*> m_widgets;
|
||||
bool m_hooks_enabled { true };
|
||||
};
|
||||
|
||||
WidgetSelection& selection() { return m_selection; }
|
||||
|
||||
private:
|
||||
virtual void paint_event(GUI::PaintEvent&) override;
|
||||
|
||||
FormEditorWidget();
|
||||
|
||||
RefPtr<FormWidget> m_form_widget;
|
||||
RefPtr<WidgetTreeModel> m_widget_tree_model;
|
||||
NonnullOwnPtr<Tool> m_tool;
|
||||
WidgetSelection m_selection;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "FormWidget.h"
|
||||
#include "FormEditorWidget.h"
|
||||
#include "Tool.h"
|
||||
#include <LibGUI/Painter.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
FormWidget::FormWidget()
|
||||
{
|
||||
set_focus_policy(GUI::FocusPolicy::StrongFocus);
|
||||
set_fill_with_background_color(true);
|
||||
set_relative_rect(5, 5, 400, 300);
|
||||
|
||||
set_greedy_for_hits(true);
|
||||
}
|
||||
|
||||
FormWidget::~FormWidget()
|
||||
{
|
||||
}
|
||||
|
||||
FormEditorWidget& FormWidget::editor()
|
||||
{
|
||||
return static_cast<FormEditorWidget&>(*parent());
|
||||
}
|
||||
|
||||
const FormEditorWidget& FormWidget::editor() const
|
||||
{
|
||||
return static_cast<const FormEditorWidget&>(*parent());
|
||||
}
|
||||
|
||||
void FormWidget::paint_event(GUI::PaintEvent& event)
|
||||
{
|
||||
GUI::Painter painter(*this);
|
||||
painter.add_clip_rect(event.rect());
|
||||
|
||||
for (int y = 0; y < height(); y += m_grid_size) {
|
||||
for (int x = 0; x < width(); x += m_grid_size) {
|
||||
painter.set_pixel({ x, y }, Color::from_rgb(0x404040));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FormWidget::second_paint_event(GUI::PaintEvent& event)
|
||||
{
|
||||
GUI::Painter painter(*this);
|
||||
painter.add_clip_rect(event.rect());
|
||||
|
||||
if (!editor().selection().is_empty()) {
|
||||
for_each_child_widget([&](auto& child) {
|
||||
if (editor().selection().contains(child)) {
|
||||
painter.draw_rect(child.relative_rect(), Color::Blue);
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
editor().tool().on_second_paint(painter, event);
|
||||
}
|
||||
|
||||
void FormWidget::mousedown_event(GUI::MouseEvent& event)
|
||||
{
|
||||
editor().tool().on_mousedown(event);
|
||||
}
|
||||
|
||||
void FormWidget::mouseup_event(GUI::MouseEvent& event)
|
||||
{
|
||||
editor().tool().on_mouseup(event);
|
||||
}
|
||||
|
||||
void FormWidget::mousemove_event(GUI::MouseEvent& event)
|
||||
{
|
||||
editor().tool().on_mousemove(event);
|
||||
}
|
||||
|
||||
void FormWidget::keydown_event(GUI::KeyEvent& event)
|
||||
{
|
||||
editor().tool().on_keydown(event);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Badge.h>
|
||||
#include <LibGUI/Widget.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
class CursorTool;
|
||||
class FormEditorWidget;
|
||||
|
||||
class FormWidget final : public GUI::Widget {
|
||||
C_OBJECT(FormWidget)
|
||||
public:
|
||||
virtual ~FormWidget() override;
|
||||
|
||||
FormEditorWidget& editor();
|
||||
const FormEditorWidget& editor() const;
|
||||
|
||||
// FIXME: This should be an app-wide preference instead.
|
||||
int grid_size() const { return m_grid_size; }
|
||||
|
||||
private:
|
||||
virtual void paint_event(GUI::PaintEvent&) override;
|
||||
virtual void second_paint_event(GUI::PaintEvent&) override;
|
||||
virtual void mousedown_event(GUI::MouseEvent&) override;
|
||||
virtual void mouseup_event(GUI::MouseEvent&) override;
|
||||
virtual void mousemove_event(GUI::MouseEvent&) override;
|
||||
virtual void keydown_event(GUI::KeyEvent&) override;
|
||||
|
||||
FormWidget();
|
||||
|
||||
int m_grid_size { 5 };
|
||||
};
|
||||
|
||||
}
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
#include "HackStudioWidget.h"
|
||||
#include "CursorTool.h"
|
||||
#include "Debugger/DebugInfoWidget.h"
|
||||
#include "Debugger/Debugger.h"
|
||||
#include "Debugger/DisassemblyWidget.h"
|
||||
|
@ -15,8 +14,6 @@
|
|||
#include "Editor.h"
|
||||
#include "EditorWrapper.h"
|
||||
#include "FindInFilesWidget.h"
|
||||
#include "FormEditorWidget.h"
|
||||
#include "FormWidget.h"
|
||||
#include "Git/DiffViewer.h"
|
||||
#include "Git/GitWidget.h"
|
||||
#include "HackStudio.h"
|
||||
|
@ -25,8 +22,6 @@
|
|||
#include "Project.h"
|
||||
#include "ProjectDeclarations.h"
|
||||
#include "TerminalWrapper.h"
|
||||
#include "WidgetTool.h"
|
||||
#include "WidgetTreeModel.h"
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibCore/ArgsParser.h>
|
||||
|
@ -102,8 +97,6 @@ HackStudioWidget::HackStudioWidget(const String& path_to_project)
|
|||
// Put a placeholder widget front & center since we don't have a file open yet.
|
||||
m_right_hand_stack->add<GUI::Widget>();
|
||||
|
||||
create_form_editor(*m_right_hand_stack);
|
||||
|
||||
m_diff_viewer = m_right_hand_stack->add<DiffViewer>();
|
||||
|
||||
m_editors_splitter = m_right_hand_stack->add<GUI::VerticalSplitter>();
|
||||
|
@ -780,95 +773,6 @@ void HackStudioWidget::create_open_files_view(GUI::Widget& parent)
|
|||
};
|
||||
}
|
||||
|
||||
void HackStudioWidget::create_form_editor(GUI::Widget& parent)
|
||||
{
|
||||
m_form_inner_container = parent.add<GUI::Widget>();
|
||||
m_form_inner_container->set_layout<GUI::HorizontalBoxLayout>();
|
||||
auto& form_widgets_toolbar = m_form_inner_container->add<GUI::Toolbar>(Orientation::Vertical, 26);
|
||||
form_widgets_toolbar.set_fixed_width(38);
|
||||
|
||||
GUI::ActionGroup tool_actions;
|
||||
tool_actions.set_exclusive(true);
|
||||
|
||||
auto cursor_tool_action = GUI::Action::create_checkable("Cursor", Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Cursor.png"), [this](auto&) {
|
||||
m_form_editor_widget->set_tool(make<CursorTool>(*m_form_editor_widget));
|
||||
});
|
||||
cursor_tool_action->set_checked(true);
|
||||
tool_actions.add_action(cursor_tool_action);
|
||||
|
||||
form_widgets_toolbar.add_action(cursor_tool_action);
|
||||
|
||||
auto& widget_class = *Core::ObjectClassRegistration::find("GUI::Widget");
|
||||
|
||||
Core::ObjectClassRegistration::for_each([&, this](const Core::ObjectClassRegistration& reg) {
|
||||
if (!reg.is_derived_from(widget_class))
|
||||
return;
|
||||
constexpr size_t gui_namespace_prefix_length = sizeof("GUI::") - 1;
|
||||
auto icon_path = String::formatted("/res/icons/hackstudio/G{}.png",
|
||||
reg.class_name().substring(gui_namespace_prefix_length, reg.class_name().length() - gui_namespace_prefix_length));
|
||||
if (!Core::File::exists(icon_path))
|
||||
return;
|
||||
|
||||
auto action = GUI::Action::create_checkable(reg.class_name(), Gfx::Bitmap::load_from_file(icon_path), [®, this](auto&) {
|
||||
m_form_editor_widget->set_tool(make<WidgetTool>(*m_form_editor_widget, reg));
|
||||
auto widget = static_ptr_cast<Widget>(reg.construct());
|
||||
m_form_editor_widget->form_widget().add_child(widget);
|
||||
widget->set_relative_rect(30, 30, 30, 30);
|
||||
m_form_editor_widget->model().update();
|
||||
});
|
||||
action->set_checked(false);
|
||||
tool_actions.add_action(action);
|
||||
form_widgets_toolbar.add_action(move(action));
|
||||
});
|
||||
|
||||
auto& form_editor_inner_splitter = m_form_inner_container->add<GUI::HorizontalSplitter>();
|
||||
|
||||
m_form_editor_widget = form_editor_inner_splitter.add<FormEditorWidget>();
|
||||
|
||||
auto& form_editing_pane_container = form_editor_inner_splitter.add<GUI::VerticalSplitter>();
|
||||
form_editing_pane_container.set_fixed_width(190);
|
||||
form_editing_pane_container.set_layout<GUI::VerticalBoxLayout>();
|
||||
|
||||
auto add_properties_pane = [&](auto& text, auto& pane_widget) {
|
||||
auto& wrapper = form_editing_pane_container.add<GUI::Widget>();
|
||||
wrapper.set_layout<GUI::VerticalBoxLayout>();
|
||||
auto& label = wrapper.add<GUI::Label>(text);
|
||||
label.set_fill_with_background_color(true);
|
||||
label.set_text_alignment(Gfx::TextAlignment::CenterLeft);
|
||||
label.set_font(Gfx::FontDatabase::default_bold_font());
|
||||
label.set_fixed_height(16);
|
||||
wrapper.add_child(pane_widget);
|
||||
};
|
||||
|
||||
m_form_widget_tree_view = GUI::TreeView::construct();
|
||||
m_form_widget_tree_view->set_model(m_form_editor_widget->model());
|
||||
m_form_widget_tree_view->on_selection_change = [this] {
|
||||
m_form_editor_widget->selection().disable_hooks();
|
||||
m_form_editor_widget->selection().clear();
|
||||
m_form_widget_tree_view->selection().for_each_index([this](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() != &m_form_editor_widget->form_widget())
|
||||
m_form_editor_widget->selection().add(*(GUI::Widget*)index.internal_data());
|
||||
});
|
||||
m_form_editor_widget->update();
|
||||
m_form_editor_widget->selection().enable_hooks();
|
||||
};
|
||||
|
||||
m_form_editor_widget->selection().on_add = [this](auto& widget) {
|
||||
m_form_widget_tree_view->selection().add(m_form_editor_widget->model().index_for_widget(widget));
|
||||
};
|
||||
m_form_editor_widget->selection().on_remove = [this](auto& widget) {
|
||||
m_form_widget_tree_view->selection().remove(m_form_editor_widget->model().index_for_widget(widget));
|
||||
};
|
||||
m_form_editor_widget->selection().on_clear = [this] {
|
||||
m_form_widget_tree_view->selection().clear();
|
||||
};
|
||||
|
||||
add_properties_pane("Form widget tree:", *m_form_widget_tree_view);
|
||||
add_properties_pane("Widget properties:", *GUI::TableView::construct());
|
||||
}
|
||||
|
||||
void HackStudioWidget::create_toolbar(GUI::Widget& parent)
|
||||
{
|
||||
auto& toolbar = parent.add<GUI::Toolbar>();
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "Debugger/DisassemblyWidget.h"
|
||||
#include "EditorWrapper.h"
|
||||
#include "FindInFilesWidget.h"
|
||||
#include "FormEditorWidget.h"
|
||||
#include "Git/DiffViewer.h"
|
||||
#include "Git/GitWidget.h"
|
||||
#include "Locator.h"
|
||||
|
@ -102,7 +101,6 @@ private:
|
|||
void handle_external_file_deletion(const String& filepath);
|
||||
|
||||
void create_open_files_view(GUI::Widget& parent);
|
||||
void create_form_editor(GUI::Widget& parent);
|
||||
void create_toolbar(GUI::Widget& parent);
|
||||
void create_action_tab(GUI::Widget& parent);
|
||||
void create_app_menubar(GUI::Menubar&);
|
||||
|
@ -135,7 +133,6 @@ private:
|
|||
RefPtr<GUI::StackWidget> m_right_hand_stack;
|
||||
RefPtr<GUI::Splitter> m_editors_splitter;
|
||||
RefPtr<GUI::Widget> m_form_inner_container;
|
||||
RefPtr<FormEditorWidget> m_form_editor_widget;
|
||||
RefPtr<GUI::TreeView> m_form_widget_tree_view;
|
||||
RefPtr<DiffViewer> m_diff_viewer;
|
||||
RefPtr<GitWidget> m_git_widget;
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <LibCore/Forward.h>
|
||||
#include <LibGUI/Forward.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
class FormEditorWidget;
|
||||
|
||||
class Tool {
|
||||
AK_MAKE_NONCOPYABLE(Tool);
|
||||
AK_MAKE_NONMOVABLE(Tool);
|
||||
|
||||
public:
|
||||
virtual ~Tool() { }
|
||||
|
||||
virtual void on_mousedown(GUI::MouseEvent&) = 0;
|
||||
virtual void on_mouseup(GUI::MouseEvent&) = 0;
|
||||
virtual void on_mousemove(GUI::MouseEvent&) = 0;
|
||||
virtual void on_keydown(GUI::KeyEvent&) = 0;
|
||||
virtual void on_second_paint(GUI::Painter&, GUI::PaintEvent&) { }
|
||||
|
||||
virtual const char* class_name() const = 0;
|
||||
|
||||
virtual void attach() { }
|
||||
virtual void detach() { }
|
||||
|
||||
protected:
|
||||
explicit Tool(FormEditorWidget& editor)
|
||||
: m_editor(editor)
|
||||
{
|
||||
}
|
||||
|
||||
FormEditorWidget& m_editor;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "WidgetTool.h"
|
||||
#include <AK/Format.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
void WidgetTool::on_mousedown([[maybe_unused]] GUI::MouseEvent& event)
|
||||
{
|
||||
dbgln("WidgetTool::on_mousedown");
|
||||
}
|
||||
|
||||
void WidgetTool::on_mouseup([[maybe_unused]] GUI::MouseEvent& event)
|
||||
{
|
||||
dbgln("WidgetTool::on_mouseup");
|
||||
}
|
||||
|
||||
void WidgetTool::on_mousemove([[maybe_unused]] GUI::MouseEvent& event)
|
||||
{
|
||||
dbgln("WidgetTool::on_mousemove");
|
||||
}
|
||||
|
||||
void WidgetTool::on_keydown([[maybe_unused]] GUI::KeyEvent& event)
|
||||
{
|
||||
dbgln("WidgetTool::on_keydown");
|
||||
}
|
||||
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Tool.h"
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
class WidgetTool final : public Tool {
|
||||
public:
|
||||
explicit WidgetTool(FormEditorWidget& editor, const Core::ObjectClassRegistration& meta_class)
|
||||
: Tool(editor)
|
||||
, m_meta_class(meta_class)
|
||||
{
|
||||
}
|
||||
virtual ~WidgetTool() override { }
|
||||
|
||||
private:
|
||||
virtual const char* class_name() const override { return "WidgetTool"; }
|
||||
virtual void on_mousedown(GUI::MouseEvent&) override;
|
||||
virtual void on_mouseup(GUI::MouseEvent&) override;
|
||||
virtual void on_mousemove(GUI::MouseEvent&) override;
|
||||
virtual void on_keydown(GUI::KeyEvent&) override;
|
||||
|
||||
const Core::ObjectClassRegistration& m_meta_class;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "WidgetTreeModel.h"
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibGUI/Widget.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
WidgetTreeModel::WidgetTreeModel(GUI::Widget& root)
|
||||
: m_root(root)
|
||||
{
|
||||
m_widget_icon.set_bitmap_for_size(16, Gfx::Bitmap::load_from_file("/res/icons/16x16/inspector-object.png"));
|
||||
}
|
||||
|
||||
WidgetTreeModel::~WidgetTreeModel()
|
||||
{
|
||||
}
|
||||
|
||||
GUI::ModelIndex WidgetTreeModel::index(int row, int column, const GUI::ModelIndex& parent) const
|
||||
{
|
||||
if (!parent.is_valid()) {
|
||||
return create_index(row, column, m_root.ptr());
|
||||
}
|
||||
auto& parent_node = *static_cast<GUI::Widget*>(parent.internal_data());
|
||||
return create_index(row, column, parent_node.child_widgets().at(row));
|
||||
}
|
||||
|
||||
GUI::ModelIndex WidgetTreeModel::parent_index(const GUI::ModelIndex& index) const
|
||||
{
|
||||
if (!index.is_valid())
|
||||
return {};
|
||||
auto& widget = *static_cast<GUI::Widget*>(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 GUI::ModelIndex 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;
|
||||
}
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
return {};
|
||||
}
|
||||
|
||||
int WidgetTreeModel::row_count(const GUI::ModelIndex& index) const
|
||||
{
|
||||
if (!index.is_valid())
|
||||
return 1;
|
||||
auto& widget = *static_cast<GUI::Widget*>(index.internal_data());
|
||||
return widget.child_widgets().size();
|
||||
}
|
||||
|
||||
int WidgetTreeModel::column_count(const GUI::ModelIndex&) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
GUI::Variant WidgetTreeModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const
|
||||
{
|
||||
auto* widget = static_cast<GUI::Widget*>(index.internal_data());
|
||||
if (role == GUI::ModelRole::Icon) {
|
||||
return m_widget_icon;
|
||||
}
|
||||
if (role == GUI::ModelRole::Display) {
|
||||
return String::formatted("{} ({})", widget->class_name(), widget->relative_rect());
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void WidgetTreeModel::update()
|
||||
{
|
||||
did_update();
|
||||
}
|
||||
|
||||
GUI::ModelIndex WidgetTreeModel::index_for_widget(GUI::Widget& 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 {};
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibGUI/Model.h>
|
||||
#include <LibGUI/Painter.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
class WidgetTreeModel final : public GUI::Model {
|
||||
public:
|
||||
static NonnullRefPtr<WidgetTreeModel> create(GUI::Widget& root) { return adopt_ref(*new WidgetTreeModel(root)); }
|
||||
virtual ~WidgetTreeModel() override;
|
||||
|
||||
virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override;
|
||||
virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override;
|
||||
virtual GUI::Variant data(const GUI::ModelIndex&, GUI::ModelRole) const override;
|
||||
virtual GUI::ModelIndex index(int row, int column, const GUI::ModelIndex& parent = GUI::ModelIndex()) const override;
|
||||
virtual GUI::ModelIndex parent_index(const GUI::ModelIndex&) const override;
|
||||
virtual void update() override;
|
||||
|
||||
GUI::ModelIndex index_for_widget(GUI::Widget&) const;
|
||||
|
||||
private:
|
||||
explicit WidgetTreeModel(GUI::Widget&);
|
||||
|
||||
NonnullRefPtr<GUI::Widget> m_root;
|
||||
GUI::Icon m_widget_icon;
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue