Refactor of ConfigDef / ConfigOptionDef / PrintConfigDef /

Field and other UI elements to handle enums in a generic way.
Needs a review by @yusanka
This commit is contained in:
Vojtech Bubnik 2023-02-01 15:31:10 +01:00 committed by YuSanka
parent a1b0188e3a
commit d58c8b1bbd
14 changed files with 627 additions and 586 deletions

View File

@ -268,7 +268,7 @@ ConfigOption* ConfigOptionDef::create_empty_option() const
// case coPoint3s: return new ConfigOptionPoint3s(); // case coPoint3s: return new ConfigOptionPoint3s();
case coBool: return new ConfigOptionBool(); case coBool: return new ConfigOptionBool();
case coBools: return new ConfigOptionBools(); case coBools: return new ConfigOptionBools();
case coEnum: return new ConfigOptionEnumGeneric(this->enum_keys_map); case coEnum: return new ConfigOptionEnumGeneric(this->enum_def->m_enum_keys_map);
default: throw ConfigurationError(std::string("Unknown option type for option ") + this->label); default: throw ConfigurationError(std::string("Unknown option type for option ") + this->label);
} }
} }
@ -279,7 +279,7 @@ ConfigOption* ConfigOptionDef::create_default_option() const
if (this->default_value) if (this->default_value)
return (this->default_value->type() == coEnum) ? return (this->default_value->type() == coEnum) ?
// Special case: For a DynamicConfig, convert a templated enum to a generic enum. // Special case: For a DynamicConfig, convert a templated enum to a generic enum.
new ConfigOptionEnumGeneric(this->enum_keys_map, this->default_value->getInt()) : new ConfigOptionEnumGeneric(this->enum_def->m_enum_keys_map, this->default_value->getInt()) :
this->default_value->clone(); this->default_value->clone();
return this->create_empty_option(); return this->create_empty_option();
} }
@ -303,6 +303,31 @@ ConfigOptionDef* ConfigDef::add_nullable(const t_config_option_key &opt_key, Con
return def; return def;
} }
void ConfigDef::finalize()
{
// Validate & finalize open & closed enums.
for (std::pair<const t_config_option_key, ConfigOptionDef> &kvp : options) {
ConfigOptionDef& def = kvp.second;
if (def.type == coEnum) {
assert(def.enum_def);
assert(def.enum_def->is_valid_closed_enum());
assert(def.gui_type != ConfigOptionDef::GUIType::i_enum_open &&
def.gui_type != ConfigOptionDef::GUIType::f_enum_open &&
def.gui_type != ConfigOptionDef::GUIType::select_open);
def.enum_def->finalize_closed_enum();
} else if (def.gui_type == ConfigOptionDef::GUIType::i_enum_open || def.gui_type == ConfigOptionDef::GUIType::f_enum_open ||
def.gui_type == ConfigOptionDef::GUIType::select_open) {
assert(def.enum_def);
assert(def.enum_def->is_valid_open_enum());
assert(def.gui_type != ConfigOptionDef::GUIType::i_enum_open || def.type == coInt || def.type == coInts);
assert(def.gui_type != ConfigOptionDef::GUIType::f_enum_open || def.type == coFloat || def.type == coPercent || def.type == coFloatOrPercent);
assert(def.gui_type != ConfigOptionDef::GUIType::select_open || def.type == coString || def.type == coStrings);
} else {
assert(! def.enum_def);
}
}
}
std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, std::function<bool(const ConfigOptionDef &)> filter) const std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, std::function<bool(const ConfigOptionDef &)> filter) const
{ {
// prepare a function for wrapping text // prepare a function for wrapping text
@ -378,8 +403,8 @@ std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, s
descr += " ("; descr += " (";
if (!def.sidetext.empty()) { if (!def.sidetext.empty()) {
descr += def.sidetext + ", "; descr += def.sidetext + ", ";
} else if (!def.enum_values.empty()) { } else if (def.enum_def->has_values()) {
descr += boost::algorithm::join(def.enum_values, ", ") + "; "; descr += boost::algorithm::join(def.enum_def->values(), ", ") + "; ";
} }
descr += "default: " + def.default_value->serialize() + ")"; descr += "default: " + def.default_value->serialize() + ")";
} }
@ -1142,7 +1167,7 @@ bool DynamicConfig::read_cli(int argc, const char* const argv[], t_config_option
} }
const t_config_option_key &opt_key = it->second; const t_config_option_key &opt_key = it->second;
const ConfigOptionDef &optdef = this->def()->options.at(opt_key); const ConfigOptionDef &optdef = *this->option_def(opt_key);
// If the option type expects a value and it was not already provided, // If the option type expects a value and it was not already provided,
// look for it in the next token. // look for it in the next token.

View File

@ -11,6 +11,7 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <type_traits>
#include <vector> #include <vector>
#include <float.h> #include <float.h>
#include "libslic3r.h" #include "libslic3r.h"
@ -226,6 +227,7 @@ enum ForwardCompatibilitySubstitutionRule
EnableSilentDisableSystem, EnableSilentDisableSystem,
}; };
class ConfigDef;
class ConfigOption; class ConfigOption;
class ConfigOptionDef; class ConfigOptionDef;
// For forward definition of ConfigOption in ConfigOptionUniquePtr, we have to define a custom deleter. // For forward definition of ConfigOption in ConfigOptionUniquePtr, we have to define a custom deleter.
@ -1547,7 +1549,7 @@ public:
return false; return false;
} }
// Map from an enum name to an enum integer value. // Map from an enum integer value to name.
static const t_config_enum_names& get_enum_names(); static const t_config_enum_names& get_enum_names();
// Map from an enum name to an enum integer value. // Map from an enum name to an enum integer value.
static const t_config_enum_values& get_enum_values(); static const t_config_enum_values& get_enum_values();
@ -1619,6 +1621,177 @@ private:
template<class Archive> void serialize(Archive& ar) { ar(cereal::base_class<ConfigOptionInt>(this)); } template<class Archive> void serialize(Archive& ar) { ar(cereal::base_class<ConfigOptionInt>(this)); }
}; };
// Definition of values / labels for a combo box.
// Mostly used for closed enums (when type == coEnum), but may be used for
// open enums with ints resp. floats, if gui_type is set to GUIType::i_enum_open" resp. GUIType::f_enum_open.
class ConfigOptionEnumDef {
public:
bool has_values() const { return ! m_values.empty(); }
bool has_labels() const { return ! m_labels.empty(); }
const std::vector<std::string>& values() const { return m_values; }
const std::string& value(int idx) const { return m_values[idx]; }
// Used for open enums (gui_type is set to GUIType::i_enum_open" resp. GUIType::f_enum_open).
// If values not defined, use labels.
const std::vector<std::string>& enums() const {
assert(this->is_valid_open_enum());
return this->has_values() ? m_values : m_labels;
}
// Used for closed enums. If labels are not defined, use values instead.
const std::vector<std::string>& labels() const { return this->has_labels() ? m_labels : m_values; }
const std::string& label(int idx) const { return this->labels()[idx]; }
// Look up a closed enum value of this combo box based on an index of the combo box value / label.
// Such a mapping should always succeed.
int index_to_enum(int index) const {
// It has to be a closed enum, thus values have to be defined.
assert(this->is_valid_closed_enum());
assert(index >= 0 && index < int(m_values.size()));
if (m_values_ordinary)
return index;
else {
auto it = m_enum_keys_map->find(m_values[index]);
assert(it != m_enum_keys_map->end());
return it->second;
}
}
// Look up an index of value / label of this combo box based on enum value.
// Such a mapping may fail, thus an optional is returned.
std::optional<int> enum_to_index(int enum_val) const {
assert(this->is_valid_closed_enum());
assert(enum_val >= 0 && enum_val < int(m_enum_names->size()));
if (m_values_ordinary)
return { enum_val };
else {
auto it = std::find(m_values.begin(), m_values.end(), (*m_enum_names)[enum_val]);
return it == m_values.end() ? std::optional<int>{} : std::optional<int>{ int(it - m_values.begin()) };
}
}
// Look up an index of value / label of this combo box based on value string.
std::optional<int> value_to_index(const std::string &value) const {
assert(this->is_valid_open_enum() || this->is_valid_closed_enum());
auto it = std::find(m_values.begin(), m_values.end(), value);
return it == m_values.end() ?
std::optional<int>{} : std::optional<int>{ it - m_values.begin() };
}
// Look up an index of label of this combo box. Used for open enums.
std::optional<int> label_to_index(const std::string &value) const {
assert(is_valid_open_enum());
const auto &ls = this->labels();
auto it = std::find(ls.begin(), ls.end(), value);
return it == ls.end() ?
std::optional<int>{} : std::optional<int>{ it - ls.begin() };
}
std::optional<std::reference_wrapper<const std::string>> enum_to_value(int enum_val) const {
assert(this->is_valid_closed_enum());
auto opt = this->enum_to_index(enum_val);
return opt.has_value() ?
std::optional<std::reference_wrapper<const std::string>>{ this->value(opt.value()) } :
std::optional<std::reference_wrapper<const std::string>>{};
}
std::optional<std::reference_wrapper<const std::string>> enum_to_label(int enum_val) const {
assert(this->is_valid_closed_enum());
auto opt = this->enum_to_index(enum_val);
return opt.has_value() ?
std::optional<std::reference_wrapper<const std::string>>{ this->label(opt.value()) } :
std::optional<std::reference_wrapper<const std::string>>{};
}
#ifndef NDEBUG
bool is_valid_closed_enum() const {
return m_enum_names != nullptr && m_enum_keys_map != nullptr &&
! m_values.empty() && (m_labels.empty() || m_values.size() == m_labels.size());
}
bool is_valid_open_enum() const {
return m_enum_names == nullptr && m_enum_keys_map == nullptr &&
(! m_values.empty() || ! m_labels.empty()) && (m_values.empty() || m_labels.empty() || m_values.size() == m_labels.size());
}
#endif // NDEBUG
void clear() {
m_values_ordinary = false;
m_enum_names = nullptr;
m_enum_keys_map = nullptr;
m_values.clear();
m_labels.clear();
}
ConfigOptionEnumDef* clone() const { return new ConfigOptionEnumDef{ *this }; }
private:
friend ConfigDef;
friend ConfigOptionDef;
// Only allow ConfigOptionEnumDef() to be created from ConfigOptionDef.
ConfigOptionEnumDef() = default;
void set_values(const std::vector<std::string> &v) {
m_values = v;
assert(m_labels.empty() || m_labels.size() == m_values.size());
}
void set_values(const std::initializer_list<std::string_view> il) {
m_values.clear();
m_values.reserve(il.size());
for (const std::string_view p : il)
m_values.emplace_back(p);
assert(m_labels.empty() || m_labels.size() == m_values.size());
}
void set_values(const std::initializer_list<std::pair<std::string_view, std::string_view>> il) {
m_values.clear();
m_values.reserve(il.size());
m_labels.clear();
m_labels.reserve(il.size());
for (const std::pair<std::string_view, std::string_view> p : il) {
m_values.emplace_back(p.first);
m_labels.emplace_back(p.second);
}
}
void set_labels(const std::initializer_list<std::string_view> il) {
m_labels.clear();
m_labels.reserve(il.size());
for (const std::string_view p : il)
m_labels.emplace_back(p);
assert(m_values.empty() || m_labels.size() == m_values.size());
}
void finalize_closed_enum() {
assert(this->is_valid_closed_enum());
// Check whether def.enum_values contains all the values of def.enum_keys_map and
// that they are sorted by their ordinary values.
m_values_ordinary = true;
for (const std::pair<std::string, int>& key : *m_enum_keys_map) {
assert(key.second >= 0);
if (key.second >= this->values().size() || this->value(key.second) != key.first) {
m_values_ordinary = false;
break;
}
}
}
std::vector<std::string> m_values;
std::vector<std::string> m_labels;
// If true, then enum_values are sorted and they contain all the values, thus the UI element ordinary
// to enum value could be converted directly.
bool m_values_ordinary { false };
template<typename EnumType>
void set_enum_map()
{
m_enum_names = &ConfigOptionEnum<EnumType>::get_enum_names();
m_enum_keys_map = &ConfigOptionEnum<EnumType>::get_enum_values();
}
// For enums (when type == coEnum). Maps enums to enum names.
// Initialized by ConfigOptionEnum<xxx>::get_enum_names()
const t_config_enum_names* m_enum_names{ nullptr };
// For enums (when type == coEnum). Maps enum_values to enums.
// Initialized by ConfigOptionEnum<xxx>::get_enum_values()
const t_config_enum_values* m_enum_keys_map{ nullptr };
};
// Definition of a configuration value for the purpose of GUI presentation, editing, value mapping and config file handling. // Definition of a configuration value for the purpose of GUI presentation, editing, value mapping and config file handling.
class ConfigOptionDef class ConfigOptionDef
{ {
@ -1629,10 +1802,10 @@ public:
i_enum_open, i_enum_open,
// Open enums, float value could be one of the enumerated values or something else. // Open enums, float value could be one of the enumerated values or something else.
f_enum_open, f_enum_open,
// Open enums, string value could be one of the enumerated values or something else.
select_open,
// Color picker, string value. // Color picker, string value.
color, color,
// ???
select_open,
// Currently unused. // Currently unused.
slider, slider,
// Static text // Static text
@ -1683,7 +1856,7 @@ public:
case coPoint3: { auto opt = new ConfigOptionPoint3(); archive(*opt); return opt; } case coPoint3: { auto opt = new ConfigOptionPoint3(); archive(*opt); return opt; }
case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; } case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; }
case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; } case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; }
case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_keys_map); archive(*opt); return opt; } case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_def->m_enum_keys_map); archive(*opt); return opt; }
default: throw ConfigurationError(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key); default: throw ConfigurationError(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key);
} }
} }
@ -1780,30 +1953,73 @@ public:
// Sometimes a single value may well define multiple values in a "beginner" mode. // Sometimes a single value may well define multiple values in a "beginner" mode.
// Currently used for aliasing "solid_layers" to "top_solid_layers", "bottom_solid_layers". // Currently used for aliasing "solid_layers" to "top_solid_layers", "bottom_solid_layers".
std::vector<t_config_option_key> shortcut; std::vector<t_config_option_key> shortcut;
// Definition of values / labels for a combo box.
// Mostly used for enums (when type == coEnum), but may be used for ints resp. floats, if gui_type is set to "i_enum_open" resp. "f_enum_open".
std::vector<std::string> enum_values;
std::vector<std::string> enum_labels;
// For enums (when type == coEnum). Maps enum_values to enums.
// Initialized by ConfigOptionEnum<xxx>::get_enum_values()
const t_config_enum_values *enum_keys_map = nullptr;
void set_enum_values(std::initializer_list<std::pair<std::string_view, std::string_view>> il) { Slic3r::clonable_ptr<ConfigOptionEnumDef> enum_def;
enum_values.clear();
enum_values.reserve(il.size()); void set_enum_values(const std::initializer_list<std::string_view> il) {
enum_labels.clear(); this->enum_def_new();
enum_labels.reserve(il.size()); enum_def->set_values(il);
for (const std::pair<std::string_view, std::string_view> p : il) { }
enum_values.emplace_back(p.first);
enum_labels.emplace_back(p.second); void set_enum_values(GUIType gui_type, const std::initializer_list<std::string_view> il) {
} this->enum_def_new();
assert(gui_type == GUIType::i_enum_open || gui_type == GUIType::f_enum_open || gui_type == GUIType::select_open);
this->gui_type = gui_type;
enum_def->set_values(il);
}
void set_enum_values(const std::initializer_list<std::pair<std::string_view, std::string_view>> il) {
this->enum_def_new();
enum_def->set_values(il);
}
void set_enum_values(GUIType gui_type, const std::initializer_list<std::pair<std::string_view, std::string_view>> il) {
this->enum_def_new();
assert(gui_type == GUIType::i_enum_open || gui_type == GUIType::f_enum_open);
this->gui_type = gui_type;
enum_def->set_values(il);
}
template<typename Values, typename Labels>
void set_enum_values(Values &&values, Labels &&labels) {
this->enum_def_new();
enum_def->set_values(std::move(values));
enum_def->set_labels(std::move(labels));
}
void set_enum_labels(GUIType gui_type, const std::initializer_list<std::string_view> il) {
this->enum_def_new();
assert(gui_type == GUIType::i_enum_open || gui_type == GUIType::f_enum_open || gui_type == ConfigOptionDef::GUIType::select_open);
this->gui_type = gui_type;
enum_def->set_labels(il);
}
template<typename EnumType>
void set_enum(std::initializer_list<std::string_view> il) {
this->set_enum_values(il);
enum_def->set_enum_map<EnumType>();
}
template<typename EnumType>
void set_enum(std::initializer_list<std::pair<std::string_view, std::string_view>> il) {
this->set_enum_values(il);
enum_def->set_enum_map<EnumType>();
}
template<typename EnumType, typename Values, typename Labels>
void set_enum(Values &&values, Labels &&labels) {
this->set_enum_values(std::move(values), std::move(labels));
enum_def->set_enum_map<EnumType>();
}
template<typename EnumType, typename Values>
void set_enum(Values &&values, const std::initializer_list<std::string_view> labels) {
this->set_enum_values(std::move(values), labels);
enum_def->set_enum_map<EnumType>();
} }
bool has_enum_value(const std::string &value) const { bool has_enum_value(const std::string &value) const {
for (const std::string &v : enum_values) return enum_def && enum_def->value_to_index(value).has_value();
if (v == value)
return true;
return false;
} }
// 0 is an invalid key. // 0 is an invalid key.
@ -1815,6 +2031,14 @@ public:
// Assign this key to cli to disable CLI for this option. // Assign this key to cli to disable CLI for this option.
static const constexpr char *nocli = "~~~noCLI"; static const constexpr char *nocli = "~~~noCLI";
private:
void enum_def_new() {
if (enum_def)
enum_def->clear();
else
enum_def = Slic3r::clonable_ptr<ConfigOptionEnumDef>(new ConfigOptionEnumDef{});
}
}; };
inline bool operator<(const ConfigSubstitution &lhs, const ConfigSubstitution &rhs) throw() { inline bool operator<(const ConfigSubstitution &lhs, const ConfigSubstitution &rhs) throw() {
@ -1860,6 +2084,8 @@ public:
protected: protected:
ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type); ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type);
ConfigOptionDef* add_nullable(const t_config_option_key &opt_key, ConfigOptionType type); ConfigOptionDef* add_nullable(const t_config_option_key &opt_key, ConfigOptionType type);
// Finalize open / close enums, validate everything.
void finalize();
}; };
// A pure interface to resolving ConfigOptions. // A pure interface to resolving ConfigOptions.
@ -1969,7 +2195,12 @@ public:
{ return dynamic_cast<T*>(this->optptr(opt_key, create)); } { return dynamic_cast<T*>(this->optptr(opt_key, create)); }
template<class T> const T* opt(const t_config_option_key &opt_key) const template<class T> const T* opt(const t_config_option_key &opt_key) const
{ return dynamic_cast<const T*>(this->optptr(opt_key)); } { return dynamic_cast<const T*>(this->optptr(opt_key)); }
// Get definition for a particular option.
// Returns null if such an option definition does not exist.
const ConfigOptionDef* option_def(const t_config_option_key &opt_key) const
{ return this->def()->get(opt_key); }
// Apply all keys of other ConfigBase defined by this->def() to this ConfigBase. // Apply all keys of other ConfigBase defined by this->def() to this ConfigBase.
// An UnknownOptionException is thrown in case some option keys of other are not defined by this->def(), // An UnknownOptionException is thrown in case some option keys of other are not defined by this->def(),
// or this ConfigBase is of a StaticConfig type and it does not support some of the keys, and ignore_nonexistent is not set. // or this ConfigBase is of a StaticConfig type and it does not support some of the keys, and ignore_nonexistent is not set.

