Implemented cursor movement inside SearchComboPopup
+ Added checkboxes for editing of the option's name (include "Group"/"Category" or not) + some code refactoring
This commit is contained in:
parent
167f7cf5de
commit
45147d887b
7 changed files with 152 additions and 50 deletions
|
@ -4480,28 +4480,39 @@ bool GLCanvas3D::_render_search_list(float pos_x) const
|
||||||
|
|
||||||
size_t selected = size_t(-1);
|
size_t selected = size_t(-1);
|
||||||
bool edited = false;
|
bool edited = false;
|
||||||
|
bool check_changed = false;
|
||||||
float em = static_cast<float>(wxGetApp().em_unit());
|
float em = static_cast<float>(wxGetApp().em_unit());
|
||||||
#if ENABLE_RETINA_GL
|
#if ENABLE_RETINA_GL
|
||||||
em *= m_retina_helper->get_scale_factor();
|
em *= m_retina_helper->get_scale_factor();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string& search_line = wxGetApp().sidebar().get_search_line();
|
Sidebar& sidebar = wxGetApp().sidebar();
|
||||||
|
|
||||||
|
std::string& search_line = sidebar.get_search_line();
|
||||||
char *s = new char[255];
|
char *s = new char[255];
|
||||||
strcpy(s, search_line.empty() ? _u8L("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(45 * em, 30 * em), &search_string_getter, s, selected, edited);
|
imgui->search_list(ImVec2(45 * em, 30 * em), &search_string_getter, s,
|
||||||
|
sidebar.get_searcher().category, sidebar.get_searcher().group,
|
||||||
|
selected, edited, check_changed);
|
||||||
|
|
||||||
search_line = s;
|
search_line = s;
|
||||||
delete [] s;
|
delete [] s;
|
||||||
|
|
||||||
if (edited)
|
if (edited)
|
||||||
wxGetApp().sidebar().search_and_apply_tab_search_lines();
|
sidebar.search_and_apply_tab_search_lines();
|
||||||
|
|
||||||
|
if (check_changed) {
|
||||||
|
if (search_line == _u8L("Type here to search"))
|
||||||
|
search_line.clear();
|
||||||
|
sidebar.search_and_apply_tab_search_lines(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (selected != size_t(-1))
|
if (selected != size_t(-1))
|
||||||
{
|
{
|
||||||
// selected == 9999 means that Esc kye was pressed
|
// selected == 9999 means that Esc kye was pressed
|
||||||
if (selected != 9999)
|
if (selected != 9999)
|
||||||
wxGetApp().sidebar().jump_to_option(selected);
|
sidebar.jump_to_option(selected);
|
||||||
action_taken = true;
|
action_taken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
|
#include "I18N.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
@ -538,7 +539,8 @@ static bool selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, const char**), char* search_str, size_t& selected, bool& edited)
|
void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, const char**), char* search_str,
|
||||||
|
bool& category, bool& group, size_t& selected, bool& edited, bool& check_changed)
|
||||||
{
|
{
|
||||||
// ImGui::ListBoxHeader("", size);
|
// ImGui::ListBoxHeader("", size);
|
||||||
{
|
{
|
||||||
|
@ -604,6 +606,23 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::ListBoxFooter();
|
ImGui::ListBoxFooter();
|
||||||
|
|
||||||
|
// add checkboxes for show/hide Categories and Groups
|
||||||
|
text(_L("Use for search")+":");
|
||||||
|
ImGui::SameLine();
|
||||||
|
bool cat = category;
|
||||||
|
checkbox(_L("Category"), cat);
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
category = !category;
|
||||||
|
check_changed = true;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
bool gr = group;
|
||||||
|
checkbox(_L("Group"), gr);
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
group = !group;
|
||||||
|
check_changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiWrapper::disabled_begin(bool disabled)
|
void ImGuiWrapper::disabled_begin(bool disabled)
|
||||||
|
|
|
@ -74,7 +74,8 @@ public:
|
||||||
bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
|
bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
|
||||||
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection); // Use -1 to not mark any option as selected
|
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection); // Use -1 to not mark any option as selected
|
||||||
bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected);
|
bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected);
|
||||||
void search_list(const ImVec2& size, bool (*items_getter)(int, const char**), char* search_str, size_t& selected, bool& edited);
|
void search_list(const ImVec2& size, bool (*items_getter)(int, const char**), char* search_str,
|
||||||
|
bool& category, bool& group, size_t& selected, bool& edited, bool& check_changed);
|
||||||
|
|
||||||
void disabled_begin(bool disabled);
|
void disabled_begin(bool disabled);
|
||||||
void disabled_end();
|
void disabled_end();
|
||||||
|
|
|
@ -1091,9 +1091,9 @@ void Sidebar::msw_rescale()
|
||||||
p->scrolled->Layout();
|
p->scrolled->Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sidebar::search_and_apply_tab_search_lines()
|
void Sidebar::search_and_apply_tab_search_lines(bool force/* = false*/)
|
||||||
{
|
{
|
||||||
if (p->searcher.search(p->search_line))
|
if (p->searcher.search(p->search_line, force))
|
||||||
apply_search_line_on_tabs();
|
apply_search_line_on_tabs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ public:
|
||||||
void update_mode_sizer() const;
|
void update_mode_sizer() const;
|
||||||
void update_reslice_btn_tooltip() const;
|
void update_reslice_btn_tooltip() const;
|
||||||
void msw_rescale();
|
void msw_rescale();
|
||||||
void search_and_apply_tab_search_lines();
|
void search_and_apply_tab_search_lines(bool force = false);
|
||||||
void jump_to_option(size_t selected);
|
void jump_to_option(size_t selected);
|
||||||
|
|
||||||
ObjectManipulation* obj_manipul();
|
ObjectManipulation* obj_manipul();
|
||||||
|
|
|
@ -186,11 +186,22 @@ bool OptionsSearcher::search(const std::string& search, bool force/* = false*/)
|
||||||
|
|
||||||
bool full_list = search.empty();
|
bool full_list = search.empty();
|
||||||
|
|
||||||
|
auto get_label = [this](const Option& opt)
|
||||||
|
{
|
||||||
|
wxString label;
|
||||||
|
if (category)
|
||||||
|
label += opt.category_local + " > ";
|
||||||
|
if (group)
|
||||||
|
label += opt.group_local + " > ";
|
||||||
|
label += opt.label_local;
|
||||||
|
return label;
|
||||||
|
};
|
||||||
|
|
||||||
for (size_t i=0; i < options.size(); i++)
|
for (size_t i=0; i < options.size(); i++)
|
||||||
{
|
{
|
||||||
const Option &opt = options[i];
|
const Option &opt = options[i];
|
||||||
if (full_list) {
|
if (full_list) {
|
||||||
wxString label = opt.category_local + " > " + opt.group_local + " > " + opt.label_local;
|
wxString label = get_label(opt);
|
||||||
found.emplace_back(FoundOption{ label, label, i, 0 });
|
found.emplace_back(FoundOption{ label, label, i, 0 });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +211,8 @@ bool OptionsSearcher::search(const std::string& search, bool force/* = false*/)
|
||||||
FMFlag fuzzy_match_flag = opt.fuzzy_match(search, score);
|
FMFlag fuzzy_match_flag = opt.fuzzy_match(search, score);
|
||||||
if (fuzzy_match_flag != fmUndef)
|
if (fuzzy_match_flag != fmUndef)
|
||||||
{
|
{
|
||||||
wxString label = opt.category_local + " > " + opt.group_local + " > " + opt.label_local;
|
wxString label = get_label(opt); //opt.category_local + " > " + opt.group_local + " > " + opt.label_local;
|
||||||
|
|
||||||
if ( fuzzy_match_flag == fmLabel ) label += "(" + opt.label + ")";
|
if ( fuzzy_match_flag == fmLabel ) label += "(" + opt.label + ")";
|
||||||
else if (fuzzy_match_flag == fmGroup ) label += "(" + opt.group + ")";
|
else if (fuzzy_match_flag == fmGroup ) label += "(" + opt.group + ")";
|
||||||
else if (fuzzy_match_flag == fmCategory) label += "(" + opt.category + ")";
|
else if (fuzzy_match_flag == fmCategory) label += "(" + opt.category + ")";
|
||||||
|
@ -243,6 +255,81 @@ void OptionsSearcher::add_key(const std::string& opt_key, const wxString& group,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
// SearchComboPopup
|
||||||
|
//------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
void SearchComboPopup::Init()
|
||||||
|
{
|
||||||
|
this->Bind(wxEVT_MOTION, &SearchComboPopup::OnMouseMove, this);
|
||||||
|
this->Bind(wxEVT_LEFT_UP, &SearchComboPopup::OnMouseClick, this);
|
||||||
|
this->Bind(wxEVT_KEY_DOWN, &SearchComboPopup::OnKeyDown, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SearchComboPopup::Create(wxWindow* parent)
|
||||||
|
{
|
||||||
|
return wxListBox::Create(parent, 1, wxPoint(0, 0), wxDefaultSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchComboPopup::SetStringValue(const wxString& s)
|
||||||
|
{
|
||||||
|
int n = wxListBox::FindString(s);
|
||||||
|
if (n >= 0 && n < wxListBox::GetCount())
|
||||||
|
wxListBox::Select(n);
|
||||||
|
|
||||||
|
// save a combo control's string
|
||||||
|
m_input_string = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchComboPopup::ProcessSelection(int selection)
|
||||||
|
{
|
||||||
|
wxCommandEvent event(wxEVT_LISTBOX, GetId());
|
||||||
|
event.SetInt(selection);
|
||||||
|
event.SetEventObject(this);
|
||||||
|
ProcessEvent(event);
|
||||||
|
|
||||||
|
Dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchComboPopup::OnMouseMove(wxMouseEvent& event)
|
||||||
|
{
|
||||||
|
wxPoint pt = wxGetMousePosition() - this->GetScreenPosition();
|
||||||
|
int selection = this->HitTest(pt);
|
||||||
|
wxListBox::Select(selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchComboPopup::OnMouseClick(wxMouseEvent&)
|
||||||
|
{
|
||||||
|
int selection = wxListBox::GetSelection();
|
||||||
|
SetSelection(wxNOT_FOUND);
|
||||||
|
ProcessSelection(selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchComboPopup::OnKeyDown(wxKeyEvent& event)
|
||||||
|
{
|
||||||
|
int key = event.GetKeyCode();
|
||||||
|
|
||||||
|
// change selected item in the list
|
||||||
|
if (key == WXK_UP || key == WXK_DOWN)
|
||||||
|
{
|
||||||
|
int selection = wxListBox::GetSelection();
|
||||||
|
|
||||||
|
if (key == WXK_UP && selection > 0)
|
||||||
|
selection--;
|
||||||
|
int last_item_id = int(wxListBox::GetCount() - 1);
|
||||||
|
if (key == WXK_DOWN && selection < int(wxListBox::GetCount() - 1))
|
||||||
|
selection++;
|
||||||
|
|
||||||
|
wxListBox::Select(selection);
|
||||||
|
}
|
||||||
|
// send wxEVT_LISTBOX event if "Enter" was pushed
|
||||||
|
else if (key == WXK_NUMPAD_ENTER || key == WXK_RETURN)
|
||||||
|
ProcessSelection(wxListBox::GetSelection());
|
||||||
|
else
|
||||||
|
event.Skip(); // !Needed to have EVT_CHAR generated as well
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------
|
//------------------------------------------
|
||||||
// SearchCtrl
|
// SearchCtrl
|
||||||
//------------------------------------------
|
//------------------------------------------
|
||||||
|
@ -266,7 +353,12 @@ SearchCtrl::SearchCtrl(wxWindow* parent) :
|
||||||
this->Bind(wxEVT_TEXT, &SearchCtrl::OnInputText, this);
|
this->Bind(wxEVT_TEXT, &SearchCtrl::OnInputText, this);
|
||||||
this->Bind(wxEVT_TEXT_ENTER, &SearchCtrl::PopupList, this);
|
this->Bind(wxEVT_TEXT_ENTER, &SearchCtrl::PopupList, this);
|
||||||
this->Bind(wxEVT_COMBOBOX_DROPDOWN, &SearchCtrl::PopupList, this);
|
this->Bind(wxEVT_COMBOBOX_DROPDOWN, &SearchCtrl::PopupList, this);
|
||||||
|
/*
|
||||||
|
this->Bind(wxEVT_KEY_DOWN, [this](wxKeyEvent&e)
|
||||||
|
{
|
||||||
|
|
||||||
|
});
|
||||||
|
*/
|
||||||
this->GetTextCtrl()->Bind(wxEVT_LEFT_UP, &SearchCtrl::OnLeftUpInTextCtrl, this);
|
this->GetTextCtrl()->Bind(wxEVT_LEFT_UP, &SearchCtrl::OnLeftUpInTextCtrl, this);
|
||||||
popupListBox->Bind(wxEVT_LISTBOX, &SearchCtrl::OnSelect, this);
|
popupListBox->Bind(wxEVT_LISTBOX, &SearchCtrl::OnSelect, this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,9 @@ class OptionsSearcher
|
||||||
size_t found_size() const { return found.size(); }
|
size_t found_size() const { return found.size(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool category{ false };
|
||||||
|
bool group{ true };
|
||||||
|
|
||||||
void init(std::vector<InputInfo> input_values);
|
void init(std::vector<InputInfo> input_values);
|
||||||
bool search(const std::string& search, bool force = false);
|
bool search(const std::string& search, bool force = false);
|
||||||
|
|
||||||
|
@ -115,54 +118,30 @@ class SearchComboPopup : public wxListBox, public wxComboPopup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Initialize member variables
|
// Initialize member variables
|
||||||
virtual void Init()
|
void Init();
|
||||||
{
|
|
||||||
this->Bind(wxEVT_MOTION, &SearchComboPopup::OnMouseMove, this);
|
|
||||||
this->Bind(wxEVT_LEFT_UP, &SearchComboPopup::OnMouseClick, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create popup control
|
// Create popup control
|
||||||
virtual bool Create(wxWindow* parent)
|
virtual bool Create(wxWindow* parent);
|
||||||
{
|
|
||||||
return wxListBox::Create(parent, 1, wxPoint(0, 0), wxDefaultSize);
|
|
||||||
}
|
|
||||||
// Return pointer to the created control
|
// Return pointer to the created control
|
||||||
virtual wxWindow* GetControl() { return this; }
|
virtual wxWindow* GetControl() { return this; }
|
||||||
// Translate string into a list selection
|
|
||||||
virtual void SetStringValue(const wxString& s)
|
|
||||||
{
|
|
||||||
int n = wxListBox::FindString(s);
|
|
||||||
if (n >= 0 && n < wxListBox::GetCount())
|
|
||||||
wxListBox::Select(n);
|
|
||||||
|
|
||||||
// save a combo control's string
|
// Translate string into a list selection
|
||||||
m_input_string = s;
|
virtual void SetStringValue(const wxString& s);
|
||||||
}
|
|
||||||
// Get list selection as a string
|
// Get list selection as a string
|
||||||
virtual wxString GetStringValue() const
|
virtual wxString GetStringValue() const {
|
||||||
{
|
|
||||||
// we shouldn't change a combo control's string
|
// we shouldn't change a combo control's string
|
||||||
return m_input_string;
|
return m_input_string;
|
||||||
}
|
}
|
||||||
// Do mouse hot-tracking (which is typical in list popups)
|
|
||||||
void OnMouseMove(wxMouseEvent& event)
|
|
||||||
{
|
|
||||||
wxPoint pt = wxGetMousePosition() - this->GetScreenPosition();
|
|
||||||
int selection = this->HitTest(pt);
|
|
||||||
wxListBox::Select(selection);
|
|
||||||
}
|
|
||||||
// On mouse left up, set the value and close the popup
|
|
||||||
void OnMouseClick(wxMouseEvent& WXUNUSED(event))
|
|
||||||
{
|
|
||||||
int selection = wxListBox::GetSelection();
|
|
||||||
SetSelection(wxNOT_FOUND);
|
|
||||||
wxCommandEvent event(wxEVT_LISTBOX, GetId());
|
|
||||||
event.SetInt(selection);
|
|
||||||
event.SetEventObject(this);
|
|
||||||
ProcessEvent(event);
|
|
||||||
|
|
||||||
Dismiss();
|
void ProcessSelection(int selection);
|
||||||
}
|
|
||||||
|
// Do mouse hot-tracking (which is typical in list popups)
|
||||||
|
void OnMouseMove(wxMouseEvent& event);
|
||||||
|
// On mouse left up, set the value and close the popup
|
||||||
|
void OnMouseClick(wxMouseEvent& WXUNUSED(event));
|
||||||
|
// process Up/Down arrows and Enter press
|
||||||
|
void OnKeyDown(wxKeyEvent& event);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxString m_input_string;
|
wxString m_input_string;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue