Modify Canvas Size to be more "tool like" (easier to change the edges size, C keyboard shortcut)

This commit is contained in:
David Capello 2019-04-22 15:57:45 -03:00
parent af0b700a6d
commit bbba80c809
5 changed files with 103 additions and 47 deletions

View File

@ -62,6 +62,7 @@
<key command="KeyboardShortcuts" shortcut="Ctrl+Alt+Shift+K" mac="Cmd+Alt+Shift+K" /> <key command="KeyboardShortcuts" shortcut="Ctrl+Alt+Shift+K" mac="Cmd+Alt+Shift+K" />
<!-- Sprite --> <!-- Sprite -->
<key command="SpriteProperties" shortcut="Ctrl+P" mac="Cmd+P" /> <key command="SpriteProperties" shortcut="Ctrl+P" mac="Cmd+P" />
<key command="CanvasSize" shortcut="C" />
<!-- Layer --> <!-- Layer -->
<key command="LayerProperties" shortcut="Shift+P" /> <key command="LayerProperties" shortcut="Shift+P" />
<key command="LayerVisibility" shortcut="Shift+X" /> <key command="LayerVisibility" shortcut="Shift+X" />
@ -502,7 +503,7 @@
<key tool="eyedropper" shortcut="I" /> <key tool="eyedropper" shortcut="I" />
<key tool="hand" shortcut="H" /> <key tool="hand" shortcut="H" />
<key tool="move" shortcut="V" /> <key tool="move" shortcut="V" />
<key tool="slice" shortcut="C" /> <key tool="slice" shortcut="Ctrl+Alt+C" mac="Cmd+Alt+C" />
<key tool="zoom" shortcut="Z" /> <key tool="zoom" shortcut="Z" />
<key tool="paint_bucket" shortcut="G" /> <key tool="paint_bucket" shortcut="G" />

View File

@ -17,9 +17,11 @@
#include "app/tx.h" #include "app/tx.h"
#include "app/ui/button_set.h" #include "app/ui/button_set.h"
#include "app/ui/color_bar.h" #include "app/ui/color_bar.h"
#include "app/ui/doc_view.h"
#include "app/ui/editor/editor.h" #include "app/ui/editor/editor.h"
#include "app/ui/editor/select_box_state.h" #include "app/ui/editor/select_box_state.h"
#include "app/ui/skin/skin_theme.h" #include "app/ui/skin/skin_theme.h"
#include "app/ui_context.h"
#include "base/bind.h" #include "base/bind.h"
#include "doc/image.h" #include "doc/image.h"
#include "doc/mask.h" #include "doc/mask.h"
@ -312,7 +314,15 @@ void CanvasSizeCommand::onExecute(Context* context)
std::unique_ptr<CanvasSizeWindow> window(new CanvasSizeWindow()); std::unique_ptr<CanvasSizeWindow> window(new CanvasSizeWindow());
window->remapWindow(); window->remapWindow();
window->centerWindow();
// Find best position for the window on the editor
if (DocView* docView = static_cast<UIContext*>(context)->activeView()) {
window->positionWindow(
docView->bounds().x2() - window->bounds().w,
docView->bounds().y);
}
else
window->centerWindow();
load_window_pos(window.get(), "CanvasSize"); load_window_pos(window.get(), "CanvasSize");
window->setVisible(true); window->setVisible(true);

View File

