Removes bottom status bar.

StatusBar class calls are commented out and replaced with notifications.
SlicicingProgress notification shows progress of slicing, ProgressIndicator notification handles other progress information, like arrange objects etc.
This commit is contained in:
David Kocik 2021-09-10 14:31:31 +02:00
parent 3db4804e47
commit b9dab7540e
23 changed files with 908 additions and 292 deletions

View file

@ -33,32 +33,32 @@ wxDEFINE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClic
wxDEFINE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent);
const NotificationManager::NotificationData NotificationManager::basic_notifications[] = {
{NotificationType::Mouse3dDisconnected, NotificationLevel::RegularNotification, 10, _u8L("3D Mouse disconnected.") },
{NotificationType::PresetUpdateAvailable, NotificationLevel::ImportantNotification, 20, _u8L("Configuration update is available."), _u8L("See more."),
{NotificationType::Mouse3dDisconnected, NotificationLevel::RegularNotificationLevel, 10, _u8L("3D Mouse disconnected.") },
{NotificationType::PresetUpdateAvailable, NotificationLevel::ImportantNotificationLevel, 20, _u8L("Configuration update is available."), _u8L("See more."),
[](wxEvtHandler* evnthndlr) {
if (evnthndlr != nullptr)
wxPostEvent(evnthndlr, PresetUpdateAvailableClickedEvent(EVT_PRESET_UPDATE_AVAILABLE_CLICKED));
return true;
}
},
{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotification, 20, _u8L("New version is available."), _u8L("See Releases page."), [](wxEvtHandler* evnthndlr) {
{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotificationLevel, 20, _u8L("New version is available."), _u8L("See Releases page."), [](wxEvtHandler* evnthndlr) {
wxGetApp().open_browser_with_warning_dialog("https://github.com/prusa3d/PrusaSlicer/releases"); return true; }},
{NotificationType::EmptyColorChangeCode, NotificationLevel::RegularNotification, 10,
{NotificationType::EmptyColorChangeCode, NotificationLevel::RegularNotificationLevel, 10,
_u8L("You have just added a G-code for color change, but its value is empty.\n"
"To export the G-code correctly, check the \"Color Change G-code\" in \"Printer Settings > Custom G-code\"") },
{NotificationType::EmptyAutoColorChange, NotificationLevel::RegularNotification, 10,
{NotificationType::EmptyAutoColorChange, NotificationLevel::RegularNotificationLevel, 10,
_u8L("No color change event was added to the print. The print does not look like a sign.") },
{NotificationType::DesktopIntegrationSuccess, NotificationLevel::RegularNotification, 10,
{NotificationType::DesktopIntegrationSuccess, NotificationLevel::RegularNotificationLevel, 10,
_u8L("Desktop integration was successful.") },
{NotificationType::DesktopIntegrationFail, NotificationLevel::WarningNotification, 10,
{NotificationType::DesktopIntegrationFail, NotificationLevel::WarningNotificationLevel, 10,
_u8L("Desktop integration failed.") },
{NotificationType::UndoDesktopIntegrationSuccess, NotificationLevel::RegularNotification, 10,
{NotificationType::UndoDesktopIntegrationSuccess, NotificationLevel::RegularNotificationLevel, 10,
_u8L("Undo desktop integration was successful.") },
{NotificationType::UndoDesktopIntegrationFail, NotificationLevel::WarningNotification, 10,
{NotificationType::UndoDesktopIntegrationFail, NotificationLevel::WarningNotificationLevel, 10,
_u8L("Undo desktop integration failed.") },
//{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotification, 20, _u8L("New vesion of PrusaSlicer is available.", _u8L("Download page.") },
//{NotificationType::LoadingFailed, NotificationLevel::RegularNotification, 20, _u8L("Loading of model has Failed") },
//{NotificationType::DeviceEjected, NotificationLevel::RegularNotification, 10, _u8L("Removable device has been safely ejected")} // if we want changeble text (like here name of device), we need to do it as CustomNotification
//{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotificationLevel, 20, _u8L("New vesion of PrusaSlicer is available.", _u8L("Download page.") },
//{NotificationType::LoadingFailed, NotificationLevel::RegularNotificationLevel, 20, _u8L("Loading of model has Failed") },
//{NotificationType::DeviceEjected, NotificationLevel::RegularNotificationLevel, 10, _u8L("Removable device has been safely ejected")} // if we want changeble text (like here name of device), we need to do it as CustomNotification
};
namespace {
@ -255,13 +255,13 @@ bool NotificationManager::PopNotification::push_background_color()
push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
return true;
}
if (m_data.level == NotificationLevel::ErrorNotification) {
if (m_data.level == NotificationLevel::ErrorNotificationLevel) {
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
backcolor.x += 0.3f;
push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
return true;
}
if (m_data.level == NotificationLevel::WarningNotification) {
if (m_data.level == NotificationLevel::WarningNotificationLevel) {
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
backcolor.x += 0.3f;
backcolor.y += 0.15f;
@ -276,9 +276,9 @@ void NotificationManager::PopNotification::count_spaces()
m_line_height = ImGui::CalcTextSize("A").y;
m_left_indentation = m_line_height;
if (m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) {
if (m_data.level == NotificationLevel::ErrorNotificationLevel || m_data.level == NotificationLevel::WarningNotificationLevel) {
std::string text;
text = (m_data.level == NotificationLevel::ErrorNotification ? ImGui::ErrorMarker : ImGui::WarningMarker);
text = (m_data.level == NotificationLevel::ErrorNotificationLevel ? ImGui::ErrorMarker : ImGui::WarningMarker);
float picture_width = ImGui::CalcTextSize(text.c_str()).x;
m_left_indentation = picture_width + m_line_height / 2;
}
@ -505,9 +505,9 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
void NotificationManager::PopNotification::render_left_sign(ImGuiWrapper& imgui)
{
if (m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) {
if (m_data.level == NotificationLevel::ErrorNotificationLevel || m_data.level == NotificationLevel::WarningNotificationLevel) {
std::string text;
text = (m_data.level == NotificationLevel::ErrorNotification ? ImGui::ErrorMarker : ImGui::WarningMarker);
text = (m_data.level == NotificationLevel::ErrorNotificationLevel ? ImGui::ErrorMarker : ImGui::WarningMarker);
ImGui::SetCursorPosX(m_line_height / 3);
ImGui::SetCursorPosY(m_window_height / 2 - m_line_height);
imgui.text(text.c_str());
@ -583,19 +583,23 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64
int64_t now = GLCanvas3D::timestamp_now();
// reset fade opacity for non-closing notifications or hover during fading
if (m_state != EState::FadingOut && m_state != EState::ClosePending && m_state != EState::Finished) {
m_current_fade_opacity = 1.0f;
}
// reset timers - hovered state is set in render
if (m_state == EState::Hovered) {
m_current_fade_opacity = 1.0f;
m_state = EState::Unknown;
init();
// Timers when not fading
} else if (m_state != EState::NotFading && m_state != EState::FadingOut && m_data.duration != 0 && !paused) {
} else if (m_state != EState::NotFading && m_state != EState::FadingOut && get_duration() != 0 && !paused) {
int64_t up_time = now - m_notification_start;
if (up_time >= m_data.duration * 1000) {
if (up_time >= get_duration() * 1000) {
m_state = EState::FadingOut;
m_fading_start = now;
} else {
m_next_render = m_data.duration * 1000 - up_time;
m_next_render = get_duration() * 1000 - up_time;
}
}
// Timers when fading
@ -626,53 +630,6 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64
return false;
}
NotificationManager::SlicingCompleteLargeNotification::SlicingCompleteLargeNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool large) :
NotificationManager::PopNotification(n, id_provider, evt_handler)
{
set_large(large);
}
void NotificationManager::SlicingCompleteLargeNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
if (!m_is_large)
PopNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
else {
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 text1_size = ImGui::CalcTextSize(m_text1.c_str());
float x_offset = m_left_indentation;
std::string fulltext = m_text1 + m_hypertext + m_text2;
ImVec2 text_size = ImGui::CalcTextSize(fulltext.c_str());
float cursor_y = win_size.y / 2 - text_size.y / 2;
if (m_has_print_info) {
x_offset = 20;
cursor_y = win_size.y / 2 + win_size.y / 6 - text_size.y / 2;
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(cursor_y);
imgui.text(m_print_info.c_str());
cursor_y = win_size.y / 2 - win_size.y / 6 - text_size.y / 2;
}
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(cursor_y);
imgui.text(m_text1.c_str());
render_hypertext(imgui, x_offset + text1_size.x + 4, cursor_y, m_hypertext);
}
}
void NotificationManager::SlicingCompleteLargeNotification::set_print_info(const std::string &info)
{
m_print_info = info;
m_has_print_info = true;
if (m_is_large)
m_lines_count = 2;
}
void NotificationManager::SlicingCompleteLargeNotification::set_large(bool l)
{
m_is_large = l;
//FIXME this information should not be lost (change m_data?)
// m_counting_down = !l;
m_hypertext = l ? _u8L("Export G-Code.") : std::string();
m_state = l ? EState::Shown : EState::Hidden;
init();
}
//---------------ExportFinishedNotification-----------
void NotificationManager::ExportFinishedNotification::count_spaces()
{
@ -680,9 +637,9 @@ void NotificationManager::ExportFinishedNotification::count_spaces()
m_line_height = ImGui::CalcTextSize("A").y;
m_left_indentation = m_line_height;
if (m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) {
if (m_data.level == NotificationLevel::ErrorNotificationLevel || m_data.level == NotificationLevel::WarningNotificationLevel) {
std::string text;
text = (m_data.level == NotificationLevel::ErrorNotification ? ImGui::ErrorMarker : ImGui::WarningMarker);
text = (m_data.level == NotificationLevel::ErrorNotificationLevel ? ImGui::ErrorMarker : ImGui::WarningMarker);
float picture_width = ImGui::CalcTextSize(text.c_str()).x;
m_left_indentation = picture_width + m_line_height / 2;
}
@ -793,6 +750,9 @@ void NotificationManager::ProgressBarNotification::init()
{
PopNotification::init();
//m_lines_count++;
if (m_endlines.empty()) {
m_endlines.push_back(0);
}
if(m_lines_count >= 2) {
m_lines_count = 3;
m_multiline = true;
@ -897,8 +857,17 @@ void NotificationManager::ProgressBarNotification::render_bar(ImGuiWrapper& imgu
ImVec2 lineEnd = ImVec2(win_pos_x - m_window_width_offset, win_pos_y + win_size_y / 2 + (m_multiline ? m_line_height / 2 : 0));
ImVec2 lineStart = ImVec2(win_pos_x - win_size_x + m_left_indentation, win_pos_y + win_size_y / 2 + (m_multiline ? m_line_height / 2 : 0));
ImVec2 midPoint = ImVec2(lineStart.x + (lineEnd.x - lineStart.x) * m_percentage, lineStart.y);
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(gray_color.x * 255), (int)(gray_color.y * 255), (int)(gray_color.z * 255), (1.0f * 255.f)), m_line_height * 0.2f);
ImGui::GetWindowDrawList()->AddLine(lineStart, midPoint, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (1.0f * 255.f)), m_line_height * 0.2f);
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(gray_color.x * 255), (int)(gray_color.y * 255), (int)(gray_color.z * 255), (m_current_fade_opacity * 255.f)), m_line_height * 0.2f);
ImGui::GetWindowDrawList()->AddLine(lineStart, midPoint, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (m_current_fade_opacity * 255.f)), m_line_height * 0.2f);
if (m_render_percentage) {
std::string text;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "%";
text = stream.str();
ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4));
imgui.text(text.c_str());
}
}
//------PrintHostUploadNotification----------------
void NotificationManager::PrintHostUploadNotification::init()
@ -915,7 +884,7 @@ void NotificationManager::PrintHostUploadNotification::count_spaces()
m_left_indentation = m_line_height;
if (m_uj_state == UploadJobState::PB_ERROR) {
std::string text;
text = (m_data.level == NotificationLevel::ErrorNotification ? ImGui::ErrorMarker : ImGui::WarningMarker);
text = (m_data.level == NotificationLevel::ErrorNotificationLevel ? ImGui::ErrorMarker : ImGui::WarningMarker);
float picture_width = ImGui::CalcTextSize(text.c_str()).x;
m_left_indentation = picture_width + m_line_height / 2;
}
@ -1102,15 +1071,382 @@ void NotificationManager::UpdatedItemsInfoNotification::render_left_sign(ImGuiWr
imgui.text(text.c_str());
}
//------SlicingProgressNotificastion
void NotificationManager::SlicingProgressNotification::init()
{
if (m_sp_state == SlicingProgressState::SP_PROGRESS) {
ProgressBarNotification::init();
//if (m_state == EState::NotFading && m_percentage >= 1.0f)
// m_state = EState::Shown;
}
else {
PopNotification::init();
}
}
void NotificationManager::SlicingProgressNotification::set_progress_state(float percent)
{
if (percent < 0.f)
set_progress_state(SlicingProgressState::SP_CANCELLED);
else if (percent >= 1.f)
set_progress_state(SlicingProgressState::SP_COMPLETED);
else
set_progress_state(SlicingProgressState::SP_PROGRESS, percent);
}
void NotificationManager::SlicingProgressNotification::set_progress_state(NotificationManager::SlicingProgressNotification::SlicingProgressState state, float percent/* = 0.f*/)
{
switch (state)
{
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING:
m_state = EState::Hidden;
set_percentage(-1);
m_has_print_info = false;
set_export_possible(false);
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS:
set_percentage(percent);
m_has_cancel_button = true;
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_CANCELLED:
set_percentage(-1);
m_has_cancel_button = false;
m_has_print_info = false;
set_export_possible(false);
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_COMPLETED:
set_percentage(1);
m_has_cancel_button = false;
m_has_print_info = false;
// m_export_possible is important only for PROGRESS state, thus we can reset it here
set_export_possible(false);
break;
default:
break;
}
m_sp_state = state;
}
void NotificationManager::SlicingProgressNotification::set_status_text(const std::string& text)
{
switch (m_sp_state)
{
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING:
m_state = EState::Hidden;
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS:
{
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, text + ".", m_is_fff ? _u8L("Export G-Code.") : _u8L("Export.") };
update(data);
m_state = EState::NotFading;
}
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_CANCELLED:
{
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, text };
update(data);
m_state = EState::Shown;
}
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_COMPLETED:
{
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, _u8L("Slicing finished."), m_is_fff ? _u8L("Export G-Code.") : _u8L("Export.") };
update(data);
m_state = EState::Shown;
}
break;
default:
break;
}
}
void NotificationManager::SlicingProgressNotification::set_print_info(const std::string& info)
{
if (m_sp_state != SlicingProgressState::SP_COMPLETED) {
set_progress_state (SlicingProgressState::SP_COMPLETED);
} else {
m_has_print_info = true;
m_print_info = info;
}
}
void NotificationManager::SlicingProgressNotification::set_sidebar_collapsed(bool collapsed)
{
m_sidebar_collapsed = collapsed;
if (m_sp_state == SlicingProgressState::SP_COMPLETED)
m_state = EState::Shown;
}
void NotificationManager::SlicingProgressNotification::on_cancel_button()
{
if (m_cancel_callback){
m_cancel_callback();
}
}
int NotificationManager::SlicingProgressNotification::get_duration()
{
if (m_sp_state == SlicingProgressState::SP_CANCELLED)
return 10;
else if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)
return 5;
else
return 0;
}
bool NotificationManager::SlicingProgressNotification::update_state(bool paused, const int64_t delta)
{
bool ret = ProgressBarNotification::update_state(paused, delta);
// sets Estate to hidden
if (get_state() == PopNotification::EState::ClosePending || get_state() == PopNotification::EState::Finished)
set_progress_state(SlicingProgressState::SP_NO_SLICING);
return ret;
}
void NotificationManager::SlicingProgressNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
if (m_sp_state == SlicingProgressState::SP_PROGRESS || (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)) {
ProgressBarNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
/* // enable for hypertext during slicing (correct call of export_enabled needed)
if (m_multiline) {
// two lines text, one line bar
ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(m_line_height / 4);
imgui.text(m_text1.substr(0, m_endlines[0]).c_str());
ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(m_line_height + m_line_height / 4);
std::string line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0), m_endlines[1] - m_endlines[0] - (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
imgui.text(line.c_str());
if (m_sidebar_collapsed && m_sp_state == SlicingProgressState::SP_PROGRESS && m_export_possible) {
ImVec2 text_size = ImGui::CalcTextSize(line.c_str());
render_hypertext(imgui, m_left_indentation + text_size.x + 4, m_line_height + m_line_height / 4, m_hypertext);
}
if (m_has_cancel_button)
render_cancel_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
else {
//one line text, one line bar
ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(m_line_height / 4);
std::string line = m_text1.substr(0, m_endlines[0]);
imgui.text(line.c_str());
if (m_sidebar_collapsed && m_sp_state == SlicingProgressState::SP_PROGRESS && m_export_possible) {
ImVec2 text_size = ImGui::CalcTextSize(line.c_str());
render_hypertext(imgui, m_left_indentation + text_size.x + 4, m_line_height / 4, m_hypertext);
}
if (m_has_cancel_button)
render_cancel_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
*/
} else if (m_sp_state == SlicingProgressState::SP_COMPLETED) {
// "Slicing Finished" on line 1 + hypertext, print info on line
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 text1_size = ImGui::CalcTextSize(m_text1.c_str());
float x_offset = m_left_indentation;
std::string fulltext = m_text1 + m_hypertext + m_text2;
ImVec2 text_size = ImGui::CalcTextSize(fulltext.c_str());
float cursor_y = win_size.y / 2 - text_size.y / 2;
if (m_sidebar_collapsed && m_has_print_info) {
x_offset = 20;
cursor_y = win_size.y / 2 + win_size.y / 6 - text_size.y / 2;
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(cursor_y);
imgui.text(m_print_info.c_str());
cursor_y = win_size.y / 2 - win_size.y / 6 - text_size.y / 2;
}
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(cursor_y);
imgui.text(m_text1.c_str());
if (m_sidebar_collapsed)
render_hypertext(imgui, x_offset + text1_size.x + 4, cursor_y, m_hypertext);
} else {
PopNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
}
void NotificationManager::SlicingProgressNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
if (!(m_sp_state == SlicingProgressState::SP_PROGRESS || (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed))) {
return;
}
//std::string text;
ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
/*
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "%";
text = stream.str();
ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4));
imgui.text(text.c_str());
*/
}
void NotificationManager::SlicingProgressNotification::render_cancel_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text;
button_text = ImGui::CancelButton;
if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y),
ImVec2(win_pos.x, win_pos.y + win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)),
true))
{
button_text = ImGui::CancelHoverButton;
}
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f);
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
on_cancel_button();
}
//invisible large button
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f);
ImGui::SetCursorPosY(0);
if (imgui.button(" ", m_line_height * 2.125, win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)))
{
on_cancel_button();
}
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
}
void NotificationManager::SlicingProgressNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
// Do not render close button while showing progress - cancel button is rendered instead
if (m_sp_state != SlicingProgressState::SP_PROGRESS) {
ProgressBarNotification::render_close_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
}
//------ProgressIndicatorNotification-------
void NotificationManager::ProgressIndicatorNotification::set_status_text(const char* text)
{
NotificationData data{ NotificationType::ProgressIndicator, NotificationLevel::ProgressBarNotificationLevel, 0, text };
update(data);
}
void NotificationManager::ProgressIndicatorNotification::init()
{
// skip ProgressBarNotification::init (same code here)
PopNotification::init();
if (m_endlines.empty()) {
m_endlines.push_back(0);
}
if (m_lines_count >= 2) {
m_lines_count = 3;
m_multiline = true;
while (m_endlines.size() < 3)
m_endlines.push_back(m_endlines.back());
}
else {
m_lines_count = 2;
m_endlines.push_back(m_endlines.back());
}
switch (m_progress_state)
{
case Slic3r::GUI::NotificationManager::ProgressIndicatorNotification::ProgressIndicatorState::PIS_HIDDEN:
m_state = EState::Hidden;
break;
case Slic3r::GUI::NotificationManager::ProgressIndicatorNotification::ProgressIndicatorState::PIS_PROGRESS_REQUEST:
case Slic3r::GUI::NotificationManager::ProgressIndicatorNotification::ProgressIndicatorState::PIS_PROGRESS_UPDATED:
m_state = EState::NotFading;
break;
case Slic3r::GUI::NotificationManager::ProgressIndicatorNotification::ProgressIndicatorState::PIS_COMPLETED:
m_state = EState::Shown;
break;
default:
break;
}
}
void NotificationManager::ProgressIndicatorNotification::set_percentage(float percent)
{
ProgressBarNotification::set_percentage(percent);
if (percent >= 0.0f && percent < 1.0f) {
m_state = EState::NotFading;
m_has_cancel_button = true;
m_progress_state = ProgressIndicatorState::PIS_PROGRESS_REQUEST;
} else if (percent >= 1.0f) {
m_state = EState::Shown;
m_progress_state = ProgressIndicatorState::PIS_COMPLETED;
m_has_cancel_button = false;
} else {
m_progress_state = ProgressIndicatorState::PIS_HIDDEN;
m_state = EState::Hidden;
}
}
bool NotificationManager::ProgressIndicatorNotification::update_state(bool paused, const int64_t delta)
{
if (m_progress_state == ProgressIndicatorState::PIS_PROGRESS_REQUEST) {
// percentage was changed (and it called schedule_extra_frame), now update must know this needs render
m_next_render = 0;
m_progress_state = ProgressIndicatorState::PIS_PROGRESS_UPDATED;
return true;
}
bool ret = ProgressBarNotification::update_state(paused, delta);
if (get_state() == PopNotification::EState::ClosePending || get_state() == PopNotification::EState::Finished)
// go to PIS_HIDDEN state
set_percentage(-1.0f);
return ret;
}
void NotificationManager::ProgressIndicatorNotification::render_cancel_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text;
button_text = ImGui::CancelButton;
if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y),
ImVec2(win_pos.x, win_pos.y + win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)),
true))
{
button_text = ImGui::CancelHoverButton;
}
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f);
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
on_cancel_button();
}
//invisible large button
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f);
ImGui::SetCursorPosY(0);
if (imgui.button(" ", m_line_height * 2.125, win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)))
{
on_cancel_button();
}
ImGui::PopStyleColor(5);
}
void NotificationManager::ProgressIndicatorNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
// Do not render close button while showing progress - cancel button is rendered instead
if (m_percentage >= 1.0f)
{
ProgressBarNotification::render_close_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
}
//------NotificationManager--------
NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
m_evt_handler(evt_handler)
{
}
NotificationManager::~NotificationManager()
{
HintDatabase::get_instance().uninit();
}
void NotificationManager::push_notification(const NotificationType type, int timestamp)
{
auto it = std::find_if(std::begin(basic_notifications), std::end(basic_notifications),
@ -1121,7 +1457,7 @@ void NotificationManager::push_notification(const NotificationType type, int tim
}
void NotificationManager::push_notification(const std::string& text, int timestamp)
{
push_notification_data({ NotificationType::CustomNotification, NotificationLevel::RegularNotification, 10, text }, timestamp);
push_notification_data({ NotificationType::CustomNotification, NotificationLevel::RegularNotificationLevel, 10, text }, timestamp);
}
void NotificationManager::push_notification(NotificationType type,
@ -1133,11 +1469,11 @@ void NotificationManager::push_notification(NotificationType type,
{
int duration = 0;
switch (level) {
case NotificationLevel::RegularNotification: duration = 10; break;
case NotificationLevel::ErrorNotification: break;
case NotificationLevel::WarningNotification: break;
case NotificationLevel::ImportantNotification: break;
case NotificationLevel::ProgressBarNotification: break;
case NotificationLevel::RegularNotificationLevel: duration = 10; break;
case NotificationLevel::ErrorNotificationLevel: break;
case NotificationLevel::WarningNotificationLevel: break;
case NotificationLevel::ImportantNotificationLevel: break;
case NotificationLevel::ProgressBarNotificationLevel: break;
default:
assert(false);
return;
@ -1146,18 +1482,19 @@ void NotificationManager::push_notification(NotificationType type,
}
void NotificationManager::push_validate_error_notification(const std::string& text)
{
push_notification_data({ NotificationType::ValidateError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, 0);
push_notification_data({ NotificationType::ValidateError, NotificationLevel::ErrorNotificationLevel, 0, _u8L("ERROR:") + "\n" + text }, 0);
set_slicing_progress_hidden();
}
void NotificationManager::push_slicing_error_notification(const std::string& text)
{
set_all_slicing_errors_gray(false);
push_notification_data({ NotificationType::SlicingError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, 0);
close_notification_of_type(NotificationType::SlicingComplete);
push_notification_data({ NotificationType::SlicingError, NotificationLevel::ErrorNotificationLevel, 0, _u8L("ERROR:") + "\n" + text }, 0);
set_slicing_progress_hidden();
}
void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, ObjectID oid, int warning_step)
{
NotificationData data { NotificationType::SlicingWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text };
NotificationData data { NotificationType::SlicingWarning, NotificationLevel::WarningNotificationLevel, 0, _u8L("WARNING:") + "\n" + text };
auto notification = std::make_unique<NotificationManager::SlicingWarningNotification>(data, m_id_provider, m_evt_handler);
notification->object_id = oid;
@ -1168,7 +1505,7 @@ void NotificationManager::push_slicing_warning_notification(const std::string& t
}
void NotificationManager::push_plater_error_notification(const std::string& text)
{
push_notification_data({ NotificationType::PlaterError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, 0);
push_notification_data({ NotificationType::PlaterError, NotificationLevel::ErrorNotificationLevel, 0, _u8L("ERROR:") + "\n" + text }, 0);
}
void NotificationManager::close_plater_error_notification(const std::string& text)
@ -1192,7 +1529,7 @@ void NotificationManager::push_plater_warning_notification(const std::string& te
}
}
NotificationData data{ NotificationType::PlaterWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text };
NotificationData data{ NotificationType::PlaterWarning, NotificationLevel::WarningNotificationLevel, 0, _u8L("WARNING:") + "\n" + text };
auto notification = std::make_unique<NotificationManager::PlaterWarningNotification>(data, m_id_provider, m_evt_handler);
push_notification_data(std::move(notification), 0);
@ -1252,49 +1589,12 @@ void NotificationManager::close_slicing_error_notification(const std::string& te
}
void NotificationManager::push_object_warning_notification(const std::string& text, ObjectID object_id, const std::string& hypertext/* = ""*/, std::function<bool(wxEvtHandler*)> callback/* = std::function<bool(wxEvtHandler*)>()*/)
{
NotificationData data{ NotificationType::ObjectWarning, NotificationLevel::WarningNotification, 0, text, hypertext, callback };
NotificationData data{ NotificationType::ObjectWarning, NotificationLevel::WarningNotificationLevel, 0, text, hypertext, callback };
auto notification = std::make_unique<NotificationManager::SlicingWarningNotification>(data, m_id_provider, m_evt_handler);
notification->object_id = object_id;
notification->warning_step = 0;
push_notification_data(std::move(notification), 0);
}
void NotificationManager::push_slicing_complete_notification(int timestamp, bool large)
{
std::string hypertext;
int time = 10;
if (has_slicing_error_notification())
return;
if (large) {
hypertext = _u8L("Export G-Code.");
time = 0;
}
NotificationData data{ NotificationType::SlicingComplete, NotificationLevel::RegularNotification, time, _u8L("Slicing finished."), hypertext,
[](wxEvtHandler* evnthndlr){
if (evnthndlr != nullptr)
wxPostEvent(evnthndlr, ExportGcodeNotificationClickedEvent(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED));
return true;
}
};
push_notification_data(std::make_unique<NotificationManager::SlicingCompleteLargeNotification>(data, m_id_provider, m_evt_handler, large), timestamp);
}
void NotificationManager::set_slicing_complete_print_time(const std::string &info)
{
for (std::unique_ptr<PopNotification> &notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingComplete) {
dynamic_cast<SlicingCompleteLargeNotification*>(notification.get())->set_print_info(info);
break;
}
}
}
void NotificationManager::set_slicing_complete_large(bool large)
{
for (std::unique_ptr<PopNotification> &notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingComplete) {
dynamic_cast<SlicingCompleteLargeNotification*>(notification.get())->set_large(large);
break;
}
}
}
void NotificationManager::close_notification_of_type(const NotificationType type)
{
for (std::unique_ptr<PopNotification> &notification : m_pop_notifications) {
@ -1324,7 +1624,7 @@ void NotificationManager::remove_object_warnings_of_released_objects(const std::
void NotificationManager::push_exporting_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable)
{
close_notification_of_type(NotificationType::ExportFinished);
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotification, on_removable ? 0 : 20, _u8L("Exporting finished.") + "\n" + path };
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotificationLevel, on_removable ? 0 : 20, _u8L("Exporting finished.") + "\n" + path };
push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path), 0);
}
@ -1338,7 +1638,7 @@ void NotificationManager::push_upload_job_notification(int id, float filesize,
}
}
std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host);
NotificationData data{ NotificationType::PrintHostUpload, NotificationLevel::ProgressBarNotification, 10, text };
NotificationData data{ NotificationType::PrintHostUpload, NotificationLevel::ProgressBarNotificationLevel, 10, text };
push_notification_data(std::make_unique<NotificationManager::PrintHostUploadNotification>(data, m_id_provider, m_evt_handler, 0, id, filesize), 0);
}
void NotificationManager::set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage)
@ -1380,6 +1680,153 @@ void NotificationManager::upload_job_notification_show_error(int id, const std::
}
}
}
void NotificationManager::init_slicing_progress_notification(std::function<void()> cancel_callback)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
dynamic_cast<SlicingProgressNotification*>(notification.get())->set_cancel_callback(cancel_callback);
return;
}
}
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, std::string(),std::string(),
[](wxEvtHandler* evnthndlr) {
if (evnthndlr != nullptr)
wxPostEvent(evnthndlr, ExportGcodeNotificationClickedEvent(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED));
return true;
}
};
push_notification_data(std::make_unique<NotificationManager::SlicingProgressNotification>(data, m_id_provider, m_evt_handler, cancel_callback), 0);
}
void NotificationManager::set_slicing_progress_percentage(const std::string& text, float percentage)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
SlicingProgressNotification* spn = dynamic_cast<SlicingProgressNotification*>(notification.get());
spn->set_progress_state(percentage);
spn->set_status_text(text);
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
return;
}
}
// Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended
wxGetApp().plater()->init_notification_manager();
}
void NotificationManager::set_slicing_progress_hidden()
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
SlicingProgressNotification* notif = dynamic_cast<SlicingProgressNotification*>(notification.get());
notif->set_progress_state(SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING);
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
return;
}
}
// Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended
wxGetApp().plater()->init_notification_manager();
}
void NotificationManager::set_slicing_complete_print_time(const std::string& info, bool sidebar_colapsed)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
dynamic_cast<SlicingProgressNotification*>(notification.get())->set_sidebar_collapsed(sidebar_colapsed);
dynamic_cast<SlicingProgressNotification*>(notification.get())->set_print_info(info);
break;
}
}
}
void NotificationManager::set_sidebar_collapsed(bool collapsed)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
dynamic_cast<SlicingProgressNotification*>(notification.get())->set_sidebar_collapsed(collapsed);
break;
}
}
}
void NotificationManager::set_fff(bool fff)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
dynamic_cast<SlicingProgressNotification*>(notification.get())->set_fff(fff);
break;
}
}
}
void NotificationManager::set_slicing_progress_export_possible()
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
dynamic_cast<SlicingProgressNotification*>(notification.get())->set_export_possible(true);
break;
}
}
}
void NotificationManager::init_progress_indicator()
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::ProgressIndicator) {
return;
}
}
NotificationData data{ NotificationType::ProgressIndicator, NotificationLevel::ProgressBarNotificationLevel, 2};
auto notification = std::make_unique<NotificationManager::ProgressIndicatorNotification>(data, m_id_provider, m_evt_handler);
push_notification_data(std::move(notification), 0);
}
void NotificationManager::progress_indicator_set_range(int range)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::ProgressIndicator) {
dynamic_cast<ProgressIndicatorNotification*>(notification.get())->set_range(range);
return;
}
}
init_progress_indicator();
}
void NotificationManager::progress_indicator_set_cancel_callback(CancelFn callback/* = CancelFn()*/)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::ProgressIndicator) {
dynamic_cast<ProgressIndicatorNotification*>(notification.get())->set_cancel_callback(callback);
return;
}
}
init_progress_indicator();
}
void NotificationManager::progress_indicator_set_progress(int pr)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::ProgressIndicator) {
dynamic_cast<ProgressIndicatorNotification*>(notification.get())->set_progress(pr);
// Ask for rendering - needs to be done on every progress. Calls to here doesnt trigger IDLE event or rendering.
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(100);
return;
}
}
init_progress_indicator();
}
void NotificationManager::progress_indicator_set_status_text(const char* text)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::ProgressIndicator) {
dynamic_cast<ProgressIndicatorNotification*>(notification.get())->set_status_text(text);
return;
}
}
init_progress_indicator();
}
int NotificationManager::progress_indicator_get_range() const
{
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::ProgressIndicator) {
return dynamic_cast<ProgressIndicatorNotification*>(notification.get())->get_range();
}
}
return 0;
}
void NotificationManager::push_hint_notification(bool open_next)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
@ -1389,7 +1836,7 @@ void NotificationManager::push_hint_notification(bool open_next)
}
}
NotificationData data{ NotificationType::DidYouKnowHint, NotificationLevel::RegularNotification, 300, "" };
NotificationData data{ NotificationType::DidYouKnowHint, NotificationLevel::HintNotificationLevel, 300, "" };
// from user - open now
if (!open_next) {
push_notification_data(std::make_unique<NotificationManager::HintNotification>(data, m_id_provider, m_evt_handler, open_next), 0);
@ -1397,8 +1844,8 @@ void NotificationManager::push_hint_notification(bool open_next)
// at startup - delay for half a second to let other notification pop up, than try every 30 seconds
// show only if no notifications are shown
} else {
auto condition = [this]() {
return this->get_notification_count() == 0;
auto condition = [&self = std::as_const(*this)]() {
return self.get_notification_count() == 0;
};
push_delayed_notification(std::make_unique<NotificationManager::HintNotification>(data, m_id_provider, m_evt_handler, open_next), condition, 500, 30000);
}
@ -1412,7 +1859,10 @@ bool NotificationManager::is_hint_notification_open()
}
return false;
}
void NotificationManager::deactivate_loaded_hints()
{
HintDatabase::get_instance().uninit();
}
void NotificationManager::push_updated_item_info_notification(InfoItemType type)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
@ -1422,7 +1872,7 @@ void NotificationManager::push_updated_item_info_notification(InfoItemType type)
}
}
NotificationData data{ NotificationType::UpdatedItemsInfo, NotificationLevel::RegularNotification, 5, "" };
NotificationData data{ NotificationType::UpdatedItemsInfo, NotificationLevel::RegularNotificationLevel, 5, "" };
auto notification = std::make_unique<NotificationManager::UpdatedItemsInfoNotification>(data, m_id_provider, m_evt_handler, type);
if (push_notification_data(std::move(notification), 0)) {
(dynamic_cast<UpdatedItemsInfoNotification*>(m_pop_notifications.back().get()))->add_type(type);
@ -1444,17 +1894,20 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
}
}
GLCanvas3D& canvas = *wxGetApp().plater()->get_current_canvas3D();
bool retval = false;
if (this->activate_existing(notification.get())) {
m_pop_notifications.back()->update(notification->get_data());
canvas.schedule_extra_frame(0);
return false;
if (m_initialized) { // ignore update action - it cant be initialized if canvas and imgui context is not ready
m_pop_notifications.back()->update(notification->get_data());
}
} else {
m_pop_notifications.emplace_back(std::move(notification));
canvas.schedule_extra_frame(0);
return true;
retval = true;
}
if (!m_initialized)
return retval;
GLCanvas3D& canvas = *wxGetApp().plater()->get_current_canvas3D();
canvas.schedule_extra_frame(0);
return retval;
}
void NotificationManager::push_delayed_notification(std::unique_ptr<NotificationManager::PopNotification> notification, std::function<bool(void)> condition_callback, int64_t initial_delay, int64_t delay_interval)
@ -1608,6 +2061,8 @@ void NotificationManager::set_in_preview(bool preview)
notification->hide(preview);
if (notification->get_type() == NotificationType::SignDetected)
notification->hide(!preview);
if (m_in_preview && notification->get_type() == NotificationType::DidYouKnowHint)
notification->close();
}
}