diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 005b3c11f..7f61ad7f3 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -188,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) @@ -222,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 @@ -245,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); @@ -286,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; } @@ -300,6 +302,17 @@ 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(); @@ -802,22 +815,64 @@ void NotificationManager::ProgressBarNotification::init() if(m_state == EState::Shown) m_state = EState::NotFading; } -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; + +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++; } - m_window_width_offset = m_line_height * (m_has_cancel_button ? 6 : 4); - m_window_width = m_line_height * 25; } + + 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. @@ -862,6 +917,32 @@ void NotificationManager::PrintHostUploadNotification::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; @@ -911,6 +992,16 @@ void NotificationManager::PrintHostUploadNotification::render_bar(ImGuiWrapper& 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); diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 1cf780988..17657948e 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -240,11 +240,9 @@ private: 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, @@ -258,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; @@ -367,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; @@ -378,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}; @@ -404,20 +412,23 @@ private: { m_has_cancel_button = true; } - virtual void init() override; 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