diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4e2e33570f..20dd49afcb 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -380,7 +380,6 @@ struct Sidebar::priv ~priv(); void show_preset_comboboxes(); - void on_search_update(); void jump_to_object(ObjectDataViewModelNode* item); void can_search(); @@ -423,15 +422,6 @@ void Sidebar::priv::show_preset_comboboxes() scrolled->Refresh(); } -void Sidebar::priv::on_search_update() -{ - m_object_list->assembly_plate_object_name(); - - wxString search_text = m_search_item->GetTextCtrl()->GetValue(); - m_object_list->GetModel()->search_object(search_text); - dia->update_list(); -} - void Sidebar::priv::jump_to_object(ObjectDataViewModelNode* item) { m_object_list->selected_object(item); @@ -1108,23 +1098,21 @@ Sidebar::Sidebar(Plater *parent) text_ctrl->SetSize(wxSize(-1, FromDIP(16))); // Centers text vertically text_ctrl->Bind(wxEVT_SET_FOCUS, [this](wxFocusEvent& e) { - this->p->on_search_update(); + if (p->dia->IsShown()) { + e.Skip(); + return; + } p->m_search_bar->SetBorderColor(wxColour("#009688")); wxPoint pos = this->p->m_search_bar->ClientToScreen(wxPoint(0, 0)); +#ifndef __WXGTK__ pos.y += this->p->m_search_bar->GetRect().height; +#else + this->p->m_search_item->Enable(false); +#endif p->dia->SetPosition(pos); p->dia->Popup(); e.Skip(); // required to show caret }); - text_ctrl->Bind(wxEVT_COMMAND_TEXT_UPDATED, [this](wxCommandEvent&) { - this->p->on_search_update(); - }); - text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { - p->dia->Dismiss(); - p->m_search_bar->SetBorderColor(wxColour("#CECECE")); - p->m_search_item->GetTextCtrl()->SetValue(""); // reset value when loose focus - e.Skip(); - }); auto search_sizer = new wxBoxSizer(wxHORIZONTAL); search_sizer->Add(new wxWindow(p->m_search_bar, wxID_ANY, wxDefaultPosition, wxSize(0, 0)), 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(1)); @@ -1134,6 +1122,13 @@ Sidebar::Sidebar(Plater *parent) search_sizer->Fit(p->m_search_bar); p->m_object_list = new ObjectList(p->scrolled); + p->m_object_list->Bind(wxCUSTOMEVT_EXIT_SEARCH, [this](wxCommandEvent&) { +#ifdef __WXGTK__ + this->p->m_search_item->Enable(true); +#endif + this->p->m_search_bar->SetBorderColor(wxColour("#CECECE")); + this->p->m_search_item->GetTextCtrl()->SetValue(""); // reset value when close + }); p->sizer_params->Add(p->m_search_bar, 0, wxALL | wxEXPAND, 0); p->sizer_params->Add(p->m_object_list, 1, wxEXPAND | wxTOP, 0); @@ -1143,7 +1138,7 @@ Sidebar::Sidebar(Plater *parent) // Frequently Object Settings p->object_settings = new ObjectSettings(p->scrolled); - p->dia = new Search::SearchObjectDialog(p->m_object_list, text_ctrl); + p->dia = new Search::SearchObjectDialog(p->m_object_list, p->scrolled->GetParent(), p->m_search_item); #if !NEW_OBJECT_SETTING p->object_settings->Hide(); p->sizer_params->Add(p->object_settings->get_sizer(), 0, wxEXPAND | wxTOP, 5 * em / 10); diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index efa7e3581a..9906a2ea3b 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -523,7 +523,7 @@ void SearchItem::on_mouse_left_up(wxMouseEvent &evt) } if (m_search_object_dialog) { - m_search_object_dialog->Dismiss(); + m_search_object_dialog->Die(); wxCommandEvent event(wxCUSTOMEVT_JUMP_TO_OBJECT); event.SetClientData(m_item); wxPostEvent(GUI::wxGetApp().plater(), event); @@ -553,9 +553,7 @@ SearchDialog::SearchDialog(OptionsSearcher *searcher, Preset::Type type, wxWindo em = GUI::wxGetApp().em_unit(); - m_text_color = wxColour(38, 46, 48); m_bg_colour = wxColour(255, 255, 255); - m_hover_colour = wxColour(248, 248, 248); m_thumb_color = wxColour(196, 196, 196); SetFont(GUI::wxGetApp().normal_font()); @@ -582,10 +580,8 @@ SearchDialog::SearchDialog(OptionsSearcher *searcher, Preset::Type type, wxWindo search_line->SetFont(GUI::wxGetApp().bold_font()); #endif - // default_string = _L("Enter a search term"); search_line->Bind(wxEVT_TEXT, &SearchDialog::OnInputText, this); search_line->Bind(wxEVT_LEFT_UP, &SearchDialog::OnLeftUpInTextCtrl, this); - search_line->Bind(wxEVT_KEY_DOWN, &SearchDialog::OnKeyDown, this); search_line2 = search_line->GetTextCtrl(); // scroll window @@ -681,76 +677,21 @@ void SearchDialog::Die() wxPostEvent(search_line, event); } -void SearchDialog::ProcessSelection(wxDataViewItem selection) -{ - if (!selection.IsOk()) return; - // this->EndModal(wxID_CLOSE); - - // If call GUI::wxGetApp().sidebar.jump_to_option() directly from here, - // then mainframe will not have focus and found option will not be "active" (have cursor) as a result - // SearchDialog have to be closed and have to lose a focus - // and only after that jump_to_option() function can be called - // So, post event to plater: - wxCommandEvent event(wxCUSTOMEVT_JUMP_TO_OPTION); - event.SetInt(search_list_model->GetRow(selection)); - wxPostEvent(GUI::wxGetApp().plater(), event); -} - void SearchDialog::OnInputText(wxCommandEvent &) { search_line2->SetInsertionPointEnd(); wxString input_string = search_line2->GetValue(); - if (input_string == default_string) input_string.Clear(); + if (input_string == wxEmptyString) input_string.Clear(); searcher->search(into_u8(input_string), true, search_type); update_list(); } void SearchDialog::OnLeftUpInTextCtrl(wxEvent &event) { - if (search_line2->GetValue() == default_string) search_line2->SetValue(""); + if (search_line2->GetValue() == wxEmptyString) search_line2->SetValue(""); event.Skip(); } -void SearchDialog::OnKeyDown(wxKeyEvent &event) -{ - event.Skip(); - /* int key = event.GetKeyCode(); - - if (key == WXK_UP || key == WXK_DOWN) - { - search_list->SetFocus(); - - auto item = search_list->GetSelection(); - - if (item.IsOk()) { - unsigned selection = search_list_model->GetRow(item); - - if (key == WXK_UP && selection > 0) - selection--; - if (key == WXK_DOWN && selection < unsigned(search_list_model->GetCount() - 1)) - selection++; - - prevent_list_events = true; - search_list->Select(search_list_model->GetItem(selection)); - prevent_list_events = false; - } - } - - else if (key == WXK_NUMPAD_ENTER || key == WXK_RETURN) - ProcessSelection(search_list->GetSelection()); - else - event.Skip();*/ -} - -void SearchDialog::OnActivate(wxDataViewEvent &event) { ProcessSelection(event.GetItem()); } - -void SearchDialog::OnSelect(wxDataViewEvent &event) -{ - if (prevent_list_events) return; - // if (wxGetMouseState().LeftIsDown()) - // ProcessSelection(search_list->GetSelection()); -} - void SearchDialog::update_list() { #ifndef __WXGTK__ @@ -787,77 +728,12 @@ void SearchDialog::update_list() #ifndef __WXGTK__ Thaw(); #endif - - // Under OSX model->Clear invoke wxEVT_DATAVIEW_SELECTION_CHANGED, so - // set prevent_list_events to true already here - // prevent_list_events = true; - // search_list_model->Clear(); - - /* const std::vector &filters = searcher->found_options(); - for (const FoundOption &item : filters) - search_list_model->Prepend(item.label);*/ - - // select first item, if search_list - /*if (search_list_model->GetCount() > 0) - search_list->Select(search_list_model->GetItem(0)); - prevent_list_events = false;*/ - // Refresh(); } -void SearchDialog::OnCheck(wxCommandEvent &event) -{ - OptionViewParameters ¶ms = searcher->view_params; - params.category = check_category->GetValue(); - - searcher->search(); - update_list(); -} - -void SearchDialog::OnMotion(wxMouseEvent &event) -{ - wxDataViewItem item; - wxWindow * win = this; - - // search_list->HitTest(wxGetMousePosition() - win->GetScreenPosition(), item, col); - // search_list->Select(item); - - event.Skip(); -} - -void SearchDialog::OnLeftDown(wxMouseEvent &event) { ProcessSelection(search_list->GetSelection()); } - void SearchDialog::msw_rescale() { - /* const int &em = GUI::wxGetApp().em_unit(); - - search_list_model->msw_rescale(); - search_list->GetColumn(SearchListModel::colIcon )->SetWidth(3 * em); - search_list->GetColumn(SearchListModel::colMarkedText)->SetWidth(45 * em); - - msw_buttons_rescale(this, em, { wxID_CANCEL }); - - const wxSize& size = wxSize(40 * em, 30 * em); - SetMinSize(size); - - Fit(); - Refresh();*/ } -// void SearchDialog::on_sys_color_changed() -//{ -//#ifdef _WIN32 -// GUI::wxGetApp().UpdateAllStaticTextDarkUI(this); -// GUI::wxGetApp().UpdateDarkUI(static_cast(this->FindWindowById(wxID_CANCEL, this)), true); -// for (wxWindow* win : std::vector {search_line, search_list, check_category, check_english}) -// if (win) GUI::wxGetApp().UpdateDarkUI(win); -//#endif -// -// // msw_rescale updates just icons, so use it -// search_list_model->msw_rescale(); -// -// Refresh(); -//} - // ---------------------------------------------------------------------------- // SearchListModel // ---------------------------------------------------------------------------- @@ -906,15 +782,16 @@ void SearchListModel::GetValueByRow(wxVariant &variant, unsigned int row, unsign } } -SearchObjectDialog::SearchObjectDialog(GUI::ObjectList* object_list, wxWindow* parent) - : PopupWindow(parent, wxBORDER_NONE), m_object_list(object_list) +SearchObjectDialog::SearchObjectDialog(GUI::ObjectList* object_list, wxWindow* parent, TextInput* input) + : PopupWindow(parent, wxBORDER_NONE | wxPU_CONTAINS_CONTROLS), m_object_list(object_list) { + search_line = input; + Freeze(); SetBackgroundColour(wxColour(238, 238, 238)); em = GUI::wxGetApp().em_unit(); - m_text_color = wxColour(38, 46, 48); m_bg_color = wxColour(255, 255, 255); m_thumb_color = wxColour(196, 196, 196); @@ -933,6 +810,19 @@ SearchObjectDialog::SearchObjectDialog(GUI::ObjectList* object_list, wxWindow* p m_client_panel = new wxPanel(m_border_panel, wxID_ANY, wxDefaultPosition, wxSize(POPUP_WIDTH * em, POPUP_HEIGHT * em), wxTAB_TRAVERSAL); m_client_panel->SetBackgroundColour(m_bg_color); + // search line +#ifdef __WXGTK__ + search_line = new TextInput(m_client_panel, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0); + search_line->SetBackgroundColour(wxColour(238, 238, 238)); + search_line->SetForegroundColour(wxColour(43, 52, 54)); + search_line->SetFont(GUI::wxGetApp().bold_font()); +#endif + + search_line->Bind(wxEVT_TEXT, &SearchObjectDialog::OnInputText, this); + search_line->Bind(wxEVT_LEFT_UP, &SearchObjectDialog::OnLeftUpInTextCtrl, this); + search_line2 = search_line->GetTextCtrl(); + + // scroll window m_scrolledWindow = new ScrolledWindow(m_client_panel, wxID_ANY, wxDefaultPosition, wxSize(POPUP_WIDTH * em - (em + em / 2), POPUP_HEIGHT * em), wxVSCROLL, 6, 6); m_scrolledWindow->SetMarginColor(m_bg_color); @@ -947,6 +837,10 @@ SearchObjectDialog::SearchObjectDialog(GUI::ObjectList* object_list, wxWindow* p m_listPanel->Fit(); m_scrolledWindow->SetScrollbars(1, 1, 0, m_listPanel->GetSize().GetHeight()); +#ifdef __WXGTK__ + m_sizer_body->Add(search_line, 0, wxEXPAND | wxALL, em / 2); + search_line = input; +#endif m_sizer_body->Add(m_scrolledWindow, 0, wxEXPAND | wxALL, em); m_client_panel->SetSizer(m_sizer_body); @@ -970,15 +864,70 @@ SearchObjectDialog::~SearchObjectDialog() {} void SearchObjectDialog::Popup(wxPoint position /*= wxDefaultPosition*/) { - update_list(); + if (m_is_dismissing || this->IsShown()) { + return; + } + search_line2->SetValue(wxString("")); +#ifdef __WXOSX__ + // On macOS we need to remove the focus from the text input before popping up the + // dropdown list, otherwise the text input won't be usable + m_object_list->SetFocus(); +#endif PopupWindow::Popup(); + search_line2->SetFocus(); + + m_object_list->assembly_plate_object_name(); + m_object_list->GetModel()->search_object(wxEmptyString); + update_list(); } +void SearchObjectDialog::MSWDismissUnfocusedPopup() +{ + Dismiss(); + OnDismiss(); +} + +void SearchObjectDialog::OnDismiss() {} + void SearchObjectDialog::Dismiss() { - auto focus_window = this->GetParent()->HasFocus(); + auto pos = wxGetMousePosition(); + auto focus_window = wxWindow::FindFocus(); if (!focus_window) - PopupWindow::Dismiss(); + Die(); + else if (!search_line->GetScreenRect().Contains(pos) && !this->GetScreenRect().Contains(pos)) { + Die(); + } +} + +void SearchObjectDialog::Die() +{ + m_is_dismissing = true; + m_object_list->SetFocus(); + PopupWindow::Dismiss(); + wxCommandEvent event(wxCUSTOMEVT_EXIT_SEARCH); + wxPostEvent(m_object_list, event); + m_is_dismissing = false; +} + +void SearchObjectDialog::OnInputText(wxCommandEvent&) +{ + search_line2->SetInsertionPointEnd(); + wxString input_string = search_line2->GetValue(); + if (input_string == wxEmptyString) + input_string.Clear(); + + m_object_list->assembly_plate_object_name(); + m_object_list->GetModel()->search_object(input_string); + + update_list(); +} + +void SearchObjectDialog::OnLeftUpInTextCtrl(wxEvent& event) +{ + if (search_line2->GetValue() == wxEmptyString) + search_line2->SetValue(""); + event.Skip(); } void SearchObjectDialog::update_list() diff --git a/src/slic3r/GUI/Search.hpp b/src/slic3r/GUI/Search.hpp index 31b83b8cf3..b827f5c3eb 100644 --- a/src/slic3r/GUI/Search.hpp +++ b/src/slic3r/GUI/Search.hpp @@ -184,25 +184,15 @@ class SearchListModel; class SearchDialog : public PopupWindow { public: - wxString search_str; - wxString default_string; - - bool prevent_list_events{false}; - - wxColour m_text_color; wxColour m_bg_colour; - wxColour m_hover_colour; - wxColour m_bold_colour; wxColour m_thumb_color; wxBoxSizer *m_sizer_body{nullptr}; wxBoxSizer *m_sizer_main{nullptr}; wxBoxSizer *m_sizer_border{nullptr}; - wxBoxSizer *m_listsizer{nullptr}; wxWindow *m_border_panel{nullptr}; wxWindow *m_client_panel{nullptr}; - wxWindow *m_listPanel{nullptr}; wxWindow *m_event_tag{nullptr}; wxWindow *m_search_item_tag{nullptr}; @@ -215,23 +205,12 @@ public: wxTextCtrl * search_line2{nullptr}; Preset::Type search_type = Preset::TYPE_INVALID; - wxDataViewCtrl * search_list{nullptr}; ScrolledWindow * m_scrolledWindow{nullptr}; - SearchListModel *search_list_model{nullptr}; - wxCheckBox * check_category{nullptr}; OptionsSearcher *searcher{nullptr}; void OnInputText(wxCommandEvent &event); void OnLeftUpInTextCtrl(wxEvent &event); - void OnKeyDown(wxKeyEvent &event); - - void OnActivate(wxDataViewEvent &event); - void OnSelect(wxDataViewEvent &event); - - void OnCheck(wxCommandEvent &event); - void OnMotion(wxMouseEvent &event); - void OnLeftDown(wxMouseEvent &event); void update_list(); @@ -244,12 +223,8 @@ public: void OnDismiss(); void Dismiss(); void Die(); - void ProcessSelection(wxDataViewItem selection); void msw_rescale(); - // void on_sys_color_changed() override; -protected: - // void on_dpi_changed(const wxRect& suggested_rect) override { msw_rescale(); } }; // ---------------------------------------------------------------------------- @@ -284,11 +259,17 @@ public: class SearchObjectDialog : public PopupWindow { public: - SearchObjectDialog(GUI::ObjectList* object_list, wxWindow* parent); + SearchObjectDialog(GUI::ObjectList* object_list, wxWindow* parent, TextInput* input); ~SearchObjectDialog(); + void MSWDismissUnfocusedPopup(); void Popup(wxPoint position = wxDefaultPosition); + void OnDismiss(); void Dismiss(); + void Die(); + + void OnInputText(wxCommandEvent& event); + void OnLeftUpInTextCtrl(wxEvent& event); void update_list(); @@ -299,12 +280,13 @@ public: const int POPUP_WIDTH = 41; const int POPUP_HEIGHT = 45; + TextInput* search_line{nullptr}; + wxTextCtrl* search_line2{nullptr}; + ScrolledWindow* m_scrolledWindow{ nullptr }; - wxColour m_text_color; wxColour m_bg_color; wxColour m_thumb_color; - wxColour m_bold_color; wxBoxSizer* m_sizer_body{ nullptr }; wxBoxSizer* m_sizer_main{ nullptr }; @@ -312,7 +294,9 @@ public: wxWindow* m_border_panel{ nullptr }; wxWindow* m_client_panel{ nullptr }; - wxWindow* m_listPanel{ nullptr }; + +private: + bool m_is_dismissing{ false }; }; } // namespace Search