Merge branch 'dk_notifications'
This commit is contained in:
commit
98b5397245
13 changed files with 723 additions and 366 deletions
67
resources/icons/notification_cancel.svg
Normal file
67
resources/icons/notification_cancel.svg
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 800 800"
|
||||
style="enable-background:new 0 0 800 800;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="notification_cancel.svg"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"><metadata
|
||||
id="metadata15"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs13" /><sodipodi:namedview
|
||||
inkscape:document-rotation="0"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2066"
|
||||
id="namedview11"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.26"
|
||||
inkscape:cx="400"
|
||||
inkscape:cy="389.28571"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{fill:#ED6B21;}
|
||||
</style>
|
||||
|
||||
|
||||
<g
|
||||
id="g4"
|
||||
transform="matrix(0.9775,0,0,0.9775,53.547,53.54775)">
|
||||
<path
|
||||
id="path2"
|
||||
class="st0"
|
||||
d="M 597.2,701.3 H 110.6 C 53.2,701.3 6.5,654.6 6.5,597.2 V 110.6 C 6.5,53.2 53.2,6.5 110.6,6.5 h 486.6 c 57.4,0 104.1,46.7 104.1,104.1 v 486.6 c 0,57.4 -46.7,104.1 -104.1,104.1 z M 110.6,52.4 c -32,0 -58.2,26 -58.2,58.2 v 486.6 c 0,32 26,58.2 58.2,58.2 h 486.6 c 32,0 58.2,-26 58.2,-58.2 V 110.6 c 0,-32 -26,-58.2 -58.2,-58.2 z" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.674603"
|
||||
d="m 150.65676,738.12999 c -12.4717,-1.39663 -26.66772,-5.94192 -37.84321,-12.11671 -17.754551,-9.80992 -33.768844,-26.68981 -42.418124,-44.71089 -5.985061,-12.4701 -8.760227,-23.35456 -9.821918,-38.52249 -0.48061,-6.8663 -0.640464,-87.42616 -0.497289,-250.61508 0.195544,-222.88027 0.294923,-240.94223 1.356742,-246.58759 4.2349,-22.51562 13.68014,-40.62012 29.200931,-55.97194 14.237938,-14.082924 31.958648,-23.427941 52.602238,-27.739791 5.87892,-1.227937 14.00696,-1.268146 256.3492,-1.268146 h 250.27778 l 7.08334,1.561512 c 21.30688,4.697075 36.90336,13.216072 51.96052,28.381502 14.67865,14.784203 23.1932,30.350373 27.76125,50.752683 l 1.56791,7.00271 v 250.95239 c 0,242.72256 -0.0418,251.15149 -1.26428,257.0238 -9.30592,44.69034 -45.18963,77.43352 -89.75566,81.90028 -9.17898,0.92002 -488.33076,0.87927 -496.55943,-0.0425 z M 652.87275,692.49 c 19.93824,-6.17834 34.6922,-21.42493 40.00111,-41.33675 l 1.51306,-5.67494 V 399.58544 153.69259 l -1.52571,-5.73412 c -5.66288,-21.28292 -21.4158,-36.89778 -42.2051,-41.83523 -5.63965,-1.33941 -7.66026,-1.3488 -253.17948,-1.17613 l -247.49447,0.17405 -4.72222,1.5953 c -18.05932,6.10093 -31.7315,19.23923 -37.4918,36.0278 -1.04762,3.05333 -2.22128,7.52472 -2.60813,9.93642 -0.47859,2.9836 -0.705,81.91876 -0.70847,246.99889 -0.005,218.14117 0.10226,243.1829 1.05916,248.25397 4.27172,22.63802 22.24346,40.86392 44.80877,45.4425 3.58848,0.72811 49.16893,0.87009 250.95237,0.78171 l 246.56747,-0.10801 z"
|
||||
id="path17" /><rect
|
||||
y="239.60318"
|
||||
x="240.87302"
|
||||
height="321.58731"
|
||||
width="322.22223"
|
||||
id="rect30"
|
||||
style="fill:#ed6b21;stroke-width:0.4" /></svg>
|
After Width: | Height: | Size: 3.6 KiB |
67
resources/icons/notification_cancel_hover.svg
Normal file
67
resources/icons/notification_cancel_hover.svg
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 800 800"
|
||||
style="enable-background:new 0 0 800 800;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="notification_cancel_hover.svg"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"><metadata
|
||||
id="metadata15"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs13" /><sodipodi:namedview
|
||||
inkscape:document-rotation="0"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2066"
|
||||
id="namedview11"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.26"
|
||||
inkscape:cx="400"
|
||||
inkscape:cy="389.28571"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{fill:#ED6B21;}
|
||||
</style>
|
||||
|
||||
|
||||
<g
|
||||
id="g4"
|
||||
transform="matrix(1.173,0,0,1.173,-15.64045,-15.6397)">
|
||||
<path
|
||||
id="path2"
|
||||
class="st0"
|
||||
d="M 597.2,701.3 H 110.6 C 53.2,701.3 6.5,654.6 6.5,597.2 V 110.6 C 6.5,53.2 53.2,6.5 110.6,6.5 h 486.6 c 57.4,0 104.1,46.7 104.1,104.1 v 486.6 c 0,57.4 -46.7,104.1 -104.1,104.1 z M 110.6,52.4 c -32,0 -58.2,26 -58.2,58.2 v 486.6 c 0,32 26,58.2 58.2,58.2 h 486.6 c 32,0 58.2,-26 58.2,-58.2 V 110.6 c 0,-32 -26,-58.2 -58.2,-58.2 z" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.809524"
|
||||
d="M 100.89126,805.85899 C 85.925222,804.18303 68.889998,798.72868 55.47941,791.31894 34.173949,779.54703 14.956797,759.29116 4.5776612,737.66587 -2.604412,722.70175 -5.9346112,709.6404 -7.2086404,691.43888 -7.7853724,683.19932 -7.9771972,586.52749 -7.8053872,390.70078 -7.5707344,123.24446 -7.4514796,101.57011 -6.1772968,94.795676 -1.0954168,67.776932 10.238871,46.051532 28.86382,27.629348 45.949346,10.729839 67.214198,-0.4841812 91.986506,-5.6584012 99.04121,-7.1319256 108.79486,-7.1801764 399.60555,-7.1801764 h 300.33333 l 8.50001,1.8738144 c 25.56826,5.63649 44.28403,15.859286 62.35262,34.057802 17.61438,17.741044 27.83184,36.420448 33.3135,60.90322 l 1.8815,8.403252 V 399.20078 c 0,291.26707 -0.0502,301.38179 -1.51714,308.42856 -11.1671,53.62841 -54.22756,92.92022 -107.70679,98.28034 -11.01478,1.10402 -585.99691,1.05512 -595.87132,-0.051 z M 703.55045,751.091 c 23.92589,-7.41401 41.63064,-25.70992 48.00133,-49.6041 l 1.81567,-6.80993 V 399.60553 104.53411 L 751.5366,97.653164 C 744.74115,72.11366 725.83764,53.375828 700.89048,47.450888 694.1229,45.843596 691.69817,45.832328 397.07511,46.039532 l -296.99337,0.20886 -5.666662,1.91436 c -21.671184,7.321116 -38.0778,23.087076 -44.99016,43.23336 -1.257144,3.663996 -2.665536,9.029668 -3.129756,11.923708 -0.574308,3.58032 -0.846,98.30251 -0.850164,296.39866 -0.006,261.76941 0.122712,291.81948 1.270992,297.90477 5.126064,27.16562 26.692152,49.0367 53.77052,54.531 4.30618,0.87373 59.00272,1.04411 301.14285,0.93805 l 295.88096,-0.12961 z"
|
||||
id="path17" /><rect
|
||||
y="207.62682"
|
||||
x="209.15077"
|
||||
height="385.90479"
|
||||
width="386.66669"
|
||||
id="rect30"
|
||||
style="fill:#ed6b21;stroke-width:0.48" /></svg>
|
After Width: | Height: | Size: 3.7 KiB |
|
@ -123,6 +123,8 @@ namespace ImGui
|
|||
const char ErrorMarker = 0x11;
|
||||
const char EjectButton = 0x12;
|
||||
const char EjectHoverButton = 0x13;
|
||||
const char CancelButton = 0x14;
|
||||
const char CancelHoverButton = 0x15;
|
||||
// void MyFunction(const char* name, const MyMatrix44& v);
|
||||
|
||||
}
|
||||
|
|
|
@ -845,6 +845,57 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
|
|||
return contained_min_one;
|
||||
}
|
||||
|
||||
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, bool& partlyOut, bool& fullyOut)
|
||||
{
|
||||
if (config == nullptr)
|
||||
return false;
|
||||
|
||||
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config->option("bed_shape"));
|
||||
if (opt == nullptr)
|
||||
return false;
|
||||
|
||||
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
|
||||
BoundingBoxf3 print_volume(Vec3d(unscale<double>(bed_box_2D.min(0)), unscale<double>(bed_box_2D.min(1)), 0.0), Vec3d(unscale<double>(bed_box_2D.max(0)), unscale<double>(bed_box_2D.max(1)), config->opt_float("max_print_height")));
|
||||
// Allow the objects to protrude below the print bed
|
||||
print_volume.min(2) = -1e10;
|
||||
print_volume.min(0) -= BedEpsilon;
|
||||
print_volume.min(1) -= BedEpsilon;
|
||||
print_volume.max(0) += BedEpsilon;
|
||||
print_volume.max(1) += BedEpsilon;
|
||||
|
||||
bool contained_min_one = false;
|
||||
|
||||
partlyOut = false;
|
||||
fullyOut = false;
|
||||
for (GLVolume* volume : this->volumes)
|
||||
{
|
||||
if ((volume == nullptr) || volume->is_modifier || (volume->is_wipe_tower && !volume->shader_outside_printer_detection_enabled) || ((volume->composite_id.volume_id < 0) && !volume->shader_outside_printer_detection_enabled))
|
||||
continue;
|
||||
|
||||
const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box();
|
||||
bool contained = print_volume.contains(bb);
|
||||
|
||||
volume->is_outside = !contained;
|
||||
if (!volume->printable)
|
||||
continue;
|
||||
|
||||
if (contained)
|
||||
contained_min_one = true;
|
||||
|
||||
if (volume->is_outside) {
|
||||
if (print_volume.intersects(bb))
|
||||
partlyOut = true;
|
||||
else
|
||||
fullyOut = true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (out_state != nullptr)
|
||||
*out_state = state;
|
||||
*/
|
||||
return contained_min_one;
|
||||
}
|
||||
|
||||
void GLVolumeCollection::reset_outside_state()
|
||||
{
|
||||
for (GLVolume* volume : this->volumes)
|
||||
|
|
|
@ -569,6 +569,7 @@ public:
|
|||
// returns true if all the volumes are completely contained in the print volume
|
||||
// returns the containment state in the given out_state, if non-null
|
||||
bool check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state);
|
||||
bool check_outside_state(const DynamicPrintConfig* config, bool& partlyOut, bool& fullyOut);
|
||||
void reset_outside_state();
|
||||
|
||||
void update_colors_by_extruder(const DynamicPrintConfig* config);
|
||||
|
|
|
@ -641,6 +641,7 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool
|
|||
error = true;
|
||||
break;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(error) << state << " : " << text ;
|
||||
auto ¬ification_manager = *wxGetApp().plater()->get_notification_manager();
|
||||
if (state) {
|
||||
if(error)
|
||||
|
@ -1620,9 +1621,6 @@ void GLCanvas3D::render()
|
|||
wxGetApp().plater()->init_environment_texture();
|
||||
#endif // ENABLE_ENVIRONMENT_MAP
|
||||
|
||||
m_render_timer.Stop();
|
||||
m_extra_frame_requested_delayed = std::numeric_limits<int>::max();
|
||||
|
||||
const Size& cnv_size = get_canvas_size();
|
||||
// Probably due to different order of events on Linux/GTK2, when one switched from 3D scene
|
||||
// to preview, this was called before canvas had its final size. It reported zero width
|
||||
|
@ -1754,7 +1752,7 @@ void GLCanvas3D::render()
|
|||
m_tooltip.render(m_mouse.position, *this);
|
||||
|
||||
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this);
|
||||
wxGetApp().plater()->get_notification_manager()->render_notifications(get_overlay_window_width());
|
||||
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width());
|
||||
|
||||
wxGetApp().imgui()->render();
|
||||
|
||||
|
@ -2238,24 +2236,24 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
|
||||
// checks for geometry outside the print volume to render it accordingly
|
||||
if (!m_volumes.empty()) {
|
||||
ModelInstanceEPrintVolumeState state;
|
||||
|
||||
const bool contained_min_one = m_volumes.check_outside_state(m_config, &state);
|
||||
bool partlyOut = false;
|
||||
bool fullyOut = false;
|
||||
const bool contained_min_one = m_volumes.check_outside_state(m_config, partlyOut, fullyOut);
|
||||
|
||||
#if ENABLE_WARNING_TEXTURE_REMOVAL
|
||||
_set_warning_notification(EWarning::ObjectClashed, state == ModelInstancePVS_Partly_Outside);
|
||||
_set_warning_notification(EWarning::ObjectOutside, state == ModelInstancePVS_Fully_Outside);
|
||||
if (printer_technology != ptSLA || state == ModelInstancePVS_Inside)
|
||||
_set_warning_notification(EWarning::ObjectClashed, partlyOut);
|
||||
_set_warning_notification(EWarning::ObjectOutside, fullyOut);
|
||||
if (printer_technology != ptSLA || !contained_min_one)
|
||||
_set_warning_notification(EWarning::SlaSupportsOutside, false);
|
||||
#else
|
||||
_set_warning_texture(WarningTexture::ObjectClashed, state == ModelInstancePVS_Partly_Outside);
|
||||
_set_warning_texture(WarningTexture::ObjectOutside, state == ModelInstancePVS_Fully_Outside);
|
||||
if(printer_technology != ptSLA || state == ModelInstancePVS_Inside)
|
||||
_set_warning_texture(WarningTexture::ObjectClashed, partlyOut);
|
||||
_set_warning_texture(WarningTexture::ObjectOutside, fullyOut);
|
||||
if(printer_technology != ptSLA || !contained_min_one)
|
||||
_set_warning_texture(WarningTexture::SlaSupportsOutside, false);
|
||||
#endif // ENABLE_WARNING_TEXTURE_REMOVAL
|
||||
|
||||
post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS,
|
||||
contained_min_one && !m_model->objects.empty() && state != ModelInstancePVS_Partly_Outside));
|
||||
contained_min_one && !m_model->objects.empty() && !partlyOut));
|
||||
}
|
||||
else {
|
||||
#if ENABLE_WARNING_TEXTURE_REMOVAL
|
||||
|
@ -2442,13 +2440,13 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
|||
if (!m_initialized)
|
||||
return;
|
||||
|
||||
// FIXME
|
||||
m_dirty |= m_main_toolbar.update_items_state();
|
||||
m_dirty |= m_undoredo_toolbar.update_items_state();
|
||||
m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state();
|
||||
m_dirty |= wxGetApp().plater()->get_collapse_toolbar().update_items_state();
|
||||
bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera());
|
||||
m_dirty |= mouse3d_controller_applied;
|
||||
m_dirty |= wxGetApp().plater()->get_notification_manager()->update_notifications(*this);
|
||||
|
||||
if (!m_dirty)
|
||||
return;
|
||||
|
@ -2982,30 +2980,39 @@ void GLCanvas3D::on_timer(wxTimerEvent& evt)
|
|||
|
||||
void GLCanvas3D::on_render_timer(wxTimerEvent& evt)
|
||||
{
|
||||
// If slicer is not top window -> restart timer with one second to try again
|
||||
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()) {
|
||||
request_extra_frame_delayed(1000);
|
||||
return;
|
||||
}
|
||||
//render();
|
||||
m_dirty = true;
|
||||
wxWakeUpIdle();
|
||||
// no need to do anything here
|
||||
// right after this event is recieved, idle event is fired
|
||||
|
||||
//m_dirty = true;
|
||||
//wxWakeUpIdle();
|
||||
}
|
||||
|
||||
void GLCanvas3D::request_extra_frame_delayed(int miliseconds)
|
||||
|
||||
void GLCanvas3D::schedule_extra_frame(int miliseconds)
|
||||
{
|
||||
// Schedule idle event right now
|
||||
if (miliseconds == 0)
|
||||
{
|
||||
// We want to wakeup idle evnt but most likely this is call inside render cycle so we need to wait
|
||||
if (m_in_render)
|
||||
miliseconds = 33;
|
||||
else {
|
||||
m_dirty = true;
|
||||
wxWakeUpIdle();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Start timer
|
||||
int64_t now = timestamp_now();
|
||||
// Timer is not running
|
||||
if (! m_render_timer.IsRunning()) {
|
||||
m_extra_frame_requested_delayed = miliseconds;
|
||||
m_render_timer.StartOnce(miliseconds);
|
||||
m_render_timer_start = now;
|
||||
// Timer is running - restart only if new period is shorter than remaning period
|
||||
} else {
|
||||
const int64_t remaining_time = (m_render_timer_start + m_extra_frame_requested_delayed) - now;
|
||||
if (miliseconds < remaining_time) {
|
||||
if (miliseconds + 20 < remaining_time) {
|
||||
m_render_timer.Stop();
|
||||
m_extra_frame_requested_delayed = miliseconds;
|
||||
m_render_timer.StartOnce(miliseconds);
|
||||
|
|
|
@ -743,7 +743,8 @@ public:
|
|||
void msw_rescale();
|
||||
|
||||
void request_extra_frame() { m_extra_frame_requested = true; }
|
||||
void request_extra_frame_delayed(int miliseconds);
|
||||
|
||||
void schedule_extra_frame(int miliseconds);
|
||||
|
||||
int get_main_toolbar_item_id(const std::string& name) const { return m_main_toolbar.get_item_id(name); }
|
||||
void force_main_toolbar_left_action(int item_id) { m_main_toolbar.force_left_action(item_id, *this); }
|
||||
|
|
|
@ -1978,6 +1978,11 @@ wxNotebook* GUI_App::tab_panel() const
|
|||
return mainframe->m_tabpanel;
|
||||
}
|
||||
|
||||
NotificationManager* GUI_App::notification_manager()
|
||||
{
|
||||
return plater_->get_notification_manager();
|
||||
}
|
||||
|
||||
// extruders count from selected printer preset
|
||||
int GUI_App::extruders_cnt() const
|
||||
{
|
||||
|
|
|
@ -43,6 +43,7 @@ class ObjectSettings;
|
|||
class ObjectList;
|
||||
class ObjectLayers;
|
||||
class Plater;
|
||||
class NotificationManager;
|
||||
struct GUI_InitParams;
|
||||
|
||||
|
||||
|
@ -226,14 +227,14 @@ public:
|
|||
void MacOpenFiles(const wxArrayString &fileNames) override;
|
||||
#endif /* __APPLE */
|
||||
|
||||
Sidebar& sidebar();
|
||||
ObjectManipulation* obj_manipul();
|
||||
ObjectSettings* obj_settings();
|
||||
ObjectList* obj_list();
|
||||
ObjectLayers* obj_layers();
|
||||
Plater* plater();
|
||||
Model& model();
|
||||
|
||||
Sidebar& sidebar();
|
||||
ObjectManipulation* obj_manipul();
|
||||
ObjectSettings* obj_settings();
|
||||
ObjectList* obj_list();
|
||||
ObjectLayers* obj_layers();
|
||||
Plater* plater();
|
||||
Model& model();
|
||||
NotificationManager* notification_manager();
|
||||
|
||||
// Parameters extracted from the command line to be passed to GUI after initialization.
|
||||
const GUI_InitParams* init_params { nullptr };
|
||||
|
|
|
@ -51,7 +51,9 @@ static const std::map<const char, std::string> font_icons_large = {
|
|||
{ImGui::EjectButton , "notification_eject_sd" },
|
||||
{ImGui::EjectHoverButton , "notification_eject_sd_hover" },
|
||||
{ImGui::WarningMarker , "notification_warning" },
|
||||
{ImGui::ErrorMarker , "notification_error" }
|
||||
{ImGui::ErrorMarker , "notification_error" },
|
||||
{ImGui::CancelButton , "notification_cancel" },
|
||||
{ImGui::CancelHoverButton , "notification_cancel_hover" },
|
||||
};
|
||||
|
||||
const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.333f, 0.333f, 0.333f, 1.0f };
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Plater.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#include "ImGuiWrapper.hpp"
|
||||
#include "PrintHostDialogs.hpp"
|
||||
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
|
@ -22,9 +23,6 @@ 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;
|
||||
// If timeout is changed to higher than 1 second, substract_time call should be revorked
|
||||
//static constexpr int MAX_TIMEOUT_MILISECONDS = 1000;
|
||||
//static constexpr int MAX_TIMEOUT_SECONDS = 1;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -131,35 +129,29 @@ void NotificationManager::NotificationIDProvider::release_id(int) {}
|
|||
NotificationManager::PopNotification::PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler) :
|
||||
m_data (n)
|
||||
, m_id_provider (id_provider)
|
||||
, m_remaining_time (n.duration)
|
||||
, m_last_remaining_time (n.duration)
|
||||
, m_counting_down (n.duration != 0)
|
||||
, m_text1 (n.text1)
|
||||
, m_hypertext (n.hypertext)
|
||||
, m_text2 (n.text2)
|
||||
, m_evt_handler (evt_handler)
|
||||
, m_notification_start (GLCanvas3D::timestamp_now())
|
||||
{
|
||||
//init();
|
||||
}
|
||||
{}
|
||||
|
||||
void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width)
|
||||
{
|
||||
if (!m_initialized)
|
||||
|
||||
if (m_state == EState::Unknown)
|
||||
init();
|
||||
|
||||
if (m_hidden) {
|
||||
if (m_state == EState::Hidden) {
|
||||
m_top_y = initial_y - GAP_WIDTH;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_fading_out)
|
||||
m_last_render_fading = GLCanvas3D::timestamp_now();
|
||||
|
||||
Size cnv_size = canvas.get_canvas_size();
|
||||
Size cnv_size = canvas.get_canvas_size();
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
ImVec2 mouse_pos = ImGui::GetMousePos();
|
||||
float right_gap = SPACE_RIGHT_PANEL + (move_from_overlay ? overlay_width + m_line_height * 5 : 0);
|
||||
ImVec2 mouse_pos = ImGui::GetMousePos();
|
||||
float right_gap = SPACE_RIGHT_PANEL + (move_from_overlay ? overlay_width + m_line_height * 5 : 0);
|
||||
bool fading_pop = false;
|
||||
|
||||
if (m_line_height != ImGui::CalcTextSize("A").y)
|
||||
init();
|
||||
|
@ -174,54 +166,46 @@ void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float init
|
|||
imgui.set_next_window_size(m_window_width, m_window_height, ImGuiCond_Always);
|
||||
|
||||
// find if hovered
|
||||
m_hovered = false;
|
||||
if (m_state == EState::Hovered)
|
||||
m_state = EState::Shown;
|
||||
|
||||
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) {
|
||||
ImGui::SetNextWindowFocus();
|
||||
m_hovered = true;
|
||||
m_state = EState::Hovered;
|
||||
}
|
||||
|
||||
|
||||
// color change based on fading out
|
||||
bool fading_pop = false;
|
||||
if (m_fading_out) {
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text), m_fading_out, m_current_fade_opacity);
|
||||
if (m_state == EState::FadingOut) {
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), true, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text), true, m_current_fade_opacity);
|
||||
fading_pop = true;
|
||||
}
|
||||
|
||||
|
||||
// background color
|
||||
if (m_is_gray) {
|
||||
ImVec4 backcolor(0.7f, 0.7f, 0.7f, 0.5f);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
}
|
||||
else if (m_data.level == NotificationLevel::ErrorNotification) {
|
||||
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
|
||||
backcolor.x += 0.3f;
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
}
|
||||
else if (m_data.level == NotificationLevel::WarningNotification) {
|
||||
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
|
||||
backcolor.x += 0.3f;
|
||||
backcolor.y += 0.15f;
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
}
|
||||
|
||||
// name of window - probably indentifies window and is shown so last_end add whitespaces according to id
|
||||
|
||||
// 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);
|
||||
|
||||
if (imgui.begin(name, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar)) {
|
||||
ImVec2 win_size = ImGui::GetWindowSize();
|
||||
|
||||
//FIXME: dont forget to us this for texts
|
||||
//GUI::format(_utf8(L()));
|
||||
|
||||
/*
|
||||
//countdown numbers
|
||||
ImGui::SetCursorPosX(15);
|
||||
ImGui::SetCursorPosY(15);
|
||||
imgui.text(std::to_string(m_remaining_time).c_str());
|
||||
*/
|
||||
|
||||
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);
|
||||
|
@ -253,6 +237,7 @@ void NotificationManager::PopNotification::count_spaces()
|
|||
m_window_width_offset = m_left_indentation + m_line_height * 3.f;
|
||||
m_window_width = m_line_height * 25;
|
||||
}
|
||||
|
||||
void NotificationManager::PopNotification::init()
|
||||
{
|
||||
std::string text = m_text1 + " " + m_hypertext;
|
||||
|
@ -306,7 +291,7 @@ void NotificationManager::PopNotification::init()
|
|||
}
|
||||
if (m_lines_count == 3)
|
||||
m_multiline = true;
|
||||
m_initialized = true;
|
||||
m_state = EState::Shown;
|
||||
}
|
||||
void NotificationManager::PopNotification::set_next_window_size(ImGuiWrapper& imgui)
|
||||
{
|
||||
|
@ -375,12 +360,14 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
|
|||
ImGui::SetCursorPosY(win_size.y / 2 - win_size.y / 6 - m_line_height / 2);
|
||||
imgui.text(m_text1.substr(0, m_endlines[0]).c_str());
|
||||
// line2
|
||||
std::string line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
|
||||
cursor_y = win_size.y / 2 + win_size.y / 6 - m_line_height / 2;
|
||||
ImGui::SetCursorPosX(x_offset);
|
||||
ImGui::SetCursorPosY(cursor_y);
|
||||
imgui.text(line.c_str());
|
||||
cursor_x = x_offset + ImGui::CalcTextSize(line.c_str()).x;
|
||||
if (m_text1.length() > m_endlines[0]) {
|
||||
std::string line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
|
||||
cursor_y = win_size.y / 2 + win_size.y / 6 - m_line_height / 2;
|
||||
ImGui::SetCursorPosX(x_offset);
|
||||
ImGui::SetCursorPosY(cursor_y);
|
||||
imgui.text(line.c_str());
|
||||
cursor_x = x_offset + ImGui::CalcTextSize(line.c_str()).x;
|
||||
}
|
||||
} else {
|
||||
ImGui::SetCursorPosX(x_offset);
|
||||
ImGui::SetCursorPosY(cursor_y);
|
||||
|
@ -423,8 +410,8 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
|
|||
m_multiline = true;
|
||||
set_next_window_size(imgui);
|
||||
}
|
||||
else {
|
||||
m_close_pending = on_text_click();
|
||||
else if (on_text_click()) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
@ -432,12 +419,12 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
|
|||
ImGui::PopStyleColor();
|
||||
|
||||
//hover color
|
||||
ImVec4 orange_color = ImVec4(.99f, .313f, .0f, 1.0f);//ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
||||
ImVec4 orange_color = ImVec4(.99f, .313f, .0f, 1.0f);
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly))
|
||||
orange_color.y += 0.2f;
|
||||
|
||||
//text
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, orange_color, m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, orange_color, m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
ImGui::SetCursorPosX(text_x);
|
||||
ImGui::SetCursorPosY(text_y);
|
||||
imgui.text(text.c_str());
|
||||
|
@ -448,7 +435,7 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
|
|||
lineEnd.y -= 2;
|
||||
ImVec2 lineStart = lineEnd;
|
||||
lineStart.x = ImGui::GetItemRectMin().x;
|
||||
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (int)(orange_color.w * 255.f * (m_fading_out ? m_current_fade_opacity : 1.f))));
|
||||
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (int)(orange_color.w * 255.f * (m_state == EState::FadingOut ? m_current_fade_opacity : 1.f))));
|
||||
|
||||
}
|
||||
|
||||
|
@ -458,12 +445,11 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
|
|||
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));
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
Notifications_Internal::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));
|
||||
|
||||
|
||||
//button - if part if treggered
|
||||
std::string button_text;
|
||||
button_text = ImGui::CloseNotifButton;
|
||||
|
||||
|
@ -479,7 +465,7 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
|
|||
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
|
||||
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
|
||||
{
|
||||
m_close_pending = true;
|
||||
close();
|
||||
}
|
||||
|
||||
//invisible large button
|
||||
|
@ -487,7 +473,7 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
|
|||
ImGui::SetCursorPosY(0);
|
||||
if (imgui.button(" ", m_line_height * 2.125, win_size.y - ( m_minimize_b_visible ? 2 * m_line_height : 0)))
|
||||
{
|
||||
m_close_pending = true;
|
||||
close();
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
|
@ -510,9 +496,9 @@ void NotificationManager::PopNotification::render_minimize_button(ImGuiWrapper&
|
|||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
|
||||
Notifications_Internal::push_style_color(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
|
||||
|
||||
//button - if part if treggered
|
||||
|
@ -564,71 +550,62 @@ bool NotificationManager::PopNotification::compare_text(const std::string& text)
|
|||
return false;
|
||||
}
|
||||
|
||||
void NotificationManager::PopNotification::update_state()
|
||||
bool NotificationManager::PopNotification::update_state(bool paused, const int64_t delta)
|
||||
{
|
||||
if (!m_initialized)
|
||||
init();
|
||||
|
||||
m_next_render = std::numeric_limits<int64_t>::max();
|
||||
|
||||
if (m_hidden) {
|
||||
m_state = EState::Hidden;
|
||||
return;
|
||||
if (m_state == EState::Unknown) {
|
||||
init();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_state == EState::Hidden) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t now = GLCanvas3D::timestamp_now();
|
||||
|
||||
if (m_hovered) {
|
||||
// reset fading
|
||||
m_fading_out = false;
|
||||
// reset timers - hovered state is set in render
|
||||
if (m_state == EState::Hovered) {
|
||||
m_current_fade_opacity = 1.0f;
|
||||
m_remaining_time = m_data.duration;
|
||||
m_notification_start = now;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (m_counting_down) {
|
||||
// Timers when not fading
|
||||
} else if (m_state != EState::FadingOut && m_data.duration != 0 && !paused) {
|
||||
int64_t up_time = now - m_notification_start;
|
||||
if (up_time >= m_data.duration * 1000) {
|
||||
m_state = EState::FadingOut;
|
||||
m_fading_start = now;
|
||||
} else {
|
||||
m_next_render = m_data.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_fading_out && m_current_fade_opacity <= 0.0f)
|
||||
m_finished = true;
|
||||
else if (!m_fading_out && /*m_remaining_time <=0*/up_time >= m_data.duration * 1000) {
|
||||
m_fading_out = true;
|
||||
m_fading_start = now;
|
||||
m_last_render_fading = now;
|
||||
} else if (!m_fading_out) {
|
||||
m_next_render = m_data.duration * 1000 - up_time;//std::min<int64_t>(/*m_data.duration * 1000 - up_time*/m_remaining_time * 1000, MAX_TIMEOUT_MILISECONDS);
|
||||
}
|
||||
|
||||
if (m_state == EState::Finished) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_finished) {
|
||||
|
||||
if (m_state == EState::ClosePending) {
|
||||
m_state = EState::Finished;
|
||||
m_next_render = 0;
|
||||
return;
|
||||
}
|
||||
if (m_close_pending) {
|
||||
m_finished = true;
|
||||
m_state = EState::ClosePending;
|
||||
m_next_render = 0;
|
||||
return;
|
||||
}
|
||||
if (m_fading_out) {
|
||||
if (!m_paused) {
|
||||
m_state = EState::FadingOutStatic;
|
||||
int64_t curr_time = now - m_fading_start;
|
||||
int64_t no_render_time = now - m_last_render_fading;
|
||||
m_current_fade_opacity = std::clamp(1.0f - 0.001f * static_cast<float>(curr_time) / FADING_OUT_DURATION, 0.0f, 1.0f);
|
||||
auto next_render = FADING_OUT_TIMEOUT - no_render_time;
|
||||
if (next_render <= 0) {
|
||||
//m_last_render_fading = GLCanvas3D::timestamp_now();
|
||||
m_state = EState::FadingOutRender;
|
||||
m_next_render = 0;
|
||||
} else
|
||||
m_next_render = next_render;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NotificationManager::SlicingCompleteLargeNotification::SlicingCompleteLargeNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool large) :
|
||||
|
@ -672,9 +649,10 @@ void NotificationManager::SlicingCompleteLargeNotification::set_print_info(const
|
|||
void NotificationManager::SlicingCompleteLargeNotification::set_large(bool l)
|
||||
{
|
||||
m_is_large = l;
|
||||
m_counting_down = !l;
|
||||
//FIXME this information should not be lost (change m_data?)
|
||||
// m_counting_down = !l;
|
||||
m_hypertext = l ? _u8L("Export G-Code.") : std::string();
|
||||
m_hidden = !l;
|
||||
m_state = l ? EState::Shown : EState::Hidden;
|
||||
}
|
||||
//---------------ExportFinishedNotification-----------
|
||||
void NotificationManager::ExportFinishedNotification::count_spaces()
|
||||
|
@ -733,8 +711,8 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW
|
|||
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));
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_fading_out, m_current_fade_opacity);
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
Notifications_Internal::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;
|
||||
|
@ -768,7 +746,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW
|
|||
assert(m_evt_handler != nullptr);
|
||||
if (m_evt_handler != nullptr)
|
||||
wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED));
|
||||
m_close_pending = true;
|
||||
close();
|
||||
}
|
||||
|
||||
//invisible large button
|
||||
|
@ -779,7 +757,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW
|
|||
assert(m_evt_handler != nullptr);
|
||||
if (m_evt_handler != nullptr)
|
||||
wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED));
|
||||
m_close_pending = true;
|
||||
close();
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
|
@ -799,30 +777,157 @@ void NotificationManager::ProgressBarNotification::init()
|
|||
m_lines_count++;
|
||||
m_endlines.push_back(m_endlines.back());
|
||||
}
|
||||
void NotificationManager::ProgressBarNotification::count_spaces()
|
||||
{
|
||||
//determine line width
|
||||
m_line_height = ImGui::CalcTextSize("A").y;
|
||||
|
||||
m_left_indentation = m_line_height;
|
||||
if (m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) {
|
||||
std::string text;
|
||||
text = (m_data.level == NotificationLevel::ErrorNotification ? 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_line_height * (m_has_cancel_button ? 6 : 4);
|
||||
m_window_width = m_line_height * 25;
|
||||
}
|
||||
|
||||
void NotificationManager::ProgressBarNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
PopNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||
// line1 - we do not print any more text than what fits on line 1. Line 2 is bar.
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 - win_size_y / 6 - m_line_height / 2);
|
||||
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);
|
||||
float invisible_length = 0;//((float)(m_data.duration - m_remaining_time) / (float)m_data.duration * win_size_x);
|
||||
//invisible_length -= win_size_x / ((float)m_data.duration * 60.f) * (60 - m_countdown_frame);
|
||||
ImVec2 lineEnd = ImVec2(win_pos_x - invisible_length - m_window_width_offset, win_pos_y + win_size_y/2 + m_line_height / 2);
|
||||
ImVec2 lineStart = ImVec2(win_pos_x - win_size_x + m_left_indentation, win_pos_y + win_size_y/2 + m_line_height / 2);
|
||||
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (1.0f * 255.f)), m_line_height * 0.7f);
|
||||
/*
|
||||
//countdown line
|
||||
ImVec4 orange_color = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
||||
float invisible_length = ((float)(m_data.duration - m_remaining_time) / (float)m_data.duration * win_size_x);
|
||||
invisible_length -= win_size_x / ((float)m_data.duration * 60.f) * (60 - m_countdown_frame);
|
||||
ImVec2 lineEnd = ImVec2(win_pos_x - invisible_length, win_pos_y + win_size_y - 5);
|
||||
ImVec2 lineStart = ImVec2(win_pos_x - win_size_x, win_pos_y + win_size_y - 5);
|
||||
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (int)(orange_color.picture_width * 255.f * (m_fading_out ? m_current_fade_opacity : 1.f))), 2.f);
|
||||
if (!m_paused)
|
||||
m_countdown_frame++;
|
||||
*/
|
||||
ImVec4 orange_color = ImVec4(.99f, .313f, .0f, 1.0f);
|
||||
ImVec4 gray_color = ImVec4(.34f, .34f, .34f, 1.0f);
|
||||
ImVec2 lineEnd = ImVec2(win_pos_x - m_window_width_offset, win_pos_y + win_size_y / 2 + m_line_height / 4);
|
||||
ImVec2 lineStart = ImVec2(win_pos_x - win_size_x + m_left_indentation, win_pos_y + win_size_y / 2 + m_line_height / 4);
|
||||
ImVec2 midPoint = ImVec2(lineStart.x + (lineEnd.x - lineStart.x) * m_percentage, lineStart.y);
|
||||
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(gray_color.x * 255), (int)(gray_color.y * 255), (int)(gray_color.z * 255), (1.0f * 255.f)), m_line_height * 0.2f);
|
||||
ImGui::GetWindowDrawList()->AddLine(lineStart, midPoint, IM_COL32((int)(orange_color.x * 255), (int)(orange_color.y * 255), (int)(orange_color.z * 255), (1.0f * 255.f)), m_line_height * 0.2f);
|
||||
}
|
||||
//------PrintHostUploadNotification----------------
|
||||
void NotificationManager::PrintHostUploadNotification::set_percentage(float percent)
|
||||
{
|
||||
if (m_uj_state == UploadJobState::PB_CANCELLED)
|
||||
return;
|
||||
m_percentage = percent;
|
||||
if (percent >= 1.0f) {
|
||||
m_uj_state = UploadJobState::PB_COMPLETED;
|
||||
m_has_cancel_button = false;
|
||||
} else if (percent < 0.0f) {
|
||||
error();
|
||||
} else {
|
||||
m_uj_state = UploadJobState::PB_PROGRESS;
|
||||
m_has_cancel_button = true;
|
||||
}
|
||||
}
|
||||
void NotificationManager::PrintHostUploadNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
std::string text;
|
||||
switch (m_uj_state) {
|
||||
case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_PROGRESS:
|
||||
{
|
||||
ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||
float uploaded = m_file_size / 100 * m_percentage;
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "% - " << uploaded << " of " << m_file_size << "MB uploaded";
|
||||
text = stream.str();
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 /*- m_line_height / 4 * 3*/);
|
||||
break;
|
||||
}
|
||||
case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_ERROR:
|
||||
text = _u8L("ERROR");
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - m_line_height / 2);
|
||||
break;
|
||||
case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_CANCELLED:
|
||||
text = _u8L("CANCELED");
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - m_line_height / 2);
|
||||
break;
|
||||
case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_COMPLETED:
|
||||
text = _u8L("COMPLETED");
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - m_line_height / 2);
|
||||
break;
|
||||
}
|
||||
|
||||
imgui.text(text.c_str());
|
||||
|
||||
}
|
||||
void NotificationManager::PrintHostUploadNotification::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));
|
||||
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
Notifications_Internal::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 - m_line_height * 5.f, win_pos.y),
|
||||
ImVec2(win_pos.x - m_line_height * 2.5f, win_pos.y + win_size.y),
|
||||
true))
|
||||
{
|
||||
button_text = ImGui::CancelHoverButton;
|
||||
// tooltip
|
||||
long time_now = wxGetLocalTime();
|
||||
if (m_hover_time > 0 && m_hover_time < time_now) {
|
||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
|
||||
ImGui::BeginTooltip();
|
||||
imgui.text(_u8L("Cancel upload") + " " + GUI::shortkey_ctrl_prefix() + "T");
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
if (m_hover_time == 0)
|
||||
m_hover_time = time_now;
|
||||
}
|
||||
else
|
||||
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) {
|
||||
auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_CANCEL, m_job_id, m_job_id);
|
||||
wxQueueEvent(m_evt_handler, evt);
|
||||
}
|
||||
}
|
||||
|
||||
//invisible large button
|
||||
ImGui::SetCursorPosX(win_size.x - m_line_height * 4.625f);
|
||||
ImGui::SetCursorPosY(0);
|
||||
if (imgui.button(" ", m_line_height * 2.f, win_size.y))
|
||||
{
|
||||
assert(m_evt_handler != nullptr);
|
||||
if (m_evt_handler != nullptr) {
|
||||
auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_CANCEL, m_job_id, m_job_id);
|
||||
wxQueueEvent(m_evt_handler, evt);
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
}
|
||||
//------NotificationManager--------
|
||||
NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
|
||||
|
@ -881,12 +986,7 @@ void NotificationManager::push_plater_error_notification(const std::string& text
|
|||
{
|
||||
push_notification_data({ NotificationType::PlaterError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, 0);
|
||||
}
|
||||
void NotificationManager::push_plater_warning_notification(const std::string& text)
|
||||
{
|
||||
push_notification_data({ NotificationType::PlaterWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text }, 0);
|
||||
// dissaper if in preview
|
||||
set_in_preview(m_in_preview);
|
||||
}
|
||||
|
||||
void NotificationManager::close_plater_error_notification(const std::string& text)
|
||||
{
|
||||
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
||||
|
@ -895,11 +995,32 @@ void NotificationManager::close_plater_error_notification(const std::string& tex
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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::WarningNotification, 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
|
||||
set_in_preview(m_in_preview);
|
||||
}
|
||||
|
||||
void NotificationManager::close_plater_warning_notification(const std::string& text)
|
||||
{
|
||||
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::PlaterWarning && notification->compare_text(_u8L("WARNING:") + "\n" + text)) {
|
||||
notification->close();
|
||||
dynamic_cast<PlaterWarningNotification*>(notification.get())->real_close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -997,23 +1118,50 @@ void NotificationManager::push_exporting_finished_notification(const std::string
|
|||
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotification, on_removable ? 0 : 20, _u8L("Exporting finished.") + "\n" + path };
|
||||
push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path), 0);
|
||||
}
|
||||
void NotificationManager::push_progress_bar_notification(const std::string& text, float percentage)
|
||||
|
||||
void NotificationManager::push_upload_job_notification(wxEvtHandler* evt_handler, int id, float filesize, const std::string& filename, const std::string& host, float percentage)
|
||||
{
|
||||
NotificationData data{ NotificationType::ProgressBar, NotificationLevel::ProgressBarNotification, 0, text };
|
||||
push_notification_data(std::make_unique<NotificationManager::ProgressBarNotification>(data, m_id_provider, m_evt_handler, 0), 0);
|
||||
std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host);
|
||||
NotificationData data{ NotificationType::PrintHostUpload, NotificationLevel::ProgressBarNotification, 0, text };
|
||||
push_notification_data(std::make_unique<NotificationManager::PrintHostUploadNotification>(data, m_id_provider, evt_handler, 0, id, filesize), 0);
|
||||
}
|
||||
void NotificationManager::set_progress_bar_percentage(const std::string& text, float percentage)
|
||||
void NotificationManager::set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage)
|
||||
{
|
||||
std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host);
|
||||
bool found = false;
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::ProgressBar && notification->compare_text(text)) {
|
||||
dynamic_cast<ProgressBarNotification*>(notification.get())->set_percentage(percentage);
|
||||
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame();
|
||||
dynamic_cast<PrintHostUploadNotification*>(notification.get())->set_percentage(percentage);
|
||||
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (!found) {
|
||||
push_progress_bar_notification(text, percentage);
|
||||
push_upload_job_notification(id, filename, host, percentage);
|
||||
}
|
||||
*/
|
||||
}
|
||||
void NotificationManager::upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host)
|
||||
{
|
||||
std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host);
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::PrintHostUpload && notification->compare_text(text)) {
|
||||
dynamic_cast<PrintHostUploadNotification*>(notification.get())->cancel();
|
||||
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void NotificationManager::upload_job_notification_show_error(int id, const std::string& filename, const std::string& host)
|
||||
{
|
||||
std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host);
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::PrintHostUpload && notification->compare_text(text)) {
|
||||
dynamic_cast<PrintHostUploadNotification*>(notification.get())->error();
|
||||
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool NotificationManager::push_notification_data(const NotificationData& notification_data, int timestamp)
|
||||
|
@ -1035,20 +1183,19 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
|
|||
|
||||
if (this->activate_existing(notification.get())) {
|
||||
m_pop_notifications.back()->update(notification->get_data());
|
||||
canvas.request_extra_frame_delayed(33);
|
||||
canvas.schedule_extra_frame(0);
|
||||
return false;
|
||||
} else {
|
||||
m_pop_notifications.emplace_back(std::move(notification));
|
||||
canvas.request_extra_frame_delayed(33);
|
||||
canvas.schedule_extra_frame(0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationManager::render_notifications(float overlay_width)
|
||||
void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay_width)
|
||||
{
|
||||
sort_notifications();
|
||||
|
||||
GLCanvas3D& canvas = *wxGetApp().plater()->get_current_canvas3D();
|
||||
|
||||
float last_y = 0.0f;
|
||||
|
||||
for (const auto& notification : m_pop_notifications) {
|
||||
|
@ -1059,7 +1206,49 @@ void NotificationManager::render_notifications(float overlay_width)
|
|||
}
|
||||
|
||||
}
|
||||
update_notifications();
|
||||
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;
|
||||
}
|
||||
|
||||
// request next frame in future
|
||||
if (next_render < max)
|
||||
canvas.schedule_extra_frame(int(next_render));
|
||||
|
||||
return request_render;
|
||||
}
|
||||
|
||||
void NotificationManager::sort_notifications()
|
||||
|
@ -1080,7 +1269,8 @@ bool NotificationManager::activate_existing(const NotificationManager::PopNotifi
|
|||
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()) {
|
||||
if (new_type == NotificationType::CustomNotification || new_type == NotificationType::PlaterWarning) {
|
||||
if (std::find(m_multiple_types.begin(), m_multiple_types.end(), new_type) != m_multiple_types.end()) {
|
||||
//if (new_type == NotificationType::CustomNotification || new_type == NotificationType::PlaterWarning || new_type == NotificationType::ProgressBar) {
|
||||
if (!(*it)->compare_text(new_text))
|
||||
continue;
|
||||
} else if (new_type == NotificationType::SlicingWarning) {
|
||||
|
@ -1112,103 +1302,6 @@ void NotificationManager::set_in_preview(bool preview)
|
|||
}
|
||||
}
|
||||
|
||||
void NotificationManager::update_notifications()
|
||||
{
|
||||
// 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;
|
||||
|
||||
//static size_t last_size = m_pop_notifications.size();
|
||||
|
||||
//request frames
|
||||
int64_t next_render = std::numeric_limits<int64_t>::max();
|
||||
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
||||
std::unique_ptr<PopNotification>& notification = *it;
|
||||
notification->set_paused(m_hovered);
|
||||
notification->update_state();
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
m_requires_update = false;
|
||||
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->requires_update()) {
|
||||
m_requires_update = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
// update hovering state
|
||||
m_hovered = false;
|
||||
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->is_hovered()) {
|
||||
m_hovered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Reuire render if some notification was just deleted.
|
||||
size_t curr_size = m_pop_notifications.size();
|
||||
m_requires_render = m_hovered || (last_size != curr_size);
|
||||
last_size = curr_size;
|
||||
|
||||
// Ask notification if it needs render
|
||||
if (!m_requires_render) {
|
||||
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->requires_render()) {
|
||||
m_requires_render = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Make sure there will be update after last notification erased
|
||||
if (m_requires_render)
|
||||
m_requires_update = true;
|
||||
*/
|
||||
|
||||
|
||||
if (next_render == 0)
|
||||
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame_delayed(33); //few milliseconds to get from GLCanvas::render
|
||||
else if (next_render < std::numeric_limits<int64_t>::max())
|
||||
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame_delayed(int(next_render));
|
||||
|
||||
/*
|
||||
// actualizate timers
|
||||
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;
|
||||
|
||||
{
|
||||
// Control the fade-out.
|
||||
// time in seconds
|
||||
long now = wxGetLocalTime();
|
||||
// Pausing fade-out when the mouse is over some notification.
|
||||
if (!m_hovered && m_last_time < now) {
|
||||
if (now - m_last_time >= MAX_TIMEOUT_SECONDS) {
|
||||
for (auto& notification : m_pop_notifications) {
|
||||
//if (notification->get_state() != PopNotification::EState::Static)
|
||||
notification->substract_remaining_time(MAX_TIMEOUT_SECONDS);
|
||||
}
|
||||
m_last_time = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool NotificationManager::has_slicing_error_notification()
|
||||
{
|
||||
return std::any_of(m_pop_notifications.begin(), m_pop_notifications.end(), [](auto &n) {
|
||||
|
|
|
@ -66,6 +66,8 @@ enum class NotificationType
|
|||
PlaterWarning,
|
||||
// Progress bar instead of text.
|
||||
ProgressBar,
|
||||
// Progress bar with info from Print Host Upload Queue dialog.
|
||||
PrintHostUpload,
|
||||
// Notification, when Color Change G-code is empty and user try to add color change on DoubleSlider.
|
||||
EmptyColorChangeCode,
|
||||
// Notification that custom supports/seams were deleted after mesh repair.
|
||||
|
@ -140,21 +142,24 @@ public:
|
|||
// Exporting finished, show this information with path, button to open containing folder and if ejectable - eject button
|
||||
void push_exporting_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable);
|
||||
// notification with progress bar
|
||||
void push_progress_bar_notification(const std::string& text, float percentage = 0);
|
||||
void set_progress_bar_percentage(const std::string& text, float percentage);
|
||||
void push_upload_job_notification(wxEvtHandler* evt_handler, int id, float filesize, const std::string& filename, const std::string& host, float percentage = 0);
|
||||
void set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage);
|
||||
void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host);
|
||||
void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host);
|
||||
// Close old notification ExportFinished.
|
||||
void new_export_began(bool on_removable);
|
||||
// finds ExportFinished notification and closes it if it was to removable device
|
||||
void device_ejected();
|
||||
// renders notifications in queue and deletes expired ones
|
||||
void render_notifications(float overlay_width);
|
||||
void render_notifications(GLCanvas3D& canvas, float overlay_width);
|
||||
// finds and closes all notifications of given type
|
||||
void close_notification_of_type(const NotificationType type);
|
||||
// Which view is active? Plater or G-code preview? Hide warnings in G-code preview.
|
||||
void set_in_preview(bool preview);
|
||||
// Move to left to avoid colision with variable layer height gizmo.
|
||||
void set_move_from_overlay(bool move) { m_move_from_overlay = move; }
|
||||
|
||||
// perform update_state on each notification and ask for more frames if needed, return true for render needed
|
||||
bool update_notifications(GLCanvas3D& canvas);
|
||||
private:
|
||||
// duration 0 means not disapearing
|
||||
struct NotificationData {
|
||||
|
@ -192,23 +197,24 @@ private:
|
|||
|
||||
enum class EState
|
||||
{
|
||||
Unknown,
|
||||
Unknown, // NOT initialized
|
||||
Hidden,
|
||||
FadingOutRender, // Requesting Render
|
||||
FadingOutStatic,
|
||||
Shown, // Requesting Render at some time if duration != 0
|
||||
FadingOut, // Requesting Render at some time
|
||||
ClosePending, // Requesting Render
|
||||
Finished, // Requesting Render
|
||||
Hovered, // Followed by Shown
|
||||
Paused
|
||||
};
|
||||
|
||||
PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler);
|
||||
virtual ~PopNotification() { if (m_id) m_id_provider.release_id(m_id); }
|
||||
void render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width);
|
||||
// close will dissapear notification on next render
|
||||
void close() { m_close_pending = true; }
|
||||
virtual void close() { m_state = EState::ClosePending; }
|
||||
// data from newer notification of same type
|
||||
void update(const NotificationData& n);
|
||||
bool is_finished() const { return m_finished || m_close_pending; }
|
||||
bool is_hovered() const { return m_hovered; }
|
||||
bool is_finished() const { return m_state == EState::ClosePending || m_state == EState::Finished; }
|
||||
// returns top after movement
|
||||
float get_top() const { return m_top_y; }
|
||||
//returns top in actual frame
|
||||
|
@ -216,23 +222,17 @@ private:
|
|||
const NotificationType get_type() const { return m_data.type; }
|
||||
const NotificationData get_data() const { return m_data; }
|
||||
const bool is_gray() const { return m_is_gray; }
|
||||
// Call equals one second down
|
||||
void substract_remaining_time(int seconds) { m_remaining_time -= seconds; }
|
||||
void set_gray(bool g) { m_is_gray = g; }
|
||||
void set_paused(bool p) { m_paused = p; }
|
||||
bool compare_text(const std::string& text);
|
||||
void hide(bool h) { m_hidden = h; }
|
||||
// sets m_next_render with time of next mandatory rendering
|
||||
void update_state();
|
||||
int64_t next_render() const { return m_next_render; }
|
||||
/*
|
||||
bool requires_render() const { return m_state == EState::FadingOutRender || m_state == EState::ClosePending || m_state == EState::Finished; }
|
||||
bool requires_update() const { return m_state != EState::Hidden; }
|
||||
*/
|
||||
EState get_state() const { return m_state; }
|
||||
protected:
|
||||
void hide(bool h) { m_state = h ? EState::Hidden : EState::Unknown; }
|
||||
// sets m_next_render with time of next mandatory rendering. Delta is time since last render.
|
||||
bool update_state(bool paused, const int64_t delta);
|
||||
int64_t next_render() const { return is_finished() ? 0 : m_next_render; }
|
||||
EState get_state() const { return m_state; }
|
||||
bool is_hovered() const { return m_state == EState::Hovered; }
|
||||
|
||||
// Call after every size change
|
||||
void init();
|
||||
virtual void init();
|
||||
// Part of init()
|
||||
virtual void count_spaces();
|
||||
// Calculetes correct size but not se it in imgui!
|
||||
|
@ -254,45 +254,36 @@ private:
|
|||
// Hypertext action, returns true if notification should close.
|
||||
// Action is stored in NotificationData::callback as std::function<bool(wxEvtHandler*)>
|
||||
virtual bool on_text_click();
|
||||
|
||||
protected:
|
||||
const NotificationData m_data;
|
||||
|
||||
// For reusing ImGUI windows.
|
||||
NotificationIDProvider &m_id_provider;
|
||||
int m_id{ 0 };
|
||||
|
||||
// State for rendering
|
||||
EState m_state { EState::Unknown };
|
||||
|
||||
int m_id { 0 };
|
||||
bool m_initialized { false };
|
||||
// Time values for rendering fade-out
|
||||
|
||||
int64_t m_fading_start{ 0LL };
|
||||
|
||||
// first appereance of notification or last hover;
|
||||
int64_t m_notification_start;
|
||||
// time to next must-do render
|
||||
int64_t m_next_render{ std::numeric_limits<int64_t>::max() };
|
||||
float m_current_fade_opacity{ 1.0f };
|
||||
|
||||
// Notification data
|
||||
|
||||
// Main text
|
||||
std::string m_text1;
|
||||
// Clickable text
|
||||
std::string m_hypertext;
|
||||
// Aditional text after hypertext - currently not used
|
||||
std::string m_text2;
|
||||
// Countdown variables
|
||||
long m_remaining_time;
|
||||
bool m_counting_down;
|
||||
long m_last_remaining_time;
|
||||
bool m_paused { false };
|
||||
int m_countdown_frame { 0 };
|
||||
bool m_fading_out { false };
|
||||
int64_t m_fading_start { 0LL };
|
||||
// time of last done render when fading
|
||||
int64_t m_last_render_fading { 0LL };
|
||||
// first appereance of notification or last hover;
|
||||
int64_t m_notification_start;
|
||||
// time to next must-do render
|
||||
int64_t m_next_render { std::numeric_limits<int64_t>::max() };
|
||||
float m_current_fade_opacity { 1.0f };
|
||||
// If hidden the notif is alive but not visible to user
|
||||
bool m_hidden { false };
|
||||
// m_finished = true - does not render, marked to delete
|
||||
bool m_finished { false };
|
||||
// Will go to m_finished next render
|
||||
bool m_close_pending { false };
|
||||
bool m_hovered { false };
|
||||
// variables to count positions correctly
|
||||
|
||||
// inner variables to position notification window, texts and buttons correctly
|
||||
|
||||
// all space without text
|
||||
float m_window_width_offset;
|
||||
// Space on left side without text
|
||||
|
@ -302,9 +293,7 @@ private:
|
|||
float m_window_width { 450.0f };
|
||||
//Distance from bottom of notifications to top of this notification
|
||||
float m_top_y { 0.0f };
|
||||
|
||||
// Height of text
|
||||
// Used as basic scaling unit!
|
||||
// Height of text - Used as basic scaling unit!
|
||||
float m_line_height;
|
||||
std::vector<size_t> m_endlines;
|
||||
// Gray are f.e. eorrors when its uknown if they are still valid
|
||||
|
@ -344,21 +333,78 @@ private:
|
|||
int warning_step;
|
||||
};
|
||||
|
||||
class PlaterWarningNotification : public PopNotification
|
||||
{
|
||||
public:
|
||||
PlaterWarningNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler) : PopNotification(n, id_provider, evt_handler) {}
|
||||
virtual void close() { m_state = EState::Hidden; }
|
||||
void real_close() { m_state = EState::ClosePending; }
|
||||
void show() { m_state = EState::Unknown; }
|
||||
};
|
||||
|
||||
|
||||
class ProgressBarNotification : public PopNotification
|
||||
{
|
||||
public:
|
||||
|
||||
ProgressBarNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, float percentage) : PopNotification(n, id_provider, evt_handler) { set_percentage(percentage); }
|
||||
void set_percentage(float percent) { m_percentage = percent; if (percent >= 1.0f) m_progress_complete = true; else m_progress_complete = false; }
|
||||
virtual void set_percentage(float percent) { m_percentage = percent; }
|
||||
protected:
|
||||
virtual void init();
|
||||
virtual void init() override;
|
||||
virtual void count_spaces() override;
|
||||
virtual void render_text(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y);
|
||||
void render_bar(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y);
|
||||
bool m_progress_complete{ false };
|
||||
float m_percentage;
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y);
|
||||
virtual void render_bar(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y);
|
||||
virtual void render_cancel_button(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y)
|
||||
{}
|
||||
float m_percentage;
|
||||
|
||||
bool m_has_cancel_button {false};
|
||||
// local time of last hover for showing tooltip
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class PrintHostUploadNotification : public ProgressBarNotification
|
||||
{
|
||||
public:
|
||||
enum class UploadJobState
|
||||
{
|
||||
PB_PROGRESS,
|
||||
PB_ERROR,
|
||||
PB_CANCELLED,
|
||||
PB_COMPLETED
|
||||
};
|
||||
PrintHostUploadNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, float percentage, int job_id, float filesize)
|
||||
:ProgressBarNotification(n, id_provider, evt_handler, percentage)
|
||||
, m_job_id(job_id)
|
||||
, m_file_size(filesize)
|
||||
{
|
||||
m_has_cancel_button = true;
|
||||
}
|
||||
static std::string get_upload_job_text(int id, const std::string& filename, const std::string& host) { return "[" + std::to_string(id) + "] " + filename + " -> " + host; }
|
||||
virtual void set_percentage(float percent);
|
||||
void cancel() { m_uj_state = UploadJobState::PB_CANCELLED; m_has_cancel_button = false; }
|
||||
void error() { m_uj_state = UploadJobState::PB_ERROR; m_has_cancel_button = false; }
|
||||
protected:
|
||||
virtual void render_bar(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y);
|
||||
virtual void render_cancel_button(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y);
|
||||
// Identifies job in cancel callback
|
||||
int m_job_id;
|
||||
// Size of uploaded size to be displayed in MB
|
||||
float m_file_size;
|
||||
long m_hover_time{ 0 };
|
||||
UploadJobState m_uj_state{ UploadJobState::PB_PROGRESS };
|
||||
};
|
||||
|
||||
class ExportFinishedNotification : public PopNotification
|
||||
|
@ -405,32 +451,25 @@ private:
|
|||
void sort_notifications();
|
||||
// If there is some error notification active, then the "Export G-code" notification after the slicing is finished is suppressed.
|
||||
bool has_slicing_error_notification();
|
||||
// perform update_state on each notification and ask for more frames if needed
|
||||
void update_notifications();
|
||||
|
||||
|
||||
// Target for wxWidgets events sent by clicking on the hyperlink available at some notifications.
|
||||
wxEvtHandler* m_evt_handler;
|
||||
// Cache of IDs to identify and reuse ImGUI windows.
|
||||
NotificationIDProvider m_id_provider;
|
||||
std::deque<std::unique_ptr<PopNotification>> m_pop_notifications;
|
||||
// Last render time in seconds for fade out control.
|
||||
long m_last_time { 0 };
|
||||
// When mouse hovers over some notification, the fade-out of all notifications is suppressed.
|
||||
bool m_hovered { false };
|
||||
//timestamps used for slicing finished - notification could be gone so it needs to be stored here
|
||||
std::unordered_set<int> m_used_timestamps;
|
||||
// True if G-code preview is active. False if the Plater is active.
|
||||
bool m_in_preview { false };
|
||||
// True if the layer editing is enabled in Plater, so that the notifications are shifted left of it.
|
||||
bool m_move_from_overlay { false };
|
||||
|
||||
// Timestamp of last rendering
|
||||
int64_t m_last_render { 0LL };
|
||||
// Notification types that can be shown multiple types at once (compared by text)
|
||||
const std::vector<NotificationType> m_multiple_types = { NotificationType::CustomNotification, NotificationType::PlaterWarning, NotificationType::ProgressBar, NotificationType::PrintHostUpload };
|
||||
//prepared (basic) notifications
|
||||
const std::vector<NotificationData> basic_notifications = {
|
||||
// {NotificationType::SlicingNotPossible, NotificationLevel::RegularNotification, 10, _u8L("Slicing is not possible.")},
|
||||
// {NotificationType::ExportToRemovableFinished, NotificationLevel::ImportantNotification, 0, _u8L("Exporting finished."), _u8L("Eject drive.") },
|
||||
{NotificationType::Mouse3dDisconnected, NotificationLevel::RegularNotification, 10, _u8L("3D Mouse disconnected.") },
|
||||
// {NotificationType::Mouse3dConnected, NotificationLevel::RegularNotification, 5, _u8L("3D Mouse connected.") },
|
||||
// {NotificationType::NewPresetsAviable, NotificationLevel::ImportantNotification, 20, _u8L("New Presets are available."), _u8L("See here.") },
|
||||
{NotificationType::PresetUpdateAvailable, NotificationLevel::ImportantNotification, 20, _u8L("Configuration update is available."), _u8L("See more."),
|
||||
[](wxEvtHandler* evnthndlr) {
|
||||
if (evnthndlr != nullptr)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "wxExtensions.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "NotificationManager.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
|
@ -280,6 +281,8 @@ void PrintHostQueueDialog::append_job(const PrintHostJob &job)
|
|||
job_list->AppendItem(fields, static_cast<wxUIntPtr>(ST_NEW));
|
||||
// Both strings are UTF-8 encoded.
|
||||
upload_names.emplace_back(job.printhost->get_host(), job.upload_data.upload_path.string());
|
||||
|
||||
//wxGetApp().notification_manager()->push_upload_job_notification(this, job_list->GetItemCount(), 0, job.upload_data.upload_path.string(), job.printhost->get_host());
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_dpi_changed(const wxRect &suggested_rect)
|
||||
|
@ -345,6 +348,14 @@ void PrintHostQueueDialog::on_progress(Event &evt)
|
|||
}
|
||||
|
||||
on_list_select();
|
||||
|
||||
if (evt.progress > 0)
|
||||
{
|
||||
wxVariant nm, hst;
|
||||
job_list->GetValue(nm, evt.job_id, COL_FILENAME);
|
||||
job_list->GetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_percentage(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()), 100 / evt.progress);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_error(Event &evt)
|
||||
|
@ -360,6 +371,11 @@ void PrintHostQueueDialog::on_error(Event &evt)
|
|||
on_list_select();
|
||||
|
||||
GUI::show_error(nullptr, errormsg);
|
||||
|
||||
wxVariant nm, hst;
|
||||
job_list->GetValue(nm, evt.job_id, COL_FILENAME);
|
||||
job_list->GetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->upload_job_notification_show_error(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()));
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_cancel(Event &evt)
|
||||
|
@ -370,6 +386,11 @@ void PrintHostQueueDialog::on_cancel(Event &evt)
|
|||
job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS);
|
||||
|
||||
on_list_select();
|
||||
|
||||
wxVariant nm, hst;
|
||||
job_list->GetValue(nm, evt.job_id, COL_FILENAME);
|
||||
job_list->GetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->upload_job_notification_show_canceled(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()));
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::get_active_jobs(std::vector<std::pair<std::string, std::string>>& ret)
|
||||
|
|
Loading…
Reference in a new issue