Files
panopainter/src/app_core/document_export.h

284 lines
9.5 KiB
C++

#pragma once
#include "foundation/result.h"
#include <string>
#include <string_view>
#include <utility>
namespace pp::app {
struct DocumentExportFileTarget {
std::string path;
std::string suggested_name;
};
struct DocumentExportCollectionTarget {
std::string directory;
std::string stem_path;
};
struct DocumentExportStemTarget {
std::string stem_path;
};
struct DocumentExportSuggestedName {
std::string name;
};
enum class DocumentExportStartDecision {
start_now,
show_license_disabled,
unavailable_no_canvas,
};
enum class DocumentExportMenuKind {
jpeg,
png,
layers,
cube_faces,
depth,
animation_frames,
animation_mp4,
timelapse,
};
enum class DocumentExportMenuAction {
show_jpeg_dialog,
show_png_dialog,
show_layers_dialog,
show_cube_faces_dialog,
show_depth_dialog,
show_animation_frames_dialog,
show_animation_mp4_dialog,
show_timelapse_dialog,
show_license_disabled,
unavailable_no_canvas,
};
struct DocumentExportMenuPlan {
DocumentExportMenuKind kind = DocumentExportMenuKind::jpeg;
DocumentExportMenuAction action = DocumentExportMenuAction::show_jpeg_dialog;
bool opens_dialog = true;
};
class DocumentExportMenuServices {
public:
virtual ~DocumentExportMenuServices() = default;
virtual void show_jpeg_dialog() = 0;
virtual void show_png_dialog() = 0;
virtual void show_layers_dialog() = 0;
virtual void show_cube_faces_dialog() = 0;
virtual void show_depth_dialog() = 0;
virtual void show_animation_frames_dialog() = 0;
virtual void show_animation_mp4_dialog() = 0;
virtual void show_timelapse_dialog() = 0;
virtual void show_license_disabled() = 0;
};
[[nodiscard]] constexpr DocumentExportStartDecision plan_document_export_start(
bool requires_license,
bool license_valid,
bool has_canvas) noexcept
{
if (requires_license && !license_valid) {
return DocumentExportStartDecision::show_license_disabled;
}
return has_canvas
? DocumentExportStartDecision::start_now
: DocumentExportStartDecision::unavailable_no_canvas;
}
[[nodiscard]] constexpr bool document_export_menu_requires_license(
DocumentExportMenuKind kind) noexcept
{
switch (kind) {
case DocumentExportMenuKind::animation_mp4:
case DocumentExportMenuKind::timelapse:
return true;
case DocumentExportMenuKind::jpeg:
case DocumentExportMenuKind::png:
case DocumentExportMenuKind::layers:
case DocumentExportMenuKind::cube_faces:
case DocumentExportMenuKind::depth:
case DocumentExportMenuKind::animation_frames:
return false;
}
return false;
}
[[nodiscard]] constexpr DocumentExportMenuAction document_export_menu_dialog_action(
DocumentExportMenuKind kind) noexcept
{
switch (kind) {
case DocumentExportMenuKind::jpeg:
return DocumentExportMenuAction::show_jpeg_dialog;
case DocumentExportMenuKind::png:
return DocumentExportMenuAction::show_png_dialog;
case DocumentExportMenuKind::layers:
return DocumentExportMenuAction::show_layers_dialog;
case DocumentExportMenuKind::cube_faces:
return DocumentExportMenuAction::show_cube_faces_dialog;
case DocumentExportMenuKind::depth:
return DocumentExportMenuAction::show_depth_dialog;
case DocumentExportMenuKind::animation_frames:
return DocumentExportMenuAction::show_animation_frames_dialog;
case DocumentExportMenuKind::animation_mp4:
return DocumentExportMenuAction::show_animation_mp4_dialog;
case DocumentExportMenuKind::timelapse:
return DocumentExportMenuAction::show_timelapse_dialog;
}
return DocumentExportMenuAction::show_jpeg_dialog;
}
[[nodiscard]] constexpr DocumentExportMenuPlan plan_document_export_menu_action(
DocumentExportMenuKind kind,
bool has_canvas,
bool license_valid) noexcept
{
DocumentExportMenuPlan plan;
plan.kind = kind;
plan.action = document_export_menu_dialog_action(kind);
const auto start = plan_document_export_start(
document_export_menu_requires_license(kind),
license_valid,
has_canvas);
if (start == DocumentExportStartDecision::show_license_disabled) {
plan.action = DocumentExportMenuAction::show_license_disabled;
plan.opens_dialog = false;
} else if (start == DocumentExportStartDecision::unavailable_no_canvas) {
plan.action = DocumentExportMenuAction::unavailable_no_canvas;
plan.opens_dialog = false;
}
return plan;
}
[[nodiscard]] inline pp::foundation::Result<DocumentExportFileTarget> make_document_export_file_target(
std::string_view work_directory,
std::string_view document_name,
std::string_view extension)
{
if (document_name.empty()) {
return pp::foundation::Result<DocumentExportFileTarget>::failure(
pp::foundation::Status::invalid_argument("document name must not be empty"));
}
if (extension.empty()) {
return pp::foundation::Result<DocumentExportFileTarget>::failure(
pp::foundation::Status::invalid_argument("extension must not be empty"));
}
DocumentExportFileTarget target;
target.suggested_name.reserve(document_name.size() + extension.size());
target.suggested_name += document_name;
target.suggested_name += extension;
target.path.reserve(work_directory.size() + target.suggested_name.size() + 1);
target.path += work_directory;
target.path += "/";
target.path += target.suggested_name;
return pp::foundation::Result<DocumentExportFileTarget>::success(std::move(target));
}
[[nodiscard]] inline pp::foundation::Result<DocumentExportCollectionTarget> make_document_export_collection_target(
std::string_view work_directory,
std::string_view document_name,
std::string_view suffix)
{
if (document_name.empty()) {
return pp::foundation::Result<DocumentExportCollectionTarget>::failure(
pp::foundation::Status::invalid_argument("document name must not be empty"));
}
DocumentExportCollectionTarget target;
target.directory.reserve(work_directory.size() + document_name.size() + suffix.size() + 1);
target.directory += work_directory;
target.directory += "/";
target.directory += document_name;
target.directory += suffix;
target.stem_path.reserve(target.directory.size() + document_name.size() + 1);
target.stem_path += target.directory;
target.stem_path += "/";
target.stem_path += document_name;
return pp::foundation::Result<DocumentExportCollectionTarget>::success(std::move(target));
}
[[nodiscard]] inline pp::foundation::Result<DocumentExportStemTarget> make_document_export_stem_target(
std::string_view directory,
std::string_view document_name)
{
if (document_name.empty()) {
return pp::foundation::Result<DocumentExportStemTarget>::failure(
pp::foundation::Status::invalid_argument("document name must not be empty"));
}
DocumentExportStemTarget target;
target.stem_path.reserve(directory.size() + document_name.size() + 1);
target.stem_path += directory;
target.stem_path += "/";
target.stem_path += document_name;
return pp::foundation::Result<DocumentExportStemTarget>::success(std::move(target));
}
[[nodiscard]] inline pp::foundation::Result<DocumentExportSuggestedName> make_document_export_suggested_name(
std::string_view document_name,
std::string_view suffix)
{
if (document_name.empty()) {
return pp::foundation::Result<DocumentExportSuggestedName>::failure(
pp::foundation::Status::invalid_argument("document name must not be empty"));
}
DocumentExportSuggestedName target;
target.name.reserve(document_name.size() + suffix.size());
target.name += document_name;
target.name += suffix;
return pp::foundation::Result<DocumentExportSuggestedName>::success(std::move(target));
}
[[nodiscard]] inline pp::foundation::Status execute_document_export_menu_plan(
const DocumentExportMenuPlan& plan,
DocumentExportMenuServices& services)
{
switch (plan.action) {
case DocumentExportMenuAction::show_jpeg_dialog:
services.show_jpeg_dialog();
return pp::foundation::Status::success();
case DocumentExportMenuAction::show_png_dialog:
services.show_png_dialog();
return pp::foundation::Status::success();
case DocumentExportMenuAction::show_layers_dialog:
services.show_layers_dialog();
return pp::foundation::Status::success();
case DocumentExportMenuAction::show_cube_faces_dialog:
services.show_cube_faces_dialog();
return pp::foundation::Status::success();
case DocumentExportMenuAction::show_depth_dialog:
services.show_depth_dialog();
return pp::foundation::Status::success();
case DocumentExportMenuAction::show_animation_frames_dialog:
services.show_animation_frames_dialog();
return pp::foundation::Status::success();
case DocumentExportMenuAction::show_animation_mp4_dialog:
services.show_animation_mp4_dialog();
return pp::foundation::Status::success();
case DocumentExportMenuAction::show_timelapse_dialog:
services.show_timelapse_dialog();
return pp::foundation::Status::success();
case DocumentExportMenuAction::show_license_disabled:
services.show_license_disabled();
return pp::foundation::Status::success();
case DocumentExportMenuAction::unavailable_no_canvas:
return pp::foundation::Status::success();
}
return pp::foundation::Status::invalid_argument("unknown document export menu action");
}
}