@ -1,4 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello // Copyright (C) 2001-2017 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -8,33 +9,34 @@
#define APP_UI_EDITOR_RULER_H_INCLUDED #define APP_UI_EDITOR_RULER_H_INCLUDED
#pragma once #pragma once
#include "ui/base.h"
namespace app { namespace app {
// A ruler inside the editor. It is used by SelectBoxState to show // A ruler inside the editor. It is used by SelectBoxState to show
// rulers that can be dragged by the user. // rulers that can be dragged by the user.
class Ruler { class Ruler {
public: public:
enum Orientation { Horizontal, Vertical };
Ruler() Ruler()
: m_orientation(Horizontal) : m_align(0)
, m_position(0) { , m_position(0) {
} }
Ruler(Orientation orientation, int position) Ruler(const int align,
: m_orientation(orientation) const int position)
: m_align(align)
, m_position(position) { , m_position(position) {
} }
Orientation orientation() const { return m_orientation; } int align() const { return m_align; }
int position() const { return m_position; } int position() const { return m_position; }
void setPosition(int position) { void setPosition(const int position) {
m_position = position; m_position = position;
} }
private: private:
Orientation m_orientation; int m_align;
int m_position; int m_position;
}; };

View File

@ -79,16 +79,16 @@ gfx::Rect SelectBoxState::getBoxBounds() const
void SelectBoxState::setBoxBounds(const gfx::Rect& box) void SelectBoxState::setBoxBounds(const gfx::Rect& box)
{ {
m_rulers[H1] = Ruler(HORIZONTAL | TOP, box.y);
m_rulers[H2] = Ruler(HORIZONTAL | BOTTOM, box.y+box.h);
m_rulers[V1] = Ruler(VERTICAL | LEFT, box.x);
m_rulers[V2] = Ruler(VERTICAL | RIGHT, box.x+box.w);
if (hasFlag(Flags::PaddingRulers)) { if (hasFlag(Flags::PaddingRulers)) {
int w = m_rulers[PV].position() - m_rulers[V2].position(); const gfx::Size padding(
int h = m_rulers[PH].position() - m_rulers[H2].position(); m_rulers[PV].position() - m_rulers[V2].position(),
m_rulers[PH] = Ruler(Ruler::Horizontal, m_rulers[H2].position() + h); m_rulers[PH].position() - m_rulers[H2].position());
m_rulers[PV] = Ruler(Ruler::Vertical, m_rulers[V2].position() + w); setPaddingBounds(padding);
} }
m_rulers[H1] = Ruler(Ruler::Horizontal, box.y);
m_rulers[H2] = Ruler(Ruler::Horizontal, box.y+box.h);
m_rulers[V1] = Ruler(Ruler::Vertical, box.x);
m_rulers[V2] = Ruler(Ruler::Vertical, box.x+box.w);
} }
// Get and Set Padding for Import Sprite Sheet box state // Get and Set Padding for Import Sprite Sheet box state
@ -107,8 +107,8 @@ gfx::Size SelectBoxState::getPaddingBounds() const
void SelectBoxState::setPaddingBounds(const gfx::Size& padding) void SelectBoxState::setPaddingBounds(const gfx::Size& padding)
{ {
ASSERT(hasFlag(Flags::PaddingRulers)); ASSERT(hasFlag(Flags::PaddingRulers));
m_rulers[PH] = Ruler(Ruler::Horizontal, m_rulers[H2].position() + padding.h); m_rulers[PH] = Ruler(HORIZONTAL | BOTTOM, m_rulers[H2].position() + padding.h);
m_rulers[PV] = Ruler(Ruler::Vertical, m_rulers[V2].position() + padding.w); m_rulers[PV] = Ruler(VERTICAL | RIGHT, m_rulers[V2].position() + padding.w);
} }
void SelectBoxState::onEnterState(Editor* editor) void SelectBoxState::onEnterState(Editor* editor)
@ -187,11 +187,10 @@ bool SelectBoxState::onMouseMove(Editor* editor, MouseMessage* msg)
for (int i : m_movingRulers) { for (int i : m_movingRulers) {
Ruler& ruler = m_rulers[i]; Ruler& ruler = m_rulers[i];
const Ruler& start = m_startRulers[i]; const Ruler& start = m_startRulers[i];
int oppositeRuler = i^1;// 0 and 1 are opposites, and 2 and 3 Ruler& oppRuler = oppositeRuler(i);
Ruler& oppRuler = m_rulers[oppositeRuler];
switch (ruler.orientation()) { switch (ruler.align() & (HORIZONTAL | VERTICAL)) {
case Ruler::Horizontal: case HORIZONTAL:
if (hasFlag(Flags::PaddingRulers) && (i == H2)) { if (hasFlag(Flags::PaddingRulers) && (i == H2)) {
int pad = m_rulers[PH].position() - m_rulers[H2].position(); int pad = m_rulers[PH].position() - m_rulers[H2].position();
m_rulers[PH].setPosition(start.position() + delta.y + pad); m_rulers[PH].setPosition(start.position() + delta.y + pad);
@ -201,7 +200,7 @@ bool SelectBoxState::onMouseMove(Editor* editor, MouseMessage* msg)
oppRuler.setPosition(editor->sprite()->height() oppRuler.setPosition(editor->sprite()->height()
- start.position() - delta.y); - start.position() - delta.y);
break; break;
case Ruler::Vertical: case VERTICAL:
if (hasFlag(Flags::PaddingRulers) && (i == V2)) { if (hasFlag(Flags::PaddingRulers) && (i == V2)) {
int pad = m_rulers[PV].position() - m_rulers[V2].position(); int pad = m_rulers[PV].position() - m_rulers[V2].position();
m_rulers[PV].setPosition(start.position() + delta.x + pad); m_rulers[PV].setPosition(start.position() + delta.x + pad);
@ -462,7 +461,7 @@ void SelectBoxState::postRenderDecorator(EditorPostRender* render)
render->fillRect(dark, gfx::Rect(rc.x2(), rc.y, vp.x2()-rc.x2(), rc.h)); render->fillRect(dark, gfx::Rect(rc.x2(), rc.y, vp.x2()-rc.x2(), rc.h));
} }
} }
// Draw the grid rulers when padding is posible (i.e. Flag::PaddingRulers=true) // Draw the grid rulers when padding is posible (i.e. Flag::PaddingRulers=true)
if (hasFlag(Flags::PaddingRulers)) { if (hasFlag(Flags::PaddingRulers)) {
if (hasFlag(Flags::HGrid) && hasFlag(Flags::VGrid)) { if (hasFlag(Flags::HGrid) && hasFlag(Flags::VGrid)) {
@ -527,15 +526,15 @@ void SelectBoxState::postRenderDecorator(EditorPostRender* render)
// Draw the rulers enclosing the box // Draw the rulers enclosing the box
if (hasFlag(Flags::Rulers)) { if (hasFlag(Flags::Rulers)) {
for (const Ruler& ruler : m_rulers) { for (const Ruler& ruler : m_rulers) {
switch (ruler.orientation()) { switch (ruler.align() & (HORIZONTAL | VERTICAL)) {
case Ruler::Horizontal: { case HORIZONTAL: {
const int y = ruler.position()+mainOffset.y; const int y = ruler.position()+mainOffset.y;
render->drawLine(rulerColor, vp.x, y, vp.x+vp.w-1, y); render->drawLine(rulerColor, vp.x, y, vp.x+vp.w-1, y);
break; break;
} }
case Ruler::Vertical: { case VERTICAL: {
const int x = ruler.position()+mainOffset.x; const int x = ruler.position()+mainOffset.x;
render->drawLine(rulerColor, x, vp.y, x, vp.y+vp.h-1); render->drawLine(rulerColor, x, vp.y, x, vp.y+vp.h-1);
break; break;
@ -560,6 +559,12 @@ void SelectBoxState::updateContextBar()
contextBar->updateForSelectingBox(m_delegate->onGetContextBarHelp()); contextBar->updateForSelectingBox(m_delegate->onGetContextBarHelp());
} }
Ruler& SelectBoxState::oppositeRuler(const int rulerIndex)
{
// 0 and 1 are opposites, and 2 and 3
return m_rulers[rulerIndex ^ 1];
}
int SelectBoxState::hitTestRulers(Editor* editor, int SelectBoxState::hitTestRulers(Editor* editor,
const gfx::Point& mousePos, const gfx::Point& mousePos,
const bool updateMovingRulers) const bool updateMovingRulers)
@ -568,15 +573,22 @@ int SelectBoxState::hitTestRulers(Editor* editor,
ASSERT(H2 == 1); ASSERT(H2 == 1);
ASSERT(V1 == 2); ASSERT(V1 == 2);
ASSERT(V2 == 3); ASSERT(V2 == 3);
int aligns[] = { TOP, BOTTOM, LEFT, RIGHT, BOTTOM, RIGHT };
int align = 0; int align = 0;
if (updateMovingRulers) if (updateMovingRulers)
m_movingRulers.clear(); m_movingRulers.clear();
for (int i=0; i<int(m_rulers.size()); ++i) { for (int i=0; i<int(m_rulers.size()); ++i) {
if (hitTestRuler(editor, m_rulers[i], mousePos)) { const Ruler& ruler = m_rulers[i];
align |= aligns[i]; const Ruler& oppRuler = oppositeRuler(i);
if (hitTestRuler(editor, ruler, oppRuler, mousePos)) {
if (!hasFlag(Flags::PaddingRulers) &&
(((ruler.align() & (LEFT | TOP)) && ruler.position() > oppRuler.position()) ||
((ruler.align() & (RIGHT | BOTTOM)) && ruler.position() <= oppRuler.position())))
align |= oppRuler.align();
else
align |= ruler.align();
if (updateMovingRulers) if (updateMovingRulers)
m_movingRulers.push_back(i); m_movingRulers.push_back(i);
} }
@ -599,25 +611,52 @@ int SelectBoxState::hitTestRulers(Editor* editor,
return align; return align;
} }
bool SelectBoxState::hitTestRuler(Editor* editor, const Ruler& ruler, int SelectBoxState::hitTestRuler(Editor* editor,
const gfx::Point& mousePos) const Ruler& ruler,
const Ruler& oppRuler,
const gfx::Point& mousePos)
{ {
gfx::Point pt = editor->mainTilePosition(); gfx::Point pt = editor->mainTilePosition();
pt = editor->editorToScreen( pt = editor->editorToScreen(
pt + gfx::Point(ruler.position(), ruler.position())); pt + gfx::Point(ruler.position(), ruler.position()));
switch (ruler.orientation()) { switch (ruler.align() & (HORIZONTAL | VERTICAL)) {
case Ruler::Horizontal: case HORIZONTAL:
return (mousePos.y >= pt.y-2*guiscale() && if (!hasFlag(Flags::PaddingRulers)) {
mousePos.y <= pt.y+2*guiscale()); if (ruler.position() <= oppRuler.position()) {
if (mousePos.y <= pt.y+2*guiscale())
return ruler.align();
}
else if (ruler.position() > oppRuler.position()) {
if (mousePos.y >= pt.y-2*guiscale())
return ruler.align();
}
}
if (mousePos.y >= pt.y-2*guiscale() &&
mousePos.y <= pt.y+2*guiscale()) {
return ruler.align();
}
break;
case Ruler::Vertical: case VERTICAL:
return (mousePos.x >= pt.x-2*guiscale() && if (!hasFlag(Flags::PaddingRulers)) {
mousePos.x <= pt.x+2*guiscale()); if (ruler.position() <= oppRuler.position()) {
if (mousePos.x <= pt.x+2*guiscale())
return ruler.align();
}
else if (ruler.position() > oppRuler.position()) {
if (mousePos.x >= pt.x-2*guiscale())
return ruler.align();
}
}
if (mousePos.x >= pt.x-2*guiscale() &&
mousePos.x <= pt.x+2*guiscale())
return ruler.align();
break;
} }
return false; return 0;
} }
bool SelectBoxState::hasFlag(Flags flag) const bool SelectBoxState::hasFlag(Flags flag) const
@ -627,7 +666,7 @@ bool SelectBoxState::hasFlag(Flags flag) const
CursorType SelectBoxState::cursorFromAlign(const int align) const CursorType SelectBoxState::cursorFromAlign(const int align) const
{ {
switch (align) { switch (align & (LEFT | TOP | RIGHT | BOTTOM)) {
case LEFT: return kSizeWCursor; case LEFT: return kSizeWCursor;
case RIGHT: return kSizeECursor; case RIGHT: return kSizeECursor;
case TOP: return kSizeNCursor; case TOP: return kSizeNCursor;

View File

@ -107,16 +107,20 @@ namespace app {
typedef std::vector<Ruler> Rulers; typedef std::vector<Ruler> Rulers;
void updateContextBar(); void updateContextBar();
Ruler& oppositeRuler(const int rulerIndex);
// This returns a ui align value (e.g. LEFT for the ruler) // This returns a ui align value (e.g. LEFT for the ruler)
int hitTestRulers(Editor* editor, int hitTestRulers(Editor* editor,
const gfx::Point& mousePos, const gfx::Point& mousePos,
const bool updateMovingRulers); const bool updateMovingRulers);
// Returns true if the position screen position (x, y) is touching // Returns 0 if the mouse position on screen (mousePos) is not
// the given ruler. // touching any ruler, or in other case returns the alignment of
bool hitTestRuler(Editor* editor, const Ruler& ruler, // the ruler being touch (useful to show a proper mouse cursor).
const gfx::Point& mousePos); int hitTestRuler(Editor* editor,
const Ruler& ruler,
const Ruler& oppRuler,
const gfx::Point& mousePos);
ui::CursorType cursorFromAlign(const int align) const; ui::CursorType cursorFromAlign(const int align) const;