1
0
mirror of synced 2025-02-03 04:47:10 +01:00
Wolf b646ece14b
impr: Refactor and restructure Event Manager (#2082)
### Problem description
This PR addresses issue #2013 that described a cluttered Event Manager.

This is a DX issue and should not impact the users whatsoever.

### Implementation description
The changes revolve around three main points:

1. the Event Manager (`event_manager.hpp`) was split into four
categories: GUI, Interaction, Lifecycle, and Provider, and two types:
Events, and Requests. This results in the following files:
    - `events_gui.hpp`
    - `events_interaction.hpp`
    - `events_lifecycle.hpp`
    - `events_provider.hpp`
    - `requests_gui.hpp`
    - `requests_interaction.hpp`
    - `requests_lifecycle.hpp`
    - `requests_provider.hpp`

2. Every event and request now has its own piece of documentation, with
a `@brief`, accompanied by a longer comment if needed, and gets its
`@param`s described.

3. The old `event_manager.hpp` import was removed and replaced by the
correct imports wherever needed, as to reduce spread of those files only
to where they are truly useful.

### Additional things
The commits have been split into (chrono-)logical steps:
- `feat`: split the Event Manager, and replace the imports
- `refactor`, `chore`: make various small changes to match the required
structure
- `docs`: add documentation for events and requests

Hopefully, this will help to review the PR.
*Note: Beware of very long rebuild times in between the commits, use
them sparingly! The Actions will ensure this PR builds anyways*

Closes #2013

---------

Signed-off-by: BioTheWolff <47079795+BioTheWolff@users.noreply.github.com>
Co-authored-by: Nik <werwolv98@gmail.com>
2025-01-25 15:32:07 +00:00

192 lines
6.6 KiB
C++

#pragma once
#include <hex.hpp>
#include <imgui.h>
#include <imgui_internal.h>
#include <hex/ui/imgui_imhex_extensions.h>
#include <hex/api/imhex_api.hpp>
#include <hex/api/shortcut_manager.hpp>
#include <hex/api/localization_manager.hpp>
#include <hex/providers/provider.hpp>
#include <hex/providers/provider_data.hpp>
#include <hex/helpers/utils.hpp>
#include <map>
#include <string>
namespace hex {
class View {
explicit View(UnlocalizedString unlocalizedName, const char *icon);
public:
virtual ~View() = default;
/**
* @brief Draws the view
* @note Do not override this method. Override drawContent() instead
*/
virtual void draw() = 0;
/**
* @brief Draws the content of the view
*/
virtual void drawContent() = 0;
/**
* @brief Draws content that should always be visible, even if the view is not open
*/
virtual void drawAlwaysVisibleContent() { }
/**
* @brief Whether or not the view window should be drawn
* @return True if the view window should be drawn, false otherwise
*/
[[nodiscard]] virtual bool shouldDraw() const;
/**
* @brief Whether or not the entire view should be processed
* If this returns false, the view will not be drawn and no shortcuts will be handled. This includes things
* drawn in the drawAlwaysVisibleContent() function.
* @return True if the view should be processed, false otherwise
*/
[[nodiscard]] virtual bool shouldProcess() const;
/**
* @brief Whether or not the view should have an entry in the view menu
* @return True if the view should have an entry in the view menu, false otherwise
*/
[[nodiscard]] virtual bool hasViewMenuItemEntry() const;
/**
* @brief Gets the minimum size of the view window
* @return The minimum size of the view window
*/
[[nodiscard]] virtual ImVec2 getMinSize() const;
/**
* @brief Gets the maximum size of the view window
* @return The maximum size of the view window
*/
[[nodiscard]] virtual ImVec2 getMaxSize() const;
/**
* @brief Gets additional window flags for the view window
* @return Additional window flags for the view window
*/
[[nodiscard]] virtual ImGuiWindowFlags getWindowFlags() const;
[[nodiscard]] virtual bool shouldStoreWindowState() const { return true; }
[[nodiscard]] const char *getIcon() const { return m_icon; }
[[nodiscard]] bool &getWindowOpenState();
[[nodiscard]] const bool &getWindowOpenState() const;
[[nodiscard]] const UnlocalizedString &getUnlocalizedName() const;
[[nodiscard]] std::string getName() const;
[[nodiscard]] bool didWindowJustOpen();
void setWindowJustOpened(bool state);
void trackViewOpenState();
static void discardNavigationRequests();
[[nodiscard]] static std::string toWindowName(const UnlocalizedString &unlocalizedName);
public:
class Window;
class Special;
class Floating;
class Modal;
private:
UnlocalizedString m_unlocalizedViewName;
bool m_windowOpen = false, m_prevWindowOpen = false;
std::map<Shortcut, ShortcutManager::ShortcutEntry> m_shortcuts;
bool m_windowJustOpened = false;
const char *m_icon;
friend class ShortcutManager;
};
/**
* @brief A view that draws a regular window. This should be the default for most views
*/
class View::Window : public View {
public:
explicit Window(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
void draw() final {
if (this->shouldDraw()) {
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
if (ImGui::Begin(View::toWindowName(this->getUnlocalizedName()).c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | this->getWindowFlags())) {
this->drawContent();
}
ImGui::End();
}
}
};
/**
* @brief A view that doesn't handle any window creation and just draws its content.
* This should be used if you intend to draw your own special window
*/
class View::Special : public View {
public:
explicit Special(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
void draw() final {
if (this->shouldDraw()) {
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
this->drawContent();
}
}
};
/**
* @brief A view that draws a floating window. These are the same as regular windows but cannot be docked
*/
class View::Floating : public View::Window {
public:
explicit Floating(UnlocalizedString unlocalizedName) : Window(std::move(unlocalizedName), "") {}
[[nodiscard]] ImGuiWindowFlags getWindowFlags() const override { return ImGuiWindowFlags_NoDocking; }
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
};
/**
* @brief A view that draws a modal window. The window will always be drawn on top and will block input to other windows
*/
class View::Modal : public View {
public:
explicit Modal(UnlocalizedString unlocalizedName) : View(std::move(unlocalizedName), "") {}
void draw() final {
if (this->shouldDraw()) {
if (this->getWindowOpenState())
ImGui::OpenPopup(View::toWindowName(this->getUnlocalizedName()).c_str());
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
if (ImGui::BeginPopupModal(View::toWindowName(this->getUnlocalizedName()).c_str(), this->hasCloseButton() ? &this->getWindowOpenState() : nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | this->getWindowFlags())) {
this->drawContent();
ImGui::EndPopup();
}
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
this->getWindowOpenState() = false;
}
}
[[nodiscard]] virtual bool hasCloseButton() const { return true; }
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
};
}