MassBuilderSaveTool/src/ToastQueue/ToastQueue.cpp

163 lines
5.2 KiB
C++

// MassBuilderSaveTool
// Copyright (C) 2021-2022 Guillaume Jacquemin
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <Corrade/Utility/FormatStl.h>
#include <Magnum/Math/Functions.h>
#include <imgui.h>
#include "../FontAwesome/IconsFontAwesome5.h"
#include "ToastQueue.h"
using namespace Corrade;
constexpr UnsignedInt success_colour = 0xff67d23bu;
constexpr UnsignedInt info_colour = 0xffcc832fu;
constexpr UnsignedInt warning_colour = 0xff2fcfc7u;
constexpr UnsignedInt error_colour = 0xff3134cdu;
constexpr UnsignedInt fade_time = 150;
constexpr Float base_opacity = 1.0f;
constexpr Vector2 padding{20.0f, 20.0f};
constexpr Float toast_spacing = 10.0f;
Toast::Toast(Type type, const std::string& message, std::chrono::milliseconds timeout):
_type{type}, _message{message}, _timeout{timeout}, _creationTime{std::chrono::steady_clock::now()}
{
_phaseTrack = Animation::Track<UnsignedInt, Phase>{{
{0, Phase::FadeIn},
{fade_time, Phase::Wait},
{fade_time + timeout.count(), Phase::FadeOut},
{(fade_time * 2) + timeout.count(), Phase::TimedOut}
}, Math::select, Animation::Extrapolation::Constant};
}
auto Toast::type() -> Type {
return _type;
}
auto Toast::message() -> const std::string& {
return _message;
}
auto Toast::timeout() -> std::chrono::milliseconds {
return _timeout;
}
auto Toast::creationTime() -> std::chrono::steady_clock::time_point {
return _creationTime;
}
auto Toast::elapsedTime() -> std::chrono::milliseconds {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - _creationTime);
}
auto Toast::phase() -> Phase {
return _phaseTrack.at(elapsedTime().count());
}
auto Toast::opacity() -> Float {
Phase phase = this->phase();
Long elapsed_time = elapsedTime().count();
if(phase == Phase::FadeIn) {
return Float(elapsed_time) / Float(fade_time);
}
else if(phase == Phase::FadeOut) {
return 1.0f - ((Float(elapsed_time) - Float(fade_time) - Float(_timeout.count())) / Float(fade_time));
}
return 1.0f;
}
void ToastQueue::addToast(Toast&& toast) {
_toasts.push_back(std::move(toast));
}
void ToastQueue::addToast(Toast::Type type, const std::string& message, std::chrono::milliseconds timeout) {
_toasts.emplace_back(type, message, timeout);
}
void ToastQueue::draw(Vector2i viewport_size) {
Float height = 0.0f;
for(UnsignedInt i = 0; i < _toasts.size(); i++) {
Toast* current = &_toasts[i];
if(current->phase() == Toast::Phase::TimedOut) {
removeToast(i);
continue;
}
std::string win_id = Utility::formatString("##Toast{}", i);
Float opacity = base_opacity * current->opacity();
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, opacity);
ImGui::SetNextWindowPos({viewport_size.x() - padding.x(), viewport_size.y() - padding.y() - height}, ImGuiCond_Always, {1.0f, 1.0f});
if(ImGui::Begin(win_id.c_str(), nullptr,
ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoDecoration|
ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoNav|ImGuiWindowFlags_NoFocusOnAppearing))
{
ImColor colour = 0xffffffff;
switch(current->type()) {
case Toast::Type::Default:
break;
case Toast::Type::Success:
colour = success_colour;
ImGui::TextColored(colour, ICON_FA_CHECK_CIRCLE);
break;
case Toast::Type::Info:
colour = info_colour;
ImGui::TextColored(colour, ICON_FA_INFO_CIRCLE);
break;
case Toast::Type::Warning:
colour = warning_colour;
ImGui::TextColored(colour, ICON_FA_EXCLAMATION_TRIANGLE);
break;
case Toast::Type::Error:
colour = error_colour;
ImGui::TextColored(colour, ICON_FA_TIMES_CIRCLE);
break;
}
if(current->type() != Toast::Type::Default) {
ImGui::SameLine();
}
if(current->message().length() > 127) {
ImGui::TextColored(colour, "%.*s...", 127, current->message().c_str());
}
else {
ImGui::TextColored(colour, current->message().c_str());
}
height += ImGui::GetWindowHeight() + toast_spacing;
}
ImGui::End();
ImGui::PopStyleVar();
}
}
void ToastQueue::removeToast(Long index) {
_toasts.erase(_toasts.begin() + index);
}