mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Merge branch 'dk_bar'
This commit is contained in:
		
						commit
						b9b84f4f27
					
				
					 23 changed files with 908 additions and 292 deletions
				
			
		|  | @ -958,6 +958,8 @@ bool GUI_App::on_init_inner() | |||
| //     update_mode(); // !!! do that later
 | ||||
|     SetTopWindow(mainframe); | ||||
| 
 | ||||
|     plater_->init_notification_manager(); | ||||
| 
 | ||||
|     m_printhost_job_queue.reset(new PrintHostJobQueue(mainframe->printhost_queue_dlg())); | ||||
| 
 | ||||
|     if (is_gcode_viewer()) { | ||||
|  | @ -2278,7 +2280,7 @@ wxBookCtrlBase* GUI_App::tab_panel() const | |||
|     return mainframe->m_tabpanel; | ||||
| } | ||||
| 
 | ||||
| NotificationManager* GUI_App::notification_manager()  | ||||
| std::shared_ptr<NotificationManager> GUI_App::notification_manager()  | ||||
| { | ||||
|     return plater_->get_notification_manager(); | ||||
| } | ||||
|  |  | |||
|  | @ -276,7 +276,7 @@ public: | |||
|     ObjectLayers*        obj_layers(); | ||||
|     Plater*              plater(); | ||||
|     Model&      		 model(); | ||||
|     NotificationManager* notification_manager(); | ||||
|     std::shared_ptr<NotificationManager> notification_manager(); | ||||
| 
 | ||||
|     // Parameters extracted from the command line to be passed to GUI after initialization.
 | ||||
|     GUI_InitParams* init_params { nullptr }; | ||||
|  |  | |||
|  | @ -734,9 +734,9 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee | |||
| 
 | ||||
