mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 04:19:12 +00:00
Add touch magnify event to support OS X trackpad gesture
This commit is contained in:
parent
ef4a4822da
commit
15e10ad9f6
@ -361,6 +361,12 @@ void Editor::setZoom(const render::Zoom& zoom)
|
||||
m_zoom = zoom;
|
||||
notifyZoomChanged();
|
||||
}
|
||||
else {
|
||||
// Just copy the zoom as the internal "Zoom::m_internalScale"
|
||||
// value might be different and we want to keep this value updated
|
||||
// for better zooming experience in StateWithWheelBehavior.
|
||||
m_zoom = zoom;
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::setDefaultScroll()
|
||||
@ -1273,6 +1279,13 @@ bool Editor::onProcessMessage(Message* msg)
|
||||
}
|
||||
break;
|
||||
|
||||
case kTouchMagnifyMessage:
|
||||
if (m_sprite) {
|
||||
EditorStatePtr holdState(m_state);
|
||||
return m_state->onTouchMagnify(this, static_cast<TouchMessage*>(msg));
|
||||
}
|
||||
break;
|
||||
|
||||
case kKeyDownMessage:
|
||||
if (m_sprite) {
|
||||
EditorStatePtr holdState(m_state);
|
||||
@ -1488,9 +1501,9 @@ void Editor::setZoomAndCenterInMouse(const Zoom& zoom,
|
||||
padding.x - (screenPos.x-vp.x) + zoom.apply(spritePos.x+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.x)),
|
||||
padding.y - (screenPos.y-vp.y) + zoom.apply(spritePos.y+zoom.remove(1)/2) + int(zoom.apply(subpixelPos.y)));
|
||||
|
||||
if ((m_zoom != zoom) || (screenPos != view->viewScroll())) {
|
||||
setZoom(zoom);
|
||||
setZoom(zoom);
|
||||
|
||||
if ((m_zoom != zoom) || (screenPos != view->viewScroll())) {
|
||||
updateEditor();
|
||||
setEditorScroll(scrollPos);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@ -18,8 +18,9 @@ namespace gfx {
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class MouseMessage;
|
||||
class KeyMessage;
|
||||
class MouseMessage;
|
||||
class TouchMessage;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
@ -85,6 +86,9 @@ namespace app {
|
||||
// Called when the user moves the mouse wheel over the editor.
|
||||
virtual bool onMouseWheel(Editor* editor, ui::MouseMessage* msg) { return false; }
|
||||
|
||||
// Called when the user wants to zoom in/out using a pinch gesture in the trackpad.
|
||||
virtual bool onTouchMagnify(Editor* editor, ui::TouchMessage* msg) { return false; }
|
||||
|
||||
// Called each time the mouse changes its position so we can set an
|
||||
// appropiated cursor depending on the new coordinates of the mouse
|
||||
// pointer.
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@ -36,7 +36,7 @@ enum WHEEL_ACTION { WHEEL_NONE,
|
||||
|
||||
bool StateWithWheelBehavior::onMouseWheel(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
int dz = msg->wheelDelta().x + msg->wheelDelta().y;
|
||||
double dz = msg->wheelDelta().x + msg->wheelDelta().y;
|
||||
WHEEL_ACTION wheelAction = WHEEL_NONE;
|
||||
bool scrollBigSteps = false;
|
||||
|
||||
@ -79,7 +79,7 @@ bool StateWithWheelBehavior::onMouseWheel(Editor* editor, MouseMessage* msg)
|
||||
if (ColorBar::instance()->getFgColor().getType() == app::Color::IndexType) {
|
||||
int lastIndex = get_current_palette()->size()-1;
|
||||
|
||||
newIndex = ColorBar::instance()->getFgColor().getIndex() + dz;
|
||||
newIndex = ColorBar::instance()->getFgColor().getIndex() + int(dz);
|
||||
newIndex = MID(0, newIndex, lastIndex);
|
||||
}
|
||||
ColorBar::instance()->setFgColor(app::Color::fromIndex(newIndex));
|
||||
@ -92,7 +92,7 @@ bool StateWithWheelBehavior::onMouseWheel(Editor* editor, MouseMessage* msg)
|
||||
if (ColorBar::instance()->getBgColor().getType() == app::Color::IndexType) {
|
||||
int lastIndex = get_current_palette()->size()-1;
|
||||
|
||||
newIndex = ColorBar::instance()->getBgColor().getIndex() + dz;
|
||||
newIndex = ColorBar::instance()->getBgColor().getIndex() + int(dz);
|
||||
newIndex = MID(0, newIndex, lastIndex);
|
||||
}
|
||||
ColorBar::instance()->setBgColor(app::Color::fromIndex(newIndex));
|
||||
@ -102,27 +102,25 @@ bool StateWithWheelBehavior::onMouseWheel(Editor* editor, MouseMessage* msg)
|
||||
case WHEEL_FRAME:
|
||||
{
|
||||
Command* command = CommandsModule::instance()->getCommandByName
|
||||
((dz < 0) ? CommandId::GotoNextFrame:
|
||||
CommandId::GotoPreviousFrame);
|
||||
((dz < 0.0) ? CommandId::GotoNextFrame:
|
||||
CommandId::GotoPreviousFrame);
|
||||
if (command)
|
||||
UIContext::instance()->executeCommand(command);
|
||||
}
|
||||
break;
|
||||
|
||||
case WHEEL_ZOOM: {
|
||||
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||
render::Zoom zoom = editor->zoom();
|
||||
|
||||
zoom = render::Zoom::fromLinearScale(zoom.linearScale() - dz);
|
||||
|
||||
if (editor->zoom() != zoom) {
|
||||
bool center = Preferences::instance().editor.zoomFromCenterWithWheel();
|
||||
|
||||
editor->setZoomAndCenterInMouse(
|
||||
zoom, mouseMsg->position(),
|
||||
(center ? Editor::ZoomBehavior::CENTER:
|
||||
Editor::ZoomBehavior::MOUSE));
|
||||
if (msg->preciseWheel()) {
|
||||
dz /= 1.5;
|
||||
if (dz < -1.0) dz = -1.0;
|
||||
else if (dz > 1.0) dz = 1.0;
|
||||
}
|
||||
|
||||
zoom = render::Zoom::fromLinearScale(zoom.linearScale() - int(dz));
|
||||
|
||||
setZoom(editor, zoom, msg->position());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -139,10 +137,10 @@ bool StateWithWheelBehavior::onMouseWheel(Editor* editor, MouseMessage* msg)
|
||||
gfx::Rect vp = view->viewportBounds();
|
||||
|
||||
if (wheelAction == WHEEL_HSCROLL) {
|
||||
delta.x = dz * vp.w;
|
||||
delta.x = int(dz * vp.w);
|
||||
}
|
||||
else {
|
||||
delta.y = dz * vp.h;
|
||||
delta.y = int(dz * vp.h);
|
||||
}
|
||||
|
||||
if (scrollBigSteps) {
|
||||
@ -162,4 +160,26 @@ bool StateWithWheelBehavior::onMouseWheel(Editor* editor, MouseMessage* msg)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StateWithWheelBehavior::onTouchMagnify(Editor* editor, ui::TouchMessage* msg)
|
||||
{
|
||||
render::Zoom zoom = editor->zoom();
|
||||
zoom = render::Zoom::fromScale(
|
||||
zoom.internalScale() + zoom.internalScale() * msg->magnification());
|
||||
|
||||
setZoom(editor, zoom, msg->position());
|
||||
return true;
|
||||
}
|
||||
|
||||
void StateWithWheelBehavior::setZoom(Editor* editor,
|
||||
const render::Zoom& zoom,
|
||||
const gfx::Point& mousePos)
|
||||
{
|
||||
bool center = Preferences::instance().editor.zoomFromCenterWithWheel();
|
||||
|
||||
editor->setZoomAndCenterInMouse(
|
||||
zoom, mousePos,
|
||||
(center ? Editor::ZoomBehavior::CENTER:
|
||||
Editor::ZoomBehavior::MOUSE));
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@ -11,11 +11,18 @@
|
||||
|
||||
#include "app/ui/editor/editor_state.h"
|
||||
|
||||
namespace render {
|
||||
class Zoom;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
|
||||
class StateWithWheelBehavior : public EditorState {
|
||||
public:
|
||||
virtual bool onMouseWheel(Editor* editor, ui::MouseMessage* msg) override;
|
||||
virtual bool onTouchMagnify(Editor* editor, ui::TouchMessage* msg) override;
|
||||
private:
|
||||
void setZoom(Editor* editor, const render::Zoom& zoom, const gfx::Point& mousePos);
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -34,6 +34,15 @@ static int scales[][2] = {
|
||||
|
||||
static int scales_size = sizeof(scales) / sizeof(scales[0]);
|
||||
|
||||
Zoom::Zoom(int num, int den)
|
||||
: m_num(num)
|
||||
, m_den(den)
|
||||
{
|
||||
ASSERT(m_num > 0);
|
||||
ASSERT(m_den > 0);
|
||||
m_internalScale = scale();
|
||||
}
|
||||
|
||||
void Zoom::in()
|
||||
{
|
||||
int i = linearScale();
|
||||
@ -41,6 +50,7 @@ void Zoom::in()
|
||||
++i;
|
||||
m_num = scales[i][0];
|
||||
m_den = scales[i][1];
|
||||
m_internalScale = scale();
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,6 +61,7 @@ void Zoom::out()
|
||||
--i;
|
||||
m_num = scales[i][0];
|
||||
m_den = scales[i][1];
|
||||
m_internalScale = scale();
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +80,9 @@ int Zoom::linearScale() const
|
||||
// static
|
||||
Zoom Zoom::fromScale(double scale)
|
||||
{
|
||||
return fromLinearScale(findClosestLinearScale(scale));
|
||||
Zoom zoom = fromLinearScale(findClosestLinearScale(scale));
|
||||
zoom.m_internalScale = scale;
|
||||
return zoom;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -14,13 +14,16 @@ namespace render {
|
||||
|
||||
class Zoom {
|
||||
public:
|
||||
Zoom(int num, int den)
|
||||
: m_num(num), m_den(den) {
|
||||
ASSERT(m_num > 0);
|
||||
ASSERT(m_den > 0);
|
||||
Zoom(int num, int den);
|
||||
|
||||
double scale() const {
|
||||
return static_cast<double>(m_num) / static_cast<double>(m_den);
|
||||
}
|
||||
|
||||
double scale() const { return static_cast<double>(m_num) / static_cast<double>(m_den); }
|
||||
// This value isn't used in operator==() or operator!=()
|
||||
double internalScale() const {
|
||||
return m_internalScale;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T apply(T x) const {
|
||||
@ -72,6 +75,9 @@ namespace render {
|
||||
|
||||
int m_num;
|
||||
int m_den;
|
||||
|
||||
// Internal scale value used for precise zooming purposes.
|
||||
double m_internalScale;
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2012-2015 David Capello
|
||||
// Copyright (C) 2012-2016 David Capello
|
||||
//
|
||||
// This source file is ditributed under a BSD-like license, please
|
||||
// read LICENSE.txt for more information.
|
||||
@ -35,6 +35,7 @@ namespace she {
|
||||
MouseDoubleClick,
|
||||
KeyDown,
|
||||
KeyUp,
|
||||
TouchMagnify,
|
||||
};
|
||||
|
||||
enum MouseButton {
|
||||
@ -67,6 +68,7 @@ namespace she {
|
||||
gfx::Point wheelDelta() const { return m_wheelDelta; }
|
||||
bool preciseWheel() const { return m_preciseWheel; }
|
||||
MouseButton button() const { return m_button; }
|
||||
double magnification() const { return m_magnification; }
|
||||
|
||||
void setType(Type type) { m_type = type; }
|
||||
void setDisplay(Display* display) { m_display = display; }
|
||||
@ -80,6 +82,7 @@ namespace she {
|
||||
void setWheelDelta(const gfx::Point& delta) { m_wheelDelta = delta; }
|
||||
void setPreciseWheel(bool precise) { m_preciseWheel = precise; }
|
||||
void setButton(MouseButton button) { m_button = button; }
|
||||
void setMagnification(double magnification) { m_magnification = magnification; }
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
@ -93,6 +96,7 @@ namespace she {
|
||||
gfx::Point m_wheelDelta;
|
||||
bool m_preciseWheel;
|
||||
MouseButton m_button;
|
||||
double m_magnification;
|
||||
};
|
||||
|
||||
} // namespace she
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SHE library
|
||||
// Copyright (C) 2015 David Capello
|
||||
// Copyright (C) 2015-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -370,6 +370,17 @@ bool is_key_pressed(KeyScancode scancode)
|
||||
queue_event(ev);
|
||||
}
|
||||
|
||||
- (void)magnifyWithEvent:(NSEvent*)event
|
||||
{
|
||||
Event ev;
|
||||
ev.setType(Event::TouchMagnify);
|
||||
ev.setMagnification(event.magnification);
|
||||
ev.setPosition(get_local_mouse_pos(self, event));
|
||||
ev.setModifiers(get_modifiers_from_nsevent(event));
|
||||
|
||||
queue_event(ev);
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(NSEvent*)event
|
||||
{
|
||||
[self updateCurrentCursor];
|
||||
|
@ -380,6 +380,16 @@ void Manager::generateMessagesFromSheEvents()
|
||||
sheEvent.preciseWheel());
|
||||
break;
|
||||
}
|
||||
|
||||
case she::Event::TouchMagnify: {
|
||||
_internal_set_mouse_position(sheEvent.position());
|
||||
|
||||
handleTouchMagnify(sheEvent.position(),
|
||||
sheEvent.modifiers(),
|
||||
sheEvent.magnification());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,6 +489,24 @@ void Manager::handleMouseWheel(const gfx::Point& mousePos,
|
||||
wheelDelta, preciseWheel));
|
||||
}
|
||||
|
||||
void Manager::handleTouchMagnify(const gfx::Point& mousePos,
|
||||
const KeyModifiers modifiers,
|
||||
const double magnification)
|
||||
{
|
||||
Widget* widget = (capture_widget ? capture_widget: mouse_widget);
|
||||
if (widget) {
|
||||
Message* msg = new TouchMessage(
|
||||
kTouchMagnifyMessage,
|
||||
modifiers,
|
||||
mousePos,
|
||||
magnification);
|
||||
|
||||
msg->addRecipient(widget);
|
||||
|
||||
enqueueMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Handles Z order: Send the window to top (only when you click in a
|
||||
// window that aren't the desktop).
|
||||
void Manager::handleWindowZOrder()
|
||||
@ -1222,6 +1250,7 @@ void Manager::pumpQueue()
|
||||
"kMouseMoveMessage",
|
||||
"kSetCursorMessage",
|
||||
"kMouseWheelMessage",
|
||||
"kTouchMagnifyMessage",
|
||||
};
|
||||
const char* string =
|
||||
(msg->type() >= kOpenMessage &&
|
||||
|
@ -123,6 +123,9 @@ namespace ui {
|
||||
void handleMouseDoubleClick(const gfx::Point& mousePos, MouseButtons mouseButtons, KeyModifiers modifiers);
|
||||
void handleMouseWheel(const gfx::Point& mousePos, MouseButtons mouseButtons, KeyModifiers modifiers,
|
||||
const gfx::Point& wheelDelta, bool preciseWheel);
|
||||
void handleTouchMagnify(const gfx::Point& mousePos,
|
||||
const KeyModifiers modifiers,
|
||||
const double magnification);
|
||||
void handleWindowZOrder();
|
||||
|
||||
void pumpQueue();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2013, 2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -129,6 +129,25 @@ namespace ui {
|
||||
bool m_preciseWheel;
|
||||
};
|
||||
|
||||
class TouchMessage : public Message {
|
||||
public:
|
||||
TouchMessage(MessageType type,
|
||||
KeyModifiers modifiers,
|
||||
const gfx::Point& pos,
|
||||
double magnification)
|
||||
: Message(type, modifiers),
|
||||
m_pos(pos),
|
||||
m_magnification(magnification) {
|
||||
}
|
||||
|
||||
const gfx::Point& position() const { return m_pos; }
|
||||
double magnification() const { return m_magnification; }
|
||||
|
||||
private:
|
||||
gfx::Point m_pos; // Mouse position
|
||||
double m_magnification;
|
||||
};
|
||||
|
||||
class TimerMessage : public Message {
|
||||
public:
|
||||
TimerMessage(int count, Timer* timer)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2013, 2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -38,6 +38,9 @@ namespace ui {
|
||||
kSetCursorMessage, // A widget needs to setup the mouse cursor.
|
||||
kMouseWheelMessage, // User moves the wheel.
|
||||
|
||||
// Touch related messages.
|
||||
kTouchMagnifyMessage,
|
||||
|
||||
// TODO Drag'n'drop messages...
|
||||
// k...DndMessage
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user