From 210e33f76aa7ce77bc7d2ad681b774412fb27eda Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 21 Apr 2011 17:39:43 -0300 Subject: [PATCH] Improve "Canvas Size" command to show rulers to change the canvas size. + Added EditorDecorator and EditorState::getDecorator(). + Added EditorPreRender and EditorPostRender classes. + Added Image::rectblend and image_rectblend functions to draw transparent rectangles. + Added SelectTileState and Ruler classes. --- data/widgets/canvas_size.xml | 4 +- src/CMakeLists.txt | 1 + src/commands/cmd_canvas_size.cpp | 106 ++++++++++--- src/raster/image.cpp | 27 ++++ src/raster/image.h | 2 + src/raster/image_impl.h | 21 +++ src/widgets/editor/editor.cpp | 80 +++++++++- src/widgets/editor/editor_decorator.h | 56 +++++++ src/widgets/editor/editor_state.h | 4 + src/widgets/editor/ruler.h | 61 ++++++++ src/widgets/editor/select_tile_state.cpp | 189 +++++++++++++++++++++++ src/widgets/editor/select_tile_state.h | 74 +++++++++ 12 files changed, 600 insertions(+), 25 deletions(-) create mode 100644 src/widgets/editor/editor_decorator.h create mode 100644 src/widgets/editor/ruler.h create mode 100644 src/widgets/editor/select_tile_state.cpp create mode 100644 src/widgets/editor/select_tile_state.h diff --git a/data/widgets/canvas_size.xml b/data/widgets/canvas_size.xml index 276a95ae2..42e435f29 100644 --- a/data/widgets/canvas_size.xml +++ b/data/widgets/canvas_size.xml @@ -1,8 +1,7 @@ - - + - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 03a9a7af5..e870a979c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -289,6 +289,7 @@ add_library(aseprite-library widgets/editor/moving_pixels_state.cpp widgets/editor/pixels_movement.cpp widgets/editor/scrolling_state.cpp + widgets/editor/select_tile_state.cpp widgets/editor/standby_state.cpp widgets/editor/tool_loop_impl.cpp widgets/fileview.cpp diff --git a/src/commands/cmd_canvas_size.cpp b/src/commands/cmd_canvas_size.cpp index 40c3db1cb..b8b55c588 100644 --- a/src/commands/cmd_canvas_size.cpp +++ b/src/commands/cmd_canvas_size.cpp @@ -19,18 +19,97 @@ #include "config.h" #include "app/color_utils.h" +#include "base/unique_ptr.h" #include "commands/command.h" #include "document_wrappers.h" #include "gui/gui.h" +#include "modules/editors.h" #include "modules/gui.h" #include "raster/image.h" #include "raster/mask.h" #include "raster/sprite.h" #include "undo_transaction.h" #include "widgets/color_bar.h" +#include "widgets/editor/editor.h" +#include "widgets/editor/select_tile_state.h" #include +// Frame used to show canvas parameters. +class CanvasSizeFrame : public Frame + , public SelectTileDelegate +{ +public: + CanvasSizeFrame(int left, int top, int right, int bottom) + : Frame(false, "Canvas Size") + , m_editor(current_editor) + , m_rect(-left, -top, + current_editor->getSprite()->getWidth() + right, + current_editor->getSprite()->getHeight() + bottom) + { + m_mainBox = load_widget("canvas_size.xml", "main_box"); + get_widgets(m_mainBox, + "left", &m_left, + "top", &m_top, + "right", &m_right, + "bottom", &m_bottom, + "ok", &m_ok, NULL); + + addChild(m_mainBox); + + m_left->setTextf("%d", left); + m_right->setTextf("%d", right); + m_top->setTextf("%d", top); + m_bottom->setTextf("%d", bottom); + + m_editor->setDefaultState(EditorStatePtr(new SelectTileState(this, m_rect))); + } + + ~CanvasSizeFrame() + { + m_editor->setDefaultState(EditorStatePtr(new StandbyState)); + } + + bool pressedOk() { return get_killer() == m_ok; } + + int getLeft() const { return m_left->getTextInt(); } + int getRight() const { return m_right->getTextInt(); } + int getTop() const { return m_top->getTextInt(); } + int getBottom() const { return m_bottom->getTextInt(); } + + // SelectTileDelegate impleentation + virtual void onChangeRectangle(const gfx::Rect& rect) OVERRIDE + { + m_rect = rect; + + m_left->setTextf("%d", -m_rect.x); + m_top->setTextf("%d", -m_rect.y); + m_right->setTextf("%d", (m_rect.x + m_rect.w) - current_editor->getSprite()->getWidth()); + m_bottom->setTextf("%d", (m_rect.y + m_rect.h) - current_editor->getSprite()->getHeight()); + } + +protected: + virtual void onBroadcastMouseMessage(WidgetsList& targets) OVERRIDE + { + Frame::onBroadcastMouseMessage(targets); + + // Add the editor as receptor of mouse events too. + targets.push_back(View::getView(m_editor)); + } + +private: + Editor* m_editor; + Widget* m_mainBox; + Widget* m_left; + Widget* m_right; + Widget* m_top; + Widget* m_bottom; + Widget* m_ok; + gfx::Rect m_rect; +}; + +////////////////////////////////////////////////////////////////////// + class CanvasSizeCommand : public Command { int m_left, m_right, m_top, m_bottom; @@ -64,40 +143,27 @@ void CanvasSizeCommand::onExecute(Context* context) const Sprite* sprite(document->getSprite()); if (context->isUiAvailable()) { - JWidget left, top, right, bottom, ok; - // load the window widget - FramePtr window(load_widget("canvas_size.xml", "canvas_size")); - get_widgets(window, - "left", &left, - "top", &top, - "right", &right, - "bottom", &bottom, - "ok", &ok, NULL); + UniquePtr window(new CanvasSizeFrame(0, 0, 0, 0)); window->remap_window(); window->center_window(); - left->setTextf("%d", m_left); - right->setTextf("%d", m_right); - top->setTextf("%d", m_top); - bottom->setTextf("%d", m_bottom); - load_window_pos(window, "CanvasSize"); window->setVisible(true); window->open_window_fg(); save_window_pos(window, "CanvasSize"); - if (window->get_killer() != ok) + if (!window->pressedOk()) return; - m_left = left->getTextInt(); - m_right = right->getTextInt(); - m_top = top->getTextInt(); - m_bottom = bottom->getTextInt(); + m_left = window->getLeft(); + m_right = window->getRight(); + m_top = window->getTop(); + m_bottom = window->getBottom(); } - // resize canvas + // Resize canvas int x1 = -m_left; int y1 = -m_top; diff --git a/src/raster/image.cpp b/src/raster/image.cpp index b87a50b82..778d7f039 100644 --- a/src/raster/image.cpp +++ b/src/raster/image.cpp @@ -296,6 +296,33 @@ void image_rectfill(Image* image, int x1, int y1, int x2, int y2, int color) image->rectfill(x1, y1, x2, y2, color); } +void image_rectblend(Image* image, int x1, int y1, int x2, int y2, int color, int opacity) +{ + int t; + + if (x1 > x2) { + t = x1; + x1 = x2; + x2 = t; + } + + if (y1 > y2) { + t = y1; + y1 = y2; + y2 = t; + } + + if ((x2 < 0) || (x1 >= image->w) || (y2 < 0) || (y1 >= image->h)) + return; + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + if (x2 >= image->w) x2 = image->w-1; + if (y2 >= image->h) y2 = image->h-1; + + image->rectblend(x1, y1, x2, y2, color, opacity); +} + typedef struct Data { Image* image; diff --git a/src/raster/image.h b/src/raster/image.h index 53217afb9..a71122c94 100644 --- a/src/raster/image.h +++ b/src/raster/image.h @@ -64,6 +64,7 @@ public: virtual void merge(const Image* src, int x, int y, int opacity, int blend_mode) = 0; virtual void hline(int x1, int y, int x2, int color) = 0; virtual void rectfill(int x1, int y1, int x2, int y2, int color) = 0; + virtual void rectblend(int x1, int y1, int x2, int y2, int color, int opacity) = 0; virtual void to_allegro(BITMAP* bmp, int x, int y, const Palette* palette) const = 0; }; @@ -90,6 +91,7 @@ void image_hline(Image* image, int x1, int y, int x2, int color); void image_vline(Image* image, int x, int y1, int y2, int color); void image_rect(Image* image, int x1, int y1, int x2, int y2, int color); void image_rectfill(Image* image, int x1, int y1, int x2, int y2, int color); +void image_rectblend(Image* image, int x1, int y1, int x2, int y2, int color, int opacity); void image_line(Image* image, int x1, int y1, int x2, int y2, int color); void image_ellipse(Image* image, int x1, int y1, int x2, int y2, int color); void image_ellipsefill(Image* image, int x1, int y1, int x2, int y2, int color); diff --git a/src/raster/image_impl.h b/src/raster/image_impl.h index 533d3cd3c..a2e5f0b1b 100644 --- a/src/raster/image_impl.h +++ b/src/raster/image_impl.h @@ -19,6 +19,7 @@ #ifndef RASTER_IMAGE_IMPL_H_INCLUDED #define RASTER_IMAGE_IMPL_H_INCLUDED +#include "raster/blend.h" #include "raster/image.h" #include "raster/palette.h" @@ -221,6 +222,11 @@ public: } } + virtual void rectblend(int x1, int y1, int x2, int y2, int color, int opacity) + { + rectfill(x1, y1, x2, y2, color); + } + virtual void to_allegro(BITMAP* bmp, int x, int y, const Palette* palette) const; }; @@ -228,6 +234,21 @@ public: ////////////////////////////////////////////////////////////////////// // Specializations +template<> +void ImageImpl::rectblend(int x1, int y1, int x2, int y2, int color, int opacity) +{ + address_t addr; + int x, y; + + for (y=y1; y<=y2; ++y) { + addr = line_address(y)+x1; + for (x=x1; x<=x2; ++x) { + *addr = _rgba_blend_normal(*addr, color, opacity); + ++addr; + } + } +} + template<> void ImageImpl::clear(int color) { diff --git a/src/widgets/editor/editor.cpp b/src/widgets/editor/editor.cpp index 89b64b2ab..79e57b901 100644 --- a/src/widgets/editor/editor.cpp +++ b/src/widgets/editor/editor.cpp @@ -42,6 +42,7 @@ #include "util/misc.h" #include "util/render.h" #include "widgets/color_bar.h" +#include "widgets/editor/editor_decorator.h" #include "widgets/editor/standby_state.h" #include "widgets/statebar.h" @@ -50,6 +51,68 @@ using namespace gfx; +class EditorPreRenderImpl : public EditorPreRender +{ +public: + EditorPreRenderImpl(Editor* editor, Image* image, Point& offset, int zoom) + : m_editor(editor) + , m_image(image) + , m_offset(offset) + , m_zoom(zoom) + { + } + + Editor* getEditor() OVERRIDE + { + return m_editor; + } + + Image* getImage() OVERRIDE + { + return m_image; + } + + void fillRect(const gfx::Rect& rect, uint32_t rgbaColor, int opacity) OVERRIDE + { + image_rectblend(m_image, + m_offset.x + (rect.x << m_zoom), + m_offset.y + (rect.y << m_zoom), + m_offset.x + ((rect.x+rect.w) << m_zoom) - 1, + m_offset.y + ((rect.y+rect.h) << m_zoom) - 1, rgbaColor, opacity); + } + +private: + Editor* m_editor; + Image* m_image; + Point m_offset; + int m_zoom; +}; + +class EditorPostRenderImpl : public EditorPostRender +{ +public: + EditorPostRenderImpl(Editor* editor) + : m_editor(editor) + { + } + + Editor* getEditor() + { + return m_editor; + } + + void drawLine(int x1, int y1, int x2, int y2, int screenColor) + { + int u1, v1, u2, v2; + m_editor->editorToScreen(x1, y1, &u1, &v1); + m_editor->editorToScreen(x2, y2, &u2, &v2); + line(ji_screen, u1, v1, u2, v2, screenColor); + } + +private: + Editor* m_editor; +}; + Editor::Editor() : Widget(editor_type()) , m_defaultState(EditorStatePtr(new StandbyState())) @@ -328,6 +391,13 @@ void Editor::drawSprite(int x1, int y1, int x2, int y2) m_zoom, true); if (rendered) { + // Pre-render decorator. + if (EditorDecorator* decorator = m_defaultState->getDecorator()) { + EditorPreRenderImpl preRender(this, rendered, + Point(-source_x, -source_y), m_zoom); + decorator->preRenderDecorator(&preRender); + } + #ifdef DRAWSPRITE_DOUBLEBUFFERED BITMAP *bmp = create_bitmap(width, height); @@ -362,6 +432,12 @@ void Editor::drawSprite(int x1, int y1, int x2, int y2) if (settings->getGridVisible()) this->drawGrid(settings->getGridBounds(), settings->getGridColor()); + + // Post-render decorator. + if (EditorDecorator* decorator = m_defaultState->getDecorator()) { + EditorPostRenderImpl postRender(this); + decorator->postRenderDecorator(&postRender); + } } void Editor::drawSpriteSafe(int x1, int y1, int x2, int y2) @@ -690,10 +766,10 @@ void Editor::removeListener(EditorListener* listener) } // Returns the visible area of the active sprite. -gfx::Rect Editor::getVisibleSpriteBounds() +Rect Editor::getVisibleSpriteBounds() { // Return an empty rectangle if there is not a active sprite. - if (!m_sprite) return gfx::Rect(); + if (!m_sprite) return Rect(); View* view = View::getView(this); Rect vp = view->getViewportBounds(); diff --git a/src/widgets/editor/editor_decorator.h b/src/widgets/editor/editor_decorator.h new file mode 100644 index 000000000..0e153e00b --- /dev/null +++ b/src/widgets/editor/editor_decorator.h @@ -0,0 +1,56 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef WIDGETS_EDITOR_EDITOR_DECORATOR_H_INCLUDED +#define WIDGETS_EDITOR_EDITOR_DECORATOR_H_INCLUDED + +namespace gfx { + class Rect; +} + +class Editor; +class EditorDecorator; +class Graphics; +class Image; + +class EditorPreRender +{ +public: + virtual ~EditorPreRender() { } + virtual Editor* getEditor() = 0; + virtual Image* getImage() = 0; + virtual void fillRect(const gfx::Rect& rect, uint32_t rgbaColor, int opacity) = 0; +}; + +class EditorPostRender +{ +public: + virtual ~EditorPostRender() { } + virtual Editor* getEditor() = 0; + virtual void drawLine(int x1, int y1, int x2, int y2, int screenColor) = 0; +}; + +class EditorDecorator +{ +public: + virtual ~EditorDecorator() { } + virtual void preRenderDecorator(EditorPreRender* render) = 0; + virtual void postRenderDecorator(EditorPostRender* render) = 0; +}; + +#endif // WIDGETS_EDITOR_EDITOR_DECORATOR_H_INCLUDED diff --git a/src/widgets/editor/editor_state.h b/src/widgets/editor/editor_state.h index c6036bccf..bd0d9cad2 100644 --- a/src/widgets/editor/editor_state.h +++ b/src/widgets/editor/editor_state.h @@ -20,6 +20,7 @@ #define WIDGETS_EDITOR_EDITOR_STATE_H_INCLUDED class Editor; +class EditorDecorator; union Message; // Represents one state of the sprite's editor (Editor class). This @@ -76,6 +77,9 @@ public: // drawing cursor. virtual bool requirePenPreview() { return false; } + // Called after the sprite is painted. + virtual EditorDecorator* getDecorator() { return NULL; } + }; #endif // WIDGETS_EDITOR_EDITOR_STATE_H_INCLUDED diff --git a/src/widgets/editor/ruler.h b/src/widgets/editor/ruler.h new file mode 100644 index 000000000..6d005fa42 --- /dev/null +++ b/src/widgets/editor/ruler.h @@ -0,0 +1,61 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef WIDGETS_EDITOR_RULER_H_INCLUDED +#define WIDGETS_EDITOR_RULER_H_INCLUDED + +// A ruler inside the editor. It is used by SelectTileState to show +// rulers that can be dragged by the user. +class Ruler +{ +public: + enum Orientation { Horizontal, Vertical }; + + Ruler() + : m_orientation(Horizontal) + , m_position(0) + { + } + + Ruler(Orientation orientation, int position) + : m_orientation(orientation) + , m_position(position) + { + } + + Orientation getOrientation() const + { + return m_orientation; + } + + int getPosition() const + { + return m_position; + } + + void setPosition(int position) + { + m_position = position; + } + +private: + Orientation m_orientation; + int m_position; +}; + +#endif // WIDGETS_EDITOR_RULER_H_INCLUDED diff --git a/src/widgets/editor/select_tile_state.cpp b/src/widgets/editor/select_tile_state.cpp new file mode 100644 index 000000000..f7ac24100 --- /dev/null +++ b/src/widgets/editor/select_tile_state.cpp @@ -0,0 +1,189 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "widgets/editor/select_tile_state.h" + +#include "gfx/rect.h" +#include "gui/message.h" +#include "gui/system.h" +#include "gui/view.h" +#include "raster/image.h" +#include "raster/sprite.h" +#include "widgets/editor/editor.h" + +#include + +SelectTileState::SelectTileState(SelectTileDelegate* delegate, const gfx::Rect& rc) + : m_delegate(delegate) + , m_rulers(4) + , m_movingRuler(-1) +{ + m_rulers[H1] = Ruler(Ruler::Horizontal, rc.y); + m_rulers[H2] = Ruler(Ruler::Horizontal, rc.y+rc.h); + m_rulers[V1] = Ruler(Ruler::Vertical, rc.x); + m_rulers[V2] = Ruler(Ruler::Vertical, rc.x+rc.w); +} + +bool SelectTileState::onMouseDown(Editor* editor, Message* msg) +{ + if (msg->mouse.left || msg->mouse.right) { + m_movingRuler = -1; + + for (int i=0; i<(int)m_rulers.size(); ++i) { + if (touchRuler(editor, m_rulers[i], msg->mouse.x, msg->mouse.y)) { + m_movingRuler = i; + break; + } + } + + editor->captureMouse(); + return true; + } + + return StandbyState::onMouseDown(editor, msg); +} + +bool SelectTileState::onMouseUp(Editor* editor, Message* msg) +{ + m_movingRuler = -1; + return StandbyState::onMouseUp(editor, msg); +} + +bool SelectTileState::onMouseMove(Editor* editor, Message* msg) +{ + if (m_movingRuler >= 0) { + int u, v; + editor->screenToEditor(msg->mouse.x, msg->mouse.y, &u, &v); + + switch (m_rulers[m_movingRuler].getOrientation()) { + + case Ruler::Horizontal: + m_rulers[m_movingRuler].setPosition(v); + break; + + case Ruler::Vertical: + m_rulers[m_movingRuler].setPosition(u); + break; + } + + if (m_delegate) + m_delegate->onChangeRectangle(getBoxBounds()); + + editor->invalidate(); + return true; + } + return StandbyState::onMouseMove(editor, msg); +} + +bool SelectTileState::onSetCursor(Editor* editor) +{ + int x = jmouse_x(0); + int y = jmouse_y(0); + + for (Rulers::iterator it = m_rulers.begin(), end = m_rulers.end(); it != end; ++it) { + if (touchRuler(editor, *it, x, y)) { + switch (it->getOrientation()) { + case Ruler::Horizontal: + jmouse_set_cursor(JI_CURSOR_SIZE_T); + return true; + case Ruler::Vertical: + jmouse_set_cursor(JI_CURSOR_SIZE_L); + return true; + } + } + } + + return false; +} + +EditorDecorator* SelectTileState::getDecorator() +{ + return this; +} + +void SelectTileState::preRenderDecorator(EditorPreRender* render) +{ + gfx::Rect rc = getBoxBounds(); + Image* image = render->getImage(); + Sprite* sprite = render->getEditor()->getSprite(); + int sprite_w = sprite->getWidth(); + int sprite_h = sprite->getHeight(); + + // Top band + if (rc.y > 0) + render->fillRect(gfx::Rect(0, 0, sprite_w, rc.y), _rgba(0, 0, 0, 255), 128); + + // Bottom band + if (rc.y+rc.h < sprite_h) + render->fillRect(gfx::Rect(0, rc.y+rc.h, sprite_w, sprite_h-(rc.y+rc.h)), _rgba(0, 0, 0, 255), 128); + + // Left band + if (rc.x > 0) + render->fillRect(gfx::Rect(0, rc.y, rc.x, rc.h), _rgba(0, 0, 0, 255), 128); + + // Right band + if (rc.x+rc.w < sprite_w) + render->fillRect(gfx::Rect(rc.x+rc.w, rc.y, sprite_w-(rc.x+rc.w), rc.h), _rgba(0, 0, 0, 255), 128); +} + +void SelectTileState::postRenderDecorator(EditorPostRender* render) +{ + Editor* editor = render->getEditor(); + int zoom = editor->getZoom(); + gfx::Rect vp = View::getView(editor)->getViewportBounds(); + int rulerColor = makecol(0, 0, 255); + + vp.w += 1<screenToEditor(vp, &vp); + + for (Rulers::iterator it = m_rulers.begin(), end = m_rulers.end(); it != end; ++it) { + switch (it->getOrientation()) { + case Ruler::Horizontal: + render->drawLine(vp.x, it->getPosition(), vp.x+vp.w-1, it->getPosition(), rulerColor); + break; + case Ruler::Vertical: + render->drawLine(it->getPosition(), vp.y, it->getPosition(), vp.y+vp.h-1, rulerColor); + break; + } + } +} + +gfx::Rect SelectTileState::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()); + return gfx::Rect(x1, y1, x2 - x1, y2 - y1); +} + +bool SelectTileState::touchRuler(Editor* editor, Ruler& ruler, int x, int y) +{ + int u, v; + editor->editorToScreen(ruler.getPosition(), ruler.getPosition(), &u, &v); + + switch (ruler.getOrientation()) { + case Ruler::Horizontal: return (y >= v-2 && y <= v+2); + case Ruler::Vertical: return (x >= u-2 && x <= u+2); + } + + return false; +} diff --git a/src/widgets/editor/select_tile_state.h b/src/widgets/editor/select_tile_state.h new file mode 100644 index 000000000..e98078265 --- /dev/null +++ b/src/widgets/editor/select_tile_state.h @@ -0,0 +1,74 @@ +/* ASE - Allegro Sprite Editor + * Copyright (C) 2001-2011 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef WIDGETS_EDITOR_SELECT_TILE_STATE_H_INCLUDED +#define WIDGETS_EDITOR_SELECT_TILE_STATE_H_INCLUDED + +#include "base/compiler_specific.h" +#include "widgets/editor/editor_decorator.h" +#include "widgets/editor/ruler.h" +#include "widgets/editor/standby_state.h" + +#include + +class SelectTileDelegate +{ +public: + virtual ~SelectTileDelegate() { } + virtual void onChangeRectangle(const gfx::Rect& rect) = 0; +}; + +class SelectTileState : public StandbyState + , public EditorDecorator +{ + enum { H1, H2, V1, V2 }; + +public: + SelectTileState(SelectTileDelegate* delegate, const gfx::Rect& rc); + + // EditorState overrides + virtual bool onMouseDown(Editor* editor, Message* msg) OVERRIDE; + virtual bool onMouseUp(Editor* editor, Message* msg) OVERRIDE; + virtual bool onMouseMove(Editor* editor, Message* msg) OVERRIDE; + virtual bool onSetCursor(Editor* editor) OVERRIDE; + virtual EditorDecorator* getDecorator() OVERRIDE; + + // Returns false as it overrides default standby state behavior & + // look. This state uses normal arrow cursors. + virtual bool requirePenPreview() OVERRIDE { return false; } + + // EditorDecorator overrides + virtual void preRenderDecorator(EditorPreRender* render) OVERRIDE; + virtual void postRenderDecorator(EditorPostRender* render) OVERRIDE; + +private: + typedef std::vector Rulers; + + // Returns the bounding box arranged by the rulers. + gfx::Rect getBoxBounds() const; + + // Returns true if the position screen position (x, y) is touching + // the given ruler. + bool touchRuler(Editor* editor, Ruler& ruler, int x, int y); + + SelectTileDelegate* m_delegate; + Rulers m_rulers; + int m_movingRuler; +}; + +#endif // WIDGETS_EDITOR_STANDBY_STATE_H_INCLUDED