View File

@ -653,10 +653,10 @@ std::string Print::validate(std::string* warning) const
"If support is to be printed with the current extruder (support_material_extruder == 0 or support_material_interface_extruder == 0), " "If support is to be printed with the current extruder (support_material_extruder == 0 or support_material_interface_extruder == 0), "
"all nozzles have to be of the same diameter."); "all nozzles have to be of the same diameter.");
} }
if (this->has_wipe_tower()) { if (this->has_wipe_tower() && object->config().support_material_style != smsOrganic) {
if (object->config().support_material_contact_distance == 0) { if (object->config().support_material_contact_distance == 0) {
// Soluble interface // Soluble interface
if (object->config().support_material_contact_distance == 0 && ! object->config().support_material_synchronize_layers) if (! object->config().support_material_synchronize_layers)
return L("For the Wipe Tower to work with the soluble supports, the support layers need to be synchronized with the object layers."); return L("For the Wipe Tower to work with the soluble supports, the support layers need to be synchronized with the object layers.");
} else { } else {
// Non-soluble interface // Non-soluble interface

View File

@ -243,6 +243,7 @@ PrintConfigDef::PrintConfigDef()
assign_printer_technology_to_unknown(this->options, ptFFF); assign_printer_technology_to_unknown(this->options, ptFFF);
this->init_sla_params(); this->init_sla_params();
assign_printer_technology_to_unknown(this->options, ptSLA); assign_printer_technology_to_unknown(this->options, ptSLA);
this->finalize();
} }
void PrintConfigDef::init_common_params() void PrintConfigDef::init_common_params()
@ -252,9 +253,7 @@ void PrintConfigDef::init_common_params()
def = this->add("printer_technology", coEnum); def = this->add("printer_technology", coEnum);
def->label = L("Printer technology"); def->label = L("Printer technology");
def->tooltip = L("Printer technology"); def->tooltip = L("Printer technology");
def->enum_keys_map = &ConfigOptionEnum<PrinterTechnology>::get_enum_values(); def->set_enum<PrinterTechnology>({ "FFF", "SLA" });
def->enum_values.push_back("FFF");
def->enum_values.push_back("SLA");
def->set_default_value(new ConfigOptionEnum<PrinterTechnology>(ptFFF)); def->set_default_value(new ConfigOptionEnum<PrinterTechnology>(ptFFF));
def = this->add("bed_shape", coPoints); def = this->add("bed_shape", coPoints);
@ -293,10 +292,7 @@ void PrintConfigDef::init_common_params()
def->label = L("Format of G-code thumbnails"); def->label = L("Format of G-code thumbnails");
def->tooltip = L("Format of G-code thumbnails: PNG for best quality, JPG for smallest size, QOI for low memory firmware"); def->tooltip = L("Format of G-code thumbnails: PNG for best quality, JPG for smallest size, QOI for low memory firmware");
def->mode = comExpert; def->mode = comExpert;
def->enum_keys_map = &ConfigOptionEnum<GCodeThumbnailsFormat>::get_enum_values(); def->set_enum<GCodeThumbnailsFormat>({ "PNG", "JPG", "QOI" });
def->enum_values.push_back("PNG");
def->enum_values.push_back("JPG");
def->enum_values.push_back("QOI");
def->set_default_value(new ConfigOptionEnum<GCodeThumbnailsFormat>(GCodeThumbnailsFormat::PNG)); def->set_default_value(new ConfigOptionEnum<GCodeThumbnailsFormat>(GCodeThumbnailsFormat::PNG));
def = this->add("layer_height", coFloat); def = this->add("layer_height", coFloat);
@ -338,7 +334,7 @@ void PrintConfigDef::init_common_params()
def = this->add("printhost_port", coString); def = this->add("printhost_port", coString);
def->label = L("Printer"); def->label = L("Printer");
def->tooltip = L("Name of the printer"); def->tooltip = L("Name of the printer");
def->gui_type = ConfigOptionDef::GUIType::select_open; // def->gui_type = ConfigOptionDef::GUIType::select_open;
def->mode = comAdvanced; def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli; def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionString("")); def->set_default_value(new ConfigOptionString(""));
@ -385,11 +381,10 @@ void PrintConfigDef::init_common_params()
def = this->add("printhost_authorization_type", coEnum); def = this->add("printhost_authorization_type", coEnum);
def->label = L("Authorization Type"); def->label = L("Authorization Type");
// def->tooltip = L(""); // def->tooltip = L("");
def->enum_keys_map = &ConfigOptionEnum<AuthorizationType>::get_enum_values(); def->set_enum<AuthorizationType>({
def->enum_values.push_back("key"); { "key", L("API key") },
def->enum_values.push_back("user"); { "user", L("HTTP digest") }
def->enum_labels.push_back(L("API key")); });
def->enum_labels.push_back(L("HTTP digest"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli; def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionEnum<AuthorizationType>(atKeyPassword)); def->set_default_value(new ConfigOptionEnum<AuthorizationType>(atKeyPassword));
@ -585,15 +580,12 @@ void PrintConfigDef::init_fff_params()
def->label = L("Brim type"); def->label = L("Brim type");
def->category = L("Skirt and brim"); def->category = L("Skirt and brim");
def->tooltip = L("The places where the brim will be printed around each object on the first layer."); def->tooltip = L("The places where the brim will be printed around each object on the first layer.");
def->enum_keys_map = &ConfigOptionEnum<BrimType>::get_enum_values(); def->set_enum<BrimType>({
def->enum_values.emplace_back("no_brim"); { "no_brim", L("No brim") },
def->enum_values.emplace_back("outer_only"); { "outer_only", L("Outer brim only") },
def->enum_values.emplace_back("inner_only"); { "inner_only", L("Inner brim only") },
def->enum_values.emplace_back("outer_and_inner"); { "outer_and_inner", L("Outer and inner brim") }
def->enum_labels.emplace_back(L("No brim")); });
def->enum_labels.emplace_back(L("Outer brim only"));
def->enum_labels.emplace_back(L("Inner brim only"));
def->enum_labels.emplace_back(L("Outer and inner brim"));
def->mode = comSimple; def->mode = comSimple;
def->set_default_value(new ConfigOptionEnum<BrimType>(btOuterOnly)); def->set_default_value(new ConfigOptionEnum<BrimType>(btOuterOnly));
@ -774,8 +766,7 @@ void PrintConfigDef::init_fff_params()
def->category = L("Infill"); def->category = L("Infill");
def->tooltip = L("Fill pattern for top infill. This only affects the top visible layer, and not its adjacent solid shells."); def->tooltip = L("Fill pattern for top infill. This only affects the top visible layer, and not its adjacent solid shells.");
def->cli = "top-fill-pattern|external-fill-pattern|solid-fill-pattern"; def->cli = "top-fill-pattern|external-fill-pattern|solid-fill-pattern";
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values(); def->set_enum<InfillPattern>({
def->set_enum_values({
{ "rectilinear", L("Rectilinear") }, { "rectilinear", L("Rectilinear") },
{ "monotonic", L("Monotonic") }, { "monotonic", L("Monotonic") },
{ "monotoniclines", L("Monotonic Lines") }, { "monotoniclines", L("Monotonic Lines") },
@ -795,9 +786,7 @@ void PrintConfigDef::init_fff_params()
def->category = L("Infill"); def->category = L("Infill");
def->tooltip = L("Fill pattern for bottom infill. This only affects the bottom external visible layer, and not its adjacent solid shells."); def->tooltip = L("Fill pattern for bottom infill. This only affects the bottom external visible layer, and not its adjacent solid shells.");
def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern"; def->cli = "bottom-fill-pattern|external-fill-pattern|solid-fill-pattern";
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values(); def->enum_def = Slic3r::clonable_ptr<Slic3r::ConfigOptionEnumDef>(def_top_fill_pattern->enum_def->clone());
def->enum_values = def_top_fill_pattern->enum_values;
def->enum_labels = def_top_fill_pattern->enum_labels;
def->aliases = def_top_fill_pattern->aliases; def->aliases = def_top_fill_pattern->aliases;
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipMonotonic)); def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipMonotonic));
@ -851,18 +840,13 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionBool(false)); def->set_default_value(new ConfigOptionBool(false));
def = this->add("extruder", coInt); def = this->add("extruder", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Extruder"); def->label = L("Extruder");
def->category = L("Extruders"); def->category = L("Extruders");
def->tooltip = L("The extruder to use (unless more specific extruder settings are specified). " def->tooltip = L("The extruder to use (unless more specific extruder settings are specified). "
"This value overrides perimeter and infill extruders, but not the support extruders."); "This value overrides perimeter and infill extruders, but not the support extruders.");
def->min = 0; // 0 = inherit defaults def->min = 0; // 0 = inherit defaults
def->enum_labels.push_back(L("default")); // override label for item 0 def->set_enum_labels(ConfigOptionDef::GUIType::i_enum_open,
def->enum_labels.push_back("1"); { L("default"), "1", "2", "3", "4", "5" }); // override label for item 0
def->enum_labels.push_back("2");
def->enum_labels.push_back("3");
def->enum_labels.push_back("4");
def->enum_labels.push_back("5");
def = this->add("extruder_clearance_height", coFloat); def = this->add("extruder_clearance_height", coFloat);
def->label = L("Height"); def->label = L("Height");
@ -1096,29 +1080,29 @@ void PrintConfigDef::init_fff_params()
def = this->add("filament_type", coStrings); def = this->add("filament_type", coStrings);
def->label = L("Filament type"); def->label = L("Filament type");
def->tooltip = L("The filament material type for use in custom G-codes."); def->tooltip = L("The filament material type for use in custom G-codes.");
def->gui_type = ConfigOptionDef::GUIType::f_enum_open;
def->gui_flags = "show_value"; def->gui_flags = "show_value";
def->enum_values.push_back("PLA"); def->set_enum_values(ConfigOptionDef::GUIType::select_open, {
def->enum_values.push_back("PET"); "PLA",
def->enum_values.push_back("ABS"); "PET",
def->enum_values.push_back("ASA"); "ABS",
def->enum_values.push_back("FLEX"); "ASA",
def->enum_values.push_back("HIPS"); "FLEX",
def->enum_values.push_back("EDGE"); "HIPS",
def->enum_values.push_back("NGEN"); "EDGE",
def->enum_values.push_back("PA"); "NGEN",
def->enum_values.push_back("NYLON"); "PA",
def->enum_values.push_back("PVA"); "NYLON",
def->enum_values.push_back("PC"); "PVA",
def->enum_values.push_back("PP"); "PC",
def->enum_values.push_back("PEI"); "PP",
def->enum_values.push_back("PEEK"); "PEI",
def->enum_values.push_back("PEKK"); "PEEK",
def->enum_values.push_back("POM"); "PEKK",
def->enum_values.push_back("PSU"); "POM",
def->enum_values.push_back("PVDF"); "PSU",
def->enum_values.push_back("SCAFF"); "PVDF",
"SCAFF"
});
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionStrings { "PLA" }); def->set_default_value(new ConfigOptionStrings { "PLA" });
@ -1166,7 +1150,6 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionFloat(45)); def->set_default_value(new ConfigOptionFloat(45));
def = this->add("fill_density", coPercent); def = this->add("fill_density", coPercent);
def->gui_type = ConfigOptionDef::GUIType::f_enum_open;
def->gui_flags = "show_value"; def->gui_flags = "show_value";
def->label = L("Fill density"); def->label = L("Fill density");
def->category = L("Infill"); def->category = L("Infill");
@ -1174,75 +1157,47 @@ void PrintConfigDef::init_fff_params()
def->sidetext = L("%"); def->sidetext = L("%");
def->min = 0; def->min = 0;
def->max = 100; def->max = 100;
def->enum_values.push_back("0"); def->set_enum_values(ConfigOptionDef::GUIType::f_enum_open, {
def->enum_values.push_back("5"); { "0", "0%" },
def->enum_values.push_back("10"); { "5", "5%" },
def->enum_values.push_back("15"); { "10", "10%" },
def->enum_values.push_back("20"); { "15", "15%" },
def->enum_values.push_back("25"); { "20", "20%" },
def->enum_values.push_back("30"); { "25", "25%" },
def->enum_values.push_back("40"); { "30", "30%" },
def->enum_values.push_back("50"); { "40", "40%" },
def->enum_values.push_back("60"); { "50", "50%" },
def->enum_values.push_back("70"); { "60", "60%" },
def->enum_values.push_back("80"); { "70", "70%" },
def->enum_values.push_back("90"); { "80", "80%" },
def->enum_values.push_back("100"); { "90", "90%" },
def->enum_labels.push_back("0%"); { "100", "100%" }
def->enum_labels.push_back("5%"); });
def->enum_labels.push_back("10%");
def->enum_labels.push_back("15%");
def->enum_labels.push_back("20%");
def->enum_labels.push_back("25%");
def->enum_labels.push_back("30%");
def->enum_labels.push_back("40%");
def->enum_labels.push_back("50%");
def->enum_labels.push_back("60%");
def->enum_labels.push_back("70%");
def->enum_labels.push_back("80%");
def->enum_labels.push_back("90%");
def->enum_labels.push_back("100%");
def->set_default_value(new ConfigOptionPercent(20)); def->set_default_value(new ConfigOptionPercent(20));
def = this->add("fill_pattern", coEnum); def = this->add("fill_pattern", coEnum);
def->label = L("Fill pattern"); def->label = L("Fill pattern");
def->category = L("Infill"); def->category = L("Infill");
def->tooltip = L("Fill pattern for general low-density infill."); def->tooltip = L("Fill pattern for general low-density infill.");
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values(); def->set_enum<InfillPattern>({
def->enum_values.push_back("rectilinear"); { "rectilinear", L("Rectilinear") },
def->enum_values.push_back("alignedrectilinear"); { "alignedrectilinear", L("Aligned Rectilinear") },
def->enum_values.push_back("grid"); { "grid", L("Grid") },
def->enum_values.push_back("triangles"); { "triangles", L("Triangles")},
def->enum_values.push_back("stars"); { "stars", L("Stars")},
def->enum_values.push_back("cubic"); { "cubic", L("Cubic")},
def->enum_values.push_back("line"); { "line", L("Line")},
def->enum_values.push_back("concentric"); { "concentric", L("Concentric")},
def->enum_values.push_back("honeycomb"); { "honeycomb", L("Honeycomb")},
def->enum_values.push_back("3dhoneycomb"); { "3dhoneycomb", L("3D Honeycomb")},
def->enum_values.push_back("gyroid"); { "gyroid", L("Gyroid")},
def->enum_values.push_back("hilbertcurve"); { "hilbertcurve", L("Hilbert Curve")},
def->enum_values.push_back("archimedeanchords"); { "archimedeanchords", L("Archimedean Chords")},
def->enum_values.push_back("octagramspiral"); { "octagramspiral", L("Octagram Spiral")},
def->enum_values.push_back("adaptivecubic"); { "adaptivecubic", L("Adaptive Cubic")},
def->enum_values.push_back("supportcubic"); { "supportcubic", L("Support Cubic")},
def->enum_values.push_back("lightning"); { "lightning", L("Lightning")}
def->enum_labels.push_back(L("Rectilinear")); });
def->enum_labels.push_back(L("Aligned Rectilinear"));
def->enum_labels.push_back(L("Grid"));
def->enum_labels.push_back(L("Triangles"));
def->enum_labels.push_back(L("Stars"));
def->enum_labels.push_back(L("Cubic"));
def->enum_labels.push_back(L("Line"));
def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back(L("Honeycomb"));
def->enum_labels.push_back(L("3D Honeycomb"));
def->enum_labels.push_back(L("Gyroid"));
def->enum_labels.push_back(L("Hilbert Curve"));
def->enum_labels.push_back(L("Archimedean Chords"));
def->enum_labels.push_back(L("Octagram Spiral"));
def->enum_labels.push_back(L("Adaptive Cubic"));
def->enum_labels.push_back(L("Support Cubic"));
def->enum_labels.push_back(L("Lightning"));
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipStars)); def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipStars));
def = this->add("first_layer_acceleration", coFloat); def = this->add("first_layer_acceleration", coFloat);
@ -1343,14 +1298,11 @@ void PrintConfigDef::init_fff_params()
def->label = L("Fuzzy Skin"); def->label = L("Fuzzy Skin");
def->category = L("Fuzzy Skin"); def->category = L("Fuzzy Skin");
def->tooltip = L("Fuzzy skin type."); def->tooltip = L("Fuzzy skin type.");
def->set_enum<FuzzySkinType>({
def->enum_keys_map = &ConfigOptionEnum<FuzzySkinType>::get_enum_values(); { "none", L("None") },
def->enum_values.push_back("none"); { "external", L("Outside walls") },
def->enum_values.push_back("external"); { "all", L("All walls") }
def->enum_values.push_back("all"); });
def->enum_labels.push_back(L("None"));
def->enum_labels.push_back(L("Outside walls"));
def->enum_labels.push_back(L("All walls"));
def->mode = comSimple; def->mode = comSimple;
def->set_default_value(new ConfigOptionEnum<FuzzySkinType>(FuzzySkinType::None)); def->set_default_value(new ConfigOptionEnum<FuzzySkinType>(FuzzySkinType::None));
@ -1404,31 +1356,20 @@ void PrintConfigDef::init_fff_params()
def->tooltip = L("Some G/M-code commands, including temperature control and others, are not universal. " def->tooltip = L("Some G/M-code commands, including temperature control and others, are not universal. "
"Set this option to your printer's firmware to get a compatible output. " "Set this option to your printer's firmware to get a compatible output. "
"The \"No extrusion\" flavor prevents PrusaSlicer from exporting any extrusion value at all."); "The \"No extrusion\" flavor prevents PrusaSlicer from exporting any extrusion value at all.");
def->enum_keys_map = &ConfigOptionEnum<GCodeFlavor>::get_enum_values(); def->set_enum<GCodeFlavor>({
def->enum_values.push_back("reprap"); { "reprap", "RepRap/Sprinter" },
def->enum_values.push_back("reprapfirmware"); { "reprapfirmware", "RepRapFirmware" },
def->enum_values.push_back("repetier"); { "repetier", "Repetier" },
def->enum_values.push_back("teacup"); { "teacup", "Teacup" },
def->enum_values.push_back("makerware"); { "makerware", "MakerWare (MakerBot)" },
def->enum_values.push_back("marlin"); { "marlin", "Marlin (legacy)" },
def->enum_values.push_back("marlin2"); { "marlin2", "Marlin 2" },
def->enum_values.push_back("sailfish"); { "sailfish", "Sailfish (MakerBot)" },
def->enum_values.push_back("mach3"); { "mach3", "Mach3/LinuxCNC" },
def->enum_values.push_back("machinekit"); { "machinekit", "Machinekit" },
def->enum_values.push_back("smoothie"); { "smoothie", "Smoothie" },
def->enum_values.push_back("no-extrusion"); { "no-extrusion", L("No extrusion") }
def->enum_labels.push_back("RepRap/Sprinter"); });
def->enum_labels.push_back("RepRapFirmware");
def->enum_labels.push_back("Repetier");
def->enum_labels.push_back("Teacup");
def->enum_labels.push_back("MakerWare (MakerBot)");
def->enum_labels.push_back("Marlin (legacy)");
def->enum_labels.push_back("Marlin 2");
def->enum_labels.push_back("Sailfish (MakerBot)");
def->enum_labels.push_back("Mach3/LinuxCNC");
def->enum_labels.push_back("Machinekit");
def->enum_labels.push_back("Smoothie");
def->enum_labels.push_back(L("No extrusion"));
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionEnum<GCodeFlavor>(gcfRepRapSprinter)); def->set_default_value(new ConfigOptionEnum<GCodeFlavor>(gcfRepRapSprinter));
@ -1486,19 +1427,14 @@ void PrintConfigDef::init_fff_params()
def->sidetext = L("mm or %"); def->sidetext = L("mm or %");
def->ratio_over = "infill_extrusion_width"; def->ratio_over = "infill_extrusion_width";
def->max_literal = 1000; def->max_literal = 1000;
def->gui_type = ConfigOptionDef::GUIType::f_enum_open; def->set_enum_values(ConfigOptionDef::GUIType::f_enum_open, {
def->enum_values.push_back("0"); { "0", L("0 (no open anchors)") },
def->enum_values.push_back("1"); { "1", L("1 mm") },
def->enum_values.push_back("2"); { "2", L("2 mm") },
def->enum_values.push_back("5"); { "5", L("5 mm") },
def->enum_values.push_back("10"); { "10", L("10 mm") },
def->enum_values.push_back("1000"); { "1000", L("1000 (unlimited)") }
def->enum_labels.push_back(L("0 (no open anchors)")); });
def->enum_labels.push_back(L("1 mm"));
def->enum_labels.push_back(L("2 mm"));
def->enum_labels.push_back(L("5 mm"));
def->enum_labels.push_back(L("10 mm"));
def->enum_labels.push_back(L("1000 (unlimited)"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(600, true)); def->set_default_value(new ConfigOptionFloatOrPercent(600, true));
@ -1514,14 +1450,14 @@ void PrintConfigDef::init_fff_params()
def->sidetext = def_infill_anchor_min->sidetext; def->sidetext = def_infill_anchor_min->sidetext;
def->ratio_over = def_infill_anchor_min->ratio_over; def->ratio_over = def_infill_anchor_min->ratio_over;
def->max_literal = def_infill_anchor_min->max_literal; def->max_literal = def_infill_anchor_min->max_literal;
def->gui_type = def_infill_anchor_min->gui_type; def->set_enum_values(ConfigOptionDef::GUIType::f_enum_open, {
def->enum_values = def_infill_anchor_min->enum_values; { "0", L("0 (not anchored)") },
def->enum_labels.push_back(L("0 (not anchored)")); { "1", L("1 mm") },
def->enum_labels.push_back(L("1 mm")); { "2", L("2 mm") },
def->enum_labels.push_back(L("2 mm")); { "5", L("5 mm") },
def->enum_labels.push_back(L("5 mm")); { "10", L("10 mm") },
def->enum_labels.push_back(L("10 mm")); { "1000", L("1000 (unlimited)") }
def->enum_labels.push_back(L("1000 (unlimited)")); });
def->mode = def_infill_anchor_min->mode; def->mode = def_infill_anchor_min->mode;
def->set_default_value(new ConfigOptionFloatOrPercent(50, false)); def->set_default_value(new ConfigOptionFloatOrPercent(50, false));
@ -1625,13 +1561,11 @@ void PrintConfigDef::init_fff_params()
def->label = L("Ironing Type"); def->label = L("Ironing Type");
def->category = L("Ironing"); def->category = L("Ironing");
def->tooltip = L("Ironing Type"); def->tooltip = L("Ironing Type");
def->enum_keys_map = &ConfigOptionEnum<IroningType>::get_enum_values(); def->set_enum<IroningType>({
def->enum_values.push_back("top"); { "top", L("All top surfaces") },
def->enum_values.push_back("topmost"); { "topmost", L("Topmost surface only") },
def->enum_values.push_back("solid"); { "solid", L("All solid surfaces") }
def->enum_labels.push_back(L("All top surfaces")); });
def->enum_labels.push_back(L("Topmost surface only"));
def->enum_labels.push_back(L("All solid surfaces"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<IroningType>(IroningType::TopSurfaces)); def->set_default_value(new ConfigOptionEnum<IroningType>(IroningType::TopSurfaces));
@ -1695,13 +1629,11 @@ void PrintConfigDef::init_fff_params()
def->full_label = L("Purpose of Machine Limits"); def->full_label = L("Purpose of Machine Limits");
def->category = L("Machine limits"); def->category = L("Machine limits");
def->tooltip = L("How to apply the Machine Limits"); def->tooltip = L("How to apply the Machine Limits");
def->enum_keys_map = &ConfigOptionEnum<MachineLimitsUsage>::get_enum_values(); def->set_enum<MachineLimitsUsage>({
def->enum_values.push_back("emit_to_gcode"); { "emit_to_gcode", L("Emit to G-code") },
def->enum_values.push_back("time_estimate_only"); { "time_estimate_only", L("Use for time estimate") },
def->enum_values.push_back("ignore"); { "ignore", L("Ignore") }
def->enum_labels.push_back(L("Emit to G-code")); });
def->enum_labels.push_back(L("Use for time estimate"));
def->enum_labels.push_back(L("Ignore"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<MachineLimitsUsage>(MachineLimitsUsage::TimeEstimateOnly)); def->set_default_value(new ConfigOptionEnum<MachineLimitsUsage>(MachineLimitsUsage::TimeEstimateOnly));
@ -1947,23 +1879,16 @@ void PrintConfigDef::init_fff_params()
def->label = L("Host Type"); def->label = L("Host Type");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field must contain " def->tooltip = L("Slic3r can upload G-code files to a printer host. This field must contain "
"the kind of the host."); "the kind of the host.");
def->enum_keys_map = &ConfigOptionEnum<PrintHostType>::get_enum_values(); def->set_enum<PrintHostType>({
def->enum_values.push_back("prusalink"); { "prusalink", "PrusaLink" },
def->enum_values.push_back("prusaconnect"); { "prusaconnect", "PrusaConnect" },
def->enum_values.push_back("octoprint"); { "octoprint", "OctoPrint" },
def->enum_values.push_back("duet"); { "duet", "Duet" },
def->enum_values.push_back("flashair"); { "flashair", "FlashAir" },
def->enum_values.push_back("astrobox"); { "astrobox", "AstroBox" },
def->enum_values.push_back("repetier"); { "repetier", "Repetier" },
def->enum_values.push_back("mks"); { "mks", "MKS" }
def->enum_labels.push_back("PrusaLink"); });
def->enum_labels.push_back("PrusaConnect");
def->enum_labels.push_back("OctoPrint");
def->enum_labels.push_back("Duet");
def->enum_labels.push_back("FlashAir");
def->enum_labels.push_back("AstroBox");
def->enum_labels.push_back("Repetier");
def->enum_labels.push_back("MKS");
def->mode = comAdvanced; def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli; def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionEnum<PrintHostType>(htPrusaLink)); def->set_default_value(new ConfigOptionEnum<PrintHostType>(htPrusaLink));
@ -2296,15 +2221,12 @@ void PrintConfigDef::init_fff_params()
def->label = L("Seam position"); def->label = L("Seam position");
def->category = L("Layers and Perimeters"); def->category = L("Layers and Perimeters");
def->tooltip = L("Position of perimeters starting points."); def->tooltip = L("Position of perimeters starting points.");
def->enum_keys_map = &ConfigOptionEnum<SeamPosition>::get_enum_values(); def->set_enum<SeamPosition>({
def->enum_values.push_back("random"); { "random", L("Random") },
def->enum_values.push_back("nearest"); { "nearest", L("Nearest") },
def->enum_values.push_back("aligned"); { "aligned", L("Aligned") },
def->enum_values.push_back("rear"); { "rear", L("Rear") }
def->enum_labels.push_back(L("Random")); });
def->enum_labels.push_back(L("Nearest"));
def->enum_labels.push_back(L("Aligned"));
def->enum_labels.push_back(L("Rear"));
def->mode = comSimple; def->mode = comSimple;
def->set_default_value(new ConfigOptionEnum<SeamPosition>(spAligned)); def->set_default_value(new ConfigOptionEnum<SeamPosition>(spAligned));
@ -2356,13 +2278,11 @@ void PrintConfigDef::init_fff_params()
"Enabled = skirt is as tall as the highest printed object.\n" "Enabled = skirt is as tall as the highest printed object.\n"
"Limited = skirt is as tall as specified by skirt_height.\n" "Limited = skirt is as tall as specified by skirt_height.\n"
"This is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft."); "This is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft.");
def->enum_keys_map = &ConfigOptionEnum<DraftShield>::get_enum_values(); def->set_enum<DraftShield>({
def->enum_values.push_back("disabled"); { "disabled", L("Disabled") },
def->enum_values.push_back("limited"); { "limited", L("Limited") },
def->enum_values.push_back("enabled"); { "enabled", L("Enabled") }
def->enum_labels.push_back(L("Disabled")); });
def->enum_labels.push_back(L("Limited"));
def->enum_labels.push_back(L("Enabled"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<DraftShield>(dsDisabled)); def->set_default_value(new ConfigOptionEnum<DraftShield>(dsDisabled));
@ -2579,13 +2499,11 @@ void PrintConfigDef::init_fff_params()
def->label = L("Slicing Mode"); def->label = L("Slicing Mode");
def->category = L("Advanced"); def->category = L("Advanced");
def->tooltip = L("Use \"Even-odd\" for 3DLabPrint airplane models. Use \"Close holes\" to close all holes in the model."); def->tooltip = L("Use \"Even-odd\" for 3DLabPrint airplane models. Use \"Close holes\" to close all holes in the model.");
def->enum_keys_map = &ConfigOptionEnum<SlicingMode>::get_enum_values(); def->set_enum<SlicingMode>({
def->enum_values.push_back("regular"); { "regular", L("Regular") },
def->enum_values.push_back("even_odd"); { "even_odd", L("Even-odd") },
def->enum_values.push_back("close_holes"); { "close_holes", L("Close holes") }
def->enum_labels.push_back(L("Regular")); });
def->enum_labels.push_back(L("Even-odd"));
def->enum_labels.push_back(L("Close holes"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<SlicingMode>(SlicingMode::Regular)); def->set_default_value(new ConfigOptionEnum<SlicingMode>(SlicingMode::Regular));
@ -2634,7 +2552,6 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionBool(false)); def->set_default_value(new ConfigOptionBool(false));
def = this->add("support_material_contact_distance", coFloat); def = this->add("support_material_contact_distance", coFloat);
def->gui_type = ConfigOptionDef::GUIType::f_enum_open;
def->label = L("Top contact Z distance"); def->label = L("Top contact Z distance");
def->category = L("Support material"); def->category = L("Support material");
def->tooltip = L("The vertical distance between object and support material interface. " def->tooltip = L("The vertical distance between object and support material interface. "
@ -2642,30 +2559,27 @@ void PrintConfigDef::init_fff_params()
"for the first object layer."); "for the first object layer.");
def->sidetext = L("mm"); def->sidetext = L("mm");
// def->min = 0; // def->min = 0;
def->enum_values.push_back("0"); def->set_enum_values(ConfigOptionDef::GUIType::f_enum_open, {
def->enum_values.push_back("0.1"); { "0", L("0 (soluble)") },
def->enum_values.push_back("0.2"); { "0.1", L("0.1 (detachable)") },
def->enum_labels.push_back(L("0 (soluble)")); { "0.2", L("0.2 (detachable)") }
def->enum_labels.push_back(L("0.1 (detachable)")); });
def->enum_labels.push_back(L("0.2 (detachable)"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.2)); def->set_default_value(new ConfigOptionFloat(0.2));
def = this->add("support_material_bottom_contact_distance", coFloat); def = this->add("support_material_bottom_contact_distance", coFloat);
def->gui_type = ConfigOptionDef::GUIType::f_enum_open;
def->label = L("Bottom contact Z distance"); def->label = L("Bottom contact Z distance");
def->category = L("Support material"); def->category = L("Support material");
def->tooltip = L("The vertical distance between the object top surface and the support material interface. " def->tooltip = L("The vertical distance between the object top surface and the support material interface. "
"If set to zero, support_material_contact_distance will be used for both top and bottom contact Z distances."); "If set to zero, support_material_contact_distance will be used for both top and bottom contact Z distances.");
def->sidetext = L("mm"); def->sidetext = L("mm");
// def->min = 0; // def->min = 0;
def->enum_values.push_back("0");
def->enum_values.push_back("0.1");
def->enum_values.push_back("0.2");
//TRN To be shown in Print Settings "Bottom contact Z distance". Have to be as short as possible //TRN To be shown in Print Settings "Bottom contact Z distance". Have to be as short as possible
def->enum_labels.push_back(L("Same as top")); def->set_enum_values(ConfigOptionDef::GUIType::f_enum_open, {
def->enum_labels.push_back("0.1"); { "0", L("Same as top") },
def->enum_labels.push_back("0.2"); { "0.1", "0.1" },
{ "0.2", "0.2" }
});
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0)); def->set_default_value(new ConfigOptionFloat(0));
@ -2720,36 +2634,35 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionInt(1)); def->set_default_value(new ConfigOptionInt(1));
auto support_material_interface_layers = def = this->add("support_material_interface_layers", coInt); auto support_material_interface_layers = def = this->add("support_material_interface_layers", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Top interface layers"); def->label = L("Top interface layers");
def->category = L("Support material"); def->category = L("Support material");
def->tooltip = L("Number of interface layers to insert between the object(s) and support material."); def->tooltip = L("Number of interface layers to insert between the object(s) and support material.");
def->sidetext = L("layers"); def->sidetext = L("layers");
def->min = 0; def->min = 0;
def->enum_values.push_back("0"); def->set_enum_values(ConfigOptionDef::GUIType::i_enum_open, {
def->enum_values.push_back("1"); { "0", L("0 (off)") },
def->enum_values.push_back("2"); { "1", L("1 (light)") },
def->enum_values.push_back("3"); { "2", L("2 (default)") },
def->enum_labels.push_back(L("0 (off)")); { "3", L("3 (heavy)") }
def->enum_labels.push_back(L("1 (light)")); });
def->enum_labels.push_back(L("2 (default)"));
def->enum_labels.push_back(L("3 (heavy)"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(3)); def->set_default_value(new ConfigOptionInt(3));
def = this->add("support_material_bottom_interface_layers", coInt); def = this->add("support_material_bottom_interface_layers", coInt);
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->label = L("Bottom interface layers"); def->label = L("Bottom interface layers");
def->category = L("Support material"); def->category = L("Support material");
def->tooltip = L("Number of interface layers to insert between the object(s) and support material. " def->tooltip = L("Number of interface layers to insert between the object(s) and support material. "
"Set to -1 to use support_material_interface_layers"); "Set to -1 to use support_material_interface_layers");
def->sidetext = L("layers"); def->sidetext = L("layers");
def->min = -1; def->min = -1;
def->enum_values.push_back("-1");
append(def->enum_values, support_material_interface_layers->enum_values);
//TRN To be shown in Print Settings "Bottom interface layers". Have to be as short as possible //TRN To be shown in Print Settings "Bottom interface layers". Have to be as short as possible
def->enum_labels.push_back(L("Same as top")); def->set_enum_values(ConfigOptionDef::GUIType::i_enum_open, {
append(def->enum_labels, support_material_interface_layers->enum_labels); { "-1", L("Same as top") },
{ "0", L("0 (off)") },
{ "1", L("1 (light)") },
{ "2", L("2 (default)") },
{ "3", L("3 (heavy)") }
});
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(-1)); def->set_default_value(new ConfigOptionInt(-1));
@ -2787,13 +2700,11 @@ void PrintConfigDef::init_fff_params()
def->label = L("Pattern"); def->label = L("Pattern");
def->category = L("Support material"); def->category = L("Support material");
def->tooltip = L("Pattern used to generate support material."); def->tooltip = L("Pattern used to generate support material.");
def->enum_keys_map = &ConfigOptionEnum<SupportMaterialPattern>::get_enum_values(); def->set_enum<SupportMaterialPattern>({
def->enum_values.push_back("rectilinear"); { "rectilinear", L("Rectilinear") },
def->enum_values.push_back("rectilinear-grid"); { "rectilinear-grid", L("Rectilinear grid") },
def->enum_values.push_back("honeycomb"); { "honeycomb", L("Honeycomb") }
def->enum_labels.push_back(L("Rectilinear")); });
def->enum_labels.push_back(L("Rectilinear grid"));
def->enum_labels.push_back(L("Honeycomb"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear)); def->set_default_value(new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear));
@ -2803,13 +2714,11 @@ void PrintConfigDef::init_fff_params()
def->tooltip = L("Pattern used to generate support material interface. " def->tooltip = L("Pattern used to generate support material interface. "
"Default pattern for non-soluble support interface is Rectilinear, " "Default pattern for non-soluble support interface is Rectilinear, "
"while default pattern for soluble support interface is Concentric."); "while default pattern for soluble support interface is Concentric.");
def->enum_keys_map = &ConfigOptionEnum<SupportMaterialInterfacePattern>::get_enum_values(); def->set_enum<SupportMaterialInterfacePattern>({
def->enum_values.push_back("auto"); { "auto", L("Default") },
def->enum_values.push_back("rectilinear"); { "rectilinear", L("Rectilinear") },
def->enum_values.push_back("concentric"); { "concentric", L("Concentric") }
def->enum_labels.push_back(L("Default")); });
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Concentric"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<SupportMaterialInterfacePattern>(smipRectilinear)); def->set_default_value(new ConfigOptionEnum<SupportMaterialInterfacePattern>(smipRectilinear));
@ -2837,8 +2746,7 @@ void PrintConfigDef::init_fff_params()
def->tooltip = L("Style and shape of the support towers. Projecting the supports into a regular grid " def->tooltip = L("Style and shape of the support towers. Projecting the supports into a regular grid "
"will create more stable supports, while snug support towers will save material and reduce " "will create more stable supports, while snug support towers will save material and reduce "
"object scarring."); "object scarring.");
def->enum_keys_map = &ConfigOptionEnum<SupportMaterialStyle>::get_enum_values(); def->set_enum<SupportMaterialStyle>({
def->set_enum_values({
{ "grid", L("Grid") }, { "grid", L("Grid") },
{ "snug", L("Snug") }, { "snug", L("Snug") },
{ "organic", L("Organic") } { "organic", L("Organic") }
@ -3207,11 +3115,10 @@ void PrintConfigDef::init_fff_params()
"very thin areas is used gap-fill. " "very thin areas is used gap-fill. "
"Arachne engine produces perimeters with variable extrusion width. " "Arachne engine produces perimeters with variable extrusion width. "
"This setting also affects the Concentric infill."); "This setting also affects the Concentric infill.");
def->enum_keys_map = &ConfigOptionEnum<PerimeterGeneratorType>::get_enum_values(); def->set_enum<PerimeterGeneratorType>({
def->enum_values.push_back("classic"); { "classic", L("Classic") },
def->enum_values.push_back("arachne"); { "arachne", L("Arachne") }
def->enum_labels.push_back(L("Classic")); });
def->enum_labels.push_back(L("Arachne"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<PerimeterGeneratorType>(PerimeterGeneratorType::Arachne)); def->set_default_value(new ConfigOptionEnum<PerimeterGeneratorType>(PerimeterGeneratorType::Arachne));
@ -3434,13 +3341,9 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix)
" Can be zig-zag, cross (double zig-zag) or dynamic which" " Can be zig-zag, cross (double zig-zag) or dynamic which"
" will automatically switch between the first two depending" " will automatically switch between the first two depending"
" on the distance of the two pillars."); " on the distance of the two pillars.");
def->enum_keys_map = &ConfigOptionEnum<SLAPillarConnectionMode>::get_enum_values(); def->set_enum<SLAPillarConnectionMode>(
def->enum_keys_map = &ConfigOptionEnum<SLAPillarConnectionMode>::get_enum_values(); ConfigOptionEnum<SLAPillarConnectionMode>::get_enum_names(),
def->enum_values = ConfigOptionEnum<SLAPillarConnectionMode>::get_enum_names(); { L("Zig-Zag"), L("Cross"), L("Dynamic") });
def->enum_labels = ConfigOptionEnum<SLAPillarConnectionMode>::get_enum_names();
def->enum_labels[0] = L("Zig-Zag");
def->enum_labels[1] = L("Cross");
def->enum_labels[2] = L("Dynamic");
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum(SLAPillarConnectionMode::dynamic)); def->set_default_value(new ConfigOptionEnum(SLAPillarConnectionMode::dynamic));
@ -3602,11 +3505,10 @@ void PrintConfigDef::init_sla_params()
def->tooltip = L("Set the actual LCD display orientation inside the SLA printer." def->tooltip = L("Set the actual LCD display orientation inside the SLA printer."
" Portrait mode will flip the meaning of display width and height parameters" " Portrait mode will flip the meaning of display width and height parameters"
" and the output images will be rotated by 90 degrees."); " and the output images will be rotated by 90 degrees.");
def->enum_keys_map = &ConfigOptionEnum<SLADisplayOrientation>::get_enum_values(); def->set_enum<SLADisplayOrientation>({
def->enum_values.push_back("landscape"); { "landscape", L("Landscape") },
def->enum_values.push_back("portrait"); { "portrait", L("Portrait") }
def->enum_labels.push_back(L("Landscape")); });
def->enum_labels.push_back(L("Portrait"));
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionEnum<SLADisplayOrientation>(sladoPortrait)); def->set_default_value(new ConfigOptionEnum<SLADisplayOrientation>(sladoPortrait));
@ -3718,13 +3620,9 @@ void PrintConfigDef::init_sla_params()
def = this->add("material_type", coString); def = this->add("material_type", coString);
def->label = L("SLA material type"); def->label = L("SLA material type");
def->tooltip = L("SLA material type"); def->tooltip = L("SLA material type");
def->gui_type = ConfigOptionDef::GUIType::f_enum_open; // TODO: ???
def->gui_flags = "show_value"; def->gui_flags = "show_value";
def->enum_values.push_back("Tough"); def->set_enum_values(ConfigOptionDef::GUIType::select_open,
def->enum_values.push_back("Flexible"); { "Tough", "Flexible", "Casting", "Dental", "Heat-resistant" });
def->enum_values.push_back("Casting");
def->enum_values.push_back("Dental");
def->enum_values.push_back("Heat-resistant");
def->set_default_value(new ConfigOptionString("Tough")); def->set_default_value(new ConfigOptionString("Tough"));
def = this->add("initial_layer_height", coFloat); def = this->add("initial_layer_height", coFloat);
@ -3898,12 +3796,10 @@ void PrintConfigDef::init_sla_params()
def = this->add("support_tree_type", coEnum); def = this->add("support_tree_type", coEnum);
def->label = L("Support tree type"); def->label = L("Support tree type");
def->tooltip = L("Support tree building strategy"); def->tooltip = L("Support tree building strategy");
def->enum_keys_map = &ConfigOptionEnum<sla::SupportTreeType>::get_enum_values(); def->set_enum<sla::SupportTreeType>(
def->enum_values = ConfigOptionEnum<sla::SupportTreeType>::get_enum_names(); ConfigOptionEnum<sla::SupportTreeType>::get_enum_names(),
def->enum_labels = ConfigOptionEnum<sla::SupportTreeType>::get_enum_names(); { L("Default"), L("Branching (experimental)") });
def->enum_labels[0] = L("Default"); // TODO: def->enum_def->labels[2] = L("Organic");
def->enum_labels[1] = L("Branching (experimental)");
// TODO: def->enum_labels[2] = L("Organic");
def->mode = comSimple; def->mode = comSimple;
def->set_default_value(new ConfigOptionEnum(sla::SupportTreeType::Default)); def->set_default_value(new ConfigOptionEnum(sla::SupportTreeType::Default));
@ -4107,13 +4003,11 @@ void PrintConfigDef::init_sla_params()
def->tooltip = L( def->tooltip = L(
"A slower printing profile might be necessary when using materials with higher viscosity " "A slower printing profile might be necessary when using materials with higher viscosity "
"or with some hollowed parts. It slows down the tilt movement and adds a delay before exposure."); "or with some hollowed parts. It slows down the tilt movement and adds a delay before exposure.");
def->enum_keys_map = &ConfigOptionEnum<SLAMaterialSpeed>::get_enum_values(); def->set_enum<SLAMaterialSpeed>({
def->enum_values.push_back("slow"); { "slow", L("Slow") },
def->enum_values.push_back("fast"); { "fast", L("Fast") },
def->enum_values.push_back("high_viscosity"); { "high_viscosity", L("High viscosity") }
def->enum_labels.push_back(L("Slow")); });
def->enum_labels.push_back(L("Fast"));
def->enum_labels.push_back(L("High viscosity"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<SLAMaterialSpeed>(slamsFast)); def->set_default_value(new ConfigOptionEnum<SLAMaterialSpeed>(slamsFast));
@ -4126,7 +4020,7 @@ void PrintConfigDef::init_sla_params()
def->label = L("SLA output precision"); def->label = L("SLA output precision");
def->tooltip = L("Minimum resolution in nanometers"); def->tooltip = L("Minimum resolution in nanometers");
def->sidetext = L("mm"); def->sidetext = L("mm");
def->min = SCALING_FACTOR; def->min = float(SCALING_FACTOR);
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0.001)); def->set_default_value(new ConfigOptionFloat(0.001));
} }
@ -4794,13 +4688,11 @@ CLIMiscConfigDef::CLIMiscConfigDef()
def->tooltip = L("This version of PrusaSlicer may not understand configurations produced by the newest PrusaSlicer versions. " def->tooltip = L("This version of PrusaSlicer may not understand configurations produced by the newest PrusaSlicer versions. "
"For example, newer PrusaSlicer may extend the list of supported firmware flavors. One may decide to " "For example, newer PrusaSlicer may extend the list of supported firmware flavors. One may decide to "
"bail out or to substitute an unknown value with a default silently or verbosely."); "bail out or to substitute an unknown value with a default silently or verbosely.");
def->enum_keys_map = &ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>::get_enum_values(); def->set_enum<ForwardCompatibilitySubstitutionRule>({
def->enum_values.push_back("disable"); { "disable", L("Bail out on unknown configuration values") },
def->enum_values.push_back("enable"); { "enable", L("Enable reading unknown configuration values by verbosely substituting them with defaults.") },
def->enum_values.push_back("enable_silent"); { "enable_silent", L("Enable reading unknown configuration values by silently substituting them with defaults.") }
def->enum_labels.push_back(L("Bail out on unknown configuration values")); });
def->enum_labels.push_back(L("Enable reading unknown configuration values by verbosely substituting them with defaults."));
def->enum_labels.push_back(L("Enable reading unknown configuration values by silently substituting them with defaults."));
def->set_default_value(new ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>(ForwardCompatibilitySubstitutionRule::Enable)); def->set_default_value(new ConfigOptionEnum<ForwardCompatibilitySubstitutionRule>(ForwardCompatibilitySubstitutionRule::Enable));
def = this->add("load", coStrings); def = this->add("load", coStrings);