|             double top_area = area(object->get_layer(int(object->layers().size()) - 1)->lslices); | ||||
|             if( bottom_area - top_area > delta_area) { | ||||
|                 NotificationManager* notif_mngr = wxGetApp().plater()->get_notification_manager(); | ||||
|                 std::shared_ptr<NotificationManager> notif_mngr = wxGetApp().plater()->get_notification_manager(); | ||||
|                 notif_mngr->push_notification( | ||||
|                     NotificationType::SignDetected, NotificationManager::NotificationLevel::RegularNotification, | ||||
|                     NotificationType::SignDetected, NotificationManager::NotificationLevel::RegularNotificationLevel, | ||||
|                     _u8L("NOTE:") + "\n" + _u8L("Sliced object looks like the sign") + "\n", | ||||
|                     _u8L("Apply auto color change to print"), | ||||
|                     [this](wxEvtHandler*) { | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ static inline void show_notification_extruders_limit_exceeded() | |||
|     wxGetApp() | ||||
|         .plater() | ||||
|         ->get_notification_manager() | ||||
|         ->push_notification(NotificationType::MmSegmentationExceededExtrudersLimit, NotificationManager::NotificationLevel::RegularNotification, | ||||
|         ->push_notification(NotificationType::MmSegmentationExceededExtrudersLimit, NotificationManager::NotificationLevel::RegularNotificationLevel, | ||||
|                             GUI::format(_L("Your printer has more extruders than the multi-material painting gizmo supports. For this reason, only the " | ||||
|                                            "first %1% extruders will be able to be used for painting."), GLGizmoMmuSegmentation::EXTRUDERS_LIMIT)); | ||||
| } | ||||
|  |  | |||
|  | @ -337,7 +337,7 @@ void GLGizmoSimplify::on_set_state() | |||
|             auto notification_manager = wxGetApp().plater()->get_notification_manager(); | ||||
|             notification_manager->push_notification( | ||||
|                 NotificationType::CustomNotification, | ||||
|                 NotificationManager::NotificationLevel::RegularNotification, | ||||
|                 NotificationManager::NotificationLevel::RegularNotificationLevel, | ||||
|                 _u8L("ERROR: Wait until Simplification ends or Cancel process.")); | ||||
|             return; | ||||
|         } | ||||
|  |  | |||
|  | @ -194,7 +194,7 @@ bool GLGizmosManager::check_gizmos_closed_except(EType type) const | |||
|     if (get_current_type() != type && get_current_type() != Undefined) { | ||||
|         wxGetApp().plater()->get_notification_manager()->push_notification( | ||||
|                     NotificationType::CustomSupportsAndSeamRemovedAfterRepair, | ||||
|                     NotificationManager::NotificationLevel::RegularNotification, | ||||
|                     NotificationManager::NotificationLevel::RegularNotificationLevel, | ||||
|                     _u8L("ERROR: Please close all manipulators available from " | ||||
|                          "the left toolbar first")); | ||||
|         return false; | ||||
|  | @ -1256,7 +1256,7 @@ bool GLGizmosManager::is_in_editing_mode(bool error_notification) const | |||
|     if (error_notification) | ||||
|         wxGetApp().plater()->get_notification_manager()->push_notification( | ||||
|                     NotificationType::QuitSLAManualMode, | ||||
|                     NotificationManager::NotificationLevel::ErrorNotification, | ||||
|                     NotificationManager::NotificationLevel::ErrorNotificationLevel, | ||||
|                     _u8L("You are currently editing SLA support points. Please, " | ||||
|                          "apply or discard your changes first.")); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1012,7 +1012,7 @@ void NotificationManager::HintNotification::retrieve_data(bool new_hint/* = true | |||
| 	if(hint_data != nullptr) | ||||
|     { | ||||
|         NotificationData nd { NotificationType::DidYouKnowHint, | ||||
| 						      NotificationLevel::RegularNotification, | ||||
| 						      NotificationLevel::RegularNotificationLevel, | ||||
| 							  0, | ||||
| 						      hint_data->text, | ||||
| 							  hint_data->hypertext, nullptr, | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ namespace Slic3r { | |||
| class ModelInstance; | ||||
| 
 | ||||
| namespace GUI { | ||||
| class NotificationManager; | ||||
| 
 | ||||
| class ArrangeJob : public PlaterJob | ||||
| { | ||||
|  | @ -39,8 +40,8 @@ protected: | |||
|     void process() override; | ||||
| 
 | ||||
| public: | ||||
|     ArrangeJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater) | ||||
|         : PlaterJob{std::move(pri), plater} | ||||
|     ArrangeJob(std::shared_ptr<NotificationManager> nm, Plater *plater) | ||||
|         : PlaterJob{nm, plater} | ||||
|     {} | ||||
|      | ||||
|     int status_range() const override | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
| class Plater; | ||||
| class NotificationManager; | ||||
| 
 | ||||
| class FillBedJob : public PlaterJob | ||||
| { | ||||
|  | @ -27,8 +28,8 @@ protected: | |||
|     void process() override; | ||||
| 
 | ||||
| public: | ||||
|     FillBedJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater) | ||||
|         : PlaterJob{std::move(pri), plater} | ||||
|     FillBedJob(std::shared_ptr<NotificationManager> nm, Plater *plater) | ||||
|         : PlaterJob{nm, plater} | ||||
|     {} | ||||
| 
 | ||||
|     int status_range() const override | ||||
|  |  | |||
|  | @ -2,9 +2,11 @@ | |||
| #include <exception> | ||||
| 
 | ||||
| #include "Job.hpp" | ||||
| #include "../NotificationManager.hpp" | ||||
| #include <libslic3r/Thread.hpp> | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| void GUI::Job::run(std::exception_ptr &eptr) | ||||
|  | @ -30,8 +32,8 @@ void GUI::Job::update_status(int st, const wxString &msg) | |||
|     wxQueueEvent(this, evt); | ||||
| } | ||||
| 
 | ||||
| GUI::Job::Job(std::shared_ptr<ProgressIndicator> pri) | ||||
|     : m_progress(std::move(pri)) | ||||
| GUI::Job::Job(std::shared_ptr<NotificationManager> nm) | ||||
|     : m_notifications(nm) | ||||
| { | ||||
|     m_thread_evt_id = wxNewId(); | ||||
| 
 | ||||
|  | @ -40,21 +42,21 @@ GUI::Job::Job(std::shared_ptr<ProgressIndicator> pri) | |||
| 
 | ||||
|         auto msg = evt.GetString(); | ||||
|         if (!msg.empty() && !m_worker_error) | ||||
|             m_progress->set_status_text(msg.ToUTF8().data()); | ||||
|             m_notifications->progress_indicator_set_status_text(msg.ToUTF8().data()); | ||||
| 
 | ||||
|         if (m_finalized) return; | ||||
| 
 | ||||
|         m_progress->set_progress(evt.GetInt()); | ||||
|         m_notifications->progress_indicator_set_progress(evt.GetInt()); | ||||
|         if (evt.GetInt() == status_range() || m_worker_error) { | ||||
|             // set back the original range and cancel callback
 | ||||
|             m_progress->set_range(m_range); | ||||
|             m_progress->set_cancel_callback(); | ||||
|             m_notifications->progress_indicator_set_range(m_range); | ||||
|             m_notifications->progress_indicator_set_cancel_callback(); | ||||
|             wxEndBusyCursor(); | ||||
|              | ||||
|             if (m_worker_error) { | ||||
|                 m_finalized = true; | ||||
|                 m_progress->set_status_text(""); | ||||
|                 m_progress->set_progress(m_range); | ||||
|                 m_notifications->progress_indicator_set_status_text(""); | ||||
|                 m_notifications->progress_indicator_set_progress(m_range); | ||||
|                 on_exception(m_worker_error); | ||||
|             } | ||||
|             else { | ||||
|  | @ -86,12 +88,12 @@ void GUI::Job::start() | |||
|         prepare(); | ||||
|          | ||||
|         // Save the current status indicatior range and push the new one
 | ||||
|         m_range = m_progress->get_range(); | ||||
|         m_progress->set_range(status_range()); | ||||
|         m_range = m_notifications->progress_indicator_get_range(); | ||||
|         m_notifications->progress_indicator_set_range(status_range()); | ||||
|          | ||||
|         // init cancellation flag and set the cancel callback
 | ||||
|         m_canceled.store(false); | ||||
|         m_progress->set_cancel_callback( | ||||
|         m_notifications->progress_indicator_set_cancel_callback( | ||||
|                     [this]() { m_canceled.store(true); }); | ||||
|          | ||||
|         m_finalized  = false; | ||||
|  |  | |||
|  | @ -8,14 +8,13 @@ | |||
| 
 | ||||
| #include <slic3r/GUI/I18N.hpp> | ||||
| 
 | ||||
| #include "ProgressIndicator.hpp" | ||||
| 
 | ||||
| #include <wx/event.h> | ||||
| 
 | ||||
| #include <boost/thread.hpp> | ||||
| 
 | ||||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
| class NotificationManager; | ||||
| // A class to handle UI jobs like arranging and optimizing rotation.
 | ||||
| // These are not instant jobs, the user has to be informed about their
 | ||||
| // state in the status progress indicator. On the other hand they are
 | ||||
|  | @ -33,7 +32,7 @@ class Job : public wxEvtHandler | |||
|     boost::thread     m_thread; | ||||
|     std::atomic<bool> m_running{false}, m_canceled{false}; | ||||
|     bool              m_finalized = false, m_finalizing = false; | ||||
|     std::shared_ptr<ProgressIndicator> m_progress; | ||||
|     std::shared_ptr<NotificationManager>               m_notifications; | ||||
|     std::exception_ptr                 m_worker_error = nullptr; | ||||
|      | ||||
|     void run(std::exception_ptr &); | ||||
|  | @ -65,7 +64,7 @@ protected: | |||
|     } | ||||
|     | ||||
| public: | ||||
|     Job(std::shared_ptr<ProgressIndicator> pri); | ||||
|     Job(std::shared_ptr<NotificationManager> nm); | ||||
|      | ||||
|     bool is_finalized() const { return m_finalized; } | ||||
|      | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
| class Plater; | ||||
| class NotificationManager; | ||||
| 
 | ||||
| class PlaterJob : public Job { | ||||
| protected: | ||||
|  | @ -15,8 +16,8 @@ protected: | |||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     PlaterJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater): | ||||
|         Job{std::move(pri)}, m_plater{plater} {} | ||||
|     PlaterJob(std::shared_ptr<NotificationManager> nm, Plater *plater): | ||||
|         Job{nm}, m_plater{plater} {} | ||||
| }; | ||||
| 
 | ||||
| }} // namespace Slic3r::GUI
 | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ namespace Slic3r { | |||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
| class NotificationManager; | ||||
| 
 | ||||
| class RotoptimizeJob : public PlaterJob | ||||
| { | ||||
|     using FindFn = std::function<Vec2d(const ModelObject &           mo, | ||||
|  | @ -52,8 +54,8 @@ protected: | |||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     RotoptimizeJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater) | ||||
|         : PlaterJob{std::move(pri), plater} | ||||
|     RotoptimizeJob(std::shared_ptr<NotificationManager> nm, Plater *plater) | ||||
|         : PlaterJob{nm, plater} | ||||
|     {} | ||||
| 
 | ||||
|     void finalize() override; | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include "slic3r/GUI/GUI_App.hpp" | ||||
| #include "slic3r/GUI/Plater.hpp" | ||||
| #include "slic3r/GUI/GUI_ObjectList.hpp" | ||||
| #include "slic3r/GUI/NotificationManager.hpp" | ||||
| 
 | ||||
| #include "libslic3r/Model.hpp" | ||||
| #include "libslic3r/PresetBundle.hpp" | ||||
|  | @ -124,8 +125,8 @@ public: | |||
|     priv(Plater *plt) : plater{plt} {} | ||||
| }; | ||||
| 
 | ||||
| SLAImportJob::SLAImportJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater) | ||||
|     : PlaterJob{std::move(pri), plater}, p{std::make_unique<priv>(plater)} | ||||
| SLAImportJob::SLAImportJob(std::shared_ptr<NotificationManager> nm, Plater *plater) | ||||
|     : PlaterJob{nm, plater}, p{std::make_unique<priv>(plater)} | ||||
| {} | ||||
| 
 | ||||
| SLAImportJob::~SLAImportJob() = default; | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ | |||
| 
 | ||||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
| class NotificationManager; | ||||
| 
 | ||||
| class SLAImportJob : public PlaterJob { | ||||
|     class priv; | ||||
|      | ||||
|  | @ -16,7 +18,7 @@ protected: | |||
|     void finalize() override; | ||||
| 
 | ||||
| public: | ||||
|     SLAImportJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater); | ||||
|     SLAImportJob(std::shared_ptr<NotificationManager> nm, Plater *plater); | ||||
|     ~SLAImportJob(); | ||||
| 
 | ||||
|     void reset(); | ||||
|  |  | |||
|  | @ -155,13 +155,13 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S | |||
|     SetIcon(main_frame_icon(wxGetApp().get_app_mode())); | ||||
| 
 | ||||
| 	// initialize status bar
 | ||||
|     m_statusbar = std::make_shared<ProgressStatusBar>(this); | ||||
|     m_statusbar->set_font(GUI::wxGetApp().normal_font()); | ||||
|     if (wxGetApp().is_editor()) | ||||
|         m_statusbar->embed(this); | ||||
|     m_statusbar->set_status_text(_L("Version") + " " + | ||||
|         SLIC3R_VERSION + " - " + | ||||
|         _L("Remember to check for updates at https://github.com/prusa3d/PrusaSlicer/releases")); | ||||
| //    m_statusbar = std::make_shared<ProgressStatusBar>(this);
 | ||||
| //    m_statusbar->set_font(GUI::wxGetApp().normal_font());
 | ||||
| //    if (wxGetApp().is_editor())
 | ||||
| //        m_statusbar->embed(this);
 | ||||
| //    m_statusbar->set_status_text(_L("Version") + " " +
 | ||||
| //        SLIC3R_VERSION + " - " +
 | ||||
| //       _L("Remember to check for updates at https://github.com/prusa3d/PrusaSlicer/releases"));
 | ||||
| 
 | ||||
|     // initialize tabpanel and menubar
 | ||||
|     init_tabpanel(); | ||||
|  | @ -1033,7 +1033,7 @@ void MainFrame::on_sys_color_changed() | |||
|     wxGetApp().init_label_colours(); | ||||
| #ifdef __WXMSW__ | ||||
|     wxGetApp().UpdateDarkUI(m_tabpanel); | ||||
|     m_statusbar->update_dark_ui(); | ||||
|  //   m_statusbar->update_dark_ui();
 | ||||
| #ifdef _MSW_DARK_MODE | ||||
|     // update common mode sizer
 | ||||
|     if (!wxGetApp().tabs_as_menu()) | ||||
|  |  | |||
|  | @ -204,7 +204,7 @@ public: | |||
|     wxWindow*             m_plater_page{ nullptr }; | ||||
|     wxProgressDialog*     m_progress_dialog { nullptr }; | ||||
|     PrintHostQueueDialog* m_printhost_queue_dlg; | ||||
|     std::shared_ptr<ProgressStatusBar>  m_statusbar; | ||||
| //    std::shared_ptr<ProgressStatusBar>  m_statusbar;
 | ||||
| 
 | ||||
| #ifdef __APPLE__ | ||||
|     std::unique_ptr<wxTaskBarIcon> m_taskbar_icon; | ||||
|  |  | |||
|  | @ -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> ¬ification : 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> ¬ification : 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> ¬ification : 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(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include "GLCanvas3D.hpp" | ||||
| #include "Event.hpp" | ||||
| #include "I18N.hpp" | ||||
| #include "Jobs/ProgressIndicator.hpp" | ||||
| 
 | ||||
| #include <libslic3r/ObjectID.hpp> | ||||
| #include <libslic3r/Technologies.hpp> | ||||
|  | @ -27,6 +28,8 @@ wxDECLARE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationCli | |||
| using PresetUpdateAvailableClickedEvent = SimpleEvent; | ||||
| wxDECLARE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent); | ||||
| 
 | ||||
| using CancelFn = std::function<void()>; | ||||
| 
 | ||||
| class GLCanvas3D; | ||||
| class ImGuiWrapper; | ||||
| enum class InfoItemType; | ||||
|  | @ -34,9 +37,6 @@ enum class InfoItemType; | |||
| enum class NotificationType | ||||
| { | ||||
| 	CustomNotification, | ||||
| 	// Notification on end of slicing and G-code processing (the full G-code preview is available).
 | ||||
| 	// Contains a hyperlink to export the G-code to a removable media.
 | ||||
| 	SlicingComplete, | ||||
| //	SlicingNotPossible,
 | ||||
| 	// Notification on end of export to a removable media, with hyperling to eject the external media.
 | ||||
| 	// Obsolete by ExportFinished
 | ||||
|  | @ -78,6 +78,10 @@ enum class NotificationType | |||
| 	ProgressBar, | ||||
| 	// Progress bar with info from Print Host Upload Queue dialog.
 | ||||
| 	PrintHostUpload, | ||||
| 	// Progress bar with cancel button, cannot be closed
 | ||||
| 	// On end of slicing and G-code processing (the full G-code preview is available),
 | ||||
| 	// contains a hyperlink to export the G-code to a removable media or hdd.
 | ||||
| 	SlicingProgress, | ||||
| 	// Notification, when Color Change G-code is empty and user try to add color change on DoubleSlider.
 | ||||
|     EmptyColorChangeCode, | ||||
|     // Notification that custom supports/seams were deleted after mesh repair.
 | ||||
|  | @ -100,6 +104,8 @@ enum class NotificationType | |||
| 	// Shows when  ObjectList::update_info_items finds information that should be stressed to the user
 | ||||
| 	// Might contain logo taken from gizmos
 | ||||
| 	UpdatedItemsInfo, | ||||
| 	// Progress bar notification with methods to replace ProgressIndicator class.
 | ||||
| 	ProgressIndicator | ||||
| }; | ||||
| 
 | ||||
| class NotificationManager | ||||
|  | @ -109,27 +115,31 @@ public: | |||
| 	{ | ||||
| 		// The notifications will be presented in the order of importance, thus these enum values
 | ||||
| 		// are sorted by the importance.
 | ||||
| 		// "Good to know" notification, usually but not always with a quick fade-out.
 | ||||
| 		RegularNotification = 1, | ||||
| 		// Important notification with progress bar, no fade-out, might appear again after closing. Position at the bottom.
 | ||||
| 		ProgressBarNotificationLevel = 1, | ||||
| 		// "Did you know" notification with special icon and buttons, Position close to bottom.
 | ||||
| 		HintNotificationLevel, | ||||
| 		// "Good to know" notification, usually but not always with a quick fade-out.		
 | ||||
| 		RegularNotificationLevel, | ||||
| 		// 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, | ||||
| 		ImportantNotificationLevel, | ||||
| 		// Warning, no fade-out.
 | ||||
| 		WarningNotification, | ||||
| 		// Error, no fade-out.
 | ||||
| 		ErrorNotification, | ||||
| 		WarningNotificationLevel, | ||||
| 		// Error, no fade-out. Top most position.
 | ||||
| 		ErrorNotificationLevel, | ||||
| 	}; | ||||
| 
 | ||||
| 	NotificationManager(wxEvtHandler* evt_handler); | ||||
| 	~NotificationManager(); | ||||
| 	~NotificationManager(){} | ||||
| 	 | ||||
| 	// init is called after canvas3d is created. Notifications added before init are not showed or updated
 | ||||
| 	void init() { m_initialized = true; } | ||||
| 	// Push a prefabricated notification from basic_notifications (see the table at the end of this file).
 | ||||
| 	void push_notification(const NotificationType type, int timestamp = 0); | ||||
| 	// Push a NotificationType::CustomNotification with NotificationLevel::RegularNotification and 10s fade out interval.
 | ||||
| 	// Push a NotificationType::CustomNotification with NotificationLevel::RegularNotificationLevel and 10s fade out interval.
 | ||||
| 	void push_notification(const std::string& text, int timestamp = 0); | ||||
| 	// Push a NotificationType::CustomNotification with provided notification level and 10s for RegularNotification.
 | ||||
| 	// ErrorNotification and ImportantNotification are never faded out.
 | ||||
| 	// Push a NotificationType::CustomNotification with provided notification level and 10s for RegularNotificationLevel.
 | ||||
| 	// ErrorNotificationLevel and ImportantNotificationLevel are never faded out.
 | ||||
|     void push_notification(NotificationType type, NotificationLevel level, const std::string& text, const std::string& hypertext = "", | ||||
|                            std::function<bool(wxEvtHandler*)> callback = std::function<bool(wxEvtHandler*)>(), int timestamp = 0); | ||||
| 	// Creates Validate Error notification with a custom text and no fade out.
 | ||||
|  | @ -162,25 +172,44 @@ public: | |||
| 	// Close object warnings, whose ObjectID is not in the list.
 | ||||
| 	// living_oids is expected to be sorted.
 | ||||
| 	void remove_object_warnings_of_released_objects(const std::vector<ObjectID>& living_oids); | ||||
| 	// Creates special notification slicing complete.
 | ||||
| 	// If large = true (Plater side bar is closed), then printing time and export button is shown
 | ||||
| 	// at the notification and fade-out is disabled. Otherwise the fade out time is set to 10s.
 | ||||
| 	void push_slicing_complete_notification(int timestamp, bool large); | ||||
| 	// Add a print time estimate to an existing SlicingComplete notification.
 | ||||
| 	void set_slicing_complete_print_time(const std::string &info); | ||||
| 	// Called when the side bar changes its visibility, as the "slicing complete" notification supplements
 | ||||
| 	// the "slicing info" normally shown at the side bar.
 | ||||
| 	void set_slicing_complete_large(bool large); | ||||
| 	void set_sidebar_collapsed(bool collapsed); | ||||
| 	// Set technology for correct text in SlicingProgress.
 | ||||
| 	void set_fff(bool b); | ||||
| 	void set_fdm(bool b) { set_fff(b); } | ||||
| 	void set_sla(bool b) { set_fff(!b); } | ||||
| 	// Exporting finished, show this information with path, button to open containing folder and if ejectable - eject button
 | ||||
| 	void push_exporting_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable); | ||||
| 	// notification with progress bar
 | ||||
| 	// notifications with progress bar
 | ||||
| 	// print host upload
 | ||||
| 	void push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage = 0); | ||||
| 	void set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage); | ||||
| 	void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host); | ||||
| 	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<void()> cancel_callback); | ||||
| 	// percentage negative = canceled, <0-1) = progress, 1 = completed 
 | ||||
| 	void set_slicing_progress_percentage(const std::string& text, float percentage); | ||||
| 	// 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.
 | ||||
| 	void set_slicing_complete_print_time(const std::string& info, bool sidebar_colapsed); | ||||
| 	void set_slicing_progress_export_possible(); | ||||
| 	// ProgressIndicator notification
 | ||||
| 	// init adds hidden instance of progress indi notif that should always live (goes to hidden instead of erasing)
 | ||||
| 	void init_progress_indicator(); | ||||
| 	// functions equal to ProgressIndicator class
 | ||||
| 	void progress_indicator_set_range(int range); | ||||
| 	void progress_indicator_set_cancel_callback(CancelFn callback = CancelFn()); | ||||
| 	void progress_indicator_set_progress(int pr); | ||||
| 	void progress_indicator_set_status_text(const char*); // utf8 char array
 | ||||
| 	int  progress_indicator_get_range() const; | ||||
| 	// Hint (did you know) notification
 | ||||
| 	void push_hint_notification(bool open_next); | ||||
| 	bool is_hint_notification_open(); | ||||
| 	// Forces Hints to reload its content when next hint should be showed
 | ||||
| 	void deactivate_loaded_hints(); | ||||
| 	void push_updated_item_info_notification(InfoItemType type); | ||||
| 	// Close old notification ExportFinished.
 | ||||
| 	void new_export_began(bool on_removable); | ||||
|  | @ -267,7 +296,7 @@ private: | |||
| 		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); | ||||
| 		virtual 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; }  | ||||
|  | @ -303,6 +332,8 @@ private: | |||
| 		virtual void count_lines(); | ||||
| 		// returns true if PopStyleColor should be called later to pop this push
 | ||||
| 		virtual bool push_background_color(); | ||||
| 		// used this function instead of reading directly m_data.duration. Some notifications might need to return changing value.
 | ||||
| 		virtual int  get_duration() { return m_data.duration; } | ||||
| 
 | ||||
| 		const NotificationData m_data; | ||||
| 		// For reusing ImGUI windows.
 | ||||
|  | @ -359,29 +390,7 @@ private: | |||
| 		wxEvtHandler*    m_evt_handler; | ||||
| 	}; | ||||
| 
 | ||||
| 	class SlicingCompleteLargeNotification : public PopNotification | ||||
| 	{ | ||||
| 	public: | ||||
| 		SlicingCompleteLargeNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool largeds); | ||||
| 		void			set_large(bool l); | ||||
| 		bool			get_large() { return m_is_large; } | ||||
| 		void			set_print_info(const std::string &info); | ||||
| 		void			render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width) override | ||||
| 		{ | ||||
| 			// This notification is always hidden if !large (means side bar is collapsed)
 | ||||
| 			if (!get_large() && !is_finished())  | ||||
| 				m_state = EState::Hidden; | ||||
| 			PopNotification::render(canvas, initial_y, move_from_overlay, overlay_width); | ||||
| 		} | ||||
| 	protected: | ||||
| 		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; | ||||
| 		bool        m_is_large; | ||||
| 		bool        m_has_print_info { false }; | ||||
|         std::string m_print_info; | ||||
| 	}; | ||||
| 	 | ||||
| 
 | ||||
| 	class SlicingWarningNotification : public PopNotification | ||||
| 	{ | ||||
|  | @ -405,7 +414,7 @@ private: | |||
| 	{ | ||||
| 	public: | ||||
| 		 | ||||
| 		ProgressBarNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, float percentage) : PopNotification(n, id_provider, evt_handler) { } | ||||
| 		ProgressBarNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler) : PopNotification(n, id_provider, evt_handler) { } | ||||
| 		virtual void set_percentage(float percent) { m_percentage = percent; } | ||||
| 	protected: | ||||
| 		virtual void init() override; | ||||
|  | @ -423,9 +432,10 @@ private: | |||
| 		{} | ||||
| 		void			render_minimize_button(ImGuiWrapper& imgui, | ||||
| 			const float win_pos_x, const float win_pos_y) override {} | ||||
| 		float				m_percentage; | ||||
| 		float				m_percentage {0.0f}; | ||||
| 		 | ||||
| 		bool				m_has_cancel_button {false}; | ||||
| 		bool                m_render_percentage {false}; | ||||
| 		// local time of last hover for showing tooltip
 | ||||
| 		 | ||||
| 	}; | ||||
|  | @ -443,7 +453,7 @@ private: | |||
| 			PB_COMPLETED | ||||
| 		}; | ||||
| 		PrintHostUploadNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, float percentage, int job_id, float filesize) | ||||
| 			:ProgressBarNotification(n, id_provider, evt_handler, percentage) | ||||
| 			:ProgressBarNotification(n, id_provider, evt_handler) | ||||
| 			, m_job_id(job_id) | ||||
| 			, m_file_size(filesize) | ||||
| 		{ | ||||
|  | @ -472,7 +482,117 @@ private: | |||
| 		// Size of uploaded size to be displayed in MB
 | ||||
| 		float			    m_file_size; | ||||
| 		long				m_hover_time{ 0 }; | ||||
| 		UploadJobState	m_uj_state{ UploadJobState::PB_PROGRESS }; | ||||
| 		UploadJobState		m_uj_state{ UploadJobState::PB_PROGRESS }; | ||||
| 	}; | ||||
| 
 | ||||
| 	class SlicingProgressNotification : public ProgressBarNotification | ||||
| 	{ | ||||
| 	public: | ||||
| 		// Inner state of notification, Each state changes bahaviour of the notification
 | ||||
| 		enum class SlicingProgressState | ||||
| 		{ | ||||
| 			SP_NO_SLICING, // hidden
 | ||||
| 			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
 | ||||
| 		}; | ||||
| 		SlicingProgressNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, std::function<void()> callback) | ||||
| 		: ProgressBarNotification(n, id_provider, evt_handler) | ||||
| 		, m_cancel_callback(callback) | ||||
| 		{ | ||||
| 			set_progress_state(SlicingProgressState::SP_NO_SLICING); | ||||
| 			m_has_cancel_button = false; | ||||
| 			m_render_percentage = true; | ||||
| 		} | ||||
| 		// sets text of notification - call after setting progress state
 | ||||
| 		void				set_status_text(const std::string& text); | ||||
| 		// sets cancel button callback
 | ||||
| 		void			    set_cancel_callback(std::function<void()> 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 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.
 | ||||
| 		void                set_sidebar_collapsed(bool collapsed); | ||||
| 		// Calls inherited update_state and ensures Estate goes to hidden not closing.
 | ||||
| 		bool                update_state(bool paused, const int64_t delta) override; | ||||
| 		// Switch between technology to provide correct text.
 | ||||
| 		void				set_fff(bool b) { m_is_fff = b; } | ||||
| 		void				set_fdm(bool b) { m_is_fff = b; } | ||||
| 		void				set_sla(bool b) { m_is_fff = !b; } | ||||
| 		void                set_export_possible(bool b) { m_export_possible = b; } | ||||
| 	protected: | ||||
| 		void        init() override; | ||||
| 		void        count_lines() override  | ||||
| 		{ | ||||
| 			if (m_sp_state == SlicingProgressState::SP_PROGRESS) | ||||
| 				ProgressBarNotification::count_lines(); | ||||
| 			else | ||||
| 				PopNotification::count_lines(); | ||||
| 		} | ||||
| 		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; | ||||
| 		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; | ||||
| 		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; | ||||
| 		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; | ||||
| 		void       on_cancel_button(); | ||||
| 		int		   get_duration() override; | ||||
| 		std::function<void()>	m_cancel_callback; | ||||
| 		SlicingProgressState	m_sp_state { SlicingProgressState::SP_PROGRESS }; | ||||
| 		bool				    m_has_print_info { false }; | ||||
| 		std::string             m_print_info; | ||||
| 		bool                    m_sidebar_collapsed { false }; | ||||
| 		bool					m_is_fff { true }; | ||||
| 		// if true, it is possible show export hyperlink in state SP_PROGRESS
 | ||||
| 		bool                    m_export_possible { false }; | ||||
| 	}; | ||||
| 
 | ||||
| 	class ProgressIndicatorNotification : public ProgressBarNotification | ||||
| 	{ | ||||
| 	public: | ||||
| 		enum class ProgressIndicatorState | ||||
| 		{ | ||||
| 			PIS_HIDDEN, // hidden
 | ||||
| 			PIS_PROGRESS_REQUEST, // progress was updated, request render on next update_state() call
 | ||||
| 			PIS_PROGRESS_UPDATED, // render was requested
 | ||||
| 			PIS_COMPLETED // both completed and canceled state. fades out into PIS_NO_SLICING
 | ||||
| 		}; | ||||
| 		ProgressIndicatorNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler)  | ||||
| 		: ProgressBarNotification(n, id_provider, evt_handler)  | ||||
| 		{ | ||||
| 			m_render_percentage = true; | ||||
| 		} | ||||
| 		// ProgressIndicator 
 | ||||
| 		void set_range(int range) { m_range = range; } | ||||
| 		void set_cancel_callback(CancelFn callback) { m_cancel_callback = callback; } | ||||
| 		void set_progress(int pr) { set_percentage((float)pr / (float)m_range); } | ||||
| 		void set_status_text(const char*); // utf8 char array
 | ||||
| 		int  get_range() const { return m_range; } | ||||
| 		// ProgressBarNotification
 | ||||
| 		void init() override; | ||||
| 		void set_percentage(float percent) override; | ||||
| 		bool update_state(bool paused, const int64_t delta) override; | ||||
| 		// Own
 | ||||
| 	protected: | ||||
| 		int						m_range { 100 }; | ||||
| 		CancelFn				m_cancel_callback { nullptr }; | ||||
| 		ProgressIndicatorState  m_progress_state { ProgressIndicatorState::PIS_HIDDEN }; | ||||
| 
 | ||||
| 		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; | ||||
| 		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; | ||||
| 		void        on_cancel_button() { if (m_cancel_callback) m_cancel_callback(); } | ||||
| 	}; | ||||
| 
 | ||||
| 	class ExportFinishedNotification : public PopNotification | ||||
|  | @ -499,7 +619,7 @@ private: | |||
| 		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; | ||||
| 		void         render_eject_button(ImGuiWrapper& imgui, | ||||
| 		void render_eject_button(ImGuiWrapper& imgui, | ||||
| 			                             const float win_size_x, const float win_size_y, | ||||
| 			                             const float win_pos_x, const float win_pos_y); | ||||
| 		void render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) override | ||||
|  | @ -562,13 +682,15 @@ private: | |||
| 	// If there is some error notification active, then the "Export G-code" notification after the slicing is finished is suppressed.
 | ||||
|     bool has_slicing_error_notification(); | ||||
|      | ||||
| 	// set by init(), until false notifications are only added not updated and frame is not requested after push
 | ||||
| 	bool m_initialized{ false }; | ||||
| 	// Target for wxWidgets events sent by clicking on the hyperlink available at some notifications.
 | ||||
| 	wxEvtHandler*                m_evt_handler; | ||||
| 	// Cache of IDs to identify and reuse ImGUI windows.
 | ||||
| 	NotificationIDProvider 		 m_id_provider; | ||||
| 	std::deque<std::unique_ptr<PopNotification>> m_pop_notifications; | ||||
| 	// delayed waiting notifications, first is remaining time
 | ||||
| 	std::deque<DelayedNotification> m_waiting_notifications; | ||||
| 	std::vector<DelayedNotification> m_waiting_notifications; | ||||
| 	//timestamps used for slicing finished - notification could be gone so it needs to be stored here
 | ||||
| 	std::unordered_set<int>      m_used_timestamps; | ||||
| 	// True if G-code preview is active. False if the Plater is active.
 | ||||
|  |  | |||
|  | @ -1208,6 +1208,8 @@ void Sidebar::update_sliced_info_sizer() | |||
|             wxString t_est = std::isnan(ps.estimated_print_time) ? "N/A" : get_time_dhms(float(ps.estimated_print_time)); | ||||
|             p->sliced_info->SetTextAndShow(siEstimatedTime, t_est, _L("Estimated printing time") + ":"); | ||||
| 
 | ||||
|             p->plater->get_notification_manager()->set_slicing_complete_print_time(_utf8("Estimated printing time: ") + boost::nowide::narrow(t_est), p->plater->is_sidebar_collapsed()); | ||||
| 
 | ||||
|             // Hide non-SLA sliced info parameters
 | ||||
|             p->sliced_info->SetTextAndShow(siFilament_m, "N/A"); | ||||
|             p->sliced_info->SetTextAndShow(siFilament_mm3, "N/A"); | ||||
|  | @ -1296,10 +1298,7 @@ void Sidebar::update_sliced_info_sizer() | |||
|                     new_label += format_wxstr("\n   - %1%", _L("normal mode")); | ||||
|                     info_text += format_wxstr("\n%1%", short_time(ps.estimated_normal_print_time)); | ||||
| 
 | ||||
|                     // uncomment next line to not disappear slicing finished notif when colapsing sidebar before time estimate
 | ||||
|                     //if (p->plater->is_sidebar_collapsed())
 | ||||
|                     p->plater->get_notification_manager()->set_slicing_complete_large(p->plater->is_sidebar_collapsed()); | ||||
|                     p->plater->get_notification_manager()->set_slicing_complete_print_time("Estimated printing time: " + ps.estimated_normal_print_time); | ||||
|                     p->plater->get_notification_manager()->set_slicing_complete_print_time(_utf8("Estimated printing time: ") + ps.estimated_normal_print_time, p->plater->is_sidebar_collapsed()); | ||||
| 
 | ||||
|                 } | ||||
|                 if (ps.estimated_silent_print_time != "N/A") { | ||||
|  | @ -1502,7 +1501,7 @@ struct Plater::priv | |||
|     GLToolbar view_toolbar; | ||||
|     GLToolbar collapse_toolbar; | ||||
|     Preview *preview; | ||||
|     NotificationManager* notification_manager { nullptr }; | ||||
|     std::shared_ptr<NotificationManager> notification_manager; | ||||
| 
 | ||||
|     ProjectDirtyStateManager dirty_state; | ||||
| 
 | ||||
|  | @ -1523,10 +1522,10 @@ struct Plater::priv | |||
|     public: | ||||
|         Jobs(priv *_m) : m(_m) | ||||
|         { | ||||
|             m_arrange_id = add_job(std::make_unique<ArrangeJob>(m->statusbar(), m->q)); | ||||
|             m_fill_bed_id = add_job(std::make_unique<FillBedJob>(m->statusbar(), m->q)); | ||||
|             m_rotoptimize_id = add_job(std::make_unique<RotoptimizeJob>(m->statusbar(), m->q)); | ||||
|             m_sla_import_id = add_job(std::make_unique<SLAImportJob>(m->statusbar(), m->q)); | ||||
|             m_arrange_id = add_job(std::make_unique<ArrangeJob>(m->notification_manager, m->q)); | ||||
|             m_fill_bed_id = add_job(std::make_unique<FillBedJob>(m->notification_manager, m->q)); | ||||
|             m_rotoptimize_id = add_job(std::make_unique<RotoptimizeJob>(m->notification_manager, m->q)); | ||||
|             m_sla_import_id = add_job(std::make_unique<SLAImportJob>(m->notification_manager, m->q)); | ||||
|         } | ||||
|          | ||||
|         void arrange() | ||||
|  | @ -1637,7 +1636,7 @@ struct Plater::priv | |||
|     void apply_free_camera_correction(bool apply = true); | ||||
|     void update_ui_from_settings(); | ||||
|     void update_main_toolbar_tooltips(); | ||||
|     std::shared_ptr<ProgressStatusBar> statusbar(); | ||||
| //   std::shared_ptr<ProgressStatusBar> statusbar();
 | ||||
|     std::string get_config(const std::string &key) const; | ||||
|     BoundingBoxf bed_shape_bb() const; | ||||
|     BoundingBox scaled_bed_shape_bb() const; | ||||
|  | @ -1788,6 +1787,8 @@ struct Plater::priv | |||
|     // extension should contain the leading dot, i.e.: ".3mf"
 | ||||
|     wxString get_project_filename(const wxString& extension = wxEmptyString) const; | ||||
|     void set_project_filename(const wxString& filename); | ||||
|     // Call after plater and Canvas#D is initialized
 | ||||
|     void init_notification_manager(); | ||||
| 
 | ||||
|     // Caching last value of show_action_buttons parameter for show_action_buttons(), so that a callback which does not know this state will not override it.
 | ||||
|     mutable bool    			ready_to_slice = { false }; | ||||
|  | @ -1797,6 +1798,7 @@ struct Plater::priv | |||
|     std::string                 last_output_dir_path; | ||||
|     bool                        inside_snapshot_capture() { return m_prevent_snapshots != 0; } | ||||
| 	bool                        process_completed_with_error { false }; | ||||
|     | ||||
| private: | ||||
|     bool layers_height_allowed() const; | ||||
| 
 | ||||
|  | @ -1845,6 +1847,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | |||
|         "support_material_contact_distance", "support_material_bottom_contact_distance", "raft_layers" | ||||
|         })) | ||||
|     , sidebar(new Sidebar(q)) | ||||
|     , notification_manager(std::make_shared<NotificationManager>(q)) | ||||
|     , m_ui_jobs(this) | ||||
|     , delayed_scene_refresh(false) | ||||
|     , view_toolbar(GLToolbar::Radio, "View") | ||||
|  | @ -2012,7 +2015,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | |||
|         }); | ||||
| #endif /* _WIN32 */ | ||||
| 
 | ||||
| 	notification_manager = new NotificationManager(this->q); | ||||
| 	//notification_manager = new NotificationManager(this->q);
 | ||||
| 
 | ||||
|     if (wxGetApp().is_editor()) { | ||||
|         this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); }); | ||||
|         this->q->Bind(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, [this](ExportGcodeNotificationClickedEvent&) { this->q->export_gcode(true); }); | ||||
|  | @ -2022,12 +2026,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | |||
| 			    this->show_action_buttons(this->ready_to_slice); | ||||
|                 notification_manager->close_notification_of_type(NotificationType::ExportFinished); | ||||
|                 notification_manager->push_notification(NotificationType::CustomNotification, | ||||
|                                                         NotificationManager::NotificationLevel::RegularNotification, | ||||
|                                                         NotificationManager::NotificationLevel::RegularNotificationLevel, | ||||
|                                                         format(_L("Successfully unmounted. The device %s(%s) can now be safely removed from the computer."), evt.data.first.name, evt.data.first.path) | ||||
|                     ); | ||||
|             } else { | ||||
|                 notification_manager->push_notification(NotificationType::CustomNotification, | ||||
|                                                         NotificationManager::NotificationLevel::ErrorNotification, | ||||
|                                                         NotificationManager::NotificationLevel::ErrorNotificationLevel, | ||||
|                                                         format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path) | ||||
|                     ); | ||||
|             } | ||||
|  | @ -2074,8 +2078,7 @@ Plater::priv::~priv() | |||
| { | ||||
|     if (config != nullptr) | ||||
|         delete config; | ||||
|     if (notification_manager != nullptr) | ||||
|         delete notification_manager; | ||||
|     notification_manager->deactivate_loaded_hints(); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::update(unsigned int flags) | ||||
|  | @ -2150,6 +2153,8 @@ void Plater::priv::collapse_sidebar(bool collapse) | |||
|     new_tooltip += " [Shift+Tab]"; | ||||
|     int id = collapse_toolbar.get_item_id("collapse_sidebar"); | ||||
|     collapse_toolbar.set_tooltip(id, new_tooltip); | ||||
| 
 | ||||
|     notification_manager->set_sidebar_collapsed(collapse); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -2177,10 +2182,11 @@ void Plater::priv::update_main_toolbar_tooltips() | |||
|     view3D->get_canvas3d()->update_tooltip_for_settings_item_in_main_toolbar(); | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<ProgressStatusBar> Plater::priv::statusbar() | ||||
| { | ||||
|     return main_frame->m_statusbar; | ||||
| } | ||||
| //std::shared_ptr<ProgressStatusBar> Plater::priv::statusbar()
 | ||||
| //{
 | ||||
| //      return nullptr;
 | ||||
| //    return main_frame->m_statusbar;
 | ||||
| //}
 | ||||
| 
 | ||||
| std::string Plater::priv::get_config(const std::string &key) const | ||||
| { | ||||
|  | @ -2325,7 +2331,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_ | |||
|                                 for (std::string& name : names) | ||||
|                                     notif_text += "\n - " + name; | ||||
|                                 notification_manager->push_notification(NotificationType::CustomNotification, | ||||
|                                     NotificationManager::NotificationLevel::RegularNotification, notif_text); | ||||
|                                     NotificationManager::NotificationLevel::RegularNotificationLevel, notif_text); | ||||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|  | @ -2467,7 +2473,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_ | |||
|     if (load_model) { | ||||
|         wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().make_preferred().string()); | ||||
|         // XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames...
 | ||||
|         statusbar()->set_status_text(_L("Loaded")); | ||||
| //        statusbar()->set_status_text(_L("Loaded"));
 | ||||
|     } | ||||
| 
 | ||||
