mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-13 02:41:16 +00:00
Support searching the Speed Dial by English names in any UI language (#16369)
This commit is contained in:
@@ -206,19 +206,52 @@ constexpr const char* kPlateGotoPrefix = "orca_plate_goto";
|
||||
constexpr const char* kRecentProjectPrefix = "orca_recent_project";
|
||||
|
||||
// Display context for a setting action's eyebrow, e.g. the "Process" in "Process : Quality : Layers".
|
||||
// Keyed by the option's preset type so the palette reads like the settings sidebar tabs.
|
||||
std::string setting_type_context(Preset::Type type)
|
||||
// Keyed by the option's preset type so the palette reads like the settings sidebar tabs. Untranslated:
|
||||
// the caller translates it for the displayed breadcrumb and keeps it for the English one.
|
||||
const char* setting_type_context(Preset::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Preset::TYPE_FILAMENT:
|
||||
case Preset::TYPE_SLA_MATERIAL: return _u8L("Filament");
|
||||
case Preset::TYPE_PRINTER: return _u8L("Printer");
|
||||
case Preset::TYPE_SLA_MATERIAL: return L("Filament");
|
||||
case Preset::TYPE_PRINTER: return L("Printer");
|
||||
case Preset::TYPE_PRINT:
|
||||
case Preset::TYPE_SLA_PRINT:
|
||||
default: return _u8L("Process");
|
||||
default: return L("Process");
|
||||
}
|
||||
}
|
||||
|
||||
// A setting's text in one language. The displayed text and its English search aliases both come from
|
||||
// here, so in an English UI the two are equal and no alias is sent.
|
||||
struct SettingText
|
||||
{
|
||||
std::string title; // the label the settings row draws
|
||||
std::string full_label; // the descriptive ConfigOptionDef name when it differs from title: a
|
||||
// search-only alias ("overhang reversal" still finds "Reverse on even")
|
||||
std::string source; // the full settings path "Process : Quality : Layers". The JS renders
|
||||
// group || source and searches every field, so putting the whole path in
|
||||
// source both displays it and makes it matchable by any segment.
|
||||
};
|
||||
|
||||
SettingText setting_text(const std::wstring& def_label, const std::string& display_label, const wxString& row_label, bool row_multi,
|
||||
const std::string& type_name, const std::wstring& category, const std::wstring& group)
|
||||
{
|
||||
SettingText text;
|
||||
const std::string def = boost::nowide::narrow(def_label);
|
||||
text.title = into_u8(Search::resolve_setting_title(from_u8(display_label), row_label, row_multi));
|
||||
if (text.title.empty())
|
||||
text.title = def;
|
||||
if (text.title != def)
|
||||
text.full_label = def;
|
||||
|
||||
std::wstring path = boost::nowide::widen(type_name);
|
||||
if (!category.empty())
|
||||
path += L" : " + category;
|
||||
if (!group.empty())
|
||||
path += L" : " + group;
|
||||
text.source = boost::nowide::narrow(path);
|
||||
return text;
|
||||
}
|
||||
|
||||
// Stable, non-localized mode token for the webview, which maps it to a badge ("Developer" etc.).
|
||||
const char* mode_key(ConfigOptionMode mode)
|
||||
{
|
||||
@@ -305,8 +338,9 @@ struct PlateAction : AppAction
|
||||
PlateAction(int index, std::string title, std::string source_name)
|
||||
: AppAction(AppActionId{id_for(index)}, std::move(title), kOrcaSourceKey, std::move(source_name)), plate_index(index)
|
||||
{
|
||||
this->kind = AppActionKind::Command;
|
||||
this->group = _u8L("Plate");
|
||||
this->kind = AppActionKind::Command;
|
||||
this->group_en = L("Plate");
|
||||
this->group = I18N::translate_utf8(this->group_en);
|
||||
}
|
||||
|
||||
AppActionRunResult run(const std::string& /*param*/) const override
|
||||
@@ -328,8 +362,9 @@ struct RecentProjectAction : AppAction
|
||||
RecentProjectAction(std::string path, std::string title, std::string source)
|
||||
: AppAction(AppActionId{id_for(path)}, std::move(title), kOrcaSourceKey, std::move(source)), file_path(std::move(path))
|
||||
{
|
||||
this->kind = AppActionKind::Command;
|
||||
this->group = _u8L("Recent Projects");
|
||||
this->kind = AppActionKind::Command;
|
||||
this->group_en = L("Recent Projects");
|
||||
this->group = I18N::translate_utf8(this->group_en);
|
||||
}
|
||||
|
||||
AppActionRunResult run(const std::string& /*param*/) const override
|
||||
@@ -342,6 +377,30 @@ struct RecentProjectAction : AppAction
|
||||
|
||||
} // namespace
|
||||
|
||||
nlohmann::json action_json(const AppAction& a)
|
||||
{
|
||||
nlohmann::json j({{"id", a.id()},
|
||||
{"title", a.title()},
|
||||
{"full_label", a.full_label},
|
||||
{"source", a.source_name()},
|
||||
{"group", a.group},
|
||||
{"kind", a.kind == AppActionKind::Plugin ? "plugin" : "command"},
|
||||
{"input", a.input},
|
||||
{"icon", a.icon},
|
||||
{"mode", mode_key(a.required_mode)},
|
||||
{"desc", a.tooltip},
|
||||
{"wiki", !a.help_url.empty()}});
|
||||
auto add_alias = [&j](const char* key, const std::string& english, const std::string& local) {
|
||||
if (!english.empty() && english != local)
|
||||
j[key] = english;
|
||||
};
|
||||
add_alias("title_en", a.title_en, a.title());
|
||||
add_alias("group_en", a.group_en, a.group);
|
||||
add_alias("source_en", a.source_en, a.source_name());
|
||||
add_alias("full_label_en", a.full_label_en, a.full_label);
|
||||
return j;
|
||||
}
|
||||
|
||||
ActionRegistry::~ActionRegistry() = default;
|
||||
|
||||
void ActionRegistry::init()
|
||||
@@ -430,7 +489,8 @@ void ActionRegistry::relocalize_builtins()
|
||||
|
||||
// Drop only the built-in commands; plugins and the dynamically materialised families are
|
||||
// either unlocalized or rebuilt per snapshot. remove() only erases the map entry, and upsert()
|
||||
// re-seeds favourites/stats from config, so key-based ids keep their pinned state.
|
||||
// re-seeds favourites/stats from config, so key-based ids keep their pinned state. make_action()
|
||||
// translates in the new locale.
|
||||
std::vector<std::string> stale;
|
||||
for (const auto& [id, action] : m_actions)
|
||||
if (action->source_key() == kOrcaSourceKey && action->kind == AppActionKind::Command)
|
||||
@@ -438,7 +498,6 @@ void ActionRegistry::relocalize_builtins()
|
||||
for (const std::string& id : stale)
|
||||
remove(id);
|
||||
|
||||
NativeCommands::rebuild_catalog();
|
||||
for (const NativeCommand& c : NativeCommands::catalog())
|
||||
upsert(NativeCommands::make_action(c));
|
||||
}
|
||||
@@ -672,28 +731,22 @@ void ActionRegistry::materialize_setting_actions()
|
||||
const std::string id = SettingAction::id_for(opt.opt_key(), opt.type);
|
||||
seen.insert(id);
|
||||
|
||||
// The page draws Line::label; the descriptive ConfigOptionDef name stays a search-only alias
|
||||
// ("overhang reversal" still finds "Reverse on even").
|
||||
const std::string search_label = boost::nowide::narrow(opt.label_local.empty() ? opt.label : opt.label_local);
|
||||
std::string title = into_u8(Search::resolve_setting_title(from_u8(opt.display_label), row.label, row.multi));
|
||||
if (title.empty())
|
||||
title = search_label;
|
||||
// The localized text the page shows, and its English search aliases from the untranslated row
|
||||
// label, def name and breadcrumb.
|
||||
const char* type_context = setting_type_context(opt.type);
|
||||
SettingText local = setting_text(opt.label_local.empty() ? opt.label : opt.label_local, opt.display_label, row.label, row.multi,
|
||||
I18N::translate_utf8(type_context), opt.category_local, opt.group_local);
|
||||
SettingText english = setting_text(opt.label, opt.display_label_en, row.label_en, row.multi, type_context,
|
||||
Tab::translate_category(opt.category, opt.type, false).ToStdWstring(), opt.group);
|
||||
|
||||
// Eyebrow/source = the full settings path "Process : Quality : Layers" (localized). The JS
|
||||
// renders group || source and searches source + " " + group, so putting the whole path in
|
||||
// source both displays it and makes it matchable by any segment (e.g. a "quality" query).
|
||||
std::wstring path = boost::nowide::widen(setting_type_context(opt.type));
|
||||
if (!opt.category_local.empty())
|
||||
path += L" : " + opt.category_local;
|
||||
if (!opt.group_local.empty())
|
||||
path += L" : " + opt.group_local;
|
||||
|
||||
// title = the label the settings row draws; group stays empty so the source path (above) is
|
||||
// the single display/search breadcrumb rather than being duplicated.
|
||||
auto action = std::make_unique<SettingAction>(opt.opt_key(), opt.type, title, std::string(), opt.category,
|
||||
boost::nowide::narrow(path), opt.mode);
|
||||
if (title != search_label)
|
||||
action->full_label = search_label;
|
||||
// group stays empty so the source path is the single display/search breadcrumb rather than
|
||||
// being duplicated.
|
||||
auto action = std::make_unique<SettingAction>(opt.opt_key(), opt.type, local.title, std::string(), opt.category, local.source,
|
||||
opt.mode);
|
||||
action->full_label = std::move(local.full_label);
|
||||
action->title_en = std::move(english.title);
|
||||
action->full_label_en = std::move(english.full_label);
|
||||
action->source_en = std::move(english.source);
|
||||
|
||||
// Tile pictogram = the icon of the setting's own group header (e.g. Advanced -> param_advanced),
|
||||
// the one shown next to it in the page. Fall back to the page/category icon for groups
|
||||
@@ -751,13 +804,14 @@ void ActionRegistry::materialize_plate_actions()
|
||||
seen.insert(id);
|
||||
|
||||
// "Go to Plate N" + " (name)" when the plate is named, matching the object-list label.
|
||||
std::string title(_u8L("Go to Plate"));
|
||||
title += " " + std::to_string(i + 1);
|
||||
const std::string name = plate->get_plate_name();
|
||||
const char* go_to_plate = L("Go to Plate");
|
||||
std::string suffix = " " + std::to_string(i + 1);
|
||||
const std::string name = plate->get_plate_name();
|
||||
if (!name.empty())
|
||||
title += " (" + name + ")";
|
||||
suffix += " (" + name + ")";
|
||||
|
||||
auto action = std::make_unique<PlateAction>(int(i), title, kOrcaSourceName);
|
||||
auto action = std::make_unique<PlateAction>(int(i), I18N::translate_utf8(go_to_plate) + suffix, kOrcaSourceName);
|
||||
action->title_en = go_to_plate + suffix;
|
||||
seed_from(stats, favs, id, *action);
|
||||
auto const action_id = action->id();
|
||||
auto const app_action = std::shared_ptr<AppAction>(std::move(action));
|
||||
@@ -868,23 +922,9 @@ nlohmann::json ActionRegistry::snapshot()
|
||||
return a->id() < b->id();
|
||||
});
|
||||
|
||||
auto action_to_json = [](const AppAction* a) {
|
||||
return nlohmann::json({{"id", a->id()},
|
||||
{"title", a->title()},
|
||||
{"full_label", a->full_label},
|
||||
{"source", a->source_name()},
|
||||
{"group", a->group},
|
||||
{"kind", a->kind == AppActionKind::Plugin ? "plugin" : "command"},
|
||||
{"input", a->input},
|
||||
{"icon", a->icon},
|
||||
{"mode", mode_key(a->required_mode)},
|
||||
{"desc", a->tooltip},
|
||||
{"wiki", !a->help_url.empty()}});
|
||||
};
|
||||
|
||||
nlohmann::json actions = nlohmann::json::array();
|
||||
for (const AppAction* a : sorted)
|
||||
actions.push_back(action_to_json(a));
|
||||
actions.push_back(action_json(*a));
|
||||
|
||||
// why: favourites is the ORDERED pin list - it must come from favourite_actions
|
||||
// as stored, not be re-derived from the frecency-sorted actions (that would
|
||||
@@ -917,7 +957,7 @@ nlohmann::json ActionRegistry::snapshot()
|
||||
recent.resize(recent_limit);
|
||||
nlohmann::json recent_json = nlohmann::json::array();
|
||||
for (const AppAction* a : recent)
|
||||
recent_json.push_back(action_to_json(a));
|
||||
recent_json.push_back(action_json(*a));
|
||||
|
||||
return {{"actions", std::move(actions)},
|
||||
{"favourites", std::move(favourites)},
|
||||
@@ -937,14 +977,21 @@ nlohmann::json ActionRegistry::tab_options() const
|
||||
MainFrame* mf = wxGetApp().mainframe;
|
||||
if (!mf || !mf->m_tabpanel)
|
||||
return out;
|
||||
// English labels of the built-in pages whose id is not already their English name, so the tab
|
||||
// picker can be searched in English in any UI language.
|
||||
static const std::unordered_map<std::string, const char*> english_labels{
|
||||
{TAB_ID_MONITOR, L("Device")}, {TAB_ID_MONITOR_WEB, L("Device (Web)")}, {TAB_ID_MULTI_DEVICE, L("Multi-device")}};
|
||||
|
||||
Notebook* notebook = mf->m_tabpanel;
|
||||
for (size_t i = 0; i < notebook->GetPageCount(); ++i) {
|
||||
const wxString id = notebook->GetPageName(i);
|
||||
if (id.empty())
|
||||
continue;
|
||||
out.push_back({{"id", id.ToStdString()},
|
||||
{"title", notebook->GetPageLabel(i).ToStdString()},
|
||||
{"icon", notebook->GetPageIcon(i)}});
|
||||
const std::string title = notebook->GetPageLabel(i).ToStdString();
|
||||
nlohmann::json tab({{"id", id.ToStdString()}, {"title", title}, {"icon", notebook->GetPageIcon(i)}});
|
||||
if (auto it = english_labels.find(id.ToStdString()); it != english_labels.end() && title != it->second)
|
||||
tab["title_en"] = it->second;
|
||||
out.push_back(std::move(tab));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -88,6 +88,14 @@ struct AppAction
|
||||
// Search-only alias when the title differs from the descriptive ConfigOptionDef name (e.g. title
|
||||
// "Reverse on even", full_label "Overhang reversal"). Empty when the two agree.
|
||||
std::string full_label;
|
||||
// Search-only English counterparts of title(), group, source_name() and full_label, so a
|
||||
// localized UI can still be searched in English. Each is derived exactly like the localized
|
||||
// text it mirrors, minus the translation, so in an English UI it equals that text. Empty when
|
||||
// there is no translated counterpart.
|
||||
std::string title_en;
|
||||
std::string group_en;
|
||||
std::string source_en;
|
||||
std::string full_label_en;
|
||||
// Full wiki URL, when the action has one (SettingActions whose row declared a label_path).
|
||||
std::string help_url;
|
||||
|
||||
@@ -138,6 +146,11 @@ inline bool requires_mode_switch(ConfigOptionMode setting_mode, ConfigOptionMode
|
||||
// hand-edited config must never grow the quick-launch bar past `limit`, and a duplicated id must collapse to its first pin.
|
||||
std::vector<std::string> cap_favourites(const std::vector<std::string>& ids, size_t limit);
|
||||
|
||||
// One action as the Speed Dial page receives it. Each English alias (title_en, group_en, source_en,
|
||||
// full_label_en) is sent only when it is non-empty and differs from its localized counterpart, so an
|
||||
// English UI receives none and searches exactly the displayed text.
|
||||
nlohmann::json action_json(const AppAction& a);
|
||||
|
||||
// Self-contained sink and single owner of runnable actions for the app session.
|
||||
//
|
||||
// Workflow:
|
||||
|
||||
@@ -1020,7 +1020,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in
|
||||
const BrimType brim_type = config->opt_enum<BrimType>("brim_type");
|
||||
const bool have_auto_brim_ear = brim_type == btEar && !is_belt_tilted;
|
||||
const bool have_painted_brim_ear = brim_type == btPainted && !is_belt_tilted;
|
||||
set_option_label("brim_width", have_auto_brim_ear ? _L("Brim ear radius") : _L("Brim width"));
|
||||
set_option_label("brim_width", have_auto_brim_ear ? L("Brim ear radius") : L("Brim width"));
|
||||
const auto brim_width = config->opt_float("brim_width");
|
||||
// Automatic brim ear settings require a non-zero brim width.
|
||||
toggle_field("brim_ears_max_angle", brim_width > 0.0f);
|
||||
|
||||
@@ -80,6 +80,8 @@ public:
|
||||
t_config_option_keys const &applying_keys() const;
|
||||
void toggle_field(const std::string& field_key, const bool toggle, int opt_index = -1);
|
||||
void toggle_line(const std::string& field_key, const bool toggle, int opt_index = -1);
|
||||
// Renames an option's row. `label` is the untranslated English msgid (an L("...") string); the
|
||||
// row translates it for display.
|
||||
void set_option_label(const std::string& field_key, const wxString& label, int opt_index = -1);
|
||||
|
||||
// FFF print
|
||||
|
||||
+106
-113
@@ -142,19 +142,24 @@ struct CommandAction : AppAction
|
||||
AppActionRunResult run(const std::string& param) const override { return NativeCommands::run(command_key, param); }
|
||||
|
||||
explicit CommandAction(const NativeCommand& c)
|
||||
: AppAction(AppActionId{AppAction::compose_id(kCommandPrefix, c.key, kOrcaSourceKey)}, c.title, kOrcaSourceKey, kOrcaSourceName)
|
||||
: AppAction(AppActionId{AppAction::compose_id(kCommandPrefix, c.key, kOrcaSourceKey)}, I18N::translate_utf8(c.title), kOrcaSourceKey,
|
||||
kOrcaSourceName)
|
||||
, command_key(c.key)
|
||||
{
|
||||
this->kind = AppActionKind::Command;
|
||||
this->group = c.group;
|
||||
this->input = c.input;
|
||||
this->icon = c.icon;
|
||||
this->kind = AppActionKind::Command;
|
||||
this->group = I18N::translate_utf8(c.group);
|
||||
this->title_en = c.title;
|
||||
this->group_en = c.group;
|
||||
this->input = c.input;
|
||||
this->icon = c.icon;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<NativeCommand> build_command_catalog()
|
||||
{
|
||||
std::vector<NativeCommand> out;
|
||||
// `title` and `group` are the untranslated English msgids, L("...")-marked at each call so xgettext
|
||||
// extracts them.
|
||||
auto add = [&](std::string key, std::string title, std::string group, std::function<AppActionRunResult(const std::string&)> runner,
|
||||
std::string input = {}, std::string icon = {}) {
|
||||
out.push_back({std::move(key), std::move(title), std::move(group), std::move(input), std::move(icon), std::move(runner)});
|
||||
@@ -166,7 +171,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
};
|
||||
|
||||
// ---- Slice & Export ----
|
||||
add_with_icon("slice_and_preview", _u8L("Slice and Preview"), _u8L("Slice & Export"), "media_play", [](const std::string&) {
|
||||
add_with_icon("slice_and_preview", L("Slice and Preview"), L("Slice & Export"), "media_play", [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (plater) {
|
||||
plater->reslice();
|
||||
@@ -178,7 +183,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
});
|
||||
|
||||
add_with_icon(
|
||||
"go_to_layer", _u8L("Go to layer (percent)"), _u8L("Commands"), "height_range_layer",
|
||||
"go_to_layer", L("Go to layer (percent)"), L("Commands"), "height_range_layer",
|
||||
[](const std::string& param) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (plater) {
|
||||
@@ -194,7 +199,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
// "go_to_tab" is two-phase: the palette collects the tab after activating it, then hands the tab
|
||||
// id back as `param` (same contract as go_to_layer's percent).
|
||||
add(
|
||||
"go_to_tab", _u8L("Go to tab..."), _u8L("Commands"),
|
||||
"go_to_tab", L("Go to tab..."), L("Commands"),
|
||||
[](const std::string& param) {
|
||||
if (MainFrame* mf = wxGetApp().mainframe; mf && !param.empty())
|
||||
mf->select_tab(from_u8(param));
|
||||
@@ -202,41 +207,41 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
},
|
||||
"tab");
|
||||
|
||||
add_with_icon("load_project", _u8L("Load Project"), _u8L("Commands"), "menu_open", [](const std::string&) {
|
||||
add_with_icon("load_project", L("Load Project"), L("Commands"), "menu_open", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->load_project();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("save_project", _u8L("Save Project"), _u8L("Commands"), "menu_save", [](const std::string&) {
|
||||
add_with_icon("save_project", L("Save Project"), L("Commands"), "menu_save", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->save_project(false);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("save_project_as", _u8L("Save Project As"), _u8L("Commands"), "menu_save", [](const std::string&) {
|
||||
add_with_icon("save_project_as", L("Save Project As"), L("Commands"), "menu_save", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->save_project(true);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("open_preferences", _u8L("Preferences"), _u8L("Commands"), "cog", [](const std::string&) {
|
||||
add_with_icon("open_preferences", L("Preferences"), L("Commands"), "cog", [](const std::string&) {
|
||||
wxGetApp().open_preferences();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
|
||||
// ---- Mode ----
|
||||
add_with_icon("mode_simple", _u8L("Mode: Simple"), _u8L("Mode"), "advanced", [](const std::string&) {
|
||||
add_with_icon("mode_simple", L("Mode: Simple"), L("Mode"), "advanced", [](const std::string&) {
|
||||
wxGetApp().set_mode(comSimple);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("mode_advanced", _u8L("Mode: Advanced"), _u8L("Mode"), "advanced", [](const std::string&) {
|
||||
add_with_icon("mode_advanced", L("Mode: Advanced"), L("Mode"), "advanced", [](const std::string&) {
|
||||
wxGetApp().set_mode(comAdvanced);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("mode_expert", _u8L("Mode: Expert"), _u8L("Mode"), "advanced", [](const std::string&) {
|
||||
add_with_icon("mode_expert", L("Mode: Expert"), L("Mode"), "advanced", [](const std::string&) {
|
||||
wxGetApp().set_mode(comExpert);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
// Mirrors Preferences > Developer > Developer mode: flip the flag, persist, refresh the UI.
|
||||
add_with_icon("toggle_developer_mode", _u8L("Toggle Developer Mode"), _u8L("Mode"), "advanced", [](const std::string&) {
|
||||
add_with_icon("toggle_developer_mode", L("Toggle Developer Mode"), L("Mode"), "advanced", [](const std::string&) {
|
||||
GUI_App& app = wxGetApp();
|
||||
const bool on = !app.app_config->get_bool("developer_mode");
|
||||
app.app_config->set_bool("developer_mode", on);
|
||||
@@ -246,27 +251,27 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
});
|
||||
|
||||
// ---- Export pipeline ----
|
||||
add_with_icon("export_gcode", _u8L("Export G-code"), _u8L("Slice & Export"), "custom-gcode_gcode", [](const std::string&) {
|
||||
add_with_icon("export_gcode", L("Export G-code"), L("Slice & Export"), "custom-gcode_gcode", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->export_gcode(false);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("export_stl", _u8L("Export STL"), _u8L("Slice & Export"), "save", [](const std::string&) {
|
||||
add_with_icon("export_stl", L("Export STL"), L("Slice & Export"), "save", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->export_stl();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("export_3mf", _u8L("Export 3MF"), _u8L("Slice & Export"), "menu_save", [](const std::string&) {
|
||||
add_with_icon("export_3mf", L("Export 3MF"), L("Slice & Export"), "menu_save", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->export_core_3mf();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("export_sliced_file", _u8L("Export Sliced File"), _u8L("Slice & Export"), "save", [](const std::string&) {
|
||||
add_with_icon("export_sliced_file", L("Export Sliced File"), L("Slice & Export"), "save", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->export_gcode_3mf(false);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("export_all_sliced_file", _u8L("Export All Sliced Files"), _u8L("Slice & Export"), "save", [](const std::string&) {
|
||||
add_with_icon("export_all_sliced_file", L("Export All Sliced Files"), L("Slice & Export"), "save", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->export_gcode_3mf(true);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
@@ -275,39 +280,39 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
// ---- Calibration ----
|
||||
// The tab-strip calib_sf glyph is drawn white for the dark tab bar and vanishes on the palette's
|
||||
// light tile, so each wizard borrows the matching settings-group icon instead (gray + accent green).
|
||||
add_with_icon("calib_temperature", _u8L("Temperature Calibration"), _u8L("Calibration"), "param_temperature",
|
||||
add_with_icon("calib_temperature", L("Temperature Calibration"), L("Calibration"), "param_temperature",
|
||||
[](const std::string&) { return calib_command(CalibKind::Temperature); });
|
||||
add_with_icon("calib_max_volumetric", _u8L("Max Volumetric Speed Calibration"), _u8L("Calibration"), "param_volumetric_speed",
|
||||
add_with_icon("calib_max_volumetric", L("Max Volumetric Speed Calibration"), L("Calibration"), "param_volumetric_speed",
|
||||
[](const std::string&) { return calib_command(CalibKind::MaxVolumetric); });
|
||||
add_with_icon("calib_pressure_advance", _u8L("Pressure Advance Calibration"), _u8L("Calibration"), "param_flow_ratio_and_pressure_advance",
|
||||
add_with_icon("calib_pressure_advance", L("Pressure Advance Calibration"), L("Calibration"), "param_flow_ratio_and_pressure_advance",
|
||||
[](const std::string&) { return calib_command(CalibKind::PressureAdvance); });
|
||||
add_with_icon("calib_flow_ratio", _u8L("Flow Ratio Calibration"), _u8L("Calibration"), "param_flow_ratio_and_pressure_advance",
|
||||
add_with_icon("calib_flow_ratio", L("Flow Ratio Calibration"), L("Calibration"), "param_flow_ratio_and_pressure_advance",
|
||||
[](const std::string&) { return calib_command(CalibKind::FlowRatio); });
|
||||
add_with_icon("calib_retraction", _u8L("Retraction Calibration"), _u8L("Calibration"), "param_retraction",
|
||||
add_with_icon("calib_retraction", L("Retraction Calibration"), L("Calibration"), "param_retraction",
|
||||
[](const std::string&) { return calib_command(CalibKind::Retraction); });
|
||||
add_with_icon("calib_cornering", _u8L("Cornering Calibration"), _u8L("Calibration"), "param_precision",
|
||||
add_with_icon("calib_cornering", L("Cornering Calibration"), L("Calibration"), "param_precision",
|
||||
[](const std::string&) { return calib_command(CalibKind::Cornering); });
|
||||
add_with_icon("calib_input_shaping_freq", _u8L("Input Shaping Frequency Calibration"), _u8L("Calibration"), "param_resonance_avoidance",
|
||||
add_with_icon("calib_input_shaping_freq", L("Input Shaping Frequency Calibration"), L("Calibration"), "param_resonance_avoidance",
|
||||
[](const std::string&) { return calib_command(CalibKind::InputShapingFreq); });
|
||||
add_with_icon("calib_input_shaping_damp", _u8L("Input Shaping Damping Calibration"), _u8L("Calibration"), "param_resonance_avoidance",
|
||||
add_with_icon("calib_input_shaping_damp", L("Input Shaping Damping Calibration"), L("Calibration"), "param_resonance_avoidance",
|
||||
[](const std::string&) { return calib_command(CalibKind::InputShapingDamp); });
|
||||
add_with_icon("calib_vfa", _u8L("VFA Calibration"), _u8L("Calibration"), "param_speed", [](const std::string&) { return calib_command(CalibKind::VFA); });
|
||||
add_with_icon("calib_vfa", L("VFA Calibration"), L("Calibration"), "param_speed", [](const std::string&) { return calib_command(CalibKind::VFA); });
|
||||
|
||||
// ---- View ----
|
||||
// Titles are built with _u8L here (not via a variable) so xgettext can extract them.
|
||||
// Titles are L("...")-marked here (not via a variable) so xgettext can extract them.
|
||||
for (auto [key, dir, title] :
|
||||
std::initializer_list<std::tuple<const char*, const char*, std::string>>{{"view_top", "top", _u8L("View: Top")},
|
||||
{"view_bottom", "bottom", _u8L("View: Bottom")},
|
||||
{"view_front", "front", _u8L("View: Front")},
|
||||
{"view_rear", "rear", _u8L("View: Rear")},
|
||||
{"view_left", "left", _u8L("View: Left")},
|
||||
{"view_right", "right", _u8L("View: Right")},
|
||||
{"view_iso", "iso", _u8L("View: Isometric")}}) {
|
||||
std::initializer_list<std::tuple<const char*, const char*, std::string>>{{"view_top", "top", L("View: Top")},
|
||||
{"view_bottom", "bottom", L("View: Bottom")},
|
||||
{"view_front", "front", L("View: Front")},
|
||||
{"view_rear", "rear", L("View: Rear")},
|
||||
{"view_left", "left", L("View: Left")},
|
||||
{"view_right", "right", L("View: Right")},
|
||||
{"view_iso", "iso", L("View: Isometric")}}) {
|
||||
std::string k = key, d = dir;
|
||||
add(k, title, _u8L("View"),
|
||||
add(k, title, L("View"),
|
||||
[d](const std::string&) { return view_command(wxGetApp().plater(), d); });
|
||||
}
|
||||
add("view_default", _u8L("View: Default"), _u8L("View"), [](const std::string&) {
|
||||
add("view_default", L("View: Default"), L("View"), [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (plater) {
|
||||
plater->select_view("plate");
|
||||
@@ -316,75 +321,75 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
}
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("view_fit_bed", _u8L("Fit Bed to View"), _u8L("View"), [](const std::string&) {
|
||||
add("view_fit_bed", L("Fit Bed to View"), L("View"), [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
if (GLCanvas3D* canvas = plater->get_current_canvas3D())
|
||||
canvas->zoom_to_bed();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("view_toggle_perspective", _u8L("Toggle Perspective"), _u8L("View"), [](const std::string&) {
|
||||
add("view_toggle_perspective", L("Toggle Perspective"), L("View"), [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->get_camera().select_next_type();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("reset_window_layout", _u8L("Reset Window Layout"), _u8L("View"), "toolbar_reset", [](const std::string&) {
|
||||
add_with_icon("reset_window_layout", L("Reset Window Layout"), L("View"), "toolbar_reset", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->reset_window_layout();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
|
||||
// ---- Object ----
|
||||
add_with_icon("obj_delete", _u8L("Delete Selected"), _u8L("Object"), "delete", [](const std::string&) {
|
||||
add_with_icon("obj_delete", L("Delete Selected"), L("Object"), "delete", [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return !p->is_selection_empty(); }, [](Plater* p) { p->remove_selected(); });
|
||||
});
|
||||
add_with_icon("obj_delete_all", _u8L("Delete All Objects"), _u8L("Object"), "delete", [](const std::string&) {
|
||||
add_with_icon("obj_delete_all", L("Delete All Objects"), L("Object"), "delete", [](const std::string&) {
|
||||
return object_op(
|
||||
wxGetApp().plater(), [](Plater* p) { return p->can_delete_all(); }, [](Plater* p) { p->delete_all_objects_from_model(); });
|
||||
});
|
||||
add_with_icon("obj_mirror_x", _u8L("Mirror X"), _u8L("Object"), "menu_mirror_x", [](const std::string&) {
|
||||
add_with_icon("obj_mirror_x", L("Mirror X"), L("Object"), "menu_mirror_x", [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return p->can_mirror(); }, [](Plater* p) { p->mirror(Axis::X); });
|
||||
});
|
||||
add_with_icon("obj_mirror_y", _u8L("Mirror Y"), _u8L("Object"), "menu_mirror_y", [](const std::string&) {
|
||||
add_with_icon("obj_mirror_y", L("Mirror Y"), L("Object"), "menu_mirror_y", [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return p->can_mirror(); }, [](Plater* p) { p->mirror(Axis::Y); });
|
||||
});
|
||||
add_with_icon("obj_mirror_z", _u8L("Mirror Z"), _u8L("Object"), "menu_mirror_z", [](const std::string&) {
|
||||
add_with_icon("obj_mirror_z", L("Mirror Z"), L("Object"), "menu_mirror_z", [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return p->can_mirror(); }, [](Plater* p) { p->mirror(Axis::Z); });
|
||||
});
|
||||
add_with_icon("obj_split_objects", _u8L("Split to Objects"), _u8L("Object"), "menu_split_objects", [](const std::string&) {
|
||||
add_with_icon("obj_split_objects", L("Split to Objects"), L("Object"), "menu_split_objects", [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return p->can_split_to_objects(); }, [](Plater* p) { p->split_object(true); });
|
||||
});
|
||||
add_with_icon("obj_split_parts", _u8L("Split to Parts"), _u8L("Object"), "menu_split_parts", [](const std::string&) {
|
||||
add_with_icon("obj_split_parts", L("Split to Parts"), L("Object"), "menu_split_parts", [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return p->can_split_to_volumes(); }, [](Plater* p) { p->split_volume(); });
|
||||
});
|
||||
add("obj_center", _u8L("Center Selected on Plate"), _u8L("Object"), [](const std::string&) {
|
||||
add("obj_center", L("Center Selected on Plate"), L("Object"), [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return !p->is_selection_empty(); }, [](Plater* p) { p->center_selection(); });
|
||||
});
|
||||
add_with_icon("obj_drop", _u8L("Drop to Bed"), _u8L("Object"), "toolbar_flatten", [](const std::string&) {
|
||||
add_with_icon("obj_drop", L("Drop to Bed"), L("Object"), "toolbar_flatten", [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return !p->is_selection_empty(); }, [](Plater* p) { p->drop_selection(); });
|
||||
});
|
||||
add("obj_fit_volume", _u8L("Scale to Fit Print Volume"), _u8L("Object"), [](const std::string&) {
|
||||
add("obj_fit_volume", L("Scale to Fit Print Volume"), L("Object"), [](const std::string&) {
|
||||
return object_op(
|
||||
wxGetApp().plater(), [](Plater* p) { return p->can_scale_to_print_volume(); },
|
||||
[](Plater* p) { p->scale_selection_to_fit_print_volume(); });
|
||||
});
|
||||
add_with_icon("obj_instances_up", _u8L("Increase Instances"), _u8L("Object"), "instance_add", [](const std::string&) {
|
||||
add_with_icon("obj_instances_up", L("Increase Instances"), L("Object"), "instance_add", [](const std::string&) {
|
||||
return object_op(
|
||||
wxGetApp().plater(), [](Plater* p) { return p->can_increase_instances(); }, [](Plater* p) { p->increase_instances(); });
|
||||
});
|
||||
add_with_icon("obj_instances_down", _u8L("Decrease Instances"), _u8L("Object"), "instance_remove", [](const std::string&) {
|
||||
add_with_icon("obj_instances_down", L("Decrease Instances"), L("Object"), "instance_remove", [](const std::string&) {
|
||||
return object_op(
|
||||
wxGetApp().plater(), [](Plater* p) { return p->can_decrease_instances(); }, [](Plater* p) { p->decrease_instances(); });
|
||||
});
|
||||
add_with_icon("obj_arrange", _u8L("Auto-Arrange"), _u8L("Object"), "toolbar_arrange", [](const std::string&) {
|
||||
add_with_icon("obj_arrange", L("Auto-Arrange"), L("Object"), "toolbar_arrange", [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return p->can_arrange(); }, [](Plater* p) { p->arrange(); });
|
||||
});
|
||||
add_with_icon("obj_orient", _u8L("Auto-Orient"), _u8L("Object"), "toolbar_orient", [](const std::string&) {
|
||||
add_with_icon("obj_orient", L("Auto-Orient"), L("Object"), "toolbar_orient", [](const std::string&) {
|
||||
return object_op(wxGetApp().plater(), [](Plater* p) { return p->can_arrange(); }, [](Plater* p) { p->orient(); });
|
||||
});
|
||||
|
||||
// ---- Add Primitive ---- (the Add > Add Primitive submenu; creates a new object)
|
||||
auto add_primitive = [&](std::string key, std::string title, std::string icon, const char* type_name) {
|
||||
add_with_icon(std::move(key), std::move(title), _u8L("Add Primitive"), std::move(icon), [type_name](const std::string&) {
|
||||
add_with_icon(std::move(key), std::move(title), L("Add Primitive"), std::move(icon), [type_name](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (plater) {
|
||||
ensure_3d_view(plater);
|
||||
@@ -394,13 +399,13 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
};
|
||||
add_primitive("add_primitive_cube", _u8L("Cube"), "menu_obj_cube", "Cube");
|
||||
add_primitive("add_primitive_cylinder", _u8L("Cylinder"), "menu_obj_cylinder", "Cylinder");
|
||||
add_primitive("add_primitive_sphere", _u8L("Sphere"), "menu_obj_sphere", "Sphere");
|
||||
add_primitive("add_primitive_cone", _u8L("Cone"), "menu_obj_cone", "Cone");
|
||||
add_primitive("add_primitive_disc", _u8L("Disc"), "menu_obj_disc", "Disc");
|
||||
add_primitive("add_primitive_torus", _u8L("Torus"), "menu_obj_torus", "Torus");
|
||||
add_with_icon("add_primitive_text", _u8L("Text"), _u8L("Add Primitive"), "menu_obj_text", [](const std::string&) {
|
||||
add_primitive("add_primitive_cube", L("Cube"), "menu_obj_cube", "Cube");
|
||||
add_primitive("add_primitive_cylinder", L("Cylinder"), "menu_obj_cylinder", "Cylinder");
|
||||
add_primitive("add_primitive_sphere", L("Sphere"), "menu_obj_sphere", "Sphere");
|
||||
add_primitive("add_primitive_cone", L("Cone"), "menu_obj_cone", "Cone");
|
||||
add_primitive("add_primitive_disc", L("Disc"), "menu_obj_disc", "Disc");
|
||||
add_primitive("add_primitive_torus", L("Torus"), "menu_obj_torus", "Torus");
|
||||
add_with_icon("add_primitive_text", L("Text"), L("Add Primitive"), "menu_obj_text", [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (plater) {
|
||||
ensure_3d_view(plater);
|
||||
@@ -410,7 +415,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
}
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("add_primitive_svg", _u8L("SVG"), _u8L("Add Primitive"), "menu_obj_svg", [](const std::string&) {
|
||||
add_with_icon("add_primitive_svg", L("SVG"), L("Add Primitive"), "menu_obj_svg", [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (plater) {
|
||||
ensure_3d_view(plater);
|
||||
@@ -424,7 +429,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
// ---- Add Handy models ---- (the Add > Add Handy models submenu)
|
||||
const std::vector<MenuFactory::HandyModel>& handy = MenuFactory::handy_models();
|
||||
for (std::size_t i = 0; i < handy.size(); ++i) {
|
||||
add("add_handy_" + std::string(handy[i].key), Slic3r::GUI::I18N::translate_utf8(handy[i].label), _u8L("Add Handy models"),
|
||||
add("add_handy_" + std::string(handy[i].key), handy[i].label, L("Add Handy models"),
|
||||
[i](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
ensure_3d_view(plater);
|
||||
@@ -434,7 +439,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
}
|
||||
|
||||
// ---- Plate ----
|
||||
add_with_icon("plate_add", _u8L("Add Plate"), _u8L("Plate"), "toolbar_add_plate", [](const std::string&) {
|
||||
add_with_icon("plate_add", L("Add Plate"), L("Plate"), "toolbar_add_plate", [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (!is_fff_plater(plater))
|
||||
return plate_unavailable();
|
||||
@@ -443,7 +448,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
plater->add_plate();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("plate_duplicate", _u8L("Duplicate Plate"), _u8L("Plate"), "menu_copy", [](const std::string&) {
|
||||
add_with_icon("plate_duplicate", L("Duplicate Plate"), L("Plate"), "menu_copy", [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (!is_fff_plater(plater))
|
||||
return plate_unavailable();
|
||||
@@ -452,7 +457,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
plater->duplicate_plate();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("plate_delete", _u8L("Delete Plate"), _u8L("Plate"), "delete", [](const std::string&) {
|
||||
add_with_icon("plate_delete", L("Delete Plate"), L("Plate"), "delete", [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (!is_fff_plater(plater))
|
||||
return plate_unavailable();
|
||||
@@ -461,7 +466,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
plater->delete_plate();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("plate_rename", _u8L("Rename Plate"), _u8L("Plate"), "plate_name_edit", [](const std::string&) {
|
||||
add_with_icon("plate_rename", L("Rename Plate"), L("Plate"), "plate_name_edit", [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (!is_fff_plater(plater))
|
||||
return plate_unavailable();
|
||||
@@ -472,7 +477,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
curr->set_plate_name(dlg.get_plate_name().ToUTF8().data());
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("plate_toggle_lock", _u8L("Toggle Plate Lock"), _u8L("Plate"), "lock_normal", [](const std::string&) {
|
||||
add_with_icon("plate_toggle_lock", L("Toggle Plate Lock"), L("Plate"), "lock_normal", [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (!is_fff_plater(plater))
|
||||
return plate_unavailable();
|
||||
@@ -482,7 +487,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
plates.lock_plate(index, !plates.is_locked(index));
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("plate_goto", _u8L("Go to Plate"), _u8L("Plate"), "go_next_plate", [](const std::string& param) {
|
||||
add_with_icon("plate_goto", L("Go to Plate"), L("Plate"), "go_next_plate", [](const std::string& param) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
if (!is_fff_plater(plater))
|
||||
return plate_unavailable();
|
||||
@@ -500,7 +505,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
});
|
||||
|
||||
// ---- Printer / device connection ----
|
||||
add_with_icon("sync_ams", _u8L("Synchronize Filament List from AMS"), _u8L("Printer"), "ams_fila_sync", [](const std::string&) {
|
||||
add_with_icon("sync_ams", L("Synchronize Filament List from AMS"), L("Printer"), "ams_fila_sync", [](const std::string&) {
|
||||
Plater* plater = wxGetApp().plater();
|
||||
DeviceManager* dev = wxGetApp().getDeviceManager();
|
||||
if (dev && dev->get_selected_machine() && plater) {
|
||||
@@ -511,11 +516,11 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
});
|
||||
|
||||
// ---- Presets / cloud ----
|
||||
add_with_icon("preset_bundle", _u8L("Open Preset Bundle"), _u8L("Presets"), "menu_edit_preset", [](const std::string&) {
|
||||
add_with_icon("preset_bundle", L("Open Preset Bundle"), L("Presets"), "menu_edit_preset", [](const std::string&) {
|
||||
wxGetApp().open_presetbundledialog();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("sync_presets", _u8L("Sync Presets"), _u8L("Presets"), "printer_sync_ok", [](const std::string&) {
|
||||
add_with_icon("sync_presets", L("Sync Presets"), L("Presets"), "printer_sync_ok", [](const std::string&) {
|
||||
if (!wxGetApp().is_user_login())
|
||||
return AppActionRunResult{AppActionRunResult::Level::Info, _L("Sign in to sync presets.")};
|
||||
wxGetApp().restart_sync_user_preset();
|
||||
@@ -523,7 +528,7 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
});
|
||||
|
||||
// ---- Import ----
|
||||
add_with_icon("import_file", _u8L("Import 3MF/STL/STEP/SVG/OBJ/AMF"), _u8L("Import"), "menu_open", [](const std::string&) {
|
||||
add_with_icon("import_file", L("Import 3MF/STL/STEP/SVG/OBJ/AMF"), L("Import"), "menu_open", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater()) {
|
||||
#ifdef __APPLE__
|
||||
plater->add_model();
|
||||
@@ -533,71 +538,71 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
}
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("import_zip_archive", _u8L("Import ZIP Archive"), _u8L("Import"), "menu_open", [](const std::string&) {
|
||||
add_with_icon("import_zip_archive", L("Import ZIP Archive"), L("Import"), "menu_open", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->import_zip_archive();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("import_configs", _u8L("Import Configs"), _u8L("Import"), "menu_open", [](const std::string&) {
|
||||
add_with_icon("import_configs", L("Import Configs"), L("Import"), "menu_open", [](const std::string&) {
|
||||
if (MainFrame* mf = wxGetApp().mainframe)
|
||||
mf->load_config_file();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
|
||||
// ---- Export extras ----
|
||||
add_with_icon("export_stl_multi", _u8L("Export All Objects as STLs"), _u8L("Export"), "save", [](const std::string&) {
|
||||
add_with_icon("export_stl_multi", L("Export All Objects as STLs"), L("Export"), "save", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->export_stl(false, false, true);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("export_drc_single", _u8L("Export All Objects as DRC (one file)"), _u8L("Export"), "save", [](const std::string&) {
|
||||
add_with_icon("export_drc_single", L("Export All Objects as DRC (one file)"), L("Export"), "save", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->export_stl(false, false, false, FT_DRC);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("export_drc_multi", _u8L("Export All Objects as DRCs"), _u8L("Export"), "save", [](const std::string&) {
|
||||
add_with_icon("export_drc_multi", L("Export All Objects as DRCs"), L("Export"), "save", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->export_stl(false, false, true, FT_DRC);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("export_toolpaths_obj", _u8L("Export Toolpaths as OBJ"), _u8L("Export"), "custom-gcode_gcode", [](const std::string&) {
|
||||
add_with_icon("export_toolpaths_obj", L("Export Toolpaths as OBJ"), L("Export"), "custom-gcode_gcode", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater())
|
||||
plater->export_toolpaths_to_obj();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("export_config", _u8L("Export Preset Bundle"), _u8L("Export"), "save", [](const std::string&) {
|
||||
add_with_icon("export_config", L("Export Preset Bundle"), L("Export"), "save", [](const std::string&) {
|
||||
if (MainFrame* mf = wxGetApp().mainframe)
|
||||
mf->export_config();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
|
||||
// ---- Help ---- (mirrors the top-bar Help menu, plus the wiki/YouTube links)
|
||||
add("help_keyboard_shortcuts", _u8L("Keyboard Shortcuts"), _u8L("Help"), [](const std::string&) {
|
||||
add("help_keyboard_shortcuts", L("Keyboard Shortcuts"), L("Help"), [](const std::string&) {
|
||||
wxGetApp().keyboard_shortcuts(ShortcutContext::Global);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("help_setup_wizard", _u8L("Setup Wizard"), _u8L("Help"), [](const std::string&) {
|
||||
add("help_setup_wizard", L("Setup Wizard"), L("Help"), [](const std::string&) {
|
||||
wxGetApp().ShowUserGuide();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("help_open_config_folder", _u8L("Show Configuration Folder"), _u8L("Help"), "open_project", [](const std::string&) {
|
||||
add_with_icon("help_open_config_folder", L("Show Configuration Folder"), L("Help"), "open_project", [](const std::string&) {
|
||||
Slic3r::GUI::desktop_open_datadir_folder();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("help_troubleshoot", _u8L("Troubleshoot Center"), _u8L("Help"), [](const std::string&) {
|
||||
add("help_troubleshoot", L("Troubleshoot Center"), L("Help"), [](const std::string&) {
|
||||
wxGetApp().troubleshoot();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("help_network_test", _u8L("Open Network Test"), _u8L("Help"), [](const std::string&) {
|
||||
add("help_network_test", L("Open Network Test"), L("Help"), [](const std::string&) {
|
||||
NetworkTestDialog dlg(wxGetApp().mainframe);
|
||||
dlg.ShowModal();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("help_benchmark_3d_scene", _u8L("Benchmark 3D Scene"), _u8L("Help"), [](const std::string&) {
|
||||
add("help_benchmark_3d_scene", L("Benchmark 3D Scene"), L("Help"), [](const std::string&) {
|
||||
run_scene_benchmark();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("help_tip_of_the_day", _u8L("Show Tip of the Day"), _u8L("Help"), "info", [](const std::string&) {
|
||||
add_with_icon("help_tip_of_the_day", L("Show Tip of the Day"), L("Help"), "info", [](const std::string&) {
|
||||
if (Plater* plater = wxGetApp().plater()) {
|
||||
plater->get_dailytips()->open();
|
||||
if (GLCanvas3D* canvas = plater->get_current_canvas3D())
|
||||
@@ -605,37 +610,37 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
}
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("help_check_updates", _u8L("Check for Updates"), _u8L("Help"), "refresh", [](const std::string&) {
|
||||
add_with_icon("help_check_updates", L("Check for Updates"), L("Help"), "refresh", [](const std::string&) {
|
||||
wxGetApp().check_new_version_sf(true, 1);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("help_about", _u8L("About OrcaSlicer"), _u8L("Help"), "OrcaSlicer_gradient_circle", [](const std::string&) {
|
||||
add_with_icon("help_about", L("About OrcaSlicer"), L("Help"), "OrcaSlicer_gradient_circle", [](const std::string&) {
|
||||
Slic3r::GUI::about();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add_with_icon("open_wiki", _u8L("Open Wiki"), _u8L("Help"), "link_wiki_img", [](const std::string&) {
|
||||
add_with_icon("open_wiki", L("Open Wiki"), L("Help"), "link_wiki_img", [](const std::string&) {
|
||||
wxLaunchDefaultBrowser("https://www.orcaslicer.com/wiki/", wxBROWSER_NEW_WINDOW);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("open_youtube", _u8L("Open YouTube Channel"), _u8L("Help"), [](const std::string&) {
|
||||
add("open_youtube", L("Open YouTube Channel"), L("Help"), [](const std::string&) {
|
||||
wxLaunchDefaultBrowser("https://www.youtube.com/@OfficialOrcaSlicer/videos", wxBROWSER_NEW_WINDOW);
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
|
||||
// ---- Plugins ----
|
||||
add("open_plugins", _u8L("Open Plugins"), _u8L("Plugins"), [](const std::string&) {
|
||||
add("open_plugins", L("Open Plugins"), L("Plugins"), [](const std::string&) {
|
||||
wxGetApp().open_plugins_dialog();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("refresh_plugins", _u8L("Refresh Plugins"), _u8L("Plugins"), [](const std::string&) {
|
||||
add("refresh_plugins", L("Refresh Plugins"), L("Plugins"), [](const std::string&) {
|
||||
wxGetApp().refresh_plugins();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("install_plugin", _u8L("Install Plugin"), _u8L("Plugins"), [](const std::string&) {
|
||||
add("install_plugin", L("Install Plugin"), L("Plugins"), [](const std::string&) {
|
||||
open_plugin_hub();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
add("install_local_plugin", _u8L("Install Local Plugin"), _u8L("Plugins"), [](const std::string&) {
|
||||
add("install_local_plugin", L("Install Local Plugin"), L("Plugins"), [](const std::string&) {
|
||||
wxGetApp().install_local_plugin();
|
||||
return AppActionRunResult{AppActionRunResult::Level::Success};
|
||||
});
|
||||
@@ -643,24 +648,12 @@ std::vector<NativeCommand> build_command_catalog()
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<NativeCommand>& catalog_storage()
|
||||
{
|
||||
static std::vector<NativeCommand> commands = build_command_catalog();
|
||||
return commands;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const std::vector<NativeCommand>& NativeCommands::catalog()
|
||||
{
|
||||
return catalog_storage();
|
||||
}
|
||||
|
||||
void NativeCommands::rebuild_catalog()
|
||||
{
|
||||
// build_command_catalog() re-runs _u8L under the current locale, so replacing the storage
|
||||
// refreshes every translated title/group after a language switch.
|
||||
catalog_storage() = build_command_catalog();
|
||||
static const std::vector<NativeCommand> commands = build_command_catalog();
|
||||
return commands;
|
||||
}
|
||||
|
||||
std::unique_ptr<AppAction> NativeCommands::make_action(const NativeCommand& command)
|
||||
|
||||
@@ -16,27 +16,25 @@ namespace Slic3r { namespace GUI {
|
||||
struct NativeCommand
|
||||
{
|
||||
std::string key;
|
||||
std::string title;
|
||||
std::string group;
|
||||
std::string title; // untranslated English msgid; make_action() translates it for display
|
||||
std::string group; // likewise
|
||||
std::string input; // "percent"/"tab" or "" for immediate run
|
||||
std::string icon; // SVG base name, or "" to render a blank tile
|
||||
std::function<AppActionRunResult(const std::string& param)> runner;
|
||||
};
|
||||
|
||||
namespace NativeCommands {
|
||||
// The full built-in command catalog. Built on first use and reused; call rebuild_catalog() after a
|
||||
// live UI language switch so the translated titles/groups match the new locale. UI thread only.
|
||||
// The full built-in command catalog. Built on first use and reused; it holds no translated text, so
|
||||
// it stays valid across a UI language switch. UI thread only.
|
||||
const std::vector<NativeCommand>& catalog();
|
||||
|
||||
// Rebuilds the catalog in the current locale. UI thread only.
|
||||
void rebuild_catalog();
|
||||
|
||||
// Dispatches `key` to its runner (unknown keys return a quiet Info). UI thread only.
|
||||
AppActionRunResult run(const std::string& key, const std::string& param = {});
|
||||
|
||||
// Materialises one catalog entry as a runnable AppAction. Keeps the catalog's identity,
|
||||
// presentation and behaviour as the single source of truth; ActionRegistry only stores and
|
||||
// dispatches the result. UI thread only.
|
||||
// Materialises one catalog entry as a runnable AppAction, titled in the current UI language with the
|
||||
// English title/group kept as search aliases. Keeps the catalog's identity, presentation and
|
||||
// behaviour as the single source of truth; ActionRegistry only stores and dispatches the result.
|
||||
// UI thread only.
|
||||
std::unique_ptr<AppAction> make_action(const NativeCommand& command);
|
||||
} // namespace NativeCommands
|
||||
|
||||
|
||||
@@ -275,7 +275,8 @@ void OptionsGroup::append_line(const Line& line)
|
||||
const wxString leaf = (leaf_src == L_CONTEXT("Top", "Layers") || leaf_src == L_CONTEXT("Bottom", "Layers")) ?
|
||||
_L_CONTEXT(leaf_src, "Layers") :
|
||||
_(leaf_src);
|
||||
index.set_line_label(opt.opt_id, type, Search::compose_display_label(line.label, leaf, multi));
|
||||
index.set_line_label(opt.opt_id, type, Search::compose_display_label(line.label, leaf, multi),
|
||||
Search::compose_display_label(line.label_en, from_u8(leaf_src), multi));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,7 +651,7 @@ Line OptionsGroup::create_single_option_line(const Option& option, const std::st
|
||||
{
|
||||
wxString tooltip = _(get_formatted_tooltip_text(option.opt, option.opt_id));
|
||||
|
||||
Line retval{_(option.opt.label), tooltip};
|
||||
Line retval{from_u8(option.opt.label), tooltip};
|
||||
retval.label_path = path;
|
||||
retval.append_option(option);
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ class Line : public UndoValueUIManager
|
||||
bool m_is_separator{ false };
|
||||
public:
|
||||
wxString label;
|
||||
wxString label_en; // untranslated English of `label`, searchable by the Speed Dial in any UI language
|
||||
wxString label_tooltip;
|
||||
std::string label_path;
|
||||
bool undo_to_sys{false}; // BBS: object config
|
||||
@@ -86,12 +87,16 @@ public:
|
||||
void append_widget(const widget_t widget) {
|
||||
m_extra_widgets.push_back(widget);
|
||||
}
|
||||
// `label` and `tooltip` are the untranslated English msgids; they are translated for display.
|
||||
Line(wxString label, wxString tooltip) :
|
||||
label(_(label)), label_tooltip(_(tooltip)) {}
|
||||
label(_(label)), label_en(label), label_tooltip(_(tooltip)) {}
|
||||
Line() : m_is_separator(true) {}
|
||||
|
||||
// `new_label` is the untranslated English msgid (an L("...") string), like the ctor's label:
|
||||
// it is translated for display and kept as label_en.
|
||||
void set_label(const wxString& new_label) {
|
||||
label = new_label;
|
||||
label = _(new_label);
|
||||
label_en = new_label;
|
||||
if (label_widget != nullptr) {
|
||||
label_widget->SetLabel(label + (label.IsEmpty() ? "" : ": "));
|
||||
label_widget->Refresh();
|
||||
|
||||
@@ -63,7 +63,7 @@ static Option make_option(const std::string &key, Preset::Type type, const wxStr
|
||||
GUI::Tab::translate_category(category, type).ToStdWstring(), false, mode, tooltip, gc.path,
|
||||
// The settings page draws Line::label; carrying it lets the Speed Dial name a setting
|
||||
// the way the page does. `label`/`label_local` stay the search-oriented name.
|
||||
into_u8(gc.line_label)};
|
||||
into_u8(gc.line_label), into_u8(gc.line_label_en)};
|
||||
return option;
|
||||
}
|
||||
|
||||
@@ -250,11 +250,13 @@ void SettingsIndex::set_path(const std::string &opt_key, Preset::Type type, cons
|
||||
m_groups_and_categories[get_key(opt_key, type)].path = path;
|
||||
}
|
||||
|
||||
void SettingsIndex::set_line_label(const std::string &opt_key, Preset::Type type, const wxString &label)
|
||||
void SettingsIndex::set_line_label(const std::string &opt_key, Preset::Type type, const wxString &label, const wxString &label_en)
|
||||
{
|
||||
if (label.IsEmpty())
|
||||
return;
|
||||
m_groups_and_categories[get_key(opt_key, type)].line_label = label;
|
||||
GroupAndCategory &gc = m_groups_and_categories[get_key(opt_key, type)];
|
||||
gc.line_label = label;
|
||||
gc.line_label_en = label_en;
|
||||
}
|
||||
|
||||
} // namespace Search
|
||||
|
||||
@@ -28,12 +28,14 @@ struct GroupAndCategory
|
||||
wxString group;
|
||||
wxString category;
|
||||
wxString icon; // icon of the group's own header, or empty
|
||||
wxString line_label; // label the settings row actually draws (Line::label), or empty
|
||||
std::string path; // wiki path (Line::label_path) of the option's line, or empty
|
||||
wxString line_label; // label the settings row actually draws (Line::label), or empty
|
||||
wxString line_label_en; // untranslated English of line_label, or empty
|
||||
std::string path; // wiki path (Line::label_path) of the option's line, or empty
|
||||
};
|
||||
|
||||
// Title for a setting: the row label, qualified with the field leaf when the row packs several
|
||||
// options (e.g. "Cool Plate \u2013 First layer"). Pure; inputs are already localized.
|
||||
// options (e.g. "Cool Plate \u2013 First layer"). Pure; both inputs are in the same language (the
|
||||
// localized title, or its English counterpart).
|
||||
inline wxString compose_display_label(const wxString& line_label, const wxString& leaf_label, bool multi)
|
||||
{
|
||||
if (line_label.empty())
|
||||
@@ -73,6 +75,7 @@ struct Option
|
||||
std::string tooltip; // localized ConfigOptionDef::tooltip, or empty
|
||||
std::string wiki_path; // Line::label_path for the option's row, or empty
|
||||
std::string display_label; // label the settings row draws (localized); empty falls back to label
|
||||
std::string display_label_en; // untranslated English of display_label, or empty
|
||||
|
||||
std::string opt_key() const;
|
||||
};
|
||||
@@ -98,9 +101,9 @@ public:
|
||||
void add_key(const std::string &opt_key, Preset::Type type, const wxString &group, const wxString &category,
|
||||
const wxString &icon = wxEmptyString);
|
||||
void set_path(const std::string &opt_key, Preset::Type type, const std::string &path);
|
||||
// Record the label the option's row draws, so the Speed Dial names a setting like the page
|
||||
// (ConfigOptionDef::label/full_label is a search name, not the row text).
|
||||
void set_line_label(const std::string &opt_key, Preset::Type type, const wxString &label);
|
||||
// Record the label the option's row draws and its untranslated English, so the Speed Dial names a
|
||||
// setting like the page (ConfigOptionDef::label/full_label is a search name, not the row text).
|
||||
void set_line_label(const std::string &opt_key, Preset::Type type, const wxString &label, const wxString &label_en);
|
||||
|
||||
const std::vector<Option> &options() const { return m_options; }
|
||||
const std::vector<Option> &all_options() const { return m_all_modes; }
|
||||
|
||||
@@ -817,23 +817,24 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str
|
||||
// Names of categories is save in English always. We translate them only for UI.
|
||||
// But category "Extruder n" can't be translated regularly (using _()), so
|
||||
// just for this category we should splite the title and translate "Extruder" word separately
|
||||
wxString Tab::translate_category(const wxString& title, Preset::Type preset_type)
|
||||
wxString Tab::translate_category(const wxString& title, Preset::Type preset_type, bool translate)
|
||||
{
|
||||
auto tr = [translate](const wxString& s) { return translate ? _(s) : s; };
|
||||
if (preset_type == Preset::TYPE_PRINTER && title.Contains("Extruder ")) {
|
||||
auto preset = wxGetApp().preset_bundle;
|
||||
if (preset && preset->is_bbl_vendor()) {
|
||||
if (title == "Extruder 1") return _("Left Extruder");
|
||||
if (title == "Extruder 2") return _("Right Extruder");
|
||||
if (title == "Extruder 1") return tr(L("Left Extruder"));
|
||||
if (title == "Extruder 2") return tr(L("Right Extruder"));
|
||||
}
|
||||
return _("Extruder") + title.SubString(8, title.Last());
|
||||
return tr(L("Extruder")) + title.SubString(8, title.Last());
|
||||
}
|
||||
// Orca: one "Extruder" page serves all extruders; name it "Extruders" when there are several.
|
||||
if (preset_type == Preset::TYPE_PRINTER && title == "Extruder") {
|
||||
auto preset = wxGetApp().preset_bundle;
|
||||
if (preset && preset->get_printer_extruder_count() > 1)
|
||||
return _("Extruders");
|
||||
return tr(L("Extruders"));
|
||||
}
|
||||
return _(title);
|
||||
return tr(title);
|
||||
}
|
||||
|
||||
void Tab::OnActivate()
|
||||
@@ -1865,14 +1866,14 @@ Tab::SettingRowState Tab::setting_row_state(const std::string &opt_id) const
|
||||
if (opt.opt_id != opt_id)
|
||||
continue;
|
||||
if (line.toggle_visible) // shown on any owning page is enough
|
||||
return {true, line.label, line.get_options().size() > 1};
|
||||
return {true, line.label, line.label_en, line.get_options().size() > 1};
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Never registered on a page -> visible, but with no row label to contribute.
|
||||
return {!found, wxString(), false};
|
||||
return {!found, wxString(), wxString(), false};
|
||||
}
|
||||
|
||||
// To be called by custom widgets, load a value into a config,
|
||||
|
||||
@@ -405,7 +405,11 @@ public:
|
||||
void on_roll_back_value(const bool to_sys = false);
|
||||
|
||||
PageShp add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false);
|
||||
static wxString translate_category(const wxString& title, Preset::Type preset_type);
|
||||
// The name a category is displayed under. A few printer pages are renamed for display (BBL
|
||||
// "Extruder 1/2" -> "Left/Right Extruder", the shared "Extruder" page -> "Extruders" when there are
|
||||
// several). With `translate` false the same name is returned untranslated, i.e. as an English UI
|
||||
// displays it.
|
||||
static wxString translate_category(const wxString& title, Preset::Type preset_type, bool translate = true);
|
||||
|
||||
virtual void OnActivate();
|
||||
virtual void on_preset_loaded() {}
|
||||
@@ -432,6 +436,8 @@ public:
|
||||
Field* get_field(const t_config_option_key &opt_key, Page** selected_page, int opt_index = -1);
|
||||
void toggle_option(const std::string &opt_key, bool toggle, int opt_index = -1);
|
||||
void toggle_line(const std::string &opt_key, bool toggle, int opt_index = -1); // BBS: hide some line
|
||||
// Renames the row that owns the option. `label` is the untranslated English msgid (an L("...")
|
||||
// string); it is translated for display and kept as the row's English search alias.
|
||||
void set_option_label(const std::string &opt_key, const wxString &label, int opt_index = -1);
|
||||
|
||||
// Live state of the settings row that owns an option, read from the built pages.
|
||||
@@ -439,6 +445,7 @@ public:
|
||||
{
|
||||
bool visible{true}; // false when ConfigManipulation hides the row
|
||||
wxString label; // Line::label the row draws (may change at runtime)
|
||||
wxString label_en; // Line::label_en, the untranslated English of label
|
||||
bool multi{false}; // row packs several options, so label is precomposed
|
||||
};
|
||||
SettingRowState setting_row_state(const std::string &opt_id) const;
|
||||
|
||||
Reference in New Issue
Block a user