ladybird/Userland/Applications/PixelPaint/Tools/MoveTool.cpp
Zaggy1024 7ce346e50e PixelPaint: Allow keydown events to bubble from ImageEditor
Previously, all keydown KeyEvents were accepted, causing parent widgets
not to receive them. With the addition of shortcut handling to keydown,
shortcuts were not called when the ImageEditor was focused.
2022-11-14 16:08:11 +00:00

161 lines
4.9 KiB
C++

/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "MoveTool.h"
#include "../Image.h"
#include "../ImageEditor.h"
#include "../Layer.h"
#include <LibGUI/Action.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Painter.h>
#include <LibGUI/Window.h>
namespace PixelPaint {
void MoveTool::on_mousedown(Layer* layer, MouseEvent& event)
{
if (event.image_event().button() == GUI::MouseButton::Secondary) {
m_editor->start_panning(event.raw_event().position());
return;
}
if (!layer)
return;
auto& layer_event = event.layer_event();
auto& image_event = event.image_event();
if (layer_event.button() != GUI::MouseButton::Primary)
return;
if (!layer->rect().contains(layer_event.position()) && !m_mouse_in_resize_corner)
return;
m_scaling = m_mouse_in_resize_corner;
m_layer_being_moved = *layer;
m_event_origin = image_event.position();
m_layer_origin = layer->location();
}
void MoveTool::on_mousemove(Layer* layer, MouseEvent& event)
{
if (m_editor->is_panning()) {
m_editor->pan_to(event.raw_event().position());
return;
}
if (!layer)
return;
constexpr int sensitivity = 20;
Gfx::IntPoint grab_rect_position = Gfx::IntPoint(layer->location().x() + layer->size().width() - sensitivity / 2, layer->location().y() + layer->size().height() - sensitivity / 2);
Gfx::IntRect grab_rect = Gfx::IntRect(grab_rect_position, Gfx::IntSize(sensitivity, sensitivity));
auto updated_is_in_lower_right_corner = grab_rect.contains(event.image_event().position()); // check if the mouse is in the lower right corner
if (m_mouse_in_resize_corner != updated_is_in_lower_right_corner) {
m_mouse_in_resize_corner = updated_is_in_lower_right_corner;
m_editor->update_tool_cursor();
}
if (m_scaling) {
auto& cursor_location = event.image_event().position();
auto width = abs(m_layer_being_moved->location().x() - cursor_location.x());
auto height = abs(m_layer_being_moved->location().y() - cursor_location.y());
if (m_keep_ascept_ratio) {
if (abs(width - m_layer_being_moved->size().width()) > abs(height - m_layer_being_moved->size().height())) {
height = width * m_layer_being_moved->size().height() / m_layer_being_moved->size().width();
} else {
width = height * m_layer_being_moved->size().width() / m_layer_being_moved->size().height();
}
}
m_new_layer_size = Gfx::IntSize(width, height);
// TODO: Change this according to which direction the user is scaling
m_new_scaled_layer_location = Gfx::IntPoint(m_layer_being_moved->location().x(), m_layer_being_moved->location().y());
}
auto& image_event = event.image_event();
if (!m_layer_being_moved || m_scaling)
return;
auto delta = image_event.position() - m_event_origin;
m_layer_being_moved->set_location(m_layer_origin.translated(delta));
m_editor->layers_did_change();
}
void MoveTool::on_mouseup(Layer* layer, MouseEvent& event)
{
if (event.image_event().button() == GUI::MouseButton::Secondary) {
m_editor->stop_panning();
m_editor->set_override_cursor(cursor());
return;
}
if (!layer)
return;
auto& layer_event = event.layer_event();
if (layer_event.button() != GUI::MouseButton::Primary)
return;
if (m_scaling) {
m_editor->active_layer()->resize(m_new_layer_size, m_new_scaled_layer_location, Gfx::Painter::ScalingMode::BilinearBlend);
}
m_scaling = false;
m_layer_being_moved = nullptr;
m_editor->update_tool_cursor();
m_editor->did_complete_action(tool_name());
}
bool MoveTool::on_keydown(GUI::KeyEvent const& event)
{
if (event.key() == Key_Shift)
m_keep_ascept_ratio = true;
if (m_scaling)
return true;
if (event.modifiers() != 0)
return false;
auto* layer = m_editor->active_layer();
if (!layer)
return false;
auto new_location = layer->location();
switch (event.key()) {
case Key_Up:
new_location.translate_by(0, -1);
break;
case Key_Down:
new_location.translate_by(0, 1);
break;
case Key_Left:
new_location.translate_by(-1, 0);
break;
case Key_Right:
new_location.translate_by(1, 0);
break;
default:
return false;
}
layer->set_location(new_location);
m_editor->layers_did_change();
return true;
}
void MoveTool::on_keyup(GUI::KeyEvent& event)
{
if (event.key() == Key_Shift)
m_keep_ascept_ratio = false;
}
Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> MoveTool::cursor()
{
if (m_mouse_in_resize_corner || m_scaling)
return Gfx::StandardCursor::ResizeDiagonalTLBR;
return Gfx::StandardCursor::Move;
}
}