diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index b3a1aa17b..e59d61d0a 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -587,8 +587,6 @@ void NotificationManager::PopNotification::render_left_sign(ImGuiWrapper& imgui) } void NotificationManager::PopNotification::render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) { - ImVec4 orange_color = ImGui::GetStyleColorVec4(ImGuiCol_Button); - orange_color.w = 0.8f; ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); Notifications_Internal::push_style_color(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_fading_out, m_current_fade_opacity); @@ -623,27 +621,9 @@ void NotificationManager::PopNotification::render_minimize_button(ImGuiWrapper& } bool NotificationManager::PopNotification::on_text_click() { - bool ret = true; - switch (m_data.type) { - case NotificationType::SlicingComplete : - //wxGetApp().plater()->export_gcode(false); - assert(m_evt_handler != nullptr); - if (m_evt_handler != nullptr) - wxPostEvent(m_evt_handler, ExportGcodeNotificationClickedEvent(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED)); - break; - case NotificationType::PresetUpdateAvailable : - //wxGetApp().plater()->export_gcode(false); - assert(m_evt_handler != nullptr); - if (m_evt_handler != nullptr) - wxPostEvent(m_evt_handler, PresetUpdateAvailableClickedEvent(EVT_PRESET_UPDATE_AVAILABLE_CLICKED)); - break; - case NotificationType::NewAppAvailable: - wxLaunchDefaultBrowser("https://github.com/prusa3d/PrusaSlicer/releases"); - break; - default: - break; - } - return ret; + if(m_data.callback != nullptr) + return m_data.callback(m_evt_handler); + return false; } void NotificationManager::PopNotification::update(const NotificationData& n) { @@ -831,6 +811,39 @@ bool NotificationManager::ExportFinishedNotification::on_text_click() Notifications_Internal::open_folder(m_export_dir_path); return false; } +//------ProgressBar---------------- +void NotificationManager::ProgressBarNotification::init() +{ + PopNotification::init(); + m_lines_count++; + m_endlines.push_back(m_endlines.back()); +} +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) +{ + PopNotification::render_text(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) +{ + float bar_y = win_size_y / 2 - win_size_y / 6 + m_line_height; + ImVec4 orange_color = ImVec4(.99f, .313f, .0f, 1.0f); + float invisible_length = 0;//((float)(m_data.duration - m_remaining_time) / (float)m_data.duration * win_size_x); + //invisible_length -= win_size_x / ((float)m_data.duration * 60.f) * (60 - m_countdown_frame); + ImVec2 lineEnd = ImVec2(win_pos_x - invisible_length - m_window_width_offset, win_pos_y + win_size_y/2 + m_line_height / 2); + ImVec2 lineStart = ImVec2(win_pos_x - win_size_x + m_left_indentation, win_pos_y + win_size_y/2 + m_line_height / 2); + ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, 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.7f); + /* + //countdown line + ImVec4 orange_color = ImGui::GetStyleColorVec4(ImGuiCol_Button); + float invisible_length = ((float)(m_data.duration - m_remaining_time) / (float)m_data.duration * win_size_x); + invisible_length -= win_size_x / ((float)m_data.duration * 60.f) * (60 - m_countdown_frame); + ImVec2 lineEnd = ImVec2(win_pos_x - invisible_length, win_pos_y + win_size_y - 5); + ImVec2 lineStart = ImVec2(win_pos_x - win_size_x, win_pos_y + win_size_y - 5); + ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (int)(orange_color.picture_width * 255.f * (m_fading_out ? m_current_fade_opacity : 1.f))), 2.f); + if (!m_paused) + m_countdown_frame++; + */ +} //------NotificationManager-------- NotificationManager::NotificationManager(wxEvtHandler* evt_handler) : m_evt_handler(evt_handler) @@ -948,7 +961,8 @@ void NotificationManager::push_slicing_complete_notification(GLCanvas3D& canvas, hypertext = _u8L("Export G-Code."); time = 0; } - NotificationData data{ NotificationType::SlicingComplete, NotificationLevel::RegularNotification, time, _u8L("Slicing finished."), hypertext }; + 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(data, m_id_provider, m_evt_handler, large), canvas, timestamp); } @@ -994,6 +1008,25 @@ void NotificationManager::push_exporting_finished_notification(GLCanvas3D& canva push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, on_removable, path, dir_path), canvas, 0); } +void NotificationManager::push_progress_bar_notification(const std::string& text, GLCanvas3D& canvas, float percentage) +{ + NotificationData data{ NotificationType::ProgressBar, NotificationLevel::ProgressBarNotification, 0, text }; + push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, 0),canvas, 0); +} +void NotificationManager::set_progress_bar_percentage(const std::string& text, float percentage, GLCanvas3D& canvas) +{ + bool found = false; + for (std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::ProgressBar && notification->compare_text(text)) { + dynamic_cast(notification.get())->set_percentage(percentage); + canvas.request_extra_frame(); + found = true; + } + } + if (!found) { + push_progress_bar_notification(text, canvas, percentage); + } +} bool NotificationManager::push_notification_data(const NotificationData ¬ification_data, GLCanvas3D& canvas, int timestamp) { return push_notification_data(std::make_unique(notification_data, m_id_provider, m_evt_handler), canvas, timestamp); diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 0550dab9b..d483173c3 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -60,7 +60,9 @@ enum class NotificationType // Object partially outside the print volume. Cannot slice. PlaterError, // Object fully outside the print volume, or extrusion outside the print volume. Slicing is not disabled. - PlaterWarning + PlaterWarning, + // Progress bar instead of text. + ProgressBar }; class NotificationManager @@ -74,6 +76,8 @@ public: RegularNotification = 1, // Information notification without a fade-out or with a longer fade-out. ImportantNotification, + // Important notification with progress bar, no fade-out, might appear again after closing. + ProgressBarNotification, // Warning, no fade-out. WarningNotification, // Error, no fade-out. @@ -121,7 +125,10 @@ public: void set_slicing_complete_large(bool large); // Exporting finished, show this information with path, button to open containing folder and if ejectable - eject button void push_exporting_finished_notification(GLCanvas3D& canvas, std::string path, std::string dir_path, bool on_removable); - // Close old notification ExportFinished. + // notification with progress bar + void push_progress_bar_notification(const std::string& text, GLCanvas3D& canvas, float percentage = 0); + void set_progress_bar_percentage(const std::string& text, float percentage, GLCanvas3D& canvas); + // Close old notification ExportFinished. void new_export_began(bool on_removable); // finds ExportFinished notification and closes it if it was to removable device void device_ejected(); @@ -137,13 +144,15 @@ public: private: // duration 0 means not disapearing struct NotificationData { - NotificationType type; - NotificationLevel level; + NotificationType type; + NotificationLevel level; // Fade out time - const int duration; - const std::string text1; - const std::string hypertext; - const std::string text2; + const int duration; + const std::string text1; + const std::string hypertext; + // Callback for hypertext - returns if notif shall close. + std::function callback { nullptr }; + const std::string text2; }; // Cache of IDs to identify and reuse ImGUI windows. @@ -301,6 +310,23 @@ private: int warning_step; }; + class ProgressBarNotification : public PopNotification + { + public: + ProgressBarNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, float percentage) : PopNotification(n, id_provider, evt_handler) { set_percentage(percentage); } + void set_percentage(float percent) { m_percentage = percent; if (percent >= 1.0f) m_progress_complete = true; else m_progress_complete = false; } + protected: + virtual void init(); + 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); + 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); + bool m_progress_complete{ false }; + float m_percentage; + }; + class ExportFinishedNotification : public PopNotification { public: @@ -369,8 +395,10 @@ private: {NotificationType::Mouse3dDisconnected, NotificationLevel::RegularNotification, 10, _u8L("3D Mouse disconnected.") }, // {NotificationType::Mouse3dConnected, NotificationLevel::RegularNotification, 5, _u8L("3D Mouse connected.") }, // {NotificationType::NewPresetsAviable, NotificationLevel::ImportantNotification, 20, _u8L("New Presets are available."), _u8L("See here.") }, - {NotificationType::PresetUpdateAvailable, NotificationLevel::ImportantNotification, 20, _u8L("Configuration update is available."), _u8L("See more.")}, - {NotificationType::NewAppAvailable, NotificationLevel::ImportantNotification, 20, _u8L("New version is available."), _u8L("See Releases page.")}, + {NotificationType::PresetUpdateAvailable, NotificationLevel::ImportantNotification, 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){ + wxLaunchDefaultBrowser("https://github.com/prusa3d/PrusaSlicer/releases"); return true; }}, //{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 diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 6b7b2214c..43c968d83 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3456,6 +3456,7 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) this->statusbar()->set_progress(evt.status.percent); this->statusbar()->set_status_text(_(evt.status.text) + wxString::FromUTF8("…")); + //notification_manager->set_progress_bar_percentage("Slicing progress", (float)evt.status.percent / 100.0f, *q->get_current_canvas3D()); } if (evt.status.flags & (PrintBase::SlicingStatus::RELOAD_SCENE | PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS)) { switch (this->printer_technology) { @@ -3507,7 +3508,6 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) void Plater::priv::on_slicing_completed(wxCommandEvent & evt) { notification_manager->push_slicing_complete_notification(*q->get_current_canvas3D(), evt.GetInt(), is_sidebar_collapsed()); - switch (this->printer_technology) { case ptFFF: this->update_fff_scene();