Convert SaveFileBaseCommand to CommandWithNewParams

With this patch we fixed some use cases:
* We can show the ui with a default filename { filename=..., ui=true }
* We can specify fromFrame/toFrame for SaveFileCopyAs
This commit is contained in:
David Capello 2022-06-13 17:04:12 -03:00
parent d160fb8b91
commit ddc1b76214
6 changed files with 80 additions and 58 deletions

View File

@ -86,24 +86,18 @@ private:
//////////////////////////////////////////////////////////////////////
SaveFileBaseCommand::SaveFileBaseCommand(const char* id, CommandFlags flags)
: Command(id, flags)
: CommandWithNewParams<SaveFileParams>(id, flags)
{
m_useUI = true;
m_ignoreEmpty = false;
}
void SaveFileBaseCommand::onLoadParams(const Params& params)
{
m_filename = params.get("filename");
m_filenameFormat = params.get("filename-format");
m_tag = params.get("frame-tag");
m_aniDir = params.get("ani-dir");
m_slice = params.get("slice");
CommandWithNewParams<SaveFileParams>::onLoadParams(params);
if (params.has_param("from-frame") ||
params.has_param("to-frame")) {
doc::frame_t fromFrame = params.get_as<doc::frame_t>("from-frame");
doc::frame_t toFrame = params.get_as<doc::frame_t>("to-frame");
if (this->params().fromFrame.isSet() ||
this->params().toFrame.isSet()) {
doc::frame_t fromFrame = this->params().fromFrame();
doc::frame_t toFrame = this->params().toFrame();
m_selFrames.insert(fromFrame, toFrame);
m_adjustFramesByTag = true;
}
@ -111,11 +105,6 @@ void SaveFileBaseCommand::onLoadParams(const Params& params)
m_selFrames.clear();
m_adjustFramesByTag = false;
}
std::string useUI = params.get("useUI");
m_useUI = (useUI.empty() || (useUI == "true"));
m_ignoreEmpty = params.get_as<bool>("ignoreEmpty");
}
// Returns true if there is a current sprite to save.
@ -141,19 +130,15 @@ std::string SaveFileBaseCommand::saveAsDialog(
// preferences.
Preferences::instance().save();
std::string filename;
if (!m_filename.empty()) {
filename = m_filename;
}
else {
std::string filename = params().filename();
if (filename.empty() || params().ui()) {
base::paths exts = get_writable_extensions();
filename = initialFilename;
#ifdef ENABLE_UI
again:;
base::paths newfilename;
if (!m_useUI ||
if (!params().ui() ||
!app::show_file_selector(
dlgTitle, filename, exts,
FileSelectorType::Save,
@ -200,8 +185,8 @@ void SaveFileBaseCommand::saveDocumentInBackground(
const std::string& filename,
const MarkAsSaved markAsSaved)
{
if (!m_aniDir.empty()) {
switch (convert_string_to_anidir(m_aniDir)) {
if (params().aniDir.isSet()) {
switch (params().aniDir()) {
case AniDir::REVERSE:
m_selFrames = m_selFrames.makeReverse();
break;
@ -211,7 +196,7 @@ void SaveFileBaseCommand::saveDocumentInBackground(
}
}
FileOpROI roi(document, m_slice, m_tag,
FileOpROI roi(document, params().slice(), params().tag(),
m_selFrames, m_adjustFramesByTag);
std::unique_ptr<FileOp> fop(
@ -219,8 +204,8 @@ void SaveFileBaseCommand::saveDocumentInBackground(
context,
roi,
filename,
m_filenameFormat,
m_ignoreEmpty));
params().filenameFormat(),
params().ignoreEmpty()));
if (!fop)
return;
@ -283,7 +268,8 @@ void SaveFileCommand::onExecute(Context* context)
saveDocumentInBackground(
context, document,
documentReader->filename(),
(params().filename.isSet() ? params().filename():
documentReader->filename()),
MarkAsSaved::On);
}
// If the document isn't associated to a file, we must to show the
@ -291,7 +277,8 @@ void SaveFileCommand::onExecute(Context* context)
// for this document.
else {
saveAsDialog(context, "Save File",
document->filename(),
(params().filename.isSet() ? params().filename():
document->filename()),
MarkAsSaved::On);
}
}
@ -313,7 +300,8 @@ void SaveFileAsCommand::onExecute(Context* context)
{
Doc* document = context->activeDocument();
saveAsDialog(context, "Save As",
document->filename(),
(params().filename.isSet() ? params().filename():
document->filename()),
MarkAsSaved::On);
}
@ -337,17 +325,17 @@ SaveFileCopyAsCommand::SaveFileCopyAsCommand()
void SaveFileCopyAsCommand::onExecute(Context* context)
{
Doc* doc = context->activeDocument();
std::string outputFilename = m_filename;
std::string outputFilename = params().filename();
std::string layers = kAllLayers;
std::string frames = kAllFrames;
double xscale = 1.0;
double yscale = 1.0;
bool applyPixelRatio = false;
doc::AniDir aniDirValue = convert_string_to_anidir(m_aniDir);
doc::AniDir aniDirValue = params().aniDir();
bool isForTwitter = false;
#if ENABLE_UI
if (m_useUI && context->isUIAvailable()) {
if (params().ui() && context->isUIAvailable()) {
ExportFileWindow win(doc);
bool askOverwrite = true;
@ -367,6 +355,8 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
return result;
});
win.setAniDir(aniDirValue);
win.remapWindow();
load_window_pos(&win, "ExportFile");
again:;
@ -446,20 +436,22 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
layers,
layersVisibility);
// Selected frames to export
SelectedFrames selFrames;
Tag* tag = calculate_selected_frames(
site, frames, selFrames);
if (tag)
m_tag = tag->name();
m_selFrames = selFrames;
// m_selFrames is not empty if fromFrame/toFrame parameters are
// specified.
if (m_selFrames.empty()) {
// Selected frames to export
SelectedFrames selFrames;
Tag* tag = calculate_selected_frames(
site, frames, selFrames);
if (tag)
params().tag(tag->name());
m_selFrames = selFrames;
}
m_adjustFramesByTag = false;
}
base::ScopedValue<std::string> restoreAniDir(
m_aniDir,
convert_anidir_to_string(aniDirValue), // New value
m_aniDir); // Restore old value
// Set ani dir
params().aniDir(aniDirValue);
// TODO This should be set as options for the specific encoder
GifEncoderDurationFix fixGif(isForTwitter);

View File

@ -10,6 +10,8 @@
#pragma once
#include "app/commands/command.h"
#include "app/commands/new_params.h"
#include "doc/anidir.h"
#include "doc/selected_frames.h"
#include <string>
@ -17,7 +19,19 @@
namespace app {
class Doc;
class SaveFileBaseCommand : public Command {
struct SaveFileParams : public NewParams {
Param<bool> ui { this, true, { "ui", "useUI" } };
Param<std::string> filename { this, std::string(), "filename" };
Param<std::string> filenameFormat { this, std::string(), { "filenameFormat", "filename-format" } };
Param<std::string> tag { this, std::string(), { "tag", "frame-tag" } };
Param<doc::AniDir> aniDir { this, doc::AniDir::FORWARD, { "aniDir", "ani-dir" } };
Param<std::string> slice { this, std::string(), "slice" };
Param<doc::frame_t> fromFrame { this, 0, { "fromFrame", "from-frame" } };
Param<doc::frame_t> toFrame { this, 0, { "toFrame", "to-frame" } };
Param<bool> ignoreEmpty { this, false, "ignoreEmpty" };
};
class SaveFileBaseCommand : public CommandWithNewParams<SaveFileParams> {
public:
enum class MarkAsSaved { Off, On };
enum class SaveInBackground { Off, On };
@ -41,15 +55,8 @@ namespace app {
const std::string& filename,
const MarkAsSaved markAsSaved);
std::string m_filename;
std::string m_filenameFormat;
std::string m_tag;
std::string m_aniDir;
std::string m_slice;
doc::SelectedFrames m_selFrames;
bool m_adjustFramesByTag;
bool m_useUI;
bool m_ignoreEmpty;
};
} // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -18,6 +18,7 @@
#include "base/split_string.h"
#include "base/string.h"
#include "doc/algorithm/resize_image.h"
#include "doc/anidir.h"
#include "doc/color_mode.h"
#include "filters/color_curve.h"
#include "filters/hue_saturation_filter.h"
@ -144,6 +145,12 @@ void Param<doc::ColorMode>::fromString(const std::string& value)
setValue(doc::ColorMode::RGB);
}
template<>
void Param<doc::AniDir>::fromString(const std::string& value)
{
setValue(convert_string_to_anidir(value));
}
template<>
void Param<app::Color>::fromString(const std::string& value)
{
@ -303,6 +310,15 @@ void Param<doc::ColorMode>::fromLua(lua_State* L, int index)
setValue((doc::ColorMode)lua_tointeger(L, index));
}
template<>
void Param<doc::AniDir>::fromLua(lua_State* L, int index)
{
if (lua_type(L, index) == LUA_TSTRING)
fromString(lua_tostring(L, index));
else
setValue((doc::AniDir)lua_tointeger(L, index));
}
template<>
void Param<app::Color>::fromLua(lua_State* L, int index)
{

View File

@ -10,6 +10,6 @@
// Increment this value if the scripting API is modified between two
// released Aseprite versions.
#define API_VERSION 18
#define API_VERSION 19
#endif

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2018 David Capello
//
// This program is distributed under the terms of
@ -141,6 +141,11 @@ bool ExportFileWindow::isForTwitter() const
return forTwitter()->isSelected();
}
void ExportFileWindow::setAniDir(const doc::AniDir aniDir)
{
anidir()->setSelectedItemIndex(int(aniDir));
}
void ExportFileWindow::setOutputFilename(const std::string& pathAndFilename)
{
m_outputPath = base::get_file_path(pathAndFilename);

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2020 Igara Studio S.A.
// Copyright (C) 2020-2022 Igara Studio S.A.
// Copyright (C) 2018 David Capello
//
// This program is distributed under the terms of
@ -34,6 +34,8 @@ namespace app {
bool applyPixelRatio() const;
bool isForTwitter() const;
void setAniDir(const doc::AniDir aniDir);
obs::signal<std::string()> SelectOutputFile;
private: