1 #ifndef slic3r_SearchComboBox_hpp_
2 #define slic3r_SearchComboBox_hpp_
3 
4 #include <vector>
5 #include <map>
6 
7 #include <wx/panel.h>
8 #include <wx/sizer.h>
9 #include <wx/listctrl.h>
10 
11 #include <wx/combo.h>
12 
13 #include <wx/checkbox.h>
14 #include <wx/dialog.h>
15 
16 #include "GUI_Utils.hpp"
17 #include "wxExtensions.hpp"
18 #include "libslic3r/Preset.hpp"
19 
20 
21 namespace Slic3r {
22 
23 namespace Search{
24 
25 class SearchDialog;
26 
27 struct InputInfo
28 {
29     DynamicPrintConfig* config  {nullptr};
30     Preset::Type        type    {Preset::TYPE_INVALID};
31     ConfigOptionMode    mode    {comSimple};
32 };
33 
34 struct GroupAndCategory {
35     wxString        group;
36     wxString        category;
37 };
38 
39 struct Option {
40 //    bool operator<(const Option& other) const { return other.label > this->label; }
operator <Slic3r::Search::Option41     bool operator<(const Option& other) const { return other.opt_key > this->opt_key; }
42 
43     // Fuzzy matching works at a character level. Thus matching with wide characters is a safer bet than with short characters,
44     // though for some languages (Chinese?) it may not work correctly.
45     std::wstring    opt_key;
46     Preset::Type    type {Preset::TYPE_INVALID};
47     std::wstring    label;
48     std::wstring    label_local;
49     std::wstring    group;
50     std::wstring    group_local;
51     std::wstring    category;
52     std::wstring    category_local;
53 };
54 
55 struct FoundOption {
56 	// UTF8 encoding, to be consumed by ImGUI by reference.
57     std::string     label;
58     std::string     marked_label;
59     std::string     tooltip;
60     size_t          option_idx {0};
61     int             outScore {0};
62 
63     // Returning pointers to contents of std::string members, to be used by ImGUI for rendering.
64     void get_marked_label_and_tooltip(const char** label, const char** tooltip) const;
65 };
66 
67 struct OptionViewParameters
68 {
69     bool category   {false};
70     bool english    {false};
71 
72     int  hovered_id {0};
73 };
74 
75 class OptionsSearcher
76 {
77     std::string                             search_line;
78     std::map<std::string, GroupAndCategory> groups_and_categories;
79     PrinterTechnology                       printer_technology;
80 
81     std::vector<Option>                     options {};
82     std::vector<FoundOption>                found {};
83 
84     void append_options(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode);
85 
sort_options()86     void sort_options() {
87         std::sort(options.begin(), options.end(), [](const Option& o1, const Option& o2) {
88             return o1.label < o2.label; });
89     }
sort_found()90     void sort_found() {
91         std::sort(found.begin(), found.end(), [](const FoundOption& f1, const FoundOption& f2) {
92             return f1.outScore > f2.outScore || (f1.outScore == f2.outScore && f1.label < f2.label); });
93     };
94 
options_size() const95     size_t options_size() const { return options.size(); }
found_size() const96     size_t found_size()   const { return found.size(); }
97 
98 public:
99     OptionViewParameters                    view_params;
100 
101     SearchDialog*                           search_dialog { nullptr };
102 
103     OptionsSearcher();
104     ~OptionsSearcher();
105 
106     void init(std::vector<InputInfo> input_values);
107     void apply(DynamicPrintConfig *config,
108                Preset::Type        type,
109                ConfigOptionMode    mode);
110     bool search();
111     bool search(const std::string& search, bool force = false);
112 
113     void add_key(const std::string& opt_key, const wxString& group, const wxString& category);
114 
size() const115     size_t size() const         { return found_size(); }
116 
operator [](const size_t pos) const117     const FoundOption& operator[](const size_t pos) const noexcept { return found[pos]; }
118     const Option& get_option(size_t pos_in_filter) const;
119     const Option& get_option(const std::string& opt_key) const;
120 
found_options()121     const std::vector<FoundOption>& found_options() { return found; }
get_group_and_category(const std::string & opt_key)122     const GroupAndCategory&         get_group_and_category (const std::string& opt_key) { return groups_and_categories[opt_key]; }
search_string()123     std::string& search_string() { return search_line; }
124 
set_printer_technology(PrinterTechnology pt)125     void set_printer_technology(PrinterTechnology pt) { printer_technology = pt; }
126 
sort_options_by_opt_key()127     void sort_options_by_opt_key() {
128         std::sort(options.begin(), options.end(), [](const Option& o1, const Option& o2) {
129             return o1.opt_key < o2.opt_key; });
130     }
131 };
132 
133 
134 //------------------------------------------
135 //          SearchDialog
136 //------------------------------------------
137 class SearchListModel;
138 class SearchDialog : public GUI::DPIDialog
139 {
140     wxString search_str;
141     wxString default_string;
142 
143     bool     prevent_list_events {false};
144 
145     wxTextCtrl*         search_line         { nullptr };
146     wxDataViewCtrl*     search_list         { nullptr };
147     SearchListModel*    search_list_model   { nullptr };
148     wxCheckBox*         check_category      { nullptr };
149     wxCheckBox*         check_english       { nullptr };
150 
151     OptionsSearcher*    searcher            { nullptr };
152 
153     void OnInputText(wxCommandEvent& event);
154     void OnLeftUpInTextCtrl(wxEvent& event);
155     void OnKeyDown(wxKeyEvent& event);
156 
157     void OnActivate(wxDataViewEvent& event);
158     void OnSelect(wxDataViewEvent& event);
159 
160     void OnCheck(wxCommandEvent& event);
161     void OnMotion(wxMouseEvent& event);
162     void OnLeftDown(wxMouseEvent& event);
163 
164     void update_list();
165 
166 public:
167     SearchDialog(OptionsSearcher* searcher);
~SearchDialog()168     ~SearchDialog() {}
169 
170     void Popup(wxPoint position = wxDefaultPosition);
171     void ProcessSelection(wxDataViewItem selection);
172 
173 protected:
174     void on_dpi_changed(const wxRect& suggested_rect) override;
175     void on_sys_color_changed() override;
176 };
177 
178 
179 // ----------------------------------------------------------------------------
180 // SearchListModel
181 // ----------------------------------------------------------------------------
182 
183 class SearchListModel : public wxDataViewVirtualListModel
184 {
185     std::vector<std::pair<wxString, int>>   m_values;
186     ScalableBitmap                          m_icon[5];
187 
188 public:
189     enum {
190         colIcon,
191         colMarkedText,
192         colMax
193     };
194 
195     SearchListModel(wxWindow* parent);
196 
197     // helper methods to change the model
198 
199     void Clear();
200     void Prepend(const std::string& text);
201     void msw_rescale();
202 
203     // implementation of base class virtuals to define model
204 
GetColumnCount() const205     unsigned int GetColumnCount() const override { return colMax; }
206     wxString GetColumnType(unsigned int col) const override;
207     void GetValueByRow(wxVariant& variant, unsigned int row, unsigned int col) const override;
GetAttrByRow(unsigned int row,unsigned int col,wxDataViewItemAttr & attr) const208     bool GetAttrByRow(unsigned int row, unsigned int col, wxDataViewItemAttr& attr) const override { return true; }
SetValueByRow(const wxVariant & variant,unsigned int row,unsigned int col)209     bool SetValueByRow(const wxVariant& variant, unsigned int row, unsigned int col) override { return false; }
210 };
211 
212 
213 
214 
215 } // Search namespace
216 }
217 
218 #endif //slic3r_SearchComboBox_hpp_
219