|     // automatic selection of added objects
 | ||||
|  | @ -2880,7 +2886,7 @@ void Plater::priv::split_object() | |||
|         // If we splited object which is contain some parts/modifiers then all non-solid parts (modifiers) were deleted
 | ||||
|         if (current_model_object->volumes.size() > 1 && current_model_object->volumes.size() != new_objects.size()) | ||||
|             notification_manager->push_notification(NotificationType::CustomNotification, | ||||
|                 NotificationManager::NotificationLevel::RegularNotification, | ||||
|                 NotificationManager::NotificationLevel::RegularNotificationLevel, | ||||
|                 _u8L("All non-solid parts (modifiers) were deleted")); | ||||
| 
 | ||||
|         Plater::TakeSnapshot snapshot(q, _L("Split to Objects")); | ||||
|  | @ -2956,7 +2962,7 @@ void Plater::priv::process_validation_warning(const std::string& warning) const | |||
| 
 | ||||
|         notification_manager->push_notification( | ||||
|             NotificationType::ValidateWarning, | ||||
|             NotificationManager::NotificationLevel::WarningNotification, | ||||
|             NotificationManager::NotificationLevel::WarningNotificationLevel, | ||||
|             _u8L("WARNING:") + "\n" + text, hypertext, action_fn | ||||
|         ); | ||||
|     } | ||||
|  | @ -3002,6 +3008,8 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool | |||
|         // In SLA mode, we need to reload the 3D scene every time to show the support structures.
 | ||||