View File

@ -116,44 +116,48 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
} }
} }
if (config->opt_bool("wipe_tower") && config->opt_bool("support_material") && auto style = config->opt_enum<SupportMaterialStyle>("support_material_style");
config->opt_float("support_material_contact_distance") > 0. &&
(config->opt_int("support_material_extruder") != 0 || config->opt_int("support_material_interface_extruder") != 0)) {
wxString msg_text = _(L("The Wipe Tower currently supports the non-soluble supports only\n"
"if they are printed with the current extruder without triggering a tool change.\n"
"(both support_material_extruder and support_material_interface_extruder need to be set to 0)."));
if (is_global_config)
msg_text += "\n\n" + _(L("Shall I adjust those settings in order to enable the Wipe Tower?"));
MessageDialog dialog (m_msg_dlg_parent, msg_text, _(L("Wipe Tower")),
wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK));
DynamicPrintConfig new_conf = *config;
auto answer = dialog.ShowModal();
if (!is_global_config || answer == wxID_YES) {
new_conf.set_key_value("support_material_extruder", new ConfigOptionInt(0));
new_conf.set_key_value("support_material_interface_extruder", new ConfigOptionInt(0));
}
else
new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
apply(config, &new_conf);
}
if (config->opt_bool("wipe_tower") && config->opt_bool("support_material") && if (config->opt_bool("wipe_tower") && config->opt_bool("support_material") &&
config->opt_float("support_material_contact_distance") == 0 && // Organic supports are always synchronized with object layers as of now.
!config->opt_bool("support_material_synchronize_layers")) { config->opt_enum<SupportMaterialStyle>("support_material_style") != smsOrganic) {
wxString msg_text = _(L("For the Wipe Tower to work with the soluble supports, the support layers\n" if (config->opt_float("support_material_contact_distance") == 0) {
"need to be synchronized with the object layers.")); if (!config->opt_bool("support_material_synchronize_layers")) {
if (is_global_config) wxString msg_text = _(L("For the Wipe Tower to work with the soluble supports, the support layers\n"
msg_text += "\n\n" + _(L("Shall I synchronize support layers in order to enable the Wipe Tower?")); "need to be synchronized with the object layers."));
MessageDialog dialog(m_msg_dlg_parent, msg_text, _(L("Wipe Tower")), if (is_global_config)
wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK)); msg_text += "\n\n" + _(L("Shall I synchronize support layers in order to enable the Wipe Tower?"));
DynamicPrintConfig new_conf = *config; MessageDialog dialog(m_msg_dlg_parent, msg_text, _(L("Wipe Tower")),
auto answer = dialog.ShowModal(); wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK));
if (!is_global_config || answer == wxID_YES) { DynamicPrintConfig new_conf = *config;
new_conf.set_key_value("support_material_synchronize_layers", new ConfigOptionBool(true)); auto answer = dialog.ShowModal();
if (!is_global_config || answer == wxID_YES) {
new_conf.set_key_value("support_material_synchronize_layers", new ConfigOptionBool(true));
}
else
new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
apply(config, &new_conf);
}
} else {
if ((config->opt_int("support_material_extruder") != 0 || config->opt_int("support_material_interface_extruder") != 0)) {
wxString msg_text = _(L("The Wipe Tower currently supports the non-soluble supports only\n"
"if they are printed with the current extruder without triggering a tool change.\n"
"(both support_material_extruder and support_material_interface_extruder need to be set to 0)."));
if (is_global_config)
msg_text += "\n\n" + _(L("Shall I adjust those settings in order to enable the Wipe Tower?"));
MessageDialog dialog (m_msg_dlg_parent, msg_text, _(L("Wipe Tower")),
wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK));
DynamicPrintConfig new_conf = *config;
auto answer = dialog.ShowModal();
if (!is_global_config || answer == wxID_YES) {
new_conf.set_key_value("support_material_extruder", new ConfigOptionInt(0));
new_conf.set_key_value("support_material_interface_extruder", new ConfigOptionInt(0));
}
else
new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
apply(config, &new_conf);
}
} }
else
new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
apply(config, &new_conf);
} }
// Check "support_material" and "overhangs" relations only on global settings level // Check "support_material" and "overhangs" relations only on global settings level
@ -183,18 +187,14 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
} }
if (config->option<ConfigOptionPercent>("fill_density")->value == 100) { if (config->option<ConfigOptionPercent>("fill_density")->value == 100) {
std::string fill_pattern = config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->serialize(); const int fill_pattern = config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->value;
const auto &top_fill_pattern_values = config->def()->get("top_fill_pattern")->enum_values; if (bool correct_100p_fill = config->option_def("top_fill_pattern")->enum_def->enum_to_index(fill_pattern).has_value();
bool correct_100p_fill = std::find(top_fill_pattern_values.begin(), top_fill_pattern_values.end(), fill_pattern) != top_fill_pattern_values.end(); ! correct_100p_fill) {
if (!correct_100p_fill) {
// get fill_pattern name from enum_labels for using this one at dialog_msg // get fill_pattern name from enum_labels for using this one at dialog_msg
const ConfigOptionDef *fill_pattern_def = config->def()->get("fill_pattern"); const ConfigOptionDef *fill_pattern_def = config->option_def("fill_pattern");
assert(fill_pattern_def != nullptr); assert(fill_pattern_def != nullptr);
auto it_pattern = std::find(fill_pattern_def->enum_values.begin(), fill_pattern_def->enum_values.end(), fill_pattern); if (auto label = fill_pattern_def->enum_def->enum_to_label(fill_pattern); label.has_value()) {
assert(it_pattern != fill_pattern_def->enum_values.end()); wxString msg_text = GUI::format_wxstr(_L("The %1% infill pattern is not supposed to work at 100%% density."), _(label.value()));
if (it_pattern != fill_pattern_def->enum_values.end()) {
wxString msg_text = GUI::format_wxstr(_L("The %1% infill pattern is not supposed to work at 100%% density."),
_(fill_pattern_def->enum_labels[it_pattern - fill_pattern_def->enum_values.begin()]));
if (is_global_config) if (is_global_config)
msg_text += "\n\n" + _L("Shall I switch to rectilinear fill pattern?"); msg_text += "\n\n" + _L("Shall I switch to rectilinear fill pattern?");
MessageDialog dialog(m_msg_dlg_parent, msg_text, _L("Infill"), MessageDialog dialog(m_msg_dlg_parent, msg_text, _L("Infill"),

View File

@ -1129,16 +1129,15 @@ void PageMaterials::sort_list_data(StringList* list, bool add_All_item, bool mat
else else
other_profiles.push_back(data); other_profiles.push_back(data);
} }
if(material_type_ordering) { if (material_type_ordering) {
const ConfigOptionDef* def = print_config_def.get("filament_type"); const ConfigOptionDef* def = print_config_def.get("filament_type");
std::vector<std::string>enum_values = def->enum_values;
size_t end_of_sorted = 0; size_t end_of_sorted = 0;
for (size_t vals = 0; vals < enum_values.size(); vals++) { for (const std::string &value : def->enum_def->values()) {
for (size_t profs = end_of_sorted; profs < other_profiles.size(); profs++) for (size_t profs = end_of_sorted; profs < other_profiles.size(); profs++)
{ {
// find instead compare because PET vs PETG // find instead compare because PET vs PETG
if (other_profiles[profs].get().find(enum_values[vals]) != std::string::npos) { if (other_profiles[profs].get().find(value) != std::string::npos) {
//swap //swap
if(profs != end_of_sorted) { if(profs != end_of_sorted) {
std::reference_wrapper<const std::string> aux = other_profiles[end_of_sorted]; std::reference_wrapper<const std::string> aux = other_profiles[end_of_sorted];
@ -1660,14 +1659,14 @@ PageFirmware::PageFirmware(ConfigWizard *parent)
append_text(_(gcode_opt.tooltip)); append_text(_(gcode_opt.tooltip));
wxArrayString choices; wxArrayString choices;
choices.Alloc(gcode_opt.enum_labels.size()); choices.Alloc(gcode_opt.enum_def->labels().size());
for (const auto &label : gcode_opt.enum_labels) { for (const auto &label : gcode_opt.enum_def->labels()) {
choices.Add(label); choices.Add(label);
} }
gcode_picker = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices); gcode_picker = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices);
wxGetApp().UpdateDarkUI(gcode_picker); wxGetApp().UpdateDarkUI(gcode_picker);
const auto &enum_values = gcode_opt.enum_values; const auto &enum_values = gcode_opt.enum_def->values();
auto needle = enum_values.cend(); auto needle = enum_values.cend();
if (gcode_opt.default_value) { if (gcode_opt.default_value) {
needle = std::find(enum_values.cbegin(), enum_values.cend(), gcode_opt.default_value->serialize()); needle = std::find(enum_values.cbegin(), enum_values.cend(), gcode_opt.default_value->serialize());
@ -1684,7 +1683,7 @@ PageFirmware::PageFirmware(ConfigWizard *parent)
void PageFirmware::apply_custom_config(DynamicPrintConfig &config) void PageFirmware::apply_custom_config(DynamicPrintConfig &config)
{ {
auto sel = gcode_picker->GetSelection(); auto sel = gcode_picker->GetSelection();
if (sel >= 0 && (size_t)sel < gcode_opt.enum_labels.size()) { if (sel >= 0 && (size_t)sel < gcode_opt.enum_def->labels().size()) {
auto *opt = new ConfigOptionEnum<GCodeFlavor>(static_cast<GCodeFlavor>(sel)); auto *opt = new ConfigOptionEnum<GCodeFlavor>(static_cast<GCodeFlavor>(sel));
config.set_key_value("gcode_flavor", opt); config.set_key_value("gcode_flavor", opt);
} }

View File

@ -1021,16 +1021,10 @@ void Choice::BUILD() {
// recast as a wxWindow to fit the calling convention // recast as a wxWindow to fit the calling convention
window = dynamic_cast<wxWindow*>(temp); window = dynamic_cast<wxWindow*>(temp);
if (! m_opt.enum_labels.empty() || ! m_opt.enum_values.empty()) { if (auto &labels = m_opt.enum_def->labels(); ! labels.empty()) {
if (m_opt.enum_labels.empty()) { bool localized = m_opt.enum_def->has_labels();
// Append non-localized enum_values for (const std::string &el : labels)
for (auto el : m_opt.enum_values) temp->Append(localized ? _(wxString::FromUTF8(el)) : wxString::FromUTF8(el));
temp->Append(el);
} else {
// Append localized enum_labels
for (auto el : m_opt.enum_labels)
temp->Append(_(el));
}
set_selection(); set_selection();
} }
@ -1141,33 +1135,23 @@ void Choice::set_selection()
} }
if (!text_value.IsEmpty()) { if (!text_value.IsEmpty()) {
size_t idx = 0; if (auto opt = m_opt.enum_def->value_to_index(into_u8(text_value)); opt.has_value())
for (auto el : m_opt.enum_values) { // This enum has a value field of the same content as text_value. Select it.
if (el == text_value) field->SetSelection(opt.value());
break; else
++idx; field->SetValue(text_value);
}
idx == m_opt.enum_values.size() ? field->SetValue(text_value) : field->SetSelection(idx);
} }
} }
void Choice::set_value(const std::string& value, bool change_event) //! Redundant? void Choice::set_value(const std::string& value, bool change_event) //! Redundant?
{ {
m_disable_change_event = !change_event; m_disable_change_event = !change_event;
size_t idx=0;
for (auto el : m_opt.enum_values)
{
if (el == value)
break;
++idx;
}
choice_ctrl* field = dynamic_cast<choice_ctrl*>(window); choice_ctrl* field = dynamic_cast<choice_ctrl*>(window);
idx == m_opt.enum_values.size() ? if (auto opt = m_opt.enum_def->value_to_index(value); opt.has_value())
field->SetValue(value) : // This enum has a value field of the same content as text_value. Select it.
field->SetSelection(idx); field->SetSelection(opt.value());
else
field->SetValue(value);
m_disable_change_event = false; m_disable_change_event = false;
} }
@ -1184,27 +1168,17 @@ void Choice::set_value(const boost::any& value, bool change_event)
case coFloatOrPercent: case coFloatOrPercent:
case coString: case coString:
case coStrings: { case coStrings: {
wxString text_value; wxString text_value = m_opt.type == coInt ?
if (m_opt.type == coInt) wxString::Format(_T("%i"), int(boost::any_cast<int>(value))) :
text_value = wxString::Format(_T("%i"), int(boost::any_cast<int>(value))); boost::any_cast<wxString>(value);
else if (auto idx = m_opt.enum_def->label_to_index(into_u8(text_value)); idx.has_value()) {
text_value = boost::any_cast<wxString>(value); field->SetSelection(idx.value());
size_t idx = 0; } else {
const std::vector<std::string>& enums = m_opt.enum_values.empty() ? m_opt.enum_labels : m_opt.enum_values;
for (auto el : enums)
{
if (el == text_value)
break;
++idx;
}
if (idx == enums.size()) {
// For editable Combobox under OSX is needed to set selection to -1 explicitly, // For editable Combobox under OSX is needed to set selection to -1 explicitly,
// otherwise selection doesn't be changed // otherwise selection doesn't be changed
field->SetSelection(-1); field->SetSelection(-1);
field->SetValue(text_value); field->SetValue(text_value);
} }
else
field->SetSelection(idx);
if (!m_value.empty() && m_opt.opt_key == "fill_density") { if (!m_value.empty() && m_opt.opt_key == "fill_density") {
// If m_value was changed before, then update m_value here too to avoid case // If m_value was changed before, then update m_value here too to avoid case
@ -1217,36 +1191,9 @@ void Choice::set_value(const boost::any& value, bool change_event)
break; break;
} }
case coEnum: { case coEnum: {
int val = boost::any_cast<int>(value); auto val = m_opt.enum_def->enum_to_index(boost::any_cast<int>(value));
if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "fill_pattern") assert(val.has_value());
{ field->SetSelection(val.has_value() ? val.value() : 0);
std::string key;
const t_config_enum_values& map_names = ConfigOptionEnum<InfillPattern>::get_enum_values();
for (auto it : map_names)
if (val == it.second) {
key = it.first;
break;
}
const std::vector<std::string>& values = m_opt.enum_values;
auto it = std::find(values.begin(), values.end(), key);
val = it == values.end() ? 0 : it - values.begin();
}
else if (m_opt_id == "support_material_style")
{
std::string key;
const t_config_enum_values& map_names = ConfigOptionEnum<SupportMaterialStyle>::get_enum_values();
for (auto it : map_names)
if (val == it.second) {
key = it.first;
break;
}
const std::vector<std::string>& values = m_opt.enum_values;
auto it = std::find(values.begin(), values.end(), key);
val = it == values.end() ? 0 : it - values.begin();
}
field->SetSelection(val);
break; break;
} }
default: default:
@ -1309,28 +1256,21 @@ boost::any& Choice::get_value()
return m_value = boost::any(ret_str); return m_value = boost::any(ret_str);
if (m_opt.type == coEnum) if (m_opt.type == coEnum)
{ // Closed enum: The combo box item index returned by the field must be convertible to an enum value.
if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "fill_pattern") { m_value = m_opt.enum_def->index_to_enum(field->GetSelection());
const std::string& key = m_opt.enum_values[field->GetSelection()];
m_value = int(ConfigOptionEnum<InfillPattern>::get_enum_values().at(key));
} else if (m_opt_id == "support_material_style") {
m_value = int(ConfigOptionEnum<SupportMaterialStyle>::get_enum_values().at(m_opt.enum_values[field->GetSelection()]));
}
else
m_value = field->GetSelection();
}
else if (m_opt.gui_type == ConfigOptionDef::GUIType::f_enum_open || m_opt.gui_type == ConfigOptionDef::GUIType::i_enum_open) { else if (m_opt.gui_type == ConfigOptionDef::GUIType::f_enum_open || m_opt.gui_type == ConfigOptionDef::GUIType::i_enum_open) {
// Open enum: The combo box item index returned by the field
const int ret_enum = field->GetSelection(); const int ret_enum = field->GetSelection();
if (ret_enum < 0 || m_opt.enum_values.empty() || m_opt.type == coStrings || if (ret_enum < 0 || ! m_opt.enum_def->has_values() || m_opt.type == coStrings ||
(ret_str != m_opt.enum_values[ret_enum] && ret_str != _(m_opt.enum_labels[ret_enum]))) (into_u8(ret_str) != m_opt.enum_def->value(ret_enum) && ret_str != _(m_opt.enum_def->label(ret_enum))))
// modifies ret_string! // modifies ret_string!
get_value_by_opt_type(ret_str); get_value_by_opt_type(ret_str);
else if (m_opt.type == coFloatOrPercent) else if (m_opt.type == coFloatOrPercent)
m_value = m_opt.enum_values[ret_enum]; m_value = m_opt.enum_def->value(ret_enum);
else if (m_opt.type == coInt) else if (m_opt.type == coInt)
m_value = atoi(m_opt.enum_values[ret_enum].c_str()); m_value = atoi(m_opt.enum_def->value(ret_enum).c_str());
else else
m_value = string_to_double_decimal_point(m_opt.enum_values[ret_enum]); m_value = string_to_double_decimal_point(m_opt.enum_def->value(ret_enum));
} }
else else
// modifies ret_string! // modifies ret_string!

View File

@ -280,34 +280,11 @@ static void add_config_substitutions(const ConfigSubstitutions& conf_substitutio
switch (def->type) { switch (def->type) {
case coEnum: case coEnum:
{ {
const std::vector<std::string>& labels = def->enum_labels; auto opt = def->enum_def->enum_to_index(conf_substitution.new_value->getInt());
const std::vector<std::string>& values = def->enum_values; new_val = opt.has_value() ?
int val = conf_substitution.new_value->getInt(); wxString("\"") + def->enum_def->value(opt.value()) + "\"" + " (" +
_(wxString::FromUTF8(def->enum_def->label(opt.value()))) + ")" :
bool is_infill = def->opt_key == "top_fill_pattern" || _L("Undefined");
def->opt_key == "bottom_fill_pattern" ||
def->opt_key == "fill_pattern" ||
def->opt_key == "support_material_style";
// Each infill doesn't use all list of infill declared in PrintConfig.hpp.
// So we should "convert" val to the correct one
if (is_infill) {
for (const auto& key_val : *def->enum_keys_map)
if ((int)key_val.second == val) {
auto it = std::find(values.begin(), values.end(), key_val.first);
if (it == values.end())
break;
auto idx = it - values.begin();
new_val = wxString("\"") + values[idx] + "\"" + " (" + from_u8(_utf8(labels[idx])) + ")";
break;
}
if (new_val.IsEmpty()) {
assert(false);
new_val = _L("Undefined");
}
}
else
new_val = wxString("\"") + values[val] + "\"" + " (" + from_u8(_utf8(labels[val])) + ")";
break; break;
} }
case coBool: case coBool:

View File

@ -511,14 +511,14 @@ GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const
for (const std::string& key : keys) { for (const std::string& key : keys) {
if (object_cfg.has(key)) if (object_cfg.has(key))
out.emplace_back(object_cfg.option(key), &object_cfg.def()->options.at(key)); // at() needed for const map out.emplace_back(object_cfg.option(key), object_cfg.option_def(key));
else else
if (print_cfg.has(key)) if (print_cfg.has(key))
out.emplace_back(print_cfg.option(key), &print_cfg.def()->options.at(key)); out.emplace_back(print_cfg.option(key), print_cfg.option_def(key));
else { // we must get it from defaults else { // we must get it from defaults
if (default_cfg == nullptr) if (default_cfg == nullptr)
default_cfg.reset(DynamicPrintConfig::new_from_defaults_keys(keys)); default_cfg.reset(DynamicPrintConfig::new_from_defaults_keys(keys));
out.emplace_back(default_cfg->option(key), &default_cfg->def()->options.at(key)); out.emplace_back(default_cfg->option(key), default_cfg->option_def(key));
} }
} }

View File

@ -613,32 +613,33 @@ void PhysicalPrinterDialog::update_host_type(bool printer_change)
// Append localized enum_labels // Append localized enum_labels
assert(ht->m_opt.enum_labels.size() == ht->m_opt.enum_values.size()); assert(ht->m_opt.enum_def->labels().size() == ht->m_opt.enum_def->values().size());
for (size_t i = 0; i < ht->m_opt.enum_labels.size(); i++) { for (size_t i = 0; i < ht->m_opt.enum_def->labels().size(); ++ i) {
if (ht->m_opt.enum_values[i] == "prusalink"){ wxString label = _(ht->m_opt.enum_def->label(i));
link.label = _(ht->m_opt.enum_labels[i]); if (const std::string &value = ht->m_opt.enum_def->value(i);
value == "prusalink") {
link.label = label;
if (!link.supported) if (!link.supported)
continue; continue;
} } else if (value == "prusaconnect") {
if (ht->m_opt.enum_values[i] == "prusaconnect") { connect.label = label;
connect.label = _(ht->m_opt.enum_labels[i]);
if (!connect.supported) if (!connect.supported)
continue; continue;
} }
types.Add(_(ht->m_opt.enum_labels[i])); types.Add(label);
} }
Choice* choice = dynamic_cast<Choice*>(ht); Choice* choice = dynamic_cast<Choice*>(ht);
choice->set_values(types); choice->set_values(types);
int index_in_choice = (printer_change ? 0 : last_in_conf); int index_in_choice = (printer_change ? 0 : last_in_conf);
choice->set_value(index_in_choice); choice->set_value(index_in_choice);
if (link.supported && link.label == _(ht->m_opt.enum_labels[index_in_choice])) if (link.supported && link.label == _(ht->m_opt.enum_def->label(index_in_choice)))
m_config->set_key_value("host_type", new ConfigOptionEnum<PrintHostType>(htPrusaLink)); m_config->set_key_value("host_type", new ConfigOptionEnum<PrintHostType>(htPrusaLink));
else if (link.supported && link.label == _(ht->m_opt.enum_labels[index_in_choice])) else if (link.supported && link.label == _(ht->m_opt.enum_def->label(index_in_choice)))
m_config->set_key_value("host_type", new ConfigOptionEnum<PrintHostType>(htPrusaConnect)); m_config->set_key_value("host_type", new ConfigOptionEnum<PrintHostType>(htPrusaConnect));
else { else {
int host_type = std::clamp(index_in_choice + ((int)ht->m_opt.enum_values.size() - (int)types.size()), 0, (int)ht->m_opt.enum_values.size() - 1); int host_type = std::clamp(index_in_choice + ((int)ht->m_opt.enum_def->values().size() - (int)types.size()), 0, (int)ht->m_opt.enum_def->values().size() - 1);
PrintHostType type = static_cast<PrintHostType>(host_type); PrintHostType type = static_cast<PrintHostType>(host_type);
m_config->set_key_value("host_type", new ConfigOptionEnum<PrintHostType>(type)); m_config->set_key_value("host_type", new ConfigOptionEnum<PrintHostType>(type));
} }

View File

@ -433,12 +433,13 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) :
ConfigOptionDef support_def; ConfigOptionDef support_def;
support_def.label = L("Supports"); support_def.label = L("Supports");
support_def.type = coStrings; support_def.type = coStrings;
support_def.gui_type = ConfigOptionDef::GUIType::select_open;
support_def.tooltip = L("Select what kind of support do you need"); support_def.tooltip = L("Select what kind of support do you need");
support_def.enum_labels.push_back(L("None")); support_def.set_enum_labels(ConfigOptionDef::GUIType::select_open, {
support_def.enum_labels.push_back(L("Support on build plate only")); L("None"),
support_def.enum_labels.push_back(L("For support enforcers only")); L("Support on build plate only"),
support_def.enum_labels.push_back(L("Everywhere")); L("For support enforcers only"),
L("Everywhere")
});
support_def.set_default_value(new ConfigOptionStrings{ "None" }); support_def.set_default_value(new ConfigOptionStrings{ "None" });
Option option = Option(support_def, "support"); Option option = Option(support_def, "support");
option.opt.full_width = true; option.opt.full_width = true;
@ -587,11 +588,12 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) :
ConfigOptionDef pad_def; ConfigOptionDef pad_def;
pad_def.label = L("Pad"); pad_def.label = L("Pad");
pad_def.type = coStrings; pad_def.type = coStrings;
pad_def.gui_type = ConfigOptionDef::GUIType::select_open;
pad_def.tooltip = L("Select what kind of pad do you need"); pad_def.tooltip = L("Select what kind of pad do you need");
pad_def.enum_labels.push_back(L("None")); pad_def.set_enum_labels(ConfigOptionDef::GUIType::select_open, {
pad_def.enum_labels.push_back(L("Below object")); L("None"),
pad_def.enum_labels.push_back(L("Around object")); L("Below object"),
L("Around object")
});
pad_def.set_default_value(new ConfigOptionStrings{ "Below object" }); pad_def.set_default_value(new ConfigOptionStrings{ "Below object" });
option = Option(pad_def, "pad"); option = Option(pad_def, "pad");
option.opt.full_width = true; option.opt.full_width = true;

View File

@ -165,23 +165,20 @@ static void append_bool_option( std::shared_ptr<ConfigOptionsGroup> optgroup,
wxGetApp().sidebar().get_searcher().add_key(opt_key, Preset::TYPE_PREFERENCES, optgroup->config_category(), L("Preferences")); wxGetApp().sidebar().get_searcher().add_key(opt_key, Preset::TYPE_PREFERENCES, optgroup->config_category(), L("Preferences"));
} }
template<typename EnumType>
static void append_enum_option( std::shared_ptr<ConfigOptionsGroup> optgroup, static void append_enum_option( std::shared_ptr<ConfigOptionsGroup> optgroup,
const std::string& opt_key, const std::string& opt_key,
const std::string& label, const std::string& label,
const std::string& tooltip, const std::string& tooltip,
const ConfigOption* def_val, const ConfigOption* def_val,
const t_config_enum_values *enum_keys_map, std::initializer_list<std::pair<std::string_view, std::string_view>> enum_values,
std::initializer_list<std::string> enum_values,
std::initializer_list<std::string> enum_labels,
ConfigOptionMode mode = comSimple) ConfigOptionMode mode = comSimple)
{ {
ConfigOptionDef def = {opt_key, coEnum }; ConfigOptionDef def = {opt_key, coEnum };
def.label = label; def.label = label;
def.tooltip = tooltip; def.tooltip = tooltip;
def.mode = mode; def.mode = mode;
def.enum_keys_map = enum_keys_map; def.set_enum<EnumType>(enum_values);
def.enum_values = std::vector<std::string>(enum_values);
def.enum_labels = std::vector<std::string>(enum_labels);
def.set_default_value(def_val); def.set_default_value(def_val);
Option option(def, opt_key); Option option(def, opt_key);
@ -210,7 +207,7 @@ static void append_string_option(std::shared_ptr<ConfigOptionsGroup> optgroup,
wxGetApp().sidebar().get_searcher().add_key(opt_key, Preset::TYPE_PREFERENCES, optgroup->config_category(), L("Preferences")); wxGetApp().sidebar().get_searcher().add_key(opt_key, Preset::TYPE_PREFERENCES, optgroup->config_category(), L("Preferences"));
} }
static void append_preferences_option_to_searcer(std::shared_ptr<ConfigOptionsGroup> optgroup, static void append_preferences_option_to_searcher(std::shared_ptr<ConfigOptionsGroup> optgroup,
const std::string& opt_key, const std::string& opt_key,
const wxString& label) const wxString& label)
{ {
@ -547,13 +544,14 @@ void PreferencesDialog::build()
L("If enabled, useful hints are displayed at startup."), L("If enabled, useful hints are displayed at startup."),
app_config->get("show_hints") == "1"); app_config->get("show_hints") == "1");
append_enum_option(m_optgroup_gui, "notify_release", append_enum_option<NotifyReleaseMode>(m_optgroup_gui, "notify_release",
L("Notify about new releases"), L("Notify about new releases"),
L("You will be notified about new release after startup acordingly: All = Regular release and alpha / beta releases. Release only = regular release."), L("You will be notified about new release after startup acordingly: All = Regular release and alpha / beta releases. Release only = regular release."),
new ConfigOptionEnum<NotifyReleaseMode>(static_cast<NotifyReleaseMode>(s_keys_map_NotifyReleaseMode.at(app_config->get("notify_release")))), new ConfigOptionEnum<NotifyReleaseMode>(static_cast<NotifyReleaseMode>(s_keys_map_NotifyReleaseMode.at(app_config->get("notify_release")))),
&ConfigOptionEnum<NotifyReleaseMode>::get_enum_values(), { { "all", L("All") },
{"all", "release", "none"}, { "release", L("Release only") },
{L("All"), L("Release only"), L("None")}); { "none", L("None") }
});
m_optgroup_gui->append_separator(); m_optgroup_gui->append_separator();
@ -1026,7 +1024,7 @@ void PreferencesDialog::create_settings_mode_widget()
sizer->Add(stb_sizer, 1, wxALIGN_CENTER_VERTICAL); sizer->Add(stb_sizer, 1, wxALIGN_CENTER_VERTICAL);
m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit());
append_preferences_option_to_searcer(m_optgroup_gui, opt_key, title); append_preferences_option_to_searcher(m_optgroup_gui, opt_key, title);
} }
void PreferencesDialog::create_settings_text_color_widget() void PreferencesDialog::create_settings_text_color_widget()
@ -1050,7 +1048,7 @@ void PreferencesDialog::create_settings_text_color_widget()
m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit());
append_preferences_option_to_searcer(m_optgroup_gui, opt_key, title); append_preferences_option_to_searcher(m_optgroup_gui, opt_key, title);
} }
void PreferencesDialog::create_settings_mode_color_widget() void PreferencesDialog::create_settings_mode_color_widget()
@ -1077,7 +1075,7 @@ void PreferencesDialog::create_settings_mode_color_widget()
m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); m_optgroup_gui->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit());
append_preferences_option_to_searcer(m_optgroup_gui, opt_key, title); append_preferences_option_to_searcher(m_optgroup_gui, opt_key, title);
} }
void PreferencesDialog::create_downloader_path_sizer() void PreferencesDialog::create_downloader_path_sizer()
@ -1096,7 +1094,7 @@ void PreferencesDialog::create_downloader_path_sizer()
m_optgroup_other->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit()); m_optgroup_other->sizer->Add(sizer, 0, wxEXPAND | wxTOP, em_unit());
append_preferences_option_to_searcer(m_optgroup_other, opt_key, title); append_preferences_option_to_searcher(m_optgroup_other, opt_key, title);
} }
void PreferencesDialog::init_highlighter(const t_config_option_key& opt_key) void PreferencesDialog::init_highlighter(const t_config_option_key& opt_key)

View File

@ -111,7 +111,7 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty
for (std::string opt_key : config->keys()) for (std::string opt_key : config->keys())
{ {
const ConfigOptionDef& opt = config->def()->options.at(opt_key); const ConfigOptionDef& opt = *config->option_def(opt_key);
if (opt.mode > mode) if (opt.mode > mode)
continue; continue;

View File

@ -1056,27 +1056,6 @@ bool UnsavedChangesDialog::save(PresetCollection* dependent_presets, bool show_s
return true; return true;
} }
wxString get_string_from_enum(const std::string& opt_key, const DynamicPrintConfig& config, bool is_infill = false)
{
const ConfigOptionDef& def = config.def()->options.at(opt_key);
const std::vector<std::string>& names = def.enum_labels.empty() ? def.enum_values : def.enum_labels;
int val = config.option(opt_key)->getInt();
// Each infill doesn't use all list of infill declared in PrintConfig.hpp.
// So we should "convert" val to the correct one
if (is_infill) {
for (auto key_val : *def.enum_keys_map)
if (int(key_val.second) == val) {
auto it = std::find(def.enum_values.begin(), def.enum_values.end(), key_val.first);
if (it == def.enum_values.end())
return "";
return from_u8(_utf8(names[it - def.enum_values.begin()]));
}
return _L("Undef");
}
return from_u8(_utf8(names[val]));
}
static size_t get_id_from_opt_key(std::string opt_key) static size_t get_id_from_opt_key(std::string opt_key)
{ {
int pos = opt_key.find("#"); int pos = opt_key.find("#");
@ -1214,11 +1193,8 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
return out; return out;
} }
case coEnum: { case coEnum: {
return get_string_from_enum(opt_key, config, auto opt = config.option_def(opt_key)->enum_def->enum_to_label(config.option(opt_key)->getInt());
opt_key == "top_fill_pattern" || return opt.has_value() ? _(wxString::FromUTF8(opt.value())) : _L("Undef");
opt_key == "bottom_fill_pattern" ||
opt_key == "fill_pattern" ||
opt_key == "support_material_style");
} }
case coPoints: { case coPoints: {
if (opt_key == "bed_shape") { if (opt_key == "bed_shape") {