| 1 | // Aseprite |
| 2 | // Copyright (C) 2019-2020 Igara Studio S.A. |
| 3 | // Copyright (C) 2016-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/set_palette.h" |
| 14 | #include "app/commands/command.h" |
| 15 | #include "app/commands/new_params.h" |
| 16 | #include "app/console.h" |
| 17 | #include "app/context.h" |
| 18 | #include "app/context_access.h" |
| 19 | #include "app/i18n/strings.h" |
| 20 | #include "app/pref/preferences.h" |
| 21 | #include "app/tx.h" |
| 22 | #include "doc/palette.h" |
| 23 | #include "fmt/format.h" |
| 24 | |
| 25 | #ifdef ENABLE_SCRIPTING |
| 26 | #include "app/script/luacpp.h" |
| 27 | #endif |
| 28 | |
| 29 | namespace app { |
| 30 | |
| 31 | enum class AddColorSource { Fg, Bg, Color }; |
| 32 | |
| 33 | template<> |
| 34 | void Param<AddColorSource>::fromString(const std::string& value) |
| 35 | { |
| 36 | if (value == "fg" || |
| 37 | value == "foreground" ) |
| 38 | setValue(AddColorSource::Fg); |
| 39 | else if (value == "bg" || |
| 40 | value == "background" ) |
| 41 | setValue(AddColorSource::Bg); |
| 42 | else |
| 43 | setValue(AddColorSource::Color); |
| 44 | } |
| 45 | |
| 46 | #ifdef ENABLE_SCRIPTING |
| 47 | template<> |
| 48 | void Param<AddColorSource>::fromLua(lua_State* L, int index) |
| 49 | { |
| 50 | fromString(lua_tostring(L, index)); |
| 51 | } |
| 52 | #endif // ENABLE_SCRIPTING |
| 53 | |
| 54 | struct AddColorParams : public NewParams { |
| 55 | Param<AddColorSource> source { this, AddColorSource::Color, "source" }; |
| 56 | Param<app::Color> color { this, app::Color::fromMask(), "color" }; |
| 57 | }; |
| 58 | |
| 59 | class AddColorCommand : public CommandWithNewParams<AddColorParams> { |
| 60 | public: |
| 61 | AddColorCommand(); |
| 62 | protected: |
| 63 | bool onEnabled(Context* ctx) override; |
| 64 | void onExecute(Context* ctx) override; |
| 65 | std::string onGetFriendlyName() const override; |
| 66 | }; |
| 67 | |
| 68 | AddColorCommand::AddColorCommand() |
| 69 | : CommandWithNewParams<AddColorParams>(CommandId::AddColor(), CmdUIOnlyFlag) |
| 70 | { |
| 71 | } |
| 72 | |
| 73 | bool AddColorCommand::onEnabled(Context* ctx) |
| 74 | { |
| 75 | return ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable); |
| 76 | } |
| 77 | |
| 78 | void AddColorCommand::onExecute(Context* ctx) |
| 79 | { |
| 80 | app::Color appColor; |
| 81 | |
| 82 | switch (params().source()) { |
| 83 | case AddColorSource::Fg: |
| 84 | appColor = Preferences::instance().colorBar.fgColor(); |
| 85 | break; |
| 86 | case AddColorSource::Bg: |
| 87 | appColor = Preferences::instance().colorBar.bgColor(); |
| 88 | break; |
| 89 | case AddColorSource::Color: |
| 90 | appColor = params().color(); |
| 91 | break; |
| 92 | } |
| 93 | |
| 94 | Palette* pal = ctx->activeSite().palette(); |
| 95 | ASSERT(pal); |
| 96 | if (!pal) |
| 97 | return; |
| 98 | |
| 99 | try { |
| 100 | std::unique_ptr<Palette> newPalette(new Palette(*pal)); |
| 101 | color_t color = doc::rgba( |
| 102 | appColor.getRed(), |
| 103 | appColor.getGreen(), |
| 104 | appColor.getBlue(), |
| 105 | appColor.getAlpha()); |
| 106 | int index = newPalette->findExactMatch( |
| 107 | appColor.getRed(), |
| 108 | appColor.getGreen(), |
| 109 | appColor.getBlue(), |
| 110 | appColor.getAlpha(), -1); |
| 111 | |
| 112 | // It should be -1, because the user has pressed the warning |
| 113 | // button that is available only when the color isn't in the |
| 114 | // palette. |
| 115 | ASSERT(index < 0); |
| 116 | if (index >= 0) |
| 117 | return; |
| 118 | |
| 119 | ContextWriter writer(ctx); |
| 120 | Doc* document(writer.document()); |
| 121 | Sprite* sprite = writer.sprite(); |
| 122 | if (!document || !sprite) { |
| 123 | ASSERT(false); |
| 124 | return; |
| 125 | } |
| 126 | |
| 127 | newPalette->addEntry(color); |
| 128 | index = newPalette->size()-1; |
| 129 | |
| 130 | if (document) { |
| 131 | frame_t frame = writer.frame(); |
| 132 | |
| 133 | Tx tx(writer.context(), friendlyName(), ModifyDocument); |
| 134 | tx(new cmd::SetPalette(sprite, frame, newPalette.get())); |
| 135 | tx.commit(); |
| 136 | } |
| 137 | } |
| 138 | catch (base::Exception& e) { |
| 139 | Console::showException(e); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | std::string AddColorCommand::onGetFriendlyName() const |
| 144 | { |
| 145 | std::string source; |
| 146 | switch (params().source()) { |
| 147 | case AddColorSource::Fg: source = Strings::commands_AddColor_Foreground(); break; |
| 148 | case AddColorSource::Bg: source = Strings::commands_AddColor_Background(); break; |
| 149 | case AddColorSource::Color: source = Strings::commands_AddColor_Specific(); break; |
| 150 | } |
| 151 | return fmt::format(getBaseFriendlyName(), source); |
| 152 | } |
| 153 | |
| 154 | Command* CommandFactory::createAddColorCommand() |
| 155 | { |
| 156 | return new AddColorCommand; |
| 157 | } |
| 158 | |
| 159 | } // namespace app |
| 160 | |