From e188893c28e32996330b44cbf8e1bece1b4f5565 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 13 Mar 2020 22:37:18 +0100 Subject: [PATCH] Start to implement "Search through options" --- src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/Plater.cpp | 30 ++++- src/slic3r/GUI/Plater.hpp | 1 + src/slic3r/GUI/SearchComboBox.cpp | 211 ++++++++++++++++++++++++++++++ src/slic3r/GUI/SearchComboBox.hpp | 87 ++++++++++++ src/slic3r/GUI/Tab.cpp | 67 +++++++++- src/slic3r/GUI/Tab.hpp | 4 + 7 files changed, 397 insertions(+), 5 deletions(-) create mode 100644 src/slic3r/GUI/SearchComboBox.cpp create mode 100644 src/slic3r/GUI/SearchComboBox.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 5e0c34da0..d6850ee54 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -150,6 +150,8 @@ set(SLIC3R_GUI_SOURCES GUI/DoubleSlider.hpp GUI/ObjectDataViewModel.cpp GUI/ObjectDataViewModel.hpp + GUI/SearchComboBox.cpp + GUI/SearchComboBox.hpp Utils/Http.cpp Utils/Http.hpp Utils/FixModelByWin10.cpp diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2a25762a8..66ba11887 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -82,6 +82,7 @@ #include "../Utils/UndoRedo.hpp" #include "../Utils/Thread.hpp" #include "RemovableDriveManager.hpp" +#include "SearchComboBox.hpp" #include // Needs to be last because reasons :-/ #include "WipeTowerDialog.hpp" @@ -705,6 +706,7 @@ struct Sidebar::priv wxBoxSizer *sizer_params; FreqChangedParams *frequently_changed_parameters{ nullptr }; + SearchComboBox *search_cb{ nullptr }; ObjectList *object_list{ nullptr }; ObjectManipulation *object_manipulation{ nullptr }; ObjectSettings *object_settings{ nullptr }; @@ -831,6 +833,10 @@ Sidebar::Sidebar(Plater *parent) p->frequently_changed_parameters = new FreqChangedParams(p->scrolled); p->sizer_params->Add(p->frequently_changed_parameters->get_sizer(), 0, wxEXPAND | wxTOP | wxBOTTOM, wxOSX ? 1 : margin_5); + // Search combobox + p->search_cb = new SearchComboBox(p->scrolled); + p->sizer_params->Add(p->search_cb, 0, wxEXPAND | wxTOP | wxBOTTOM, wxOSX ? 1 : margin_5); + // Object List p->object_list = new ObjectList(p->scrolled); p->sizer_params->Add(p->object_list->get_sizer(), 1, wxEXPAND); @@ -1341,6 +1347,23 @@ bool Sidebar::is_multifilament() return p->combos_filament.size() > 1; } +static std::vector get_search_inputs(ConfigOptionMode mode) +{ + std::vector ret {}; + + auto& tabs_list = wxGetApp().tabs_list; + auto print_tech = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology(); + for (auto tab : tabs_list) + if (tab->supports_printer_technology(print_tech)) + ret.emplace_back(SearchInput{tab->get_config(), tab->type(), mode}); + + return ret; +} + +void Sidebar::update_search_list() +{ + p->search_cb->init(get_search_inputs(m_mode)); +} void Sidebar::update_mode() { @@ -1348,6 +1371,7 @@ void Sidebar::update_mode() update_reslice_btn_tooltip(); update_mode_sizer(); + update_search_list(); wxWindowUpdateLocker noUpdates(this); @@ -3650,13 +3674,17 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) // update plater with new config wxGetApp().plater()->on_config_change(wxGetApp().preset_bundle->full_config()); + if (preset_type == Preset::TYPE_PRINTER) { /* Settings list can be changed after printer preset changing, so * update all settings items for all item had it. * Furthermore, Layers editing is implemented only for FFF printers * and for SLA presets they should be deleted */ - if (preset_type == Preset::TYPE_PRINTER) wxGetApp().obj_list()->update_object_list_by_printer_technology(); + + // print technology could be changed, so we should to update a search list + sidebar->update_search_list(); + } } void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index f737cf59a..9fff172a3 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -125,6 +125,7 @@ public: bool show_export_removable(bool show) const; bool is_multifilament(); void update_mode(); + void update_search_list(); std::vector& combos_filament(); private: diff --git a/src/slic3r/GUI/SearchComboBox.cpp b/src/slic3r/GUI/SearchComboBox.cpp new file mode 100644 index 000000000..b17643bc9 --- /dev/null +++ b/src/slic3r/GUI/SearchComboBox.cpp @@ -0,0 +1,211 @@ +#include "SearchComboBox.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "libslic3r/PrintConfig.hpp" +#include "GUI_App.hpp" +#include "Tab.hpp" +#include "PresetBundle.hpp" + +using boost::optional; + +namespace Slic3r { +namespace GUI { + +bool SearchOptions::Option::containes(const wxString& search_) const +{ + wxString search = search_.Lower(); + wxString label_ = label.Lower(); + wxString category_ = category.Lower(); + + return (opt_key.find(into_u8(search)) != std::string::npos || + label_.Find(search) != wxNOT_FOUND || + category_.Find(search) != wxNOT_FOUND); +/* */ + + auto search_str = into_u8(search); + auto pos = opt_key.find(into_u8(search)); + bool in_opt_key = pos != std::string::npos; + bool in_label = label_.Find(search) != wxNOT_FOUND; + bool in_category = category_.Find(search) != wxNOT_FOUND; + + if (in_opt_key || in_label || in_category) + return true; + return false; +} + + +template +void change_opt_key(std::string& opt_key, DynamicPrintConfig* config) +{ + T* opt_cur = static_cast(config->option(opt_key)); + if (opt_cur->values.size() > 0) + opt_key += "#" + std::to_string(0); +} + +void SearchOptions::append_options(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode) +{ + for (std::string opt_key : config->keys()) + { + const ConfigOptionDef& opt = config->def()->options.at(opt_key); + if (opt.mode > mode) + continue; + + if (type == Preset::TYPE_SLA_MATERIAL || type == Preset::TYPE_PRINTER) + switch (config->option(opt_key)->type()) + { + case coInts: change_opt_key(opt_key, config); break; + case coBools: change_opt_key(opt_key, config); break; + case coFloats: change_opt_key(opt_key, config); break; + case coStrings: change_opt_key(opt_key, config); break; + case coPercents:change_opt_key(opt_key, config); break; + case coPoints: change_opt_key(opt_key, config); break; + default: break; + } + + wxString label; + if (!opt.category.empty()) + label += _(opt.category) + " : "; + label += _(opt.full_label.empty() ? opt.label : opt.full_label); + + options.emplace(Option{ opt_key, label, opt.category, type }); + } +} + + +SearchComboBox::SearchComboBox(wxWindow *parent) : +wxBitmapComboBox(parent, wxID_ANY, "", wxDefaultPosition, wxSize(25 * wxGetApp().em_unit(), -1)), + em_unit(wxGetApp().em_unit()) +{ + SetFont(wxGetApp().normal_font()); + default_search_line = search_line = _(L("Search through options")) + dots; + bmp = ScalableBitmap(this, "search"); + +#ifdef _WIN32 + // Workaround for ignoring CBN_EDITCHANGE events, which are processed after the content of the combo box changes, so that + // the index of the item inside CBN_EDITCHANGE may no more be valid. +// EnableTextChangedEvents(false); +#endif /* _WIN32 */ + + Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &evt) { + auto selected_item = this->GetSelection(); + SearchOptions::Option* opt = reinterpret_cast(this->GetClientData(selected_item)); + wxGetApp().get_tab(opt->type)->activate_option(opt->opt_key, opt->category); + + evt.StopPropagation(); + + SuppressUpdate su(this); + this->SetValue(search_line); + }); + + Bind(wxEVT_TEXT, [this](wxCommandEvent &e) { + if (prevent_update) + return; + + if (this->IsTextEmpty()) + { + return; + } + + if (search_line != this->GetValue()) { + update_combobox(); + search_line = this->GetValue(); + } + }); + + Bind(wxEVT_KILL_FOCUS, [this](wxEvent & e) { + e.Skip(); + + SuppressUpdate su(this); + this->SetValue(search_line.IsEmpty() ? default_search_line : search_line); + }); +} + +SearchComboBox::~SearchComboBox() +{ +} + +void SearchComboBox::msw_rescale() +{ + em_unit = wxGetApp().em_unit(); + + wxSize size = wxSize(25 * em_unit, -1); + + // Set rescaled min height to correct layout + this->SetMinSize(size); + // Set rescaled size + this->SetSize(size); + + update_combobox(); +} + +void SearchComboBox::init(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode) +{ + search_list.clear(); + search_list.append_options(config, type, mode); + + update_combobox(); +} + +void SearchComboBox::init(std::vector input_values) +{ + search_list.clear(); + + for (auto i : input_values) + search_list.append_options(i.config, i.type, i.mode); + + update_combobox(); +} + +void SearchComboBox::update_combobox() +{ + wxString search_str = this->GetValue(); + if (search_str.IsEmpty() || search_str == default_search_line) + // add whole options list to the controll + append_all_items(); + else + append_items(search_str); +} + +void SearchComboBox::append_all_items() +{ + this->Clear(); + for (const SearchOptions::Option& item : search_list.options) + if (!item.label.IsEmpty()) + append(item.label, (void*)&item); + + SuppressUpdate su(this); + this->SetValue(default_search_line); +} + +void SearchComboBox::append_items(const wxString& search) +{ + this->Clear(); + + auto cmp = [](SearchOptions::Option* o1, SearchOptions::Option* o2) { return o1->label > o2->label; }; + std::set ret(cmp); + + for (const SearchOptions::Option& option : search_list.options) + if (option.containes(search)) + append(option.label, (void*)&option); + + this->Popup(); + SuppressUpdate su(this); + this->SetValue(search); + this->SetInsertionPointEnd(); +} + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/SearchComboBox.hpp b/src/slic3r/GUI/SearchComboBox.hpp new file mode 100644 index 000000000..0f8e83137 --- /dev/null +++ b/src/slic3r/GUI/SearchComboBox.hpp @@ -0,0 +1,87 @@ +#ifndef slic3r_SearchComboBox_hpp_ +#define slic3r_SearchComboBox_hpp_ + +#include +#include +#include + +#include + +#include "Preset.hpp" +#include "wxExtensions.hpp" + + +namespace Slic3r { + +namespace GUI { + +struct SearchInput +{ + DynamicPrintConfig* config {nullptr}; + Preset::Type type {Preset::TYPE_INVALID}; + ConfigOptionMode mode {comSimple}; +}; + +class SearchOptions +{ +public: + struct Option { + bool operator<(const Option& other) const { return other.label > this->label; } + bool operator>(const Option& other) const { return other.label < this->label; } + + std::string opt_key; + wxString label; + wxString category; + Preset::Type type {Preset::TYPE_INVALID}; + // wxString grope; + + bool containes(const wxString& search) const; + }; + + std::set