1// Aseprite
2// Copyright (C) 2019 Igara Studio S.A.
3// Copyright (C) 2001-2018 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/app.h"
13#include "app/cmd/shift_masked_cel.h"
14#include "app/commands/cmd_move_mask.h"
15#include "app/commands/command.h"
16#include "app/commands/params.h"
17#include "app/context_access.h"
18#include "app/doc_api.h"
19#include "app/i18n/strings.h"
20#include "app/modules/editors.h"
21#include "app/modules/gui.h"
22#include "app/pref/preferences.h"
23#include "app/tx.h"
24#include "app/ui/doc_view.h"
25#include "app/ui/editor/editor.h"
26#include "app/ui_context.h"
27#include "base/convert_to.h"
28#include "doc/mask.h"
29#include "doc/sprite.h"
30#include "fmt/format.h"
31#include "ui/view.h"
32
33namespace app {
34
35MoveMaskCommand::MoveMaskCommand()
36 : Command(CommandId::MoveMask(), CmdRecordableFlag)
37{
38}
39
40void MoveMaskCommand::onLoadParams(const Params& params)
41{
42 std::string target = params.get("target");
43 if (target == "boundaries") m_target = Boundaries;
44 else if (target == "content") m_target = Content;
45
46 if (params.has_param("wrap"))
47 m_wrap = params.get_as<bool>("wrap");
48 else
49 m_wrap = false;
50
51 m_moveThing.onLoadParams(params);
52}
53
54bool MoveMaskCommand::onEnabled(Context* context)
55{
56 switch (m_target) {
57
58 case Boundaries:
59 return context->checkFlags(ContextFlags::HasActiveDocument |
60 ContextFlags::HasVisibleMask);
61
62 case Content:
63 if (m_wrap)
64 return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
65 ContextFlags::HasVisibleMask |
66 ContextFlags::HasActiveImage |
67 ContextFlags::ActiveLayerIsEditable);
68 else
69 return (current_editor != nullptr) &&
70 context->checkFlags(ContextFlags::HasActiveDocument |
71 ContextFlags::HasVisibleMask |
72 ContextFlags::HasActiveImage);
73
74 }
75
76 return false;
77}
78
79void MoveMaskCommand::onExecute(Context* context)
80{
81 gfx::Point delta = m_moveThing.getDelta(context);
82
83 switch (m_target) {
84
85 case Boundaries: {
86 ContextWriter writer(context);
87 Doc* document(writer.document());
88 {
89 Tx tx(writer.context(), "Move Selection", DoesntModifyDocument);
90 gfx::Point pt = document->mask()->bounds().origin();
91 document->getApi(tx).setMaskPosition(pt.x+delta.x, pt.y+delta.y);
92 tx.commit();
93 }
94
95 update_screen_for_document(document);
96 break;
97 }
98
99 case Content:
100 if (m_wrap) {
101 ContextWriter writer(context);
102 if (writer.cel()) {
103 // Rotate content
104 Tx tx(writer.context(), "Shift Pixels");
105 tx(new cmd::ShiftMaskedCel(writer.cel(), delta.x, delta.y));
106 tx.commit();
107 }
108 update_screen_for_document(writer.document());
109 }
110 else {
111 current_editor->startSelectionTransformation(delta, 0.0);
112 }
113 break;
114
115 }
116}
117
118std::string MoveMaskCommand::onGetFriendlyName() const
119{
120 std::string content;
121 switch (m_target) {
122 case Boundaries: content = Strings::commands_MoveMask_Boundaries(); break;
123 case Content: content = Strings::commands_MoveMask_Content(); break;
124 }
125 return fmt::format(getBaseFriendlyName(),
126 content, m_moveThing.getFriendlyString());
127}
128
129Command* CommandFactory::createMoveMaskCommand()
130{
131 return new MoveMaskCommand;
132}
133
134} // namespace app
135