aseprite/src/app/commands/cmd_symmetry_mode.cpp

132 lines
4.1 KiB
C++

// Aseprite
// Copyright (C) 2018-2024 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/app.h"
#include "app/commands/command.h"
#include "app/commands/params.h"
#include "app/context.h"
#include "app/doc.h"
#include "app/i18n/strings.h"
#include "app/pref/preferences.h"
#include "app/ui/context_bar.h"
namespace app {
class SymmetryModeCommand : public Command {
public:
SymmetryModeCommand();
protected:
void onLoadParams(const Params& params) override;
bool onEnabled(Context* context) override;
bool onChecked(Context* context) override;
void onExecute(Context* context) override;
std::string onGetFriendlyName() const override;
private:
app::gen::SymmetryMode m_mode = app::gen::SymmetryMode::NONE;
};
SymmetryModeCommand::SymmetryModeCommand() : Command(CommandId::SymmetryMode())
{
}
std::string SymmetryModeCommand::onGetFriendlyName() const
{
switch (m_mode) {
case app::gen::SymmetryMode::HORIZONTAL: return Strings::symmetry_toggle_horizontal();
case app::gen::SymmetryMode::VERTICAL: return Strings::symmetry_toggle_vertical();
case app::gen::SymmetryMode::RIGHT_DIAG: return Strings::symmetry_toggle_right_diagonal();
case app::gen::SymmetryMode::LEFT_DIAG: return Strings::symmetry_toggle_left_diagonal();
default: return Strings::symmetry_toggle();
}
}
void SymmetryModeCommand::onLoadParams(const Params& params)
{
std::string mode = params.get("orientation");
if (mode == "vertical")
m_mode = app::gen::SymmetryMode::VERTICAL;
else if (mode == "horizontal")
m_mode = app::gen::SymmetryMode::HORIZONTAL;
else if (mode == "right_diagonal")
m_mode = app::gen::SymmetryMode::RIGHT_DIAG;
else if (mode == "left_diagonal")
m_mode = app::gen::SymmetryMode::LEFT_DIAG;
else
m_mode = app::gen::SymmetryMode::NONE;
}
bool SymmetryModeCommand::onEnabled(Context* ctx)
{
return ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable | ContextFlags::HasActiveSprite);
}
bool SymmetryModeCommand::onChecked(Context* ctx)
{
return Preferences::instance().symmetryMode.enabled();
}
void SymmetryModeCommand::onExecute(Context* ctx)
{
auto& enabled = Preferences::instance().symmetryMode.enabled;
// When the m_mode is NONE, it toggles the whole symmetry controls in
// the context bar.
if (m_mode == app::gen::SymmetryMode::NONE) {
enabled(!enabled());
}
// In other case it toggles the specific document symmetry specified
// in m_mode.
else {
Doc* doc = ctx->activeDocument();
DocumentPreferences& docPref = Preferences::instance().document(doc);
const app::gen::SymmetryMode actual = docPref.symmetry.mode();
// If the symmetry options are hidden, we'll always show them and
// activate the m_mode symmetry. We cannot just toggle the
// symmetry when the options aren't visible in the context bar,
// because if m_mode is checked, this would cause to show the
// symmetry options in the context bar but with a unchecked m_mode
// symmetry.
if (!enabled()) {
docPref.symmetry.mode(app::gen::SymmetryMode(int(m_mode) | int(actual)));
enabled(true);
}
// If the symmetry options are visible, we just switch the m_mode
// symmetry.
else {
docPref.symmetry.mode(app::gen::SymmetryMode(int(m_mode) ^ int(actual)));
}
// Redraw all editors
//
// TODO It looks like only the current editor shows the symmetry,
// so it's not necessary to invalidate all editors (only the
// current one).
doc->notifyGeneralUpdate();
// Redraw the buttons in the context bar.
//
// TODO Same with context bar, in the future the context bar could
// be listening the DocPref changes to be automatically
// invalidated (like it already does with symmetryMode.enabled)
if (App::instance()->contextBar())
App::instance()->contextBar()->updateForActiveTool();
}
}
Command* CommandFactory::createSymmetryModeCommand()
{
return new SymmetryModeCommand;
}
} // namespace app