mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	FIX: Intercept IDLE event in DropDown to fix various problems on MacOS
Change-Id: Ia9aa96c90f1b7c3f6c33b7325dc28a4f780969c3
This commit is contained in:
		
							parent
							
								
									ace72ecdbc
								
							
						
					
					
						commit
						646934953c
					
				
					 5 changed files with 59 additions and 40 deletions
				
			
		|  | @ -317,25 +317,14 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR | |||
|     c_editor->SetSelection(atoi(data.GetText().c_str()) - 1); | ||||
| 
 | ||||
|      | ||||
| #ifndef _WIN32 | ||||
|     c_editor->Bind(wxEVT_COMBOBOX, [this, c_editor](wxCommandEvent& evt) { | ||||
| #ifdef __linux__ | ||||
|     c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) { | ||||
|         // to avoid event propagation to other sidebar items
 | ||||
|         evt.StopPropagation(); | ||||
|         // FinishEditing grabs new selection and triggers config update. We better call
 | ||||
|         // it explicitly, automatic update on KILL_FOCUS didn't work on Linux.
 | ||||
|         c_editor->SetClientData(this); | ||||
|         this->FinishEditing(); | ||||
|     }); | ||||
|     c_editor->Bind(wxEVT_COMBOBOX_DROPDOWN, [this, c_editor](wxCommandEvent& evt) { | ||||
|         c_editor->SetClientData(this); | ||||
|         this->FinishEditing(); | ||||
|     }); | ||||
|     c_editor->Bind(wxEVT_KILL_FOCUS, [this, c_editor](wxFocusEvent& evt) { | ||||
|         if (!c_editor->GetDropDown().IsShown() && c_editor->GetClientData() == nullptr) { // TODO: Fix called twice
 | ||||
|             c_editor->SetClientData(this); | ||||
|             this->FinishEditing(); | ||||
|         } | ||||
|     }, c_editor->GetId()); | ||||
| #else | ||||
|     // to avoid event propagation to other sidebar items
 | ||||
|     c_editor->Bind(wxEVT_COMBOBOX, [](wxCommandEvent& evt) { evt.StopPropagation(); }); | ||||
|  |  | |||
|  | @ -4741,9 +4741,7 @@ void ObjectList::OnEditingStarted(wxDataViewEvent &event) | |||
|     auto item = event.GetItem(); | ||||
|     if (!renderer->GetEditorCtrl()) { | ||||
|         renderer->StartEditing(item, GetItemRect(item, column)); | ||||
|         if (col == colFilament) // TODO: not handle KILL_FOCUS from ComboBox
 | ||||
|             renderer->GetEditorCtrl()->PopEventHandler(); | ||||
|         else if (col == colName) // TODO: for colName editing, disable shortcuts
 | ||||
|         if (col == colName) // TODO: for colName editing, disable shortcuts
 | ||||
|             SetAcceleratorTable(wxNullAcceleratorTable); | ||||
|     } | ||||
| #endif //__WXMSW__
 | ||||
