Implement Search for GCode DataView

This commit is contained in:
Ocraftyone 2024-01-08 18:00:32 -05:00
parent 43417b0f63
commit 068b888199
No known key found for this signature in database
GPG key ID: 85836ED21AD4D125
2 changed files with 145 additions and 19 deletions

View file

@ -50,9 +50,28 @@ EditGCodeDialog::EditGCodeDialog(wxWindow* parent, const std::string& key, const
auto* grid_sizer = new wxFlexGridSizer(1, 3, 5, 15); auto* grid_sizer = new wxFlexGridSizer(1, 3, 5, 15);
grid_sizer->SetFlexibleDirection(wxBOTH); 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 = new ParamsViewCtrl(this, wxSize(em * 45, em * 70));
m_params_list->SetFont(wxGetApp().code_font()); m_params_list->SetFont(wxGetApp().code_font());
wxGetApp().UpdateDarkUI(m_params_list); 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 = new ScalableButton(this, wxID_ANY, "add_copies");
m_add_btn->SetToolTip(_L("Add selected placeholder to G-code")); m_add_btn->SetToolTip(_L("Add selected placeholder to G-code"));
@ -66,7 +85,7 @@ EditGCodeDialog::EditGCodeDialog(wxWindow* parent, const std::string& key, const
m_gcode_editor->SetInsertionPointEnd(); m_gcode_editor->SetInsertionPointEnd();
wxGetApp().UpdateDarkUI(m_gcode_editor); wxGetApp().UpdateDarkUI(m_gcode_editor);
grid_sizer->Add(m_params_list, 1, wxEXPAND); grid_sizer->Add(param_sizer, 1, wxEXPAND);
grid_sizer->Add(m_add_btn, 0, wxALIGN_CENTER_VERTICAL); grid_sizer->Add(m_add_btn, 0, wxALIGN_CENTER_VERTICAL);
grid_sizer->Add(m_gcode_editor, 2, wxEXPAND); grid_sizer->Add(m_gcode_editor, 2, wxEXPAND);
@ -116,6 +135,15 @@ std::string EditGCodeDialog::get_edited_gcode() const
return into_u8(m_gcode_editor->GetValue()); 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) static ParamType get_type(const std::string& opt_key, const ConfigOptionDef& opt_def)
{ {
return opt_def.is_scalar() ? ParamType::Scalar : ParamType::Vector; return opt_def.is_scalar() ? ParamType::Scalar : ParamType::Vector;
@ -486,30 +514,35 @@ static void make_bold(wxString& str)
// ParamsModelNode: a node inside ParamsModel // ParamsModelNode: a node inside ParamsModel
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
ParamsNode::ParamsNode(const wxString& group_name, const std::string& icon_name) ParamsNode::ParamsNode(const wxString& group_name, const std::string& icon_name, wxDataViewCtrl* ctrl)
: icon_name(icon_name) : icon_name(icon_name)
, text(group_name) , text(group_name)
, m_ctrl(ctrl)
{ {
make_bold(text); make_bold(text);
} }
ParamsNode::ParamsNode( ParamsNode * parent, ParamsNode::ParamsNode( ParamsNode * parent,
const wxString& sub_group_name, const wxString& sub_group_name,
const std::string& icon_name) const std::string& icon_name,
wxDataViewCtrl* ctrl)
: m_parent(parent) : m_parent(parent)
, icon_name(icon_name) , icon_name(icon_name)
, text(sub_group_name) , text(sub_group_name)
, m_ctrl(ctrl)
{ {
make_bold(text); make_bold(text);
} }
ParamsNode::ParamsNode( ParamsNode* parent, ParamsNode::ParamsNode( ParamsNode* parent,
ParamType param_type, ParamType param_type,
const std::string& param_key) const std::string& param_key,
wxDataViewCtrl* ctrl)
: m_parent(parent) : m_parent(parent)
, m_param_type(param_type) , m_param_type(param_type)
, m_container(false) , m_container(false)
, param_key(param_key) , param_key(param_key)
, m_ctrl(ctrl)
{ {
text = from_u8(param_key); text = from_u8(param_key);
if (param_type == ParamType::Vector) if (param_type == ParamType::Vector)
@ -520,6 +553,48 @@ ParamsNode::ParamsNode( ParamsNode* parent,
icon_name = ParamsInfo.at(param_type); icon_name = ParamsInfo.at(param_type);
} }
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 (IsParamNode() && text.find(search_text) != wxString::npos)
Enable();
else
Disable();
else
Enable();
}
void ParamsNode::FinishSearch()
{
Enable();
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
@ -532,7 +607,7 @@ ParamsModel::ParamsModel()
wxDataViewItem ParamsModel::AppendGroup(const wxString& group_name, wxDataViewItem ParamsModel::AppendGroup(const wxString& group_name,
const std::string& icon_name) const std::string& icon_name)
{ {
m_group_nodes.emplace_back(std::make_unique<ParamsNode>(group_name, icon_name)); m_group_nodes.emplace_back(std::make_unique<ParamsNode>(group_name, icon_name, m_ctrl));
wxDataViewItem parent(nullptr); wxDataViewItem parent(nullptr);
wxDataViewItem child((void*)m_group_nodes.back().get()); wxDataViewItem child((void*)m_group_nodes.back().get());
@ -550,7 +625,7 @@ wxDataViewItem ParamsModel::AppendSubGroup(wxDataViewItem parent,
if (!parent_node) if (!parent_node)
return wxDataViewItem(0); return wxDataViewItem(0);
parent_node->Append(std::make_unique<ParamsNode>(parent_node, sub_group_name, icon_name)); 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()); const wxDataViewItem sub_group_item((void*)parent_node->GetChildren().back().get());
ItemAdded(parent, sub_group_item); ItemAdded(parent, sub_group_item);
@ -565,7 +640,7 @@ wxDataViewItem ParamsModel::AppendParam(wxDataViewItem parent,
if (!parent_node) if (!parent_node)
return wxDataViewItem(0); return wxDataViewItem(0);
parent_node->Append(std::make_unique<ParamsNode>(parent_node, param_type, param_key)); 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()); const wxDataViewItem child_item((void*)parent_node->GetChildren().back().get());
@ -603,6 +678,34 @@ std::string ParamsModel::GetTopLevelCategory(wxDataViewItem item)
return std::string(); 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) wxDataViewItem ParamsModel::Delete(const wxDataViewItem& item)
{ {
auto ret_item = wxDataViewItem(nullptr); auto ret_item = wxDataViewItem(nullptr);
@ -723,12 +826,14 @@ unsigned int ParamsModel::GetChildren(const wxDataViewItem& parent, wxDataViewIt
if (parent_node == nullptr) { if (parent_node == nullptr) {
for (const auto& group : m_group_nodes) for (const auto& group : m_group_nodes)
array.Add(wxDataViewItem((void*)group.get())); if (group->IsEnabled())
array.Add(wxDataViewItem((void*)group.get()));
} }
else { else {
const ParamsNodePtrArray& children = parent_node->GetChildren(); const ParamsNodePtrArray& children = parent_node->GetChildren();
for (const std::unique_ptr<ParamsNode>& child : children) for (const std::unique_ptr<ParamsNode>& child : children)
array.Add(wxDataViewItem((void*)child.get())); if (child->IsEnabled())
array.Add(wxDataViewItem((void*)child.get()));
} }
return array.Count(); return array.Count();

View file

@ -10,6 +10,7 @@
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
#include "libslic3r/Preset.hpp" #include "libslic3r/Preset.hpp"
#include "libslic3r/PrintConfig.hpp" #include "libslic3r/PrintConfig.hpp"
#include <wx/srchctrl.h>
class wxListBox; class wxListBox;
class wxTextCtrl; class wxTextCtrl;
@ -27,11 +28,12 @@ class ParamsViewCtrl;
class EditGCodeDialog : public DPIDialog class EditGCodeDialog : public DPIDialog
{ {
ParamsViewCtrl* m_params_list {nullptr}; ParamsViewCtrl* m_params_list {nullptr};
ScalableButton* m_add_btn {nullptr}; ScalableButton* m_add_btn {nullptr};
wxTextCtrl* m_gcode_editor {nullptr}; wxTextCtrl* m_gcode_editor {nullptr};
wxStaticText* m_param_label {nullptr}; wxStaticText* m_param_label {nullptr};
wxStaticText* m_param_description {nullptr}; wxStaticText* m_param_description {nullptr};
wxSearchCtrl* m_search_bar {nullptr};
ReadOnlySlicingStatesConfigDef cgp_ro_slicing_states_config_def; ReadOnlySlicingStatesConfigDef cgp_ro_slicing_states_config_def;
ReadWriteSlicingStatesConfigDef cgp_rw_slicing_states_config_def; ReadWriteSlicingStatesConfigDef cgp_rw_slicing_states_config_def;
@ -48,6 +50,7 @@ public:
~EditGCodeDialog(); ~EditGCodeDialog();
std::string get_edited_gcode() const; std::string get_edited_gcode() const;
void on_search_update();
void init_params_list(const std::string& custom_gcode_name); void init_params_list(const std::string& custom_gcode_name);
wxDataViewItem add_presets_placeholders(); wxDataViewItem add_presets_placeholders();
@ -93,6 +96,7 @@ class ParamsNode
{ {
ParamsNode* m_parent{ nullptr }; ParamsNode* m_parent{ nullptr };
ParamsNodePtrArray m_children; ParamsNodePtrArray m_children;
wxDataViewCtrl* m_ctrl;
ParamType m_param_type{ ParamType::Undef }; ParamType m_param_type{ ParamType::Undef };
@ -106,6 +110,8 @@ class ParamsNode
// AND the classical node was removed (a new node temporary without children // AND the classical node was removed (a new node temporary without children
// would be added to the control) // would be added to the control)
bool m_container{ true }; bool m_container{ true };
bool m_expanded_before_search{false};
bool m_enabled{true};
public: public:
@ -119,25 +125,36 @@ public:
wxString text; wxString text;
// Group params(root) node // Group params(root) node
ParamsNode(const wxString& group_name, const std::string& icon_name); ParamsNode(const wxString& group_name, const std::string& icon_name, wxDataViewCtrl* ctrl);
// sub SlicingState node // sub SlicingState node
ParamsNode(ParamsNode* parent, ParamsNode(ParamsNode* parent,
const wxString& sub_group_name, const wxString& sub_group_name,
const std::string& icon_name); const std::string& icon_name,
wxDataViewCtrl* ctrl);
// parametre node // parametre node
ParamsNode( ParamsNode* parent, ParamsNode( ParamsNode* parent,
ParamType param_type, ParamType param_type,
const std::string& param_key); const std::string& param_key,
wxDataViewCtrl* ctrl);
bool IsContainer() const { return m_container; } bool IsContainer() const { return m_container; }
bool IsGroupNode() const { return m_parent == nullptr; } bool IsGroupNode() const { return m_parent == nullptr; }
bool IsParamNode() const { return m_param_type != ParamType::Undef; } bool IsParamNode() const { return m_param_type != ParamType::Undef; }
void SetContainer(bool is_container) { m_container = is_container; } 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; } ParamsNode* GetParent() { return m_parent; }
ParamsNodePtrArray& GetChildren() { return m_children; } ParamsNodePtrArray& GetChildren() { return m_children; }
wxDataViewItemArray GetEnabledChildren();
void Append(std::unique_ptr<ParamsNode> child) { m_children.emplace_back(std::move(child)); } void Append(std::unique_ptr<ParamsNode> child) { m_children.emplace_back(std::move(child)); }
}; };
@ -149,8 +166,9 @@ public:
class ParamsModel : public wxDataViewModel class ParamsModel : public wxDataViewModel
{ {
ParamsNodePtrArray m_group_nodes; ParamsNodePtrArray m_group_nodes;
wxDataViewCtrl* m_ctrl{ nullptr }; wxDataViewCtrl* m_ctrl{ nullptr };
bool m_currently_searching{false};
public: public:
@ -176,6 +194,9 @@ public:
std::string GetParamKey(wxDataViewItem item); std::string GetParamKey(wxDataViewItem item);
std::string GetTopLevelCategory(wxDataViewItem item); std::string GetTopLevelCategory(wxDataViewItem item);
void RefreshSearch(const wxString& search_text);
void FinishSearch();
void Clear(); void Clear();
wxDataViewItem GetParent(const wxDataViewItem& item) const override; wxDataViewItem GetParent(const wxDataViewItem& item) const override;