diff --git a/.travis.yml b/.travis.yml index 607a702..b00ee99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ before_deploy: - sed -i "s/__VERSION__/$TRAVIS_BUILD_NUMBER/g" bintray-spec.json deploy: - - provider: pages + - provider: pages skip_cleanup: true github_token: $GITHUB_TOKEN keep-history: true diff --git a/CMakeLists.txt b/CMakeLists.txt index b91b16e..eba2aba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,9 +20,9 @@ option(ENABLE_DOXYGEN "Build documentation" OFF) # ================ Project ======================== # Project name and a few useful settings -project(struct +project(editor VERSION 0.0.$ENV{TRAVIS_BUILD_NUMBER} - DESCRIPTION "OTUS c++ homeworks: struct" + DESCRIPTION "OTUS c++ homeworks: editor" LANGUAGES CXX ) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt new file mode 100644 index 0000000..b8a4d1c --- /dev/null +++ b/apps/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Editor) \ No newline at end of file diff --git a/apps/Editor/CMakeLists.txt b/apps/Editor/CMakeLists.txt new file mode 100644 index 0000000..5effe1f --- /dev/null +++ b/apps/Editor/CMakeLists.txt @@ -0,0 +1,4 @@ +add_and_install_project_app(editor + DEPEND + lib_Editor +) \ No newline at end of file diff --git a/apps/Editor/src/main_GraphicEditor.cpp b/apps/Editor/src/main_GraphicEditor.cpp new file mode 100644 index 0000000..b7fdcae --- /dev/null +++ b/apps/Editor/src/main_GraphicEditor.cpp @@ -0,0 +1,25 @@ +/** + * \brief Main application + */ + +#include +#include +#include + +#include + +using namespace document; + +int main() { + GraphicEditor editor; + editor.CreateNewDocument("/tmp/file0.jpg", DocumentType::JPG); + editor.ImportDocument("/tmp/file1.jpg"); + editor.ExportDocument("/tmp/file1_export.jpg", DocumentType::PNG); + auto config = PrimitiveConfig{Color::Red, LineStyle::Solid, {0,0}, std::make_shared()}; + auto circle = std::make_shared(1, config); + editor.CreatePrimitive(circle); + editor.RemovePrimitive(circle); + editor.SetActiveDocument(); + + return 0; +} diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt new file mode 100644 index 0000000..b8a4d1c --- /dev/null +++ b/library/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Editor) \ No newline at end of file diff --git a/library/Editor/CMakeLists.txt b/library/Editor/CMakeLists.txt new file mode 100644 index 0000000..a8d262f --- /dev/null +++ b/library/Editor/CMakeLists.txt @@ -0,0 +1,3 @@ +add_project_library() + +add_subdirectory(test) \ No newline at end of file diff --git a/library/Editor/README.MD b/library/Editor/README.MD new file mode 100644 index 0000000..61eacde --- /dev/null +++ b/library/Editor/README.MD @@ -0,0 +1,23 @@ +# OTUS course: "C++ Developer. Professional" + +## Домашнее Задание 4 + +Спроектировать простейший графический векторный редактор. Подготовить макеты классов, отражающих структуру будущего проекта. + +Функционал для макетирования следующий: - создание нового документа + +- импорт документа из файла +- экспорт документа в файл +- создание графического примитива - удаление графического примитива + +Основной упор сделать на шаблон контроллера (MVC) и полиморфизм. Функции, являющиеся обработчиками GUI, собрать в одном файле с функцией `main`. + +Внимание должно быть сосредоточено на декларациях, реализация только в крайнем случае для минимальной демонстрации необходимых вызовов. Проект должен компилироваться, все заголовки должны пройти стадию компиляции. + +Задание считается выполненным успешно, если все файлы прошли стадию компиляции, все классы охвачены диаграммами, код успешно прошел анализ. +Дополнительные рекомендации + +1. Заложить в интерфейсы использование умных указателей, тем самым решив вопрос владения объектами. +2. Помнить про принцип единственности ответственности, разделить код на логические модули (классы, функции). +3. Избегать дублирования кода. + \ No newline at end of file diff --git a/library/Editor/include/Editor/Document/Color/Color.h b/library/Editor/include/Editor/Document/Color/Color.h new file mode 100644 index 0000000..ee704b4 --- /dev/null +++ b/library/Editor/include/Editor/Document/Color/Color.h @@ -0,0 +1,11 @@ +#pragma once + +namespace document { + +enum class Color { + Red, + Green, + Blue +}; + +} // namespace document { \ No newline at end of file diff --git a/library/Editor/include/Editor/Document/Document.h b/library/Editor/include/Editor/Document/Document.h new file mode 100644 index 0000000..3ac001f --- /dev/null +++ b/library/Editor/include/Editor/Document/Document.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +#include + +namespace document { + +class PNG : public IDocument { +public: + PNG(const std::filesystem::path& path): IDocument(path) {} + bool SaveAs(const std::filesystem::path& new_path, DocumentType) override { + return true; + } +}; + +class JPG : public IDocument { +public: + JPG(const std::filesystem::path& path): IDocument(path) {} + bool SaveAs(const std::filesystem::path& new_path, DocumentType) override { + return true; + } +}; + +} // namespace document \ No newline at end of file diff --git a/library/Editor/include/Editor/Document/DocumentType.h b/library/Editor/include/Editor/Document/DocumentType.h new file mode 100644 index 0000000..49b3f96 --- /dev/null +++ b/library/Editor/include/Editor/Document/DocumentType.h @@ -0,0 +1,15 @@ +#pragma once + +namespace document { + +/** + * @brief Supported type of documents for Graphic Editor + * + */ + +enum class DocumentType { + PNG = 0, + JPG = 1 +}; + +} // namespace document \ No newline at end of file diff --git a/library/Editor/include/Editor/Document/IDocument.h b/library/Editor/include/Editor/Document/IDocument.h new file mode 100644 index 0000000..6faf758 --- /dev/null +++ b/library/Editor/include/Editor/Document/IDocument.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include +#include + +namespace document { + +class IDocument { +public: + IDocument(const std::filesystem::path& path) : + m_path(path) {} + + virtual bool SaveAs(const std::filesystem::path& new_path, DocumentType) = 0; + + bool AddPrimitive(const std::shared_ptr primitive) { + m_primitives.push_back(primitive); + return true; + } + + virtual void Update() {}; + + std::vector>& GetAllPrimitives() { return m_primitives; } + + virtual ~IDocument() = default; +protected: + std::filesystem::path m_path; + std::vector> m_primitives; +}; + +} // namespace document \ No newline at end of file diff --git a/library/Editor/include/Editor/Document/Primitives/Circle.h b/library/Editor/include/Editor/Document/Primitives/Circle.h new file mode 100644 index 0000000..1f45fba --- /dev/null +++ b/library/Editor/include/Editor/Document/Primitives/Circle.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +namespace document { + +class Circle: public IPrimitive { +public: + Circle(const float radius, PrimitiveConfig config): + IPrimitive(config), m_radius(radius) {} +private: + float m_radius; +}; + +} // namespace document { \ No newline at end of file diff --git a/library/Editor/include/Editor/Document/Primitives/IPrimitive.h b/library/Editor/include/Editor/Document/Primitives/IPrimitive.h new file mode 100644 index 0000000..880f9bb --- /dev/null +++ b/library/Editor/include/Editor/Document/Primitives/IPrimitive.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace document { + +class IPrimitive { +public: + IPrimitive(const PrimitiveConfig& config): + m_config(config) {} +protected: + PrimitiveConfig m_config; +}; + +} // namespace document { \ No newline at end of file diff --git a/library/Editor/include/Editor/Document/Primitives/Line.h b/library/Editor/include/Editor/Document/Primitives/Line.h new file mode 100644 index 0000000..ddedd0a --- /dev/null +++ b/library/Editor/include/Editor/Document/Primitives/Line.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +namespace document { + +class Line: public IPrimitive { +public: + Line(const float width, PrimitiveConfig config): + IPrimitive(config), m_width(width) {} +private: + float m_width; +}; + +} // namespace document { \ No newline at end of file diff --git a/library/Editor/include/Editor/Document/Primitives/PrimitiveConfig.h b/library/Editor/include/Editor/Document/Primitives/PrimitiveConfig.h new file mode 100644 index 0000000..4d9ecd1 --- /dev/null +++ b/library/Editor/include/Editor/Document/Primitives/PrimitiveConfig.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +#include + +namespace document { + +struct Position { + float x; + float y; +}; + +enum class LineStyle { + Dash, + Solid +}; + +struct PrimitiveConfig { + Color color; + LineStyle line_style; + Position position; + std::shared_ptr tool; +}; + +enum class PrimitiveType { + Circle, + Line +}; + +} // namespace document diff --git a/library/Editor/include/Editor/Document/Tools/ITool.h b/library/Editor/include/Editor/Document/Tools/ITool.h new file mode 100644 index 0000000..0c29f93 --- /dev/null +++ b/library/Editor/include/Editor/Document/Tools/ITool.h @@ -0,0 +1,8 @@ +#pragma once + + +namespace document { + +class ITool {}; + +} // namespace document { \ No newline at end of file diff --git a/library/Editor/include/Editor/Document/Tools/Tools.h b/library/Editor/include/Editor/Document/Tools/Tools.h new file mode 100644 index 0000000..c95e576 --- /dev/null +++ b/library/Editor/include/Editor/Document/Tools/Tools.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace document { + +class Brush: public ITool {}; + +class Pensil: public ITool {}; + +} // namespace document \ No newline at end of file diff --git a/library/Editor/include/Editor/GraphicEditor.h b/library/Editor/include/Editor/GraphicEditor.h new file mode 100644 index 0000000..6df62aa --- /dev/null +++ b/library/Editor/include/Editor/GraphicEditor.h @@ -0,0 +1,25 @@ +/** + * \file Editor.h + * \brief Declaration of Simple Vector Graphics Editor + * \version 0.1 + * + * \copyright Copyright (c) 2021 + * + */ + +#pragma once + +#include +#include +#include +#include + +class GraphicEditor: public IEditor { +public: + std::shared_ptr CreateNewDocument(const std::filesystem::path& path, document::DocumentType) override; + void ImportDocument(const std::filesystem::path& path) override; + void ExportDocument(const std::filesystem::path& path, document::DocumentType) override; + +private: + document::DocumentType GetDocumentType(const std::filesystem::path& path); +}; \ No newline at end of file diff --git a/library/Editor/include/Editor/IEditor.h b/library/Editor/include/Editor/IEditor.h new file mode 100644 index 0000000..712b18b --- /dev/null +++ b/library/Editor/include/Editor/IEditor.h @@ -0,0 +1,91 @@ +/** + * \file IEditor.h + * \author Vladislav Kozlov + * \brief Interface for Editor + * \version 0.1 + * + * @copyright Copyright (c) 2021 + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#if !defined(__LINUX__) +#define __LINUX__ 1 +#endif + +#if !defined(__WINDOWS__) +#define __WINDOWS__ !(__LINUX__) +#endif + +template +class IEditor { +public: + IEditor(); + + virtual std::shared_ptr CreateNewDocument(const std::filesystem::path&, document::DocumentType) = 0; + virtual void ImportDocument(const std::filesystem::path& path) = 0; + virtual void ExportDocument(const std::filesystem::path& path, document::DocumentType) = 0; + void CreatePrimitive(std::shared_ptr new_primitive); + void RemovePrimitive(std::shared_ptr primitive); + void SetActiveDocument(); + + virtual ~IEditor(); +protected: + void Update(); + + std::unique_ptr m_windows_manager; + std::shared_ptr m_active_window; + std::vector> m_documents; + std::shared_ptr m_active_document; + +}; + +template +IEditor::IEditor() { + if constexpr(__LINUX__) { + m_windows_manager = std::make_unique(); + } else if constexpr (__WINDOWS__) { + m_windows_manager = std::make_unique(); + } else { + throw std::runtime_error("No available Windows Manager."); + } + m_active_window = m_windows_manager->CreateNewWindow({0,0, {0,0}}); +} + +template +void IEditor::CreatePrimitive(std::shared_ptr new_primitive) { + m_active_document->AddPrimitive(new_primitive); + this->Update(); +} + +template +void IEditor::RemovePrimitive(std::shared_ptr primitive) { + std::remove(m_active_document->GetAllPrimitives().begin(), m_active_document->GetAllPrimitives().end(), primitive); + this->Update(); +} + +template +void IEditor::SetActiveDocument() {} + +template +void IEditor::Update() { + m_active_document->Update(); + m_active_window->Update(); +}; + +template +IEditor::~IEditor() = default; \ No newline at end of file diff --git a/library/Editor/include/Editor/WindowsManager/GnomeWindowsManager.h b/library/Editor/include/Editor/WindowsManager/GnomeWindowsManager.h new file mode 100644 index 0000000..4123099 --- /dev/null +++ b/library/Editor/include/Editor/WindowsManager/GnomeWindowsManager.h @@ -0,0 +1,39 @@ +/** + * @file WindowsManager for Linux (Gnome) + * @brief Interface for Window Managers + * @version 0.1 + * @date 2021-01-28 + * + * @copyright Copyright (c) 2021 + * + */ + +#pragma once + +#include +#include + +namespace windows_manager { + +class GnomeWindow: public IWindow { +public: + GnomeWindow(const WindowConfig& config); + bool Update() override; +}; + +class GnomeWindowsManager: public IWindowsManager { +public: + GnomeWindowsManager() = default; + + // Movable only + GnomeWindowsManager(const GnomeWindowsManager&) = delete; + GnomeWindowsManager& operator=(const GnomeWindowsManager&) = delete; + + GnomeWindowsManager(GnomeWindowsManager&&) = default; + GnomeWindowsManager& operator=(GnomeWindowsManager&&) = default; + + bool Update(IWindow&) override final; + std::shared_ptr CreateNewWindow(const WindowConfig& config) override final; +}; + +} // namespace windows_manager diff --git a/library/Editor/include/Editor/WindowsManager/IWindowsManager.h b/library/Editor/include/Editor/WindowsManager/IWindowsManager.h new file mode 100644 index 0000000..ffcba82 --- /dev/null +++ b/library/Editor/include/Editor/WindowsManager/IWindowsManager.h @@ -0,0 +1,50 @@ +/** + * @file IWindowsManager.h + * @brief Interface for Window Managers. Of caurse, it's better to move it to a seperate + * library, but for educational purposes let's leave it here. + * @version 0.1 + * @date 2021-01-28 + * + * @copyright Copyright (c) 2021 + * + */ + +#pragma once + +#include + +#include +#include + +namespace windows_manager { + +class IWindow { +public: + IWindow(const WindowConfig& config): m_config(config) {} + virtual bool Update() = 0; + + virtual ~IWindow() = default; +protected: + WindowConfig m_config; +}; + +class IWindowsManager { +public: + IWindowsManager() = default; + + // movable only. There should be only 1 WindowManager in a system + IWindowsManager(const IWindowsManager&) = delete; + IWindowsManager& operator=(const IWindowsManager&) = delete; + IWindowsManager(IWindowsManager&&) = default; + IWindowsManager& operator=(IWindowsManager&&) = default; + + virtual bool Update(IWindow&) = 0; + virtual std::shared_ptr CreateNewWindow(const WindowConfig& config) = 0; + + virtual ~IWindowsManager() = default; + +protected: + std::vector> m_windows; +}; + +} // namespace windows_manager diff --git a/library/Editor/include/Editor/WindowsManager/MicrosoftWindowsManager.h b/library/Editor/include/Editor/WindowsManager/MicrosoftWindowsManager.h new file mode 100644 index 0000000..d0806fc --- /dev/null +++ b/library/Editor/include/Editor/WindowsManager/MicrosoftWindowsManager.h @@ -0,0 +1,39 @@ +/** + * @file WindowsManager for Microsoft + * @brief Interface for Window Managers + * @version 0.1 + * @date 2021-01-28 + * + * @copyright Copyright (c) 2021 + * + */ + +#pragma once + +#include + +namespace windows_manager { + +class MicrosoftWindow: public IWindow { +public: + + MicrosoftWindow(const WindowConfig& config); + bool Update() override; +}; + +class MicrosoftWindowsManager: public IWindowsManager { +public: + MicrosoftWindowsManager() = default; + + // Movable only + MicrosoftWindowsManager(const MicrosoftWindowsManager&) = delete; + MicrosoftWindowsManager& operator=(const MicrosoftWindowsManager&) = delete; + + MicrosoftWindowsManager(MicrosoftWindowsManager&&) = default; + MicrosoftWindowsManager& operator=(MicrosoftWindowsManager&&) = default; + + bool Update(IWindow&) override final; + std::shared_ptr CreateNewWindow(const WindowConfig& config) override final; +}; + +} // namespace windows_manager diff --git a/library/Editor/include/Editor/WindowsManager/WindowConfig.h b/library/Editor/include/Editor/WindowsManager/WindowConfig.h new file mode 100644 index 0000000..3ac5a5b --- /dev/null +++ b/library/Editor/include/Editor/WindowsManager/WindowConfig.h @@ -0,0 +1,28 @@ +/** + * @file WindowConfig.h + * @brief Configuration for a newly created Window + * @version 0.1 + * @date 2021-01-28 + * + * @copyright Copyright (c) 2021 + * + */ + +#pragma once + +#include + +namespace windows_manager { + +struct Position { + float x; + float y; +}; + +struct WindowConfig { + size_t width; + size_t height; + Position position; +}; + +} // namespace windows_manager \ No newline at end of file diff --git a/library/Editor/src/GraphicEditor.cpp b/library/Editor/src/GraphicEditor.cpp new file mode 100644 index 0000000..9b697a9 --- /dev/null +++ b/library/Editor/src/GraphicEditor.cpp @@ -0,0 +1,32 @@ +#include +#include + +namespace fs = std::filesystem; +using namespace document; + +std::shared_ptr GraphicEditor::CreateNewDocument(const fs::path& path, DocumentType type) { + std::shared_ptr new_doc = nullptr; + switch (type) { + case DocumentType::JPG: + new_doc = std::make_shared(path); + break; + case DocumentType::PNG: + new_doc = std::make_shared(path); + } + + m_documents.push_back(new_doc); + return new_doc; +} + +DocumentType GraphicEditor::GetDocumentType(const fs::path& path) { + return DocumentType::JPG; +} + +void GraphicEditor::ImportDocument(const fs::path& path) { + auto doc_type = GetDocumentType(path); + CreateNewDocument(path, doc_type); +} + +void GraphicEditor::ExportDocument(const fs::path& path, DocumentType type) { + m_active_document->SaveAs(path, type); +} \ No newline at end of file diff --git a/library/Editor/src/WindowManager/GnomeWindowsManager.cpp b/library/Editor/src/WindowManager/GnomeWindowsManager.cpp new file mode 100644 index 0000000..b6740cd --- /dev/null +++ b/library/Editor/src/WindowManager/GnomeWindowsManager.cpp @@ -0,0 +1,36 @@ +/** + * @file GnomeWindowsManager.cpp + * @brief Implementation for GNU Linux (Gnome) + * @version 0.1 + * @date 2021-01-28 + * + * @copyright Copyright (c) 2021 + * + */ +#include + +#include + +namespace windows_manager { + +GnomeWindow::GnomeWindow(const WindowConfig& config): + IWindow(config) {} + +bool GnomeWindow::Update() { + return true; +} + +bool GnomeWindowsManager::Update(IWindow&) { + for (auto& window: m_windows) { + window->Update(); + } + return true; +} + +std::shared_ptr GnomeWindowsManager::CreateNewWindow(const WindowConfig& config) { + auto new_window = std::make_shared(config); + m_windows.push_back(new_window); + return new_window; +} + +} // namespace windows_manager \ No newline at end of file diff --git a/library/Editor/src/WindowManager/MicrosoftWindowsManager copy.cpp b/library/Editor/src/WindowManager/MicrosoftWindowsManager copy.cpp new file mode 100644 index 0000000..fe2d812 --- /dev/null +++ b/library/Editor/src/WindowManager/MicrosoftWindowsManager copy.cpp @@ -0,0 +1,37 @@ +/** + * @file MicrosoftWindowsManager.cpp + * @brief Implementation for Windows Manager from Microsoft + * @version 0.1 + * @date 2021-01-28 + * + * @copyright Copyright (c) 2021 + * + */ +#include + +#include + +namespace windows_manager { + +MicrosoftWindow::MicrosoftWindow(const WindowConfig& config): + IWindow(config) {} + +bool MicrosoftWindow::Update() { + std::cout << "Updated Microsoft Window\n"; + return true; +} + +bool MicrosoftWindowsManager::Update(IWindow&) { + for (auto& window: m_windows) { + window->Update(); + } + return true; +} + +std::shared_ptr MicrosoftWindowsManager::CreateNewWindow(const WindowConfig& config) { + auto new_window = std::make_shared(config); + m_windows.push_back(new_window); + return new_window; +} + +} // namespace windows_manager \ No newline at end of file diff --git a/library/Editor/test/CMakeLists.txt b/library/Editor/test/CMakeLists.txt new file mode 100644 index 0000000..b6826b6 --- /dev/null +++ b/library/Editor/test/CMakeLists.txt @@ -0,0 +1 @@ +add_project_test() \ No newline at end of file diff --git a/library/Editor/test/src/test_Editor.cpp b/library/Editor/test/src/test_Editor.cpp new file mode 100644 index 0000000..e13aff4 --- /dev/null +++ b/library/Editor/test/src/test_Editor.cpp @@ -0,0 +1,13 @@ +#include + +#include + +TEST(Editor, Ctor) +{ + GraphicEditor editor; +} + +int main(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 5e89cac..b3cc6bd 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,5 +1,5 @@ -project=Struct -binary_name=struct +project=Editor +binary_name=editor cmake . -DENABLE_GTEST=ON -DENABLE_DOXYGEN=ON # build lib cmake --build . --target lib_$project