diff --git a/data/gui.xml b/data/gui.xml
index 3007b72e3..d031fa68d 100644
--- a/data/gui.xml
+++ b/data/gui.xml
@@ -121,6 +121,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ffb5cef4d..99fce2761 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -223,6 +223,7 @@ add_library(aseprite-library
commands/cmd_rotate_canvas.cpp
commands/cmd_save_file.cpp
commands/cmd_save_mask.cpp
+ commands/cmd_scroll.cpp
commands/cmd_select_file.cpp
commands/cmd_sprite_editor.cpp
commands/cmd_sprite_properties.cpp
diff --git a/src/commands/cmd_scroll.cpp b/src/commands/cmd_scroll.cpp
new file mode 100644
index 000000000..d050e21a8
--- /dev/null
+++ b/src/commands/cmd_scroll.cpp
@@ -0,0 +1,149 @@
+/* ASEPRITE
+ * Copyright (C) 2001-2012 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 "commands/command.h"
+#include "commands/params.h"
+#include "document_wrappers.h"
+#include "gui/view.h"
+#include "modules/editors.h"
+#include "settings/settings.h"
+#include "widgets/editor/editor.h"
+
+//////////////////////////////////////////////////////////////////////
+// scroll
+
+class ScrollCommand : public Command
+{
+public:
+ enum Direction { Left, Up, Right, Down, };
+ enum Units {
+ Pixel,
+ TileWidth,
+ TileHeight,
+ ZoomedPixel,
+ ZoomedTileWidth,
+ ZoomedTileHeight,
+ ViewportWidth,
+ ViewportHeight
+ };
+
+ ScrollCommand();
+ Command* clone() { return new ScrollCommand(*this); }
+
+protected:
+ void onLoadParams(Params* params);
+ bool onEnabled(Context* context);
+ void onExecute(Context* context);
+
+private:
+ Direction m_direction;
+ Units m_units;
+ int m_quantity;
+};
+
+ScrollCommand::ScrollCommand()
+ : Command("Scroll",
+ "Scroll",
+ CmdUIOnlyFlag)
+{
+}
+
+void ScrollCommand::onLoadParams(Params* params)
+{
+ std::string direction = params->get("direction");
+ if (direction == "left") m_direction = Left;
+ else if (direction == "right") m_direction = Right;
+ else if (direction == "up") m_direction = Up;
+ else if (direction == "down") m_direction = Down;
+
+ std::string units = params->get("units");
+ if (units == "pixel") m_units = Pixel;
+ else if (units == "tile-width") m_units = TileWidth;
+ else if (units == "tile-height") m_units = TileHeight;
+ else if (units == "zoomed-pixel") m_units = ZoomedPixel;
+ else if (units == "zoomed-tile-width") m_units = ZoomedTileWidth;
+ else if (units == "zoomed-tile-height") m_units = ZoomedTileHeight;
+ else if (units == "viewport-width") m_units = ViewportWidth;
+ else if (units == "viewport-height") m_units = ViewportHeight;
+
+ int quantity = params->get_as("quantity");
+ m_quantity = std::max(1, quantity);
+}
+
+bool ScrollCommand::onEnabled(Context* context)
+{
+ ActiveDocumentWriter document(context);
+ return document != NULL;
+}
+
+void ScrollCommand::onExecute(Context* context)
+{
+ View* view = View::getView(current_editor);
+ gfx::Rect vp = view->getViewportBounds();
+ gfx::Point scroll = view->getViewScroll();
+ gfx::Rect gridBounds = context->getSettings()->getGridBounds();
+ int dx = 0;
+ int dy = 0;
+ int pixels = 0;
+
+ switch (m_units) {
+ case Pixel:
+ pixels = 1;
+ break;
+ case TileWidth:
+ pixels = gridBounds.w;
+ break;
+ case TileHeight:
+ pixels = gridBounds.h;
+ break;
+ case ZoomedPixel:
+ pixels = 1 << current_editor->getZoom();
+ break;
+ case ZoomedTileWidth:
+ pixels = gridBounds.w << current_editor->getZoom();
+ break;
+ case ZoomedTileHeight:
+ pixels = gridBounds.h << current_editor->getZoom();
+ break;
+ case ViewportWidth:
+ pixels = vp.h;
+ break;
+ case ViewportHeight:
+ pixels = vp.w;
+ break;
+ }
+
+ switch (m_direction) {
+ case Left: dx = -m_quantity * pixels; break;
+ case Right: dx = +m_quantity * pixels; break;
+ case Up: dy = -m_quantity * pixels; break;
+ case Down: dy = +m_quantity * pixels; break;
+ }
+
+ current_editor->setEditorScroll(scroll.x+dx, scroll.y+dy, true);
+}
+
+//////////////////////////////////////////////////////////////////////
+// CommandFactory
+
+Command* CommandFactory::createScrollCommand()
+{
+ return new ScrollCommand;
+}
diff --git a/src/commands/commands_list.h b/src/commands/commands_list.h
index 0d41244cf..3bea69d3e 100644
--- a/src/commands/commands_list.h
+++ b/src/commands/commands_list.h
@@ -95,6 +95,7 @@ FOR_EACH_COMMAND(SaveFile)
FOR_EACH_COMMAND(SaveFileAs)
FOR_EACH_COMMAND(SaveFileCopyAs)
FOR_EACH_COMMAND(SaveMask)
+FOR_EACH_COMMAND(Scroll)
FOR_EACH_COMMAND(SelectFile)
FOR_EACH_COMMAND(ShowGrid)
FOR_EACH_COMMAND(SnapToGrid)