mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-18 14:21:12 -06:00
Port EditGCodeDialog from PrusaSlicer (#3417)
This is a port of the EditGCodeDialog from PrusaSlicer 2.7.x. There were a few changes made to make it a bit more functional. Also, it isn't quite fully complete, but it should be in a very usable state. General Changes: - Implement UndoValueUIManager and EditValueUI in Field - Implement EditGCodeDialog and add buttons to the tabs - Other minor changes to accommodate the new classes Differences from PrusaSlicer's Implementation: - backported to wxWidgets 3.1.5 (reverse commit8770c4b7
after updating to 3.2.x) - icons have been updated to use Orca colors - improve the report that tells you if certain placeholders have not been defined properly for the dialog. It now shows all issues at once rather than having to fix then recompile to see the next issue. - allow the use of the cmake option `ORCA_CHECK_GCODE_PLACEHOLDERS` to toggle the above report since our workflow rarely uses debug mode. - if a custom gcode value is not set when checking gcode placeholders, a testing value is set. Custom gcode is not parsed if it is empty, and the only way to check if the placeholders are all defined is by running the placeholder operation on the custom gcode. - some calls to `print.config()` in Gcode.cpp were changed to `m_config` to support the above testing values feature (only m_config is modified with the placeholders and `print.config()` would return an empty string) - a macro has been added to quickly add a definition to SlicingStatesConfigDefs with less boiler plate (it could technically be used for any ConfigOptionDef, but that would hurt interoperability with PS. I tried to not use the macro for too many PS defined definitions.) - the presets are now also categorized by the page they are on in their tab <table> <tr> <td>Prusa <td>Orca <tr> <td> <img src="27cb4f48
-d225-4563-9aeb-b2b461f8bff5" /> <td> <img src="4fcd8cde
-2427-4d1a-a0ed-1738b570b919" /> </table> TODO: - [x] Make sure all linux fixes have been applied - [x] Finish adding "universal" gcode options - [x] add search function to dataview (maybe?) - [x] determine if any options are being left out of the preset categories by getting options from Tab rather than Presets. If so, consider adding outside of the groupings
This commit is contained in:
commit
5ff00fb48c
33 changed files with 2155 additions and 122 deletions
|
@ -212,6 +212,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/PresetComboBoxes.cpp
|
||||
GUI/BitmapComboBox.hpp
|
||||
GUI/BitmapComboBox.cpp
|
||||
GUI/EditGCodeDialog.hpp
|
||||
GUI/EditGCodeDialog.cpp
|
||||
GUI/SavePresetDialog.hpp
|
||||
GUI/SavePresetDialog.cpp
|
||||
GUI/GUI_Colors.hpp
|
||||
|
|
976
src/slic3r/GUI/EditGCodeDialog.cpp
Normal file
976
src/slic3r/GUI/EditGCodeDialog.cpp
Normal file
|
@ -0,0 +1,976 @@
|
|||
#include "EditGCodeDialog.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "format.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include "ExtraRenderers.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "Plater.hpp"
|
||||
|
||||
#include "libslic3r/PlaceholderParser.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
|
||||
#define BTN_GAP FromDIP(20)
|
||||
#define BTN_SIZE wxSize(FromDIP(58), FromDIP(24))
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
//------------------------------------------
|
||||
// EditGCodeDialog
|
||||
//------------------------------------------
|
||||
|
||||
EditGCodeDialog::EditGCodeDialog(wxWindow* parent, const std::string& key, const std::string& value) :
|
||||
DPIDialog(parent, wxID_ANY, format_wxstr(_L("Edit Custom G-code (%1%)"), key), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/)
|
||||
{
|
||||
SetFont(wxGetApp().normal_font());
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
wxGetApp().UpdateDarkUI(this);
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
|
||||
int border = 10;
|
||||
int em = em_unit();
|
||||
|
||||
wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _L("Built-in placeholders (Double click item to add to G-code)") + ":");
|
||||
|
||||
auto* grid_sizer = new wxFlexGridSizer(1, 3, 5, 15);
|
||||
grid_sizer->SetFlexibleDirection(wxBOTH);
|
||||
|
||||
auto* param_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_search_bar = new wxSearchCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
|
||||
m_search_bar->ShowSearchButton(true);
|
||||
m_search_bar->ShowCancelButton(true);
|
||||
m_search_bar->SetDescriptiveText(_L("Search gcode placeholders"));
|
||||
m_search_bar->SetForegroundColour(*wxBLACK);
|
||||
wxGetApp().UpdateDarkUI(m_search_bar);
|
||||
|
||||
m_search_bar->Bind(wxEVT_SET_FOCUS, [this](wxFocusEvent&) {
|
||||
// this->on_search_update();
|
||||
});
|
||||
m_search_bar->Bind(wxEVT_COMMAND_TEXT_UPDATED, [this](wxCommandEvent&) {
|
||||
this->on_search_update();
|
||||
});
|
||||
|
||||
param_sizer->Add(m_search_bar, 0, wxEXPAND | wxALL, border);
|
||||
|
||||
m_params_list = new ParamsViewCtrl(this, wxSize(em * 45, em * 70));
|
||||
m_params_list->SetFont(wxGetApp().code_font());
|
||||
wxGetApp().UpdateDarkUI(m_params_list);
|
||||
param_sizer->Add(m_params_list, 0, wxEXPAND | wxALL, border);
|
||||
|
||||
m_add_btn = new ScalableButton(this, wxID_ANY, "add_copies");
|
||||
m_add_btn->SetToolTip(_L("Add selected placeholder to G-code"));
|
||||
|
||||
m_gcode_editor = new wxTextCtrl(this, wxID_ANY, value, wxDefaultPosition, wxSize(em * 75, em * 70), wxTE_MULTILINE
|
||||
#ifdef _WIN32
|
||||
| wxBORDER_SIMPLE
|
||||
#endif
|
||||
);
|
||||
m_gcode_editor->SetFont(wxGetApp().code_font());
|
||||
m_gcode_editor->SetInsertionPointEnd();
|
||||
wxGetApp().UpdateDarkUI(m_gcode_editor);
|
||||
|
||||
grid_sizer->Add(param_sizer, 1, wxEXPAND);
|
||||
grid_sizer->Add(m_add_btn, 0, wxTOP, m_params_list->GetSize().y/2);
|
||||
grid_sizer->Add(m_gcode_editor, 2, wxEXPAND);
|
||||
|
||||
grid_sizer->AddGrowableRow(0, 1);
|
||||
grid_sizer->AddGrowableCol(0, 1);
|
||||
grid_sizer->AddGrowableCol(2, 1);
|
||||
|
||||
m_param_label = new wxStaticText(this, wxID_ANY, _L("Select placeholder"));
|
||||
m_param_label->SetFont(wxGetApp().bold_font());
|
||||
|
||||
m_param_description = new wxStaticText(this, wxID_ANY, wxEmptyString);
|
||||
|
||||
//Orca: use custom buttons
|
||||
auto btn_sizer = create_btn_sizer(wxOK | wxCANCEL);
|
||||
for(auto btn : m_button_list)
|
||||
wxGetApp().UpdateDarkUI(btn.second);
|
||||
|
||||
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
topSizer->Add(label_top , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border);
|
||||
topSizer->Add(grid_sizer , 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border);
|
||||
topSizer->Add(m_param_label , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border);
|
||||
topSizer->Add(m_param_description , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border);
|
||||
topSizer->Add(btn_sizer , 0, wxEXPAND | wxALL, border);
|
||||
|
||||
SetSizer(topSizer);
|
||||
topSizer->SetSizeHints(this);
|
||||
|
||||
this->Fit();
|
||||
this->Layout();
|
||||
|
||||
this->CenterOnScreen();
|
||||
|
||||
init_params_list(key);
|
||||
bind_list_and_button();
|
||||
}
|
||||
|
||||
EditGCodeDialog::~EditGCodeDialog()
|
||||
{
|
||||
// To avoid redundant process of wxEVT_DATAVIEW_SELECTION_CHANGED after dialog distroing (on Linux)
|
||||
// unbind this event from params_list
|
||||
m_params_list->Unbind(wxEVT_DATAVIEW_SELECTION_CHANGED, &EditGCodeDialog::selection_changed, this);
|
||||
}
|
||||
|
||||
std::string EditGCodeDialog::get_edited_gcode() const
|
||||
{
|
||||
return into_u8(m_gcode_editor->GetValue());
|
||||
}
|
||||
|
||||
void EditGCodeDialog::on_search_update()
|
||||
{
|
||||
wxString search_text = m_search_bar->GetValue().Lower();
|
||||
if (search_text.empty())
|
||||
m_params_list->model->FinishSearch();
|
||||
else
|
||||
m_params_list->model->RefreshSearch(search_text);
|
||||
}
|
||||
|
||||
static ParamType get_type(const std::string& opt_key, const ConfigOptionDef& opt_def)
|
||||
{
|
||||
return opt_def.is_scalar() ? ParamType::Scalar : ParamType::Vector;
|
||||
}
|
||||
|
||||
void EditGCodeDialog::init_params_list(const std::string& custom_gcode_name)
|
||||
{
|
||||
const auto& custom_gcode_placeholders = custom_gcode_specific_placeholders();
|
||||
const auto& specific_params = custom_gcode_placeholders.count(custom_gcode_name) > 0 ?
|
||||
custom_gcode_placeholders.at(custom_gcode_name) : t_config_option_keys({});
|
||||
|
||||
// Add slicing states placeholders
|
||||
|
||||
wxDataViewItem slicing_state = m_params_list->AppendGroup(_L("[Global] Slicing State"), "custom-gcode_slicing-state_global");
|
||||
if (!cgp_ro_slicing_states_config_def.empty()) {
|
||||
wxDataViewItem read_only = m_params_list->AppendSubGroup(slicing_state, _L("Read Only"), "lock_closed");
|
||||
for (const auto& [opt_key, def]: cgp_ro_slicing_states_config_def.options)
|
||||
m_params_list->AppendParam(read_only, get_type(opt_key, def), opt_key);
|
||||
}
|
||||
|
||||
if (!cgp_rw_slicing_states_config_def.empty()) {
|
||||
wxDataViewItem read_write = m_params_list->AppendSubGroup(slicing_state, _L("Read Write"), "lock_open");
|
||||
for (const auto& [opt_key, def] : cgp_rw_slicing_states_config_def.options)
|
||||
m_params_list->AppendParam(read_write, get_type(opt_key, def), opt_key);
|
||||
}
|
||||
|
||||
// add other universal params, which are related to slicing state
|
||||
if (!cgp_other_slicing_states_config_def.empty()) {
|
||||
slicing_state = m_params_list->AppendGroup(_L("Slicing State"), "custom-gcode_slicing-state");
|
||||
for (const auto& [opt_key, def] : cgp_other_slicing_states_config_def.options)
|
||||
m_params_list->AppendParam(slicing_state, get_type(opt_key, def), opt_key);
|
||||
}
|
||||
|
||||
// Add universal placeholders
|
||||
|
||||
{
|
||||
// Add print statistics subgroup
|
||||
|
||||
if (!cgp_print_statistics_config_def.empty()) {
|
||||
wxDataViewItem statistics = m_params_list->AppendGroup(_L("Print Statistics"), "custom-gcode_stats");
|
||||
for (const auto& [opt_key, def] : cgp_print_statistics_config_def.options)
|
||||
m_params_list->AppendParam(statistics, get_type(opt_key, def), opt_key);
|
||||
}
|
||||
|
||||
// Add objects info subgroup
|
||||
|
||||
if (!cgp_objects_info_config_def.empty()) {
|
||||
wxDataViewItem objects_info = m_params_list->AppendGroup(_L("Objects Info"), "custom-gcode_object-info");
|
||||
for (const auto& [opt_key, def] : cgp_objects_info_config_def.options)
|
||||
m_params_list->AppendParam(objects_info, get_type(opt_key, def), opt_key);
|
||||
}
|
||||
|
||||
// Add dimensions subgroup
|
||||
|
||||
if (!cgp_dimensions_config_def.empty()) {
|
||||
wxDataViewItem dimensions = m_params_list->AppendGroup(_L("Dimensions"), "custom-gcode_measure");
|
||||
for (const auto& [opt_key, def] : cgp_dimensions_config_def.options)
|
||||
m_params_list->AppendParam(dimensions, get_type(opt_key, def), opt_key);
|
||||
}
|
||||
|
||||
// Add temperature subgroup
|
||||
|
||||
if (!cgp_temperatures_config_def.empty()) {
|
||||
wxDataViewItem temperatures = m_params_list->AppendGroup(_L("Temperatures"), "custom-gcode_temperature");
|
||||
for (const auto& [opt_key, def] : cgp_temperatures_config_def.options)
|
||||
m_params_list->AppendParam(temperatures, get_type(opt_key, def), opt_key);
|
||||
}
|
||||
|
||||
// Add timestamp subgroup
|
||||
|
||||
if (!cgp_timestamps_config_def.empty()) {
|
||||
wxDataViewItem dimensions = m_params_list->AppendGroup(_L("Timestamps"), "print-time");
|
||||
for (const auto& [opt_key, def] : cgp_timestamps_config_def.options)
|
||||
m_params_list->AppendParam(dimensions, get_type(opt_key, def), opt_key);
|
||||
}
|
||||
}
|
||||
|
||||
// Add specific placeholders
|
||||
|
||||
if (!specific_params.empty()) {
|
||||
wxDataViewItem group = m_params_list->AppendGroup(format_wxstr(_L("Specific for %1%"), custom_gcode_name), "custom-gcode_gcode");
|
||||
for (const auto& opt_key : specific_params)
|
||||
if (auto def = custom_gcode_specific_config_def.get(opt_key); def && def->type != coNone) {
|
||||
m_params_list->AppendParam(group, get_type(opt_key, *def), opt_key);
|
||||
}
|
||||
m_params_list->Expand(group);
|
||||
}
|
||||
|
||||
// Add placeholders from presets
|
||||
|
||||
wxDataViewItem presets = add_presets_placeholders();
|
||||
// add other params which are related to presets
|
||||
if (!cgp_other_presets_config_def.empty())
|
||||
for (const auto& [opt_key, def] : cgp_other_presets_config_def.options)
|
||||
m_params_list->AppendParam(presets, get_type(opt_key, def), opt_key);
|
||||
}
|
||||
|
||||
wxDataViewItem EditGCodeDialog::add_presets_placeholders()
|
||||
{
|
||||
auto get_set_from_vec = [](const std::vector<std::string>&vec) {
|
||||
return std::set(vec.begin(), vec.end());
|
||||
};
|
||||
|
||||
const bool is_fff = wxGetApp().plater()->printer_technology() == ptFFF;
|
||||
const std::set<std::string> print_options = get_set_from_vec(is_fff ? Preset::print_options() : Preset::sla_print_options());
|
||||
const std::set<std::string> material_options = get_set_from_vec(is_fff ? Preset::filament_options() : Preset::sla_material_options());
|
||||
const std::set<std::string> printer_options = get_set_from_vec(is_fff ? Preset::printer_options() : Preset::sla_printer_options());
|
||||
const auto& full_config = wxGetApp().preset_bundle->full_config();
|
||||
const auto& tab_list = wxGetApp().tabs_list;
|
||||
|
||||
Tab* tab_print;
|
||||
Tab* tab_filament;
|
||||
Tab* tab_printer;
|
||||
for (const auto tab : tab_list) {
|
||||
if (tab->m_type == Preset::TYPE_PRINT)
|
||||
tab_print = tab;
|
||||
else if (tab->m_type == Preset::TYPE_FILAMENT)
|
||||
tab_filament = tab;
|
||||
else if (tab->m_type == Preset::TYPE_PRINTER)
|
||||
tab_printer = tab;
|
||||
}
|
||||
|
||||
|
||||
// Orca: create subgroups from the pages of the tabs
|
||||
auto init_from_tab = [this, full_config](wxDataViewItem parent, Tab* tab, const set<string>& preset_keys){
|
||||
set extra_keys(preset_keys);
|
||||
for (const auto& page : tab->m_pages) {
|
||||
wxDataViewItem subgroup = m_params_list->AppendSubGroup(parent, page->title(), "empty");
|
||||
std::set<std::string> opt_keys;
|
||||
for (const auto& optgroup : page->m_optgroups)
|
||||
for (const auto& opt : optgroup->opt_map())
|
||||
opt_keys.emplace(opt.first);
|
||||
|
||||
for (const auto& opt_key : opt_keys)
|
||||
if (const ConfigOption* optptr = full_config.optptr(opt_key)) {
|
||||
extra_keys.erase(opt_key);
|
||||
m_params_list->AppendParam(subgroup, optptr->is_scalar() ? ParamType::Scalar : ParamType::Vector, opt_key);
|
||||
}
|
||||
}
|
||||
for (auto opt_key : extra_keys)
|
||||
if (const ConfigOption* optptr = full_config.optptr(opt_key))
|
||||
m_params_list->AppendParam(parent, optptr->is_scalar() ? ParamType::Scalar : ParamType::Vector, opt_key);
|
||||
};
|
||||
|
||||
wxDataViewItem group = m_params_list->AppendGroup(_L("Presets"), "cog");
|
||||
|
||||
wxDataViewItem print = m_params_list->AppendSubGroup(group, _L("Print settings"), "cog");
|
||||
init_from_tab(print, tab_print, print_options);
|
||||
|
||||
wxDataViewItem material = m_params_list->AppendSubGroup(group, _(is_fff ? L("Filament settings") : L("SLA Materials settings")), is_fff ? "filament" : "resin");
|
||||
init_from_tab(material, tab_filament, material_options);
|
||||
|
||||
wxDataViewItem printer = m_params_list->AppendSubGroup(group, _L("Printer settings"), is_fff ? "printer" : "sla_printer");
|
||||
init_from_tab(printer, tab_printer, printer_options);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
void EditGCodeDialog::add_selected_value_to_gcode()
|
||||
{
|
||||
const wxString val = m_params_list->GetSelectedValue();
|
||||
if (val.IsEmpty())
|
||||
return;
|
||||
|
||||
m_gcode_editor->WriteText(m_gcode_editor->GetInsertionPoint() == m_gcode_editor->GetLastPosition() ? "\n" + val : val);
|
||||
|
||||
if (val.Last() == ']') {
|
||||
const long new_pos = m_gcode_editor->GetInsertionPoint();
|
||||
if (val[val.Len() - 2] == '[')
|
||||
m_gcode_editor->SetInsertionPoint(new_pos - 1); // set cursor into brackets
|
||||
else
|
||||
m_gcode_editor->SetSelection(new_pos - 17, new_pos - 1); // select "current_extruder"
|
||||
}
|
||||
|
||||
m_gcode_editor->SetFocus();
|
||||
}
|
||||
|
||||
void EditGCodeDialog::selection_changed(wxDataViewEvent& evt)
|
||||
{
|
||||
wxString label;
|
||||
wxString description;
|
||||
|
||||
const std::string opt_key = m_params_list->GetSelectedParamKey();
|
||||
if (!opt_key.empty()) {
|
||||
const ConfigOptionDef* def { nullptr };
|
||||
|
||||
for (const ConfigDef* config: std::initializer_list<const ConfigDef*> {
|
||||
&custom_gcode_specific_config_def,
|
||||
&cgp_ro_slicing_states_config_def,
|
||||
&cgp_rw_slicing_states_config_def,
|
||||
&cgp_other_slicing_states_config_def,
|
||||
&cgp_print_statistics_config_def,
|
||||
&cgp_objects_info_config_def,
|
||||
&cgp_dimensions_config_def,
|
||||
&cgp_temperatures_config_def,
|
||||
&cgp_timestamps_config_def,
|
||||
&cgp_other_presets_config_def
|
||||
}) {
|
||||
if (config->has(opt_key)) {
|
||||
def = config->get(opt_key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Orca: move below checking for def in custom defined gcode placeholders
|
||||
// This allows custom placeholders to override the default ones for this dialog
|
||||
// Override custom def if selection is within the preset category
|
||||
if (!def || m_params_list->GetSelectedTopLevelCategory() == "Presets") {
|
||||
const auto& full_config = wxGetApp().preset_bundle->full_config();
|
||||
if (const ConfigDef* config_def = full_config.def(); config_def && config_def->has(opt_key)) {
|
||||
def = config_def->get(opt_key);
|
||||
}
|
||||
}
|
||||
|
||||
if (def) {
|
||||
const ConfigOptionType scalar_type = def->is_scalar() ? def->type : static_cast<ConfigOptionType>(def->type - coVectorType);
|
||||
wxString type_str = scalar_type == coNone ? "none" :
|
||||
scalar_type == coFloat ? "float" :
|
||||
scalar_type == coInt ? "integer" :
|
||||
scalar_type == coString ? "string" :
|
||||
scalar_type == coPercent ? "percent" :
|
||||
scalar_type == coFloatOrPercent ? "float or percent" :
|
||||
scalar_type == coPoint ? "point" :
|
||||
scalar_type == coBool ? "bool" :
|
||||
scalar_type == coEnum ? "enum" : "undef";
|
||||
if (!def->is_scalar())
|
||||
type_str += "[]";
|
||||
|
||||
label = (!def || (def->full_label.empty() && def->label.empty()) ) ? format_wxstr("%1%\n(%2%)", opt_key, type_str) :
|
||||
(!def->full_label.empty() && !def->label.empty() ) ?
|
||||
format_wxstr("%1% > %2%\n(%3%)", _(def->full_label), _(def->label), type_str) :
|
||||
format_wxstr("%1%\n(%2%)", def->label.empty() ? _(def->full_label) : _(def->label), type_str);
|
||||
|
||||
if (def)
|
||||
description = get_wraped_wxString(_(def->tooltip), 120);
|
||||
}
|
||||
else
|
||||
label = "Undef optptr";
|
||||
}
|
||||
|
||||
m_param_label->SetLabel(label);
|
||||
m_param_description->SetLabel(description);
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
||||
void EditGCodeDialog::bind_list_and_button()
|
||||
{
|
||||
m_params_list->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &EditGCodeDialog::selection_changed, this);
|
||||
|
||||
m_params_list->Bind(wxEVT_DATAVIEW_ITEM_ACTIVATED, [this](wxDataViewEvent& ) {
|
||||
add_selected_value_to_gcode();
|
||||
});
|
||||
|
||||
m_add_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||
add_selected_value_to_gcode();
|
||||
});
|
||||
}
|
||||
|
||||
void EditGCodeDialog::on_dpi_changed(const wxRect&suggested_rect)
|
||||
{
|
||||
const int& em = em_unit();
|
||||
|
||||
//Orca: use custom buttons
|
||||
for (auto button_item : m_button_list)
|
||||
{
|
||||
if (button_item.first == wxOK) {
|
||||
button_item.second->SetMinSize(BTN_SIZE);
|
||||
button_item.second->SetCornerRadius(FromDIP(12));
|
||||
}
|
||||
if (button_item.first == wxCANCEL) {
|
||||
button_item.second->SetMinSize(BTN_SIZE);
|
||||
button_item.second->SetCornerRadius(FromDIP(12));
|
||||
}
|
||||
}
|
||||
|
||||
const wxSize& size = wxSize(45 * em, 35 * em);
|
||||
SetMinSize(size);
|
||||
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void EditGCodeDialog::on_sys_color_changed()
|
||||
{
|
||||
m_add_btn->msw_rescale();
|
||||
}
|
||||
|
||||
//Orca
|
||||
wxBoxSizer* EditGCodeDialog::create_btn_sizer(long flags)
|
||||
{
|
||||
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
btn_sizer->AddStretchSpacer();
|
||||
|
||||
StateColor ok_btn_bg(
|
||||
std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)
|
||||
);
|
||||
|
||||
StateColor ok_btn_bd(
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)
|
||||
);
|
||||
|
||||
StateColor ok_btn_text(
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Normal)
|
||||
);
|
||||
|
||||
StateColor cancel_btn_bg(
|
||||
std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal)
|
||||
);
|
||||
|
||||
StateColor cancel_btn_bd_(
|
||||
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Normal)
|
||||
);
|
||||
|
||||
StateColor cancel_btn_text(
|
||||
std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Normal)
|
||||
);
|
||||
|
||||
|
||||
StateColor calc_btn_bg(
|
||||
std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)
|
||||
);
|
||||
|
||||
StateColor calc_btn_bd(
|
||||
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)
|
||||
);
|
||||
|
||||
StateColor calc_btn_text(
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 254), StateColor::Normal)
|
||||
);
|
||||
|
||||
if (flags & wxOK) {
|
||||
Button* ok_btn = new Button(this, _L("OK"));
|
||||
ok_btn->SetMinSize(BTN_SIZE);
|
||||
ok_btn->SetCornerRadius(FromDIP(12));
|
||||
ok_btn->SetBackgroundColor(ok_btn_bg);
|
||||
ok_btn->SetBorderColor(ok_btn_bd);
|
||||
ok_btn->SetTextColor(ok_btn_text);
|
||||
ok_btn->SetFocus();
|
||||
ok_btn->SetId(wxID_OK);
|
||||
btn_sizer->Add(ok_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, BTN_GAP);
|
||||
m_button_list[wxOK] = ok_btn;
|
||||
}
|
||||
if (flags & wxCANCEL) {
|
||||
Button* cancel_btn = new Button(this, _L("Cancel"));
|
||||
cancel_btn->SetMinSize(BTN_SIZE);
|
||||
cancel_btn->SetCornerRadius(FromDIP(12));
|
||||
cancel_btn->SetBackgroundColor(cancel_btn_bg);
|
||||
cancel_btn->SetBorderColor(cancel_btn_bd_);
|
||||
cancel_btn->SetTextColor(cancel_btn_text);
|
||||
cancel_btn->SetId(wxID_CANCEL);
|
||||
btn_sizer->Add(cancel_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, BTN_GAP / 2);
|
||||
m_button_list[wxCANCEL] = cancel_btn;
|
||||
}
|
||||
|
||||
return btn_sizer;
|
||||
}
|
||||
|
||||
|
||||
const std::map<ParamType, std::string> ParamsInfo {
|
||||
// Type BitmapName
|
||||
{ ParamType::Scalar, "custom-gcode_single" },
|
||||
{ ParamType::Vector, "custom-gcode_vector" },
|
||||
{ ParamType::FilamentVector,"custom-gcode_vector-index" },
|
||||
};
|
||||
|
||||
static void make_bold(wxString& str)
|
||||
{
|
||||
#if defined(SUPPORTS_MARKUP) && !defined(__APPLE__)
|
||||
str = format_wxstr("<b>%1%</b>", str);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void highlight(wxString& str)
|
||||
{
|
||||
#if defined(SUPPORTS_MARKUP) && !defined(__APPLE__)
|
||||
str = format_wxstr("<span bgcolor=\"#009688\">%1%</span>", str);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ParamsModelNode: a node inside ParamsModel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ParamsNode::ParamsNode(const wxString& group_name, const std::string& icon_name, wxDataViewCtrl* ctrl)
|
||||
: icon_name(icon_name)
|
||||
, text(group_name)
|
||||
, m_ctrl(ctrl)
|
||||
, m_bold(true)
|
||||
{
|
||||
}
|
||||
|
||||
ParamsNode::ParamsNode( ParamsNode * parent,
|
||||
const wxString& sub_group_name,
|
||||
const std::string& icon_name,
|
||||
wxDataViewCtrl* ctrl)
|
||||
: m_parent(parent)
|
||||
, icon_name(icon_name)
|
||||
, text(sub_group_name)
|
||||
, m_ctrl(ctrl)
|
||||
, m_bold(true)
|
||||
{
|
||||
}
|
||||
|
||||
ParamsNode::ParamsNode( ParamsNode* parent,
|
||||
ParamType param_type,
|
||||
const std::string& param_key,
|
||||
wxDataViewCtrl* ctrl)
|
||||
: m_parent(parent)
|
||||
, m_param_type(param_type)
|
||||
, m_container(false)
|
||||
, param_key(param_key)
|
||||
, m_ctrl(ctrl)
|
||||
{
|
||||
text = from_u8(param_key);
|
||||
if (param_type == ParamType::Vector)
|
||||
text += "[]";
|
||||
else if (param_type == ParamType::FilamentVector)
|
||||
text += "[current_extruder]";
|
||||
|
||||
icon_name = ParamsInfo.at(param_type);
|
||||
}
|
||||
|
||||
wxString ParamsNode::GetFormattedText()
|
||||
{
|
||||
wxString formatted_text(text);
|
||||
if (m_highlight_index) {
|
||||
wxString substr = formatted_text.substr(m_highlight_index->first, m_highlight_index->second);
|
||||
formatted_text = formatted_text.Remove(m_highlight_index->first, m_highlight_index->second);
|
||||
highlight(substr);
|
||||
formatted_text.insert(m_highlight_index->first, substr);
|
||||
}
|
||||
|
||||
if (m_bold)
|
||||
make_bold(formatted_text);
|
||||
|
||||
return formatted_text;
|
||||
}
|
||||
|
||||
void ParamsNode::StartSearch()
|
||||
{
|
||||
const wxDataViewItem item(this);
|
||||
m_expanded_before_search = m_ctrl->IsExpanded(item);
|
||||
if (!GetChildren().empty())
|
||||
for (const auto& child : GetChildren())
|
||||
child->StartSearch();
|
||||
}
|
||||
|
||||
void ParamsNode::RefreshSearch(const wxString& search_text)
|
||||
{
|
||||
if (!GetChildren().empty())
|
||||
for (auto& child : GetChildren())
|
||||
child->RefreshSearch(search_text);
|
||||
|
||||
if (GetEnabledChildren().empty())
|
||||
if (auto pos = text.find(search_text); IsParamNode() && pos != wxString::npos) {
|
||||
m_highlight_index = make_unique<pair<int, int>>(pos, search_text.Len());
|
||||
Enable();
|
||||
} else {
|
||||
Disable();
|
||||
}
|
||||
else
|
||||
Enable();
|
||||
}
|
||||
|
||||
void ParamsNode::FinishSearch()
|
||||
{
|
||||
Enable();
|
||||
m_highlight_index.reset();
|
||||
const wxDataViewItem item(this);
|
||||
if (!GetChildren().empty())
|
||||
for (const auto& child : GetChildren())
|
||||
child->FinishSearch();
|
||||
m_expanded_before_search ? m_ctrl->Expand(item) : m_ctrl->Collapse(item);
|
||||
}
|
||||
|
||||
wxDataViewItemArray ParamsNode::GetEnabledChildren() {
|
||||
wxDataViewItemArray array;
|
||||
for (const std::unique_ptr<ParamsNode>& child : m_children)
|
||||
if (child->IsEnabled())
|
||||
array.Add(wxDataViewItem(child.get()));
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ParamsModel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ParamsModel::ParamsModel()
|
||||
{
|
||||
}
|
||||
|
||||
wxDataViewItem ParamsModel::AppendGroup(const wxString& group_name,
|
||||
const std::string& icon_name)
|
||||
{
|
||||
m_group_nodes.emplace_back(std::make_unique<ParamsNode>(group_name, icon_name, m_ctrl));
|
||||
|
||||
wxDataViewItem parent(nullptr);
|
||||
wxDataViewItem child((void*)m_group_nodes.back().get());
|
||||
|
||||
ItemAdded(parent, child);
|
||||
m_ctrl->Expand(parent);
|
||||
return child;
|
||||
}
|
||||
|
||||
wxDataViewItem ParamsModel::AppendSubGroup(wxDataViewItem parent,
|
||||
const wxString& sub_group_name,
|
||||
const std::string& icon_name)
|
||||
{
|
||||
ParamsNode* parent_node = static_cast<ParamsNode*>(parent.GetID());
|
||||
if (!parent_node)
|
||||
return wxDataViewItem(0);
|
||||
|
||||
parent_node->Append(std::make_unique<ParamsNode>(parent_node, sub_group_name, icon_name, m_ctrl));
|
||||
const wxDataViewItem sub_group_item((void*)parent_node->GetChildren().back().get());
|
||||
|
||||
ItemAdded(parent, sub_group_item);
|
||||
return sub_group_item;
|
||||
}
|
||||
|
||||
wxDataViewItem ParamsModel::AppendParam(wxDataViewItem parent,
|
||||
ParamType param_type,
|
||||
const std::string& param_key)
|
||||
{
|
||||
ParamsNode* parent_node = static_cast<ParamsNode*>(parent.GetID());
|
||||
if (!parent_node)
|
||||
return wxDataViewItem(0);
|
||||
|
||||
parent_node->Append(std::make_unique<ParamsNode>(parent_node, param_type, param_key, m_ctrl));
|
||||
|
||||
const wxDataViewItem child_item((void*)parent_node->GetChildren().back().get());
|
||||
|
||||
ItemAdded(parent, child_item);
|
||||
return child_item;
|
||||
}
|
||||
|
||||
wxString ParamsModel::GetParamName(wxDataViewItem item)
|
||||
{
|
||||
if (item.IsOk()) {
|
||||
ParamsNode* node = static_cast<ParamsNode*>(item.GetID());
|
||||
if (node->IsParamNode())
|
||||
return node->text;
|
||||
}
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
std::string ParamsModel::GetParamKey(wxDataViewItem item)
|
||||
{
|
||||
if (item.IsOk()) {
|
||||
ParamsNode* node = static_cast<ParamsNode*>(item.GetID());
|
||||
return node->param_key;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string ParamsModel::GetTopLevelCategory(wxDataViewItem item)
|
||||
{
|
||||
if (item.IsOk()) {
|
||||
ParamsNode* node = static_cast<ParamsNode*>(item.GetID());
|
||||
while (!node->IsGroupNode())
|
||||
node = node->GetParent();
|
||||
return node->text.ToStdString();
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void ParamsModel::RefreshSearch(const wxString& search_text)
|
||||
{
|
||||
if (!m_currently_searching) { // if not currently searching, save expansion state for all items
|
||||
for (const auto& node : m_group_nodes)
|
||||
node->StartSearch();
|
||||
m_currently_searching = true;
|
||||
}
|
||||
|
||||
for (const auto& node : m_group_nodes)
|
||||
node->RefreshSearch(search_text); //Enable/Disable node based on search
|
||||
|
||||
Cleared(); //Reload the model into the control
|
||||
|
||||
for (const auto& node : m_group_nodes) // (re)expand all
|
||||
m_ctrl->ExpandChildren(wxDataViewItem(node.get()));
|
||||
}
|
||||
|
||||
void ParamsModel::FinishSearch()
|
||||
{
|
||||
RefreshSearch("");
|
||||
Cleared();
|
||||
if (m_currently_searching) {
|
||||
for (const auto& node : m_group_nodes)
|
||||
node->FinishSearch();
|
||||
m_currently_searching = false;
|
||||
}
|
||||
}
|
||||
|
||||
wxDataViewItem ParamsModel::Delete(const wxDataViewItem& item)
|
||||
{
|
||||
auto ret_item = wxDataViewItem(nullptr);
|
||||
ParamsNode* node = static_cast<ParamsNode*>(item.GetID());
|
||||
if (!node) // happens if item.IsOk()==false
|
||||
return ret_item;
|
||||
|
||||
// first remove the node from the parent's array of children;
|
||||
// NOTE: m_group_nodes is only a vector of _pointers_
|
||||
// thus removing the node from it doesn't result in freeing it
|
||||
ParamsNodePtrArray& children = node->GetChildren();
|
||||
// Delete all children
|
||||
while (!children.empty())
|
||||
Delete(wxDataViewItem(children.back().get()));
|
||||
|
||||
auto node_parent = node->GetParent();
|
||||
|
||||
ParamsNodePtrArray& parents_children = node_parent ? node_parent->GetChildren() : m_group_nodes;
|
||||
auto it = find_if(parents_children.begin(), parents_children.end(),
|
||||
[node](std::unique_ptr<ParamsNode>& child) { return child.get() == node; });
|
||||
assert(it != parents_children.end());
|
||||
it = parents_children.erase(it);
|
||||
|
||||
if (it != parents_children.end())
|
||||
ret_item = wxDataViewItem(it->get());
|
||||
|
||||
wxDataViewItem parent(node_parent);
|
||||
// set m_container to FALSE if parent has no child
|
||||
if (node_parent) {
|
||||
#ifndef __WXGTK__
|
||||
if (node_parent->GetChildren().empty())
|
||||
node_parent->SetContainer(false);
|
||||
#endif //__WXGTK__
|
||||
ret_item = parent;
|
||||
}
|
||||
|
||||
// notify control
|
||||
ItemDeleted(parent, item);
|
||||
return ret_item;
|
||||
}
|
||||
|
||||
void ParamsModel::Clear()
|
||||
{
|
||||
while (!m_group_nodes.empty())
|
||||
Delete(wxDataViewItem(m_group_nodes.back().get()));
|
||||
}
|
||||
|
||||
void ParamsModel::GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const
|
||||
{
|
||||
assert(item.IsOk());
|
||||
|
||||
ParamsNode* node = static_cast<ParamsNode*>(item.GetID());
|
||||
if (col == (unsigned int)0)
|
||||
#ifdef __linux__
|
||||
// variant << wxDataViewIconText(node->GetFormattedText(), get_bmp_bundle(node->icon_name)->GetIconFor(m_ctrl->GetParent())); //TODO: update to bundle with wx update
|
||||
{
|
||||
wxIcon icon;
|
||||
icon.CopyFromBitmap(create_scaled_bitmap(node->icon_name, m_ctrl->GetParent()));
|
||||
variant << wxDataViewIconText(node->GetFormattedText(), icon);
|
||||
}
|
||||
#else
|
||||
// variant << DataViewBitmapText(node->GetFormattedText(), get_bmp_bundle(node->icon_name)->GetBitmapFor(m_ctrl->GetParent())); //TODO: update to bundle with wx update
|
||||
variant << DataViewBitmapText(node->GetFormattedText(), create_scaled_bitmap(node->icon_name, m_ctrl->GetParent()));
|
||||
#endif //__linux__
|
||||
else
|
||||
wxLogError("DiffModel::GetValue: wrong column %d", col);
|
||||
}
|
||||
|
||||
bool ParamsModel::SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col)
|
||||
{
|
||||
assert(item.IsOk());
|
||||
|
||||
ParamsNode* node = static_cast<ParamsNode*>(item.GetID());
|
||||
if (col == (unsigned int)0) {
|
||||
#ifdef __linux__
|
||||
wxDataViewIconText data;
|
||||
data << variant;
|
||||
node->icon = data.GetIcon();
|
||||
#else
|
||||
DataViewBitmapText data;
|
||||
data << variant;
|
||||
node->icon = data.GetBitmap();
|
||||
#endif
|
||||
node->text = data.GetText();
|
||||
return true;
|
||||
}
|
||||
|
||||
wxLogError("DiffModel::SetValue: wrong column");
|
||||
return false;
|
||||
}
|
||||
|
||||
wxDataViewItem ParamsModel::GetParent(const wxDataViewItem&item) const
|
||||
{
|
||||
// the invisible root node has no parent
|
||||
if (!item.IsOk())
|
||||
return wxDataViewItem(nullptr);
|
||||
|
||||
ParamsNode* node = static_cast<ParamsNode*>(item.GetID());
|
||||
|
||||
if (node->IsGroupNode())
|
||||
return wxDataViewItem(nullptr);
|
||||
|
||||
return wxDataViewItem((void*)node->GetParent());
|
||||
}
|
||||
|
||||
bool ParamsModel::IsContainer(const wxDataViewItem& item) const
|
||||
{
|
||||
// the invisble root node can have children
|
||||
if (!item.IsOk())
|
||||
return true;
|
||||
|
||||
ParamsNode* node = static_cast<ParamsNode*>(item.GetID());
|
||||
return node->IsContainer();
|
||||
}
|
||||
unsigned int ParamsModel::GetChildren(const wxDataViewItem& parent, wxDataViewItemArray& array) const
|
||||
{
|
||||
ParamsNode* parent_node = (ParamsNode*)parent.GetID();
|
||||
|
||||
if (parent_node == nullptr) {
|
||||
for (const auto& group : m_group_nodes)
|
||||
if (group->IsEnabled())
|
||||
array.Add(wxDataViewItem((void*)group.get()));
|
||||
}
|
||||
else {
|
||||
const ParamsNodePtrArray& children = parent_node->GetChildren();
|
||||
for (const std::unique_ptr<ParamsNode>& child : children)
|
||||
if (child->IsEnabled())
|
||||
array.Add(wxDataViewItem((void*)child.get()));
|
||||
}
|
||||
|
||||
return array.Count();
|
||||
}
|
||||
unsigned int ParamsModel::GetColumnCount() const { return 1; }
|
||||
wxString ParamsModel::GetColumnType(unsigned int col) const {
|
||||
#ifdef __linux__
|
||||
return wxT("wxDataViewIconText");
|
||||
#else
|
||||
return wxT("DataViewBitmapText");
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ParamsViewCtrl
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ParamsViewCtrl::ParamsViewCtrl(wxWindow *parent, wxSize size)
|
||||
: wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, size, wxDV_SINGLE | wxDV_NO_HEADER// | wxDV_ROW_LINES
|
||||
#ifdef _WIN32
|
||||
| wxBORDER_SIMPLE
|
||||
#endif
|
||||
),
|
||||
m_em_unit(em_unit(parent))
|
||||
{
|
||||
wxGetApp().UpdateDVCDarkUI(this);
|
||||
|
||||
model = new ParamsModel();
|
||||
this->AssociateModel(model);
|
||||
model->SetAssociatedControl(this);
|
||||
|
||||
#ifdef __linux__
|
||||
wxDataViewIconTextRenderer* rd = new wxDataViewIconTextRenderer();
|
||||
#ifdef SUPPORTS_MARKUP
|
||||
rd->EnableMarkup(true);
|
||||
#endif
|
||||
wxDataViewColumn* column = new wxDataViewColumn("", rd, 0, 20 * m_em_unit, wxALIGN_TOP, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_CELL_INERT);
|
||||
#else
|
||||
wxDataViewColumn* column = new wxDataViewColumn("", new BitmapTextRenderer(true, wxDATAVIEW_CELL_INERT), 0, 20 * m_em_unit, wxALIGN_TOP, wxDATAVIEW_COL_RESIZABLE);
|
||||
#endif //__linux__
|
||||
this->AppendColumn(column);
|
||||
this->SetExpanderColumn(column);
|
||||
}
|
||||
|
||||
wxDataViewItem ParamsViewCtrl::AppendGroup(const wxString& group_name, const std::string& icon_name)
|
||||
{
|
||||
return model->AppendGroup(group_name, icon_name);
|
||||
}
|
||||
|
||||
wxDataViewItem ParamsViewCtrl::AppendSubGroup( wxDataViewItem parent,
|
||||
const wxString& sub_group_name,
|
||||
const std::string& icon_name)
|
||||
{
|
||||
return model->AppendSubGroup(parent, sub_group_name, icon_name);
|
||||
}
|
||||
|
||||
wxDataViewItem ParamsViewCtrl::AppendParam( wxDataViewItem parent,
|
||||
ParamType param_type,
|
||||
const std::string& param_key)
|
||||
{
|
||||
return model->AppendParam(parent, param_type, param_key);
|
||||
}
|
||||
|
||||
wxString ParamsViewCtrl::GetValue(wxDataViewItem item)
|
||||
{
|
||||
return model->GetParamName(item);
|
||||
}
|
||||
|
||||
wxString ParamsViewCtrl::GetSelectedValue()
|
||||
{
|
||||
return model->GetParamName(this->GetSelection());
|
||||
}
|
||||
|
||||
std::string ParamsViewCtrl::GetSelectedParamKey()
|
||||
{
|
||||
return model->GetParamKey(this->GetSelection());
|
||||
}
|
||||
|
||||
std::string ParamsViewCtrl::GetSelectedTopLevelCategory()
|
||||
{
|
||||
return model->GetTopLevelCategory(this->GetSelection());
|
||||
}
|
||||
|
||||
void ParamsViewCtrl::CheckAndDeleteIfEmpty(wxDataViewItem item)
|
||||
{
|
||||
wxDataViewItemArray children;
|
||||
model->GetChildren(item, children);
|
||||
if (children.IsEmpty())
|
||||
model->Delete(item);
|
||||
}
|
||||
|
||||
void ParamsViewCtrl::Clear()
|
||||
{
|
||||
model->Clear();
|
||||
}
|
||||
|
||||
void ParamsViewCtrl::Rescale(int em/* = 0*/)
|
||||
{
|
||||
// model->Rescale();
|
||||
Refresh();
|
||||
}
|
||||
}} // namespace Slic3r::GUI
|
269
src/slic3r/GUI/EditGCodeDialog.hpp
Normal file
269
src/slic3r/GUI/EditGCodeDialog.hpp
Normal file
|
@ -0,0 +1,269 @@
|
|||
#ifndef slic3r_EditGCodeDialog_hpp_
|
||||
#define slic3r_EditGCodeDialog_hpp_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <wx/gdicmn.h>
|
||||
#include <slic3r/GUI/Widgets/Button.hpp>
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include <wx/srchctrl.h>
|
||||
|
||||
class wxListBox;
|
||||
class wxTextCtrl;
|
||||
class ScalableButton;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class ParamsViewCtrl;
|
||||
|
||||
//------------------------------------------
|
||||
// EditGCodeDialog
|
||||
//------------------------------------------
|
||||
|
||||
class EditGCodeDialog : public DPIDialog
|
||||
{
|
||||
ParamsViewCtrl* m_params_list {nullptr};
|
||||
ScalableButton* m_add_btn {nullptr};
|
||||
wxTextCtrl* m_gcode_editor {nullptr};
|
||||
wxStaticText* m_param_label {nullptr};
|
||||
wxStaticText* m_param_description {nullptr};
|
||||
wxSearchCtrl* m_search_bar {nullptr};
|
||||
|
||||
ReadOnlySlicingStatesConfigDef cgp_ro_slicing_states_config_def;
|
||||
ReadWriteSlicingStatesConfigDef cgp_rw_slicing_states_config_def;
|
||||
OtherSlicingStatesConfigDef cgp_other_slicing_states_config_def;
|
||||
PrintStatisticsConfigDef cgp_print_statistics_config_def;
|
||||
ObjectsInfoConfigDef cgp_objects_info_config_def;
|
||||
DimensionsConfigDef cgp_dimensions_config_def;
|
||||
TemperaturesConfigDef cgp_temperatures_config_def;
|
||||
TimestampsConfigDef cgp_timestamps_config_def;
|
||||
OtherPresetsConfigDef cgp_other_presets_config_def;
|
||||
|
||||
public:
|
||||
EditGCodeDialog(wxWindow*parent, const std::string&key, const std::string&value);
|
||||
~EditGCodeDialog();
|
||||
|
||||
std::string get_edited_gcode() const;
|
||||
void on_search_update();
|
||||
|
||||
void init_params_list(const std::string& custom_gcode_name);
|
||||
wxDataViewItem add_presets_placeholders();
|
||||
|
||||
void add_selected_value_to_gcode();
|
||||
void bind_list_and_button();
|
||||
|
||||
protected:
|
||||
std::unordered_map<int, Button *> m_button_list;
|
||||
|
||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||
void on_sys_color_changed() override;
|
||||
|
||||
void selection_changed(wxDataViewEvent& evt);
|
||||
|
||||
wxBoxSizer* create_btn_sizer(long flags);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ParamsModelNode: a node inside ParamsModel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class ParamsNode;
|
||||
using ParamsNodePtrArray = std::vector<std::unique_ptr<ParamsNode>>;
|
||||
|
||||
enum class ParamType {
|
||||
Undef,
|
||||
Scalar,
|
||||
Vector,
|
||||
FilamentVector,
|
||||
};
|
||||
|
||||
// On all of 3 different platforms Bitmap+Text icon column looks different
|
||||
// because of Markup text is missed or not implemented.
|
||||
// As a temporary workaround, we will use:
|
||||
// MSW - DataViewBitmapText (our custom renderer wxBitmap + wxString, supported Markup text)
|
||||
// OSX - -//-, but Markup text is not implemented right now
|
||||
// GTK - wxDataViewIconText (wxWidgets for GTK renderer wxIcon + wxString, supported Markup text)
|
||||
class ParamsNode
|
||||
{
|
||||
ParamsNode* m_parent{ nullptr };
|
||||
ParamsNodePtrArray m_children;
|
||||
wxDataViewCtrl* m_ctrl;
|
||||
|
||||
ParamType m_param_type{ ParamType::Undef };
|
||||
|
||||
// TODO/FIXME:
|
||||
// the GTK version of wxDVC (in particular wxDataViewCtrlInternal::ItemAdded)
|
||||
// needs to know in advance if a node is or _will be_ a container.
|
||||
// Thus implementing:
|
||||
// bool IsContainer() const
|
||||
// { return m_children.size()>0; }
|
||||
// doesn't work with wxGTK when DiffModel::AddToClassical is called
|
||||
// AND the classical node was removed (a new node temporary without children
|
||||
// would be added to the control)
|
||||
bool m_container{ true };
|
||||
bool m_expanded_before_search{false};
|
||||
bool m_enabled{true};
|
||||
|
||||
bool m_bold{false};
|
||||
// first is pos, second is length
|
||||
std::unique_ptr<std::pair<int, int>> m_highlight_index{nullptr};
|
||||
|
||||
public:
|
||||
|
||||
#ifdef __linux__
|
||||
wxIcon icon;
|
||||
#else
|
||||
wxBitmap icon;
|
||||
#endif //__linux__
|
||||
std::string icon_name;
|
||||
std::string param_key;
|
||||
wxString text;
|
||||
|
||||
// Group params(root) node
|
||||
ParamsNode(const wxString& group_name, const std::string& icon_name, wxDataViewCtrl* ctrl);
|
||||
|
||||
// sub SlicingState node
|
||||
ParamsNode(ParamsNode* parent,
|
||||
const wxString& sub_group_name,
|
||||
const std::string& icon_name,
|
||||
wxDataViewCtrl* ctrl);
|
||||
|
||||
// parametre node
|
||||
ParamsNode( ParamsNode* parent,
|
||||
ParamType param_type,
|
||||
const std::string& param_key,
|
||||
wxDataViewCtrl* ctrl);
|
||||
|
||||
wxString GetFormattedText();
|
||||
|
||||
bool IsContainer() const { return m_container; }
|
||||
bool IsGroupNode() const { return m_parent == nullptr; }
|
||||
bool IsParamNode() const { return m_param_type != ParamType::Undef; }
|
||||
void SetContainer(bool is_container) { m_container = is_container; }
|
||||
|
||||
bool IsEnabled() { return m_enabled; }
|
||||
void Enable(bool enable = true) { m_enabled = enable; }
|
||||
void Disable() { Enable(false); }
|
||||
|
||||
void StartSearch();
|
||||
void RefreshSearch(const wxString& search_text);
|
||||
void FinishSearch();
|
||||
|
||||
ParamsNode* GetParent() { return m_parent; }
|
||||
ParamsNodePtrArray& GetChildren() { return m_children; }
|
||||
wxDataViewItemArray GetEnabledChildren();
|
||||
|
||||
void Append(std::unique_ptr<ParamsNode> child) { m_children.emplace_back(std::move(child)); }
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ParamsModel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class ParamsModel : public wxDataViewModel
|
||||
{
|
||||
ParamsNodePtrArray m_group_nodes;
|
||||
wxDataViewCtrl* m_ctrl{ nullptr };
|
||||
bool m_currently_searching{false};
|
||||
|
||||
public:
|
||||
|
||||
ParamsModel();
|
||||
~ParamsModel() override = default;
|
||||
|
||||
void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
|
||||
|
||||
wxDataViewItem AppendGroup(const wxString& group_name,
|
||||
const std::string& icon_name);
|
||||
|
||||
wxDataViewItem AppendSubGroup(wxDataViewItem parent,
|
||||
const wxString& sub_group_name,
|
||||
const std::string&icon_name);
|
||||
|
||||
wxDataViewItem AppendParam( wxDataViewItem parent,
|
||||
ParamType param_type,
|
||||
const std::string& param_key);
|
||||
|
||||
wxDataViewItem Delete(const wxDataViewItem& item);
|
||||
|
||||
wxString GetParamName(wxDataViewItem item);
|
||||
std::string GetParamKey(wxDataViewItem item);
|
||||
std::string GetTopLevelCategory(wxDataViewItem item);
|
||||
|
||||
void RefreshSearch(const wxString& search_text);
|
||||
void FinishSearch();
|
||||
|
||||
void Clear();
|
||||
|
||||
wxDataViewItem GetParent(const wxDataViewItem& item) const override;
|
||||
unsigned int GetChildren(const wxDataViewItem& parent, wxDataViewItemArray& array) const override;
|
||||
unsigned int GetColumnCount() const override;
|
||||
wxString GetColumnType(unsigned int col) const override;
|
||||
|
||||
void GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const override;
|
||||
bool SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col) override;
|
||||
|
||||
bool IsContainer(const wxDataViewItem& item) const override;
|
||||
// Is the container just a header or an item with all columns
|
||||
// In our case it is an item with all columns
|
||||
bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ParamsViewCtrl
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class ParamsViewCtrl : public wxDataViewCtrl
|
||||
{
|
||||
int m_em_unit;
|
||||
|
||||
public:
|
||||
ParamsViewCtrl(wxWindow* parent, wxSize size);
|
||||
~ParamsViewCtrl() override {
|
||||
if (model) {
|
||||
Clear();
|
||||
model->DecRef();
|
||||
}
|
||||
}
|
||||
|
||||
ParamsModel* model{ nullptr };
|
||||
|
||||
wxDataViewItem AppendGroup(const wxString& group_name,
|
||||
const std::string& icon_name);
|
||||
|
||||
wxDataViewItem AppendSubGroup(wxDataViewItem parent,
|
||||
const wxString& sub_group_name,
|
||||
const std::string&icon_name);
|
||||
|
||||
wxDataViewItem AppendParam( wxDataViewItem parent,
|
||||
ParamType param_type,
|
||||
const std::string& param_key);
|
||||
|
||||
wxString GetValue(wxDataViewItem item);
|
||||
wxString GetSelectedValue();
|
||||
std::string GetSelectedParamKey();
|
||||
std::string GetSelectedTopLevelCategory();
|
||||
|
||||
void CheckAndDeleteIfEmpty(wxDataViewItem item);
|
||||
|
||||
void Clear();
|
||||
void Rescale(int em = 0);
|
||||
|
||||
void set_em_unit(int em) { m_em_unit = em; }
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
|
@ -196,6 +196,11 @@ void Field::on_back_to_sys_value()
|
|||
m_back_to_sys_value(m_opt_id);
|
||||
}
|
||||
|
||||
void Field::on_edit_value()
|
||||
{
|
||||
if (m_fn_edit_value)
|
||||
m_fn_edit_value(m_opt_id);
|
||||
}
|
||||
|
||||
/// Fires the enable or disable function, based on the input.
|
||||
|
||||
|
@ -206,7 +211,7 @@ wxString Field::get_tooltip_text(const wxString &default_string)
|
|||
wxString tooltip_text("");
|
||||
#ifdef NDEBUG
|
||||
wxString tooltip = _(m_opt.tooltip);
|
||||
edit_tooltip(tooltip);
|
||||
::edit_tooltip(tooltip);
|
||||
|
||||
std::string opt_id = m_opt_id;
|
||||
auto hash_pos = opt_id.find("#");
|
||||
|
|
|
@ -41,7 +41,120 @@ wxString double_to_string(double const value, const int max_precision = 4);
|
|||
wxString get_thumbnail_string(const Vec2d& value);
|
||||
wxString get_thumbnails_string(const std::vector<Vec2d>& values);
|
||||
|
||||
class Field {
|
||||
class UndoValueUIManager
|
||||
{
|
||||
struct UndoValueUI {
|
||||
// Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
|
||||
const ScalableBitmap* undo_bitmap{ nullptr };
|
||||
const wxString* undo_tooltip{ nullptr };
|
||||
// Bitmap and Tooltip text for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
|
||||
const ScalableBitmap* undo_to_sys_bitmap{ nullptr };
|
||||
const wxString* undo_to_sys_tooltip{ nullptr };
|
||||
// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
|
||||
const wxColour* label_color{ nullptr };
|
||||
// State of the blinker icon
|
||||
bool blink{ false };
|
||||
|
||||
bool set_undo_bitmap(const ScalableBitmap* bmp) {
|
||||
if (undo_bitmap != bmp) {
|
||||
undo_bitmap = bmp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_undo_to_sys_bitmap(const ScalableBitmap* bmp) {
|
||||
if (undo_to_sys_bitmap != bmp) {
|
||||
undo_to_sys_bitmap = bmp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_label_colour(const wxColour* clr) {
|
||||
if (label_color != clr) {
|
||||
label_color = clr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_undo_tooltip(const wxString* tip) {
|
||||
if (undo_tooltip != tip) {
|
||||
undo_tooltip = tip;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_undo_to_sys_tooltip(const wxString* tip) {
|
||||
if (undo_to_sys_tooltip != tip) {
|
||||
undo_to_sys_tooltip = tip;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
UndoValueUI m_undo_ui;
|
||||
|
||||
struct EditValueUI {
|
||||
// Bitmap and Tooltip text for m_Edit_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
|
||||
const ScalableBitmap* bitmap{ nullptr };
|
||||
wxString tooltip { wxEmptyString };
|
||||
|
||||
bool set_bitmap(const ScalableBitmap* bmp) {
|
||||
if (bitmap != bmp) {
|
||||
bitmap = bmp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_tooltip(const wxString& tip) {
|
||||
if (tooltip != tip) {
|
||||
tooltip = tip;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
EditValueUI m_edit_ui;
|
||||
|
||||
public:
|
||||
UndoValueUIManager() {}
|
||||
~UndoValueUIManager() {}
|
||||
|
||||
bool set_undo_bitmap(const ScalableBitmap* bmp) { return m_undo_ui.set_undo_bitmap(bmp); }
|
||||
bool set_undo_to_sys_bitmap(const ScalableBitmap* bmp) { return m_undo_ui.set_undo_to_sys_bitmap(bmp); }
|
||||
bool set_label_colour(const wxColour* clr) { return m_undo_ui.set_label_colour(clr); }
|
||||
bool set_undo_tooltip(const wxString* tip) { return m_undo_ui.set_undo_tooltip(tip); }
|
||||
bool set_undo_to_sys_tooltip(const wxString* tip) { return m_undo_ui.set_undo_to_sys_tooltip(tip); }
|
||||
|
||||
bool set_edit_bitmap(const ScalableBitmap* bmp) { return m_edit_ui.set_bitmap(bmp); }
|
||||
bool set_edit_tooltip(const wxString& tip) { return m_edit_ui.set_tooltip(tip); }
|
||||
|
||||
// ui items used for revert line value
|
||||
bool has_undo_ui() const { return m_undo_ui.undo_bitmap != nullptr; }
|
||||
const ScalableBitmap* undo_bitmap() const { return m_undo_ui.undo_bitmap; }
|
||||
const wxString* undo_tooltip() const { return m_undo_ui.undo_tooltip; }
|
||||
const ScalableBitmap* undo_to_sys_bitmap() const { return m_undo_ui.undo_to_sys_bitmap; }
|
||||
const wxString* undo_to_sys_tooltip() const { return m_undo_ui.undo_to_sys_tooltip; }
|
||||
const wxColour* label_color() const { return m_undo_ui.label_color; }
|
||||
|
||||
// Extentions
|
||||
|
||||
// Search blinker
|
||||
const bool blink() const { return m_undo_ui.blink; }
|
||||
bool* get_blink_ptr() { return &m_undo_ui.blink; }
|
||||
|
||||
// Edit field button
|
||||
bool has_edit_ui() const { return !m_edit_ui.tooltip.IsEmpty(); }
|
||||
const wxBitmap* edit_bitmap() const { return &m_edit_ui.bitmap->bmp(); }
|
||||
const wxString* edit_tooltip() const { return &m_edit_ui.tooltip; }
|
||||
};
|
||||
|
||||
class Field : public UndoValueUIManager {
|
||||
protected:
|
||||
// factory function to defer and enforce creation of derived type.
|
||||
virtual void PostInitialize();
|
||||
|
@ -70,6 +183,8 @@ public:
|
|||
void on_back_to_initial_value();
|
||||
/// Call the attached m_back_to_sys_value method.
|
||||
void on_back_to_sys_value();
|
||||
/// Call the attached m_fn_edit_value method.
|
||||
void on_edit_value();
|
||||
|
||||
public:
|
||||
/// parent wx item, opportunity to refactor (probably not necessary - data duplication)
|
||||
|
@ -85,6 +200,9 @@ public:
|
|||
t_back_to_init m_back_to_initial_value{ nullptr };
|
||||
t_back_to_init m_back_to_sys_value{ nullptr };
|
||||
|
||||
/// Callback function to edit field value
|
||||
t_back_to_init m_fn_edit_value{ nullptr };
|
||||
|
||||
// This is used to avoid recursive invocation of the field change/update by wxWidgets.
|
||||
bool m_disable_change_event {false};
|
||||
bool m_is_modified_value {false};
|
||||
|
@ -139,49 +257,6 @@ public:
|
|||
return std::move(p); //!p;
|
||||
}
|
||||
|
||||
bool set_undo_bitmap(const ScalableBitmap *bmp) {
|
||||
if (m_undo_bitmap != bmp) {
|
||||
m_undo_bitmap = bmp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_undo_to_sys_bitmap(const ScalableBitmap *bmp) {
|
||||
if (m_undo_to_sys_bitmap != bmp) {
|
||||
m_undo_to_sys_bitmap = bmp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_label_colour(const wxColour *clr) {
|
||||
if (m_label_color != clr) {
|
||||
m_label_color = clr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_undo_tooltip(const wxString *tip) {
|
||||
if (m_undo_tooltip != tip) {
|
||||
m_undo_tooltip = tip;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set_undo_to_sys_tooltip(const wxString *tip) {
|
||||
if (m_undo_to_sys_tooltip != tip) {
|
||||
m_undo_to_sys_tooltip = tip;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool* get_blink_ptr() {
|
||||
return &m_blink;
|
||||
}
|
||||
|
||||
virtual void msw_rescale();
|
||||
virtual void sys_color_changed();
|
||||
|
||||
|
@ -193,27 +268,9 @@ public:
|
|||
static int def_width_wider() ;
|
||||
static int def_width_thinner() ;
|
||||
|
||||
const ScalableBitmap* undo_bitmap() { return m_undo_bitmap; }
|
||||
const wxString* undo_tooltip() { return m_undo_tooltip; }
|
||||
const ScalableBitmap* undo_to_sys_bitmap() { return m_undo_to_sys_bitmap; }
|
||||
const wxString* undo_to_sys_tooltip() { return m_undo_to_sys_tooltip; }
|
||||
const wxColour* label_color() { return m_label_color; }
|
||||
const bool blink() { return m_blink; }
|
||||
const bool combine_side_text() { return m_combine_side_text; } // BBS: new param style
|
||||
|
||||
protected:
|
||||
// Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
|
||||
const ScalableBitmap* m_undo_bitmap = nullptr;
|
||||
const wxString* m_undo_tooltip = nullptr;
|
||||
// Bitmap and Tooltip text for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
|
||||
const ScalableBitmap* m_undo_to_sys_bitmap = nullptr;
|
||||
const wxString* m_undo_to_sys_tooltip = nullptr;
|
||||
|
||||
bool m_blink{ false };
|
||||
|
||||
// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
|
||||
const wxColour* m_label_color = nullptr;
|
||||
|
||||
// current value
|
||||
boost::any m_value;
|
||||
// last maeningful value
|
||||
|
|
|
@ -3185,14 +3185,17 @@ void GUI_App::UpdateDVCDarkUI(wxDataViewCtrl* dvc, bool highlited/* = false*/)
|
|||
UpdateDarkUI(dvc, highlited ? dark_mode() : false);
|
||||
#ifdef _MSW_DARK_MODE
|
||||
//dvc->RefreshHeaderDarkMode(&m_normal_font);
|
||||
HWND hwnd = (HWND)dvc->GenericGetHeader()->GetHandle();
|
||||
hwnd = GetWindow(hwnd, GW_CHILD);
|
||||
if (hwnd != NULL)
|
||||
NppDarkMode::SetDarkListViewHeader(hwnd);
|
||||
wxItemAttr attr;
|
||||
attr.SetTextColour(NppDarkMode::GetTextColor());
|
||||
attr.SetFont(m_normal_font);
|
||||
dvc->SetHeaderAttr(attr);
|
||||
HWND hwnd;
|
||||
if (!dvc->HasFlag(wxDV_NO_HEADER)) {
|
||||
hwnd = (HWND) dvc->GenericGetHeader()->GetHandle();
|
||||
hwnd = GetWindow(hwnd, GW_CHILD);
|
||||
if (hwnd != NULL)
|
||||
NppDarkMode::SetDarkListViewHeader(hwnd);
|
||||
wxItemAttr attr;
|
||||
attr.SetTextColour(NppDarkMode::GetTextColor());
|
||||
attr.SetFont(m_normal_font);
|
||||
dvc->SetHeaderAttr(attr);
|
||||
}
|
||||
#endif //_MSW_DARK_MODE
|
||||
if (dvc->HasFlag(wxDV_ROW_LINES))
|
||||
dvc->SetAlternateRowColour(m_color_highlight_default);
|
||||
|
|
|
@ -195,7 +195,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
|
|||
|
||||
if (line.widget) {
|
||||
#ifndef DISABLE_BLINKING
|
||||
h_pos += blinking_button_width;
|
||||
h_pos += (line.has_undo_ui() ? 3 : 1) * blinking_button_width;
|
||||
#endif
|
||||
|
||||
for (auto child : line.widget_sizer->GetChildren())
|
||||
|
@ -373,22 +373,31 @@ void OG_CustomCtrl::OnMotion(wxMouseEvent& event)
|
|||
break;
|
||||
}
|
||||
|
||||
for (size_t opt_idx = 0; opt_idx < line.rects_undo_icon.size(); opt_idx++)
|
||||
size_t undo_icons_cnt = line.rects_undo_icon.size();
|
||||
assert(line.rects_undo_icon.size() == line.rects_undo_to_sys_icon.size());
|
||||
const std::vector<Option>& option_set = line.og_line.get_options();
|
||||
for (size_t opt_idx = 0; opt_idx < undo_icons_cnt; opt_idx++) {
|
||||
const std::string& opt_key = option_set[opt_idx].opt_id;
|
||||
if (is_point_in_rect(pos, line.rects_undo_icon[opt_idx])) {
|
||||
const std::vector<Option>& option_set = line.og_line.get_options();
|
||||
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
|
||||
if (field)
|
||||
if (line.og_line.has_undo_ui())
|
||||
tooltip = *line.og_line.undo_tooltip();
|
||||
else if (Field* field = opt_group->get_field(opt_key))
|
||||
tooltip = *field->undo_tooltip();
|
||||
break;
|
||||
}
|
||||
for (size_t opt_idx = 0; opt_idx < line.rects_undo_to_sys_icon.size(); opt_idx++)
|
||||
if (is_point_in_rect(pos, line.rects_undo_to_sys_icon[opt_idx])) {
|
||||
const std::vector<Option>& option_set = line.og_line.get_options();
|
||||
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
|
||||
if (field)
|
||||
if (line.og_line.has_undo_ui())
|
||||
tooltip = *line.og_line.undo_to_sys_tooltip();
|
||||
else if (Field* field = opt_group->get_field(opt_key))
|
||||
tooltip = *field->undo_to_sys_tooltip();
|
||||
break;
|
||||
}
|
||||
if (opt_idx < line.rects_edit_icon.size() && is_point_in_rect(pos, line.rects_edit_icon[opt_idx])) {
|
||||
if (Field* field = opt_group->get_field(opt_key); field && field->has_edit_ui())
|
||||
tooltip = *field->edit_tooltip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!tooltip.IsEmpty())
|
||||
break;
|
||||
}
|
||||
|
@ -424,24 +433,40 @@ void OG_CustomCtrl::OnLeftDown(wxMouseEvent& event)
|
|||
if (!line.is_visible) continue;
|
||||
if (line.launch_browser())
|
||||
return;
|
||||
for (size_t opt_idx = 0; opt_idx < line.rects_undo_icon.size(); opt_idx++)
|
||||
size_t undo_icons_cnt = line.rects_undo_icon.size();
|
||||
assert(line.rects_undo_icon.size() == line.rects_undo_to_sys_icon.size());
|
||||
|
||||
const std::vector<Option>& option_set = line.og_line.get_options();
|
||||
for (size_t opt_idx = 0; opt_idx < undo_icons_cnt; opt_idx++) {
|
||||
const std::string& opt_key = option_set[opt_idx].opt_id;
|
||||
if (is_point_in_rect(pos, line.rects_undo_icon[opt_idx])) {
|
||||
const std::vector<Option>& option_set = line.og_line.get_options();
|
||||
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
|
||||
if (field)
|
||||
if (line.og_line.has_undo_ui()) {
|
||||
if (ConfigOptionsGroup* conf_OG = dynamic_cast<ConfigOptionsGroup*>(line.ctrl->opt_group))
|
||||
conf_OG->back_to_initial_value(opt_key);
|
||||
}
|
||||
else if (Field* field = opt_group->get_field(opt_key))
|
||||
field->on_back_to_initial_value();
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
for (size_t opt_idx = 0; opt_idx < line.rects_undo_to_sys_icon.size(); opt_idx++)
|
||||
if (is_point_in_rect(pos, line.rects_undo_to_sys_icon[opt_idx])) {
|
||||
const std::vector<Option>& option_set = line.og_line.get_options();
|
||||
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
|
||||
if (field)
|
||||
if (line.og_line.has_undo_ui()) {
|
||||
if (ConfigOptionsGroup* conf_OG = dynamic_cast<ConfigOptionsGroup*>(line.ctrl->opt_group))
|
||||
conf_OG->back_to_sys_value(opt_key);
|
||||
}
|
||||
else if (Field* field = opt_group->get_field(opt_key))
|
||||
field->on_back_to_sys_value();
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt_idx < line.rects_edit_icon.size() && is_point_in_rect(pos, line.rects_edit_icon[opt_idx])) {
|
||||
if (Field* field = opt_group->get_field(opt_key))
|
||||
field->on_edit_value();
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetFocusIgnoringChildren();
|
||||
|
@ -745,10 +770,14 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord h_pos, wxCoord v_pos)
|
|||
bool suppress_hyperlinks = false;
|
||||
if (draw_just_act_buttons) {
|
||||
//BBS: GUI refactor
|
||||
if (field && field->undo_bitmap())
|
||||
//if (field)
|
||||
// BBS: new layout
|
||||
draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), field->blink());
|
||||
if (field && field->undo_bitmap()) {
|
||||
// if (field)
|
||||
// BBS: new layout
|
||||
const wxPoint pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(),
|
||||
field->undo_bitmap()->bmp(), field->blink());
|
||||
if (field->has_edit_ui())
|
||||
draw_edit_bmp(dc, pos, *field->edit_bitmap());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -761,7 +790,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord h_pos, wxCoord v_pos)
|
|||
wxColour blink_color = StateColor::darkModeColorFor("#009688");
|
||||
bool is_url_string = false;
|
||||
if (ctrl->opt_group->label_width != 0 && !label.IsEmpty()) {
|
||||
const wxColour* text_clr = field ? field->label_color() : og_line.full_Label_color;
|
||||
const wxColour* text_clr = field ? field->label_color() : og_line.label_color();
|
||||
for (const Option& opt : option_set) {
|
||||
Field* field = ctrl->opt_group->get_field(opt.opt_id);
|
||||
if (field && field->blink()) {
|
||||
|
@ -802,7 +831,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord h_pos, wxCoord v_pos)
|
|||
|
||||
auto draw_buttons = [&h_pos, &dc, &v_pos, this](Field* field, size_t bmp_rect_id = 0) {
|
||||
if (field && field->undo_to_sys_bitmap()) {
|
||||
h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), field->blink(), bmp_rect_id);
|
||||
h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), field->blink(), bmp_rect_id).x;
|
||||
}
|
||||
#ifndef DISABLE_BLINKING
|
||||
else if (field && !field->undo_to_sys_bitmap() && field->blink())
|
||||
|
@ -945,7 +974,7 @@ wxPoint OG_CustomCtrl::CtrlLine::draw_blinking_bmp(wxDC& dc, wxPoint pos, bool i
|
|||
return wxPoint(h_pos, v_pos);
|
||||
}
|
||||
|
||||
wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, bool is_blinking, size_t rect_id)
|
||||
wxPoint OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, bool is_blinking, size_t rect_id)
|
||||
{
|
||||
#ifndef DISABLE_BLINKING
|
||||
pos = draw_blinking_bmp(dc, pos, is_blinking);
|
||||
|
@ -979,7 +1008,19 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBi
|
|||
|
||||
h_pos += bmp_dim2 + ctrl->m_h_gap;
|
||||
|
||||
return h_pos;
|
||||
return wxPoint(h_pos, v_pos);
|
||||
}
|
||||
|
||||
wxCoord OG_CustomCtrl::CtrlLine::draw_edit_bmp(wxDC &dc, wxPoint pos, const wxBitmap& bmp_edit)
|
||||
{
|
||||
const wxCoord h_pos = pos.x + ctrl->m_h_gap;
|
||||
const wxCoord v_pos = pos.y;
|
||||
const int bmp_w = bmp_edit.GetWidth();
|
||||
rects_edit_icon.emplace_back(wxRect(h_pos, v_pos, bmp_w, bmp_w));
|
||||
|
||||
dc.DrawBitmap(bmp_edit, h_pos, v_pos);
|
||||
|
||||
return h_pos + bmp_w + ctrl->m_h_gap;
|
||||
}
|
||||
|
||||
bool OG_CustomCtrl::CtrlLine::launch_browser() const
|
||||
|
|
|
@ -64,12 +64,14 @@ class OG_CustomCtrl :public wxPanel
|
|||
void render(wxDC& dc, wxCoord h_pos, wxCoord v_pos);
|
||||
wxCoord draw_text (wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width, bool is_url = false, bool is_main = false);
|
||||
wxPoint draw_blinking_bmp(wxDC& dc, wxPoint pos, bool is_blinking);
|
||||
wxCoord draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, bool is_blinking, size_t rect_id = 0);
|
||||
wxPoint draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, bool is_blinking, size_t rect_id = 0);
|
||||
wxCoord draw_edit_bmp(wxDC& dc, wxPoint pos, const wxBitmap& bmp_edit);
|
||||
bool launch_browser() const;
|
||||
bool is_separator() const { return og_line.is_separator(); }
|
||||
|
||||
std::vector<wxRect> rects_undo_icon;
|
||||
std::vector<wxRect> rects_undo_to_sys_icon;
|
||||
std::vector<wxRect> rects_edit_icon;
|
||||
wxRect rect_label;
|
||||
};
|
||||
|
||||
|
|
|
@ -102,6 +102,14 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
|
|||
};
|
||||
field->m_parent = parent();
|
||||
|
||||
if (edit_custom_gcode && opt.is_code) {
|
||||
field->m_fn_edit_value = [this](std::string opt_id) {
|
||||
if (!m_disabled)
|
||||
this->edit_custom_gcode(opt_id);
|
||||
};
|
||||
field->set_edit_tooltip(_L("Edit Custom G-code"));
|
||||
}
|
||||
|
||||
field->m_back_to_initial_value = [this](std::string opt_id) {
|
||||
if (!m_disabled)
|
||||
this->back_to_initial_value(opt_id);
|
||||
|
@ -678,6 +686,7 @@ void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config,
|
|||
opt_key == "thumbnails" || opt_key == "bed_custom_texture" || opt_key == "bed_custom_model") {
|
||||
value = get_config_value(config, opt_key);
|
||||
this->change_opt_value(opt_key, value);
|
||||
OptionsGroup::on_change_OG(opt_key, value);
|
||||
return;
|
||||
} else {
|
||||
auto opt_id = m_opt_map.find(opt_key)->first;
|
||||
|
|
|
@ -48,7 +48,8 @@ struct Option {
|
|||
using t_option = std::unique_ptr<Option>; //!
|
||||
|
||||
/// Represents option lines
|
||||
class Line {
|
||||
class Line : public UndoValueUIManager
|
||||
{
|
||||
bool m_is_separator{ false };
|
||||
public:
|
||||
wxString label;
|
||||
|
@ -58,8 +59,6 @@ public:
|
|||
bool toggle_visible{true}; // BBS: hide some line
|
||||
|
||||
size_t full_width {0};
|
||||
wxColour* full_Label_color {nullptr};
|
||||
bool blink {false};
|
||||
widget_t widget {nullptr};
|
||||
std::function<wxWindow*(wxWindow*)> near_label_widget{ nullptr };
|
||||
wxWindow* near_label_widget_win {nullptr};
|
||||
|
@ -83,10 +82,10 @@ public:
|
|||
Line() : m_is_separator(true) {}
|
||||
|
||||
bool is_separator() const { return m_is_separator; }
|
||||
bool has_only_option(const std::string& opt_key) const { return m_options.size() == 1 && m_options[0].opt_id == opt_key; }
|
||||
|
||||
const std::vector<widget_t>& get_extra_widgets() const {return m_extra_widgets;}
|
||||
const std::vector<Option>& get_options() const { return m_options; }
|
||||
bool* get_blink_ptr() { return &blink; }
|
||||
|
||||
private:
|
||||
std::vector<Option> m_options;//! {std::vector<Option>()};
|
||||
|
@ -122,6 +121,8 @@ public:
|
|||
|
||||
std::function<void(wxWindow* win)> rescale_extra_column_item { nullptr };
|
||||
std::function<void(wxWindow* win)> rescale_near_label_widget { nullptr };
|
||||
|
||||
std::function<void(const t_config_option_key& opt_key)> edit_custom_gcode { nullptr };
|
||||
|
||||
wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
|
||||
wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
|
||||
|
@ -155,6 +156,7 @@ public:
|
|||
if (m_fields.find(id) == m_fields.end()) return nullptr;
|
||||
return m_fields.at(id).get();
|
||||
}
|
||||
|
||||
bool set_value(const t_config_option_key& id, const boost::any& value, bool change_event = false) {
|
||||
if (m_fields.find(id) == m_fields.end()) return false;
|
||||
m_fields.at(id)->set_value(value, change_event);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "format.hpp"
|
||||
#include "UnsavedChangesDialog.hpp"
|
||||
#include "SavePresetDialog.hpp"
|
||||
#include "EditGCodeDialog.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "Notebook.hpp"
|
||||
|
||||
|
@ -255,6 +256,8 @@ void Tab::create_preset_tab()
|
|||
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
|
||||
add_scaled_bitmap(this, m_bmp_value_revert, "undo");
|
||||
add_scaled_bitmap(this, m_bmp_white_bullet, "dot");
|
||||
// Bitmap to be shown on the "edit" button before to each editable input field.
|
||||
add_scaled_bitmap(this, m_bmp_edit_value, "edit");
|
||||
|
||||
set_tooltips_text();
|
||||
|
||||
|
@ -708,8 +711,8 @@ void Tab::update_label_colours()
|
|||
}
|
||||
if (opt.first == "printable_area" ||
|
||||
opt.first == "compatible_prints" || opt.first == "compatible_printers" ) {
|
||||
if (m_colored_Label_colors.find(opt.first) != m_colored_Label_colors.end())
|
||||
m_colored_Label_colors.at(opt.first) = *color;
|
||||
if (Line* line = get_line(opt.first))
|
||||
line->set_label_colour(color);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -748,13 +751,13 @@ void Tab::decorate()
|
|||
for (const auto& opt : m_options_list)
|
||||
{
|
||||
Field* field = nullptr;
|
||||
wxColour* colored_label_clr = nullptr;
|
||||
bool option_without_field = false;
|
||||
|
||||
if (opt.first == "printable_area" ||
|
||||
opt.first == "compatible_prints" || opt.first == "compatible_printers")
|
||||
colored_label_clr = (m_colored_Label_colors.find(opt.first) == m_colored_Label_colors.end()) ? nullptr : &m_colored_Label_colors.at(opt.first);
|
||||
option_without_field = true;
|
||||
|
||||
if (!colored_label_clr) {
|
||||
if (!option_without_field) {
|
||||
field = get_field(opt.first);
|
||||
if (!field)
|
||||
continue;
|
||||
|
@ -789,8 +792,14 @@ void Tab::decorate()
|
|||
tt = &m_tt_white_bullet;
|
||||
}
|
||||
|
||||
if (colored_label_clr) {
|
||||
*colored_label_clr = *color;
|
||||
if (option_without_field) {
|
||||
if (Line* line = get_line(opt.first)) {
|
||||
line->set_undo_bitmap(icon);
|
||||
line->set_undo_to_sys_bitmap(sys_icon);
|
||||
line->set_undo_tooltip(tt);
|
||||
line->set_undo_to_sys_tooltip(sys_tt);
|
||||
line->set_label_colour(color);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -802,6 +811,10 @@ void Tab::decorate()
|
|||
field->set_undo_tooltip(tt);
|
||||
field->set_undo_to_sys_tooltip(sys_tt);
|
||||
field->set_label_colour(color);
|
||||
|
||||
if (field->has_edit_ui())
|
||||
field->set_edit_bitmap(&m_bmp_edit_value);
|
||||
|
||||
}
|
||||
|
||||
if (m_active_page)
|
||||
|
@ -1082,7 +1095,7 @@ void Tab::on_roll_back_value(const bool to_sys /*= true*/)
|
|||
|
||||
m_postpone_update_ui = false;
|
||||
|
||||
// When all values are rolled, then we hane to update whole tab in respect to the reverted values
|
||||
// When all values are rolled, then we have to update whole tab in respect to the reverted values
|
||||
update();
|
||||
|
||||
// BBS: restore all pages in preset, update_dirty also update combobox
|
||||
|
@ -1265,6 +1278,11 @@ Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/
|
|||
return m_active_page ? m_active_page->get_field(opt_key, opt_index) : nullptr;
|
||||
}
|
||||
|
||||
Line* Tab::get_line(const t_config_option_key& opt_key)
|
||||
{
|
||||
return m_active_page ? m_active_page->get_line(opt_key) : nullptr;
|
||||
}
|
||||
|
||||
std::pair<OG_CustomCtrl*, bool*> Tab::get_custom_ctrl_with_blinking_ptr(const t_config_option_key& opt_key, int opt_index/* = -1*/)
|
||||
{
|
||||
if (!m_active_page)
|
||||
|
@ -2880,6 +2898,43 @@ static void validate_custom_gcode_cb(Tab* tab, ConfigOptionsGroupShp opt_group,
|
|||
tab->on_value_change(opt_key, value);
|
||||
}
|
||||
|
||||
void Tab::edit_custom_gcode(const t_config_option_key& opt_key)
|
||||
{
|
||||
EditGCodeDialog dlg = EditGCodeDialog(this, opt_key, get_custom_gcode(opt_key));
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
set_custom_gcode(opt_key, dlg.get_edited_gcode());
|
||||
update_dirty();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& Tab::get_custom_gcode(const t_config_option_key& opt_key)
|
||||
{
|
||||
return m_config->opt_string(opt_key);
|
||||
}
|
||||
|
||||
void Tab::set_custom_gcode(const t_config_option_key& opt_key, const std::string& value)
|
||||
{
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value(opt_key, new ConfigOptionString(value));
|
||||
load_config(new_conf);
|
||||
}
|
||||
|
||||
const std::string& TabFilament::get_custom_gcode(const t_config_option_key& opt_key)
|
||||
{
|
||||
return m_config->opt_string(opt_key, unsigned(0));
|
||||
}
|
||||
|
||||
void TabFilament::set_custom_gcode(const t_config_option_key& opt_key, const std::string& value)
|
||||
{
|
||||
std::vector<std::string> gcodes = static_cast<const ConfigOptionStrings*>(m_config->option(opt_key))->values;
|
||||
gcodes[0] = value;
|
||||
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value(opt_key, new ConfigOptionStrings(gcodes));
|
||||
load_config(new_conf);
|
||||
}
|
||||
|
||||
void TabFilament::add_filament_overrides_page()
|
||||
{
|
||||
//BBS
|
||||
|
@ -3155,11 +3210,14 @@ void TabFilament::build()
|
|||
const int gcode_field_height = 15; // 150
|
||||
const int notes_field_height = 25; // 250
|
||||
|
||||
auto edit_custom_gcode_fn = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); };
|
||||
|
||||
page = add_options_page(L("Advanced"), "advanced");
|
||||
optgroup = page->new_optgroup(L("Filament start G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("filament_start_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3170,6 +3228,7 @@ void TabFilament::build()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("filament_end_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3471,6 +3530,8 @@ void TabPrinter::build_fff()
|
|||
optgroup->append_single_option_line("support_chamber_temp_control", "chamber-temperature");
|
||||
optgroup->append_single_option_line("support_air_filtration", "air-filtration");
|
||||
|
||||
auto edit_custom_gcode_fn = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); };
|
||||
|
||||
const int gcode_field_height = 15; // 150
|
||||
const int notes_field_height = 25; // 250
|
||||
page = add_options_page(L("Machine gcode"), "cog");
|
||||
|
@ -3478,6 +3539,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("machine_start_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3488,6 +3550,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("machine_end_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3498,6 +3561,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, optgroup](const t_config_option_key &opt_key, const boost::any &value) {
|
||||
validate_custom_gcode_cb(this, optgroup, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("printing_by_object_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3509,6 +3573,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("before_layer_change_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3519,6 +3584,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("layer_change_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3529,6 +3595,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("time_lapse_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3539,6 +3606,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("change_filament_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3549,7 +3617,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key &opt_key, const boost::any &value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("change_extrusion_role_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
@ -3560,6 +3628,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("machine_pause_gcode");
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
|
@ -3569,6 +3638,7 @@ void TabPrinter::build_fff()
|
|||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("template_custom_gcode");
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
|
@ -5312,8 +5382,12 @@ void Tab::create_line_with_widget(ConfigOptionsGroup* optgroup, const std::strin
|
|||
line.widget = widget;
|
||||
line.label_path = path;
|
||||
|
||||
m_colored_Label_colors[opt_key] = m_default_text_clr;
|
||||
line.full_Label_color = &m_colored_Label_colors[opt_key];
|
||||
// set default undo ui
|
||||
line.set_undo_bitmap(&m_bmp_white_bullet);
|
||||
line.set_undo_to_sys_bitmap(&m_bmp_white_bullet);
|
||||
line.set_undo_tooltip(&m_tt_white_bullet);
|
||||
line.set_undo_to_sys_tooltip(&m_tt_white_bullet);
|
||||
line.set_label_colour(&m_default_text_clr);
|
||||
|
||||
optgroup->append_line(line);
|
||||
}
|
||||
|
@ -5671,12 +5745,10 @@ Field *Page::get_field(const t_config_option_key &opt_key, int opt_index /*= -1*
|
|||
|
||||
Line *Page::get_line(const t_config_option_key &opt_key)
|
||||
{
|
||||
Line *line = nullptr;
|
||||
for (auto opt : m_optgroups) {
|
||||
line = opt->get_line(opt_key);
|
||||
if (line != nullptr) return line;
|
||||
}
|
||||
return line;
|
||||
for (auto opt : m_optgroups)
|
||||
if (Line* line = opt->get_line(opt_key))
|
||||
return line;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Page::set_value(const t_config_option_key &opt_key, const boost::any &value)
|
||||
|
|
|
@ -201,6 +201,8 @@ protected:
|
|||
ScalableBitmap *m_bmp_non_system;
|
||||
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
|
||||
ScalableBitmap m_bmp_value_revert;
|
||||
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
|
||||
ScalableBitmap m_bmp_edit_value;
|
||||
|
||||
std::vector<ScalableButton*> m_scaled_buttons = {};
|
||||
std::vector<ScalableBitmap*> m_scaled_bitmaps = {};
|
||||
|
@ -374,6 +376,7 @@ public:
|
|||
virtual void msw_rescale();
|
||||
virtual void sys_color_changed();
|
||||
Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const;
|
||||
Line* get_line(const t_config_option_key& opt_key);
|
||||
std::pair<OG_CustomCtrl*, bool*> get_custom_ctrl_with_blinking_ptr(const t_config_option_key& opt_key, int opt_index = -1);
|
||||
|
||||
Field* get_field(const t_config_option_key &opt_key, Page** selected_page, int opt_index = -1);
|
||||
|
@ -410,6 +413,10 @@ public:
|
|||
bool validate_custom_gcodes_was_shown{ false };
|
||||
void set_just_edit(bool just_edit);
|
||||
|
||||
void edit_custom_gcode(const t_config_option_key& opt_key);
|
||||
virtual const std::string& get_custom_gcode(const t_config_option_key& opt_key);
|
||||
virtual void set_custom_gcode(const t_config_option_key& opt_key, const std::string& value);
|
||||
|
||||
protected:
|
||||
void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const std::string& path, widget_t widget);
|
||||
wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps);
|
||||
|
@ -427,6 +434,7 @@ protected:
|
|||
|
||||
ConfigManipulation m_config_manipulation;
|
||||
ConfigManipulation get_config_manipulation();
|
||||
friend class EditGCodeDialog;
|
||||
};
|
||||
|
||||
class TabPrint : public Tab
|
||||
|
@ -562,6 +570,9 @@ public:
|
|||
void update() override;
|
||||
void clear_pages() override;
|
||||
bool supports_printer_technology(const PrinterTechnology tech) const override { return tech == ptFFF; }
|
||||
|
||||
const std::string& get_custom_gcode(const t_config_option_key& opt_key) override;
|
||||
void set_custom_gcode(const t_config_option_key& opt_key, const std::string& value) override;
|
||||
};
|
||||
|
||||
class TabPrinter : public Tab
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue