mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 07:34:03 -06:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
commit
411159b5e7
57 changed files with 2971 additions and 2371 deletions
|
@ -38,12 +38,12 @@ void AboutDialogLogo::onRepaint(wxEvent &event)
|
|||
// -----------------------------------------
|
||||
CopyrightsDialog::CopyrightsDialog()
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
: DPIDialog(NULL, wxID_ANY, from_u8((boost::format("%1% - %2%")
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, from_u8((boost::format("%1% - %2%")
|
||||
% (wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME)
|
||||
% _utf8(L("Portions copyright"))).str()),
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
#else
|
||||
: DPIDialog(NULL, wxID_ANY, from_u8((boost::format("%1% - %2%")
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, from_u8((boost::format("%1% - %2%")
|
||||
% SLIC3R_APP_NAME
|
||||
% _utf8(L("Portions copyright"))).str()),
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
|
@ -209,10 +209,10 @@ void CopyrightsDialog::onCloseDialog(wxEvent &)
|
|||
|
||||
AboutDialog::AboutDialog()
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
: DPIDialog(NULL, wxID_ANY, from_u8((boost::format(_utf8(L("About %s"))) % (wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME)).str()), wxDefaultPosition,
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, from_u8((boost::format(_utf8(L("About %s"))) % (wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME)).str()), wxDefaultPosition,
|
||||
wxDefaultSize, /*wxCAPTION*/wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
#else
|
||||
: DPIDialog(NULL, wxID_ANY, from_u8((boost::format(_utf8(L("About %s"))) % SLIC3R_APP_NAME).str()), wxDefaultPosition,
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, from_u8((boost::format(_utf8(L("About %s"))) % SLIC3R_APP_NAME).str()), wxDefaultPosition,
|
||||
wxDefaultSize, /*wxCAPTION*/wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
{
|
||||
|
|
|
@ -53,6 +53,24 @@ bool SlicingProcessCompletedEvent::critical_error() const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SlicingProcessCompletedEvent::invalidate_plater() const
|
||||
{
|
||||
if (critical_error())
|
||||
{
|
||||
try {
|
||||
this->rethrow_exception();
|
||||
}
|
||||
catch (const Slic3r::ExportError&) {
|
||||
// Exception thrown by copying file does not ivalidate plater
|
||||
return false;
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string SlicingProcessCompletedEvent::format_error_message() const
|
||||
{
|
||||
std::string error;
|
||||
|
@ -142,19 +160,19 @@ void BackgroundSlicingProcess::process_fff()
|
|||
switch (copy_ret_val) {
|
||||
case SUCCESS: break; // no error
|
||||
case FAIL_COPY_FILE:
|
||||
throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?\nError message: %1%"))) % error_message).str());
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?\nError message: %1%"))) % error_message).str());
|
||||
break;
|
||||
case FAIL_FILES_DIFFERENT:
|
||||
throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at %1%.tmp."))) % export_path).str());
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at %1%.tmp."))) % export_path).str());
|
||||
break;
|
||||
case FAIL_RENAMING:
|
||||
throw Slic3r::RuntimeError((boost::format(_utf8(L("Renaming of the G-code after copying to the selected destination folder has failed. Current path is %1%.tmp. Please try exporting again."))) % export_path).str());
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Renaming of the G-code after copying to the selected destination folder has failed. Current path is %1%.tmp. Please try exporting again."))) % export_path).str());
|
||||
break;
|
||||
case FAIL_CHECK_ORIGIN_NOT_OPENED:
|
||||
throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the original code at %1% couldn't be opened during copy check. The output G-code is at %2%.tmp."))) % m_temp_output_path % export_path).str());
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the original code at %1% couldn't be opened during copy check. The output G-code is at %2%.tmp."))) % m_temp_output_path % export_path).str());
|
||||
break;
|
||||
case FAIL_CHECK_TARGET_NOT_OPENED:
|
||||
throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the exported code couldn't be opened during copy check. The output G-code is at %1%.tmp."))) % export_path).str());
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the exported code couldn't be opened during copy check. The output G-code is at %1%.tmp."))) % export_path).str());
|
||||
break;
|
||||
default:
|
||||
throw Slic3r::RuntimeError(_utf8(L("Unknown error occured during exporting G-code.")));
|
||||
|
|
|
@ -57,6 +57,8 @@ public:
|
|||
bool error() const { return m_status == Error; }
|
||||
// Unhandled error produced by stdlib or a Win32 structured exception, or unhandled Slic3r's own critical exception.
|
||||
bool critical_error() const;
|
||||
// Critical errors does invalidate plater except CopyFileError.
|
||||
bool invalidate_plater() const;
|
||||
// Only valid if error()
|
||||
void rethrow_exception() const { assert(this->error()); assert(m_exception); std::rethrow_exception(m_exception); }
|
||||
// Produce a human readable message to be displayed by a notification or a message box.
|
||||
|
|
|
@ -109,7 +109,7 @@ static wxString generate_html_page(const Config::SnapshotDB &snapshot_db, const
|
|||
}
|
||||
|
||||
ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const wxString &on_snapshot)
|
||||
: DPIDialog(NULL, wxID_ANY, _(L("Configuration Snapshots")), wxDefaultPosition,
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, _(L("Configuration Snapshots")), wxDefaultPosition,
|
||||
wxSize(45 * wxGetApp().em_unit(), 40 * wxGetApp().em_unit()),
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX)
|
||||
{
|
||||
|
|
|
@ -191,10 +191,12 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||
|
||||
wxBitmap bitmap;
|
||||
int bitmap_width = 0;
|
||||
int bitmap_height = 0;
|
||||
const wxString bitmap_file = GUI::from_u8(Slic3r::resources_dir() + "/profiles/" + vendor.id + "/" + model.id + "_thumbnail.png");
|
||||
if (wxFileExists(bitmap_file)) {
|
||||
bitmap.LoadFile(bitmap_file, wxBITMAP_TYPE_PNG);
|
||||
bitmap_width = bitmap.GetWidth();
|
||||
bitmap_height = bitmap.GetHeight();
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Can't find bitmap file `%1%` for vendor `%2%`, printer `%3%`, using placeholder icon instead")
|
||||
% bitmap_file
|
||||
|
@ -205,6 +207,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||
if (wxFileExists(placeholder_file)) {
|
||||
bitmap.LoadFile(placeholder_file, wxBITMAP_TYPE_PNG);
|
||||
bitmap_width = bitmap.GetWidth();
|
||||
bitmap_height = bitmap.GetHeight();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,15 +277,12 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||
for (size_t j = i; j < i + cols; j++) { printer_grid->Add(bitmaps[j], 0, wxBOTTOM, 20); }
|
||||
for (size_t j = i; j < i + cols; j++) { printer_grid->Add(variants_panels[j]); }
|
||||
|
||||
// Add separator space
|
||||
if (i > 0) {
|
||||
for (size_t j = i; j < i + cols; j++) { printer_grid->Add(1, 100); }
|
||||
// Add separator space to multiliners
|
||||
if (titles.size() > cols) {
|
||||
for (size_t j = i; j < i + cols; j++) { printer_grid->Add(1, 30); }
|
||||
}
|
||||
}
|
||||
|
||||
if (odd_items > 0) {
|
||||
for (size_t i = 0; i < cols; i++) { printer_grid->Add(1, 100); }
|
||||
|
||||
const size_t rem = titles.size() - odd_items;
|
||||
|
||||
for (size_t i = rem; i < titles.size(); i++) { printer_grid->Add(titles[i], 0, wxBOTTOM, 3); }
|
||||
|
@ -1389,7 +1389,7 @@ void PageDiameters::apply_custom_config(DynamicPrintConfig &config)
|
|||
}
|
||||
|
||||
PageTemperatures::PageTemperatures(ConfigWizard *parent)
|
||||
: ConfigWizardPage(parent, _(L("Extruder and Bed Temperatures")), _(L("Temperatures")), 1)
|
||||
: ConfigWizardPage(parent, _(L("Nozzle and Bed Temperatures")), _(L("Temperatures")), 1)
|
||||
, spin_extr(new wxSpinCtrlDouble(this, wxID_ANY))
|
||||
, spin_bed(new wxSpinCtrlDouble(this, wxID_ANY))
|
||||
{
|
||||
|
|
|
@ -53,11 +53,6 @@ static std::string gcode(Type type)
|
|||
}
|
||||
}
|
||||
|
||||
static bool is_lower_thumb_editable()
|
||||
{
|
||||
return Slic3r::GUI::get_app_config()->get("seq_top_layer_only") == "0";
|
||||
}
|
||||
|
||||
Control::Control( wxWindow *parent,
|
||||
wxWindowID id,
|
||||
int lowerValue,
|
||||
|
@ -299,6 +294,8 @@ wxSize Control::get_size() const
|
|||
void Control::get_size(int* w, int* h) const
|
||||
{
|
||||
GetSize(w, h);
|
||||
if (m_draw_mode == dmSequentialGCodeView)
|
||||
return; // we have no more icons for drawing
|
||||
is_horizontal() ? *w -= m_lock_icon_dim : *h -= m_lock_icon_dim;
|
||||
}
|
||||
|
||||
|
@ -914,6 +911,10 @@ void Control::draw_revert_icon(wxDC& dc)
|
|||
|
||||
void Control::draw_cog_icon(wxDC& dc)
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if (m_draw_mode == dmSequentialGCodeView)
|
||||
return;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
int width, height;
|
||||
get_size(&width, &height);
|
||||
|
||||
|
@ -960,6 +961,13 @@ int Control::get_value_from_position(const wxCoord x, const wxCoord y)
|
|||
return int(m_min_value + double(height - SLIDER_MARGIN - y) / step + 0.5);
|
||||
}
|
||||
|
||||
bool Control::is_lower_thumb_editable()
|
||||
{
|
||||
if (m_draw_mode == dmSequentialGCodeView)
|
||||
return Slic3r::GUI::get_app_config()->get("seq_top_layer_only") == "0";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Control::detect_selected_slider(const wxPoint& pt)
|
||||
{
|
||||
if (is_point_in_rect(pt, m_rect_lower_thumb))
|
||||
|
|
|
@ -293,6 +293,7 @@ protected:
|
|||
void draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const;
|
||||
|
||||
void update_thumb_rect(const wxCoord begin_x, const wxCoord begin_y, const SelectedSlider& selection);
|
||||
bool is_lower_thumb_editable();
|
||||
bool detect_selected_slider(const wxPoint& pt);
|
||||
void correct_lower_value();
|
||||
void correct_higher_value();
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Slic3r {
|
|||
namespace GUI {
|
||||
|
||||
ExtruderSequenceDialog::ExtruderSequenceDialog(const DoubleSlider::ExtrudersSequence& sequence)
|
||||
: DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Set extruder sequence")),
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(L("Set extruder sequence")),
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||
m_sequence(sequence)
|
||||
{
|
||||
|
|
|
@ -112,16 +112,14 @@ bool GCodeViewer::Path::matches(const GCodeProcessor::MoveVertex& move) const
|
|||
case EMoveType::Custom_GCode:
|
||||
case EMoveType::Retract:
|
||||
case EMoveType::Unretract:
|
||||
case EMoveType::Extrude:
|
||||
{
|
||||
case EMoveType::Extrude: {
|
||||
// use rounding to reduce the number of generated paths
|
||||
return type == move.type && role == move.extrusion_role && height == round_to_nearest(move.height, 2) &&
|
||||
return type == move.type && move.position[2] <= first.position[2] && role == move.extrusion_role && height == round_to_nearest(move.height, 2) &&
|
||||
width == round_to_nearest(move.width, 2) && feedrate == move.feedrate && fan_speed == move.fan_speed &&
|
||||
volumetric_rate == round_to_nearest(move.volumetric_rate(), 2) && extruder_id == move.extruder_id &&
|
||||
cp_color_id == move.cp_color_id;
|
||||
}
|
||||
case EMoveType::Travel:
|
||||
{
|
||||
case EMoveType::Travel: {
|
||||
return type == move.type && feedrate == move.feedrate && extruder_id == move.extruder_id && cp_color_id == move.cp_color_id;
|
||||
}
|
||||
default: { return false; }
|
||||
|
@ -1531,14 +1529,15 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
|||
// dismiss indices data, no more needed
|
||||
std::vector<MultiIndexBuffer>().swap(indices);
|
||||
|
||||
// layers zs / roles / extruder ids / cp color ids -> extract from result
|
||||
// layers zs -> extract from result
|
||||
for (const Path& path : m_buffers[buffer_id(EMoveType::Extrude)].paths) {
|
||||
m_layers_zs.emplace_back(static_cast<double>(path.first.position[2]));
|
||||
// m_layers_zs.emplace_back(static_cast<double>(path.last.position[2]));
|
||||
}
|
||||
// roles / extruder ids / cp color ids -> extract from result
|
||||
for (size_t i = 0; i < m_moves_count; ++i) {
|
||||
const GCodeProcessor::MoveVertex& move = gcode_result.moves[i];
|
||||
if (move.type == EMoveType::Extrude)
|
||||
m_layers_zs.emplace_back(static_cast<double>(move.position[2]));
|
||||
|
||||
m_extruder_ids.emplace_back(move.extruder_id);
|
||||
|
||||
if (i > 0)
|
||||
m_roles.emplace_back(move.extrusion_role);
|
||||
}
|
||||
|
@ -2415,28 +2414,26 @@ void GCodeViewer::render_legend() const
|
|||
for (const auto& time_rec : times) {
|
||||
switch (time_rec.first)
|
||||
{
|
||||
case CustomGCode::PausePrint:
|
||||
{
|
||||
case CustomGCode::PausePrint: {
|
||||
auto it = std::find_if(custom_gcode_per_print_z.begin(), custom_gcode_per_print_z.end(), [time_rec](const CustomGCode::Item& item) { return item.type == time_rec.first; });
|
||||
if (it != custom_gcode_per_print_z.end()) {
|
||||
items.push_back({ PartialTime::EType::Print, it->extruder, Color(), Color(), time_rec.second });
|
||||
items.push_back({ PartialTime::EType::Print, it->extruder, last_color[it->extruder - 1], Color(), time_rec.second });
|
||||
items.push_back({ PartialTime::EType::Pause, it->extruder, Color(), Color(), time_rec.second });
|
||||
custom_gcode_per_print_z.erase(it);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CustomGCode::ColorChange:
|
||||
{
|
||||
case CustomGCode::ColorChange: {
|
||||
auto it = std::find_if(custom_gcode_per_print_z.begin(), custom_gcode_per_print_z.end(), [time_rec](const CustomGCode::Item& item) { return item.type == time_rec.first; });
|
||||
if (it != custom_gcode_per_print_z.end()) {
|
||||
items.push_back({ PartialTime::EType::Print, it->extruder, Color(), Color(), time_rec.second });
|
||||
items.push_back({ PartialTime::EType::Print, it->extruder, last_color[it->extruder - 1], Color(), time_rec.second });
|
||||
items.push_back({ PartialTime::EType::ColorChange, it->extruder, last_color[it->extruder - 1], decode_color(it->color), time_rec.second });
|
||||
last_color[it->extruder - 1] = decode_color(it->color);
|
||||
last_extruder_id = it->extruder;
|
||||
custom_gcode_per_print_z.erase(it);
|
||||
}
|
||||
else
|
||||
items.push_back({ PartialTime::EType::Print, last_extruder_id, Color(), Color(), time_rec.second });
|
||||
items.push_back({ PartialTime::EType::Print, last_extruder_id, last_color[last_extruder_id - 1], Color(), time_rec.second });
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2447,7 +2444,7 @@ void GCodeViewer::render_legend() const
|
|||
return items;
|
||||
};
|
||||
|
||||
auto append_color = [this, &imgui](const Color& color1, const Color& color2, std::array<float, 2>& offsets, const Times& times) {
|
||||
auto append_color_change = [this, &imgui](const Color& color1, const Color& color2, const std::array<float, 2>& offsets, const Times& times) {
|
||||
imgui.text(_u8L("Color change"));
|
||||
ImGui::SameLine();
|
||||
|
||||
|
@ -2466,6 +2463,24 @@ void GCodeViewer::render_legend() const
|
|||
imgui.text(short_time(get_time_dhms(times.second - times.first)));
|
||||
};
|
||||
|
||||
auto append_print = [this, &imgui](const Color& color, const std::array<float, 2>& offsets, const Times& times) {
|
||||
imgui.text(_u8L("Print"));
|
||||
ImGui::SameLine();
|
||||
|
||||
float icon_size = ImGui::GetTextLineHeight();
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
pos.x -= 0.5f * ImGui::GetStyle().ItemSpacing.x;
|
||||
|
||||
draw_list->AddRectFilled({ pos.x + 1.0f, pos.y + 1.0f }, { pos.x + icon_size - 1.0f, pos.y + icon_size - 1.0f },
|
||||
ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }));
|
||||
|
||||
ImGui::SameLine(offsets[0]);
|
||||
imgui.text(short_time(get_time_dhms(times.second)));
|
||||
ImGui::SameLine(offsets[1]);
|
||||
imgui.text(short_time(get_time_dhms(times.first)));
|
||||
};
|
||||
|
||||
PartialTimes partial_times = generate_partial_times(time_mode.custom_gcode_times);
|
||||
if (!partial_times.empty()) {
|
||||
labels.clear();
|
||||
|
@ -2474,8 +2489,8 @@ void GCodeViewer::render_legend() const
|
|||
for (const PartialTime& item : partial_times) {
|
||||
switch (item.type)
|
||||
{
|
||||
case PartialTime::EType::Print: { labels.push_back(_u8L("Print")); break; }
|
||||
case PartialTime::EType::Pause: { labels.push_back(_u8L("Pause")); break; }
|
||||
case PartialTime::EType::Print: { labels.push_back(_u8L("Print")); break; }
|
||||
case PartialTime::EType::Pause: { labels.push_back(_u8L("Pause")); break; }
|
||||
case PartialTime::EType::ColorChange: { labels.push_back(_u8L("Color change")); break; }
|
||||
}
|
||||
times.push_back(short_time(get_time_dhms(item.times.second)));
|
||||
|
@ -2487,25 +2502,18 @@ void GCodeViewer::render_legend() const
|
|||
for (const PartialTime& item : partial_times) {
|
||||
switch (item.type)
|
||||
{
|
||||
case PartialTime::EType::Print:
|
||||
{
|
||||
imgui.text(_u8L("Print"));
|
||||
ImGui::SameLine(offsets[0]);
|
||||
imgui.text(short_time(get_time_dhms(item.times.second)));
|
||||
ImGui::SameLine(offsets[1]);
|
||||
imgui.text(short_time(get_time_dhms(item.times.first)));
|
||||
case PartialTime::EType::Print: {
|
||||
append_print(item.color1, offsets, item.times);
|
||||
break;
|
||||
}
|
||||
case PartialTime::EType::Pause:
|
||||
{
|
||||
case PartialTime::EType::Pause: {
|
||||
imgui.text(_u8L("Pause"));
|
||||
ImGui::SameLine(offsets[0]);
|
||||
imgui.text(short_time(get_time_dhms(item.times.second - item.times.first)));
|
||||
break;
|
||||
}
|
||||
case PartialTime::EType::ColorChange:
|
||||
{
|
||||
append_color(item.color1, item.color2, offsets, item.times);
|
||||
case PartialTime::EType::ColorChange: {
|
||||
append_color_change(item.color1, item.color2, offsets, item.times);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2519,12 +2527,10 @@ void GCodeViewer::render_legend() const
|
|||
{
|
||||
case EViewType::Feedrate:
|
||||
case EViewType::Tool:
|
||||
case EViewType::ColorPrint:
|
||||
{
|
||||
case EViewType::ColorPrint: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
// title
|
||||
ImGui::Spacing();
|
||||
imgui.title(_u8L("Travel"));
|
||||
|
@ -2570,8 +2576,8 @@ void GCodeViewer::render_legend() const
|
|||
add_option(EMoveType::Unretract, EOptionsColors::Unretractions, _u8L("Deretractions"));
|
||||
add_option(EMoveType::Tool_change, EOptionsColors::ToolChanges, _u8L("Tool changes"));
|
||||
add_option(EMoveType::Color_change, EOptionsColors::ColorChanges, _u8L("Color changes"));
|
||||
add_option(EMoveType::Pause_Print, EOptionsColors::PausePrints, _u8L("Pause prints"));
|
||||
add_option(EMoveType::Custom_GCode, EOptionsColors::CustomGCodes, _u8L("Custom GCodes"));
|
||||
add_option(EMoveType::Pause_Print, EOptionsColors::PausePrints, _u8L("Print pauses"));
|
||||
add_option(EMoveType::Custom_GCode, EOptionsColors::CustomGCodes, _u8L("Custom G-codes"));
|
||||
}
|
||||
|
||||
// total estimated printing time section
|
||||
|
|
|
@ -1415,7 +1415,7 @@ void GLCanvas3D::Tooltip::render(const Vec2d& mouse_position, GLCanvas3D& canvas
|
|||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha);
|
||||
imgui.set_next_window_pos(position(0), position(1), ImGuiCond_Always, 0.0f, 0.0f);
|
||||
|
||||
imgui.begin(_L("canvas_tooltip"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing);
|
||||
imgui.begin(wxString("canvas_tooltip"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing);
|
||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
||||
ImGui::TextUnformatted(m_text.c_str());
|
||||
|
||||
|
@ -1457,6 +1457,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, wxKeyEvent);
|
|||
wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_JUMP_TO, wxKeyEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_COLLAPSE_SIDEBAR, SimpleEvent);
|
||||
|
@ -2899,6 +2900,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
// see include/wx/defs.h enum wxKeyCode
|
||||
int keyCode = evt.GetKeyCode();
|
||||
int ctrlMask = wxMOD_CONTROL;
|
||||
int shiftMask = wxMOD_SHIFT;
|
||||
|
||||
auto imgui = wxGetApp().imgui();
|
||||
if (imgui->update_key_data(evt)) {
|
||||
|
@ -2996,6 +2998,18 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); break;
|
||||
default: evt.Skip();
|
||||
}
|
||||
}
|
||||
else if ((evt.GetModifiers() & shiftMask) != 0) {
|
||||
switch (keyCode) {
|
||||
case 'g':
|
||||
case 'G': {
|
||||
if (dynamic_cast<Preview*>(m_canvas->GetParent()) != nullptr)
|
||||
post_event(wxKeyEvent(EVT_GLCANVAS_JUMP_TO, evt));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
evt.Skip();
|
||||
}
|
||||
} else if (evt.HasModifiers()) {
|
||||
evt.Skip();
|
||||
} else {
|
||||
|
@ -4385,7 +4399,7 @@ bool GLCanvas3D::_render_search_list(float pos_x) const
|
|||
|
||||
std::string& search_line = sidebar.get_search_line();
|
||||
char *s = new char[255];
|
||||
strcpy(s, search_line.empty() ? _u8L("Type here to search").c_str() : search_line.c_str());
|
||||
strcpy(s, search_line.empty() ? _u8L("Enter a search term").c_str() : search_line.c_str());
|
||||
|
||||
imgui->search_list(ImVec2(45 * em, 30 * em), &search_string_getter, s,
|
||||
sidebar.get_searcher().view_params,
|
||||
|
@ -4393,7 +4407,7 @@ bool GLCanvas3D::_render_search_list(float pos_x) const
|
|||
|
||||
search_line = s;
|
||||
delete [] s;
|
||||
if (search_line == _u8L("Type here to search"))
|
||||
if (search_line == _u8L("Enter a search term"))
|
||||
search_line.clear();
|
||||
|
||||
if (edited)
|
||||
|
|
|
@ -114,6 +114,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, wxKeyEvent);
|
|||
wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_JUMP_TO, wxKeyEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_COLLAPSE_SIDEBAR, SimpleEvent);
|
||||
|
|
|
@ -86,7 +86,7 @@ class SplashScreen : public wxSplashScreen
|
|||
{
|
||||
public:
|
||||
SplashScreen(const wxBitmap& bitmap, long splashStyle, int milliseconds, wxPoint pos = wxDefaultPosition)
|
||||
: wxSplashScreen(bitmap, splashStyle, milliseconds, nullptr, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
: wxSplashScreen(bitmap, splashStyle, milliseconds, (wxWindow*)wxGetApp().mainframe, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
#ifdef __APPLE__
|
||||
wxSIMPLE_BORDER | wxFRAME_NO_TASKBAR | wxSTAY_ON_TOP
|
||||
#else
|
||||
|
@ -892,7 +892,7 @@ bool GUI_App::on_init_inner()
|
|||
#else
|
||||
if (scrn)
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
scrn->SetText(_L("Creating settings tabs..."));
|
||||
scrn->SetText(_L("Preparing settings tabs..."));
|
||||
|
||||
mainframe = new MainFrame();
|
||||
// hide settings tabs after first Layout
|
||||
|
@ -1149,8 +1149,8 @@ void GUI_App::check_printer_presets()
|
|||
for (const std::string& preset_name : preset_names)
|
||||
msg_text += "\n \"" + from_u8(preset_name) + "\",";
|
||||
msg_text.RemoveLast();
|
||||
msg_text += "\n\n" + _L("But from this version of PrusaSlicer we don't show/use this information in Printer Settings.\n"
|
||||
"Now, this information will be exposed in physical printers settings.") + "\n\n" +
|
||||
msg_text += "\n\n" + _L("But since this version of PrusaSlicer we don't show this information in Printer Settings anymore.\n"
|
||||
"Settings will be available in physical printers settings.") + "\n\n" +
|
||||
_L("By default new Printer devices will be named as \"Printer N\" during its creation.\n"
|
||||
"Note: This name can be changed later from the physical printers settings");
|
||||
|
||||
|
|
|
@ -557,6 +557,16 @@ void Preview::msw_rescale()
|
|||
refresh_print();
|
||||
}
|
||||
|
||||
void Preview::jump_layers_slider(wxKeyEvent& evt)
|
||||
{
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if (m_layers_slider) m_layers_slider->OnChar(evt);
|
||||
#else
|
||||
if (m_slider)
|
||||
m_slider->OnKeyDown(evt);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void Preview::move_layers_slider(wxKeyEvent& evt)
|
||||
{
|
||||
|
@ -1463,8 +1473,8 @@ wxString Preview::get_option_type_string(OptionType type) const
|
|||
case OptionType::Unretractions: { return _L("Deretractions"); }
|
||||
case OptionType::ToolChanges: { return _L("Tool changes"); }
|
||||
case OptionType::ColorChanges: { return _L("Color changes"); }
|
||||
case OptionType::PausePrints: { return _L("Pause prints"); }
|
||||
case OptionType::CustomGCodes: { return _L("Custom GCodes"); }
|
||||
case OptionType::PausePrints: { return _L("Print pauses"); }
|
||||
case OptionType::CustomGCodes: { return _L("Custom G-codes"); }
|
||||
case OptionType::Shells: { return _L("Shells"); }
|
||||
case OptionType::ToolMarker: { return _L("Tool marker"); }
|
||||
case OptionType::Legend: { return _L("Legend/Estimated printing time"); }
|
||||
|
|
|
@ -179,6 +179,7 @@ Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config,
|
|||
void refresh_print();
|
||||
|
||||
void msw_rescale();
|
||||
void jump_layers_slider(wxKeyEvent& evt);
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void move_layers_slider(wxKeyEvent& evt);
|
||||
void edit_layers_slider(wxKeyEvent& evt);
|
||||
|
|
|
@ -95,6 +95,7 @@ public:
|
|||
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
|
||||
this->SetFont(m_normal_font);
|
||||
#endif
|
||||
this->CenterOnParent();
|
||||
|
||||
// Linux specific issue : get_dpi_for_window(this) still doesn't responce to the Display's scale in new wxWidgets(3.1.3).
|
||||
// So, calculate the m_em_unit value from the font size, as before
|
||||
|
|
|
@ -41,8 +41,8 @@ bool GLGizmoFdmSupports::on_init()
|
|||
|
||||
m_desc["clipping_of_view"] = _L("Clipping of view") + ": ";
|
||||
m_desc["reset_direction"] = _L("Reset direction");
|
||||
m_desc["cursor_size"] = _L("Cursor size") + ": ";
|
||||
m_desc["cursor_type"] = _L("Cursor type") + ": ";
|
||||
m_desc["cursor_size"] = _L("Brush size") + ": ";
|
||||
m_desc["cursor_type"] = _L("Brush shape") + ": ";
|
||||
m_desc["enforce_caption"] = _L("Left mouse button") + ": ";
|
||||
m_desc["enforce"] = _L("Enforce supports");
|
||||
m_desc["block_caption"] = _L("Right mouse button") + " ";
|
||||
|
@ -232,9 +232,12 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
|||
else {
|
||||
m_imgui->begin(_L("Autoset custom supports"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(_L("Threshold:") + " " + _L("deg"));
|
||||
m_imgui->text(_L("Threshold:"));
|
||||
std::string format_str = std::string("%.f") + I18N::translate_utf8("°",
|
||||
"Degree sign to use in the respective slider in FDM supports gizmo,"
|
||||
"placed after the number with no whitespace in between.");
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->slider_float("", &m_angle_threshold_deg, 0.f, 90.f, "%.f"))
|
||||
if (m_imgui->slider_float("", &m_angle_threshold_deg, 0.f, 90.f, format_str.data()))
|
||||
m_parent.set_slope_normal_angle(90.f - m_angle_threshold_deg);
|
||||
if (m_imgui->button(_L("Enforce")))
|
||||
select_facets_by_angle(m_angle_threshold_deg, false);
|
||||
|
|
|
@ -37,14 +37,14 @@ void GLGizmoPainterBase::activate_internal_undo_redo_stack(bool activate)
|
|||
if (activate && ! m_internal_stack_active) {
|
||||
wxString str = get_painter_type() == PainterGizmoType::FDM_SUPPORTS
|
||||
? _L("Supports gizmo turned on")
|
||||
: _L("Seam gizmo turned on");
|
||||
: _L("Paint-on seams on");
|
||||
Plater::TakeSnapshot(wxGetApp().plater(), str);
|
||||
wxGetApp().plater()->enter_gizmos_stack();
|
||||
m_internal_stack_active = true;
|
||||
}
|
||||
if (! activate && m_internal_stack_active) {
|
||||
wxString str = get_painter_type() == PainterGizmoType::SEAM
|
||||
? _L("Seam gizmo turned off")
|
||||
? _L("Paint-on seams off")
|
||||
: _L("Supports gizmo turned off");
|
||||
wxGetApp().plater()->leave_gizmos_stack();
|
||||
Plater::TakeSnapshot(wxGetApp().plater(), str);
|
||||
|
|
|
@ -200,62 +200,10 @@ void GLGizmoRotate::on_render_for_picking() const
|
|||
glsafe(::glPopMatrix());
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLGizmoRotate3D::RotoptimzeWindow::RotoptimzeWindow(ImGuiWrapper * imgui,
|
||||
State & state,
|
||||
const Alignment &alignment)
|
||||
: m_imgui{imgui}
|
||||
{
|
||||
imgui->begin(_L("Rotation"), ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
// adjust window position to avoid overlap the view toolbar
|
||||
float win_h = ImGui::GetWindowHeight();
|
||||
float x = alignment.x, y = alignment.y;
|
||||
y = std::min(y, alignment.bottom_limit - win_h);
|
||||
ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always);
|
||||
|
||||
static constexpr const char * button_txt = L("Optimize orientation");
|
||||
static constexpr const char * slider_txt = L("Accuracy");
|
||||
|
||||
float button_width = imgui->calc_text_size(_(button_txt)).x;
|
||||
ImGui::PushItemWidth(100.);
|
||||
//if (imgui->button(_(button_txt))) {
|
||||
if (ImGui::ArrowButton(_(button_txt).c_str(), ImGuiDir_Down)){
|
||||
std::cout << "Blip" << std::endl;
|
||||
}
|
||||
|
||||
ImGui::SliderFloat(_(slider_txt).c_str(), &state.accuracy, 0.01f, 1.f, "%.1f");
|
||||
|
||||
static const std::vector<std::string> options = {
|
||||
_L("Least supports").ToStdString(),
|
||||
_L("Suface quality").ToStdString()
|
||||
};
|
||||
|
||||
// if (imgui->combo(_L("Choose method"), options, state.method) ) {
|
||||
// std::cout << "method: " << state.method << std::endl;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
GLGizmoRotate3D::RotoptimzeWindow::~RotoptimzeWindow()
|
||||
{
|
||||
m_imgui->end();
|
||||
}
|
||||
|
||||
void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||
return;
|
||||
|
||||
// TODO:
|
||||
|
||||
// m_rotoptimizewin_state.mobj = ?;
|
||||
// RotoptimzeWindow popup{m_imgui, m_rotoptimizewin_state, {x, y, bottom_limit}};
|
||||
|
||||
}
|
||||
|
||||
void GLGizmoRotate::render_circle() const
|
||||
|
|
|
@ -136,37 +136,6 @@ protected:
|
|||
}
|
||||
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
|
||||
private:
|
||||
|
||||
class RotoptimzeWindow {
|
||||
ImGuiWrapper *m_imgui = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
struct State {
|
||||
enum Metods { mMinSupportPoints, mLegacy };
|
||||
|
||||
float accuracy = 1.f;
|
||||
int method = mMinSupportPoints;
|
||||
ModelObject *mobj = nullptr;
|
||||
};
|
||||
|
||||
struct Alignment { float x, y, bottom_limit; };
|
||||
|
||||
RotoptimzeWindow(ImGuiWrapper * imgui,
|
||||
State & state,
|
||||
const Alignment &bottom_limit);
|
||||
|
||||
~RotoptimzeWindow();
|
||||
|
||||
RotoptimzeWindow(const RotoptimzeWindow&) = delete;
|
||||
RotoptimzeWindow(RotoptimzeWindow &&) = delete;
|
||||
RotoptimzeWindow& operator=(const RotoptimzeWindow &) = delete;
|
||||
RotoptimzeWindow& operator=(RotoptimzeWindow &&) = delete;
|
||||
};
|
||||
|
||||
RotoptimzeWindow::State m_rotoptimizewin_state = {};
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
@ -24,8 +24,8 @@ bool GLGizmoSeam::on_init()
|
|||
|
||||
m_desc["clipping_of_view"] = _L("Clipping of view") + ": ";
|
||||
m_desc["reset_direction"] = _L("Reset direction");
|
||||
m_desc["cursor_size"] = _L("Cursor size") + ": ";
|
||||
m_desc["cursor_type"] = _L("Cursor type") + ": ";
|
||||
m_desc["cursor_size"] = _L("Brush size") + ": ";
|
||||
m_desc["cursor_type"] = _L("Brush shape") + ": ";
|
||||
m_desc["enforce_caption"] = _L("Left mouse button") + ": ";
|
||||
m_desc["enforce"] = _L("Enforce seam");
|
||||
m_desc["block_caption"] = _L("Right mouse button") + " ";
|
||||
|
|
|
@ -49,7 +49,9 @@ static const std::map<const char, std::string> font_icons = {
|
|||
{ImGui::MinimalizeMarker , "notification_minimalize" },
|
||||
{ImGui::MinimalizeHoverMarker , "notification_minimalize_hover" },
|
||||
{ImGui::WarningMarker , "notification_warning" },
|
||||
{ImGui::ErrorMarker , "notification_error" }
|
||||
{ImGui::ErrorMarker , "notification_error" },
|
||||
{ImGui::EjectMarker , "notification_eject_sd" },
|
||||
{ImGui::EjectHoverMarker , "notification_eject_sd_hover" },
|
||||
};
|
||||
|
||||
const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.333f, 0.333f, 0.333f, 1.0f };
|
||||
|
|
|
@ -34,9 +34,9 @@ namespace GUI {
|
|||
|
||||
KBShortcutsDialog::KBShortcutsDialog()
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
: DPIDialog(NULL, wxID_ANY, wxString(wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME) + " - " + _L("Keyboard Shortcuts"),
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, wxString(wxGetApp().is_editor() ? SLIC3R_APP_NAME : GCODEVIEWER_APP_NAME) + " - " + _L("Keyboard Shortcuts"),
|
||||
#else
|
||||
: DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Keyboard Shortcuts"),
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("Keyboard Shortcuts"),
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
{
|
||||
|
@ -213,7 +213,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
{ L("Arrow Down"), L("Lower Layer") },
|
||||
{ "U", L("Upper Layer") },
|
||||
{ "D", L("Lower Layer") },
|
||||
{ "L", L("Show/Hide Legend/Estimated printing time") },
|
||||
{ "L", L("Show/Hide Legend & Estimated printing time") },
|
||||
};
|
||||
|
||||
m_full_shortcuts.push_back(std::make_pair(_L("Preview"), preview_shortcuts));
|
||||
|
|
|
@ -238,6 +238,17 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||
event.Skip();
|
||||
});
|
||||
|
||||
// OSX specific issue:
|
||||
// When we move application between Retina and non-Retina displays, The legend on a canvas doesn't redraw
|
||||
// So, redraw explicitly canvas, when application is moved
|
||||
#ifdef ENABLE_RETINA_GL
|
||||
Bind(wxEVT_MOVE, [this](wxMoveEvent& event) {
|
||||
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
|
||||
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame();
|
||||
event.Skip();
|
||||
});
|
||||
#endif
|
||||
|
||||
wxGetApp().persist_window_geometry(this, true);
|
||||
wxGetApp().persist_window_geometry(&m_settings_dialog, true);
|
||||
|
||||
|
@ -1044,7 +1055,7 @@ void MainFrame::init_menubar()
|
|||
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(true); }, "import_plater", nullptr,
|
||||
[this](){return m_plater != nullptr; }, this);
|
||||
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import SL1 archive") + dots, _L("Load an SL1 output archive"),
|
||||
append_menu_item(import_menu, wxID_ANY, _L("Import SL1 archive") + dots, _L("Load an SL1 archive"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->import_sl1_archive(); }, "import_plater", nullptr,
|
||||
[this](){return m_plater != nullptr; }, this);
|
||||
|
||||
|
@ -1202,7 +1213,7 @@ void MainFrame::init_menubar()
|
|||
|
||||
editMenu->AppendSeparator();
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Searc&h") + "\tCtrl+F",
|
||||
_L("Find option"), [this](wxCommandEvent&) { m_plater->search(/*m_tabpanel->GetCurrentPage() == */m_plater->IsShown()); },
|
||||
_L("Search in settings"), [this](wxCommandEvent&) { m_plater->search(/*m_tabpanel->GetCurrentPage() == */m_plater->IsShown()); },
|
||||
"search", nullptr, []() {return true; }, this);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "NotificationManager.hpp"
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#include "ImGuiWrapper.hpp"
|
||||
|
@ -33,6 +34,56 @@ namespace Notifications_Internal{
|
|||
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
|
||||
|
@ -183,6 +234,7 @@ NotificationManager::PopNotification::RenderResult NotificationManager::PopNotif
|
|||
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);
|
||||
} else {
|
||||
|
@ -205,12 +257,8 @@ NotificationManager::PopNotification::RenderResult NotificationManager::PopNotif
|
|||
ImGui::PopStyleColor();
|
||||
return ret_val;
|
||||
}
|
||||
void NotificationManager::PopNotification::init()
|
||||
void NotificationManager::PopNotification::count_spaces()
|
||||
{
|
||||
std::string text = m_text1 + " " + m_hypertext;
|
||||
int last_end = 0;
|
||||
m_lines_count = 0;
|
||||
|
||||
//determine line width
|
||||
m_line_height = ImGui::CalcTextSize("A").y;
|
||||
|
||||
|
@ -221,8 +269,16 @@ void NotificationManager::PopNotification::init()
|
|||
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 * 2;
|
||||
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;
|
||||
int last_end = 0;
|
||||
m_lines_count = 0;
|
||||
|
||||
count_spaces();
|
||||
|
||||
// count lines
|
||||
m_endlines.clear();
|
||||
|
@ -233,10 +289,9 @@ void NotificationManager::PopNotification::init()
|
|||
//next line is ended by '/n'
|
||||
m_endlines.push_back(next_hard_end);
|
||||
last_end = next_hard_end + 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// find next suitable endline
|
||||
if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - 3.5f * m_line_height) {// m_window_width_offset) {
|
||||
if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset) {
|
||||
// more than one line till end
|
||||
int next_space = text.find_first_of(' ', last_end);
|
||||
if (next_space > 0) {
|
||||
|
@ -245,8 +300,19 @@ void NotificationManager::PopNotification::init()
|
|||
next_space = next_space_candidate;
|
||||
next_space_candidate = text.find_first_of(' ', next_space + 1);
|
||||
}
|
||||
m_endlines.push_back(next_space);
|
||||
last_end = next_space + 1;
|
||||
// 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) {
|
||||
float width_of_a = ImGui::CalcTextSize("a").x;
|
||||
int letter_count = (int)((m_window_width - m_window_width_offset) / width_of_a);
|
||||
while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset) {
|
||||
letter_count++;
|
||||
}
|
||||
m_endlines.push_back(last_end + letter_count);
|
||||
last_end += letter_count;
|
||||
} else {
|
||||
m_endlines.push_back(next_space);
|
||||
last_end = next_space + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -257,6 +323,8 @@ void NotificationManager::PopNotification::init()
|
|||
}
|
||||
m_lines_count++;
|
||||
}
|
||||
if (m_lines_count == 3)
|
||||
m_multiline = true;
|
||||
m_initialized = true;
|
||||
}
|
||||
void NotificationManager::PopNotification::set_next_window_size(ImGuiWrapper& imgui)
|
||||
|
@ -285,7 +353,8 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
|
|||
float shift_y = m_line_height;// -m_line_height / 20;
|
||||
for (size_t i = 0; i < m_lines_count; i++) {
|
||||
std::string line = m_text1.substr(last_end , m_endlines[i] - last_end);
|
||||
last_end = m_endlines[i] + 1;
|
||||
if(i < m_lines_count - 1)
|
||||
last_end = m_endlines[i] + (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());
|
||||
|
@ -303,7 +372,7 @@ 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] + 1, m_endlines[1] - m_endlines[0] - 1);
|
||||
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));
|
||||
if (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() - 6);
|
||||
|
@ -326,7 +395,7 @@ 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] + 1);
|
||||
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);
|
||||
|
@ -375,8 +444,7 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
|
|||
set_next_window_size(imgui);
|
||||
}
|
||||
else {
|
||||
on_text_click();
|
||||
m_close_pending = true;
|
||||
m_close_pending = on_text_click();
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
@ -407,7 +475,7 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
|
|||
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);
|
||||
ImVec2 win_pos(win_pos_x, win_pos_y);
|
||||
ImVec4 orange_color = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
||||
orange_color.w = 0.8f;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
|
||||
|
@ -422,7 +490,7 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
|
|||
button_text = ImGui::CloseIconMarker;
|
||||
|
||||
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_multiline? 2 * m_line_height : 0)),
|
||||
ImVec2(win_pos.x, win_pos.y + win_size.y - ( m_minimize_b_visible ? 2 * m_line_height : 0)),
|
||||
true))
|
||||
{
|
||||
button_text = ImGui::CloseIconHoverMarker;
|
||||
|
@ -435,11 +503,10 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
|
|||
{
|
||||
m_close_pending = true;
|
||||
}
|
||||
|
||||
//invisible large button
|
||||
ImGui::SetCursorPosX(win_size.x - win_size.x / 10.f);
|
||||
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.125);
|
||||
ImGui::SetCursorPosY(0);
|
||||
if (imgui.button(" ", win_size.x / 10.f, win_size.y - (m_multiline ? 2 * m_line_height : 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;
|
||||
}
|
||||
|
@ -540,15 +607,12 @@ void NotificationManager::PopNotification::render_minimize_button(ImGuiWrapper&
|
|||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
m_minimize_b_visible = true;
|
||||
}
|
||||
void NotificationManager::PopNotification::on_text_click()
|
||||
bool NotificationManager::PopNotification::on_text_click()
|
||||
{
|
||||
bool ret = true;
|
||||
switch (m_data.type) {
|
||||
case NotificationType::ExportToRemovableFinished :
|
||||
assert(m_evt_handler != nullptr);
|
||||
if (m_evt_handler != nullptr)
|
||||
wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED));
|
||||
break;
|
||||
case NotificationType::SlicingComplete :
|
||||
//wxGetApp().plater()->export_gcode(false);
|
||||
assert(m_evt_handler != nullptr);
|
||||
|
@ -567,6 +631,7 @@ void NotificationManager::PopNotification::on_text_click()
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
void NotificationManager::PopNotification::update(const NotificationData& n)
|
||||
{
|
||||
|
@ -633,6 +698,127 @@ void NotificationManager::SlicingCompleteLargeNotification::set_large(bool l)
|
|||
m_hypertext = l ? _u8L("Export G-Code.") : std::string();
|
||||
m_hidden = !l;
|
||||
}
|
||||
//---------------ExportFinishedNotification-----------
|
||||
void NotificationManager::ExportFinishedNotification::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;
|
||||
}
|
||||
//TODO count this properly
|
||||
m_window_width_offset = m_left_indentation + m_line_height * (m_to_removable ? 5.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)
|
||||
{
|
||||
|
||||
ImVec2 win_size(win_size_x, win_size_y);
|
||||
ImVec2 win_pos(win_pos_x, win_pos_y);
|
||||
float x_offset = m_left_indentation;
|
||||
std::string fulltext = m_text1 + m_hypertext; //+ m_text2;
|
||||
ImVec2 text_size = ImGui::CalcTextSize(fulltext.c_str());
|
||||
// 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.
|
||||
int 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++) {
|
||||
std::string line = m_text1.substr(last_end, m_endlines[i] - last_end);
|
||||
if (i < m_lines_count - 1)
|
||||
last_end = m_endlines[i] + (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 ) {
|
||||
render_hypertext(imgui, x_offset + ImGui::CalcTextSize(m_text1.substr(0, last_end).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);
|
||||
if(m_to_removable)
|
||||
render_eject_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ImVec2 win_size(win_size_x, win_size_y);
|
||||
ImVec2 win_pos(win_pos_x, win_pos_y);
|
||||
ImVec4 orange_color = ImGui::GetStyleColorVec4(ImGuiCol_Button);
|
||||
orange_color.w = 0.8f;
|
||||
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);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
|
||||
|
||||
std::string button_text;
|
||||
button_text = ImGui::EjectMarker;
|
||||
|
||||
if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - m_line_height * 4.5f, win_pos.y),
|
||||
ImVec2(win_pos.x - m_line_height * 2.5f, win_pos.y + win_size.y),
|
||||
true))
|
||||
{
|
||||
button_text = ImGui::EjectHoverMarker;
|
||||
// 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("Eject drive"));
|
||||
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 * 4.f);
|
||||
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y / 2);
|
||||
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));
|
||||
m_close_pending = true;
|
||||
}
|
||||
|
||||
//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)
|
||||
wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED));
|
||||
m_close_pending = true;
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
bool NotificationManager::ExportFinishedNotification::on_text_click()
|
||||
{
|
||||
Notifications_Internal::open_folder(m_export_dir_path);
|
||||
return false;
|
||||
}
|
||||
//------NotificationManager--------
|
||||
NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
|
||||
m_evt_handler(evt_handler)
|
||||
|
@ -789,6 +975,13 @@ void NotificationManager::remove_slicing_warnings_of_released_objects(const std:
|
|||
notification->close();
|
||||
}
|
||||
}
|
||||
void NotificationManager::push_exporting_finished_notification(GLCanvas3D& canvas, std::string path, std::string dir_path, bool on_removable)
|
||||
{
|
||||
close_notification_of_type(NotificationType::ExportFinished);
|
||||
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotification, 0, _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),
|
||||
canvas, 0);
|
||||
}
|
||||
bool NotificationManager::push_notification_data(const NotificationData ¬ification_data, GLCanvas3D& canvas, int timestamp)
|
||||
{
|
||||
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), canvas, timestamp);
|
||||
|
@ -822,7 +1015,7 @@ void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay
|
|||
bool hovered = false;
|
||||
sort_notifications();
|
||||
// iterate thru notifications and render them / erease them
|
||||
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
||||
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
||||
if ((*it)->get_finished()) {
|
||||
it = m_pop_notifications.erase(it);
|
||||
} else {
|
||||
|
@ -931,5 +1124,31 @@ bool NotificationManager::has_slicing_error_notification()
|
|||
});
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace GUI
|
||||
}//namespace Slic3r
|
||||
|
|
|
@ -32,7 +32,11 @@ enum class NotificationType
|
|||
SlicingComplete,
|
||||
// SlicingNotPossible,
|
||||
// Notification on end of export to a removable media, with hyperling to eject the external media.
|
||||
ExportToRemovableFinished,
|
||||
// Obsolete by ExportFinished
|
||||
// ExportToRemovableFinished,
|
||||
// Notification on end of export, with hyperling to see folder and eject if export was to external media.
|
||||
// Own subclass.
|
||||
ExportFinished,
|
||||
// Works on OSX only.
|
||||
//FIXME Do we want to have it on Linux and Windows? Is it possible to get the Disconnect event on Windows?
|
||||
Mouse3dDisconnected,
|
||||
|
@ -115,15 +119,21 @@ public:
|
|||
// Called when the side bar changes its visibility, as the "slicing complete" notification supplements
|
||||
// the "slicing info" normally shown at the side bar.
|
||||
void set_slicing_complete_large(bool large);
|
||||
// Exporting finished, show this information with path, button to open containing folder and if ejectable - eject button
|
||||
void push_exporting_finished_notification(GLCanvas3D& canvas, std::string path, std::string dir_path, bool on_removable);
|
||||
// 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(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
|
||||
// Move to left to avoid colision with variable layer height gizmo.
|
||||
void set_move_from_overlay(bool move) { m_move_from_overlay = move; }
|
||||
|
||||
|
||||
private:
|
||||
// duration 0 means not disapearing
|
||||
struct NotificationData {
|
||||
|
@ -169,7 +179,7 @@ private:
|
|||
void close() { m_close_pending = true; }
|
||||
// data from newer notification of same type
|
||||
void update(const NotificationData& n);
|
||||
bool get_finished() const { return m_finished; }
|
||||
bool get_finished() const { return m_finished || m_close_pending; }
|
||||
// returns top after movement
|
||||
float get_top() const { return m_top_y; }
|
||||
//returns top in actual frame
|
||||
|
@ -187,25 +197,29 @@ private:
|
|||
protected:
|
||||
// Call after every size change
|
||||
void init();
|
||||
// Part of init()
|
||||
virtual void count_spaces();
|
||||
// Calculetes correct size but not se it in imgui!
|
||||
virtual void set_next_window_size(ImGuiWrapper& imgui);
|
||||
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_close_button(ImGuiWrapper& imgui,
|
||||
virtual void render_close_button(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x , const float win_pos_y);
|
||||
void render_countdown(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x , const float win_pos_y);
|
||||
void render_hypertext(ImGuiWrapper& imgui,
|
||||
virtual void render_hypertext(ImGuiWrapper& imgui,
|
||||
const float text_x, const float text_y,
|
||||
const std::string text,
|
||||
bool more = false);
|
||||
// Left sign could be error or warning sign
|
||||
void render_left_sign(ImGuiWrapper& imgui);
|
||||
void render_minimize_button(ImGuiWrapper& imgui,
|
||||
virtual void render_minimize_button(ImGuiWrapper& imgui,
|
||||
const float win_pos_x, const float win_pos_y);
|
||||
void on_text_click();
|
||||
// Hypertext action, returns if close notification
|
||||
virtual bool on_text_click();
|
||||
|
||||
const NotificationData m_data;
|
||||
|
||||
|
@ -236,7 +250,9 @@ private:
|
|||
// Will go to m_finished next render
|
||||
bool m_close_pending { false };
|
||||
// variables to count positions correctly
|
||||
// all space without text
|
||||
float m_window_width_offset;
|
||||
// Space on left side without text
|
||||
float m_left_indentation;
|
||||
// Total size of notification window - varies based on monitor
|
||||
float m_window_height { 56.0f };
|
||||
|
@ -252,6 +268,8 @@ private:
|
|||
bool m_is_gray { false };
|
||||
//if multiline = true, notification is showing all lines(>2)
|
||||
bool m_multiline { false };
|
||||
// True if minimized button is rendered, helps to decide where is area for invisible close button
|
||||
bool m_minimize_b_visible { false };
|
||||
int m_lines_count{ 1 };
|
||||
// Target for wxWidgets events sent by clicking on the hyperlink available at some notifications.
|
||||
wxEvtHandler* m_evt_handler;
|
||||
|
@ -270,7 +288,6 @@ private:
|
|||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y)
|
||||
override;
|
||||
|
||||
bool m_is_large;
|
||||
bool m_has_print_info { false };
|
||||
std::string m_print_info { std::string() };
|
||||
|
@ -284,6 +301,40 @@ private:
|
|||
int warning_step;
|
||||
};
|
||||
|
||||
class ExportFinishedNotification : public PopNotification
|
||||
{
|
||||
public:
|
||||
ExportFinishedNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool to_removable,const std::string& export_path,const std::string& export_dir_path)
|
||||
: PopNotification(n, id_provider, evt_handler)
|
||||
, m_to_removable(to_removable)
|
||||
, m_export_path(export_path)
|
||||
, m_export_dir_path(export_dir_path)
|
||||
{
|
||||
m_multiline = true;
|
||||
}
|
||||
bool m_to_removable;
|
||||
std::string m_export_path;
|
||||
std::string m_export_dir_path;
|
||||
protected:
|
||||
// Reserves space on right for more buttons
|
||||
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) override;
|
||||
// Renders also button to open directory with exported path and eject removable media
|
||||
virtual void render_close_button(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y) override;
|
||||
void render_eject_button(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y);
|
||||
virtual void render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) override
|
||||
{ m_minimize_b_visible = false; }
|
||||
virtual bool on_text_click() override;
|
||||
// local time of last hover for showing tooltip
|
||||
long m_hover_time { 0 };
|
||||
};
|
||||
|
||||
//pushes notification into the queue of notifications that are rendered
|
||||
//can be used to create custom notification
|
||||
bool push_notification_data(const NotificationData& notification_data, GLCanvas3D& canvas, int timestamp);
|
||||
|
@ -314,7 +365,7 @@ private:
|
|||
//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::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.") },
|
||||
|
|
|
@ -62,6 +62,7 @@ OG_CustomCtrl::OG_CustomCtrl( wxWindow* parent,
|
|||
this->Bind(wxEVT_PAINT, &OG_CustomCtrl::OnPaint, this);
|
||||
this->Bind(wxEVT_MOTION, &OG_CustomCtrl::OnMotion, this);
|
||||
this->Bind(wxEVT_LEFT_DOWN, &OG_CustomCtrl::OnLeftDown, this);
|
||||
this->Bind(wxEVT_LEAVE_WINDOW, &OG_CustomCtrl::OnLeaveWin, this);
|
||||
}
|
||||
|
||||
void OG_CustomCtrl::init_ctrl_lines()
|
||||
|
@ -113,7 +114,15 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
|
|||
{
|
||||
wxCoord v_pos = 0;
|
||||
wxCoord h_pos = 0;
|
||||
for (auto ctrl_line : ctrl_lines) {
|
||||
|
||||
auto correct_line_height = [](int& line_height, wxWindow* win)
|
||||
{
|
||||
int win_height = win->GetSize().GetHeight();
|
||||
if (line_height < win_height)
|
||||
line_height = win_height;
|
||||
};
|
||||
|
||||
for (CtrlLine& ctrl_line : ctrl_lines) {
|
||||
if (&ctrl_line.og_line == &line)
|
||||
{
|
||||
h_pos = m_bmp_mode_sz.GetWidth() + m_h_gap;
|
||||
|
@ -133,6 +142,10 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
|
|||
|
||||
if (line.widget) {
|
||||
h_pos += blinking_button_width;
|
||||
|
||||
for (auto child : line.widget_sizer->GetChildren())
|
||||
if (child->IsWindow())
|
||||
correct_line_height(ctrl_line.height, child->GetWindow());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -143,11 +156,15 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
|
|||
option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0)
|
||||
{
|
||||
h_pos += 3 * blinking_button_width;
|
||||
Field* field = opt_group->get_field(option_set.front().opt_id);
|
||||
correct_line_height(ctrl_line.height, field->getWindow());
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto opt : option_set) {
|
||||
Field* field = opt_group->get_field(opt.opt_id);
|
||||
correct_line_height(ctrl_line.height, field->getWindow());
|
||||
|
||||
ConfigOptionDef option = opt.opt;
|
||||
// add label if any
|
||||
if (!option.label.empty()) {
|
||||
|
@ -281,6 +298,16 @@ void OG_CustomCtrl::OnLeftDown(wxMouseEvent& event)
|
|||
|
||||
}
|
||||
|
||||
void OG_CustomCtrl::OnLeaveWin(wxMouseEvent& event)
|
||||
{
|
||||
for (CtrlLine& line : ctrl_lines)
|
||||
line.is_focused = false;
|
||||
|
||||
Refresh();
|
||||
Update();
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
bool OG_CustomCtrl::update_visibility(ConfigOptionMode mode)
|
||||
{
|
||||
wxCoord v_pos = 0;
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
void OnPaint(wxPaintEvent&);
|
||||
void OnMotion(wxMouseEvent& event);
|
||||
void OnLeftDown(wxMouseEvent& event);
|
||||
void OnLeaveWin(wxMouseEvent& event);
|
||||
|
||||
void init_ctrl_lines();
|
||||
bool update_visibility(ConfigOptionMode mode);
|
||||
|
|
|
@ -151,8 +151,8 @@ void PresetForPrinter::msw_rescale()
|
|||
// PhysicalPrinterDialog
|
||||
//------------------------------------------
|
||||
|
||||
PhysicalPrinterDialog::PhysicalPrinterDialog(wxString printer_name) :
|
||||
DPIDialog(NULL, wxID_ANY, _L("Physical Printer"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||
PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_name) :
|
||||
DPIDialog(parent, wxID_ANY, _L("Physical Printer"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||
m_printer("", wxGetApp().preset_bundle->physical_printers.default_config())
|
||||
{
|
||||
SetFont(wxGetApp().normal_font());
|
||||
|
@ -169,7 +169,7 @@ PhysicalPrinterDialog::PhysicalPrinterDialog(wxString printer_name) :
|
|||
new_printer = false;
|
||||
}
|
||||
|
||||
wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _L("Descriptive name for the printer device") + ":");
|
||||
wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _L("Descriptive name for the printer") + ":");
|
||||
|
||||
m_add_preset_btn = new ScalableButton(this, wxID_ANY, "add_copies", "", wxDefaultSize, wxDefaultPosition, /*wxBU_LEFT | */wxBU_EXACTFIT);
|
||||
m_add_preset_btn->SetFont(wxGetApp().normal_font());
|
||||
|
@ -598,7 +598,7 @@ void PhysicalPrinterDialog::AddPreset(wxEvent& event)
|
|||
void PhysicalPrinterDialog::DeletePreset(PresetForPrinter* preset_for_printer)
|
||||
{
|
||||
if (m_presets.size() == 1) {
|
||||
wxString msg_text = _L("It's not possible to delete last related preset for the printer.");
|
||||
wxString msg_text = _L("It's not possible to delete the last related preset for the printer.");
|
||||
wxMessageDialog dialog(nullptr, msg_text, _L("Infornation"), wxICON_INFORMATION | wxOK);
|
||||
dialog.ShowModal();
|
||||
return;
|
||||
|
|
|
@ -82,7 +82,7 @@ class PhysicalPrinterDialog : public DPIDialog
|
|||
void AddPreset(wxEvent& event);
|
||||
|
||||
public:
|
||||
PhysicalPrinterDialog(wxString printer_name);
|
||||
PhysicalPrinterDialog(wxWindow* parent, wxString printer_name);
|
||||
~PhysicalPrinterDialog();
|
||||
|
||||
void update();
|
||||
|
|
|
@ -578,7 +578,7 @@ struct Sidebar::priv
|
|||
wxButton *btn_export_gcode;
|
||||
wxButton *btn_reslice;
|
||||
ScalableButton *btn_send_gcode;
|
||||
ScalableButton *btn_eject_device;
|
||||
//ScalableButton *btn_eject_device;
|
||||
ScalableButton* btn_export_gcode_removable; //exports to removable drives (appears only if removable drive is connected)
|
||||
|
||||
bool is_collapsed {false};
|
||||
|
@ -750,13 +750,14 @@ Sidebar::Sidebar(Plater *parent)
|
|||
(*btn)->Hide();
|
||||
};
|
||||
|
||||
init_scalable_btn(&p->btn_send_gcode , "export_gcode", _L("Send to printer") + "\tCtrl+Shift+G");
|
||||
init_scalable_btn(&p->btn_eject_device, "eject_sd" , _L("Remove device") + "\tCtrl+T");
|
||||
init_scalable_btn(&p->btn_export_gcode_removable, "export_to_sd", _L("Export to SD card / Flash drive") + "\tCtrl+U");
|
||||
init_scalable_btn(&p->btn_send_gcode , "export_gcode", _L("Send to printer ") + GUI::shortkey_ctrl_prefix() + "Shift+G");
|
||||
// init_scalable_btn(&p->btn_eject_device, "eject_sd" , _L("Remove device ") + GUI::shortkey_ctrl_prefix() + "T");
|
||||
init_scalable_btn(&p->btn_export_gcode_removable, "export_to_sd", _L("Export to SD card / Flash drive ") + GUI::shortkey_ctrl_prefix() + "U");
|
||||
|
||||
// regular buttons "Slice now" and "Export G-code"
|
||||
|
||||
const int scaled_height = p->btn_eject_device->GetBitmapHeight() + 4;
|
||||
// const int scaled_height = p->btn_eject_device->GetBitmapHeight() + 4;
|
||||
const int scaled_height = p->btn_export_gcode_removable->GetBitmapHeight() + 4;
|
||||
auto init_btn = [this](wxButton **btn, wxString label, const int button_height) {
|
||||
*btn = new wxButton(this, wxID_ANY, label, wxDefaultPosition,
|
||||
wxSize(-1, button_height), wxBU_EXACTFIT);
|
||||
|
@ -774,7 +775,7 @@ Sidebar::Sidebar(Plater *parent)
|
|||
complect_btns_sizer->Add(p->btn_export_gcode, 1, wxEXPAND);
|
||||
complect_btns_sizer->Add(p->btn_send_gcode);
|
||||
complect_btns_sizer->Add(p->btn_export_gcode_removable);
|
||||
complect_btns_sizer->Add(p->btn_eject_device);
|
||||
// complect_btns_sizer->Add(p->btn_eject_device);
|
||||
|
||||
|
||||
btns_sizer->Add(p->btn_reslice, 0, wxEXPAND | wxTOP, margin_5);
|
||||
|
@ -797,7 +798,7 @@ Sidebar::Sidebar(Plater *parent)
|
|||
p->plater->select_view_3D("Preview");
|
||||
});
|
||||
p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->send_gcode(); });
|
||||
p->btn_eject_device->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->eject_drive(); });
|
||||
// p->btn_eject_device->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->eject_drive(); });
|
||||
p->btn_export_gcode_removable->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->export_gcode(true); });
|
||||
}
|
||||
|
||||
|
@ -940,9 +941,9 @@ void Sidebar::msw_rescale()
|
|||
p->object_info->msw_rescale();
|
||||
|
||||
p->btn_send_gcode->msw_rescale();
|
||||
p->btn_eject_device->msw_rescale();
|
||||
// p->btn_eject_device->msw_rescale();
|
||||
p->btn_export_gcode_removable->msw_rescale();
|
||||
const int scaled_height = p->btn_eject_device->GetBitmap().GetHeight() + 4;
|
||||
const int scaled_height = p->btn_export_gcode_removable->GetBitmap().GetHeight() + 4;
|
||||
p->btn_export_gcode->SetMinSize(wxSize(-1, scaled_height));
|
||||
p->btn_reslice ->SetMinSize(wxSize(-1, scaled_height));
|
||||
|
||||
|
@ -965,7 +966,7 @@ void Sidebar::sys_color_changed()
|
|||
|
||||
// btn...->msw_rescale() updates icon on button, so use it
|
||||
p->btn_send_gcode->msw_rescale();
|
||||
p->btn_eject_device->msw_rescale();
|
||||
// p->btn_eject_device->msw_rescale();
|
||||
p->btn_export_gcode_removable->msw_rescale();
|
||||
|
||||
p->scrolled->Layout();
|
||||
|
@ -1268,7 +1269,7 @@ void Sidebar::enable_buttons(bool enable)
|
|||
p->btn_reslice->Enable(enable);
|
||||
p->btn_export_gcode->Enable(enable);
|
||||
p->btn_send_gcode->Enable(enable);
|
||||
p->btn_eject_device->Enable(enable);
|
||||
// p->btn_eject_device->Enable(enable);
|
||||
p->btn_export_gcode_removable->Enable(enable);
|
||||
}
|
||||
|
||||
|
@ -1276,8 +1277,8 @@ bool Sidebar::show_reslice(bool show) const { return p->btn_reslice->Sh
|
|||
bool Sidebar::show_export(bool show) const { return p->btn_export_gcode->Show(show); }
|
||||
bool Sidebar::show_send(bool show) const { return p->btn_send_gcode->Show(show); }
|
||||
bool Sidebar::show_export_removable(bool show) const { return p->btn_export_gcode_removable->Show(show); }
|
||||
bool Sidebar::show_eject(bool show) const { return p->btn_eject_device->Show(show); }
|
||||
bool Sidebar::get_eject_shown() const { return p->btn_eject_device->IsShown(); }
|
||||
//bool Sidebar::show_eject(bool show) const { return p->btn_eject_device->Show(show); }
|
||||
//bool Sidebar::get_eject_shown() const { return p->btn_eject_device->IsShown(); }
|
||||
|
||||
bool Sidebar::is_multifilament()
|
||||
{
|
||||
|
@ -1468,6 +1469,13 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi
|
|||
return true;
|
||||
}
|
||||
|
||||
// State to manage showing after export notifications and device ejecting
|
||||
enum ExportingStatus{
|
||||
NOT_EXPORTING,
|
||||
EXPORTING_TO_REMOVABLE,
|
||||
EXPORTING_TO_LOCAL
|
||||
};
|
||||
|
||||
// Plater / private
|
||||
struct Plater::priv
|
||||
{
|
||||
|
@ -1770,8 +1778,9 @@ struct Plater::priv
|
|||
// Caching last value of show_action_buttons parameter for show_action_buttons(), so that a callback which does not know this state will not override it.
|
||||
mutable bool ready_to_slice = { false };
|
||||
// Flag indicating that the G-code export targets a removable device, therefore the show_action_buttons() needs to be called at any case when the background processing finishes.
|
||||
bool writing_to_removable_device { false };
|
||||
bool show_ExportToRemovableFinished_notification { false };
|
||||
ExportingStatus exporting_status { NOT_EXPORTING };
|
||||
std::string last_output_path;
|
||||
std::string last_output_dir_path;
|
||||
bool inside_snapshot_capture() { return m_prevent_snapshots != 0; }
|
||||
bool process_completed_with_error { false };
|
||||
private:
|
||||
|
@ -1969,6 +1978,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_UPDATE_BED_SHAPE, [q](SimpleEvent&) { q->set_bed_shape(); });
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); });
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); });
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_JUMP_TO, [this](wxKeyEvent& evt) { preview->jump_layers_slider(evt); });
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, [this](wxKeyEvent& evt) { preview->move_layers_slider(evt); });
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_EDIT_COLOR_CHANGE, [this](wxKeyEvent& evt) { preview->edit_layers_slider(evt); });
|
||||
|
@ -2043,9 +2053,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
});
|
||||
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this, q](RemovableDrivesChangedEvent &) {
|
||||
this->show_action_buttons(this->ready_to_slice);
|
||||
if (!this->sidebar->get_eject_shown()) {
|
||||
notification_manager->close_notification_of_type(NotificationType::ExportToRemovableFinished);
|
||||
}
|
||||
// Close notification ExportingFinished but only if last export was to removable
|
||||
notification_manager->device_ejected();
|
||||
});
|
||||
// Start the background thread and register this window as a target for update events.
|
||||
wxGetApp().removable_drive_manager()->init(this->q);
|
||||
|
@ -2314,7 +2323,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||
wxMessageDialog msg_dlg(q, format_wxstr(_L(
|
||||
"Some object(s) in file %s looks like saved in inches.\n"
|
||||
"Should I consider them as a saved in inches and convert them?"), from_path(filename)) + "\n",
|
||||
_L("Saved in inches object detected"), wxICON_WARNING | wxYES | wxNO);
|
||||
_L("The object appears to be saved in inches"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (msg_dlg.ShowModal() == wxID_YES)
|
||||
convert_from_imperial_units(model);
|
||||
}
|
||||
|
@ -2912,6 +2921,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
|||
const wxString invalid_str = _L("Invalid data");
|
||||
for (auto btn : {ActionButtonType::abReslice, ActionButtonType::abSendGCode, ActionButtonType::abExport})
|
||||
sidebar->set_btn_label(btn, invalid_str);
|
||||
process_completed_with_error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3511,9 +3521,7 @@ void Plater::priv::on_slicing_completed(wxCommandEvent & evt)
|
|||
void Plater::priv::on_export_began(wxCommandEvent& evt)
|
||||
{
|
||||
if (show_warning_dialog)
|
||||
warnings_dialog();
|
||||
if (this->writing_to_removable_device)
|
||||
this->show_ExportToRemovableFinished_notification = true;
|
||||
warnings_dialog();
|
||||
}
|
||||
void Plater::priv::on_slicing_began()
|
||||
{
|
||||
|
@ -3591,10 +3599,14 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
|||
} else
|
||||
notification_manager->push_slicing_error_notification(message, *q->get_current_canvas3D());
|
||||
this->statusbar()->set_status_text(from_u8(message));
|
||||
const wxString invalid_str = _L("Invalid data");
|
||||
for (auto btn : { ActionButtonType::abReslice, ActionButtonType::abSendGCode, ActionButtonType::abExport })
|
||||
sidebar->set_btn_label(btn, invalid_str);
|
||||
process_completed_with_error = true;
|
||||
if (evt.invalidate_plater())
|
||||
{
|
||||
const wxString invalid_str = _L("Invalid data");
|
||||
for (auto btn : { ActionButtonType::abReslice, ActionButtonType::abSendGCode, ActionButtonType::abExport })
|
||||
sidebar->set_btn_label(btn, invalid_str);
|
||||
process_completed_with_error = true;
|
||||
}
|
||||
|
||||
}
|
||||
if (evt.cancelled())
|
||||
this->statusbar()->set_status_text(_L("Cancelled"));
|
||||
|
@ -3629,13 +3641,14 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
|||
show_action_buttons(false);
|
||||
}
|
||||
// If writing to removable drive was scheduled, show notification with eject button
|
||||
if (this->writing_to_removable_device && this->show_ExportToRemovableFinished_notification) {
|
||||
if (exporting_status == ExportingStatus::EXPORTING_TO_REMOVABLE && !this->process_completed_with_error) {
|
||||
show_action_buttons(false);
|
||||
notification_manager->push_notification(NotificationType::ExportToRemovableFinished, *q->get_current_canvas3D());
|
||||
}
|
||||
notification_manager->push_exporting_finished_notification(*q->get_current_canvas3D(), last_output_path, last_output_dir_path, true);
|
||||
wxGetApp().removable_drive_manager()->set_exporting_finished(true);
|
||||
}else if (exporting_status == ExportingStatus::EXPORTING_TO_LOCAL && !this->process_completed_with_error)
|
||||
notification_manager->push_exporting_finished_notification(*q->get_current_canvas3D(), last_output_path, last_output_dir_path, false);
|
||||
}
|
||||
this->show_ExportToRemovableFinished_notification = false;
|
||||
this->writing_to_removable_device = false;
|
||||
exporting_status = ExportingStatus::NOT_EXPORTING;
|
||||
}
|
||||
|
||||
void Plater::priv::on_layer_editing_toggled(bool enable)
|
||||
|
@ -4306,8 +4319,8 @@ void Plater::priv::show_action_buttons(const bool ready_to_slice) const
|
|||
if (sidebar->show_reslice(false) |
|
||||
sidebar->show_export(true) |
|
||||
sidebar->show_send(send_gcode_shown) |
|
||||
sidebar->show_export_removable(removable_media_status.has_removable_drives) |
|
||||
sidebar->show_eject(removable_media_status.has_eject))
|
||||
sidebar->show_export_removable(removable_media_status.has_removable_drives))
|
||||
// sidebar->show_eject(removable_media_status.has_eject))
|
||||
sidebar->Layout();
|
||||
}
|
||||
else
|
||||
|
@ -4318,8 +4331,8 @@ void Plater::priv::show_action_buttons(const bool ready_to_slice) const
|
|||
if (sidebar->show_reslice(ready_to_slice) |
|
||||
sidebar->show_export(!ready_to_slice) |
|
||||
sidebar->show_send(send_gcode_shown && !ready_to_slice) |
|
||||
sidebar->show_export_removable(!ready_to_slice && removable_media_status.has_removable_drives) |
|
||||
sidebar->show_eject(!ready_to_slice && removable_media_status.has_eject))
|
||||
sidebar->show_export_removable(!ready_to_slice && removable_media_status.has_removable_drives))
|
||||
// sidebar->show_eject(!ready_to_slice && removable_media_status.has_eject))
|
||||
sidebar->Layout();
|
||||
}
|
||||
}
|
||||
|
@ -4727,7 +4740,7 @@ void Plater::load_gcode(const wxString& filename)
|
|||
GCodeProcessor processor;
|
||||
processor.enable_producers(true);
|
||||
processor.enable_machine_envelope_processing(true);
|
||||
processor.process_file(filename.ToUTF8().data());
|
||||
processor.process_file(filename.ToUTF8().data(), false);
|
||||
p->gcode_result = std::move(processor.extract_result());
|
||||
|
||||
// show results
|
||||
|
@ -4958,7 +4971,7 @@ void Plater::export_gcode(bool prefer_removable)
|
|||
if (p->model.objects.empty())
|
||||
return;
|
||||
|
||||
if (p->process_completed_with_error)//here
|
||||
if (p->process_completed_with_error)
|
||||
return;
|
||||
|
||||
// If possible, remove accents from accented latin characters.
|
||||
|
@ -5003,7 +5016,10 @@ void Plater::export_gcode(bool prefer_removable)
|
|||
|
||||
if (! output_path.empty()) {
|
||||
bool path_on_removable_media = removable_drive_manager.set_and_verify_last_save_path(output_path.string());
|
||||
p->writing_to_removable_device = path_on_removable_media;
|
||||
p->notification_manager->new_export_began(path_on_removable_media);
|
||||
p->exporting_status = path_on_removable_media ? ExportingStatus::EXPORTING_TO_REMOVABLE : ExportingStatus::EXPORTING_TO_LOCAL;
|
||||
p->last_output_path = output_path.string();
|
||||
p->last_output_dir_path = output_path.parent_path().string();
|
||||
p->export_gcode(output_path, path_on_removable_media, PrintHostJob());
|
||||
// Storing a path to AppConfig either as path to removable media or a path to internal media.
|
||||
// is_path_on_removable_drive() is called with the "true" parameter to update its internal database as the user may have shuffled the external drives
|
||||
|
@ -5223,6 +5239,10 @@ void Plater::export_toolpaths_to_obj() const
|
|||
|
||||
void Plater::reslice()
|
||||
{
|
||||
// There is "invalid data" button instead "slice now"
|
||||
if (p->process_completed_with_error)
|
||||
return;
|
||||
|
||||
// Stop arrange and (or) optimize rotation tasks.
|
||||
this->stop_jobs();
|
||||
|
||||
|
|
|
@ -117,12 +117,12 @@ void PreferencesDialog::build()
|
|||
option = Option(def, "show_incompatible_presets");
|
||||
m_optgroup_general->append_single_option_line(option);
|
||||
|
||||
def.label = L("Single Instance");
|
||||
def.label = L("Single instance mode");
|
||||
def.type = coBool;
|
||||
#if __APPLE__
|
||||
def.tooltip = L("On OSX there is always only one instance of app running by default. However it is allowed to run multiple instances of same app from the command line. In such case this settings will allow only one instance.");
|
||||
#else
|
||||
def.tooltip = L("If this is enabled, when staring PrusaSlicer and another instance of same PrusaSlicer is running, that instance will be reactivated instead.");
|
||||
def.tooltip = L("If this is enabled, when starting PrusaSlicer and another instance of same PrusaSlicer is running, that instance will be reactivated instead.");
|
||||
#endif
|
||||
def.set_default_value(new ConfigOptionBool{ app_config->has("single_instance") ? app_config->get("single_instance") == "1" : false });
|
||||
option = Option(def, "single_instance");
|
||||
|
@ -153,7 +153,7 @@ void PreferencesDialog::build()
|
|||
|
||||
def.label = L("Ask for unsaved changes when closing application");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("Always ask for unsaved changes when closing application");
|
||||
def.tooltip = L("When closing the application, always ask for unsaved changes");
|
||||
def.set_default_value(new ConfigOptionBool{ app_config->get("default_action_on_close_application") == "none" });
|
||||
option = Option(def, "default_action_on_close_application");
|
||||
m_optgroup_general->append_single_option_line(option);
|
||||
|
@ -235,8 +235,8 @@ void PreferencesDialog::build()
|
|||
|
||||
def.label = L("Sequential slider applied only to top layer");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("If enabled, changes made using the sequential slider, in preview, apply only to gcode top layer, "
|
||||
"if disabled, changes made using the sequential slider, in preview, apply to the whole gcode.");
|
||||
def.tooltip = L("If enabled, changes made using the sequential slider, in preview, apply only to gcode top layer. "
|
||||
"If disabled, changes made using the sequential slider, in preview, apply to the whole gcode.");
|
||||
def.set_default_value(new ConfigOptionBool{ app_config->get("seq_top_layer_only") == "1" });
|
||||
option = Option(def, "seq_top_layer_only");
|
||||
m_optgroup_gui->append_single_option_line(option);
|
||||
|
@ -427,8 +427,8 @@ void PreferencesDialog::create_icon_size_slider()
|
|||
void PreferencesDialog::create_settings_mode_widget()
|
||||
{
|
||||
wxString choices[] = { _L("Old regular layout with the tab bar"),
|
||||
_L("New layout without the tab bar on the plater"),
|
||||
_L("Settings will be shown in the non-modal dialog") };
|
||||
_L("New layout, access via settings button in the top menu"),
|
||||
_L("Settings in non-modal window") };
|
||||
|
||||
auto app_config = get_app_config();
|
||||
int selection = app_config->get("old_settings_layout_mode") == "1" ? 0 :
|
||||
|
@ -437,7 +437,7 @@ void PreferencesDialog::create_settings_mode_widget()
|
|||
|
||||
wxWindow* parent = m_optgroup_gui->ctrl_parent();
|
||||
|
||||
m_layout_mode_box = new wxRadioBox(parent, wxID_ANY, _L("Settings layout mode"), wxDefaultPosition, wxDefaultSize, WXSIZEOF(choices), choices,
|
||||
m_layout_mode_box = new wxRadioBox(parent, wxID_ANY, _L("Layout Options"), wxDefaultPosition, wxDefaultSize, WXSIZEOF(choices), choices,
|
||||
3, wxRA_SPECIFY_ROWS);
|
||||
m_layout_mode_box->SetFont(wxGetApp().normal_font());
|
||||
m_layout_mode_box->SetSelection(selection);
|
||||
|
|
|
@ -253,14 +253,14 @@ void PresetComboBox::edit_physical_printer()
|
|||
if (!m_preset_bundle->physical_printers.has_selection())
|
||||
return;
|
||||
|
||||
PhysicalPrinterDialog dlg(this->GetString(this->GetSelection()));
|
||||
PhysicalPrinterDialog dlg(this->GetParent(),this->GetString(this->GetSelection()));
|
||||
if (dlg.ShowModal() == wxID_OK)
|
||||
update();
|
||||
}
|
||||
|
||||
void PresetComboBox::add_physical_printer()
|
||||
{
|
||||
if (PhysicalPrinterDialog(wxEmptyString).ShowModal() == wxID_OK)
|
||||
if (PhysicalPrinterDialog(this->GetParent(), wxEmptyString).ShowModal() == wxID_OK)
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -675,7 +675,7 @@ void PlaterPresetComboBox::show_add_menu()
|
|||
|
||||
append_menu_item(menu, wxID_ANY, _L("Add physical printer"), "",
|
||||
[this](wxCommandEvent&) {
|
||||
PhysicalPrinterDialog dlg(wxEmptyString);
|
||||
PhysicalPrinterDialog dlg(this->GetParent(), wxEmptyString);
|
||||
if (dlg.ShowModal() == wxID_OK)
|
||||
update();
|
||||
}, "edit_uni", menu, []() { return true; }, wxGetApp().plater());
|
||||
|
|
|
@ -391,7 +391,6 @@ bool RemovableDriveManager::set_and_verify_last_save_path(const std::string &pat
|
|||
#ifndef REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
|
||||
this->update();
|
||||
#endif // REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
|
||||
|
||||
m_last_save_path = this->get_removable_drive_from_path(path);
|
||||
m_exporting_finished = false;
|
||||
return ! m_last_save_path.empty();
|
||||
|
|
|
@ -130,15 +130,16 @@ void SavePresetDialog::Item::update()
|
|||
|
||||
if (m_valid_type == Valid && existing && m_preset_name != m_presets->get_selected_preset_name())
|
||||
{
|
||||
info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists.")) % m_preset_name).str());
|
||||
if (!existing->is_compatible)
|
||||
info_line += "\n" + _L("And selected preset is imcopatible with selected printer.");
|
||||
if (existing->is_compatible)
|
||||
info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists.")) % m_preset_name).str());
|
||||
else
|
||||
info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists and is imcopatible with selected printer.")) % m_preset_name).str());
|
||||
info_line += "\n" + _L("Note: This preset will be replaced after saving");
|
||||
m_valid_type = Warning;
|
||||
}
|
||||
|
||||
if (m_valid_type == Valid && m_preset_name.empty()) {
|
||||
info_line = _L("The empty name is not available.");
|
||||
info_line = _L("The name cannot be empty.");
|
||||
m_valid_type = NoValid;
|
||||
}
|
||||
|
||||
|
@ -171,14 +172,14 @@ void SavePresetDialog::Item::accept()
|
|||
// SavePresetDialog
|
||||
//-----------------------------------------------
|
||||
|
||||
SavePresetDialog::SavePresetDialog(Preset::Type type, std::string suffix)
|
||||
: DPIDialog(nullptr, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
|
||||
SavePresetDialog::SavePresetDialog(wxWindow* parent, Preset::Type type, std::string suffix)
|
||||
: DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
|
||||
{
|
||||
build(std::vector<Preset::Type>{type}, suffix);
|
||||
}
|
||||
|
||||
SavePresetDialog::SavePresetDialog(std::vector<Preset::Type> types, std::string suffix)
|
||||
: DPIDialog(nullptr, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
|
||||
SavePresetDialog::SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix)
|
||||
: DPIDialog(parent, wxID_ANY, _L("Save preset"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
|
||||
{
|
||||
build(types, suffix);
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ class SavePresetDialog : public DPIDialog
|
|||
|
||||
public:
|
||||
|
||||
SavePresetDialog(Preset::Type type, std::string suffix = "");
|
||||
SavePresetDialog(std::vector<Preset::Type> types, std::string suffix = "");
|
||||
SavePresetDialog(wxWindow* parent, Preset::Type type, std::string suffix = "");
|
||||
SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix = "");
|
||||
~SavePresetDialog();
|
||||
|
||||
void AddItem(Preset::Type type, const std::string& suffix);
|
||||
|
|
|
@ -430,7 +430,7 @@ SearchDialog::SearchDialog(OptionsSearcher* searcher)
|
|||
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
SetBackgroundColour(bgr_clr);
|
||||
|
||||
default_string = _L("Type here to search");
|
||||
default_string = _L("Enter a search term");
|
||||
int border = 10;
|
||||
int em = em_unit();
|
||||
|
||||
|
|
|
@ -87,9 +87,9 @@ std::string get_mem_info(bool format_as_html)
|
|||
|
||||
SysInfoDialog::SysInfoDialog()
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
: DPIDialog(NULL, wxID_ANY, (wxGetApp().is_editor() ? wxString(SLIC3R_APP_NAME) : wxString(GCODEVIEWER_APP_NAME)) + " - " + _L("System Information"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, (wxGetApp().is_editor() ? wxString(SLIC3R_APP_NAME) : wxString(GCODEVIEWER_APP_NAME)) + " - " + _L("System Information"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
#else
|
||||
: DPIDialog(NULL, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("System Information"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _L("System Information"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
{
|
||||
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
|
|
|
@ -219,7 +219,7 @@ void Tab::create_preset_tab()
|
|||
"or click this button.")));
|
||||
|
||||
add_scaled_button(panel, &m_search_btn, "search");
|
||||
m_search_btn->SetToolTip(format_wxstr(_L("Click to start a search or use %1% shortcut"), "Ctrl+F"));
|
||||
m_search_btn->SetToolTip(format_wxstr(_L("Search in settings [%1%]"), "Ctrl+F"));
|
||||
|
||||
// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
|
||||
add_scaled_bitmap(this, m_bmp_value_lock , "lock_closed");
|
||||
|
@ -2039,7 +2039,7 @@ void TabPrinter::build_print_host_upload_group(Page* page)
|
|||
wxString description_line_text = _L(""
|
||||
"Note: All parameters from this group are moved to the Physical Printer settings (see changelog).\n\n"
|
||||
"A new Physical Printer profile is created by clicking on the \"cog\" icon right of the Printer profiles combo box, "
|
||||
"by selecting the \"add or remove printers\" item in the Printer combo box. The Physical Printer profile editor opens "
|
||||
"by selecting the \"Add physical printer\" item in the Printer combo box. The Physical Printer profile editor opens "
|
||||
"also when clicking on the \"cog\" icon in the Printer settings tab. The Physical Printer profiles are being stored "
|
||||
"into PrusaSlicer/physical_printer directory.");
|
||||
|
||||
|
@ -3338,7 +3338,7 @@ void Tab::save_preset(std::string name /*= ""*/, bool detach)
|
|||
//! m_treectrl->OnSetFocus();
|
||||
|
||||
if (name.empty()) {
|
||||
SavePresetDialog dlg(m_type, detach ? _u8L("Detached") : "");
|
||||
SavePresetDialog dlg(m_parent, m_type, detach ? _u8L("Detached") : "");
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return;
|
||||
name = dlg.get_name();
|
||||
|
@ -3427,7 +3427,7 @@ void Tab::delete_preset()
|
|||
std::vector<std::string> ph_printers_only = physical_printers.get_printers_with_only_preset(current_preset.name);
|
||||
|
||||
if (!ph_printers.empty()) {
|
||||
msg += _L("Next physical printer(s) has/have selected preset") + ":";
|
||||
msg += _L("The physical printer(s) below is based on the preset, you are going to delete.");
|
||||
for (const std::string& printer : ph_printers)
|
||||
msg += "\n \"" + from_u8(printer) + "\",";
|
||||
msg.RemoveLast();
|
||||
|
@ -3435,7 +3435,7 @@ void Tab::delete_preset()
|
|||
}
|
||||
|
||||
if (!ph_printers_only.empty()) {
|
||||
msg += _L("Next physical printer(s) has/have one and only selected preset") + ":";
|
||||
msg += _L("The physical printer(s) below is based only on the preset, you are going to delete.");
|
||||
for (const std::string& printer : ph_printers_only)
|
||||
msg += "\n \"" + from_u8(printer) + "\",";
|
||||
msg.RemoveLast();
|
||||
|
|
|
@ -522,7 +522,7 @@ void UnsavedChangesModel::Rescale()
|
|||
//------------------------------------------
|
||||
|
||||
UnsavedChangesDialog::UnsavedChangesDialog(const wxString& header)
|
||||
: DPIDialog(nullptr, wxID_ANY, _L("Closing PrusaSlicer: Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe , wxID_ANY, _L("PrusaSlicer is closing: Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
{
|
||||
m_app_config_key = "default_action_on_close_application";
|
||||
|
||||
|
@ -539,7 +539,7 @@ UnsavedChangesDialog::UnsavedChangesDialog(const wxString& header)
|
|||
}
|
||||
|
||||
UnsavedChangesDialog::UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset)
|
||||
: DPIDialog(nullptr, wxID_ANY, _L("Switching Presets: Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
: DPIDialog((wxWindow*)wxGetApp().mainframe, wxID_ANY, _L("Switching Presets: Unsaved Changes"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
{
|
||||
m_app_config_key = "default_action_on_select_preset";
|
||||
|
||||
|
@ -737,7 +737,7 @@ void UnsavedChangesDialog::show_info_line(Action action, std::string preset_name
|
|||
text = _L("All modified options will be reverted.");
|
||||
else {
|
||||
if (preset_name.empty())
|
||||
text = action == Action::Save ? _L("Save the selected options.") : _L("Transfer the selected options to the newly selected presets.");
|
||||
text = action == Action::Save ? _L("Save the selected options.") : _L("Transfer the selected settings to the newly selected preset.");
|
||||
else
|
||||
text = format_wxstr(
|
||||
action == Action::Save ?
|
||||
|
@ -781,7 +781,7 @@ bool UnsavedChangesDialog::save(PresetCollection* dependent_presets)
|
|||
|
||||
// for system/default/external presets we should take an edited name
|
||||
if (preset.is_system || preset.is_default || preset.is_external) {
|
||||
SavePresetDialog save_dlg(preset.type);
|
||||
SavePresetDialog save_dlg(this, preset.type);
|
||||
if (save_dlg.ShowModal() != wxID_OK) {
|
||||
m_exit_action = Action::Discard;
|
||||
return false;
|
||||
|
@ -809,7 +809,7 @@ bool UnsavedChangesDialog::save(PresetCollection* dependent_presets)
|
|||
|
||||
|
||||
if (!types_for_save.empty()) {
|
||||
SavePresetDialog save_dlg(types_for_save);
|
||||
SavePresetDialog save_dlg(this, types_for_save);
|
||||
if (save_dlg.ShowModal() != wxID_OK) {
|
||||
m_exit_action = Action::Discard;
|
||||
return false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue