Improve canvas size UI

Now we can resize from corners (fix #1394) or move the whole canvas to
other position dragging the box from the center.
This commit is contained in:
David Capello 2017-04-07 10:28:30 -03:00
parent 4250809b1e
commit 4f5127fdba
3 changed files with 113 additions and 76 deletions

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -18,28 +18,18 @@ namespace app {
Ruler()
: m_orientation(Horizontal)
, m_position(0)
{
, m_position(0) {
}
Ruler(Orientation orientation, int position)
: m_orientation(orientation)
, m_position(position)
{
, m_position(position) {
}
Orientation getOrientation() const
{
return m_orientation;
}
Orientation orientation() const { return m_orientation; }
int position() const { return m_position; }
int getPosition() const
{
return m_position;
}
void setPosition(int position)
{
void setPosition(int position) {
m_position = position;
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2016 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -30,7 +30,7 @@ using namespace ui;
SelectBoxState::SelectBoxState(SelectBoxDelegate* delegate, const gfx::Rect& rc, Flags flags)
: m_delegate(delegate)
, m_rulers(4)
, m_movingRuler(-1)
, m_rulersDragAlign(0)
, m_selectingBox(false)
, m_flags(flags)
{
@ -50,10 +50,10 @@ void SelectBoxState::setFlags(Flags flags)
gfx::Rect SelectBoxState::getBoxBounds() const
{
int x1 = std::min(m_rulers[V1].getPosition(), m_rulers[V2].getPosition());
int y1 = std::min(m_rulers[H1].getPosition(), m_rulers[H2].getPosition());
int x2 = std::max(m_rulers[V1].getPosition(), m_rulers[V2].getPosition());
int y2 = std::max(m_rulers[H1].getPosition(), m_rulers[H2].getPosition());
int x1 = std::min(m_rulers[V1].position(), m_rulers[V2].position());
int y1 = std::min(m_rulers[H1].position(), m_rulers[H2].position());
int x2 = std::max(m_rulers[V1].position(), m_rulers[V2].position());
int y2 = std::max(m_rulers[H1].position(), m_rulers[H2].position());
return gfx::Rect(x1, y1, x2 - x1, y2 - y1);
}
@ -84,21 +84,17 @@ void SelectBoxState::onBeforePopState(Editor* editor)
bool SelectBoxState::onMouseDown(Editor* editor, MouseMessage* msg)
{
if (msg->left() || msg->right()) {
m_movingRuler = -1;
m_startingPos = editor->screenToEditor(msg->position());
if (hasFlag(Flags::Rulers)) {
for (int i=0; i<(int)m_rulers.size(); ++i) {
if (touchRuler(editor, m_rulers[i], msg->position().x, msg->position().y)) {
m_movingRuler = i;
break;
}
}
m_rulersDragAlign = hitTestRulers(editor, msg->position(), true);
if (m_rulersDragAlign)
m_startRulers = m_rulers; // Capture start positions
}
if (hasFlag(Flags::QuickBox) && m_movingRuler == -1) {
if (hasFlag(Flags::QuickBox) && m_movingRulers.empty()) {
m_selectingBox = true;
m_selectingButtons = msg->buttons();
m_startingPos = editor->screenToEditor(msg->position());
setBoxBounds(gfx::Rect(m_startingPos, gfx::Size(1, 1)));
}
@ -110,7 +106,8 @@ bool SelectBoxState::onMouseDown(Editor* editor, MouseMessage* msg)
bool SelectBoxState::onMouseUp(Editor* editor, MouseMessage* msg)
{
m_movingRuler = -1;
m_movingRulers.clear();
m_rulersDragAlign = 0;
if (m_selectingBox) {
m_selectingBox = false;
@ -132,18 +129,18 @@ bool SelectBoxState::onMouseMove(Editor* editor, MouseMessage* msg)
updateContextBar();
if (hasFlag(Flags::Rulers) && m_movingRuler >= 0) {
gfx::Point pt = editor->screenToEditor(msg->position());
if (hasFlag(Flags::Rulers) && !m_movingRulers.empty()) {
gfx::Point newPos = editor->screenToEditor(msg->position());
gfx::Point delta = newPos - m_startingPos;
switch (m_rulers[m_movingRuler].getOrientation()) {
for (int i : m_movingRulers) {
Ruler& ruler = m_rulers[i];
const Ruler& start = m_startRulers[i];
case Ruler::Horizontal:
m_rulers[m_movingRuler].setPosition(pt.y);
break;
case Ruler::Vertical:
m_rulers[m_movingRuler].setPosition(pt.x);
break;
switch (ruler.orientation()) {
case Ruler::Horizontal: ruler.setPosition(start.position() + delta.y); break;
case Ruler::Vertical: ruler.setPosition(start.position() + delta.x); break;
}
}
used = true;
}
@ -175,30 +172,15 @@ bool SelectBoxState::onMouseMove(Editor* editor, MouseMessage* msg)
bool SelectBoxState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos)
{
if (hasFlag(Flags::Rulers)) {
if (m_movingRuler >= 0) {
switch (m_rulers[m_movingRuler].getOrientation()) {
case Ruler::Horizontal:
editor->showMouseCursor(kSizeNSCursor);
return true;
case Ruler::Vertical:
editor->showMouseCursor(kSizeWECursor);
return true;
}
if (!m_movingRulers.empty()) {
editor->showMouseCursor(cursorFromAlign(m_rulersDragAlign));
return true;
}
for (Rulers::iterator it = m_rulers.begin(), end = m_rulers.end(); it != end; ++it) {
if (touchRuler(editor, *it, mouseScreenPos.x, mouseScreenPos.y)) {
switch (it->getOrientation()) {
case Ruler::Horizontal:
editor->showMouseCursor(kSizeNSCursor);
return true;
case Ruler::Vertical:
editor->showMouseCursor(kSizeWECursor);
return true;
}
}
int align = hitTestRulers(editor, mouseScreenPos, false);
if (align != 0) {
editor->showMouseCursor(cursorFromAlign(align));
return true;
}
}
@ -304,14 +286,14 @@ void SelectBoxState::postRenderDecorator(EditorPostRender* render)
// Draw the rulers enclosing the box
if (hasFlag(Flags::Rulers)) {
for (Rulers::iterator it = m_rulers.begin(), end = m_rulers.end(); it != end; ++it) {
switch (it->getOrientation()) {
switch (it->orientation()) {
case Ruler::Horizontal:
render->drawLine(vp.x, it->getPosition(), vp.x+vp.w-1, it->getPosition(), rulerColor);
render->drawLine(vp.x, it->position(), vp.x+vp.w-1, it->position(), rulerColor);
break;
case Ruler::Vertical:
render->drawLine(it->getPosition(), vp.y, it->getPosition(), vp.y+vp.h-1, rulerColor);
render->drawLine(it->position(), vp.y, it->position(), vp.y+vp.h-1, rulerColor);
break;
}
}
@ -333,14 +315,52 @@ void SelectBoxState::updateContextBar()
contextBar->updateForSelectingBox(m_delegate->onGetContextBarHelp());
}
bool SelectBoxState::touchRuler(Editor* editor, Ruler& ruler, int x, int y)
int SelectBoxState::hitTestRulers(Editor* editor,
const gfx::Point& mousePos,
const bool updateMovingRulers)
{
ASSERT(H1 == 0);
ASSERT(H2 == 1);
ASSERT(V1 == 2);
ASSERT(V2 == 3);
int aligns[] = { TOP, BOTTOM, LEFT, RIGHT };
int align = 0;
if (updateMovingRulers)
m_movingRulers.clear();
for (int i=0; i<int(m_rulers.size()); ++i) {
if (hitTestRuler(editor, m_rulers[i], mousePos)) {
align |= aligns[i];
if (updateMovingRulers)
m_movingRulers.push_back(i);
}
}
// Check moving all rulers at the same time
if (align == 0 && !hasFlag(Flags::QuickBox)) {
if (editor->editorToScreen(getBoxBounds()).contains(mousePos)) {
align = LEFT | TOP | RIGHT | BOTTOM;
if (updateMovingRulers) {
// Add all rulers
for (int i=0; i<4; ++i)
m_movingRulers.push_back(i);
}
}
}
return align;
}
bool SelectBoxState::hitTestRuler(Editor* editor, const Ruler& ruler,
const gfx::Point& mousePos)
{
gfx::Point pt = editor->editorToScreen(
gfx::Point(ruler.getPosition(), ruler.getPosition()));
gfx::Point(ruler.position(), ruler.position()));
switch (ruler.getOrientation()) {
case Ruler::Horizontal: return (y >= pt.y-2 && y <= pt.y+2);
case Ruler::Vertical: return (x >= pt.x-2 && x <= pt.x+2);
switch (ruler.orientation()) {
case Ruler::Horizontal: return (mousePos.y >= pt.y-2*guiscale() && mousePos.y <= pt.y+2*guiscale());
case Ruler::Vertical: return (mousePos.x >= pt.x-2*guiscale() && mousePos.x <= pt.x+2*guiscale());
}
return false;
@ -351,4 +371,20 @@ bool SelectBoxState::hasFlag(Flags flag) const
return (int(m_flags) & int(flag)) == int(flag);
}
CursorType SelectBoxState::cursorFromAlign(const int align) const
{
switch (align) {
case LEFT: return kSizeWCursor;
case RIGHT: return kSizeECursor;
case TOP: return kSizeNCursor;
case TOP | LEFT: return kSizeNWCursor;
case TOP | RIGHT: return kSizeNECursor;
case BOTTOM: return kSizeSCursor;
case BOTTOM | LEFT: return kSizeSWCursor;
case BOTTOM | RIGHT: return kSizeSECursor;
case TOP | BOTTOM | LEFT | RIGHT: return kMoveCursor;
}
return kArrowCursor;
}
} // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -11,10 +11,11 @@
#include "app/ui/editor/editor_decorator.h"
#include "app/ui/editor/ruler.h"
#include "app/ui/editor/standby_state.h"
#include "ui/cursor_type.h"
#include "ui/mouse_buttons.h"
#include <vector>
#include <string>
#include <vector>
namespace app {
@ -92,15 +93,25 @@ namespace app {
void updateContextBar();
// This returns a ui align value (e.g. LEFT for the ruler)
int hitTestRulers(Editor* editor,
const gfx::Point& mousePos,
const bool updateMovingRulers);
// Returns true if the position screen position (x, y) is touching
// the given ruler.
bool touchRuler(Editor* editor, Ruler& ruler, int x, int y);
bool hitTestRuler(Editor* editor, const Ruler& ruler,
const gfx::Point& mousePos);
ui::CursorType cursorFromAlign(const int align) const;
bool hasFlag(Flags flag) const;
SelectBoxDelegate* m_delegate;
Rulers m_rulers;
int m_movingRuler;
Rulers m_startRulers;
int m_rulersDragAlign; // Used to calculate the correct mouse cursor
std::vector<int> m_movingRulers;
bool m_selectingBox;
ui::MouseButtons m_selectingButtons;
gfx::Point m_startingPos;