From 976ef2c1b937a7a415a1bb462930ba3c0b44d218 Mon Sep 17 00:00:00 2001 From: David Kocik <kocikdav@gmail.com> Date: Thu, 23 Sep 2021 15:48:05 +0200 Subject: [PATCH] Progress bar notifications and Export finished notification changes. Export Finished notification ejecting state. Slicing began state in progress notification. Timing of progress bar notifications. Progress indicator disappears instantly at 100%. While slicing goes into Slicing Finished without fade out. Preventing of negative growth of slicing progress bar. Slicing progress bar - Negative percent value means now No info rather than Canceled. Hiding slicing progress at printer technology change. --- src/slic3r/GUI/NotificationManager.cpp | 126 +++++++++++++++++-------- src/slic3r/GUI/NotificationManager.hpp | 21 +++-- src/slic3r/GUI/Plater.cpp | 7 +- 3 files changed, 107 insertions(+), 47 deletions(-) diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 559ee283f..1b08e6cd2 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -593,7 +593,7 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64 m_state = EState::Unknown; init(); // Timers when not fading - } else if (m_state != EState::NotFading && m_state != EState::FadingOut && get_duration() != 0 && !paused) { + } else if (m_state != EState::NotFading && m_state != EState::FadingOut && m_state != EState::ClosePending && m_state != EState::Finished && get_duration() != 0 && !paused) { int64_t up_time = now - m_notification_start; if (up_time >= get_duration() * 1000) { m_state = EState::FadingOut; @@ -633,6 +633,10 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64 //---------------ExportFinishedNotification----------- void NotificationManager::ExportFinishedNotification::count_spaces() { + if (m_eject_pending) + { + return PopNotification::count_spaces(); + } //determine line width m_line_height = ImGui::CalcTextSize("A").y; @@ -650,7 +654,10 @@ void NotificationManager::ExportFinishedNotification::count_spaces() void NotificationManager::ExportFinishedNotification::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_eject_pending) + { + return PopNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); + } float x_offset = m_left_indentation; std::string fulltext = m_text1 + m_hypertext; //+ m_text2; // Lines are always at least two and m_multiline is always true for ExportFinishedNotification. @@ -669,7 +676,7 @@ void NotificationManager::ExportFinishedNotification::render_text(ImGuiWrapper& ImGui::SetCursorPosY(starting_y + i * shift_y); imgui.text(line.c_str()); //hyperlink text - if ( i == 0 ) { + if ( i == 0 && !m_eject_pending) { render_hypertext(imgui, x_offset + ImGui::CalcTextSize(line.c_str()).x + ImGui::CalcTextSize(" ").x, starting_y, _u8L("Open Folder.")); } } @@ -680,7 +687,7 @@ void NotificationManager::ExportFinishedNotification::render_text(ImGuiWrapper& void NotificationManager::ExportFinishedNotification::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) { PopNotification::render_close_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); - if(m_to_removable) + if(m_to_removable && ! m_eject_pending) render_eject_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); } @@ -725,7 +732,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW assert(m_evt_handler != nullptr); if (m_evt_handler != nullptr) wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED)); - close(); + on_eject_click(); } //invisible large button @@ -736,7 +743,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW assert(m_evt_handler != nullptr); if (m_evt_handler != nullptr) wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED)); - close(); + on_eject_click(); } ImGui::PopStyleColor(5); } @@ -745,6 +752,14 @@ bool NotificationManager::ExportFinishedNotification::on_text_click() open_folder(m_export_dir_path); return false; } +void NotificationManager::ExportFinishedNotification::on_eject_click() +{ + NotificationData data{ get_data().type, get_data().level , 0, _utf8("Ejecting.") }; + m_eject_pending = true; + m_multiline = false; + update(data); +} + //------ProgressBar---------------- void NotificationManager::ProgressBarNotification::init() { @@ -1071,7 +1086,7 @@ void NotificationManager::UpdatedItemsInfoNotification::render_left_sign(ImGuiWr imgui.text(text.c_str()); } -//------SlicingProgressNotificastion +//------SlicingProgressNotification void NotificationManager::SlicingProgressNotification::init() { if (m_sp_state == SlicingProgressState::SP_PROGRESS) { @@ -1084,46 +1099,53 @@ void NotificationManager::SlicingProgressNotification::init() } } -void NotificationManager::SlicingProgressNotification::set_progress_state(float percent) +bool NotificationManager::SlicingProgressNotification::set_progress_state(float percent) { if (percent < 0.f) - set_progress_state(SlicingProgressState::SP_CANCELLED); + return true;//set_progress_state(SlicingProgressState::SP_CANCELLED); else if (percent >= 1.f) - set_progress_state(SlicingProgressState::SP_COMPLETED); + return set_progress_state(SlicingProgressState::SP_COMPLETED); else - set_progress_state(SlicingProgressState::SP_PROGRESS, percent); + return set_progress_state(SlicingProgressState::SP_PROGRESS, percent); } -void NotificationManager::SlicingProgressNotification::set_progress_state(NotificationManager::SlicingProgressNotification::SlicingProgressState state, float percent/* = 0.f*/) +bool NotificationManager::SlicingProgressNotification::set_progress_state(NotificationManager::SlicingProgressNotification::SlicingProgressState state, float percent/* = 0.f*/) { switch (state) { case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING: + case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_BEGAN: m_state = EState::Hidden; set_percentage(-1); m_has_print_info = false; set_export_possible(false); - break; + m_sp_state = state; + return true; case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS: + if ((m_sp_state != SlicingProgressState::SP_BEGAN && m_sp_state != SlicingProgressState::SP_PROGRESS) || percent < m_percentage) + return false; set_percentage(percent); m_has_cancel_button = true; - break; + m_sp_state = state; + return true; 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; + m_sp_state = state; + return true; 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 + // m_export_possible is important only for SP_PROGRESS state, thus we can reset it here set_export_possible(false); - break; + m_sp_state = state; + return true; default: break; } - m_sp_state = state; + return false; } void NotificationManager::SlicingProgressNotification::set_status_text(const std::string& text) { @@ -1150,7 +1172,7 @@ void NotificationManager::SlicingProgressNotification::set_status_text(const std { 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; + m_state = EState::NotFading; } break; default: @@ -1170,7 +1192,7 @@ void NotificationManager::SlicingProgressNotification::set_sidebar_collapsed(boo { m_sidebar_collapsed = collapsed; if (m_sp_state == SlicingProgressState::SP_COMPLETED) - m_state = EState::Shown; + m_state = EState::NotFading; } void NotificationManager::SlicingProgressNotification::on_cancel_button() @@ -1184,9 +1206,9 @@ void NotificationManager::SlicingProgressNotification::on_cancel_button() int NotificationManager::SlicingProgressNotification::get_duration() { if (m_sp_state == SlicingProgressState::SP_CANCELLED) - return 10; + return 2; else if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed) - return 5; + return 0; else return 0; } @@ -1200,7 +1222,7 @@ bool NotificationManager::SlicingProgressNotification::update_state(bool paused } 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)) { + 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) { @@ -1235,7 +1257,7 @@ void NotificationManager::SlicingProgressNotification::render_text(ImGuiWrapper& render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); } */ - } else if (m_sp_state == SlicingProgressState::SP_COMPLETED) { + } else if (m_sp_state == SlicingProgressState::SP_COMPLETED && m_sidebar_collapsed) { // "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()); @@ -1260,21 +1282,18 @@ void NotificationManager::SlicingProgressNotification::render_text(ImGuiWrapper& 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) +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))) { + if (m_sp_state != SlicingProgressState::SP_PROGRESS) { 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_hypertext(ImGuiWrapper& imgui,const float text_x, const float text_y, const std::string text, bool more) +{ + if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed) + return; + ProgressBarNotification::render_hypertext(imgui, text_x, text_y, text, more); } 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) { @@ -1360,7 +1379,7 @@ void NotificationManager::ProgressIndicatorNotification::init() m_state = EState::NotFading; break; case Slic3r::GUI::NotificationManager::ProgressIndicatorNotification::ProgressIndicatorState::PIS_COMPLETED: - m_state = EState::Shown; + m_state = EState::ClosePending; break; default: break; @@ -1374,7 +1393,7 @@ void NotificationManager::ProgressIndicatorNotification::set_percentage(float pe m_has_cancel_button = true; m_progress_state = ProgressIndicatorState::PIS_PROGRESS_REQUEST; } else if (percent >= 1.0f) { - m_state = EState::Shown; + m_state = EState::FadingOut; m_progress_state = ProgressIndicatorState::PIS_COMPLETED; m_has_cancel_button = false; } else { @@ -1629,6 +1648,7 @@ void NotificationManager::push_exporting_finished_notification(const std::string close_notification_of_type(NotificationType::ExportFinished); 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); + set_slicing_progress_hidden(); } void NotificationManager::push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage) @@ -1701,12 +1721,39 @@ void NotificationManager::init_slicing_progress_notification(std::function<bool( }; push_notification_data(std::make_unique<NotificationManager::SlicingProgressNotification>(data, m_id_provider, m_evt_handler, cancel_callback), 0); } +void NotificationManager::set_slicing_progress_began() +{ + 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(SlicingProgressNotification::SlicingProgressState::SP_BEGAN); + 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_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); + if(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_canceled(const std::string& text) +{ + 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(SlicingProgressNotification::SlicingProgressState::SP_CANCELLED); spn->set_status_text(text); wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); return; @@ -1715,7 +1762,6 @@ void NotificationManager::set_slicing_progress_percentage(const std::string& tex // 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) { @@ -1773,7 +1819,7 @@ void NotificationManager::init_progress_indicator() return; } } - NotificationData data{ NotificationType::ProgressIndicator, NotificationLevel::ProgressBarNotificationLevel, 2}; + NotificationData data{ NotificationType::ProgressIndicator, NotificationLevel::ProgressBarNotificationLevel, 1}; auto notification = std::make_unique<NotificationManager::ProgressIndicatorNotification>(data, m_id_provider, m_evt_handler); push_notification_data(std::move(notification), 0); } diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index ee510b112..4481ed701 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -189,8 +189,10 @@ public: void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host); // slicing progress void init_slicing_progress_notification(std::function<bool()> cancel_callback); + void set_slicing_progress_began(); // percentage negative = canceled, <0-1) = progress, 1 = completed void set_slicing_progress_percentage(const std::string& text, float percentage); + void set_slicing_progress_canceled(const std::string& text); // hides slicing progress notification imidietly void set_slicing_progress_hidden(); // Add a print time estimate to an existing SlicingProgress notification. Set said notification to SP_COMPLETED state. @@ -492,6 +494,7 @@ private: enum class SlicingProgressState { SP_NO_SLICING, // hidden + SP_BEGAN, // still hidden but allows to go to SP_PROGRESS state. This prevents showing progress after slicing was canceled. SP_PROGRESS, // never fades outs, no close button, has cancel button SP_CANCELLED, // fades after 10 seconds, simple message SP_COMPLETED // Has export hyperlink and print info, fades after 20 sec if sidebar is shown, otherwise no fade out @@ -509,10 +512,10 @@ private: // sets cancel button callback void set_cancel_callback(std::function<bool()> callback) { m_cancel_callback = callback; } bool has_cancel_callback() const { return m_cancel_callback != nullptr; } - // sets SlicingProgressState, negative percent means canceled - void set_progress_state(float percent); - // sets SlicingProgressState, percent is used only at progress state. - void set_progress_state(SlicingProgressState state,float percent = 0.f); + // sets SlicingProgressState, negative percent means canceled, returns true if state was set succesfully. + bool set_progress_state(float percent); + // sets SlicingProgressState, percent is used only at progress state. Returns true if state was set succesfully. + bool set_progress_state(SlicingProgressState state,float percent = 0.f); // sets additional string of print info and puts notification into Completed state. void set_print_info(const std::string& info); // sets fading if in Completed state. @@ -541,8 +544,12 @@ private: const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) override; void 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) override; + const float win_size_x, const float win_size_y, + const float win_pos_x, const float win_pos_y) override; + void render_hypertext(ImGuiWrapper& imgui, + const float text_x, const float text_y, + const std::string text, + bool more = false) override ; void on_cancel_button(); int get_duration() override; // if returns false, process was already canceled @@ -626,8 +633,10 @@ private: void render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) override { m_minimize_b_visible = false; } bool on_text_click() override; + void on_eject_click(); // local time of last hover for showing tooltip long m_hover_time { 0 }; + bool m_eject_pending { false }; }; class UpdatedItemsInfoNotification : public PopNotification diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a71fb1448..a93a9d5e1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3104,6 +3104,9 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool // if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 || // (return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 ) // this->statusbar()->set_status_text(_L("Ready to slice")); + if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 || + (return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 ) + notification_manager->set_slicing_progress_hidden(); sidebar->set_btn_label(ActionButtonType::abExport, _(label_btn_export)); sidebar->set_btn_label(ActionButtonType::abSendGCode, _(label_btn_send)); @@ -3963,6 +3966,7 @@ void Plater::priv::on_slicing_began() clear_warnings(); notification_manager->close_notification_of_type(NotificationType::SignDetected); notification_manager->close_notification_of_type(NotificationType::ExportFinished); + notification_manager->set_slicing_progress_began(); } void Plater::priv::add_warning(const Slic3r::PrintStateBase::Warning& warning, size_t oid) { @@ -4060,7 +4064,7 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt) } if (evt.cancelled()) { // this->statusbar()->set_status_text(_L("Cancelled")); - this->notification_manager->set_slicing_progress_percentage(_utf8("Slicing Cancelled."), -1); + this->notification_manager->set_slicing_progress_canceled(_utf8("Slicing Cancelled.")); } this->sidebar->show_sliced_info_sizer(evt.success()); @@ -6375,6 +6379,7 @@ bool Plater::set_printer_technology(PrinterTechnology printer_technology) p->sidebar->get_searcher().set_printer_technology(printer_technology); p->notification_manager->set_fff(printer_technology == ptFFF); + p->notification_manager->set_slicing_progress_hidden(); return ret; }