|         if (printer_technology == ptSLA || (printer_technology == ptFFF && config->opt_bool("wipe_tower"))) | ||||
|             return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE; | ||||
| 
 | ||||
|         notification_manager->set_slicing_progress_hidden(); | ||||
|     } | ||||
| 
 | ||||
|     if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! background_process.empty()) { | ||||
|  | @ -3074,9 +3082,9 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool | |||
|     else | ||||
|     { | ||||
|         // Background data is valid.
 | ||||
|         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 )
 | ||||
| //            this->statusbar()->set_status_text(_L("Ready to slice"));
 | ||||
| 
 | ||||
|         sidebar->set_btn_label(ActionButtonType::abExport, _(label_btn_export)); | ||||
|         sidebar->set_btn_label(ActionButtonType::abSendGCode, _(label_btn_send)); | ||||
|  | @ -3113,10 +3121,10 @@ bool Plater::priv::restart_background_process(unsigned int state) | |||
|            (state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ) ) { | ||||
|         // The print is valid and it can be started.
 | ||||
|         if (this->background_process.start()) { | ||||
|             this->statusbar()->set_cancel_callback([this]() { | ||||
|                 this->statusbar()->set_status_text(_L("Cancelling")); | ||||
|                 this->background_process.stop(); | ||||
|             }); | ||||
| //            this->statusbar()->set_cancel_callback([this]() {
 | ||||
| //                this->statusbar()->set_status_text(_L("Cancelling"));
 | ||||
| //                this->background_process.stop();
 | ||||
| //            });
 | ||||
| 			if (!show_warning_dialog) | ||||
| 				on_slicing_began(); | ||||
|             return true; | ||||
|  | @ -3753,9 +3761,9 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) | |||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         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);
 | ||||
