diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2149f21e7..fa3d96420 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6314,31 +6314,47 @@ std::vector GLCanvas3D::_parse_colors(const std::vector& col #if ENABLE_WARNING_TEXTURE_REMOVAL void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) { + enum ErrorType{ + PLATER_WARNING, + PLATER_ERROR, + SLICING_ERROR + }; std::string text; - bool error = false; + ErrorType error = ErrorType::PLATER_WARNING; switch (warning) { case EWarning::ObjectOutside: text = _u8L("An object outside the print area was detected."); break; - case EWarning::ToolpathOutside: text = _u8L("A toolpath outside the print area was detected."); error = true; break; - case EWarning::SlaSupportsOutside: text = _u8L("SLA supports outside the print area were detected."); error = true; break; + case EWarning::ToolpathOutside: text = _u8L("A toolpath outside the print area was detected."); error = ErrorType::SLICING_ERROR; break; + case EWarning::SlaSupportsOutside: text = _u8L("SLA supports outside the print area were detected."); error = ErrorType::PLATER_ERROR; break; case EWarning::SomethingNotShown: text = _u8L("Some objects are not visible."); break; case EWarning::ObjectClashed: text = _u8L("An object outside the print area was detected.\n" "Resolve the current problem to continue slicing."); - error = true; + error = ErrorType::PLATER_ERROR; break; } auto& notification_manager = *wxGetApp().plater()->get_notification_manager(); - if (state) { - if (error) - notification_manager.push_plater_error_notification(text); - else + switch (error) + { + case PLATER_WARNING: + if (state) notification_manager.push_plater_warning_notification(text); - } - else { - if (error) - notification_manager.close_plater_error_notification(text); else notification_manager.close_plater_warning_notification(text); + break; + case PLATER_ERROR: + if (state) + notification_manager.push_plater_error_notification(text); + else + notification_manager.close_plater_error_notification(text); + break; + case SLICING_ERROR: + if (state) + notification_manager.push_slicing_error_notification(text); + else + notification_manager.close_slicing_error_notification(text); + break; + default: + break; } } #else diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index e83a0014c..7f61ad7f3 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -169,13 +169,16 @@ void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float init imgui.set_next_window_pos(win_pos.x, win_pos.y, ImGuiCond_Always, 1.0f, 0.0f); imgui.set_next_window_size(m_window_width, m_window_height, ImGuiCond_Always); - // find if hovered - if (m_state == EState::Hovered) - m_state = EState::Shown; - + + // find if hovered FIXME: do it only in update state? + if (m_state == EState::Hovered) { + m_state = EState::Unknown; + init(); + } + if (mouse_pos.x < win_pos.x && mouse_pos.x > win_pos.x - m_window_width && mouse_pos.y > win_pos.y && mouse_pos.y < win_pos.y + m_window_height) { ImGui::SetNextWindowFocus(); - m_state = EState::Hovered; + set_hovered(); } // color change based on fading out @@ -185,22 +188,8 @@ void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float init fading_pop = true; } - // background color - if (m_is_gray) { - ImVec4 backcolor(0.7f, 0.7f, 0.7f, 0.5f); - Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); - } - else if (m_data.level == NotificationLevel::ErrorNotification) { - ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); - backcolor.x += 0.3f; - Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); - } - else if (m_data.level == NotificationLevel::WarningNotification) { - ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); - backcolor.x += 0.3f; - backcolor.y += 0.15f; - Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); - } + bool bgrnd_color_pop = push_background_color(); + // name of window indentifies window - has to be unique string if (m_id == 0) @@ -219,13 +208,34 @@ void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float init } imgui.end(); - if (m_is_gray || m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) + if (bgrnd_color_pop) ImGui::PopStyleColor(); if (fading_pop) ImGui::PopStyleColor(2); } - +bool NotificationManager::PopNotification::push_background_color() +{ + if (m_is_gray) { + ImVec4 backcolor(0.7f, 0.7f, 0.7f, 0.5f); + Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); + return true; + } + if (m_data.level == NotificationLevel::ErrorNotification) { + ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); + backcolor.x += 0.3f; + Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); + return true; + } + if (m_data.level == NotificationLevel::WarningNotification) { + ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); + backcolor.x += 0.3f; + backcolor.y += 0.15f; + Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); + return true; + } + return false; +} void NotificationManager::PopNotification::count_spaces() { //determine line width @@ -242,34 +252,28 @@ void NotificationManager::PopNotification::count_spaces() m_window_width = m_line_height * 25; } -void NotificationManager::PopNotification::init() +void NotificationManager::PopNotification::count_lines() { - // Do not init closing notification - if (is_finished()) - return; - - std::string text = m_text1 + " " + m_hypertext; - size_t last_end = 0; - m_lines_count = 0; + std::string text = m_text1 + " " + m_hypertext; + size_t last_end = 0; + m_lines_count = 0; - count_spaces(); - - // count lines m_endlines.clear(); while (last_end < text.length() - 1) { - size_t next_hard_end = text.find_first_of('\n', last_end); - if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset) { + size_t next_hard_end = text.find_first_of('\n', last_end); + if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset) { //next line is ended by '/n' m_endlines.push_back(next_hard_end); last_end = next_hard_end + 1; - } else { + } + else { // find next suitable endline if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset) { // more than one line till end - size_t next_space = text.find_first_of(' ', last_end); + size_t next_space = text.find_first_of(' ', last_end); if (next_space > 0) { - size_t next_space_candidate = text.find_first_of(' ', next_space + 1); + size_t next_space_candidate = text.find_first_of(' ', next_space + 1); while (next_space_candidate > 0 && ImGui::CalcTextSize(text.substr(last_end, next_space_candidate - last_end).c_str()).x < m_window_width - m_window_width_offset) { next_space = next_space_candidate; next_space_candidate = text.find_first_of(' ', next_space + 1); @@ -283,7 +287,8 @@ void NotificationManager::PopNotification::init() } m_endlines.push_back(last_end + letter_count); last_end += letter_count; - } else { + } + else { m_endlines.push_back(next_space); last_end = next_space + 1; } @@ -297,11 +302,22 @@ void NotificationManager::PopNotification::init() } m_lines_count++; } +} + +void NotificationManager::PopNotification::init() +{ + // Do not init closing notification + if (is_finished()) + return; + + count_spaces(); + count_lines(); + if (m_lines_count == 3) m_multiline = true; m_notification_start = GLCanvas3D::timestamp_now(); - //if (m_state != EState::Hidden) - // m_state = EState::Shown; + if (m_state == EState::Unknown) + m_state = EState::Shown; } void NotificationManager::PopNotification::set_next_window_size(ImGuiWrapper& imgui) { @@ -324,8 +340,8 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons if (m_multiline) { int last_end = 0; - float starting_y = m_line_height/2;//10; - float shift_y = m_line_height;// -m_line_height / 20; + float starting_y = m_line_height/2; + float shift_y = m_line_height; for (size_t i = 0; i < m_lines_count; i++) { std::string line = m_text1.substr(last_end , m_endlines[i] - last_end); if(i < m_lines_count - 1) @@ -549,7 +565,7 @@ void NotificationManager::PopNotification::update(const NotificationData& n) m_text2 = n.text2; init(); } -bool NotificationManager::PopNotification::compare_text(const std::string& text) +bool NotificationManager::PopNotification::compare_text(const std::string& text) const { std::wstring wt1 = boost::nowide::widen(m_text1); std::wstring wt2 = boost::nowide::widen(text); @@ -579,9 +595,10 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64 // reset timers - hovered state is set in render if (m_state == EState::Hovered) { m_current_fade_opacity = 1.0f; - m_notification_start = now; + m_state = EState::Unknown; + init(); // Timers when not fading - } else if (m_state != EState::FadingOut && m_data.duration != 0 && !paused) { + } else if (m_state != EState::NotFading && m_state != EState::FadingOut && m_data.duration != 0 && !paused) { int64_t up_time = now - m_notification_start; if (up_time >= m_data.duration * 1000) { m_state = EState::FadingOut; @@ -785,53 +802,154 @@ bool NotificationManager::ExportFinishedNotification::on_text_click() void NotificationManager::ProgressBarNotification::init() { PopNotification::init(); - m_lines_count++; - m_endlines.push_back(m_endlines.back()); -} -void NotificationManager::ProgressBarNotification::count_spaces() -{ - //determine line width - m_line_height = ImGui::CalcTextSize("A").y; - - m_left_indentation = m_line_height; - if (m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) { - std::string text; - text = (m_data.level == NotificationLevel::ErrorNotification ? ImGui::ErrorMarker : ImGui::WarningMarker); - float picture_width = ImGui::CalcTextSize(text.c_str()).x; - m_left_indentation = picture_width + m_line_height / 2; + //m_lines_count++; + 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()); } - m_window_width_offset = m_line_height * (m_has_cancel_button ? 6 : 4); - m_window_width = m_line_height * 25; + if(m_state == EState::Shown) + m_state = EState::NotFading; } + +void NotificationManager::ProgressBarNotification::count_lines() +{ + std::string text = m_text1 + " " + m_hypertext; + size_t last_end = 0; + m_lines_count = 0; + + m_endlines.clear(); + while (last_end < text.length() - 1) + { + size_t next_hard_end = text.find_first_of('\n', last_end); + if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset) { + //next line is ended by '/n' + m_endlines.push_back(next_hard_end); + last_end = next_hard_end + 1; + } + else { + // find next suitable endline + if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset) { + // more than one line till end + size_t next_space = text.find_first_of(' ', last_end); + if (next_space > 0) { + size_t next_space_candidate = text.find_first_of(' ', next_space + 1); + while (next_space_candidate > 0 && ImGui::CalcTextSize(text.substr(last_end, next_space_candidate - last_end).c_str()).x < m_window_width - m_window_width_offset) { + next_space = next_space_candidate; + next_space_candidate = text.find_first_of(' ', next_space + 1); + } + // when one word longer than line. Or the last space is too early. + if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset || + ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x < (m_window_width - m_window_width_offset) / 4 * 3 + ) { + float width_of_a = ImGui::CalcTextSize("a").x; + int letter_count = (int)((m_window_width - m_window_width_offset) / width_of_a); + while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset) { + letter_count++; + } + m_endlines.push_back(last_end + letter_count); + last_end += letter_count; + } + else { + m_endlines.push_back(next_space); + last_end = next_space + 1; + } + } + } + else { + m_endlines.push_back(text.length()); + last_end = text.length(); + } + + } + m_lines_count++; + } +} + + + void NotificationManager::ProgressBarNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) { // line1 - we do not print any more text than what fits on line 1. Line 2 is bar. - ImGui::SetCursorPosX(m_left_indentation); - ImGui::SetCursorPosY(win_size_y / 2 - win_size_y / 6 - m_line_height / 2); - imgui.text(m_text1.substr(0, m_endlines[0]).c_str()); - 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); + 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_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(/*win_size_y / 2 - win_size_y / 6 -*/ m_line_height / 4); + imgui.text(m_text1.substr(0, m_endlines[0]).c_str()); + 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); + } + } void NotificationManager::ProgressBarNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) { ImVec4 orange_color = ImVec4(.99f, .313f, .0f, 1.0f); ImVec4 gray_color = ImVec4(.34f, .34f, .34f, 1.0f); - ImVec2 lineEnd = ImVec2(win_pos_x - m_window_width_offset, win_pos_y + win_size_y / 2 + m_line_height / 4); - ImVec2 lineStart = ImVec2(win_pos_x - win_size_x + m_left_indentation, win_pos_y + win_size_y / 2 + m_line_height / 4); + 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); } //------PrintHostUploadNotification---------------- +void NotificationManager::PrintHostUploadNotification::init() +{ + ProgressBarNotification::init(); + if (m_state == EState::NotFading && m_uj_state == UploadJobState::PB_COMPLETED) + m_state = EState::Shown; +} +void NotificationManager::PrintHostUploadNotification::count_spaces() +{ + //determine line width + m_line_height = ImGui::CalcTextSize("A").y; + + 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); + float picture_width = ImGui::CalcTextSize(text.c_str()).x; + m_left_indentation = picture_width + m_line_height / 2; + } + m_window_width_offset = m_line_height * 6; //(m_has_cancel_button ? 6 : 4); + m_window_width = m_line_height * 25; +} +bool NotificationManager::PrintHostUploadNotification::push_background_color() +{ + + if (m_uj_state == UploadJobState::PB_ERROR) { + ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); + backcolor.x += 0.3f; + Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); + return true; + } + return false; +} void NotificationManager::PrintHostUploadNotification::set_percentage(float percent) { m_percentage = percent; if (percent >= 1.0f) { m_uj_state = UploadJobState::PB_COMPLETED; m_has_cancel_button = false; + init(); } else if (percent < 0.0f) { error(); } else { @@ -846,34 +964,44 @@ void NotificationManager::PrintHostUploadNotification::render_bar(ImGuiWrapper& case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_PROGRESS: { ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); - float uploaded = m_file_size / 100 * m_percentage; + float uploaded = m_file_size * m_percentage; std::stringstream stream; stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "% - " << uploaded << " of " << m_file_size << "MB uploaded"; text = stream.str(); ImGui::SetCursorPosX(m_left_indentation); - ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 /*- m_line_height / 4 * 3*/); + ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4)); break; } case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_ERROR: text = _u8L("ERROR"); ImGui::SetCursorPosX(m_left_indentation); - ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - m_line_height / 2); + ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2)); break; case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_CANCELLED: text = _u8L("CANCELED"); ImGui::SetCursorPosX(m_left_indentation); - ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - m_line_height / 2); + ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2)); break; case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_COMPLETED: text = _u8L("COMPLETED"); ImGui::SetCursorPosX(m_left_indentation); - ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - m_line_height / 2); + ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2)); break; } imgui.text(text.c_str()); } +void NotificationManager::PrintHostUploadNotification::render_left_sign(ImGuiWrapper& imgui) +{ + if (m_uj_state == UploadJobState::PB_ERROR) { + std::string text; + text = ImGui::ErrorMarker; + ImGui::SetCursorPosX(m_line_height / 3); + ImGui::SetCursorPosY(m_window_height / 2 - m_line_height); + imgui.text(text.c_str()); + } +} void NotificationManager::PrintHostUploadNotification::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); @@ -1059,6 +1187,14 @@ void NotificationManager::close_slicing_errors_and_warnings() } } } +void NotificationManager::close_slicing_error_notification(const std::string& text) +{ + for (std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::SlicingError && notification->compare_text(_u8L("ERROR:") + "\n" + text)) { + notification->close(); + } + } +} void NotificationManager::push_slicing_complete_notification(int timestamp, bool large) { std::string hypertext; @@ -1122,39 +1258,53 @@ void NotificationManager::push_exporting_finished_notification(const std::string void NotificationManager::push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage) { + // find if upload with same id was not already in notification + // done by compare_jon_id not compare_text thus has to be performed here + for (std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::PrintHostUpload && dynamic_cast(notification.get())->compare_job_id(id)) { + return; + } + } std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host); - NotificationData data{ NotificationType::PrintHostUpload, NotificationLevel::ProgressBarNotification, 0, text }; + NotificationData data{ NotificationType::PrintHostUpload, NotificationLevel::ProgressBarNotification, 10, text }; push_notification_data(std::make_unique(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) { - std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host); for (std::unique_ptr& notification : m_pop_notifications) { - if (notification->get_type() == NotificationType::PrintHostUpload && notification->compare_text(text)) { - dynamic_cast(notification.get())->set_percentage(percentage); - wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); + if (notification->get_type() == NotificationType::PrintHostUpload) { + PrintHostUploadNotification* phun = dynamic_cast(notification.get()); + if (phun->compare_job_id(id)) { + phun->set_percentage(percentage); + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); + break; + } } } } void NotificationManager::upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host) { - std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host); for (std::unique_ptr& notification : m_pop_notifications) { - if (notification->get_type() == NotificationType::PrintHostUpload && notification->compare_text(text)) { - dynamic_cast(notification.get())->cancel(); - wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); - break; + if (notification->get_type() == NotificationType::PrintHostUpload) { + PrintHostUploadNotification* phun = dynamic_cast(notification.get()); + if (phun->compare_job_id(id)) { + phun->cancel(); + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); + break; + } } } } void NotificationManager::upload_job_notification_show_error(int id, const std::string& filename, const std::string& host) { - std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host); for (std::unique_ptr& notification : m_pop_notifications) { - if (notification->get_type() == NotificationType::PrintHostUpload && notification->compare_text(text)) { - dynamic_cast(notification.get())->error(); - wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); - break; + if (notification->get_type() == NotificationType::PrintHostUpload) { + PrintHostUploadNotification* phun = dynamic_cast(notification.get()); + if(phun->compare_job_id(id)) { + phun->error(); + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); + break; + } } } } diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 4f3900aeb..17657948e 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -125,6 +125,7 @@ public: // void set_slicing_warning_gray(const std::string& text, bool g); // immediately stops showing slicing errors void close_slicing_errors_and_warnings(); + void close_slicing_error_notification(const std::string& text); // Release those slicing warnings, which refer to an ObjectID, which is not in the list. // living_oids is expected to be sorted. void remove_slicing_warnings_of_released_objects(const std::vector& living_oids); @@ -207,6 +208,7 @@ private: Unknown, // NOT initialized Hidden, Shown, // Requesting Render at some time if duration != 0 + NotFading, // Never jumps to state Fading out even if duration says so FadingOut, // Requesting Render at some time ClosePending, // Requesting Render Finished, // Requesting Render @@ -230,18 +232,17 @@ private: const NotificationData get_data() const { return m_data; } const bool is_gray() const { return m_is_gray; } void set_gray(bool g) { m_is_gray = g; } - bool compare_text(const std::string& text); + virtual bool compare_text(const std::string& text) const; void hide(bool h) { if (is_finished()) return; m_state = h ? EState::Hidden : EState::Unknown; } // sets m_next_render with time of next mandatory rendering. Delta is time since last render. bool update_state(bool paused, const int64_t delta); int64_t next_render() const { return is_finished() ? 0 : m_next_render; } EState get_state() const { return m_state; } bool is_hovered() const { return m_state == EState::Hovered; } - + void set_hovered() { if (m_state != EState::Finished && m_state != EState::ClosePending && m_state != EState::Hidden && m_state != EState::Unknown) m_state = EState::Hovered; } + protected: // Call after every size change virtual void init(); - // Part of init() - virtual void count_spaces(); // Calculetes correct size but not se it in imgui! virtual void set_next_window_size(ImGuiWrapper& imgui); virtual void render_text(ImGuiWrapper& imgui, @@ -255,13 +256,20 @@ private: const std::string text, bool more = false); // Left sign could be error or warning sign - void render_left_sign(ImGuiWrapper& imgui); + virtual void render_left_sign(ImGuiWrapper& imgui); virtual void render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y); // Hypertext action, returns true if notification should close. // Action is stored in NotificationData::callback as std::function virtual bool on_text_click(); - protected: + + // Part of init(), counts horizontal spacing like left indentation + virtual void count_spaces(); + // Part of init(), counts end lines + virtual void count_lines(); + // returns true if PopStyleColor should be called later to pop this push + virtual bool push_background_color(); + const NotificationData m_data; // For reusing ImGUI windows. NotificationIDProvider &m_id_provider; @@ -364,7 +372,8 @@ private: virtual void set_percentage(float percent) { m_percentage = percent; } protected: virtual void init() override; - virtual void count_spaces() override; + virtual void count_lines() override; + virtual void render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) override; @@ -375,6 +384,8 @@ private: const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) {} + virtual void render_minimize_button(ImGuiWrapper& imgui, + const float win_pos_x, const float win_pos_y) override {} float m_percentage; bool m_has_cancel_button {false}; @@ -401,17 +412,23 @@ private: { m_has_cancel_button = true; } - static std::string get_upload_job_text(int id, const std::string& filename, const std::string& host) { return "[" + std::to_string(id) + "] " + filename + " -> " + host; } + static std::string get_upload_job_text(int id, const std::string& filename, const std::string& host) { return /*"[" + std::to_string(id) + "] " + */filename + " -> " + host; } virtual void set_percentage(float percent) override; void cancel() { m_uj_state = UploadJobState::PB_CANCELLED; m_has_cancel_button = false; } - void error() { m_uj_state = UploadJobState::PB_ERROR; m_has_cancel_button = false; } + void error() { m_uj_state = UploadJobState::PB_ERROR; m_has_cancel_button = false; init(); } + bool compare_job_id(const int other_id) const { return m_job_id == other_id; } + virtual bool compare_text(const std::string& text) const override { return false; } protected: + virtual void init() override; + virtual void count_spaces() override; + virtual bool push_background_color() override; virtual void render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) override; virtual void 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) override; + virtual void render_left_sign(ImGuiWrapper& imgui) override; // Identifies job in cancel callback int m_job_id; // Size of uploaded size to be displayed in MB diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index f69db2ea3..762450c53 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -68,8 +68,10 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_pr combo_groups->SetValue(recent_group); } - btn_sizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL)); - + auto* szr = CreateStdDialogButtonSizer(wxOK | wxCANCEL); + auto* btn_ok = szr->GetAffirmativeButton(); + btn_sizer->Add(szr); + wxString recent_path = from_u8(app_config->get("recent", CONFIG_KEY_PATH)); if (recent_path.Length() > 0 && recent_path[recent_path.Length() - 1] != '/') { recent_path += '/'; @@ -82,6 +84,20 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_pr txt_filename->SetValue(recent_path); txt_filename->SetFocus(); + wxString suffix = recent_path.substr(recent_path.find_last_of('.')); + + btn_ok->Bind(wxEVT_BUTTON, [this, suffix](wxCommandEvent&) { + wxString path = txt_filename->GetValue(); + // .gcode suffix control + if (!path.Lower().EndsWith(suffix.Lower())) + { + wxMessageDialog msg_wingow(this, wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"), suffix), wxString(SLIC3R_APP_NAME), wxYES | wxNO); + if (msg_wingow.ShowModal() == wxID_NO) + return; + } + EndDialog(wxID_OK); + }); + Fit(); CenterOnParent();