diff --git a/resources/icons/search.svg b/resources/icons/search.svg index bf97904e8..6421c7e05 100644 --- a/resources/icons/search.svg +++ b/resources/icons/search.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 7aaa1e622..bf30eb15e 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -151,8 +151,8 @@ set(SLIC3R_GUI_SOURCES GUI/DoubleSlider.hpp GUI/ObjectDataViewModel.cpp GUI/ObjectDataViewModel.hpp - GUI/SearchComboBox.cpp - GUI/SearchComboBox.hpp + GUI/Search.cpp + GUI/Search.hpp Utils/Http.cpp Utils/Http.hpp Utils/FixModelByWin10.cpp diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 470aafe23..0f9d49281 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4477,7 +4477,7 @@ bool GLCanvas3D::_render_search_list(float pos_x) const std::string& search_line = wxGetApp().sidebar().get_search_line(); char *s = new char[255]; - strcpy(s, search_line.empty() ? _utf8(L("Type here to search")).c_str() : search_line.c_str()); + strcpy(s, search_line.empty() ? _u8L("Type here to search").c_str() : search_line.c_str()); imgui->search_list(ImVec2(22 * em, 30 * em), &search_string_getter, s, selected, edited); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d270b6e0d..acf762bfb 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -80,7 +80,6 @@ #include "../Utils/FixModelByWin10.hpp" #include "../Utils/UndoRedo.hpp" #include "RemovableDriveManager.hpp" -#include "SearchComboBox.hpp" #if ENABLE_NON_STATIC_CANVAS_MANAGER #ifdef __APPLE__ @@ -1095,6 +1094,7 @@ void Sidebar::msw_rescale() void Sidebar::apply_search_filter() { p->search_list.apply_filters(p->search_line); + apply_search_line_on_tabs(); } void Sidebar::jump_to_option(size_t selected) @@ -1373,16 +1373,21 @@ static std::vector get_search_inputs(ConfigOptionMode mode) return ret; } -void Sidebar::update_search_list() +void Sidebar::apply_search_line_on_tabs() { - p->search_list.init(get_search_inputs(m_mode)); - 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)) - tab->get_search_cb()->init(p->search_list); + //tab->get_search_cb()->update_combobox(); + tab->set_search_line(p->search_line); +} + +void Sidebar::update_search_list() +{ + p->search_list.init(get_search_inputs(m_mode)); + apply_search_line_on_tabs(); } void Sidebar::update_mode() @@ -5345,7 +5350,7 @@ bool Plater::search_string_getter(int idx, const char** out_text) const SearchOptions& search_list = p->sidebar->get_search_list(); if (0 <= idx && (size_t)idx < search_list.size()) { - search_list[idx].get_label(out_text); + search_list[idx].get_marked_label(out_text); return true; } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 1fb0eab30..6544d4554 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -12,7 +12,7 @@ #include "libslic3r/BoundingBox.hpp" #include "wxExtensions.hpp" -#include "SearchComboBox.hpp" +#include "Search.hpp" class wxButton; class ScalableButton; @@ -132,6 +132,7 @@ public: void update_mode(); bool is_collapsed(); void collapse(bool collapse); + void apply_search_line_on_tabs(); void update_search_list(); std::vector& combos_filament(); diff --git a/src/slic3r/GUI/SearchComboBox.cpp b/src/slic3r/GUI/Search.cpp similarity index 65% rename from src/slic3r/GUI/SearchComboBox.cpp rename to src/slic3r/GUI/Search.cpp index 1e1ab738f..f3a0386b5 100644 --- a/src/slic3r/GUI/SearchComboBox.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -1,4 +1,4 @@ -#include "SearchComboBox.hpp" +#include "Search.hpp" #include #include @@ -13,8 +13,7 @@ #include #include -#include -#include +//#include #include "libslic3r/PrintConfig.hpp" #include "GUI_App.hpp" #include "Tab.hpp" @@ -77,6 +76,11 @@ void SearchOptions::Filter::get_label(const char** out_text) const *out_text = label.utf8_str(); } +void SearchOptions::Filter::get_marked_label(const char** out_text) const +{ + *out_text = marked_label.utf8_str(); +} + template void change_opt_key(std::string& opt_key, DynamicPrintConfig* config) { @@ -169,18 +173,18 @@ void SearchOptions::apply_filters(const std::string& search) for (size_t i=0; i < options.size(); i++) { if (full_list) { - filters.emplace_back(Filter{ options[i].label, i, 0 }); + filters.emplace_back(Filter{ options[i].label, options[i].label, i, 0 }); continue; } int score = 0; if (options[i].fuzzy_match_simple(search)/*fuzzy_match(search, score)*/) { - wxString label = options[i].label; - mark_string(label, from_u8(search)); - clear_marked_string(label); + wxString marked_label = options[i].label; + mark_string(marked_label, from_u8(search)); + clear_marked_string(marked_label); - filters.emplace_back(Filter{ label, i, score }); + filters.emplace_back(Filter{ options[i].label, marked_label, i, score }); } } @@ -203,23 +207,24 @@ const SearchOptions::Option& SearchOptions::get_option(size_t pos_in_filter) con assert(pos_in_filter != size_t(-1) && filters[pos_in_filter].option_idx != size_t(-1)); return options[filters[pos_in_filter].option_idx]; } - -SearchComboBox::SearchComboBox(wxWindow *parent) : +/* +SearchComboBox::SearchComboBox(wxWindow *parent, SearchOptions& search_list) : wxBitmapComboBox(parent, wxID_ANY, _(L("Type here to search")) + dots, wxDefaultPosition, wxSize(25 * wxGetApp().em_unit(), -1)), - em_unit(wxGetApp().em_unit()) + em_unit(wxGetApp().em_unit()), + search_list(search_list) { SetFont(wxGetApp().normal_font()); default_search_line = search_line = _(L("Type here to search")) + 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(); + if (selected_item < 0) + return; + + wxGetApp().sidebar().jump_to_option(selected_item); + + return; SearchOptions::Option* opt = reinterpret_cast(this->GetClientData(selected_item)); wxGetApp().get_tab(opt->type)->activate_option(opt->opt_key, opt->category); @@ -230,7 +235,7 @@ wxBitmapComboBox(parent, wxID_ANY, _(L("Type here to search")) + dots, wxDefault }); Bind(wxEVT_TEXT, [this](wxCommandEvent &e) { - if (prevent_update) +/* if (prevent_update) return; if (this->IsTextEmpty()) @@ -238,7 +243,10 @@ wxBitmapComboBox(parent, wxID_ANY, _(L("Type here to search")) + dots, wxDefault return; } - if (search_line != this->GetValue()) { + * / if (search_line != this->GetValue()) { + std::string& search_str = wxGetApp().sidebar().get_search_line(); + search_str = into_u8(this->GetValue()); + wxGetApp().sidebar().apply_search_filter(); update_combobox(); search_line = this->GetValue(); } @@ -293,6 +301,14 @@ void SearchComboBox::init(const SearchOptions& new_search_list) void SearchComboBox::update_combobox() { + this->Clear(); + for (const SearchOptions::Filter& item : search_list.filters) + append(item.label); + +// SuppressUpdate su(this); +// this->SetValue(default_search_line); + + return; wxString search_str = this->GetValue(); if (search_str.IsEmpty() || search_str == default_search_line) // add whole options list to the controll @@ -322,7 +338,7 @@ void SearchComboBox::append_items(const wxString& search) if (it != search_list.options.end()) append(it->label, (void*)(&(*it))); } -*/ +* / for (const SearchOptions::Option& option : search_list.options) if (option.fuzzy_match_simple(search)) @@ -332,5 +348,153 @@ void SearchComboBox::append_items(const wxString& search) this->SetValue(search); this->SetInsertionPointEnd(); } +*/ + +//------------------------------------------ +// PopupSearchList +//------------------------------------------ + +PopupSearchList::PopupSearchList(wxWindow* parent) : + wxPopupTransientWindow(parent) +{ + panel = new wxPanel(this, wxID_ANY); + + int em_unit = wxGetApp().em_unit(); + + search_ctrl = new wxListCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(25 * em_unit, 35 * em_unit), wxLC_NO_HEADER | wxLC_REPORT); + search_ctrl->AppendColumn(""); + search_ctrl->SetColumnWidth(0, 23 * em_unit); + search_ctrl->Bind(wxEVT_LIST_ITEM_SELECTED, &PopupSearchList::OnSelect, this); + + wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL); + + topSizer->Add(search_ctrl, 0, wxEXPAND | wxALL, 2); + + panel->SetSizer(topSizer); + + topSizer->Fit(panel); + SetClientSize(panel->GetSize()); +} + +void PopupSearchList::Popup(wxWindow* WXUNUSED(focus)) +{ + wxPopupTransientWindow::Popup(); +} + +void PopupSearchList::OnDismiss() +{ + wxPopupTransientWindow::OnDismiss(); +} + +bool PopupSearchList::ProcessLeftDown(wxMouseEvent& event) +{ + return wxPopupTransientWindow::ProcessLeftDown(event); +} +bool PopupSearchList::Show(bool show) +{ + return wxPopupTransientWindow::Show(show); +} + +void PopupSearchList::OnSize(wxSizeEvent& event) +{ + event.Skip(); +} + +void PopupSearchList::OnSetFocus(wxFocusEvent& event) +{ + event.Skip(); +} + +void PopupSearchList::OnKillFocus(wxFocusEvent& event) +{ + event.Skip(); +} + +void PopupSearchList::OnSelect(wxListEvent& event) +{ + int selection = event.GetIndex(); + if (selection>=0) + wxGetApp().sidebar().jump_to_option(selection); + + OnDismiss(); +} + +void PopupSearchList::update_list(std::vector& filters) +{ + search_ctrl->DeleteAllItems(); + for (const SearchOptions::Filter& item : filters) + search_ctrl->InsertItem(search_ctrl->GetItemCount(), item.label); +} + + +//------------------------------------------ +// SearchCtrl +//------------------------------------------ + +SearchCtrl::SearchCtrl(wxWindow* parent): + parent(parent) +{ + popup_win = new PopupSearchList(parent); + box_sizer = new wxBoxSizer(wxHORIZONTAL); + + search_line = new wxTextCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(25 * wxGetApp().em_unit(), -1), wxTE_PROCESS_ENTER); + search_line->Bind(wxEVT_TEXT, &SearchCtrl::OnInputText, this); + search_line->Bind(wxEVT_TEXT_ENTER, &SearchCtrl::PopupList, this); + + search_btn = new ScalableButton(parent, wxID_ANY, "search"); + search_btn->Bind(wxEVT_BUTTON, &SearchCtrl::PopupList, this); + + box_sizer->Add(search_line, 0, wxALIGN_CENTER_VERTICAL); + box_sizer->AddSpacer(5); + box_sizer->Add(search_btn, 0, wxALIGN_CENTER_VERTICAL); +} + +SearchCtrl::~SearchCtrl() +{ + if (search_btn) + search_btn->Destroy(); + if (popup_win) + popup_win->Destroy(); +} + +void SearchCtrl::OnInputText(wxCommandEvent& ) +{ + if (prevent_update) + return; + std::string& search_str = wxGetApp().sidebar().get_search_line(); + search_str = into_u8(search_line->GetValue()); + wxGetApp().sidebar().apply_search_filter(); + + popup_win->update_list(wxGetApp().sidebar().get_search_list().filters); +} + +void SearchCtrl::PopupList(wxCommandEvent& ) +{ + popup_win->update_list(wxGetApp().sidebar().get_search_list().filters); + + wxPoint pos = search_line->ClientToScreen(wxPoint(0, 0)); + wxSize sz = search_line->GetSize(); + pos.x -= sz.GetWidth(); + popup_win->Position(pos, sz); + + popup_win->Popup(); +} + +void SearchCtrl::set_search_line(const std::string& line) +{ + prevent_update = true; + search_line->SetValue(line.empty() ? _L("Type here to search") : from_u8(line)); + prevent_update = false; +} + +void SearchCtrl::msw_rescale() +{ + wxSize size = wxSize(25 * wxGetApp().em_unit(), -1); + // Set rescaled min height to correct layout + search_line->SetMinSize(size); + // Set rescaled size + search_btn->msw_rescale(); +} + }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/SearchComboBox.hpp b/src/slic3r/GUI/Search.hpp similarity index 67% rename from src/slic3r/GUI/SearchComboBox.hpp rename to src/slic3r/GUI/Search.hpp index 294395b72..6718f3af1 100644 --- a/src/slic3r/GUI/SearchComboBox.hpp +++ b/src/slic3r/GUI/Search.hpp @@ -1,11 +1,13 @@ #ifndef slic3r_SearchComboBox_hpp_ #define slic3r_SearchComboBox_hpp_ -#include #include -#include -#include +#include +#include +//#include +#include +#include #include "Preset.hpp" #include "wxExtensions.hpp" @@ -46,15 +48,20 @@ public: struct Filter { wxString label; + wxString marked_label; size_t option_idx {0}; int outScore {0}; void get_label(const char** out_text) const; + void get_marked_label(const char** out_text) const; }; std::vector filters {}; void clear_options() { options.clear(); } void clear_filters() { filters.clear(); } + + void init(std::vector input_values); + void append_options(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode); void apply_filters(const std::string& search); @@ -67,16 +74,14 @@ public: return f1.outScore > f2.outScore; }); }; - void init(std::vector input_values); size_t options_size() const { return options.size(); } size_t filters_size() const { return filters.size(); } - size_t size() const { return filters_size(); } const Filter& operator[](const size_t pos) const noexcept { return filters[pos]; } const Option& get_option(size_t pos_in_filter) const; }; - +/* class SearchComboBox : public wxBitmapComboBox { class SuppressUpdate @@ -89,9 +94,10 @@ class SearchComboBox : public wxBitmapComboBox }; public: - SearchComboBox(wxWindow *parent); + SearchComboBox(wxWindow *parent, SearchOptions& search_list); ~SearchComboBox(); + int append(const wxString& item) { return Append(item, bmp.bmp()); } int append(const wxString& item, void* clientData) { return Append(item, bmp.bmp(), clientData); } int append(const wxString& item, wxClientData* clientData) { return Append(item, bmp.bmp(), clientData); } @@ -105,8 +111,9 @@ public: void init(const SearchOptions& new_search_list); void update_combobox(); + private: - SearchOptions search_list; + SearchOptions& search_list; wxString default_search_line; wxString search_line; @@ -115,6 +122,53 @@ private: ScalableBitmap bmp; }; +*/ +class PopupSearchList : public wxPopupTransientWindow +{ +public: + PopupSearchList(wxWindow* parent); + ~PopupSearchList() {} + + // wxPopupTransientWindow virtual methods are all overridden to log them + void Popup(wxWindow* focus = NULL) wxOVERRIDE; + void OnDismiss() wxOVERRIDE; + bool ProcessLeftDown(wxMouseEvent& event) wxOVERRIDE; + bool Show(bool show = true) wxOVERRIDE; + + void update_list(std::vector& filters); + +private: + wxWindow* panel; + wxListCtrl* search_ctrl{ nullptr }; + + void OnSize(wxSizeEvent& event); + void OnSetFocus(wxFocusEvent& event); + void OnKillFocus(wxFocusEvent& event); + void OnSelect(wxListEvent& event); +}; + +class SearchCtrl +{ + wxWindow* parent {nullptr}; + wxBoxSizer* box_sizer {nullptr}; + wxTextCtrl* search_line {nullptr}; + ScalableButton* search_btn {nullptr}; + PopupSearchList* popup_win {nullptr}; + + bool prevent_update{ false }; + + void PopupList(wxCommandEvent& event); + void OnInputText(wxCommandEvent& event); + +public: + SearchCtrl(wxWindow* parent); + ~SearchCtrl(); + + wxBoxSizer* sizer() const { return box_sizer; } + + void set_search_line(const std::string& search_line); + void msw_rescale(); +}; }} diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 16ee6a789..17bb68d02 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -116,7 +116,8 @@ void Tab::create_preset_tab() m_presets_choice = new PresetBitmapComboBox(panel, wxSize(35 * m_em_unit, -1)); // search combox - m_search_cb = new SearchComboBox(panel); +// m_search_cb = new SearchComboBox(panel, wxGetApp().sidebar().get_search_list()); + m_search = new SearchCtrl(panel); auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); @@ -198,7 +199,8 @@ void Tab::create_preset_tab() m_hsizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->AddSpacer(int(/*32*/16 * scale_factor)); - m_hsizer->Add(m_search_cb, 0, wxALIGN_CENTER_VERTICAL); +// m_hsizer->Add(m_search_cb, 0, wxALIGN_CENTER_VERTICAL); + m_hsizer->Add(m_search->sizer(), 0, wxALIGN_CENTER_VERTICAL); m_hsizer->AddSpacer(int(16 * scale_factor)); // m_hsizer->AddSpacer(int(32 * scale_factor)); // m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL); @@ -767,9 +769,6 @@ void Tab::update_mode() update_visibility(); update_changed_tree_ui(); - - // update list of options for search -// m_search_cb->init(m_config, type(), m_mode); } void Tab::update_visibility() @@ -796,7 +795,8 @@ void Tab::msw_rescale() m_em_unit = wxGetApp().em_unit(); m_mode_sizer->msw_rescale(); - m_search_cb->msw_rescale(); +// m_search_cb->msw_rescale(); + m_search->msw_rescale(); m_presets_choice->SetSize(35 * m_em_unit, -1); m_treectrl->SetMinSize(wxSize(20 * m_em_unit, -1)); @@ -899,6 +899,11 @@ static wxString pad_combo_value_for_config(const DynamicPrintConfig &config) return config.opt_bool("pad_enable") ? (config.opt_bool("pad_around_object") ? _("Around object") : _("Below object")) : _("None"); } +void Tab::set_search_line(const std::string& search_line) +{ + m_search->set_search_line(search_line); +} + void Tab::on_value_change(const std::string& opt_key, const boost::any& value) { if (wxGetApp().plater() == nullptr) { diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 705a806a3..fe683b49f 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -33,7 +33,7 @@ #include "Event.hpp" #include "wxExtensions.hpp" #include "ConfigManipulation.hpp" -#include "SearchComboBox.hpp" +#include "Search.hpp" namespace Slic3r { namespace GUI { @@ -122,7 +122,8 @@ protected: std::string m_name; const wxString m_title; PresetBitmapComboBox* m_presets_choice; - SearchComboBox* m_search_cb; +// SearchComboBox* m_search_cb; + SearchCtrl* m_search; ScalableButton* m_btn_save_preset; ScalableButton* m_btn_delete_preset; ScalableButton* m_btn_hide_incompatible_presets; @@ -308,9 +309,11 @@ public: DynamicPrintConfig* get_config() { return m_config; } PresetCollection* get_presets() { return m_presets; } - SearchComboBox* get_search_cb() { return m_search_cb; } +// SearchComboBox* get_search_cb() { return m_search_cb; } size_t get_selected_preset_item() { return m_selected_preset_item; } + void set_search_line(const std::string& search_line); + void on_value_change(const std::string& opt_key, const boost::any& value); void update_wiping_button_visibility();