| //        this->statusbar()->set_progress(evt.status.percent);
 | ||||
| //        this->statusbar()->set_status_text(_(evt.status.text) + wxString::FromUTF8("…"));
 | ||||
|         notification_manager->set_slicing_progress_percentage(evt.status.text, (float)evt.status.percent / 100.0f); | ||||
|     } | ||||
|     if (evt.status.flags & (PrintBase::SlicingStatus::RELOAD_SCENE | PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS)) { | ||||
|         switch (this->printer_technology) { | ||||
|  | @ -3806,7 +3814,6 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) | |||
| 
 | ||||
| void Plater::priv::on_slicing_completed(wxCommandEvent & evt) | ||||
| { | ||||
|     notification_manager->push_slicing_complete_notification(evt.GetInt(), is_sidebar_collapsed()); | ||||
|     switch (this->printer_technology) { | ||||
|     case ptFFF: | ||||
|         this->update_fff_scene(); | ||||
|  | @ -3829,8 +3836,8 @@ void Plater::priv::on_export_began(wxCommandEvent& evt) | |||
| void Plater::priv::on_slicing_began() | ||||
| { | ||||
| 	clear_warnings(); | ||||
| 	notification_manager->close_notification_of_type(NotificationType::SlicingComplete); | ||||
|     notification_manager->close_notification_of_type(NotificationType::SignDetected); | ||||
|     notification_manager->close_notification_of_type(NotificationType::ExportFinished); | ||||
| } | ||||
| void Plater::priv::add_warning(const Slic3r::PrintStateBase::Warning& warning, size_t oid) | ||||
| { | ||||
|  | @ -3895,8 +3902,9 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt) | |||
|     // At this point of time the thread should be either finished or canceled,
 | ||||
|     // so the following call just confirms, that the produced data were consumed.
 | ||||
|     this->background_process.stop(); | ||||
|     this->statusbar()->reset_cancel_callback(); | ||||
|     this->statusbar()->stop_busy(); | ||||
| //    this->statusbar()->reset_cancel_callback();
 | ||||
| //    this->statusbar()->stop_busy();
 | ||||
|     notification_manager->set_slicing_progress_export_possible(); | ||||
| 
 | ||||
|     // Reset the "export G-code path" name, so that the automatic background processing will be enabled again.
 | ||||
|     this->background_process.reset_export(); | ||||
|  | @ -3913,7 +3921,7 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt) | |||
|                 show_error(q, message.first, message.second); | ||||
|         } else | ||||
|             notification_manager->push_slicing_error_notification(message.first); | ||||
|         this->statusbar()->set_status_text(from_u8(message.first)); | ||||
| //        this->statusbar()->set_status_text(from_u8(message.first));
 | ||||
|         if (evt.invalidate_plater()) | ||||
|         { | ||||
|             const wxString invalid_str = _L("Invalid data"); | ||||
|  | @ -3923,8 +3931,10 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt) | |||
|         } | ||||
|         has_error = true; | ||||
|     } | ||||
|     if (evt.cancelled()) | ||||
|         this->statusbar()->set_status_text(_L("Cancelled")); | ||||
|     if (evt.cancelled()) { | ||||
| //        this->statusbar()->set_status_text(_L("Cancelled"));
 | ||||
|         this->notification_manager->set_slicing_progress_percentage(_utf8("Slicing Cancelled."), -1); | ||||
|     } | ||||
| 
 | ||||
