2022-07-15 15:37:19 +00:00
# include "NotificationManager.hpp"
2022-09-15 06:51:29 +00:00
# include "HintNotification.hpp"
2022-07-15 15:37:19 +00:00
# include "GUI.hpp"
# include "ImGuiWrapper.hpp"
# include "wxExtensions.hpp"
# include "ObjectDataViewModel.hpp"
# include "GUI_ObjectList.hpp"
# include "ParamsPanel.hpp"
# include "libslic3r/Config.hpp"
# include "format.hpp"
# include <boost/algorithm/string.hpp>
# include <boost/log/trivial.hpp>
# include <boost/bind/bind.hpp>
# include <boost/nowide/convert.hpp>
# include <iostream>
# include <wx/glcanvas.h>
# include "GUI_App.hpp"
2022-08-09 09:04:16 +00:00
# ifndef IMGUI_DEFINE_MATH_OPERATORS
# define IMGUI_DEFINE_MATH_OPERATORS
# endif
# include <imgui/imgui_internal.h>
2022-07-15 15:37:19 +00:00
static constexpr float GAP_WIDTH = 10.0f ;
static constexpr float SPACE_RIGHT_PANEL = 10.0f ;
static constexpr float FADING_OUT_DURATION = 2.0f ;
// Time in Miliseconds after next render when fading out is requested
static constexpr int FADING_OUT_TIMEOUT = 100 ;
namespace Slic3r {
namespace GUI {
2022-09-16 03:31:12 +00:00
wxDEFINE_EVENT ( EVT_EJECT_DRIVE_NOTIFICAION_CLICKED , EjectDriveNotificationClickedEvent ) ;
2022-07-15 15:37:19 +00:00
wxDEFINE_EVENT ( EVT_EXPORT_GCODE_NOTIFICAION_CLICKED , ExportGcodeNotificationClickedEvent ) ;
wxDEFINE_EVENT ( EVT_PRESET_UPDATE_AVAILABLE_CLICKED , PresetUpdateAvailableClickedEvent ) ;
namespace {
/* // not used?
ImFont * add_default_font ( float pixel_size )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
ImFontConfig config ;
config . SizePixels = pixel_size ;
config . OversampleH = config . OversampleV = 1 ;
config . PixelSnapH = true ;
ImFont * font = io . Fonts - > AddFontDefault ( & config ) ;
return font ;
}
*/
inline void push_style_color ( ImGuiCol idx , const ImVec4 & col , bool fading_out , float current_fade_opacity )
{
if ( fading_out )
ImGui : : PushStyleColor ( idx , ImVec4 ( col . x , col . y , col . z , col . w * current_fade_opacity ) ) ;
else
ImGui : : PushStyleColor ( idx , col ) ;
}
void open_folder ( const std : : string & path )
{
// Code taken from desktop_open_datadir_folder()
// Execute command to open a file explorer, platform dependent.
// FIXME: The const_casts aren't needed in wxWidgets 3.1, remove them when we upgrade.
# ifdef _WIN32
const wxString widepath = from_u8 ( path ) ;
const wchar_t * argv [ ] = { L " explorer " , widepath . GetData ( ) , nullptr } ;
: : wxExecute ( const_cast < wchar_t * * > ( argv ) , wxEXEC_ASYNC , nullptr ) ;
# elif __APPLE__
const char * argv [ ] = { " open " , path . data ( ) , nullptr } ;
: : wxExecute ( const_cast < char * * > ( argv ) , wxEXEC_ASYNC , nullptr ) ;
# else
const char * argv [ ] = { " xdg-open " , path . data ( ) , nullptr } ;
// Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars,
// because they may mess up the environment expected by the file manager.
// Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure.
if ( wxGetEnv ( " APPIMAGE " , nullptr ) ) {
// We're running from AppImage
wxEnvVariableHashMap env_vars ;
wxGetEnvMap ( & env_vars ) ;
env_vars . erase ( " APPIMAGE " ) ;
env_vars . erase ( " APPDIR " ) ;
env_vars . erase ( " LD_LIBRARY_PATH " ) ;
env_vars . erase ( " LD_PRELOAD " ) ;
env_vars . erase ( " UNION_PRELOAD " ) ;
wxExecuteEnv exec_env ;
exec_env . env = std : : move ( env_vars ) ;
wxString owd ;
if ( wxGetEnv ( " OWD " , & owd ) ) {
// This is the original work directory from which the AppImage image was run,
// set it as CWD for the child process:
exec_env . cwd = std : : move ( owd ) ;
}
: : wxExecute ( const_cast < char * * > ( argv ) , wxEXEC_ASYNC , nullptr , & exec_env ) ;
}
else {
// Looks like we're NOT running from AppImage, we'll make no changes to the environment.
: : wxExecute ( const_cast < char * * > ( argv ) , wxEXEC_ASYNC , nullptr , nullptr ) ;
}
# endif
}
}
# if 1
// Reuse ImGUI Windows.
int NotificationManager : : NotificationIDProvider : : allocate_id ( )
{
int id ;
if ( m_released_ids . empty ( ) )
id = + + m_next_id ;
else {
id = m_released_ids . back ( ) ;
m_released_ids . pop_back ( ) ;
}
return id ;
}
void NotificationManager : : NotificationIDProvider : : release_id ( int id )
{
m_released_ids . push_back ( id ) ;
}
# else
// Don't reuse ImGUI Windows, allocate a new ID every time.
int NotificationManager : : NotificationIDProvider : : allocate_id ( ) { return + + m_next_id ; }
void NotificationManager : : NotificationIDProvider : : release_id ( int ) { }
# endif
//------PopNotification--------
NotificationManager : : PopNotification : : PopNotification ( const NotificationData & n , NotificationIDProvider & id_provider , wxEvtHandler * evt_handler ) :
m_data ( n )
, m_id_provider ( id_provider )
, m_text1 ( n . text1 )
, m_hypertext ( n . hypertext )
, m_text2 ( n . text2 )
, m_evt_handler ( evt_handler )
, m_notification_start ( GLCanvas3D : : timestamp_now ( ) )
{
m_ErrorColor = ImVec4 ( 0.9 , 0.36 , 0.36 , 1 ) ;
m_WarnColor = ImVec4 ( 0.99 , 0.69 , 0.455 , 1 ) ;
m_NormalColor = ImVec4 ( 0.03 , 0.6 , 0.18 , 1 ) ;
m_CurrentColor = m_NormalColor ; //Default
m_WindowBkgColor = ImVec4 ( 1 , 1 , 1 , 1 ) ;
m_TextColor = ImVec4 ( .2f , .2f , .2f , 1.0f ) ;
m_HyperTextColor = ImVec4 ( 0.03 , 0.6 , 0.18 , 1 ) ;
2022-08-03 08:25:29 +00:00
m_WindowRadius = 4.0f * wxGetApp ( ) . plater ( ) - > get_current_canvas3D ( ) - > get_scale ( ) ;
2022-07-15 15:37:19 +00:00
}
void NotificationManager : : PopNotification : : use_bbl_theme ( )
{
ImGuiStyle & OldStyle = ImGui : : GetStyle ( ) ;
m_DefaultTheme . mWindowPadding = OldStyle . WindowPadding ;
m_DefaultTheme . mWindowBkg = OldStyle . Colors [ ImGuiCol_WindowBg ] ;
m_DefaultTheme . mBorderColor = OldStyle . Colors [ ImGuiCol_Border ] ;
m_DefaultTheme . mTextColor = OldStyle . Colors [ ImGuiCol_Text ] ;
m_DefaultTheme . mWindowRound = OldStyle . WindowRounding ;
OldStyle . WindowPadding = ImVec2 ( 0 , 0 ) ;
OldStyle . WindowRounding = m_WindowRadius ;
if ( m_data . level = = NotificationLevel : : ErrorNotificationLevel )
m_CurrentColor = m_ErrorColor ;
else if ( m_data . level = = NotificationLevel : : WarningNotificationLevel )
m_CurrentColor = m_WarnColor ;
else {
if ( m_data . use_warn_color )
m_CurrentColor = m_WarnColor ;
else
m_CurrentColor = m_NormalColor ;
}
//OldStyle.Colors[ImGuiCol_Border] = m_CurrentColor;
// OldStyle.Colors[ImGuiCol_WindowBg] = m_WindowBkgColor;
// OldStyle.Colors[ImGuiCol_Text] = m_TextColor;
push_style_color ( ImGuiCol_Border , m_CurrentColor , true , m_current_fade_opacity ) ;
push_style_color ( ImGuiCol_WindowBg , m_WindowBkgColor , true , m_current_fade_opacity ) ;
push_style_color ( ImGuiCol_Text , m_TextColor , true , m_current_fade_opacity ) ;
}
void NotificationManager : : PopNotification : : restore_default_theme ( )
{
ImGuiStyle & OldStyle = ImGui : : GetStyle ( ) ;
OldStyle . WindowPadding = m_DefaultTheme . mWindowPadding ;
OldStyle . WindowRounding = m_DefaultTheme . mWindowRound ;
ImGui : : PopStyleColor ( 3 ) ;
//OldStyle.Colors[ImGuiCol_WindowBg] = m_DefaultTheme.mWindowBkg;
// OldStyle.Colors[ImGuiCol_Text] = m_DefaultTheme.mTextColor;
// OldStyle.Colors[ImGuiCol_Border] = m_DefaultTheme.mBorderColor;
}
void NotificationManager : : PopNotification : : render ( GLCanvas3D & canvas , float initial_y , bool move_from_overlay , float overlay_width , float right_margin )
{
if ( m_state = = EState : : Unknown )
init ( ) ;
if ( m_state = = EState : : Hidden ) {
m_top_y = initial_y - GAP_WIDTH ;
return ;
}
if ( m_state = = EState : : ClosePending | | m_state = = EState : : Finished )
{
m_state = EState : : Finished ;
return ;
}
Size cnv_size = canvas . get_canvas_size ( ) ;
ImGuiWrapper & imgui = * wxGetApp ( ) . imgui ( ) ;
ImVec2 mouse_pos = ImGui : : GetMousePos ( ) ;
float right_gap = right_margin + ( move_from_overlay ? overlay_width + m_line_height * 5 : 0 ) ;
bool fading_pop = false ;
if ( m_line_height ! = ImGui : : CalcTextSize ( " A " ) . y )
init ( ) ;
set_next_window_size ( imgui ) ;
// top y of window
m_top_y = initial_y + m_window_height ;
ImVec2 win_pos ( 1.0f * ( float ) cnv_size . get_width ( ) - right_gap , 1.0f * ( float ) cnv_size . get_height ( ) - m_top_y ) ;
imgui . set_next_window_pos ( win_pos . x , win_pos . y , ImGuiCond_Always , 1.0f , 0.0f ) ;
imgui . set_next_window_size ( m_window_width , m_window_height , ImGuiCond_Always ) ;
// find if hovered FIXME: do it only in update state?
if ( m_state = = EState : : Hovered ) {
m_state = EState : : Unknown ;
init ( ) ;
}
if ( mouse_pos . x < win_pos . x & & mouse_pos . x > win_pos . x - m_window_width & & mouse_pos . y > win_pos . y & & mouse_pos . y < win_pos . y + m_window_height ) {
// Uncomment if imgui window focus is needed on hover. I cant find any case.
//ImGui::SetNextWindowFocus();
set_hovered ( ) ;
}
// color change based on fading out
if ( m_state = = EState : : FadingOut ) {
push_style_color ( ImGuiCol_WindowBg , ImGui : : GetStyleColorVec4 ( ImGuiCol_WindowBg ) , true , m_current_fade_opacity ) ;
push_style_color ( ImGuiCol_Text , ImGui : : GetStyleColorVec4 ( ImGuiCol_Text ) , true , m_current_fade_opacity ) ;
push_style_color ( ImGuiCol_ButtonHovered , ImGui : : GetStyleColorVec4 ( ImGuiCol_ButtonHovered ) , true , m_current_fade_opacity ) ;
fading_pop = true ;
}
bool bgrnd_color_pop = push_background_color ( ) ;
// name of window indentifies window - has to be unique string
if ( m_id = = 0 )
m_id = m_id_provider . allocate_id ( ) ;
std : : string name = " !!Ntfctn " + std : : to_string ( m_id ) ;
use_bbl_theme ( ) ;
if ( imgui . begin ( name , ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse ) ) {
ImVec2 win_size = ImGui : : GetWindowSize ( ) ;
bbl_render_left_sign ( imgui , win_size . x , win_size . y , win_pos . x , win_pos . y ) ;
render_left_sign ( imgui ) ;
render_text ( imgui , win_size . x , win_size . y , win_pos . x , win_pos . y ) ;
render_close_button ( imgui , win_size . x , win_size . y , win_pos . x , win_pos . y ) ;
m_minimize_b_visible = false ;
if ( m_multiline & & m_lines_count > 3 )
render_minimize_button ( imgui , win_pos . x , win_pos . y ) ;
}
imgui . end ( ) ;
restore_default_theme ( ) ;
if ( bgrnd_color_pop )
ImGui : : PopStyleColor ( ) ;
if ( fading_pop )
ImGui : : PopStyleColor ( 3 ) ;
}
bool NotificationManager : : PopNotification : : push_background_color ( )
{
if ( m_is_gray ) {
ImVec4 backcolor ( 0.7f , 0.7f , 0.7f , 0.5f ) ;
push_style_color ( ImGuiCol_WindowBg , backcolor , m_state = = EState : : FadingOut , m_current_fade_opacity ) ;
return true ;
}
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 : : WarningNotificationLevel ) {
ImVec4 backcolor = ImGui : : GetStyleColorVec4 ( ImGuiCol_WindowBg ) ;
backcolor . x + = 0.3f ;
backcolor . y + = 0.15f ;
push_style_color ( ImGuiCol_WindowBg , backcolor , m_state = = EState : : FadingOut , m_current_fade_opacity ) ;
return true ;
}
return false ;
}
void NotificationManager : : PopNotification : : count_spaces ( )
{
//determine line width
m_line_height = ImGui : : CalcTextSize ( " A " ) . y ;
m_left_indentation = m_line_height ;
//if (m_data.level == NotificationLevel::ErrorNotificationLevel
// || m_data.level == NotificationLevel::WarningNotificationLevel
// || m_data.level == NotificationLevel::PrintInfoNotificationLevel
// || m_data.level == NotificationLevel::PrintInfoShortNotificationLevel) {
// std::string text;
// 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;
//}
m_window_width_offset = m_left_indentation + m_line_height * 3.f ;
m_window_width = m_line_height * 25 ;
}
void NotificationManager : : PopNotification : : count_lines ( )
{
std : : string text = m_text1 ;
size_t last_end = 0 ;
m_lines_count = 0 ;
if ( text . empty ( ) )
return ;
m_endlines . clear ( ) ;
while ( last_end < text . length ( ) - 1 )
{
size_t next_hard_end = text . find_first_of ( ' \n ' , last_end ) ;
if ( next_hard_end ! = std : : string : : npos & & ImGui : : CalcTextSize ( text . substr ( last_end , next_hard_end - last_end ) . c_str ( ) ) . x < m_window_width - m_window_width_offset ) {
//next line is ended by '/n'
m_endlines . push_back ( next_hard_end ) ;
last_end = next_hard_end + 1 ;
}
else {
// find next suitable endline
if ( ImGui : : CalcTextSize ( text . substr ( last_end ) . c_str ( ) ) . x > = m_window_width - m_window_width_offset ) {
// more than one line till end
size_t next_space = text . find_first_of ( ' ' , last_end ) ;
if ( next_space > 0 & & next_space < text . length ( ) ) {
size_t next_space_candidate = text . find_first_of ( ' ' , next_space + 1 ) ;
while ( next_space_candidate > 0 & & ImGui : : CalcTextSize ( text . substr ( last_end , next_space_candidate - last_end ) . c_str ( ) ) . x < m_window_width - m_window_width_offset ) {
next_space = next_space_candidate ;
next_space_candidate = text . find_first_of ( ' ' , next_space + 1 ) ;
}
} else {
next_space = text . length ( ) ;
}
// when one word longer than line.
if ( ImGui : : CalcTextSize ( text . substr ( last_end , next_space - last_end ) . c_str ( ) ) . x > m_window_width - m_window_width_offset | |
ImGui : : CalcTextSize ( text . substr ( last_end , next_space - last_end ) . c_str ( ) ) . x < ( m_window_width - m_window_width_offset ) / 4 * 3
) {
//BBS
wxString wx_text = from_u8 ( text . substr ( last_end , text . length ( ) - last_end ) . c_str ( ) ) ;
float width_of_char = ImGui : : CalcTextSize ( " a " ) . x ;
int letter_count = ( int ) ( ( m_window_width - m_window_width_offset ) / width_of_char ) / 2 ; // give a predict value of char count
int output_count = 0 ;
while ( true ) {
if ( letter_count > = wx_text . size ( ) )
break ;
float used_space = ImGui : : CalcTextSize ( into_u8 ( wx_text . SubString ( 0 , letter_count ) ) . c_str ( ) ) . x ;
if ( used_space > m_window_width - m_window_width_offset )
break ;
letter_count + + ;
}
if ( letter_count > 0 ) {
output_count = into_u8 ( wx_text . SubString ( 0 , letter_count - 1 ) ) . size ( ) ;
}
m_endlines . push_back ( last_end + output_count ) ;
last_end + = output_count ;
} else {
m_endlines . push_back ( next_space ) ;
last_end = next_space + 1 ;
}
}
else {
m_endlines . push_back ( text . length ( ) ) ;
last_end = text . length ( ) ;
}
}
m_lines_count + + ;
}
// hypertext calculation
if ( ! m_hypertext . empty ( ) ) {
int prev_end = m_endlines . size ( ) > 1 ? m_endlines [ m_endlines . size ( ) - 2 ] : 0 ; // m_endlines.size() - 2 because we are fitting hypertext instead of last endline
if ( ImGui : : CalcTextSize ( ( escape_string_cstyle ( text . substr ( prev_end , last_end - prev_end ) ) + m_hypertext ) . c_str ( ) ) . x > m_window_width - m_window_width_offset ) {
m_endlines . push_back ( last_end ) ;
m_lines_count + + ;
}
}
// m_text_2 (text after hypertext) is not used for regular notifications right now.
// its caluculation is in HintNotification::count_lines()
}
void NotificationManager : : PopNotification : : init ( )
{
// Do not init closing notification
if ( is_finished ( ) )
return ;
count_spaces ( ) ;
count_lines ( ) ;
if ( m_lines_count = = 3 )
m_multiline = true ;
m_notification_start = GLCanvas3D : : timestamp_now ( ) ;
if ( m_state = = EState : : Unknown )
m_state = EState : : Shown ;
}
void NotificationManager : : PopNotification : : set_next_window_size ( ImGuiWrapper & imgui )
{
m_window_height = m_multiline ?
std : : max ( m_lines_count , ( size_t ) 2 ) * m_line_height :
2 * m_line_height ;
m_window_height + = 1 * m_line_height ; // top and bottom
}
void NotificationManager : : PopNotification : : render_text ( ImGuiWrapper & imgui , const float win_size_x , const float win_size_y , const float win_pos_x , const float win_pos_y )
{
float x_offset = m_left_indentation ;
int last_end = 0 ;
float starting_y = ( m_lines_count = = 2 ? win_size_y / 2 - m_line_height : ( m_lines_count = = 1 ? win_size_y / 2 - m_line_height / 2 : m_line_height / 2 ) ) ;
float shift_y = m_line_height ;
std : : string line ;
for ( size_t i = 0 ; i < ( m_multiline ? m_endlines . size ( ) : std : : min ( m_endlines . size ( ) , ( size_t ) 2 ) ) ; i + + ) {
assert ( m_endlines . size ( ) > i & & m_text1 . size ( ) > = m_endlines [ i ] ) ;
line . clear ( ) ;
ImGui : : SetCursorPosX ( x_offset ) ;
ImGui : : SetCursorPosY ( starting_y + i * shift_y ) ;
if ( m_endlines . size ( ) > i & & m_text1 . size ( ) > = m_endlines [ i ] ) {
if ( i = = 1 & & m_endlines . size ( ) > 2 & & ! m_multiline ) {
// second line with "more" hypertext
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 ) ) ;
while ( ImGui : : CalcTextSize ( line . c_str ( ) ) . x > m_window_width - m_window_width_offset - ImGui : : CalcTextSize ( ( " .. " + _u8L ( " More " ) ) . c_str ( ) ) . x ) {
line = line . substr ( 0 , line . length ( ) - 1 ) ;
}
line + = " .. " ;
}
else {
// regural line
line = m_text1 . substr ( last_end , m_endlines [ i ] - last_end ) ;
}
last_end = m_endlines [ i ] ;
if ( m_text1 . size ( ) > m_endlines [ i ] )
last_end + = ( m_text1 [ m_endlines [ i ] ] = = ' \n ' | | m_text1 [ m_endlines [ i ] ] = = ' ' ? 1 : 0 ) ;
imgui . text ( line . c_str ( ) ) ;
}
}
//hyperlink text
if ( ! m_multiline & & m_lines_count > 2 ) {
render_hypertext ( imgui , x_offset + ImGui : : CalcTextSize ( ( line + " " ) . c_str ( ) ) . x , starting_y + shift_y , _u8L ( " More " ) , true ) ;
}
else if ( ! m_hypertext . empty ( ) ) {
render_hypertext ( imgui , x_offset + ImGui : : CalcTextSize ( ( line + ( line . empty ( ) ? " " : " " ) ) . c_str ( ) ) . x , starting_y + ( m_endlines . size ( ) - 1 ) * shift_y , m_hypertext ) ;
}
// text2 (text after hypertext) is not rendered for regular notifications
// its rendering is in HintNotification::render_text
}
void NotificationManager : : PopNotification : : render_hypertext ( ImGuiWrapper & imgui , const float text_x , const float text_y , const std : : string text , bool more )
{
//invisible button
ImVec2 part_size = ImGui : : CalcTextSize ( text . c_str ( ) ) ;
ImGui : : SetCursorPosX ( text_x - 4 ) ;
ImGui : : SetCursorPosY ( text_y - 5 ) ;
ImGui : : PushStyleColor ( ImGuiCol_Button , ImVec4 ( .4f , .4f , .4f , 0.0f ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_ButtonHovered , ImVec4 ( .5f , .5f , .5f , 0.0f ) ) ;
ImGui : : PushStyleColor ( ImGuiCol_ButtonActive , ImVec4 ( .7f , .7f , .7f , 0.0f ) ) ;
if ( imgui . button ( " " , part_size . x + 6 , part_size . y + 10 ) )
{
if ( more )
{
m_multiline = true ;
set_next_window_size ( imgui ) ;
}
else if ( on_text_click ( ) ) {
close ( ) ;
}
}
ImGui : : PopStyleColor ( 3 ) ;
//hover color
ImVec4 HyperColor = m_HyperTextColor ;
if ( ImGui : : IsItemHovered ( ImGuiHoveredFlags_RectOnly ) )
HyperColor . y + = 0.1f ;
//text
push_style_color ( ImGuiCol_Text , HyperColor , m_state = = EState : : FadingOut , m_current_fade_opacity ) ;
ImGui : : SetCursorPosX ( text_x ) ;
ImGui : : SetCursorPosY ( text_y ) ;
imgui . text ( text . c_str ( ) ) ;
ImGui : : PopStyleColor ( ) ;
//underline
ImVec2 lineEnd = ImGui : : GetItemRectMax ( ) ;
lineEnd . y - = 2 ;
ImVec2 lineStart = lineEnd ;
lineStart . x = ImGui : : GetItemRectMin ( ) . x ;
ImGui : : GetWindowDrawList ( ) - > AddLine ( lineStart , lineEnd ,
IM_COL32 ( ( int ) ( HyperColor . x * 255 ) , ( int ) ( HyperColor . y * 255 ) , ( int ) ( HyperColor . z * 255 ) ,
( int ) ( HyperColor . w * 255.f * ( m_state = = EState : : FadingOut ? m_current_fade_opacity : 1.f ) ) ) ) ;
}
void NotificationManager : : PopNotification : : 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 )
{
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 : : CloseNotifButton ;
//button_text = ImGui::PreferencesButton;
//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))
if ( ImGui : : IsMouseHoveringRect ( ImVec2 ( win_pos . x - win_size . x / 10.f , win_pos . y ) , ImVec2 ( win_pos . x , win_pos . y + 2 * m_line_height + 10 ) , true ) )
{
button_text = ImGui : : CloseNotifHoverButton ;
}
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 ( m_minimize_b_visible )
ImGui : : SetCursorPosY ( 0 ) ;
else
ImGui : : SetCursorPosY ( win_size . y / 2 - button_size . y ) ;
if ( imgui . button ( button_text . c_str ( ) , button_size . x , button_size . y ) )
{
close ( ) ;
}
//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 ) ) )
{
close ( ) ;
}
ImGui : : PopStyleColor ( 5 ) ;
}
//void NotificationManager::PopNotification::render_multiline(ImGuiWrapper &imgui, const float win_pos_x, const float win_pos_y)
//{
// if (m_data.type == NotificationType::BBLObjectInfo)
// {
// set_Multiline(true);
// }
//}
void NotificationManager : : PopNotification : : bbl_render_left_sign ( ImGuiWrapper & imgui , const float win_size_x , const float win_size_y , const float win_pos_x , const float win_pos_y )
{
ImDrawList * draw_list = ImGui : : GetWindowDrawList ( ) ;
2022-08-09 09:04:16 +00:00
ImVec2 round_rect_pos = ImVec2 ( win_pos_x - win_size_x , win_pos_y ) ;
ImVec2 round_rect_size = ImVec2 ( m_WindowRadius * 2 , win_size_y ) ;
ImVec2 rect_pos = round_rect_pos + ImVec2 ( m_WindowRadius , 0 ) ;
ImVec2 rect_size = ImVec2 ( m_WindowRadius + 2 * wxGetApp ( ) . plater ( ) - > get_current_canvas3D ( ) - > get_scale ( ) , win_size_y ) ;
ImU32 clr = ImGui : : GetColorU32 ( ImVec4 ( m_CurrentColor . x , m_CurrentColor . y , m_CurrentColor . z , m_current_fade_opacity ) ) ;
draw_list - > AddRectFilled ( round_rect_pos , round_rect_pos + round_rect_size , clr , m_WindowRadius ) ;
draw_list - > AddRectFilled ( rect_pos , rect_pos + rect_size , clr , 0 ) ;
2022-07-15 15:37:19 +00:00
}
void NotificationManager : : PopNotification : : render_left_sign ( ImGuiWrapper & imgui )
{
//if (m_data.level == NotificationLevel::ErrorNotificationLevel || m_data.level == NotificationLevel::WarningNotificationLevel) {
// std::string text;
// 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());
//} else if (m_data.level == NotificationLevel::PrintInfoNotificationLevel || m_data.level == NotificationLevel::PrintInfoShortNotificationLevel) {
// std::wstring text;
// text = ImGui::InfoMarker;
// ImGui::SetCursorPosX(m_line_height / 3);
// ImGui::SetCursorPosY(m_window_height / 2 - m_line_height);
// imgui.text(text.c_str());
//}
}
void NotificationManager : : PopNotification : : render_minimize_button ( ImGuiWrapper & imgui , const float win_pos_x , const float 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_ButtonActive , ImGui : : GetStyleColorVec4 ( ImGuiCol_WindowBg ) , m_state = = EState : : FadingOut , m_current_fade_opacity ) ;
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 ) ;
//button - if part if treggered
std : : string button_text ;
button_text = ImGui : : MinimalizeButton ;
if ( ImGui : : IsMouseHoveringRect ( ImVec2 ( win_pos_x - m_window_width / 10.f , win_pos_y + m_window_height - 2 * m_line_height + 1 ) ,
ImVec2 ( win_pos_x , win_pos_y + m_window_height ) ,
true ) )
{
button_text = ImGui : : MinimalizeHoverButton ;
}
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 ( m_window_width - m_line_height * 1.8f ) ;
ImGui : : SetCursorPosY ( m_window_height - button_size . y - 5 ) ;
if ( imgui . button ( button_text . c_str ( ) , button_size . x , button_size . y ) )
{
m_multiline = false ;
}
ImGui : : PopStyleColor ( 5 ) ;
m_minimize_b_visible = true ;
}
bool NotificationManager : : PopNotification : : on_text_click ( )
{
if ( m_data . callback ! = nullptr )
return m_data . callback ( m_evt_handler ) ;
return false ;
}
void NotificationManager : : PopNotification : : update ( const NotificationData & n )
{
m_text1 = n . text1 ;
m_hypertext = n . hypertext ;
m_text2 = n . text2 ;
const_cast < NotificationData & > ( m_data ) . callback = n . callback ;
init ( ) ;
}
void NotificationManager : : PopNotification : : append ( const std : : string & append_str )
{
m_text1 = m_text1 + " \n " + append_str ;
//m_hypertext = n.hypertext;
//m_text2 = n.text2;
//const_cast<NotificationData&>(m_data).callback = n.callback;
init ( ) ;
m_multiline = false ;
}
bool NotificationManager : : PopNotification : : compare_text ( const std : : string & text ) const
{
std : : wstring wt1 = boost : : nowide : : widen ( m_text1 ) ;
std : : wstring wt2 = boost : : nowide : : widen ( text ) ;
wt1 . erase ( std : : remove_if ( wt1 . begin ( ) , wt1 . end ( ) , : : iswspace ) , wt1 . end ( ) ) ;
wt2 . erase ( std : : remove_if ( wt2 . begin ( ) , wt2 . end ( ) , : : iswspace ) , wt2 . end ( ) ) ;
if ( wt1 . compare ( wt2 ) = = 0 )
return true ;
return false ;
}
bool NotificationManager : : PopNotification : : update_state ( bool paused , const int64_t delta )
{
m_next_render = std : : numeric_limits < int64_t > : : max ( ) ;
if ( m_state = = EState : : Unknown ) {
init ( ) ;
return true ;
}
if ( m_state = = EState : : Hidden ) {
return false ;
}
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_state = EState : : Unknown ;
init ( ) ;
// Timers when not fading
} else if ( m_state ! = EState : : NotFading & & m_state ! = EState : : FadingOut & & m_state ! = EState : : ClosePending & & m_state ! = EState : : Finished & & get_duration ( ) ! = 0 & & ! paused ) {
int64_t up_time = now - m_notification_start ;
if ( up_time > = get_duration ( ) * 1000 ) {
m_state = EState : : FadingOut ;
m_fading_start = now ;
} else {
m_next_render = get_duration ( ) * 1000 - up_time ;
}
}
// Timers when fading
if ( m_state = = EState : : FadingOut & & ! paused ) {
int64_t curr_time = now - m_fading_start ;
int64_t next_render = FADING_OUT_TIMEOUT - delta ;
m_current_fade_opacity = std : : clamp ( 1.0f - 0.001f * static_cast < float > ( curr_time ) / FADING_OUT_DURATION , 0.0f , 1.0f ) ;
if ( m_current_fade_opacity < = 0.0f ) {
m_state = EState : : Finished ;
return true ;
} else if ( next_render < = 20 ) {
m_next_render = FADING_OUT_TIMEOUT ;
return true ;
} else {
m_next_render = next_render ;
return false ;
}
}
if ( m_state = = EState : : Finished ) {
return true ;
}
if ( m_state = = EState : : ClosePending ) {
m_state = EState : : Finished ;
return true ;
}
return false ;
}
//---------------ExportFinishedNotification-----------
void NotificationManager : : ExportFinishedNotification : : count_spaces ( )
{
if ( m_eject_pending )
{
return PopNotification : : count_spaces ( ) ;
}
//determine line width
m_line_height = ImGui : : CalcTextSize ( " A " ) . y ;
m_left_indentation = m_line_height ;
//if (m_data.level == NotificationLevel::ErrorNotificationLevel || m_data.level == NotificationLevel::WarningNotificationLevel) {
// std::string text;
// 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;
//}
//TODO count this properly
m_window_width_offset = m_left_indentation + m_line_height * ( m_to_removable ? 6.f : 3.f ) ;
m_window_width = m_line_height * 25 ;
}
void NotificationManager : : ExportFinishedNotification : : render_text ( ImGuiWrapper & imgui , const float win_size_x , const float win_size_y , const float win_pos_x , const float win_pos_y )
{
if ( m_eject_pending )
{
return PopNotification : : render_text ( imgui , win_size_x , win_size_y , win_pos_x , win_pos_y ) ;
}
float x_offset = m_left_indentation ;
std : : string fulltext = m_text1 + m_hypertext ; //+ m_text2;
// Lines are always at least two and m_multiline is always true for ExportFinishedNotification.
// First line has "Export Finished" text and than hyper text open folder.
// Following lines are path to gcode.
size_t last_end = 0 ;
float starting_y = m_line_height / 2 ; //10;
float shift_y = m_line_height ; // -m_line_height / 20;
for ( size_t i = 0 ; i < m_lines_count ; i + + ) {
assert ( m_text1 . size ( ) > = m_endlines [ i ] ) ;
if ( m_text1 . size ( ) > = m_endlines [ i ] ) {
std : : string line = m_text1 . substr ( last_end , m_endlines [ i ] - last_end ) ;
last_end = m_endlines [ i ] ;
if ( m_text1 . size ( ) > m_endlines [ i ] )
last_end + = ( m_text1 [ m_endlines [ i ] ] = = ' \n ' | | m_text1 [ m_endlines [ i ] ] = = ' ' ? 1 : 0 ) ;
ImGui : : SetCursorPosX ( x_offset ) ;
ImGui : : SetCursorPosY ( starting_y + i * shift_y ) ;
imgui . text ( line . c_str ( ) ) ;
//hyperlink text
if ( i = = 0 & & ! m_eject_pending ) {
render_hypertext ( imgui , x_offset + ImGui : : CalcTextSize ( line . c_str ( ) ) . x + ImGui : : CalcTextSize ( " " ) . x , starting_y , _u8L ( " Open Folder. " ) ) ;
}
}
}
}
void NotificationManager : : ExportFinishedNotification : : render_close_button ( ImGuiWrapper & imgui , const float win_size_x , const float win_size_y , const float win_pos_x , const float win_pos_y )
{
PopNotification : : render_close_button ( imgui , win_size_x , win_size_y , win_pos_x , win_pos_y ) ;
2022-09-16 03:31:12 +00:00
if ( m_to_removable & & ! m_eject_pending )
render_eject_button ( imgui , win_size_x , win_size_y , win_pos_x , win_pos_y ) ;
2022-07-15 15:37:19 +00:00
}
2022-09-16 03:31:12 +00:00
void NotificationManager : : ExportFinishedNotification : : 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 )
2022-07-15 15:37:19 +00:00
{
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 : : EjectButton ;
2022-09-16 03:31:12 +00:00
if ( ImGui : : IsMouseHoveringRect ( ImVec2 ( win_pos . x - m_line_height * 5.f , win_pos . y ) ,
2022-07-15 15:37:19 +00:00
ImVec2 ( win_pos . x - m_line_height * 2.5f , win_pos . y + win_size . y ) ,
true ) )
{
button_text = ImGui : : EjectHoverButton ;
2022-09-16 03:31:12 +00:00
//tooltip
2022-07-15 15:37:19 +00:00
long time_now = wxGetLocalTime ( ) ;
if ( m_hover_time > 0 & & m_hover_time < time_now ) {
ImGui : : PushStyleColor ( ImGuiCol_PopupBg , ImGuiWrapper : : COL_WINDOW_BACKGROUND ) ;
2022-09-16 03:31:12 +00:00
//ImGui::BeginTooltip();
//imgui.text(_u8L("Eject drive") + " " + GUI::shortkey_ctrl_prefix() + "T");
//ImGui::EndTooltip();
2022-07-15 15:37:19 +00:00
ImGui : : PopStyleColor ( ) ;
}
if ( m_hover_time = = 0 )
m_hover_time = time_now ;
2022-09-16 03:31:12 +00:00
}
else
2022-07-15 15:37:19 +00:00
m_hover_time = 0 ;
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 * 5.0f ) ;
ImGui : : SetCursorPosY ( win_size . y / 2 - button_size . y ) ;
if ( imgui . button ( button_text . c_str ( ) , button_size . x , button_size . y ) )
{
assert ( m_evt_handler ! = nullptr ) ;
if ( m_evt_handler ! = nullptr )
wxPostEvent ( m_evt_handler , EjectDriveNotificationClickedEvent ( EVT_EJECT_DRIVE_NOTIFICAION_CLICKED ) ) ;
on_eject_click ( ) ;
}
//invisible large button
2022-09-16 03:31:12 +00:00
ImGui : : SetCursorPosX ( win_size . x - m_line_height * 4.625f ) ;
2022-07-15 15:37:19 +00:00
ImGui : : SetCursorPosY ( 0 ) ;
if ( imgui . button ( " " , m_line_height * 2.f , win_size . y ) )
{
assert ( m_evt_handler ! = nullptr ) ;
if ( m_evt_handler ! = nullptr )
wxPostEvent ( m_evt_handler , EjectDriveNotificationClickedEvent ( EVT_EJECT_DRIVE_NOTIFICAION_CLICKED ) ) ;
on_eject_click ( ) ;
}
ImGui : : PopStyleColor ( 5 ) ;
2022-09-16 03:31:12 +00:00
}
2022-07-15 15:37:19 +00:00
bool NotificationManager : : ExportFinishedNotification : : on_text_click ( )
{
open_folder ( m_export_dir_path ) ;
return false ;
}
void NotificationManager : : ExportFinishedNotification : : on_eject_click ( )
{
NotificationData data { get_data ( ) . type , get_data ( ) . level , 0 , _utf8 ( " Ejecting. " ) } ;
m_eject_pending = true ;
m_multiline = false ;
update ( data ) ;
}
//------ProgressBar----------------
void NotificationManager : : ProgressBarNotification : : init ( )
{
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 ;
while ( m_endlines . size ( ) < 3 )
m_endlines . push_back ( m_endlines . back ( ) ) ;
} else {
m_lines_count = 2 ;
m_endlines . push_back ( m_endlines . back ( ) ) ;
m_multiline = false ;
}
if ( m_state = = EState : : Shown )
m_state = EState : : NotFading ;
}
void NotificationManager : : ProgressBarNotification : : render_text ( ImGuiWrapper & imgui , const float win_size_x , const float win_size_y , const float win_pos_x , const float win_pos_y )
{
// hypertext is not rendered at all. If it is needed, it needs to be added here.
// m_endlines should have endline for each line and then for hypertext thus m_endlines[1] should always be in m_text1
if ( m_multiline ) {
assert ( m_text1 . size ( ) > = m_endlines [ 0 ] | | m_text1 . size ( ) > = m_endlines [ 1 ] ) ;
if ( m_endlines [ 0 ] > m_text1 . size ( ) | | m_endlines [ 1 ] > m_text1 . size ( ) )
return ;
// two lines text (what doesnt fit, wont show), 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_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 {
assert ( m_text1 . size ( ) > = m_endlines [ 0 ] ) ;
if ( m_endlines [ 0 ] > m_text1 . size ( ) )
return ;
//one line text, one line bar
ImGui : : SetCursorPosX ( m_left_indentation ) ;
ImGui : : SetCursorPosY ( /*win_size_y / 2 - win_size_y / 6 -*/ m_line_height / 4 ) ;
imgui . text ( m_text1 . substr ( 0 , m_endlines [ 0 ] ) . c_str ( ) ) ;
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 ) ;
}
}
void NotificationManager : : ProgressBarNotification : : render_bar ( ImGuiWrapper & imgui , const float win_size_x , const float win_size_y , const float win_pos_x , const float win_pos_y )
{
//ImVec4 orange_color = ImVec4(.99f, .313f, .0f, 1.0f);
//ImVec4 gray_color = ImVec4(.34f, .34f, .34f, 1.0f);
ImVec4 orange_color = m_NormalColor ;
ImVec4 gray_color = ImVec4 ( .7f , .7f , .7f , 1.0f ) ;
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 ) , ( 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 ( ) ) ;
}
}
//------UpdatedItemsInfoNotification-------
void NotificationManager : : UpdatedItemsInfoNotification : : count_spaces ( )
{
//determine line width
m_line_height = ImGui : : CalcTextSize ( " A " ) . y ;
//std::string text;
//text = ImGui::WarningMarker;
//float picture_width = ImGui::CalcTextSize(text.c_str()).x;
//m_left_indentation = picture_width + m_line_height / 2;
m_left_indentation = m_line_height ;
m_window_width_offset = m_left_indentation + m_line_height * 3.f ;
m_window_width = m_line_height * 25 ;
}
void NotificationManager : : UpdatedItemsInfoNotification : : add_type ( InfoItemType type )
{
std : : vector < std : : pair < InfoItemType , size_t > > : : iterator it = m_types_and_counts . begin ( ) ;
for ( ; it ! = m_types_and_counts . end ( ) ; + + it ) {
if ( ( * it ) . first = = type ) {
( * it ) . second + + ;
break ;
}
}
if ( it = = m_types_and_counts . end ( ) )
m_types_and_counts . emplace_back ( type , 1 ) ;
std : : string text ;
for ( it = m_types_and_counts . begin ( ) ; it ! = m_types_and_counts . end ( ) ; + + it ) {
if ( ( * it ) . second = = 0 )
continue ;
switch ( ( * it ) . first ) {
case InfoItemType : : CustomSupports : text + = format ( _L_PLURAL ( " %1$d Object has custom supports. " , " %1$d Objects have custom supports. " , ( * it ) . second ) , ( * it ) . second ) + " \n " ; break ;
// BBS
//case InfoItemType::CustomSeam: text += format(("%1$d Object has custom seam.", "%1$d Objects have custom seam.", (*it).second), (*it).second) + "\n"; break;
case InfoItemType : : MmuSegmentation : text + = format ( _L_PLURAL ( " %1$d Object has color painting. " , " %1$d Objects have color painting. " , ( * it ) . second ) , ( * it ) . second ) + " \n " ; break ;
// BBS
//case InfoItemType::Sinking: text += format(("%1$d Object has partial sinking.", "%1$d Objects have partial sinking.", (*it).second), (*it).second) + "\n"; break;
default : BOOST_LOG_TRIVIAL ( error ) < < " Unknown InfoItemType: " < < ( * it ) . second ; break ;
}
}
m_state = EState : : Unknown ;
NotificationData data { get_data ( ) . type , get_data ( ) . level , get_data ( ) . duration , text } ;
update ( data ) ;
}
//------SlicingProgressNotification
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 ( ) ;
}
}
bool NotificationManager : : SlicingProgressNotification : : set_progress_state ( float percent )
{
if ( percent < 0.f )
return true ; //set_progress_state(SlicingProgressState::SP_CANCELLED);
else if ( percent > = 1.f )
return set_progress_state ( SlicingProgressState : : SP_COMPLETED ) ;
else
return set_progress_state ( SlicingProgressState : : SP_PROGRESS , percent ) ;
}
bool NotificationManager : : SlicingProgressNotification : : set_progress_state ( NotificationManager : : SlicingProgressNotification : : SlicingProgressState state , float percent /* = 0.f*/ )
{
switch ( state )
{
case Slic3r : : GUI : : NotificationManager : : SlicingProgressNotification : : SlicingProgressState : : SP_NO_SLICING :
m_state = EState : : Hidden ;
set_percentage ( - 1 ) ;
m_has_print_info = false ;
set_export_possible ( false ) ;
m_sp_state = state ;
return true ;
case Slic3r : : GUI : : NotificationManager : : SlicingProgressNotification : : SlicingProgressState : : SP_BEGAN :
m_state = EState : : Hidden ;
set_percentage ( - 1 ) ;
m_has_print_info = false ;
set_export_possible ( false ) ;
m_sp_state = state ;
m_current_fade_opacity = 1 ;
return true ;
case Slic3r : : GUI : : NotificationManager : : SlicingProgressNotification : : SlicingProgressState : : SP_PROGRESS :
if ( ( m_sp_state ! = SlicingProgressState : : SP_BEGAN & & m_sp_state ! = SlicingProgressState : : SP_PROGRESS ) | | percent < m_percentage )
return false ;
set_percentage ( percent ) ;
m_has_cancel_button = true ;
m_sp_state = state ;
m_current_fade_opacity = 1 ;
return true ;
case Slic3r : : GUI : : NotificationManager : : SlicingProgressNotification : : SlicingProgressState : : SP_CANCELLED :
set_percentage ( - 1 ) ;
m_has_cancel_button = false ;
m_has_print_info = false ;
set_export_possible ( false ) ;
m_sp_state = state ;
return true ;
case Slic3r : : GUI : : NotificationManager : : SlicingProgressNotification : : SlicingProgressState : : SP_COMPLETED :
if ( m_sp_state ! = SlicingProgressState : : SP_BEGAN & & m_sp_state ! = SlicingProgressState : : SP_PROGRESS )
return false ;
set_percentage ( 1 ) ;
m_has_cancel_button = false ;
m_has_print_info = false ;
// m_export_possible is important only for SP_PROGRESS state, thus we can reset it here
set_export_possible ( false ) ;
m_sp_state = state ;
return true ;
default :
break ;
}
return false ;
}
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 + " . " } ;
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 ( " Slice ok. " ) , 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 & & collapsed )
m_state = EState : : NotFading ;
}
void NotificationManager : : SlicingProgressNotification : : on_cancel_button ( )
{
if ( m_cancel_callback ) {
if ( ! m_cancel_callback ( ) ) {
set_progress_state ( SlicingProgressState : : SP_NO_SLICING ) ;
}
}
}
int NotificationManager : : SlicingProgressNotification : : get_duration ( )
{
if ( m_sp_state = = SlicingProgressState : : SP_CANCELLED )
return 2 ;
else if ( m_sp_state = = SlicingProgressState : : SP_COMPLETED & & ! m_sidebar_collapsed )
return 2 ;
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 & & m_sidebar_collapsed ) {
// "Slicing Finished" on line 1 + hypertext, print info on line
ImVec2 win_size ( win_size_x , win_size_y ) ;
ImVec2 text1_size = ImGui : : CalcTextSize ( m_text1 . c_str ( ) ) ;
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 ) {
return ;
}
ProgressBarNotification : : render_bar ( imgui , win_size_x , win_size_y , win_pos_x , win_pos_y ) ;
}
void NotificationManager : : SlicingProgressNotification : : render_hypertext ( ImGuiWrapper & imgui , const float text_x , const float text_y , const std : : string text , bool more )
{
if ( m_sp_state = = SlicingProgressState : : SP_COMPLETED & & ! m_sidebar_collapsed )
return ;
ProgressBarNotification : : render_hypertext ( imgui , text_x , text_y , text , more ) ;
}
void NotificationManager : : SlicingProgressNotification : : render_cancel_button ( ImGuiWrapper & imgui , const float win_size_x , const float win_size_y , const float win_pos_x , const float win_pos_y )
{
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 : : ClosePending ;
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 : : FadingOut ;
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 ;
m_current_fade_opacity = 1.0f ;
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 )
{
}
void NotificationManager : : push_notification ( const NotificationType type , int timestamp )
{
auto it = std : : find_if ( std : : begin ( basic_notifications ) , std : : end ( basic_notifications ) ,
boost : : bind ( & NotificationData : : type , boost : : placeholders : : _1 ) = = type ) ;
assert ( it ! = std : : end ( basic_notifications ) ) ;
if ( it ! = std : : end ( basic_notifications ) )
push_notification_data ( * it , timestamp ) ;
}
void NotificationManager : : push_notification ( const std : : string & text , int timestamp )
{
push_notification_data ( { NotificationType : : CustomNotification , NotificationLevel : : RegularNotificationLevel , 10 , text } , timestamp ) ;
}
void NotificationManager : : push_notification ( NotificationType type ,
NotificationLevel level ,
const std : : string & text ,
const std : : string & hypertext ,
std : : function < bool ( wxEvtHandler * ) > callback ,
int timestamp )
{
int duration = get_standard_duration ( level ) ;
push_notification_data ( { type , level , duration , text , hypertext , callback } , timestamp ) ;
}
void NotificationManager : : push_delayed_notification ( const NotificationType type , std : : function < bool ( void ) > condition_callback , int64_t initial_delay , int64_t delay_interval )
{
auto it = std : : find_if ( std : : begin ( basic_notifications ) , std : : end ( basic_notifications ) ,
boost : : bind ( & NotificationData : : type , boost : : placeholders : : _1 ) = = type ) ;
assert ( it ! = std : : end ( basic_notifications ) ) ;
if ( it ! = std : : end ( basic_notifications ) )
push_delayed_notification_data ( std : : make_unique < PopNotification > ( * it , m_id_provider , m_evt_handler ) , condition_callback , initial_delay , delay_interval ) ;
}
void NotificationManager : : push_validate_error_notification ( StringObjectException const & error )
{
auto po = dynamic_cast < PrintObjectBase const * > ( error . object ) ;
auto mo = po ? po - > model_object ( ) : dynamic_cast < ModelObject const * > ( error . object ) ;
auto callback = ( mo | | ! error . opt_key . empty ( ) ) ? [ id = mo ? mo - > id ( ) : 0 , opt = error . opt_key ] ( wxEvtHandler * ) {
auto & objects = wxGetApp ( ) . model ( ) . objects ;
auto iter = id . id ? std : : find_if ( objects . begin ( ) , objects . end ( ) , [ id ] ( auto o ) { return o - > id ( ) = = id ; } ) : objects . end ( ) ;
if ( iter ! = objects . end ( ) )
wxGetApp ( ) . obj_list ( ) - > select_items ( { { * iter , nullptr } } ) ;
if ( ! opt . empty ( ) ) {
if ( iter ! = objects . end ( ) )
wxGetApp ( ) . params_panel ( ) - > switch_to_object ( ) ;
wxGetApp ( ) . sidebar ( ) . jump_to_option ( opt , Preset : : TYPE_PRINT , L " " ) ;
}
return false ;
} : std : : function < bool ( wxEvtHandler * ) > ( ) ;
auto link = ( mo | | ! error . opt_key . empty ( ) ) ? _u8L ( " Jump to " ) : " " ;
if ( mo ) link + = std : : string ( " [ " ) + mo - > name + " ] " ;
if ( ! error . opt_key . empty ( ) ) link + = std : : string ( " ( " ) + error . opt_key + " ) " ;
push_notification_data ( { NotificationType : : ValidateError , NotificationLevel : : ErrorNotificationLevel , 0 , _u8L ( " Error: " ) + " \n " + error . string , link , callback } , 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 : : 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 , int warning_msg_id )
{
NotificationData data { NotificationType : : SlicingWarning , NotificationLevel : : WarningNotificationLevel , 0 , _u8L ( " Warning: " ) + " \n " + text } ;
data . sub_msg_id = warning_msg_id ;
data . ori_text = text ;
auto notification = std : : make_unique < NotificationManager : : ObjectIDNotification > ( data , m_id_provider , m_evt_handler ) ;
notification - > object_id = oid ;
notification - > warning_step = warning_step ;
if ( push_notification_data ( std : : move ( notification ) , 0 ) ) {
m_pop_notifications . back ( ) - > set_gray ( gray ) ;
}
}
void NotificationManager : : push_plater_error_notification ( const std : : string & text )
{
push_notification_data ( { NotificationType : : PlaterError , NotificationLevel : : ErrorNotificationLevel , 0 , _u8L ( " Error: " ) + " \n " + text } , 0 ) ;
}
void NotificationManager : : close_plater_error_notification ( const std : : string & text )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : PlaterError & & notification - > compare_text ( _u8L ( " Error: " ) + " \n " + text ) ) {
notification - > close ( ) ;
}
}
}
void NotificationManager : : push_plater_warning_notification ( const std : : string & text )
{
// Find if was not hidden
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : PlaterWarning & & notification - > compare_text ( _u8L ( " Warning: " ) + " \n " + text ) ) {
if ( notification - > get_state ( ) = = PopNotification : : EState : : Hidden ) {
//dynamic_cast<PlaterWarningNotification*>(notification.get())->show();
return ;
}
}
}
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 ) ;
// dissaper if in preview
apply_in_preview ( ) ;
}
void NotificationManager : : close_plater_warning_notification ( const std : : string & text )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : PlaterWarning & & notification - > compare_text ( _u8L ( " Warning: " ) + " \n " + text ) ) {
dynamic_cast < PlaterWarningNotification * > ( notification . get ( ) ) - > real_close ( ) ;
}
}
}
void NotificationManager : : set_all_slicing_errors_gray ( bool g )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : SlicingError ) {
notification - > set_gray ( g ) ;
}
}
}
void NotificationManager : : set_all_slicing_warnings_gray ( bool g )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : SlicingWarning ) {
notification - > set_gray ( g ) ;
}
}
}
/*
void NotificationManager : : set_slicing_warning_gray ( const std : : string & text , bool g )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : SlicingWarning & & notification - > compare_text ( text ) ) {
notification - > set_gray ( g ) ;
}
}
}
*/
void NotificationManager : : close_slicing_errors_and_warnings ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : SlicingError | | notification - > get_type ( ) = = NotificationType : : SlicingWarning ) {
notification - > close ( ) ;
}
}
}
void NotificationManager : : close_slicing_error_notification ( const std : : string & text )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : SlicingError & & notification - > compare_text ( _u8L ( " Error: " ) + " \n " + text ) ) {
notification - > close ( ) ;
}
}
}
void NotificationManager : : push_simplify_suggestion_notification ( const std : : string & text , ObjectID object_id , const std : : string & hypertext /* = ""*/ , std : : function < bool ( wxEvtHandler * ) > callback /* = std::function<bool(wxEvtHandler*)>()*/ )
{
NotificationData data { NotificationType : : SimplifySuggestion , NotificationLevel : : PrintInfoNotificationLevel , 0 , text , hypertext , callback } ;
auto notification = std : : make_unique < NotificationManager : : ObjectIDNotification > ( data , m_id_provider , m_evt_handler ) ;
notification - > object_id = object_id ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : close_notification_of_type ( const NotificationType type )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = type ) {
notification - > close ( ) ;
}
}
}
void NotificationManager : : remove_slicing_warnings_of_released_objects ( const std : : vector < ObjectID > & living_oids )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : SlicingWarning ) {
if ( ! std : : binary_search ( living_oids . begin ( ) , living_oids . end ( ) ,
static_cast < ObjectIDNotification * > ( notification . get ( ) ) - > object_id ) )
notification - > close ( ) ;
}
}
void NotificationManager : : remove_simplify_suggestion_of_released_objects ( const std : : vector < ObjectID > & living_oids )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : SimplifySuggestion ) {
if ( ! std : : binary_search ( living_oids . begin ( ) , living_oids . end ( ) ,
static_cast < ObjectIDNotification * > ( notification . get ( ) ) - > object_id ) )
notification - > close ( ) ;
}
}
void NotificationManager : : remove_simplify_suggestion_with_id ( const ObjectID oid )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : SimplifySuggestion ) {
if ( static_cast < ObjectIDNotification * > ( notification . get ( ) ) - > object_id = = oid )
notification - > close ( ) ;
}
}
void NotificationManager : : set_simplify_suggestion_multiline ( const ObjectID oid , bool bMulti )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : SimplifySuggestion ) {
if ( static_cast < ObjectIDNotification * > ( notification . get ( ) ) - > object_id = = oid )
notification - > set_Multiline ( bMulti ) ;
}
}
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 : : RegularNotificationLevel , on_removable ? 0 : 20 , _u8L ( " Export ok. " ) + " \n " + path } ;
push_notification_data ( std : : make_unique < NotificationManager : : ExportFinishedNotification > ( data , m_id_provider , m_evt_handler , on_removable , path , dir_path ) , 0 ) ;
set_slicing_progress_hidden ( ) ;
}
void NotificationManager : : init_slicing_progress_notification ( std : : function < bool ( ) > 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_began ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : SlicingProgress ) {
SlicingProgressNotification * spn = dynamic_cast < SlicingProgressNotification * > ( notification . get ( ) ) ;
spn - > set_progress_state ( SlicingProgressNotification : : SlicingProgressState : : SP_BEGAN ) ;
return ;
}
}
// Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended
wxGetApp ( ) . plater ( ) - > init_notification_manager ( ) ;
}
void NotificationManager : : set_slicing_progress_percentage ( const std : : string & text , float percentage )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : SlicingProgress ) {
SlicingProgressNotification * spn = dynamic_cast < SlicingProgressNotification * > ( notification . get ( ) ) ;
if ( spn - > set_progress_state ( percentage ) ) {
spn - > set_status_text ( text ) ;
wxGetApp ( ) . plater ( ) - > get_current_canvas3D ( ) - > schedule_extra_frame ( 0 ) ;
}
return ;
}
}
// Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended
wxGetApp ( ) . plater ( ) - > init_notification_manager ( ) ;
}
void NotificationManager : : set_slicing_progress_canceled ( const std : : string & text )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : SlicingProgress ) {
SlicingProgressNotification * spn = dynamic_cast < SlicingProgressNotification * > ( notification . get ( ) ) ;
spn - > set_progress_state ( SlicingProgressNotification : : SlicingProgressState : : SP_CANCELLED ) ;
spn - > set_status_text ( text ) ;
wxGetApp ( ) . plater ( ) - > get_current_canvas3D ( ) - > schedule_extra_frame ( 0 ) ;
return ;
}
}
// 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 , 1 } ;
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 )
{
2022-09-15 06:51:29 +00:00
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : DidYouKnowHint ) {
( dynamic_cast < HintNotification * > ( notification . get ( ) ) ) - > open_next ( ) ;
return ;
}
}
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 ) ;
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 {
auto condition = [ & self = std : : as_const ( * this ) ] ( ) {
return self . get_notification_count ( ) = = 0 ;
} ;
push_delayed_notification_data ( std : : make_unique < NotificationManager : : HintNotification > ( data , m_id_provider , m_evt_handler , open_next ) , condition , 500 , 30000 ) ;
}
2022-07-15 15:37:19 +00:00
}
bool NotificationManager : : is_hint_notification_open ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : DidYouKnowHint )
return true ;
}
return false ;
}
void NotificationManager : : deactivate_loaded_hints ( )
{
;
}
void NotificationManager : : push_updated_item_info_notification ( InfoItemType type )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : UpdatedItemsInfo ) {
( dynamic_cast < UpdatedItemsInfoNotification * > ( notification . get ( ) ) ) - > add_type ( type ) ;
return ;
}
}
NotificationData data { NotificationType : : UpdatedItemsInfo , NotificationLevel : : PrintInfoNotificationLevel , 10 , " " } ;
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 ) ;
}
}
bool NotificationManager : : push_notification_data ( const NotificationData & notification_data , int timestamp )
{
return push_notification_data ( std : : make_unique < PopNotification > ( notification_data , m_id_provider , m_evt_handler ) , timestamp ) ;
}
bool NotificationManager : : push_notification_data ( std : : unique_ptr < NotificationManager : : PopNotification > notification , int timestamp )
{
// if timestamped notif, push only new one
if ( timestamp ! = 0 ) {
if ( m_used_timestamps . find ( timestamp ) = = m_used_timestamps . end ( ) ) {
m_used_timestamps . insert ( timestamp ) ;
} else {
return false ;
}
}
bool retval = false ;
if ( this - > activate_existing ( notification . get ( ) ) ) {
if ( m_initialized ) { // ignore update action - it cant be initialized if canvas and imgui context is not ready
if ( notification - > get_type ( ) = = NotificationType : : SlicingWarning ) {
m_pop_notifications . back ( ) - > append ( notification - > get_data ( ) . ori_text ) ;
}
else
m_pop_notifications . back ( ) - > update ( notification - > get_data ( ) ) ;
}
} else {
m_pop_notifications . emplace_back ( std : : move ( notification ) ) ;
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_data ( std : : unique_ptr < NotificationManager : : PopNotification > notification , std : : function < bool ( void ) > condition_callback , int64_t initial_delay , int64_t delay_interval )
{
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 ;
}
}
}
void NotificationManager : : render_notifications ( GLCanvas3D & canvas , float overlay_width , float bottom_margin , float right_margin )
{
sort_notifications ( ) ;
float last_y = bottom_margin ;
for ( const auto & notification : m_pop_notifications ) {
if ( notification - > get_state ( ) ! = PopNotification : : EState : : Hidden ) {
notification - > render ( canvas , last_y , m_move_from_overlay & & ! m_in_preview , overlay_width , right_margin * m_scale ) ;
if ( notification - > get_state ( ) ! = PopNotification : : EState : : Finished )
last_y = notification - > get_top ( ) + GAP_WIDTH ;
}
}
m_last_render = GLCanvas3D : : timestamp_now ( ) ;
}
bool NotificationManager : : update_notifications ( GLCanvas3D & canvas )
{
// no update if not top window
wxWindow * p = dynamic_cast < wxWindow * > ( wxGetApp ( ) . plater ( ) ) ;
while ( p - > GetParent ( ) ! = nullptr )
p = p - > GetParent ( ) ;
wxTopLevelWindow * top_level_wnd = dynamic_cast < wxTopLevelWindow * > ( p ) ;
if ( ! top_level_wnd - > IsActive ( ) )
return false ;
// next_render() returns numeric_limits::max if no need for frame
const int64_t max = std : : numeric_limits < int64_t > : : max ( ) ;
int64_t next_render = max ;
const int64_t time_since_render = GLCanvas3D : : timestamp_now ( ) - m_last_render ;
bool request_render = false ;
// During render, each notification detects if its currently hovered and changes its state to EState::Hovered
// If any notification is hovered, all restarts its countdown
bool hover = false ;
for ( const std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > is_hovered ( ) ) {
hover = true ;
break ;
}
}
// update state of all notif and erase finished
for ( auto it = m_pop_notifications . begin ( ) ; it ! = m_pop_notifications . end ( ) ; ) {
std : : unique_ptr < PopNotification > & notification = * it ;
request_render | = notification - > update_state ( hover , time_since_render ) ;
next_render = std : : min < int64_t > ( next_render , notification - > next_render ( ) ) ;
if ( notification - > get_state ( ) = = PopNotification : : EState : : Finished )
it = m_pop_notifications . erase ( it ) ;
else
+ + it ;
}
// delayed notifications
for ( auto it = m_waiting_notifications . begin ( ) ; it ! = m_waiting_notifications . end ( ) ; ) {
// substract time
if ( ( * it ) . remaining_time > 0 )
( * it ) . remaining_time - = time_since_render ;
if ( ( * it ) . remaining_time < = 0 ) {
if ( ( * it ) . notification & & ( * it ) . condition_callback ( ) ) { // push notification, erase it from waiting list (frame is scheduled by push)
( * it ) . notification - > reset_timer ( ) ;
// if activate_existing returns false, we expect push to return true.
if ( ! this - > activate_existing ( ( * it ) . notification . get ( ) ) | | ( * it ) . delay_interval = = 0 ) {
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 < int64_t > ( next_render , ( * it ) . remaining_time ) ;
+ + it ;
}
// request next frame in future
if ( next_render < max )
canvas . schedule_extra_frame ( int ( next_render ) ) ;
return request_render ;
}
void NotificationManager : : sort_notifications ( )
{
// Stable sorting, so that the order of equal ranges is stable.
std : : stable_sort ( m_pop_notifications . begin ( ) , m_pop_notifications . end ( ) , [ ] ( const std : : unique_ptr < PopNotification > & n1 , const std : : unique_ptr < PopNotification > & n2 ) {
int n1l = ( int ) n1 - > get_data ( ) . level ;
int n2l = ( int ) n2 - > get_data ( ) . level ;
if ( n1l = = n2l & & n1 - > is_gray ( ) & & ! n2 - > is_gray ( ) )
return true ;
return ( n1l < n2l ) ;
} ) ;
}
bool NotificationManager : : activate_existing ( const NotificationManager : : PopNotification * notification )
{
NotificationType new_type = notification - > get_type ( ) ;
const std : : string & new_text = notification - > get_data ( ) . text1 ;
for ( auto it = m_pop_notifications . begin ( ) ; it ! = m_pop_notifications . end ( ) ; + + it ) {
if ( ( * it ) - > get_type ( ) = = new_type & & ! ( * it ) - > is_finished ( ) ) {
// multiple of one type allowed, but must have different text
if ( std : : find ( m_multiple_types . begin ( ) , m_multiple_types . end ( ) , new_type ) ! = m_multiple_types . end ( ) ) {
// If found same type and same text, return true - update will be performed on the old notif
if ( ( * it ) - > compare_text ( new_text ) = = false ) {
continue ;
}
// multiple of one type allowed, but must have different text nad ObjectID
} else if ( new_type = = NotificationType : : SlicingWarning ) {
auto w1 = dynamic_cast < const ObjectIDNotification * > ( notification ) ;
auto w2 = dynamic_cast < const ObjectIDNotification * > ( it - > get ( ) ) ;
if ( w1 ! = nullptr & & w2 ! = nullptr ) {
const NotificationData & data1 = w1 - > get_data ( ) ;
const NotificationData & data2 = w2 - > get_data ( ) ;
if ( data1 . sub_msg_id ! = data2 . sub_msg_id )
continue ;
//if (!(*it)->compare_text(new_text) || w1->object_id != w2->object_id) {
// continue;
//}
} else {
continue ;
}
}
if ( it ! = m_pop_notifications . end ( ) - 1 )
std : : rotate ( it , it + 1 , m_pop_notifications . end ( ) ) ;
return true ;
}
}
return false ;
}
void NotificationManager : : set_in_preview ( bool preview )
{
m_in_preview = preview ;
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : PlaterWarning )
notification - > hide ( preview ) ;
if ( notification - > get_type ( ) = = NotificationType : : BBLPlateInfo )
notification - > hide ( preview ) ;
if ( notification - > get_type ( ) = = NotificationType : : SignDetected )
notification - > hide ( ! preview ) ;
if ( notification - > get_type ( ) = = NotificationType : : BBLObjectInfo )
notification - > hide ( preview ) ;
if ( notification - > get_type ( ) = = NotificationType : : BBLSeqPrintInfo )
notification - > hide ( preview ) ;
if ( m_in_preview & & notification - > get_type ( ) = = NotificationType : : DidYouKnowHint )
notification - > close ( ) ;
}
}
bool NotificationManager : : has_slicing_error_notification ( )
{
return std : : any_of ( m_pop_notifications . begin ( ) , m_pop_notifications . end ( ) , [ ] ( auto & n ) {
return n - > get_type ( ) = = NotificationType : : SlicingError ;
} ) ;
}
void NotificationManager : : new_export_began ( bool on_removable )
{
close_notification_of_type ( NotificationType : : ExportFinished ) ;
// If we want to hold information of ejecting removable on later export finished notifications
/*
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : ExportToRemovableFinished ) {
if ( ! on_removable ) {
const NotificationData old_data = notification - > get_data ( ) ;
notification - > update ( { old_data . type , old_data . level , old_data . duration , std : : string ( ) , old_data . hypertext } ) ;
} else {
notification - > close ( ) ;
}
return ;
}
}
*/
}
void NotificationManager : : device_ejected ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : ExportFinished & & dynamic_cast < ExportFinishedNotification * > ( notification . get ( ) ) - > m_to_removable )
notification - > close ( ) ;
}
}
size_t NotificationManager : : get_notification_count ( ) const
{
size_t ret = 0 ;
for ( const std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_state ( ) ! = PopNotification : : EState : : Hidden )
ret + + ;
}
return ret ;
}
void NotificationManager : : bbl_show_plateinfo_notification ( const std : : string & text )
{
2022-07-22 09:46:10 +00:00
NotificationData data { NotificationType : : BBLPlateInfo , NotificationLevel : : PrintInfoNotificationLevel , BBL_NOTICE_MAX_INTERVAL , text } ;
2022-07-15 15:37:19 +00:00
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : BBLPlateInfo ) {
notification - > reinit ( ) ;
notification - > update ( data ) ;
return ;
}
}
auto notification = std : : make_unique < NotificationManager : : PopNotification > ( data , m_id_provider , m_evt_handler ) ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : bbl_close_plateinfo_notification ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : BBLPlateInfo ) {
notification - > close ( ) ;
}
}
2022-07-22 09:46:10 +00:00
void NotificationManager : : bbl_show_preview_only_notification ( const std : : string & text )
{
NotificationData data { NotificationType : : BBLPreviewOnlyMode , NotificationLevel : : WarningNotificationLevel , 0 , text } ;
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : BBLPreviewOnlyMode ) {
notification - > reinit ( ) ;
notification - > update ( data ) ;
return ;
}
}
auto notification = std : : make_unique < NotificationManager : : PopNotification > ( data , m_id_provider , m_evt_handler ) ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : bbl_close_preview_only_notification ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : BBLPreviewOnlyMode ) {
notification - > close ( ) ;
}
}
2022-07-15 15:37:19 +00:00
void NotificationManager : : bbl_show_objectsinfo_notification ( const std : : string & text , bool is_warning , bool is_hidden )
{
std : : string hyper_text ;
auto callback = std : : function < bool ( wxEvtHandler * ) > ( ) ;
if ( is_warning ) {
callback = [ ] ( wxEvtHandler * ) {
wxCommandEvent * evt = new wxCommandEvent ( EVT_REPAIR_MODEL ) ;
wxQueueEvent ( wxGetApp ( ) . plater ( ) , evt ) ;
return false ;
} ;
hyper_text = _u8L ( " (Repair) " ) ;
}
2022-07-22 09:46:10 +00:00
NotificationData data { NotificationType : : BBLObjectInfo , NotificationLevel : : PrintInfoNotificationLevel , BBL_NOTICE_MAX_INTERVAL , text , hyper_text , callback } ;
2022-07-15 15:37:19 +00:00
if ( is_warning )
data . use_warn_color = true ;
for ( auto it = m_pop_notifications . begin ( ) ; it ! = m_pop_notifications . end ( ) ; ) {
std : : unique_ptr < PopNotification > & notification = * it ;
if ( notification - > get_type ( ) = = NotificationType : : BBLObjectInfo ) {
it = m_pop_notifications . erase ( it ) ;
break ;
}
else
+ + it ;
}
auto notification = std : : make_unique < NotificationManager : : PopNotification > ( data , m_id_provider , m_evt_handler ) ;
notification - > set_Multiline ( true ) ;
if ( is_hidden )
notification - > hide ( true ) ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : bbl_close_objectsinfo_notification ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : BBLObjectInfo ) { notification - > close ( ) ; }
}
void NotificationManager : : bbl_show_seqprintinfo_notification ( const std : : string & text )
{
2022-07-22 09:46:10 +00:00
NotificationData data { NotificationType : : BBLSeqPrintInfo , NotificationLevel : : PrintInfoNotificationLevel , BBL_NOTICE_MAX_INTERVAL , text } ;
2022-07-15 15:37:19 +00:00
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : BBLSeqPrintInfo ) {
notification - > reinit ( ) ;
notification - > update ( data ) ;
return ;
}
}
auto notification = std : : make_unique < NotificationManager : : PopNotification > ( data , m_id_provider , m_evt_handler ) ;
notification - > set_Multiline ( true ) ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : bbl_close_seqprintinfo_notification ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : BBLSeqPrintInfo ) { notification - > close ( ) ; }
}
2022-07-22 09:46:10 +00:00
void NotificationManager : : bbl_show_plugin_install_notification ( const std : : string & text )
{
std : : string hyper_text ;
auto callback = [ ] ( wxEvtHandler * ) {
wxCommandEvent * evt = new wxCommandEvent ( EVT_INSTALL_PLUGIN_NETWORKING ) ;
wxQueueEvent ( wxGetApp ( ) . plater ( ) , evt ) ;
return false ;
} ;
hyper_text = _u8L ( " Click here to install it. " ) ;
NotificationData data { NotificationType : : BBLPluginInstallHint , NotificationLevel : : WarningNotificationLevel , 0 , text , hyper_text , callback } ;
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : BBLPluginInstallHint ) {
notification - > reinit ( ) ;
notification - > update ( data ) ;
return ;
}
}
auto notification = std : : make_unique < NotificationManager : : PopNotification > ( data , m_id_provider , m_evt_handler ) ;
notification - > set_Multiline ( true ) ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : bbl_close_plugin_install_notification ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : BBLPluginInstallHint ) { notification - > close ( ) ; }
}
2022-07-15 15:37:19 +00:00
void NotificationManager : : bbl_show_slice_emptylayer_notification ( const std : : string & text , bool bOverride )
{
NotificationData data { NotificationType : : BBLSliceEmptyLayer , NotificationLevel : : WarningNotificationLevel , 0 , _u8L ( " WARNING: " ) + " \n " + text } ;
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : BBLSliceEmptyLayer ) {
if ( bOverride )
notification - > update ( data ) ;
else {
NotificationData sdata { NotificationType : : BBLSliceEmptyLayer , NotificationLevel : : WarningNotificationLevel , 0 , notification - > get_text1 ( ) + " \n " + text } ;
notification - > update ( sdata ) ;
}
return ;
}
}
auto notification = std : : make_unique < NotificationManager : : PopNotification > ( data , m_id_provider , m_evt_handler ) ;
notification - > set_Multiline ( true ) ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : bbl_show_app_newversion_notification ( )
{
push_notification ( NotificationType : : NewAppAvailable ) ;
}
void NotificationManager : : bbl_show_need_support_on_notification ( )
{
NotificationData data { NotificationType : : BBLNeedSupportON , NotificationLevel : : WarningNotificationLevel , 0 , _u8L ( " Warning: " ) + " \n " + _u8L ( " Your model needs support ! Please make support material enable. " ) } ;
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : BBLNeedSupportON ) {
notification - > reinit ( ) ;
notification - > update ( data ) ;
return ;
}
}
auto notification = std : : make_unique < NotificationManager : : PopNotification > ( data , m_id_provider , m_evt_handler ) ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : bbl_close_need_support_on_notification ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : BBLNeedSupportON ) { notification - > close ( ) ; }
}
void NotificationManager : : bbl_show_gcode_overlap_notification ( )
{
NotificationData data { NotificationType : : BBLGcodeOverlap , NotificationLevel : : WarningNotificationLevel , 0 ,
_u8L ( " Warning: " ) + " \n " + _u8L ( " Gcode path overlap " ) } ;
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = NotificationType : : BBLGcodeOverlap ) {
notification - > reinit ( ) ;
notification - > update ( data ) ;
return ;
}
}
auto notification = std : : make_unique < NotificationManager : : PopNotification > ( data , m_id_provider , m_evt_handler ) ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : bbl_close_gcode_overlap_notification ( )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = NotificationType : : BBLGcodeOverlap ) { notification - > close ( ) ; }
}
void NotificationManager : : bbl_show_sole_text_notification ( NotificationType sType , const std : : string & text , bool bOverride , int level , bool autohide ) {
NotificationLevel nlevel ;
int nHideTime = 20 ;
switch ( level ) {
case 1 :
nlevel = NotificationLevel : : WarningNotificationLevel ;
nHideTime = 0 ;
break ;
case 2 :
nlevel = NotificationLevel : : ErrorNotificationLevel ; break ;
nHideTime = 0 ;
case 0 :
default :
nlevel = NotificationLevel : : PrintInfoNotificationLevel ;
2022-07-22 09:46:10 +00:00
if ( autohide = = false ) nHideTime = BBL_NOTICE_MAX_INTERVAL ;
2022-07-15 15:37:19 +00:00
break ;
}
NotificationData data { sType , nlevel , nHideTime , text } ;
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications ) {
if ( notification - > get_type ( ) = = sType ) {
if ( bOverride ) {
notification - > update ( data ) ;
}
else {
NotificationData sdata { sType , nlevel , nHideTime , notification - > get_text1 ( ) + " \n " + text } ;
notification - > update ( sdata ) ;
}
return ;
}
}
auto notification = std : : make_unique < NotificationManager : : PopNotification > ( data , m_id_provider , m_evt_handler ) ;
notification - > set_Multiline ( true ) ;
push_notification_data ( std : : move ( notification ) , 0 ) ;
}
void NotificationManager : : bbl_chose_sole_text_notification ( NotificationType sType )
{
for ( std : : unique_ptr < PopNotification > & notification : m_pop_notifications )
if ( notification - > get_type ( ) = = sType ) { notification - > close ( ) ; }
}
void NotificationManager : : set_scale ( float scale )
{
if ( m_scale ! = scale ) m_scale = scale ;
}
} //namespace GUI
} //namespace Slic3r