Skip to content

Commit

Permalink
Improve canvas size UI
Browse files Browse the repository at this point in the history
Now we can resize from corners (fix aseprite#1394) or move the whole canvas to
other position dragging the box from the center.
  • Loading branch information
dacap committed Apr 7, 2017
1 parent 4250809 commit 4f5127f
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 76 deletions.
22 changes: 6 additions & 16 deletions src/app/ui/editor/ruler.h
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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;
}

int getPosition() const
{
return m_position;
}
Orientation orientation() const { return m_orientation; }
int position() const { return m_position; }

void setPosition(int position)
{
void setPosition(int position) {
m_position = position;
}

Expand Down
148 changes: 92 additions & 56 deletions src/app/ui/editor/select_box_state.cpp
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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)
{
Expand All @@ -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);
}

Expand Down Expand Up @@ -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)));
}

Expand All @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
Expand All @@ -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
19 changes: 15 additions & 4 deletions src/app/ui/editor/select_box_state.h
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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 {

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 4f5127f

Please sign in to comment.