|     this->sidebar->show_sliced_info_sizer(evt.success()); | ||||
| 
 | ||||
|  | @ -4128,6 +4138,20 @@ void Plater::priv::set_project_filename(const wxString& filename) | |||
|         wxGetApp().mainframe->add_to_recent_projects(filename); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::init_notification_manager() | ||||
| { | ||||
|     if (!notification_manager) | ||||
|         return; | ||||
|     notification_manager->init(); | ||||
| 
 | ||||
|     auto cancel_callback = [this]() { | ||||
|         this->background_process.stop(); | ||||
|     }; | ||||
|     notification_manager->init_slicing_progress_notification(cancel_callback); | ||||
|     notification_manager->set_fff(printer_technology == ptFFF); | ||||
|     notification_manager->init_progress_indicator(); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::set_current_canvas_as_dirty() | ||||
| { | ||||
|     if (current_panel == view3D) | ||||
|  | @ -5566,7 +5590,7 @@ void Plater::export_stl(bool extended, bool selection_only) | |||
|     } | ||||
| 
 | ||||
|     Slic3r::store_stl(path_u8.c_str(), &mesh, true); | ||||
|     p->statusbar()->set_status_text(format_wxstr(_L("STL file exported to %s"), path)); | ||||
| //    p->statusbar()->set_status_text(format_wxstr(_L("STL file exported to %s"), path));
 | ||||
| } | ||||
| 
 | ||||
