diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 9b01cb2fc1..219faf42ef 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1369,20 +1369,17 @@ void NotificationManager::push_hint_notification(bool open_next) } NotificationData data{ NotificationType::DidYouKnowHint, NotificationLevel::RegularNotification, 300, "" }; - // from user + // from user - open now if (!open_next) { push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 0); - // delete from delayed list - for (auto it = m_waiting_notifications.begin(); it != m_waiting_notifications.end();) { - if ((*it).notification->get_type() == NotificationType::DidYouKnowHint) { - it = m_waiting_notifications.erase(it); - } else { - ++it; - } - } - // at startup + stop_delayed_notifications_of_type(NotificationType::DidYouKnowHint); + // 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 { - push_delayed_notification(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 500, 30000); + auto condition = [this]() { + return this->get_notification_count() == 0; + }; + push_delayed_notification(std::make_unique(data, m_id_provider, m_evt_handler, open_next), condition, 500, 30000); } } @@ -1439,13 +1436,25 @@ bool NotificationManager::push_notification_data(std::unique_ptr notification, int64_t initial_delay, int64_t delay_interval) +void NotificationManager::push_delayed_notification(std::unique_ptr notification, std::function condition_callback, int64_t initial_delay, int64_t delay_interval) { - if (initial_delay == 0 && m_pop_notifications.empty()) { - push_notification_data(std::move(notification), 0); - } else { - m_waiting_notifications.emplace_back(std::move(notification), initial_delay, delay_interval); - wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(initial_delay); + if (initial_delay == 0 && condition_callback()) { + if( push_notification_data(std::move(notification), 0)) + return; + } + m_waiting_notifications.emplace_back(std::move(notification), condition_callback, initial_delay == 0 ? delay_interval : initial_delay, delay_interval); + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(initial_delay == 0 ? delay_interval : initial_delay); +} + +void NotificationManager::stop_delayed_notifications_of_type(const NotificationType type) +{ + for (auto it = m_waiting_notifications.begin(); it != m_waiting_notifications.end();) { + if ((*it).notification->get_type() == type) { + it = m_waiting_notifications.erase(it); + } + else { + ++it; + } } } @@ -1507,14 +1516,15 @@ bool NotificationManager::update_notifications(GLCanvas3D& canvas) if ((*it).remaining_time > 0) (*it).remaining_time -= time_since_render; if ((*it).remaining_time <= 0) { - if (m_pop_notifications.empty()) { // push notification, erase it from waiting list (frame is scheduled by push) + if ((*it).condition_callback()) { // push notification, erase it from waiting list (frame is scheduled by push) (*it).notification->reset_timer(); - push_notification_data(std::move((*it).notification), 0); - it = m_waiting_notifications.erase(it); - continue; - } else { // not possible to push, delay for delay_interval - (*it).remaining_time = (*it).delay_interval; + if (push_notification_data(std::move((*it).notification), 0)) { + it = m_waiting_notifications.erase(it); + continue; + } } + // not possible to push, delay for delay_interval + (*it).remaining_time = (*it).delay_interval; } next_render = std::min(next_render, (*it).remaining_time); ++it; @@ -1612,6 +1622,15 @@ void NotificationManager::device_ejected() notification->close(); } } +size_t NotificationManager::get_notification_count() const +{ + size_t ret = 0; + for (const std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_state() != PopNotification::EState::Hidden) + ret++; + } + return ret; +} }//namespace GUI }//namespace Slic3r diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index d2a2eb5a78..4aba35f4cb 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -190,6 +190,8 @@ public: void set_move_from_overlay(bool move) { m_move_from_overlay = move; } // perform update_state on each notification and ask for more frames if needed, return true for render needed bool update_notifications(GLCanvas3D& canvas); + // returns number of all notifications shown + size_t get_notification_count() const; private: // duration 0 means not disapearing struct NotificationData { @@ -521,10 +523,13 @@ private: struct DelayedNotification { std::unique_ptr notification; + std::function condition_callback; int64_t remaining_time; int64_t delay_interval; - DelayedNotification(std::unique_ptr n, int64_t r, int64_t d) + + DelayedNotification(std::unique_ptr n, std::function cb, int64_t r, int64_t d) : notification(std::move(n)) + , condition_callback(cb) , remaining_time(r) , delay_interval(d) {} @@ -534,8 +539,14 @@ private: //can be used to create custom notification bool push_notification_data(const NotificationData& notification_data, int timestamp); bool push_notification_data(std::unique_ptr notification, int timestamp); - // Delayed notifications goes first to the m_waiting_notifications vector and only after remaining time is <= 0 and m_pop_notifications are empty, notification is regular pushed. Otherwise another delay interval waiting. Timestamp is 0. - void push_delayed_notification(std::unique_ptr notification, int64_t initial_delay, int64_t delay_interval); + // Delayed notifications goes first to the m_waiting_notifications vector and only after remaining time is <= 0 + // and condition callback is success, notification is regular pushed from update function. + // Otherwise another delay interval waiting. Timestamp is 0. + // Note that notification object is constructed when being added to the waiting list, but there are no updates called on it and its timer is reset at regular push. + // Also note that no control of same notification is done during push_delayed_notification but if waiting notif fails to push, it continues waiting. + void push_delayed_notification(std::unique_ptr notification, std::function condition_callback, int64_t initial_delay, int64_t delay_interval); + // Removes all notifications of type from m_waiting_notifications + void stop_delayed_notifications_of_type(const NotificationType type); //finds older notification of same type and moves it to the end of queue. returns true if found bool activate_existing(const NotificationManager::PopNotification* notification); // Put the more important notifications to the bottom of the list.