diff --git a/resources/icons/search_blink.svg b/resources/icons/search_blink.svg index 249bb9090..467fb5e17 100644 --- a/resources/icons/search_blink.svg +++ b/resources/icons/search_blink.svg @@ -2,12 +2,6 @@ - + + diff --git a/resources/ui_layout/Readme.md b/resources/ui_layout/Readme.md index 7cfbbb868..08cf5e828 100644 --- a/resources/ui_layout/Readme.md +++ b/resources/ui_layout/Readme.md @@ -44,7 +44,7 @@ each parameter is separated by ':' * full_label: to override the label by the "full one". * full_width: to tell to create a field that span the full width. * sidetext$STR: the suffix at the right of the widget (like 'mm'). - * sidetext_width$INT: the suffix label length (override the group one). 0 for auto. + * sidetext_width$INT: the suffix label length (override the group one). -& for auto. * simple|advanced|expert: add one of these to modify the mode in which this setting appear. * width$INT: change the width of the field. Shouod work on most type of settings. * height$INT: change the height of the field. Don't works with every type of setting. diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index 948cd6ff3..3d4d8d887 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -39,10 +39,10 @@ group:Quality setting:width$5:thin_walls_overlap setting:thin_walls_merge end_line -group:Overhangs +group:label_width$12:Overhangs line:threshold for - setting:label$bridge speed and fan:width$5:overhangs_width_speed - setting:label$bridge flow:width$5:overhangs_width + setting:label$Bridge speed and fan:width$5:overhangs_width_speed + setting:label$Bridge flow:width$5:overhangs_width end_line line:Extrusion direction setting:sidetext_width$1:overhangs_reverse @@ -80,12 +80,12 @@ group:Filtering setting:resolution setting:model_precision setting:slice_closing_radius -group:label_width$8:Modifying slices +group:Modifying slices line:Curve smoothing setting:width$6:curve_smoothing_precision setting:width$6:curve_smoothing_angle_convex setting:width$6:curve_smoothing_angle_concave - setting:width$6:curve_smoothing_cutoff_dist + setting:label_width$6:width$6:curve_smoothing_cutoff_dist end_line setting:hole_to_polyhole line:XY compensation @@ -118,36 +118,36 @@ group:Reducing printing time setting:infill_every_layers setting:infill_only_where_needed line:Supporting dense layer - setting:infill_dense + setting:sidetext_width$0:infill_dense setting:infill_dense_algo end_line group:sidetext_width$3:Advanced setting:solid_infill_every_layers setting:solid_infill_below_area line:Angle - setting:label_width$6:width$5:fill_angle + setting:label_width$8:width$5:fill_angle setting:label_width$6:width$5:bridge_angle setting:label_width$6:width$5:label$increment:fill_angle_increment end_line line:Anchor solid infill by X mm - setting:label_width$6:width$5:external_infill_margin + setting:label_width$8:width$5:external_infill_margin setting:label_width$6:width$5:bridged_infill_margin end_line setting:only_retract_when_crossing_perimeters setting:infill_first group:Advanced Infill options line:Ironing infill tuning - setting:label_width$9:width$5:fill_smooth_distribution - setting:label$Spacing between ironing lines:width$5:sidetext_width$7:fill_smooth_width + setting:label_width$8:width$5:fill_smooth_distribution + setting:label_width$26:label$Spacing between ironing lines:width$5:sidetext_width$7:fill_smooth_width end_line group:Ironing post-process (This will go on top of infills and perimeters) line:Enable ironing post-process - setting:label$_:ironing + setting:label$_:sidetext_width$0:ironing setting:label$On:ironing_type end_line line:Tuning ironing - setting:ironing_flowrate - setting:ironing_spacing + setting:label_width$8:width$5:ironing_flowrate + setting:label_width$26:width$5:ironing_spacing end_line page:Skirt & Brim:skirt+brim diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 81730c78d..6f80d4fa6 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -764,7 +764,7 @@ void PrintConfigDef::init_fff_params() def->full_label = L("Default infill margin"); def->category = OptionCategory::infill; def->tooltip = L("This parameter grows the top/bottom/solid layers by the specified MM to anchor them into the part. Put 0 to deactivate it. Can be a % of the width of the perimeters."); - def->sidetext = L("mm"); + def->sidetext = L("mm/%"); def->ratio_over = "perimeter_extrusion_width"; def->min = 0; def->mode = comExpert; @@ -775,7 +775,7 @@ void PrintConfigDef::init_fff_params() def->full_label = L("Bridge margin"); def->category = OptionCategory::infill; def->tooltip = L("This parameter grows the bridged solid infill layers by the specified MM to anchor them into the part. Put 0 to deactivate it. Can be a % of the width of the external perimeter."); - def->sidetext = L("mm"); + def->sidetext = L("mm/%"); def->ratio_over = "external_perimeter_extrusion_width"; def->min = 0; def->mode = comExpert; @@ -897,15 +897,15 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionBool(false)); def = this->add("external_perimeters_nothole", coBool); - def->label = L("only for outter side"); - def->full_label = L("ext peri first for outter side"); + def->label = L("Only for outer side"); + def->full_label = L("ext peri first for outer side"); def->category = OptionCategory::perimeter; def->tooltip = L("Only do the vase trick on the external side. Useful when the thikness is too low."); def->mode = comExpert; def->set_default_value(new ConfigOptionBool(true)); def = this->add("external_perimeters_hole", coBool); - def->label = L("only for inner side"); + def->label = L("Only for inner side"); def->full_label = L("ext peri first for inner side"); def->category = OptionCategory::perimeter; def->tooltip = L("Only do the vase trick on the external side. Useful when you only want to remode seam from screw hole."); @@ -1389,6 +1389,7 @@ void PrintConfigDef::init_fff_params() def = this->add("filament_density", coFloats); def->label = L("Density"); + def->category = OptionCategory::filament; def->tooltip = L("Enter your filament density here. This is only for statistical information. " "A decent way is to weigh a known length of filament and compute the ratio " "of the length to volume. Better is to calculate the volume directly through displacement."); @@ -1607,7 +1608,7 @@ void PrintConfigDef::init_fff_params() def->ratio_over = "top_infill_extrusion_width"; def->min = 0; def->mode = comExpert; - def->sidetext = L("% or mm"); + def->sidetext = L("mm/%"); def->set_default_value(new ConfigOptionFloatOrPercent(50, true)); def = this->add("fill_smooth_distribution", coPercent); @@ -3850,8 +3851,8 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloat(10.)); def = this->add("xy_size_compensation", coFloat); - def->label = L("Outter"); - def->full_label = L("Outter XY size compensation"); + def->label = L("outer"); + def->full_label = L("outer XY size compensation"); def->category = OptionCategory::slicing; def->tooltip = L("The object will be grown/shrunk in the XY plane by the configured value " "(negative = inwards, positive = outwards). This might be useful for fine-tuning sizes." diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 9060286ee..7395f8758 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -68,7 +68,7 @@ Field::~Field() wxWindow* win = getWindow(); win->Destroy(); win = nullptr; -} + } } void Field::PostInitialize() @@ -79,8 +79,8 @@ void Field::PostInitialize() { case coPercents: case coFloats: - case coStrings: - case coBools: + case coStrings: + case coBools: case coPoints: case coInts: { auto tag_pos = m_opt_id.find("#"); @@ -220,7 +220,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true wxString label = m_opt.full_label.empty() ? _(m_opt.label) : _(m_opt.full_label); show_error(m_parent, from_u8((boost::format(_utf8(L("%s doesn't support percentage"))) % label).str())); set_value(double_to_string(m_opt.min), true); - m_value = m_opt.min; + m_value = double(m_opt.min); break; } double val; @@ -284,28 +284,29 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true if (m_opt.min > val) val = m_opt.min; set_value(double_to_string(val), true); } else if (((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) || - (m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1)) && - (m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast(m_value))) - { - if (!check_value) { - m_value.clear(); - break; - } - - const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm"; - const wxString stVal = double_to_string(val, 2); - const wxString msg_text = from_u8((boost::format(_utf8(L("Do you mean %s%% instead of %s %s?\n" - "Select YES if you want to change this value to %s%%, \n" - "or NO if you are sure that %s %s is a correct value."))) % stVal % stVal % sidetext % stVal % stVal % sidetext).str()); - wxMessageDialog dialog(m_parent, msg_text, _(L("Parameter validation")) + ": " + m_opt_id, wxICON_WARNING | wxYES | wxNO); - if (dialog.ShowModal() == wxID_YES) { - set_value(from_u8((boost::format("%s%%") % stVal).str()), false/*true*/); - str += "%%"; - } else - set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "." + (m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1)) && + (m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast(m_value))) + { + if (!check_value) { + m_value.clear(); + break; } + + const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm"; + const wxString stVal = double_to_string(val, 2); + const wxString msg_text = from_u8((boost::format(_utf8(L("Do you mean %s%% instead of %s %s?\n" + "Select YES if you want to change this value to %s%%, \n" + "or NO if you are sure that %s %s is a correct value."))) % stVal % stVal % sidetext % stVal % stVal % sidetext).str()); + wxMessageDialog dialog(m_parent, msg_text, _(L("Parameter validation")) + ": " + m_opt_id , wxICON_WARNING | wxYES | wxNO); + if (dialog.ShowModal() == wxID_YES) { + set_value(from_u8((boost::format("%s%%") % stVal).str()), false/*true*/); + str += "%%"; + } + else + set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "." } } + } m_value = std::string(str.ToUTF8().data()); break; } @@ -318,7 +319,7 @@ void Field::msw_rescale() { // update em_unit value m_em_unit = em_unit(m_parent); - } +} void Field::sys_color_changed() { @@ -564,7 +565,7 @@ void TextCtrl::msw_rescale() if (parent_is_custom_ctrl) field->SetSize(size); else - field->SetMinSize(size); + field->SetMinSize(size); } } @@ -620,9 +621,8 @@ void CheckBox::set_value(const boost::any& value, bool change_event) m_last_meaningful_value = value; dynamic_cast(window)->SetValue(m_is_na_val ? false : boost::any_cast(value) != 0); } - else{ + else dynamic_cast(window)->SetValue(boost::any_cast(value)); - } m_disable_change_event = false; } @@ -692,7 +692,7 @@ void SpinCtrl::BUILD() { break; } - const double min_val = m_opt.min == INT_MIN + const int min_val = m_opt.min == INT_MIN #ifdef __WXOSX__ // We will forcibly set the input value for SpinControl, since the value // inserted from the keyboard is not updated under OSX. @@ -701,8 +701,8 @@ void SpinCtrl::BUILD() { // less then min_val. || m_opt.min > 0 #endif - ? 0. : m_opt.min; - const double max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647.; + ? 0 : m_opt.min; + const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, 0|wxTE_PROCESS_ENTER, min_val, max_val, default_value); @@ -804,7 +804,7 @@ void SpinCtrl::msw_rescale() if (parent_is_custom_ctrl) field->SetSize(wxSize(def_width() * m_em_unit, lround(opt_height * m_em_unit))); else - field->SetMinSize(wxSize(def_width() * m_em_unit, int(1.9f*field->GetFont().GetPixelSize().y))); + field->SetMinSize(wxSize(def_width() * m_em_unit, int(1.9f*field->GetFont().GetPixelSize().y))); } #ifdef __WXOSX__ @@ -1027,10 +1027,10 @@ void Choice::set_value(const boost::any& value, bool change_event) case coString: case coStrings: { wxString text_value; - if (m_opt.type == coInt) - text_value = wxString::Format(_T("%i"), int(boost::any_cast(value))); + if (m_opt.type == coInt) + text_value = wxString::Format(_T("%i"), int(boost::any_cast(value))); else - text_value = boost::any_cast(value); + text_value = boost::any_cast(value); size_t idx = 0; for (auto el : m_opt.enum_values) { @@ -1045,11 +1045,11 @@ void Choice::set_value(const boost::any& value, bool change_event) field->SetValue(text_value); } else - field->SetSelection(idx); - break; - } - case coEnum: { - int val = boost::any_cast(value); + field->SetSelection(idx); + break; + } + case coEnum: { + int val = boost::any_cast(value); if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "solid_fill_pattern" || m_opt_id == "fill_pattern" || m_opt_id == "support_material_interface_pattern" || m_opt_id == "brim_ears_pattern") val = idx_from_enum_value(val); @@ -1142,6 +1142,7 @@ void Choice::set_values(const wxArrayString &values) m_disable_change_event = false; } + boost::any& Choice::get_value() { choice_ctrl* field = dynamic_cast(window); @@ -1154,7 +1155,7 @@ boost::any& Choice::get_value() if (m_opt_id == rp_option) return m_value = boost::any(ret_str); - if (m_opt.type == coEnum) + if (m_opt.type == coEnum) { int ret_enum = field->GetSelection(); if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "solid_fill_pattern" @@ -1267,11 +1268,11 @@ void Choice::msw_rescale() void ColourPicker::BUILD() { - auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord); - if (m_opt.height >= 0) size.SetHeight(m_opt.height * m_em_unit); - if (m_opt.width >= 0) size.SetWidth(m_opt.width * m_em_unit); + auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord); + if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit); + if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit); - // Validate the color + // Validate the color wxColour clr = wxTransparentColour; if (m_opt.type == coStrings) clr = wxColour{wxString{ m_opt.get_default_value()->get_at(m_opt_idx) }}; @@ -1358,7 +1359,7 @@ void ColourPicker::msw_rescale() if (parent_is_custom_ctrl) field->SetSize(size); else - field->SetMinSize(size); + field->SetMinSize(size); if (field->GetColour() == wxTransparentColour) set_undef_value(field); @@ -1423,9 +1424,9 @@ void PointCtrl::msw_rescale() y_textctrl->SetSize(field_size); } else { - x_textctrl->SetMinSize(field_size); - y_textctrl->SetMinSize(field_size); -} + x_textctrl->SetMinSize(field_size); + y_textctrl->SetMinSize(field_size); + } } bool PointCtrl::value_was_changed(wxTextCtrl* win) diff --git a/src/slic3r/GUI/OG_CustomCtrl.cpp b/src/slic3r/GUI/OG_CustomCtrl.cpp index 81cb5d7d6..56a11b67b 100644 --- a/src/slic3r/GUI/OG_CustomCtrl.cpp +++ b/src/slic3r/GUI/OG_CustomCtrl.cpp @@ -82,7 +82,7 @@ void OG_CustomCtrl::init_ctrl_lines() wxCoord height; // if we have a single option with no label, no sidetext just add it directly to sizer - if (option_set.size() == 1 && opt_group->label_width == 0 && option_set.front().opt.full_width && + if (option_set.size() == 1 && opt_group->title_width == 0 && option_set.front().opt.full_width && option_set.front().opt.label.empty() && option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) @@ -90,10 +90,10 @@ void OG_CustomCtrl::init_ctrl_lines() height = m_bmp_blinking_sz.GetHeight() + m_v_gap; ctrl_lines.emplace_back(CtrlLine(height, this, line, true)); } - else if (opt_group->label_width != 0 && !line.label.IsEmpty()) + else if (opt_group->title_width != 0 && !line.label.IsEmpty()) { wxSize label_sz = GetTextExtent(line.label); - height = label_sz.y * (label_sz.GetWidth() > int(opt_group->label_width * m_em_unit) ? 2 : 1) + m_v_gap; + height = label_sz.y * (label_sz.GetWidth() > int(opt_group->title_width * m_em_unit) ? 2 : 1) + m_v_gap; ctrl_lines.emplace_back(CtrlLine(height, this, line)); } else @@ -135,8 +135,8 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/) } wxString label = line.label; - if (opt_group->label_width != 0 && !label.IsEmpty()) - h_pos += opt_group->label_width * m_em_unit + m_h_gap; + if (opt_group->title_width != 0 && !label.IsEmpty()) + h_pos += opt_group->title_width * m_em_unit + m_h_gap; int blinking_button_width = m_bmp_blinking_sz.GetWidth() + m_h_gap; @@ -155,29 +155,50 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/) option_set.front().opt.label.empty() && option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) { - h_pos += 3 * blinking_button_width; + h_pos += 2 * 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) { + for (size_t i = 0; i < option_set.size(); ++i) { + if (i >= ctrl_line.is_visible.size() || !ctrl_line.is_visible[i]) + continue; + const Option& opt = option_set[i]; 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()) { + std::string opt_label = (option.label.empty() || option.label.back() != '_') ? option.label : option.label.substr(0, option.label.size() - 1); //! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1 - label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ? - _CTX(option.label, "Layers") : _(option.label); - label += ":"; + label = (opt_label == L_CONTEXT("Top", "Layers") || opt_label == L_CONTEXT("Bottom", "Layers")) ? + _CTX(opt_label, "Layers") : _(opt_label); + bool no_dots = label.empty() || option.label.back() == '_'; + if (!no_dots) + label += ":"; - wxPaintDC dc(this); - dc.SetFont(m_font); - h_pos += dc.GetMultiLineTextExtent(label).x + m_h_gap; + if (!label.empty()) { + wxPaintDC dc(this); + dc.SetFont(m_font); + if (option.label_width >= 0) { + if (option.label_width != 0) { + h_pos += option.label_width * m_em_unit; + } else { + h_pos += dc.GetMultiLineTextExtent(label).x; + } + } else { + if (opt_group->label_width > 0) { + h_pos += opt_group->label_width * m_em_unit; + } else { + h_pos += dc.GetMultiLineTextExtent(label).x; + } + } + h_pos += m_h_gap; + } } - h_pos += 3 * blinking_button_width; + h_pos += 2 * blinking_button_width; if (field == field_in) break; @@ -187,15 +208,15 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/) break; // add sidetext if any - if (!option.sidetext.empty() || opt_group->sidetext_width > 0) - h_pos += opt_group->sidetext_width * m_em_unit + m_h_gap; + if ((!option.sidetext.empty() || opt_group->sidetext_width > 0 || option.sidetext_width > 0) && option.sidetext_width != 0) + h_pos += (option.sidetext_width > 0 ? option.sidetext_width : opt_group->sidetext_width)* m_em_unit + m_h_gap; if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back()) h_pos += lround(0.6 * m_em_unit); } break; } - if (ctrl_line.is_visible) + if (ctrl_line.is_line_visible) v_pos += ctrl_line.height; } @@ -220,7 +241,7 @@ void OG_CustomCtrl::OnPaint(wxPaintEvent&) wxCoord v_pos = 0; for (CtrlLine& line : ctrl_lines) { - if (!line.is_visible) + if (!line.is_line_visible) continue; line.render(dc, v_pos); v_pos += line.height; @@ -315,7 +336,7 @@ bool OG_CustomCtrl::update_visibility(ConfigOptionMode mode) size_t invisible_lines = 0; for (CtrlLine& line : ctrl_lines) { line.update_visibility(mode); - if (line.is_visible) + if (line.is_line_visible) v_pos += (wxCoord)line.height; else invisible_lines++; @@ -338,14 +359,15 @@ void OG_CustomCtrl::correct_widgets_position(wxSizer* widget, const Line& line, auto children = widget->GetChildren(); wxPoint line_pos = get_pos(line, field); int line_height = get_height(line); - for (auto child : children) - if (child->IsWindow()) { + for (auto child : children) { + if (child->IsWindow() && child->IsShown()) { wxPoint pos = line_pos; wxSize sz = child->GetWindow()->GetSize(); pos.y += std::max(0, int(0.5 * (line_height - sz.y))); child->GetWindow()->SetPosition(pos); line_pos.x += sz.x + m_h_gap; } + } }; void OG_CustomCtrl::msw_rescale() @@ -361,7 +383,7 @@ void OG_CustomCtrl::msw_rescale() wxCoord v_pos = 0; for (CtrlLine& line : ctrl_lines) { line.msw_rescale(); - if (line.is_visible) { + if (line.is_line_visible) { v_pos += (wxCoord)line.height; } } @@ -393,7 +415,7 @@ OG_CustomCtrl::CtrlLine::CtrlLine( wxCoord height, void OG_CustomCtrl::CtrlLine::correct_items_positions() { - if (draw_just_act_buttons || !is_visible) + if (draw_just_act_buttons || !is_line_visible) return; if (og_line.near_label_widget_win) @@ -421,9 +443,9 @@ void OG_CustomCtrl::CtrlLine::msw_rescale() if (draw_just_act_buttons) height = get_bitmap_size(create_scaled_bitmap("empty")).GetHeight(); - if (ctrl->opt_group->label_width != 0 && !og_line.label.IsEmpty()) { + if (ctrl->opt_group->title_width != 0 && !og_line.label.IsEmpty()) { wxSize label_sz = ctrl->GetTextExtent(og_line.label); - height = label_sz.y * (label_sz.GetWidth() > int(ctrl->opt_group->label_width * ctrl->m_em_unit) ? 2 : 1) + ctrl->m_v_gap; + height = label_sz.y * (label_sz.GetWidth() > int(ctrl->opt_group->title_width * ctrl->m_em_unit) ? 2 : 1) + ctrl->m_v_gap; } if (og_line.get_options().front().opt.full_width) { @@ -439,21 +461,26 @@ void OG_CustomCtrl::CtrlLine::update_visibility(ConfigOptionMode mode) { const std::vector