| void Plater::export_amf() | ||||
|  | @ -5583,10 +5607,10 @@ void Plater::export_amf() | |||
|     bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1"; | ||||
|     if (Slic3r::store_amf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames)) { | ||||
|         // Success
 | ||||
|         p->statusbar()->set_status_text(format_wxstr(_L("AMF file exported to %s"), path)); | ||||
| //        p->statusbar()->set_status_text(format_wxstr(_L("AMF file exported to %s"), path));
 | ||||
|     } else { | ||||
|         // Failure
 | ||||
|         p->statusbar()->set_status_text(format_wxstr(_L("Error exporting AMF file %s"), path)); | ||||
| //        p->statusbar()->set_status_text(format_wxstr(_L("Error exporting AMF file %s"), path));
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -5625,12 +5649,12 @@ bool Plater::export_3mf(const boost::filesystem::path& output_path) | |||
|     bool ret = Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data); | ||||
|     if (ret) { | ||||
|         // Success
 | ||||
|         p->statusbar()->set_status_text(format_wxstr(_L("3MF file exported to %s"), path)); | ||||
| //        p->statusbar()->set_status_text(format_wxstr(_L("3MF file exported to %s"), path));
 | ||||
|         p->set_project_filename(path); | ||||
|     } | ||||
|     else { | ||||
|         // Failure
 | ||||
|         p->statusbar()->set_status_text(format_wxstr(_L("Error exporting 3MF file %s"), path)); | ||||
| //        p->statusbar()->set_status_text(format_wxstr(_L("Error exporting 3MF file %s"), path));
 | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | @ -6204,6 +6228,8 @@ 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); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
