Skip to content

Commit

Permalink
HackStudio: Allow moving widgets around using the CursorTool
Browse files Browse the repository at this point in the history
You can now move the widgets around, either by themselves or in group
selections, by dragging them with the cursor tool. :^)
  • Loading branch information
awesomekling committed Nov 10, 2019
1 parent f6576c4 commit 567769e
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 8 deletions.
66 changes: 59 additions & 7 deletions DevTools/HackStudio/CursorTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,76 @@ void CursorTool::on_mousedown(GMouseEvent& event)
dbg() << "CursorTool::on_mousedown";
auto& form_widget = m_editor.form_widget();
auto result = form_widget.hit_test(event.position(), GWidget::ShouldRespectGreediness::No);
if (result.widget && result.widget != &form_widget) {
if (event.modifiers() & Mod_Ctrl)
m_editor.selection().toggle(*result.widget);
else
m_editor.selection().set(*result.widget);

if (event.button() == GMouseButton::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)) {
dbg() << "Selection didn't contain " << *result.widget << ", making it the only selected one";
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();
}
// FIXME: Do we need to update any part of the FormEditorWidget outside the FormWidget?
form_widget.update();
}
}

void CursorTool::on_mouseup(GMouseEvent& event)
{
(void)event;
dbg() << "CursorTool::on_mouseup";
if (event.button() == GMouseButton::Left) {
auto& form_widget = m_editor.form_widget();
auto result = form_widget.hit_test(event.position(), GWidget::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;
}
}

void CursorTool::on_mousemove(GMouseEvent& event)
{
(void)event;
dbg() << "CursorTool::on_mousemove";

if (!m_dragging && event.buttons() & GMouseButton::Left && event.position() != m_drag_origin) {
auto& form_widget = m_editor.form_widget();
auto result = form_widget.hit_test(event.position(), GWidget::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;
});
return;
}
}
8 changes: 8 additions & 0 deletions DevTools/HackStudio/CursorTool.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#pragma once

#include "Tool.h"
#include <AK/HashMap.h>
#include <LibDraw/Point.h>

class GWidget;

class CursorTool final : public Tool {
public:
Expand All @@ -15,4 +19,8 @@ class CursorTool final : public Tool {
virtual void on_mousedown(GMouseEvent&) override;
virtual void on_mouseup(GMouseEvent&) override;
virtual void on_mousemove(GMouseEvent&) override;

Point m_drag_origin;
HashMap<GWidget*, Point> m_positions_before_drag;
bool m_dragging { false };
};
9 changes: 9 additions & 0 deletions DevTools/HackStudio/FormEditorWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ class FormEditorWidget final : public GScrollableWidget {
m_widgets.clear();
}

template<typename Callback>
void for_each(Callback callback)
{
for (auto& it : m_widgets) {
if (callback(*it) == IterationDecision::Break)
break;
}
}

WidgetSelection() {}
private:
HashTable<GWidget*> m_widgets;
Expand Down
4 changes: 3 additions & 1 deletion DevTools/HackStudio/FormWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ class FormWidget final : public GWidget {
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(GPaintEvent&) override;
virtual void second_paint_event(GPaintEvent&) override;
Expand All @@ -21,6 +24,5 @@ class FormWidget final : public GWidget {

explicit FormWidget(FormEditorWidget& parent);

// FIXME: This should be an app-wide preference instead.
int m_grid_size { 5 };
};

0 comments on commit 567769e

Please sign in to comment.