feat: Added basic toast popups

This commit is contained in:
WerWolv
2023-12-19 23:21:20 +01:00
parent a6025e72fb
commit 2b5789631f
7 changed files with 183 additions and 3 deletions

View File

@@ -45,6 +45,7 @@ set(LIBIMHEX_SOURCES
source/ui/imgui_imhex_extensions.cpp
source/ui/view.cpp
source/ui/popup.cpp
source/ui/toast.cpp
source/subcommands/subcommands.cpp
)

View File

@@ -56,8 +56,9 @@ namespace hex {
return m_close;
}
protected:
static std::mutex& getMutex();
private:
UnlocalizedString m_unlocalizedName;
bool m_closeButton, m_modal;
std::atomic<bool> m_close = false;
@@ -74,8 +75,7 @@ namespace hex {
public:
template<typename ...Args>
static void open(Args && ... args) {
static std::mutex mutex;
std::lock_guard lock(mutex);
std::lock_guard lock(getMutex());
auto popup = std::make_unique<T>(std::forward<Args>(args)...);

View File

@@ -0,0 +1,60 @@
#pragma once
#include <hex.hpp>
#include <imgui.h>
#include <list>
#include <memory>
namespace hex {
namespace impl {
class ToastBase {
public:
ToastBase(ImColor color) : m_color(color) {}
virtual ~ToastBase() = default;
virtual void draw() { drawContent(); }
virtual void drawContent() = 0;
[[nodiscard]] static std::list<std::unique_ptr<ToastBase>> &getQueuedToasts();
[[nodiscard]] const ImColor& getColor() const {
return m_color;
}
void setAppearTime(double appearTime) {
m_appearTime = appearTime;
}
[[nodiscard]] double getAppearTime() const {
return m_appearTime;
}
constexpr static double VisibilityTime = 4.0;
protected:
static std::mutex& getMutex();
double m_appearTime = 0;
ImColor m_color;
};
}
template<typename T>
class Toast : public impl::ToastBase {
public:
using impl::ToastBase::ToastBase;
template<typename ...Args>
static void open(Args && ... args) {
std::lock_guard lock(getMutex());
auto toast = std::make_unique<T>(std::forward<Args>(args)...);
getQueuedToasts().emplace_back(std::move(toast));
}
};
}

View File

@@ -9,5 +9,12 @@ namespace hex::impl {
return openPopups;
}
std::mutex& PopupBase::getMutex() {
static std::mutex mutex;
return mutex;
}
}

View File

@@ -0,0 +1,17 @@
#include <hex/ui/toast.hpp>
namespace hex::impl {
[[nodiscard]] std::list<std::unique_ptr<ToastBase>> &ToastBase::getQueuedToasts() {
static std::list<std::unique_ptr<ToastBase>> queuedToasts;
return queuedToasts;
}
std::mutex& ToastBase::getMutex() {
static std::mutex mutex;
return mutex;
}
}

View File

@@ -39,6 +39,7 @@
#include <fonts/codicons_font.h>
#include <GLFW/glfw3.h>
#include <hex/ui/toast.hpp>
namespace hex {
@@ -753,6 +754,45 @@ namespace hex {
}
}
// Draw Toasts
{
static std::unique_ptr<impl::ToastBase> currToast;
if (currToast == nullptr) {
if (auto &queuedToasts = impl::ToastBase::getQueuedToasts(); !queuedToasts.empty()) {
currToast = std::move(queuedToasts.front());
queuedToasts.pop_front();
currToast->setAppearTime(ImGui::GetTime());
}
} else {
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5_scaled);
ImGui::SetNextWindowSize(scaled({ 280, 60 }));
ImGui::SetNextWindowPos((ImHexApi::System::getMainWindowPosition() + ImHexApi::System::getMainWindowSize()) - scaled({ 10, 10 }), ImGuiCond_Always, ImVec2(1, 1));
if (ImGui::Begin("##Toast", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoInputs)) {
auto drawList = ImGui::GetWindowDrawList();
const auto min = ImGui::GetWindowPos();
const auto max = min + ImGui::GetWindowSize();
drawList->PushClipRect(min, min + scaled({ 5, 60 }));
drawList->AddRectFilled(min, max, currToast->getColor(), 5_scaled);
drawList->PopClipRect();
ImGui::Indent();
currToast->draw();
ImGui::Unindent();
}
ImGui::End();
ImGui::PopStyleVar();
if ((currToast->getAppearTime() + impl::ToastBase::VisibilityTime) < ImGui::GetTime()) {
currToast.reset();
}
}
}
// Run all deferred calls
TaskManager::runDeferredCalls();

View File

@@ -0,0 +1,55 @@
#pragma once
#include <hex/api/imhex_api.hpp>
#include <hex/ui/imgui_imhex_extensions.h>
#include <hex/ui/toast.hpp>
#include <fonts/codicons_font.h>
#include <hex/helpers/utils.hpp>
namespace hex::plugin::builtin::ui {
namespace impl {
template<typename T>
struct ToastNotification : Toast<T> {
ToastNotification(ImColor color, const char *icon, UnlocalizedString title, UnlocalizedString message)
: Toast<T>(color), m_icon(icon), m_title(std::move(title)), m_message(std::move(message)) {}
void drawContent() final {
ImGuiExt::TextFormattedColored(this->getColor(), "{}", m_icon);
ImGui::SameLine();
ImGui::PushFont(ImHexApi::Fonts::Bold());
{
ImGuiExt::TextFormatted("{}", hex::limitStringLength(Lang(m_title).get(), 30));
}
ImGui::PopFont();
ImGui::Separator();
ImGuiExt::TextFormattedWrapped("{}", hex::limitStringLength(Lang(m_message).get(), 60));
}
private:
const char *m_icon;
UnlocalizedString m_title, m_message;
};
}
struct ToastInfo : impl::ToastNotification<ToastInfo> {
ToastInfo(UnlocalizedString title, UnlocalizedString message)
: ToastNotification(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerInfo), ICON_VS_INFO, std::move(title), std::move(message)) {}
};
struct ToastWarn : impl::ToastNotification<ToastWarn> {
ToastWarn(UnlocalizedString title, UnlocalizedString message)
: ToastNotification(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerWarning), ICON_VS_WARNING, std::move(title), std::move(message)) {}
};
struct ToastError : impl::ToastNotification<ToastError> {
ToastError(UnlocalizedString title, UnlocalizedString message)
: ToastNotification(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerError), ICON_VS_ERROR, std::move(title), std::move(message)) {}
};
}