|  | @ -6224,7 +6250,7 @@ void Plater::clear_before_change_mesh(int obj_idx) | |||
|         // snapshot_time is captured by copy so the lambda knows where to undo/redo to.
 | ||||
|         get_notification_manager()->push_notification( | ||||
|                     NotificationType::CustomSupportsAndSeamRemovedAfterRepair, | ||||
|                     NotificationManager::NotificationLevel::RegularNotification, | ||||
|                     NotificationManager::NotificationLevel::RegularNotificationLevel, | ||||
|                     _u8L("Custom supports, seams and multimaterial painting were " | ||||
|                          "removed after repairing the mesh.")); | ||||
| //                    _u8L("Undo the repair"),
 | ||||
|  | @ -6237,7 +6263,7 @@ void Plater::clear_before_change_mesh(int obj_idx) | |||
| //                        else
 | ||||
| //                            notification_manager->push_notification(
 | ||||
| //                                NotificationType::CustomSupportsAndSeamRemovedAfterRepair,
 | ||||
| //                                NotificationManager::NotificationLevel::RegularNotification,
 | ||||
| //                                NotificationManager::NotificationLevel::RegularNotificationLevel,
 | ||||
| //                                _u8L("Cannot undo to before the mesh repair!"));
 | ||||
| //                        return true;
 | ||||
| //                    });
 | ||||
|  | @ -6503,14 +6529,14 @@ Mouse3DController& Plater::get_mouse3d_controller() | |||
|     return p->mouse3d_controller; | ||||
| } | ||||
| 
 | ||||
| const NotificationManager* Plater::get_notification_manager() const | ||||
| std::shared_ptr<NotificationManager> Plater::get_notification_manager() | ||||
| { | ||||
| 	return p->notification_manager; | ||||
| } | ||||
| 
 | ||||
| NotificationManager* Plater::get_notification_manager() | ||||
| void Plater::init_notification_manager() | ||||
| { | ||||
| 	return p->notification_manager; | ||||
|     p->init_notification_manager(); | ||||
| } | ||||
| 
 | ||||
| bool Plater::can_delete() const { return p->can_delete(); } | ||||
|  |  | |||
|  | @ -359,11 +359,11 @@ public: | |||
| 	void set_bed_shape() const; | ||||
|     void set_bed_shape(const Pointfs& shape, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false) const; | ||||
| 
 | ||||
| 	const NotificationManager* get_notification_manager() const; | ||||
| 	NotificationManager* get_notification_manager(); | ||||
| 	std::shared_ptr<NotificationManager> get_notification_manager(); | ||||
|     void init_notification_manager(); | ||||
| 
 | ||||
|     void bring_instance_forward(); | ||||
| 
 | ||||
|      | ||||
|     // ROII wrapper for suppressing the Undo / Redo snapshot to be taken.
 | ||||
| 	class SuppressSnapshots | ||||
| 	{ | ||||
|  |  | |||
|  | @ -194,3 +194,4 @@ void ProgressStatusBar::hide_cancel_button() | |||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ namespace Slic3r { | |||
|  * of the Slicer main window. It consists of a message area to the left and a | ||||
|  * progress indication area to the right with an optional cancel button. | ||||
|  */ | ||||
|   | ||||
| class ProgressStatusBar : public ProgressIndicator | ||||
| { | ||||
|     wxStatusBar *self;      // we cheat! It should be the base class but: perl!
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 David Kocik
						David Kocik