|  |  | |||
|  | @ -26,13 +26,14 @@ ComboBox::ComboBox(wxWindow *      parent, | |||
|                    int             n, | ||||
|                    const wxString  choices[], | ||||
|                    long            style) | ||||
|     : drop(this, texts, icons, style & DD_STYLE_MASK) | ||||
|     : drop(texts, icons) | ||||
| { | ||||
|     if (style & wxCB_READONLY) | ||||
|         style |= wxRIGHT; | ||||
|     text_off = style & CB_NO_TEXT; | ||||
|     TextInput::Create(parent, "", value, (style & CB_NO_DROP_ICON) ? "" : "drop_down", pos, size, | ||||
|                       style | wxTE_PROCESS_ENTER); | ||||
|     drop.Create(this, style & DD_STYLE_MASK); | ||||
| 
 | ||||
|     if (style & wxCB_READONLY) { | ||||
|         GetTextCtrl()->Hide(); | ||||
|  | @ -52,16 +53,12 @@ ComboBox::ComboBox(wxWindow *      parent, | |||
|         SetSelection(e.GetInt()); | ||||
|         e.SetEventObject(this); | ||||
|         e.SetId(GetId()); | ||||
|         wxMouseEvent e1; | ||||
|         mouseDown(e1); | ||||
|         GetEventHandler()->ProcessEvent(e); | ||||
|     }); | ||||
|     drop.Bind(wxEVT_SHOW, [this](auto &e) { | ||||
|         if (!e.IsShown()) { | ||||
|             drop_down = false; | ||||
|             wxCommandEvent e(wxEVT_COMBOBOX_CLOSEUP); | ||||
|             GetEventHandler()->ProcessEvent(e); | ||||
|         } | ||||
|     drop.Bind(EVT_DISMISS, [this](auto &) { | ||||
|         drop_down = false; | ||||
|         wxCommandEvent e(wxEVT_COMBOBOX_CLOSEUP); | ||||
|         GetEventHandler()->ProcessEvent(e); | ||||
|     }); | ||||
|     for (int i = 0; i < n; ++i) Append(choices[i]); | ||||
| } | ||||
|  | @ -209,7 +206,7 @@ void ComboBox::DoSetItemClientData(unsigned int n, void *data) | |||
| 
 | ||||
| void ComboBox::mouseDown(wxMouseEvent &event) | ||||
| { | ||||
|     SetFocus(); | ||||
|     //SetFocus();
 | ||||
|     if (drop_down) { | ||||
|         drop.Hide(); | ||||
|     } else if (drop.HasDismissLongTime()) { | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ | |||
| 
 | ||||
| #include <wx/dcgraph.h> | ||||
| 
 | ||||
| wxDEFINE_EVENT(EVT_DISMISS, wxCommandEvent); | ||||
| 
 | ||||
| BEGIN_EVENT_TABLE(DropDown, wxPopupTransientWindow) | ||||
| 
 | ||||
| EVT_LEFT_DOWN(DropDown::mouseDown) | ||||
|  | @ -21,12 +23,9 @@ END_EVENT_TABLE() | |||
|  * calling Refresh()/Update(). | ||||
|  */ | ||||
| 
 | ||||
| DropDown::DropDown(wxWindow *             parent, | ||||
|                    std::vector<wxString> &texts, | ||||
|                    std::vector<wxBitmap> &icons, | ||||
|                    long           style) | ||||
|     : wxPopupTransientWindow(parent) | ||||
|     , texts(texts) | ||||
| DropDown::DropDown(std::vector<wxString> &texts, | ||||
|                    std::vector<wxBitmap> &icons) | ||||
|     : texts(texts) | ||||
|     , icons(icons) | ||||
|     , state_handler(this) | ||||
|     , border_color(0xDBDBDB) | ||||
|  | @ -36,6 +35,21 @@ DropDown::DropDown(wxWindow *             parent, | |||
|     , selector_background_color(std::make_pair(0xEDFAF2, (int) StateColor::Checked), | ||||
|         std::make_pair(*wxWHITE, (int) StateColor::Normal)) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| DropDown::DropDown(wxWindow *             parent, | ||||
|                    std::vector<wxString> &texts, | ||||
|                    std::vector<wxBitmap> &icons, | ||||
|                    long           style) | ||||
|     : DropDown(texts, icons) | ||||
| { | ||||
|     Create(parent, style); | ||||
| } | ||||
| 
 | ||||
| void DropDown::Create(wxWindow *     parent, | ||||
|          long           style) | ||||
| { | ||||
|     wxPopupTransientWindow::Create(parent); | ||||
|     SetBackgroundStyle(wxBG_STYLE_PAINT); | ||||
|     SetBackgroundColour(*wxWHITE); | ||||
|     state_handler.attach({&border_color, &text_color, &selector_border_color, &selector_background_color}); | ||||
|  | @ -46,6 +60,11 @@ DropDown::DropDown(wxWindow *             parent, | |||
| 
 | ||||
|     // BBS set default font
 | ||||
|     SetFont(Label::Body_14); | ||||
| #ifdef __WXOSX__ | ||||
|     // wxPopupTransientWindow releases mouse on idle, which may cause various problems,
 | ||||
|     //  such as losting mouse move, and dismissing soon on first LEFT_DOWN event.
 | ||||
|     Bind(wxEVT_IDLE, [] (wxIdleEvent & evt) {}); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void DropDown::Invalidate(bool clear) | ||||
|  | @ -352,27 +371,31 @@ void DropDown::autoPosition() | |||
| 
 | ||||
| void DropDown::mouseDown(wxMouseEvent& event) | ||||
| { | ||||
|     // Receivce unexcepted LEFT_DOWN on Mac after OnDismiss
 | ||||
|     if (!IsShown()) | ||||
|         return; | ||||
|     // force calc hover item again
 | ||||
|     mouseMove(event); | ||||
|     pressedDown = true; | ||||
|     CaptureMouse(); | ||||
|     dragStart   = event.GetPosition(); | ||||
| } | ||||
| 
 | ||||
| void DropDown::mouseReleased(wxMouseEvent& event) | ||||
| { | ||||
|     if (pressedDown) { | ||||
|         ReleaseMouse(); | ||||
|         dragStart = wxPoint(); | ||||
|         pressedDown = false; | ||||
|         if (hover_item >= 0) // not moved
 | ||||
|         if (hover_item >= 0) { // not moved
 | ||||
|             sendDropDownEvent(); | ||||
|         DismissAndNotify(); | ||||
|             DismissAndNotify(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void DropDown::mouseMove(wxMouseEvent &event) | ||||
| { | ||||
|     wxPoint pt  = event.GetPosition(); | ||||
|     if (pressedDown) { | ||||
|         wxPoint pt  = event.GetPosition(); | ||||
|         wxPoint pt2 = offset + pt - dragStart; | ||||
|         dragStart = pt; | ||||
|         if (pt2.y > 0) | ||||
|  | @ -387,7 +410,7 @@ void DropDown::mouseMove(wxMouseEvent &event) | |||
|         } | ||||
|     } | ||||
|     if (!pressedDown || hover_item >= 0) { | ||||
|         int hover = (event.GetPosition().y - offset.y) / rowSize.y; | ||||
|         int hover = (pt.y - offset.y) / rowSize.y; | ||||
|         if (hover >= (int) texts.size()) hover = -1; | ||||
|         if (hover == hover_item) return; | ||||
|         hover_item = hover; | ||||
|  | @ -434,4 +457,6 @@ void DropDown::OnDismiss() | |||
| { | ||||
|     dismissTime = boost::posix_time::microsec_clock::universal_time(); | ||||
|     hover_item  = -1; | ||||
|     wxCommandEvent e(EVT_DISMISS); | ||||
|     GetEventHandler()->ProcessEvent(e); | ||||
| } | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ | |||
| #define DD_NO_TEXT          0x2000000 | ||||
| #define DD_STYLE_MASK       0x3000000 | ||||
| 
 | ||||
| wxDECLARE_EVENT(EVT_DISMISS, wxCommandEvent); | ||||
| 
 | ||||
| class DropDown : public wxPopupTransientWindow | ||||
| { | ||||
|     std::vector<wxString> &       texts; | ||||
|  | @ -39,11 +41,17 @@ class DropDown : public wxPopupTransientWindow | |||
|     wxPoint                  dragStart; | ||||
| 
 | ||||
| public: | ||||
|     DropDown(std::vector<wxString> &texts, | ||||
|              std::vector<wxBitmap> &icons); | ||||
|      | ||||
|     DropDown(wxWindow *     parent, | ||||
|              std::vector<wxString> &texts, | ||||
|              std::vector<wxBitmap> &icons, | ||||
|              long           style     = 0); | ||||
| 
 | ||||
|      | ||||
|     void Create(wxWindow *     parent, | ||||
|              long           style     = 0); | ||||
|      | ||||
| public: | ||||
|     void Invalidate(bool clear = false); | ||||
| 
 | ||||
|  | @ -73,6 +81,9 @@ public: | |||
|     void Rescale(); | ||||
| 
 | ||||
|     bool HasDismissLongTime(); | ||||
|      | ||||
| protected: | ||||
|     void OnDismiss() override; | ||||
| 
 | ||||
| private: | ||||
|     void paintEvent(wxPaintEvent& evt); | ||||
|  | @ -92,7 +103,6 @@ private: | |||
| 
 | ||||
|     void sendDropDownEvent(); | ||||
| 
 | ||||
|     void OnDismiss() override; | ||||
| 
 | ||||
|     DECLARE_EVENT_TABLE() | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 chunmao.guo
						chunmao.guo